O0#(p O`  @`! #@%`')+-/1 5`79=?ACoGIKMOQ SU`Y[]_a c@e`gikq s@uwy{} ` @ ` / @ ` @ ` @ ` ǀ ɠ @ ` ׀ ٠  @` `!Aa  !!!#Ao'+-/1!3A5a7O`  @`! #@%`')+-/1 5`79=?ACoGIKMOQ SU`Y[]_a c@e`gikq s@uwy{} ` @ ` / @ ` @ ` @ ` ǀ ɠ @ ` ׀ ٠  @` `!Aa  !!!#Ao'+-/1!3A5a7AUTO bW,ESRC X,E3FLAPPYBD_HI !9. bW,E.. FLAPPYBDPRG W,E`w@:T*O*m - ЭЭ"ҍ.A// Bg?<JNA |aPaa^a^!a`a aa2p3333#aw arama@3A((f (@fg3<a g< a g yfga`av09gS@3 98a`Ra`Jaa @aa y8"a?<?<LNAXONuHRn3~ 9g @N 9vgA#v 9zg0 @09fgA C@""""""""#zp9gaa`9gaaLNs#8pNuRr?980Ns8 yf,pA@ ! !`j09f! 17B`!6 1B!wDD! @H!atL!0aP!!T!ւX!ڂ\!Nu1B yf!@P!wwT! !Ns17B! !Ns1B! !Ns1GB!D !Ns1B!l !Ns1GB! !Ns1ǂB! !Ns1GB yf !cRP!!T!X!\! !Ns1ǂB!6 !Ns1WB!^ !Ns1ǂB! !Ns1WB!  !Ns1ׂB! !Ns1WB! !Ns1ׂB yf1T!6  !Ns1gB!^ !Ns1ׂB! !Ns1gB! !Ns1B! !Ns1gB! !Ns1B!& !Ns1wB!N !Ns1B!v !Ns1wB yf!ւX!ڂ\! !Ns1bB!feP!uRT! !Ns! !Ns!@aP!1cTRrNs1B yf!@P!wwT!x !Ns1B! !Ns1B! !Ns1'B! !Ns1B!  !Ns1'B! @ !Ns1B! h !Ns1'B yf !cRP!!T!X!\!  !Ns1B!  !Ns17B!  !Ns1B! 2 !Ns17B! Z  !Ns1B!  !Ns17B!  !Ns1B yf1T!   !Ns1GB!  !Ns1B! 2 !Ns1GB! Z !Ns1ǂB!  !Ns1GB!  !Ns1ǂB!  !Ns1WB!  !Ns1ǂB! " !Ns1WB1gV yf!ւX!ڂ\! j !Ns1PB!4pP1ET!  !Ns1`V!  !Ns!@aP!1cTRrNsEw0 f#F' !F#A`A`ACE(t ""€$Q0929838A@3:a<29<3NuA@2AH0NuA(`p29fgP128f@128f@128FAIAA128FAIAANuapS@aQNu8gNuF%Hp8gfgff`fZfT8 yfJ|lFA2Ak @` @p8fLNs8`Nа<f#`̰<f#`<f#``#`|#`h#*`T#`@p#F#JF' !88 %F#NuNuF%HCE 9Fg @a(#F 9Jg @a#JLNspNgNu |Nu#FNu#JNu t dRv(KDCE0DVDDDDN@&JoQ`SoQ`NuNuNuNuNuNuNuNuNuNuNu!! !$!0NuAp#bNu <A@00 NuF'a ybaa"ybAa yNaAa 9TAa09RAa 9XA!a"yb Aab"ybAaL y`g& 9\A:a"ybA*a`#N3``#N#\3`3R / #T#X`#N` #N3`3R /#T#X`F'/an yba0at"ybAad _a^AaT`A`A!`A,`A6`A@`AQ`A_`Ap`xA~`nA`dA`ZA`P3fahi3jlp#n#r#v#z3~3####Ap2<4<0AQ`/?< NA\NuF'!pF#NuF'#8&# 8*#8.#82#p86#8:#8>#8B# 8F#48J#8N8R 8S8T8U8V8W8X8Y8Z 8[L@H8\F#`aF'!8&!8* !8.!82!86p!8:!8>!8B!8F !8J4!8N8Y8Z8[ 8V8W8X8T8U8R8S L8\H@F#NuF'8    F#Nu3f 8g @ g"_MCHg`HA3fNu?<//<I?< NA\LNuHtX2AA0|9oAQLNuHt"A0|9oAQLNu/<_""""QH yAP~/L|H|pH|0H|pLH H`ACQL>< """"Q>< """"Q><;""""Q>< """"Q>< """"Q><""""Q><Y""""QNuaa,aa`p#8|#8Nu"98|aL@HD@@ yA`L\"y <r$&(*,.$@&A(@*AH<H<xH<H<H<XH<H< H< 8H< H< xH< H< H< XH< H<H<8H<H<xNuXHCVpD@ Nu8 g##:Nu##1Nup33Nua3pR33p33`  <2`3~a:a <2aja ~aN09gAaTa8#LNuAL\"yC~L"#A#B#C#D #E(#F0#J8CQNu y <r$&HHH@HHH HH`HHH@HHH HH `H H Nu09R@3A@>29{ 3`aB3pp]33p3#8|3Nu <9aa`3~ yna2aBa <9aa(aaaL09ga(#AdaNuAP\"yC~L|H|LH0CL|H|LH0CQNu"yC4 Ù$<??Q6<߀YQYőCQYQY=ÙQ8<YQYϑCQY QY;ÙQ:<YQYϑ,<YQY͙ <Q2<YQY$<i͙ <2<i$<ř6$<řiři|ǙiǑiVCii7F&<ǙiǙi(<ii7Z <ii8"H?? H??H?@`H?AH?AH?B@H?BH?CH?D H?DH?E`L?H?FL?H?FL?H?G@L?H?GL?H?HL?H?I L?H?IL?H?J`L?H?KL?H?KL?H?L@L?H?LL?H?ML?H?N L?H?NL?H?O`L?H?PL?H?PL?H?Q@L?H?QL?H?RL?H?S L?H?SL?H?T`L?H?UL?H?UL?H?V@L?H?VL?H?WL?H?X L?H?XL?H?Y`L?H?ZL?H?ZL?H?[@L?H?[L?H?\L?H?] L?H?]` "y0(M@HE*G(jp0 Ij Kj|L0`H0^`H0_H0_H0`@H0`H0aH0b H0bH0c`,h(NH02H02H03@H03H04H05 H05H06`H07H07H08@H08H09H0: H0:H0;`H0<H0H0? H0?H0@`H0AH0AH0B@H0BH0CH0D H0DH0E`L0H0FL0H0FL0H0G@L0H0GL0H0HL0H0I L0H0IL0H0J`L0H0KL0H0KL0H0L@L0H0LL0H0ML0H0N L0H0NL0H0O`L0H0PL0H0PL0H0Q@L0H0QL0H0RL0H0S L0H0SL0H0T`L0H0UL0H0UL0H0V@L0H0VL0H0WL0H0X L0H0XL0H0Y`L0H0ZL0H0ZL0H0[@L0H0[L0H0\L0H0] L0H0]` r"y0(M@HE*G(jp0 Ij Kj|L<`H<^`H<_H<_H<`@H<`HHH? H?H@`HAHAHB@HBHCHD HDHE`LHFLHFLHG@LHGLHHLHI LHILHJ`LHKLHKLHL@LHLLHMLHN LHNLHO`LHPLHPLHQ@LHQLHRLHS LHSLHT`LHULHULHV@LHVLHWLHX LHXLHY`LHZLHZLH[@LH[LH\LH] LH]` ("y0(CM@HE*G(jp0 Ij Kj|LH^`H_H_H`@H`HaHb HbHc`,h4NH2H2H3@H3H4H5 H5H6`H7H7H8@H8H9H: H:H;`H<HH? H?H@`HAHAHB@HBHCHD HDHE`LHFLHFLHG@LHGLHHLHI LHILHJ`LHKLHKLHL@LHLLHMLHN LHNLHO`LHPLHPLHQ@LHQLHRLHS LHSLHT`LHULHULHV@LHVLHWLHX LHXLHY`LHZLHZLH[@LH[LH\LH] LH]` N"y0(2IA2(g&y2A`IA8MB@H$vL?,†,* ĆƆ,*ȆʆE$H?L?P,†,ĆƆ,ȆʆH?LppL„. ćƇ. .H@L„. ćƇ. .HL@„. ćƇ. .HL„. ćƇ. .H L„. ćƇ. .HL0„. ćƇ. .H`L„. ćƇ. .HL„. ćƇ. .HLpL„HPL„HLP„HL„H0L„HL@„HpL„HL„HL? ,†,ĆƆ,ȆʆH?@L?p,†,* ĆƆ,*ȆʆE$H?NuM@H$vL?H?L?H?L?H?@H?H?H? H?H?`H?H?L?H?@L?H?Nu"y0(2(g(&yMB@H$vL$*‚E$HL`E$‚HELpL„H@L„HLP„HL„H L„HL@„H`L„HL„HL0E$‚H@L$*‚E$HNuM@H$vLHL(HL@H@HHH HH`HHLXH@LpHNu"y0(2(g&yGMB@H$vL(* „(*ĄƄE$HLXE („(ĄƄHE LppL„. ćƇ. .H@L„. ćƇ. .HLH„. ćƇ. .HL„. ćƇ. .H L„. ćƇ. .HL8„. ćƇ. .H`L„. ćƇ. .HL„. ćƇ. .HL(E („(ĄƄH@Lx(* „(*ĄƄE$HNuM@H$vLHL HL8H@HHH HH`HHLPH@LhHNu"y0(C2(g&yG MB@H$vL(„(* ĄƄE$HLP(„(ĄƄE HLppE L„. ćƇ. .H@L„. ćƇ. .HL@„. ćƇ. .HL„. ćƇ. .H L„. ćƇ. .HL0„. ćƇ. .H`L„. ćƇ. .HL„. ćƇ. .HL („(ĄƄE H@Lp(„(* ĄƄE$HNuM@H$vLHLHL0H@HHH HH`HHLHH@L`HNu"y0(C2(g&&yG(MB@H$vL$‚E$HLP$‚EHLpEL„H@L„HL@„HL„H L„HL0„H`L„HL„HL $‚EH@Lp$‚E$HNuM@H$vLHLHL0H@HHH HH`HHLHH@L`HNup$x6CfQp Nu6C@ |fY@QNut6CfQtr6Cx |fxK:EEEG0:MECPDLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCLYQYYYYQYYQCQNup$x6CfQpNu6C\@|fU@QNut6CfQtr6Cx|fxK:EEEG"0:MECPDLiii iLiiiiLiBiFiJiNLiiiiLiiiiLi"i&i*i.LiiƏiiLibifijinLiii iLiiiiQNu3 Nu09 R@| n3 Nu3 NuA<"y09 H2HA3Xe@3XeH3XeP3XeX3Xe`3Xeh3Xep3Xex3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xe3Xf3Xf3Xf3Xf3Xf 3Xf(3Xf03Xf83Xf@3XfH3XfP3XfX3Xf`3Xfh3Xfp3Xfx3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xf3Xg3Xg3Xg3Xg3Xg 3Xg(3Xg03Xg83Xg@3XgH3XgP3XgX3Xg`3Xgh3Xgp3Xgx3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xg3Xh3Xh3Xh3Xh3Xh 3Xh(3Xh03Xh83Xh@3XhH3XhP3XhX3Xh`3Xhh3Xhp3Xhx3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3Xh3XhNu3#L`8a@g3#L`3#(`p rAAx"yCPE(jalprAAx"yCEjaNp rAAx"yCEj`0#jp3`Ap2<0QNuAjAJ !| 98r4BfQNu4BQNu09fa` SyNu9 ypgm&;<9oNu#j`fR3NuR|o.AdHCLQi*iTi~iiҍiNuAprDAQNuA"yTH3Xx3Xx3Xx3Xx3Xxz3Xxr3Xxj3Xxb3XxZ3XxR3XxJ3XxB3Xx:3Xx23Xx*3Xx"3Xx3Xx3Xx 3XxTH3Xy:3Xy23Xy*3Xy"3Xy3Xy3Xy 3Xy3Xx3Xx3Xx3Xx3Xx3Xx3Xx3Xx3Xx3Xx3Xx3XxTH3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xy3Xyz3Xyr3Xyj3Xyb3XyZ3XyR3XyJ3XyBTH3Xzz3Xzr3Xzj3Xzb3XzZ3XzR3XzJ3XzB3Xz:3Xz23Xz*3Xz"3Xz3Xz3Xz 3Xz3Xy3Xy3Xy3XyTH3X{3X{3X{ 3X{3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3Xz3XzTH3X{3X{3X{3X{3X{3X{3X{3X{3X{z3X{r3X{j3X{b3X{Z3X{R3X{J3X{B3X{:3X{23X{*3X{"TH3X|Z3X|R3X|J3X|B3X|:3X|23X|*3X|"3X|3X|3X| 3X|3X{3X{3X{3X{3X{3X{3X{3X{Nua@aapA?C*apA@LCa pA@Cj`fAGCt v <r02$Ix44H@HA44H@HAEQPQCQNuAJCt v <r02$Ix44H@HA44H@HAEJQPQC0QNuAdNAXO3NuakP/</<?9?<?NA Jk0AL0 ?a6aD2@fA aNf #8aNuatjaTk>aA 8a0a/</<?9?<@NA JkaHNuACLaNu00000`pxt00pp000xx0000` 0`xx00000 x 8 | |x 00xxxx| ````0`0`00` 80xxx|||x00000| xxxl|x 0000xx0xx000`x```x`0 xx0x00x|||x00000| xxxl|x 0000xx0xx000`x``x00000080d  , $8  ( ( (F  ( ( $T   ,$  (b (  ( ,p 0 ,$ 4~0 ,2 0 ( 440 4 40 4 4 0 4 40444844 484484484848( 0000 0 80 80 80 80 80808084 44 84 80 84 808484808844448880(" 0= 0X 4s0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d 4u4d4S0B 414B4S0d (l 4n4|4~0 4440 4440 4440 444,  4440, 4.4<4>0L 4N4\4^0l 4n4|4~0 4440 4440 4440 4444 ??? EXCEPTION - ??? ERROR - ???FILE OPENFILE CLOSEFILE SEEKFILE READMEMORY ALIGNMENTOUT OF MEMORYOUT OF FILESLOTSTAIL SENTINELLZ77 SIZE MISMATCHLZ77 CHECKSUM FAILIKBD PACKETSPRITE CLEAR OVERLFLOWBUS ERRORADDRESS ERRORILLEGAL INSTRUCTIONDIVIDE BY ZEROPC xxxxxxxx SR xxxxPC OFFSET xxxxxxxxACCESS LOCATION xxxxxxxxXXXXXXXXXXXX2*DFfHK>MNQTW[1`+ DF`HK8MNQTW[0+CFZHK2MNQTX[ 0 ,`CFTHK,MNQTX[&/-CFNHK&MNQTX [,.-CFHHK MNQTX[2.@.@CFBHKMNQTX[8-.CF<HKMNQTX[>-/CF6HKMzOQTX$[D,`0 CF0HKMtO QUX*[J+0CF*HKMnOQU X0[P+ 1`CF$HJMhOQUX6[V*2CFHJMbOQUX<[\)2CFHJM\O"QUXB[b)@3@CFH|JMVO(QU"XH[h(3CF HvJMPO.RU(XN[n(4CFHpJMJO4R U.XT[t'`5 CFHjJMDO:RU4XZ[z&5CEHdJM>O@RU:X`[& 6`CEH^JM8OFRU@Xf[%7CEHXJM2OLR"UFXl[$7CEHRJM,ORR(ULXr[$@8@CEHLJM&OXR.URXx[#8C|EHFJM O^R4UXX~[#9CvEH@JMOdR:U^X["`: CpEH:JMOjR@UdX[!:CjEH4JMOpRFUjX[! ;`CdEH.JMOvRLUpX[ <C^EH(JMO|RRUvX[<CXEH"JLORXU|X[@=@CREHJLOR^UX[=CLEHJLORdUX[>CFEHJ~LORjUX[`? C@EH JxLORvUX[?00C:EHJrLORUX[ @`HC4EGJlLORUX[A`C.EGJfLORUX\A xC(EGJ`LORUX\@B@pC"EGJZLORUX\BCE|GJTLORUY\(CCEvGJNLORUY\4`D `CEpGJHLORUY \@DC EjGJBLORVY,\L E`CEdGJ<LPRVY6\VFPBE^GJ6LP RVYB\bF0BEXGJ0LPSV*YN\n@G@HBERGJ*LP SV6YZ\zG@`BELGJ$LP*SVBYf\HxBEFGJLP4S*VNYr\`I BE@GJLP>S6VZY~\I0BE:GJL~PHSBVfY\ J`BE4GJ LxPRSNVrY\KBE.GJLrP\SZV~Y\K BE(GJLlPfSfVY\@L@pBE"GILfPpSrVY\L BEGIL`PzS~VY\M 8BEGILZPSVY\`N `PBEGzILTPSVY\ N hBE GtILNPSVY] O` BEGnILHPSVY] P PBDGhILBPSVZ]" P BDGbIL<PSVZ]. @Q@ BDG\IL6PSVZ]8 Q @BDGVIL0PSWZ$]D R 0BDGPIL*PSWZ0]P `S HBDGJIL$PSWZ<]\S 0`BzDGDILPTW&ZH]h T` xBtDG>ILPTW2ZT]tU BnDG8ILPTW>Z`]U BhDG2IL QT&WJZl]@V@ pBbDG,ILQT2WVZx]*JjŠê:Zz ǚ"zjZJ:j:V r&B X@  `(8`0 8 x@@ H Pp0 X H `` P h( p px  HX  0!@#%h`'0(h*@,.P001P3x5pPp78(!" #$X@%  `&(8`'0 (8 x )@@!*H"+P#p0,X$H-``% P.h(%/p&p0x'1(2H)X 3 *04!+@5#+6%h,`7'0-8(.h9*/@:,0;.P00<01=12P>33x?5p4Pp@785(BC DEX@F  `G(8`H0 I8 xJ@@KHLPp0MX HN`` POh( Pp pQx R SHX T 0U!@V#W%h`X'0Y(hZ*@[,\.P0]0^1P_3x`5pPpa78(cd efX@g  `h(8`i0 j8 x k@@!lH"mP#p0nX$Ho``% Pph(%qp&prx's(tH)X u *0v!+@w#+x%h,`y'0-z(.h{*/@|,0}.P00~0112P33x5p4Pp785( @`0Pp @ ` 0Pp @`0Pp @`  !0!"P"#p$$% %&@&'`'())*0*+P+,pP@0 p`P@0 p  ` P @ 0 p `P@0 p`P@0 p`FLAPPYBD._HIY?'1? '?GG??8/O ?" ?'?? ?i|@?~?pd g8qG? OOG?<g'On 0<^T100@x_0WP/H _} UXAZ ` _B Jg  ՅG |5|??p pBV!O`  4>x0  sPs  yy  o 0 0 @ < /a Rww/   J@  / ``SP' ?' gg ?7gGG ?8/O ?? r'????iz||7?^^  ?OOguG?OOG?[g'OO0RR~1 1!T  P-AJ TP{  (H@   `# $bTF)Gp  ?l1p??pcp/O   ' >xpn @sso yy. ~ o 0 0 O@@ @ a jPww/   B@@  QyZOO g  ~?                           / /"/"/ >? ~$M_? ?m%z/ G _wwww_wө # ##C# k#  #   E`ޑ1Vzl @.TF_pwl~`sy/1EK| /+       w>B~_ r      0/:+    o!BR @^  @\\0Qh`[&? g#f #W# *g\! 0 { + ?"a| <@Cw03GGGG O?GGGG w/Bӷ" {l P`p0 O  ` O' '' O kO''kwCO'#AAAq PfX`?pmPP=V R1Pa:?P?M?HF??p#Vp߾~?|> ?_}??p"6?'u I١j!i$G&| "2;Pc %'/Q§kwOY)Ox/!@O`O  /@~㱊O?O0P O `O O O<O OOwOQq?"+OOtP!̀%a OO  zOO9m`]0 O?_2]'OO\001HO@OO0 ߿~^@OOO O? rOOBY@A O~9O OOO'OOO&O OO~ ЁPOOO$OOOO@&/OO[!OOO6oOOOOO6HOOOO OBOOOODOOQO ODOB_OFOOU&Oq%$/#/B_T_OOq=OO4OO@OOI? O8OO8?OOĀ9@yOPOO8$?4,iOu@CO?O<7ф@_'??O``? `OO>*a@!Oxϒ{S K!?qO F+/uOD_ O U HO'O?_OONqO 1'O%' OӼ-0 "l1T3F7>#_"Ho" @ @@` `G_V6>O#5Am "`a te F",!y~@@5 T!D"@8}B{x"@gpo&>oA2@xP37>@ad߽` !/8eO/ l jOg}}4P}| PKO@O{ uˠ_ߋL o"@@o@{`wA_>o/oO>?`[n"m_"Te"/oooooooUoooo@oo"oooooOoooooo00`foooooo4o ooo_ooMOo111/o1/o1O`1O(@@0A @/PH@H 00@@``@  ?`a@(@ !c c ?@ A ?P@@@`]ooo@ 0#op$0(PpQ x*ooOowwg 8gww3̽Rctt c_`Gtt 0?_?g 0H_(_lw%?9dMG? _ ssww3W wwqg /ss 3 /wbrO wGwQ A+4|G/~wA!Y p@ / ?@?0A /yw 60V?0>~ gn;s/> 8>_ m QoBq /룏 qpZw~>$sw/wY#0_)?# K?q>9v [8ap/o? wsImo i|uYoc Og' v O')_ / cu /O*8/p'?8!;U/V/-1! !AT;8FMDPNFUP'MBQQZ#JSEGPSUIF"UBSJ45+$VSSFOUIJHITDPSFJT#5PGHQSFTTEG@J'CVUUPO TQBD B!ScNPVT11LFZ)[+0SJHJOBMHBEFWFMPQFECZ%POH/ HVZFSSVOTPOBTUBOEB45'. 45FSPMMTTNPPUIMZBUu!  GSrTQFSTF DP0XJUIP"VUBTTFNCo %FW +@)FNVMBU PSgGVMMxTR \s JODMVEFBZVADLOFMO+PZ0G4=UJ#x+S6HPPEO!     &  ($60(((((($(((((($(((((((($8",(((((($(((((($((((((((*6(,    L  J`0         < f ,   0     x  8     V.  8 P.  >J          >rt R Z`   , (6& : ( > TR``^^        nl v v t z      0   h &<X   FF^0 0 "2. >   . X,E3.. BIRD INC P,E4BOOT INC V,E;UBOOT S UD*EBDATA X,EDDATA INC +Em9ERROR INC })Eo'FLOOR INC P,EvFONT INC UD*ExGAME INC T,Ez$GETREADYINC r+EHISCORE INC IT,EIKBD INC Ho,E\+LOG INC IT,E LZ77 INC JT,EU MEDAL INC ]N,E"PIPE INC LT,E/&PRESHIFTINC DZ*EM'RASTERS INC M,E-SCORELRGINC )E SCORESMLINC )ESKY INC DZ*ESOUND INC *U,E2 TICKER INC L,EvTITLE INC R+E%V UTIL INC AT,E)? ;Bird drawing and animation BIRDANIMVEL = $4000 ;Velocity for normal wing animation as fixed-point BIRDANIMFLAPVEL = $8000 ;Increased velocity when flap BIRDANIMDECVEL = $350 ;Decrease wing animation BIRDANIMCLAMPVEL = $1000 ;Clamp velocity SECTION TEXT ;---------------------------------- ;Initialise bird birdinit moveq.l #0,d0 move.w d0,birdx move.l d0,birdy move.l d0,birdvely move.w d0,birdoldy move.w d0,birdoldy+2 move.l d0,birdframe move.l #BIRDANIMVEL,birdframevel move.l #BIRDANIMVEL,birdframeclamp move.l #BIRDFLAPVELY_50HZ,birdflapvely move.l #GRAVITY_50HZ,birdgravity move.w d0,birdhit move.l d0,birdpalette move.l d0,birdpalette+4 rts ;---------------------------------- ;Reset bird birdreset moveq.l #0,d0 move.w d0,birdx move.l d0,birdy move.l birdflapvely,birdvely move.w d0,birdoldy move.w d0,birdoldy+2 move.l d0,birdframe move.l #BIRDANIMVEL,birdframevel move.l #BIRDANIMVEL,birdframeclamp move.w d0,birdhit rts ;---------------------------------- ;Set random bird palette birdrandompalette bsr utilrandbyte ;Get random value in d0.b and.w #3,d0 ;Mask 0...3 lsl.w #3,d0 ;*8 lea birdpalettes(pc,d0.w),a0 ;Source palette lea birdpalette,a1 ;Destination palette move.l (a0)+,(a1)+ ;Copy 4 colours move.l (a0),(a1) rts ;---------------------------------- birdpalettes dc.w $700,$630,$740,$774 ;Orange bird dc.w $720,$035,$157,$277 ;Blue bird dc.w $740,$510,$710,$730 ;Red bird dc.w $700,$630,$740,$774 ;Orange bird (duplicate as index 0...3) ;---------------------------------- ;Animate bird wings birdanim move.w birdhit,d0 ;Check if we're dead bne.s .dead move.l birdframe,d0 move.l birdframevel,d1 move.l birdframeclamp,d2 sub.l #BIRDANIMDECVEL,d1 ;Slow animation speed cmp.l d2,d1 bge.s .noclamp move.l d2,d1 ;Clamp to slowest speed .noclamp move.l d1,birdframevel add.l d1,d0 and.l #$0003ffff,d0 ;Mask frame as 0...3 fixed-point move.l d0,birdframe rts .dead move.l #4<<16,birdframe ;Force death frame as fixed-point rts ;---------------------------------- dc.w 24*16 dc.w 24*15 dc.w 24*14 dc.w 24*13 dc.w 24*12 dc.w 24*11 dc.w 24*10 dc.w 24*9 dc.w 24*8 dc.w 24*7 dc.w 24*6 dc.w 24*5 dc.w 24*4 dc.w 24*3 dc.w 24*2 dc.w 24*1 birdclip ;---------------------------------- ;Draw bird to screen birddraw ;4300 cycles, 8.5 rasters move.w birdx,d0 ;16 move.w birdy,d1 ;16 moveq.w #17-1,d7 ;4 ;Number of lines to draw move.l offscreenbse,a1 ;20 lsr.w #1,d0 ;8 ;Add X screen offset and.w #$fff8,d0 ;8 add.w d0,a1 ;8 move.w birdframe,d0 ;16 lsl.w #2,d0 ;12 ;Frame as long word index move.l birdframes(pc,d0.w),a0 ;20 ;Lookup animation sprite frame cmp.w #-17,d1 ;8 ;Cull on Y (X is always on-screen) ble.s .done ;10/8 cmp.w #160,d1 ;8 bge.s .done ;10/8 move.w d1,d1 ;4 ;Within top of screen? bge.s .topok ;10/8 add.w d1,d7 ;4 ;Clip top add.w d1,d1 ;4 ;*2 add.w birdclip(pc,d1.w),a0 ;20 ;-ve index into table to offset source moveq.w #0,d1 ;4 .topok cmp.w #160-17,d1 ;8 ;Within bottom of screen? ble.s .bottomok ;10/8 add.w #160-17,d7 ;8 ;Clip bottom sub.w d1,d7 ;4 ble.s .done ;10/8 .bottomok add.w d1,d1 ;4 ;Add Y screen line offset lea screenlines,a2 ;12 add.w (a2,d1.w),a1 ;20 .loop movem.l (a0)+,d0-d5 ;60 ;Mask/Planes 1+2+3+4 for 32 pixels and.l d0,(a1) ;20 or.l d1,(a1)+ ;20 and.l d0,(a1) ;20 or.l d2,(a1)+ ;20 and.l d3,(a1) ;20 or.l d4,(a1)+ ;20 and.l d3,(a1) ;20 or.l d5,(a1)+ ;20 lea 160-16(a1),a1 ;8 ;Next line dbra.w d7,.loop ;10/14 .done rts ;---------------------------------- birdframes dc.l birdanimspr+(408*0),birdanimspr+(408*1),birdanimspr+(408*2),birdanimspr+(408*1) dc.l birdanimspr+(408*3) ;---------------------------------- ;Clear line of bird, 92 cycles BIRDCLEARLINE MACRO movem.l \1(a0),d0-d3 ;48 movem.l d0-d3,\2(a1) ;44 ENDM ;---------------------------------- ;Clear bird background birdclear ;1820 cycles, 3.5 rasters move.w birdoldy,d0 ;16 ;Cycle bird Y for swap buffers move.w birdoldy+2,birdoldy ;28 move.w birdy,birdoldy+2 ;28 move.w d0,d0 ;4 ;Clamp Y between playable area 0...143 bge.s .clamptop ;10/8 moveq.w #0,d0 ;4 .clamptop cmp.w #143,d0 ;8 ble.s .clampbottom ;10/8 move.w #143,d0 ;8 .clampbottom move.l offscreenbse,a1 ;20 lea 56(a1),a1 ;8 ;Add X screen offset move.w d0,d1 ;4 add.w d1,d1 ;4 ;Add Y screen line offset lea screenlines,a2 ;12 add.w (a2,d1.w),a1 ;20 move.l skyimg,a0 ;20 sub.w #95,d0 ;8 ;Get line in sky source ble.s .clip ;10/8 lsl.w #4,d0 ;16 ;*16 move.w d0,d1 ;4 lsl.w #2,d1 ;12 ;*64 add.w d1,d0 ;4 ;=*80 lea 8(a0,d0.w),a0 ;8 ;Offset to sky line .clip BIRDCLEARLINE 80*0,160*0 ;92 ;Copy 17 lines of 32 pixels to screen BIRDCLEARLINE 80*1,160*1 BIRDCLEARLINE 80*2,160*2 BIRDCLEARLINE 80*3,160*3 BIRDCLEARLINE 80*4,160*4 BIRDCLEARLINE 80*5,160*5 BIRDCLEARLINE 80*6,160*6 BIRDCLEARLINE 80*7,160*7 BIRDCLEARLINE 80*8,160*8 BIRDCLEARLINE 80*9,160*9 BIRDCLEARLINE 80*10,160*10 BIRDCLEARLINE 80*11,160*11 BIRDCLEARLINE 80*12,160*12 BIRDCLEARLINE 80*13,160*13 BIRDCLEARLINE 80*14,160*14 BIRDCLEARLINE 80*15,160*15 BIRDCLEARLINE 80*16,160*16 rts ;---------------------------------- SECTION BSS birdx ds.w 1 ;Bird XY position birdy ds.w 1 birdyfrac ds.w 1 birdvely ds.w 1 ;Bird velocity as 16:16 fixed-point birdvelyfrac ds.w 1 birdoldy ds.w 2 ;Old bird Y positions for swap buffer clears birdframe ds.w 1 ;Animation frame birdframefrac ds.w 1 birdframevel ds.w 1 ;Animation velocity birdframevelfrac ds.w 1 birdframeclamp ds.w 1 ;Animation clamp birdframeclampfrac ds.w 1 birdflapvely ds.l 1 ;Upward velocity to apply on flap birdgravity ds.l 1 ;Gravity birdhit ds.w 1 ;!=0 if bird has hit a pipe or the floor birdpalette ds.w 4 ;Random palette of 4 colours used for bird EVEN ;Flappybird for the Atari ST ENABLECPUTIME = 0 ;Set to 1 to enable CPU timing bars ENABLEMEMLOG = 0 ;Set to 1 to output memory stats to log ENABLEDEBUGQUIT = 0 ;Set to 1 to enable debug quit key SECTION TEXT start move.l sp,a5 ;Store stack move.l 4(a5),a5 ;Base page as a5 move.l $c(a5),d0 ;Text segment length in d0 add.l $14(a5),d0 ;Add length of data segment add.l $1c(a5),d0 ;And add length of bss segment add.l #$1000,d0 ;Add space needed for stack move.l d0,d1 add.l a5,d1 and.l #-2,d1 ;Ensure stack address is even move.l d1,sp ;Set new stack move.l d0,-(sp) ;Size of reserved area move.l a5,-(sp) ;From base page clr.w -(sp) move.w #$4a,-(sp) ;Mshrink trap #1 add.l #12,sp ;Do as much processing as possible before change screen resolution for a clean boot sequence move.l #0,a0 ;Enter supervisor mode bsr utilsupermode bsr utilinit ;Initialise utility functions and read machine type bsr loginit ;Create log file IFGT ENABLEMEMLOG bsr utilavailablemem ;Write size of free memory to log bsr loglong ENDC bsr utilstorestate ;Store all vectors move.l #gemdoserrorhandler,$404.w ;Redirect GEMDOS error handler for silent file errors bsr errorsetexceptions ;Set exception handler bsr ikbdinit ;Set new IKBD handler bsr soundinit ;Set sound interrupt bsr rastersinit ;Initialise raster effects ;Game boot moveq.l #0,d0 move.b d0,pal50hz move.b d0,ntsc60hz move.w d0,count move.w d0,exitcount move.w d0,whiteoutcount move.w d0,flapbutton move.l d0,handler bsr datauncompress ;Uncompress LZ77 data bsr preshiftinit ;Create preshifts bsr skyinit ;Create sky preshifts bsr birdinit ;Initialise game bsr floorinit bsr pipeinit bsr gameinit bsr tickerinit bsr highscoreinit bsr tickersethighscore bsr titleinit bsr medalinit bsr titlereset ;Start on title screen ;Now change resolution bsr utilsetlowres lea intvbl,a0 ;Set new VBL vector bsr utilsetvblvector bsr utilwaitvbl ;Wait for next retrace bsr utilblackpalette ;Black out palette bsr utilfindscreen ;Find physical and off-screen addresses move.l phybse,a0 ;Clear both screens bsr utilclearscreen move.l logbse,a0 bsr utilclearscreen ;Game start bsr gamebuildscreen ;Draw game screen to both swap buffers move.l #skyhandler,timerbhandler move.l #titlehandler,handler .loop IFGT ENABLECPUTIME move.w #$700,$ffff8240.w ENDC move.l handler,a0 ;Run game handler jsr (a0) bsr floordraw bsr tickerupdate bsr tickerdraw addq.w #1,exitcount IFGT ENABLECPUTIME move.w #$000,$ffff8240.w ENDC bsr ikbdupdate ;Read input move.w debouncejoys,d0 ;Check joysticks and extended joysticks or.w debounceextjoys,d0 and.w #JOYSTICK0FIRE+JOYSTICK1FIRE,d0 move.w d0,flapbutton lea debouncekeys,a0 ;Fast check for multiple keypress bytes move.b 3(a0),d0 and.b #$10,d0 ;Check Return(bit 28) bne.s .setinput move.l 4(a0),d0 and.l #$00044002,d0 ;Check Left Shift(bit 42), Right Shift(bit 54), Space(bit 57) bne.s .setinput beq.s .noinput .setinput move.w #1,flapbutton .noinput move.b #$02,d0 ;'1' pressed for 60Hz? bsr ikbdtestdebouncekey beq.s .nontsc60hz move.b #1,ntsc60hz .nontsc60hz move.b #$0b,d0 ;'0' pressed for 50Hz? bsr ikbdtestdebouncekey beq.s .nopal50hz move.b #1,pal50hz .nopal50hz IFGT ENABLEDEBUGQUIT move.b #$01,d0 ;Pressed 'ESC' to quit? bsr ikbdtestdebouncekey bne.s .done ENDC cmp.w #MACHINE_FALCON,machine ;If running on a Falcon sync to VBL beq.s .syncvbl bsr utilwaitdisplayblank ;Wait for Display Blanking on ST/STe bra.s .sync .syncvbl bsr utilwaitvbl ;Wait for VBL on Falcon .sync move.w whiteoutcount,d0 ;Check if need to white-out screen beq.s .nowhiteout subq.w #1,d0 move.w d0,whiteoutcount move.l whiteoutbse,d0 bsr utilswapscreend0 bra.w .loop .nowhiteout bsr utilswapscreen ;Swap screens bra.w .loop .done ;Cleanup on exit bsr logcleanup bsr ikbdcleanup bsr utilrestorestate bsr soundstopall move.l oldsuper,a0 bsr utilsupermode move.w #0,-(sp) ;Return code (ie program completed without error) move.w #$4c,-(sp) ;Pterm (releases all memory and closes files) trap #1 addq.w #4,sp ;---------------------------------- ;Empty GEMDOS critical error handler to avoid GEM dialogs appearing (ie disc write-protect) gemdoserrorhandler rts ;---------------------------------- ;New VBL interrupt routine intvbl movem.l d0/a0-a1,-(sp) addq.l #1,vblcount ;Increment VBL counter move.w nextrasterset,rasterset ;Set raster set move.l timerbhandler,d0 ;Do we have a Timer B handler? beq.s .notimerb move.l d0,a0 jsr (a0) ;Set Timer B .notimerb move.l nextscreen,d0 ;Do we have a new screen address to set? beq.s .noscreen lea $ffff8201.w,a0 ;Video Base Address lsr.l #8,d0 ;Get screen address High+Mid movep.w d0,(a0) ;Write High+Mid value move.l #0,nextscreen ;Clear as done .noscreen move.l nextpalette,d0 ;Do we have a new palette? Stored as 16 STfm colours and 16 STe colours beq.s .nopalette move.l d0,a0 move.w machine,d0 btst #0,d0 ;Test bottom bit of machine which is set for STe/Falcon beq.s .standardpal lea 16*2(a0),a0 ;Select enhanced palette for STe/Falcon .standardpal lea $ffff8240.w,a1 move.l (a0)+,(a1)+ ;Copy all 16 palette RGB values move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0),(a1) move.l #0,nextpalette ;Clear as done .nopalette moveq.w #0,d0 cmp.b pal50hz,d0 ;Check for 50Hz/60Hz beq.s .nopal50hz move.b d0,pal50hz bsr utilset50hz bsr gamesetbirdvelocity ;Update velocities for refresh rate bra.s .nontsc60hz .nopal50hz cmp.b ntsc60hz,d0 beq.s .nontsc60hz move.b d0,ntsc60hz bsr utilset60hz bsr gamesetbirdvelocity .nontsc60hz movem.l (sp)+,d0/a0-a1 rte ;---------------------------------- SECTION BSS pal50hz ds.b 1 ;Set to 1 to set Hz on next VBL ntsc60hz ds.b 1 count ds.w 1 ;Generic counter exitcount ds.w 1 ;Frame counter used to clean up from previous screen whiteoutcount ds.w 1 ;White-out screen timer if !=0 flapbutton ds.w 1 ;!=0 if pressed key/fire button to flap handler ds.l 1 ;Game handler (called each frame) EVEN ;Flappybird for the Atari ST INCLUDE "\SRC\BOOT.INC" INCLUDE "\SRC\RASTERS.INC" INCLUDE "\SRC\FONT.INC" INCLUDE "\SRC\IKBD.INC" INCLUDE "\SRC\SOUND.INC" INCLUDE "\SRC\LZ77.INC" INCLUDE "\SRC\LOG.INC" INCLUDE "\SRC\ERROR.INC" INCLUDE "\SRC\UTIL.INC" INCLUDE "\SRC\GAME.INC" INCLUDE "\SRC\TITLE.INC" INCLUDE "\SRC\GETREADY.INC" INCLUDE "\SRC\MEDAL.INC" INCLUDE "\SRC\BIRD.INC" INCLUDE "\SRC\PIPE.INC" INCLUDE "\SRC\SCORELRG.INC" INCLUDE "\SRC\SCORESML.INC" INCLUDE "\SRC\FLOOR.INC" INCLUDE "\SRC\SKY.INC" INCLUDE "\SRC\TICKER.INC" INCLUDE "\SRC\PRESHIFT.INC" INCLUDE "\SRC\HISCORE.INC" INCLUDE "\SRC\DATA.INC" ;See textsize, datasize and bsssize in listing file(.LST) for game memory sizes SECTION TEXT textsize SECTION DATA datasize SECTION BSS bsssize ;INCLUDE filename ;INCBIN filename ;EVEN ;SECTION TEXT ;SECTION DATA ;SECTION BSS ;.label ;dc.b,dc.w,dc.l ;ds.b ,ds.w ,ds.l ;name EQU ;name = ;name SET (you can then do set again to change the value) ;RSRESET ;RSSET ;label1 rs.b 1 ;label2 rs.w 1 ;label MACRO ;.label\@ ;move.w \1,d0 ;move.w \2,d1 ;ENDM ;ie MARCO 12,3 ;REPT (to repeat section 'n' times, DO NOT USE IN MACRO) ;ENDR ;ie REPT 32 ;move.l (a0)+,(a1)+ ;ENDR ;IFEQ,IFNE,IFGT,IFLT,IFLE,IFGE (all compare to 0, MUST indent directive) ;ENDC ;DEBUG = 1 ;ie IFGT DEBUG ; ;ENDC . X,ED.. X,E3DATA LZ V,EEFIREFLAPINC X(ELFONT DAT UDT GAMEOVERINC lj(EWdAMEDALBKGINC )EhFY?'1? '?GG??8/O ?" ?'?? ?i|@?~?pd g8qG? OOG?<g'On 0<^T100@x_0WP/H _} UXAZ ` _B Jg  ՅG |5|??p pBV!O`  4>x0  sPs  yy  o 0 0 @ < /a Rww/   J@  / ``SP' ?' gg ?7gGG ?8/O ?? r'????iz||7?^^  ?OOguG?OOG?[g'OO0RR~1 1!T  P-AJ TP{  (H@   `# $bTF)Gp  ?l1p??pcp/O   ' >xpn @sso yy. ~ o 0 0 O@@ @ a jPww/   B@@  QyZOO g  ~?                           / /"/"/ >? ~$M_? ?m%z/ G _wwww_wө # ##C# k#  #   E`ޑ1Vzl @.TF_pwl~`sy/1EK| /+       w>B~_ r      0/:+    o!BR @^  @\\0Qh`[&? g#f #W# *g\! 0 { + ?"a| <@Cw03GGGG O?GGGG w/Bӷ" {l P`p0 O  ` O' '' O kO''kwCO'#AAAq PfX`?pmPP=V R1Pa:?P?M?HF??p#Vp߾~?|> ?_}??p"6?'u I١j!i$G&| "2;Pc %'/Q§kwOY)Ox/!@O`O  /@~㱊O?O0P O `O O O<O OOwOQq?"+OOtP!̀%a OO  zOO9m`]0 O?_2]'OO\001HO@OO0 ߿~^@OOO O? rOOBY@A O~9O OOO'OOO&O OO~ ЁPOOO$OOOO@&/OO[!OOO6oOOOOO6HOOOO OBOOOODOOQO ODOB_OFOOU&Oq%$/#/B_T_OOq=OO4OO@OOI? O8OO8?OOĀ9@yOPOO8$?4,iOu@CO?O<7ф@_'??O``? `OO>*a@!Oxϒ{S K!?qO F+/uOD_ O U HO'O?_OONqO 1'O%' OӼ-0 "l1T3F7>#_"Ho" @ @@` `G_V6>O#5Am "`a te F",!y~@@5 T!D"@8}B{x"@gpo&>oA2@xP37>@ad߽` !/8eO/ l jOg}}4P}| PKO@O{ uˠ_ߋL o"@@o@{`wA_>o/oO>?`[n"m_"Te"/oooooooUoooo@oo"oooooOoooooo00`foooooo4o ooo_ooMOo111/o1/o1O`1O(@@0A @/PH@H 00@@``@  ?`a@(@ !c c ?@ A ?P@@@`]ooo@ 0#op$0(PpQ x*ooOowwg 8gww3̽Rctt c_`Gtt 0?_?g 0H_(_lw%?9dMG? _ ssww3W wwqg /ss 3 /wbrO wGwQ A+4|G/~wA!Y p@ / ?@?0A /yw 60V?0>~ gn;s/> 8>_ m QoBq /룏 qpZw~>$sw/wY#0_)?# K?q>9v [8ap/o? wsImo i|uYoc Og' v O')_ / cu /O*8/p'?8!;U/V/-1! !AT;8FMDPNFUP'MBQQZ#JSEGPSUIF"UBSJ45+$VSSFOUIJHITDPSFJT#5PGHQSFTTEG@J'CVUUPO TQBD B!ScNPVT11LFZ)[+0SJHJOBMHBEFWFMPQFECZ%POH/ HVZFSSVOTPOBTUBOEB45'. 45FSPMMTTNPPUIMZBUu!  GSrTQFSTF DP0XJUIP"VUBTTFNCo %FW +@)FNVMBU PSgGVMMxTR \s JODMVEFBZVADLOFMO+PZ0G4=UJ#x+S6HPPEO!>1) add.w #160,d0 ;Centre on X move.l offscreenbse,a0 lea 160*9(a0),a0 ;Offset for Y bra drawscorelarge ;(does RTS) ;---------------------------------- ;Clear background behind game score gamescoreclear ;2020 cycles, 4 rasters move.l offscreenbse,a1 ;20 move.l #$ffff0000,d0 ;12 ;Sky, index 1 moveq.l #0,d1 ;4 move.l d0,d2 ;4 move.l d1,d3 ;4 move.l d0,d4 ;4 move.l d1,d5 ;4 move.l d0,d6 ;4 move.l d1,d7 ;4 move.l d0,a2 ;4 move.l d1,a3 ;4 move.l d0,a4 ;4 move.l d1,a5 ;4 movem.l d0-d7/a2-a5,160*9+56(a1) ;Clear 96 pixels by 18 lines, 1944 cycles movem.l d0-d7/a2-a5,160*10+56(a1) movem.l d0-d7/a2-a5,160*11+56(a1) movem.l d0-d7/a2-a5,160*12+56(a1) movem.l d0-d7/a2-a5,160*13+56(a1) movem.l d0-d7/a2-a5,160*14+56(a1) movem.l d0-d7/a2-a5,160*15+56(a1) movem.l d0-d7/a2-a5,160*16+56(a1) movem.l d0-d7/a2-a5,160*17+56(a1) movem.l d0-d7/a2-a5,160*18+56(a1) movem.l d0-d7/a2-a5,160*19+56(a1) movem.l d0-d7/a2-a5,160*20+56(a1) movem.l d0-d7/a2-a5,160*21+56(a1) movem.l d0-d7/a2-a5,160*22+56(a1) movem.l d0-d7/a2-a5,160*23+56(a1) movem.l d0-d7/a2-a5,160*24+56(a1) movem.l d0-d7/a2-a5,160*25+56(a1) movem.l d0-d7/a2-a5,160*26+56(a1) rts ;---------------------------------- ;Increment score by 1, pass a0.l as pointer to BCD score gamescoreinc ;100 cycles, 0.2 rasters addq.w #4,a0 ;8 ;End of destination score lea bcdone+4,a1 ;12 ;End of source '1' in BCD moveq.w #0,d0 ;4 ;Clear X (faster than using CCR) neg.w d0 ;4 abcd -(a1),-(a0) ;18 ;Add 4 BCD bytes, 8 digits abcd -(a1),-(a0) ;18 abcd -(a1),-(a0) ;18 abcd -(a1),-(a0) ;18 rts ;---------------------------------- ;Set game velocities according to 50hz/60hz gamesetbirdvelocity btst.b #1,$ffff820a.w ;Bit 1 is 0 for 60Hz or 1 for 50Hz beq.s .set60hz .set50hz move.l #BIRDFLAPVELY_50HZ,birdflapvely move.l #GRAVITY_50HZ,birdgravity rts .set60hz move.l #BIRDFLAPVELY_60HZ,birdflapvely move.l #GRAVITY_60HZ,birdgravity rts ;---------------------------------- SECTION DATA bcdone dc.l $00000001 ;'1' in 32-bit BCD format ;---------------------------------- SECTION BSS bcdscore ds.l 1 ;32-bit BCD score (BCD on 68000 dc.l $12345678 is the same as dc.b $12,$34,$56,$78) bcdhighscore ds.l 1 ;32-bit BCD high-score gameholdtimer ds.w 1 ;Hold timer to draw same image to both swap buffers whiteoutbse ds.l 1 ;White-out screen base address whiteoutscreen ds.b 32256 ;320*200 32Kbyte white-out screen, with 256 bytes for alignment ;'Get Ready' screen SECTION TEXT ;---------------------------------- ;Reset for 'Get Ready' screen getreadyreset bsr birdreset ;Reset bird move.w #112,birdx moveq.w #93,d0 move.w d0,birdy move.w d0,titlewavebasey moveq.l #0,d0 move.w d0,titlewave move.l d0,bcdscore ;Reset game score move.w d0,exitcount rts ;---------------------------------- ;Repair screen after exit getreadyrepaironexit move.l #160*92+56,d0 ;Screen offset bsr titleclearbird bsr getreadyrepairready bra getreadyrepairfiretoflap ;(does RTS) ;---------------------------------- ;'Get Ready' screen handler getreadyhandler move.w #RASTERSET_GETREADY,nextrasterset cmp.w #2,exitcount ;Repair last screen on both swap buffers bgt.s .norepair bsr titlerepaironexit .norepair bsr getreadydrawready bsr getreadydrawfiretoflap move.l #160*92+56,d0 ;Screen offset bsr titleclearbird bsr titleanimbird bsr birddraw bsr gamescoredraw bsr floorupdate move.w flapbutton,d0 ;Read input beq.s .noinput bsr gamereset move.l #gamehandler,handler lea flapsfx,a0 bsr soundplay0 .noinput rts ;---------------------------------- ;Draw 'Get Ready' logo getreadydrawready ;12764 cycles, 25 rasters lea getreadyimg,a0 ;12 move.l offscreenbse,a1 ;20 lea 160*38+40(a1),a1 ;8 moveq.w #17-1,d7 ;4 .loop movem.l (a0)+,d0-d6/a2-a6 ;108 ;Planes 1+2+3+4 for 96 pixels movem.l d0-d6/a2-a6,(a1) ;104 movem.l (a0)+,d0-d6/a2 ;76 ;Next 64 pixels movem.l d0-d6/a2,48(a1) ;72 lea 160(a1),a1 ;8 ;Next line movem.l (a0)+,d0-d6/a2-a6 ;108 movem.l d0-d6/a2-a6,(a1) ;104 movem.l (a0)+,d0-d6/a2 ;76 movem.l d0-d6/a2,48(a1) ;72 lea 160(a1),a1 ;8 dbra.w d7,.loop ;10/14 rts ;---------------------------------- ;Draw game instructions getreadydrawfiretoflap ;3172 cycles, 6 rasters move.l offscreenbse,a1 ;20 lea 160*84+64(a1),a1 ;8 INCLUDE "\SRC\DATA\FIREFLAP.INC" ;Compiled sprite, 3144 cycles rts ;---------------------------------- ;Repair 'Get Ready' logo getreadyrepairready ;6688 cycles, 13 rasters move.l offscreenbse,a1 ;20 lea 160*38+40(a1),a1 ;8 move.l #$ffff0000,d0 ;12 ;Sky, colour index 1 moveq.l #0,d1 ;4 move.l d0,d2 ;4 move.l d1,d3 ;4 move.l d0,d4 ;4 move.l d1,d5 ;4 move.l d0,d6 ;4 move.l d1,a2 ;4 move.l d0,a3 ;4 move.l d1,a4 ;4 move.l d0,a5 ;4 move.l d1,a6 ;4 moveq.w #17-1,d7 ;4 .loop movem.l d0-d6/a2-a6,(a1) ;104 ;Clear movem.l d0-d6/a2,48(a1) ;76 lea 160(a1),a1 ;8 ;Next line movem.l d0-d6/a2-a6,(a1) ;104 movem.l d0-d6/a2,48(a1) ;76 lea 160(a1),a1 ;8 dbra.w d7,.loop ;10/14 rts ;---------------------------------- ;Repair sky lines over game instructions, 304 cycles REPAIRFIRETOFLAPLINES MACRO movem.l d0-d3,(a1) ;40 movem.l d0-d3,160(a1) ;44 movem.l d0-d3,320(a1) ;44 movem.l d0-d3,480(a1) ;44 movem.l d0-d3,640(a1) ;44 movem.l d0-d3,800(a1) ;44 movem.l d0-d3,960(a1) ;44 ENDM ;---------------------------------- ;Repair game instructions getreadyrepairfiretoflap ;5024 cycles, 9.8 rasters move.l skyimg,a0 ;20 lea 80*17+16(a0),a0 ;8 ;Offset to sky line move.l offscreenbse,a1 ;20 lea 160*84+72(a1),a1 ;8 ;Matching line on screen move.l #$ffff0000,d0 ;12 ;Sky, colour index 1 moveq.l #0,d1 ;4 move.l d0,d2 ;4 move.l d1,d3 ;4 REPAIRFIRETOFLAPLINES ;304 ;Clear sky section, 28 lines lea 1120(a1),a1 ;8 REPAIRFIRETOFLAPLINES ;304 lea 1120(a1),a1 ;8 REPAIRFIRETOFLAPLINES ;304 lea 1120(a1),a1 ;8 REPAIRFIRETOFLAPLINES ;304 lea 1112(a1),a1 ;8 moveq.w #21-1,d7 ;4 ;Clear with sky image .loop movem.l (a0),d0-d6/a2 ;76 ;Read Planes 1+2+3+4 for 64 pixels of sky image lea 80(a0),a0 ;8 :Next line in source sky movem.l d0-d6/a2,(a1) ;72 ;Write to screen lea 160(a1),a1 ;8 ;Next screen line dbra.w d7,.loop ;10/14 rts  ;Read/Write high-score value to file using GEMDOS for compatibility ;The high-score is encrypted within a larger buffer and a CRC ensures the ;file cannot be tampered with (loaded values are also checked they are valid BCD) ;The GEMDOS error handler has been redirected to an empty function so file errors ;do not bring up GEMDOS dialogs during the game allowing silent errors ENABLEHIGHSCORE = 1 ;Set to 1 to enable high-score saving HISCOREBUFSIZE = 128 ;Size of high-score buffer HISCOREOFFSET = 28 ;Offset into buffer to store high-score value SECTION TEXT ;---------------------------------- ;Initialise high-score highscoreinit move.w #-1,hiscorefilehandle ;Default to error code (ie <0) bra highscoreread ;Read high-score (does RTS) IFGT ENABLEHIGHSCORE ;---------------------------------- ;Fill high-score buffer with data highscorefilldata lea datalz77+$1700,a0 ;Fill data to copy from lea hiscorebuffer,a1 bsr utilrandbyte ;Get random value in d0.b moveq.w #HISCOREBUFSIZE-1,d1 .loop add.b (a0)+,d0 move.b d0,(a1)+ dbra.w d1,.loop rts ;---------------------------------- ;Encrypt high-score buffer, pass d0.b as encrypt value highscoreencryptdata lea hiscorebuffer,a0 moveq.w #(HISCOREBUFSIZE-2)-1,d1 .loop add.b d0,(a0)+ ;Encrypt value with data ror.b #1,d0 dbra.w d1,.loop rts ;---------------------------------- ;Decrypt high-score buffer, pass d0.b as decrypt value highscoredecryptdata lea hiscorebuffer,a0 moveq.w #(HISCOREBUFSIZE-2)-1,d1 .loop sub.b d0,(a0)+ ;Decrypt value with data ror.b #1,d0 dbra.w d1,.loop rts ;---------------------------------- ;Calculate CRC and return in d0.w, with end of buffer in a0.l highscorecalccrc lea hiscorebuffer,a0 moveq.l #0,d0 ;CRC sum values moveq.l #0,d1 moveq.w #(HISCOREBUFSIZE-2)-1,d3 .loop move.b (a0)+,d2 ;Data byte add.b d2,d0 add.b d0,d1 dbra.w d3,.loop lsl.w #8,d1 ;Combine CRC sum values or.w d1,d0 ;d0.w is 16-bit CRC rts ;---------------------------------- ;Check d0.l is a valid BCD value and return -1 if not, 0 if OK highscorecheckbcd move.l d0,d1 ;Don't corrupt d0 moveq.w #8-1,d3 ;Check all digits .loop move.l d1,d2 ;Check digit is 0...9 and.w #$f,d2 cmp.w #9,d2 bgt.s .error ;Error if outside range lsr.l #4,d1 ;Check next digit dbra.w d3,.loop moveq.w #0,d1 ;Return OK rts .error moveq.w #-1,d1 ;Return error rts ;---------------------------------- ;Create high-score file highscorecreatefile move.w #0,-(sp) ;Read-Write move.l #hiscorefilename,-(sp) ;Filename, ie dc.b "FLAPPYBD._HI",0 move.w #$3c,-(sp) ;Fcreate trap #1 addq.w #8,sp move.w d0,hiscorefilehandle ;Store file handle (-ve on error) rts ;---------------------------------- ;Open high-score file highscoreopenfile move.w #2,-(sp) ;Read-Write move.l #hiscorefilename,-(sp) move.w #$3d,-(sp) ;Fopen trap #1 addq.w #8,sp move.w d0,hiscorefilehandle ;Store file handle (-ve on error) rts ;---------------------------------- ;Close high-score file highscoreclosefile move.w hiscorefilehandle,-(sp) move.w #$3e,-(sp) ;Fclose trap #1 addq.w #4,sp ;Ignore error code in d0.w move.w #-1,hiscorefilehandle ;Default to error code (ie <0) rts ENDC ;---------------------------------- ;Read data from high-score file highscoreread IFGT ENABLEHIGHSCORE bsr highscoreopenfile ;Attempt to open file bmi.s .error move.l #hiscorebuffer,-(sp) ;Buffer move.l #HISCOREBUFSIZE,-(sp) ;Length move.w hiscorefilehandle,-(sp) move.w #$3f,-(sp) ;Fread trap #1 adda.w #12,sp tst.l d0 ;Test for error code bmi.s .error lea hiscorebuffer+HISCOREBUFSIZE,a0 ;Read CRC value from buffer move.w -(a0),d0 move.w d0,-(sp) bsr highscoredecryptdata ;Decrypt buffer using CRC bsr highscorecalccrc ;Calculate CRC in d0.w move.w (sp)+,d1 cmp.w d0,d1 ;Do CRC values match? bne.s .error ;No lea hiscorebuffer+HISCOREOFFSET,a0 ;Read score from buffer move.l (a0),d0 bsr highscorecheckbcd ;Check if valid BCD bne.s .error move.l d0,bcdhighscore ;Copy score to game bsr highscoreclosefile .error ENDC rts ;---------------------------------- ;Write data to high-score file highscorewrite IFGT ENABLEHIGHSCORE bsr highscoreopenfile ;Attempt to open file bpl.s .openfile ;If fails, try to create file  bsr highscorecreatefile .openfile bmi.s .error bsr highscorefilldata ;Fill buffer with random data lea hiscorebuffer+HISCOREOFFSET,a0 ;Store score in buffer move.l bcdhighscore,(a0) bsr highscorecalccrc ;Calculate CRC move.w d0,(a0) ;Store CRC at end of buffer bsr highscoreencryptdata ;Encrypt buffer using CRC move.l #hiscorebuffer,-(sp) ;Buffer move.l #HISCOREBUFSIZE,-(sp) ;Length move.w hiscorefilehandle,-(sp) move.w #$40,-(sp) ;Fwrite trap #1 adda.w #12,sp tst.l d0 ;Test for error code bmi.s .error bsr highscoreclosefile .error ENDC rts ;---------------------------------- SECTION DATA hiscorefilename dc.b "FLAPPYBD._HI",0 EVEN ;---------------------------------- SECTION BSS hiscorefilehandle ds.w 1 ;File handle hiscorebuffer ds.b HISCOREBUFSIZE ;Buffer to read/write which holds encrypted score ;IKBD routines to store joysticks (including extended joysticks), mouse and keypresses ;NOTE - if send commands $80,1,$12,$1A (reset,disable mouse+joystick) the ST will enable both relative ;mouse and joystick packets. When in this mode joystick 1 fire is found at relative mouse button bit 0 ;NOTE - the keyboard handler uses MOVE.W #$2500,sr to allow higher priority MFP interrupts ;to run (ie Timer B and D) to prevent any Timer B palette effect glitches ENABLEEXTJOY = 1 ;Set to 1 to enable extended joysticks ENABLEMOUSE = 0 ;Set to 1 to enable mouse MOUSEBUTTON0 = $1 ;Mask for relative mouse buttons MOUSEBUTTON1 = $2 JOYSTICK0UP = $01 ;Mask for joysticks JOYSTICK0DOWN = $02 JOYSTICK0LEFT = $04 JOYSTICK0RIGHT = $08 JOYSTICK0FIRE = $80 JOYSTICK1UP = $0100 JOYSTICK1DOWN = $0200 JOYSTICK1LEFT = $0400 JOYSTICK1RIGHT = $0800 JOYSTICK1FIRE = $8000 SECTION TEXT ;---------------------------------- ;Initialise IKBD with new MFP interrupt handler and send starting commands ikbdinit moveq.l #0,d0 lea newkeys,a0 ;Clear 128 bits of key states lea keys,a1 lea debouncekeys,a2 moveq.w #4-1,d1 .loop move.l d0,(a0)+ move.l d0,(a1)+ move.l d0,(a2)+ dbra.w d1,.loop move.b d0,newmouserelbut ;Clear mouse move.b d0,newmouserelx move.b d0,newmouserely move.w #320/2,mousex move.w #200/2,mousey move.b d0,mousebut move.b d0,debouncemousebut move.w d0,newjoys ;Clear joysticks move.w d0,statejoys move.w d0,debouncejoys move.w d0,stateextjoys move.w d0,debounceextjoys move.l d0,packethandler ;Clear packet handler routine address move.w #$2700,sr ;Disable interrupts bclr.b #6,$fffffa0d.w ;Clear bit 6 (IKBD) in Interrupt Pending B move.l #intikbd,$118.w ;Set new IKBD vector move.w #$2300,sr ;Enable interrupts lea ikbdstartcmds,a0 bra ikbdsendcmds ;Set IKBD for our game (does RTS) ;---------------------------------- ;Clean up IKBD ikbdcleanup lea ikbdendcmds,a0 bra ikbdsendcmds ;Reset IKBD (does RTS) ;---------------------------------- ;Debounce all keys, joysticks and mouse buttons ikbdupdate lea newkeys,a0 ;Read keys modifed by interrupt lea keys,a1 ;Copy states to be read by game lea debouncekeys,a2 ;And make debounced states moveq.w #4-1,d2 ;128 bits .loop move.l (a0)+,d0 ;Keys move.l (a1),d1 ;Old Keys move.l d0,(a1)+ ;Copy Keys to Old Keys eor.l d0,d1 and.l d0,d1 ;Debounce Keys = Keys&(Old Keys^Keys) move.l d1,(a2)+ ;Store debounced Keys dbra.w d2,.loop move.w newjoys,d0 ;Joysticks move.w statejoys,d1 ;Old Joysticks move.w d0,statejoys ;Copy Joysticks to Old Joysticks eor.w d0,d1 and.w d0,d1 ;Debounce move.w d1,debouncejoys ;Store debounced Joysticks bsr ikbdreadextjoysticks ;Read Extended Joysticks into d0.w (0 if not supported) move.w stateextjoys,d1 ;Old Extended Joysticks move.w d0,stateextjoys ;Copy Extended Joysticks to Old Extended Joysticks eor.w d0,d1 and.w d0,d1 ;Debounce move.w d1,debounceextjoys ;Store debounced Extended Joysticks IFGT ENABLEMOUSE move.w mousex,d0 ;Get mouse position move.b newmouserelx,d1 move.b #0,newmouserelx ;Reset relative change ext.w d1 ;Sign-extend relative change add.w d1,d0 ;Add to position bge.s .leftok moveq.w #0,d0 ;Clamp 0...320 on X bra.s .rightok .leftok cmp.w #320-1,d0 ble.s .rightok move.w #320-1,d0 .rightok move.w d0,mousex move.w mousey,d0 move.b newmouserely,d1 move.b #0,newmouserely ext.w d1 add.w d1,d0 bge.s .topok moveq.w #0,d0 ;Clamp 0...200 on Y bra.s .bottomok .topok cmp.w #200-1,d0 ble.s .bottomok move.w #200-1,d0 .bottomok move.w d0,mousey move.b newmouserelbut,d0 ;Mouse Buttons move.b mousebut,d1 ;Old Buttons move.b d0,mousebut ;Copy Buttons to Old Buttons eor.b d0,d1 and.b d0,d1 ;Debounce move.b d1,debouncemousebut ;Store debounced Buttons ENDC rts ;---------------------------------- ;Return Z flag to show if key is pressed or not, pass d0.b as key scancode ikbdtestkey lea keys,a0 ;Access key states (so not modified by interrupt) ikbdbtstkey and.w #$7f,d0 ;Mask key scancode move.w d0,d1 ;Get bit 0...7 and.w #$7,d1 lsr.w #3,d0 ;Get byte offset btst.b d1,(a0,d0.w) ;Set Z state from key (0-released, 1-pressed) rts ;---------------------------------- ;Return Z flag to show if debounced key is pressed or not, pass d0.b as key scancode ikbdtestdebouncekey lea debouncekeys,a0 bra ikbdbtstkey ;---------------------------------- ;Read STe/Falcon extended joysticks and return in d0.w (returns 0 if on ST/TT) ;NOTE - on the SainT emulator it incorrectly triggers a bus error when ;addressing $ff9200/$ff9202 if we run as an STe ikbdreadextjoysticks moveq.w #0,d0 ;Clear return value IFGT ENABLEEXTJOY move.w machine,d1 btst #0,d1 ;Test bottom bit of machine which is set for STe/Falcon beq.s .noextjoysticks move.w #$fffe,$ffff9202.w ;Set mask to read joystick 0 fire button 0 in bit 1 move.w $ffff9200.w,d1 btst #1,d1 ;Extended joystick bits are clear if pressed bne.s .nofire0 or.w #JOYSTICK0FIRE,d0 ;Copy fire button to return value .nofire0 move.w #$ffef,$ffff9202.w ;Set mask to read joystick 1 fire button 0 in bit 3 move.w $ffff9200.w,d1 btst #3,d1 bne.s .nofire1 or.w #JOYSTICK1FIRE,d0 .nofire1 move.w #$fffe,$ffff9202.w ;Set mask to read joystick 0 directions in bits 8...11 move.w $ffff9202.w,d1 not.w d1 lsr.w #8,d1 and.w #$000f,d1 ;Shift bit to match JOYSTICKxxx defines or.w d1,d0 ;Copy directions move.w #$ffef,$ffff9202.w ;Set mask to read joystick 1 directions in bits 12...15 move.w $ffff9202.w,d1 not.w d1 lsr.w #4,d1 and.w #$0f00,d1 or.w d1,d0 .noextjoysticks ENDC rts ;---------------------------------- ;Send byte commands to keyboard, pass a0.l as byte count to send followed by byte commands ikbdsendcmds bsr ikbdreadysend ;Wait until able to send bytes to keyboard moveq.w #0,d0 move.b (a0)+,d0 ;Send bytes to send subq.w #1,d0 ;-1 for dbra .loop move.b (a0)+,$fffffc02.w ;Write byte to ACIA Data bsr ikbdreadysend ;Wait until sent dbra.w d0,.loop rts ;---------------------------------- ;Wait until ready to send next byte to keyboard ikbdreadysend move.b $fffffc00.w,d1 ;Read ACIA Status btst #1,d1 ;Test bit 1 Tx Data Register Empty beq.s ikbdreadysend ;Byte waiting, check again rts ;---------------------------------- ;IKBD interrupt handler intikbd move.w #$2500,sr ;Allow higher priority MFP Timer B/Timer D interrupt this routine movem.l a0/d0-d1,-(sp) moveq.l #0,d0 move.b $fffffc00.w,d0 ;Read ACIA Status btst #7,d0 ;Test bit 7 Interrupt Request beq.s .ignore btst #0,d0 ;Test bit 0 Rx Data Register Full beq.s .skipbyte .anotherbyte btst #4,d0 ;Test bit 4 Framing Error bne.s .skipbyte btst #5,d0 ;Test bit 5 Rx Overrun bne.s .skipbyte btst #6,d0 ;Test bit 6 Parity Error bne.s .skipbyte move.b $fffffc02.w,d0 ;Read ACIA Data move.l packethandler,a0 ;In middle of a packet? cmp.l #0,a0 bne.s .continuepacket ;Continue to read packet cmp.w #$f6,d0 ;Check for start of packet bge.s .startpacket ;$f6...$ff is a packet, otherwise key lea newkeys,a0 ;Store key state in table move.w d0,d1 ;Get bit 0...7 of scancode and.w #$7,d1 asr.b #3,d0 ;Get byte offset 0...15 and keep top bit of byte bmi.s .keyreleased ;N is bit 7 (0-pressed, 1-released) and.w #$f,d0 ;Mask offset bset.b d1,(a0,d0.w) ;Set key as pressed bra .done .keyreleased and.w #$f,d0 ;Mask offset bclr.b d1,(a0,d0.w) ;Set key as released .done moveq.l #0,d0 move.b $fffffc00.w,d0 ;Read ACIA Status btst #0,d0 ;Test bit 0 again to see if we have another byte bne.s .anotherbyte bclr.b #6,$fffffa11.w ;Clear bit 6 (IKBD) in Interrupt In-Service B .ignore movem.l (sp)+,a0/d0-d1 rte .skipbyte move.b $fffffc02.w,d0 ;Read ACIA Data to skip byte bra .done .continuepacket jmp (a0) ;Run routine to store next byte in packet .startpacket cmp.b #$ff,d0 ;$ff is Joystick 0 (mouse port) header bne.s .notff move.l #.ikbdpacketff,packethandler bra .done .notff cmp.b #$fe,d0 ;$fe is Joystick 1 header bne.s .notfe move.l #.ikbdpacketfe,packethandler bra .done .notfe move.b d0,d1 and.b #$f8,d1 ;$f8...$fb is Relative Mouse Position header cmp.b #$f8,d1 bne.s .notf8 and.b #$3,d0 ;Mask mouse buttons move.b d0,newmouserelbut ;Store mouse button state move.l #.ikbdpacketf8,packethandler bra .done .notf8 bra errorikbdpacket ;Unsupported keyboard packet (ie $f6, $f7 and $fc) ;Packet handlers .ikbdpacketff ;$ff move.b d0,newjoys ;Store joystick 0 (mouse port) state move.l #0,packethandler ;End of packet bra .done .ikbdpacketfe ;$fe move.b d0,newjoys+1 ;Store joystick 1 state move.l #0,packethandler ;End of packet bra .done .ikbdpacketf8 ;$f8...$fb move.b d0,newmouserelx ;Store relative mouse X move.l #.ikbdpacketf8byte2,packethandler bra .done .ikbdpacketf8byte2 move.b d0,newmouserely ;Store relative mouse Y move.l #0,packethandler ;End of packet bra .done ;---------------------------------- SECTION DATA ikbdstartcmds IFGT ENABLEMOUSE ;The following enables both auto relative mouse+auto joystick reporting dc.b 4 ;Number of bytes to send dc.b $80,1 ;Reset IKBD dc.b $12 ;Disable mouse dc.b $1A ;Disable joysticks ENDC dc.b 3 ;Number of bytes to send dc.b $80,1 ;Reset IKBD dc.b $14 ;Start auto joystick reporting ikbdendcmds dc.b 2 ;Number of bytes to send dc.b $80,1 ;Reset IKBD EVEN ;---------------------------------- SECTION BSS packethandler ds.l 1 ;Address of routine to handle packet (or 0 if none) newkeys ds.l 4 ;128 bit state of keys modified by interrupt (0-released, 1-pressed) newjoys ds.w 1 ;State of Joystick 0 (mouse port) and Joystick 1 newmouserelbut ds.b 1 ;State of relative mouse buttons, X and Y newmouserelx ds.b 1 newmouserely ds.b 1 EVEN keys ds.l 4 ;Key states for this frame debouncekeys ds.l 4 ;Debounce version of above statejoys ds.w 1 ;State of Joystick 0 and 1 for this frame debouncejoys ds.w 1 ;Debounce version of above stateextjoys ds.w 1 ;State of Extended Joystick 0 and 1 for this frame debounceextjoys ds.w 1 ;Debounce version of above mousex ds.w 1 ;Mouse X mousey ds.w 1 ;Mouse Y mousebut ds.b 1 ;Mouse buttons debouncemousebut ds.b 1 ;Debounce version of above ;Log file used for debugging ENABLELOG = 0 ;Set to 1 to enable log file SECTION TEXT ;---------------------------------- ;Create log file loginit IFGT ENABLELOG move.w #0,-(sp) ;Read-Write move.l #logfilename,-(sp) ;Filename, ie dc.b "LOG.TXT",0 move.w #$3c,-(sp) ;Fcreate trap #1 addq.w #8,sp tst.w d0 ;Test for error code bmi errorfileopen move.w d0,logfilehandle ;Store file handle ENDC rts ;---------------------------------- ;Close log file logcleanup IFGT ENABLELOG move.w logfilehandle,-(sp) move.w #$3e,-(sp) ;Fclose trap #1 addq.w #4,sp tst.w d0 ;Test for error code bmi errorfileclose ENDC rts ;---------------------------------- ;Write string in a0.l to log file logstring IFGT ENABLELOG movem.l d0-d7/a0-a6,-(sp) bsr logfindstringlength ;d0.l is length of string a0 bsr logwrite ;Write data at a0 for length d0.l movem.l (sp)+,d0-d7/a0-a6 ENDC rts ;---------------------------------- ;Write value in d0.w to log file as HEX string logword IFGT ENABLELOG movem.l d0-d7/a0-a6,-(sp) lea textword,a0 ;Buffer to write digits bsr utilword2text ;Convert d0.w to text string lea textword,a0 moveq.l #4,d0 bsr logwrite ;Write data at a0 for length d0 movem.l (sp)+,d0-d7/a0-a6 ENDC rts ;---------------------------------- ;Write value in d0.l to log file as HEX string loglong IFGT ENABLELOG movem.l d0-d7/a0-a6,-(sp) lea textlong,a0 ;Buffer to write digits bsr utillong2text ;Convert d0.l to text string lea textlong,a0 moveq.l #8,d0 bsr logwrite ;Write data at a0 for length d0 movem.l (sp)+,d0-d7/a0-a6 ENDC rts ;---------------------------------- ;Write newline to log file lognewline IFGT ENABLELOG movem.l d0-d7/a0-a6,-(sp) lea logmsgnewline,a0 moveq.l #2,d0 bsr logwrite ;Write data at a0 for length d0 movem.l (sp)+,d0-d7/a0-a6 ENDC rts ;---------------------------------- ;Write line break to log file loglinebreak IFGT ENABLELOG movem.l d0-d7/a0-a6,-(sp) lea logmsglinebreak,a0 moveq.l #12,d0 bsr logwrite ;Write data at a0 for length d0 movem.l (sp)+,d0-d7/a0-a6 ENDC rts ;---------------------------------- ;Return length of string, pass string in a0.l, return length in d0.l logfindstringlength IFGT ENABLELOG moveq.l #0,d0 .loop tst.b (a0)+ ;Loop and count characters in string beq.s .done addq.l #1,d0 bra.s .loop .done suba.l d0,a0 ;Restore a0 back to start of string subq.w #1,a0 ENDC rts ;---------------------------------- ;Write data to log file, pass buffer in a0.l and length in d0.l logwrite IFGT ENABLELOG move.l a0,-(sp) ;Buffer move.l d0,-(sp) ;Length move.w logfilehandle,-(sp) move.w #$40,-(sp) ;Fwrite trap #1 adda.w #12,sp tst.l d0 ;Test for error code bmi errorfileread ENDC rts ;---------------------------------- SECTION DATA IFGT ENABLELOG logfilename dc.b "LOG.TXT",0 logmsgnewline dc.b $d,$a,0 logmsglinebreak dc.b "----------",$d,$a,0 EVEN ENDC ;---------------------------------- SECTION BSS IFGT ENABLELOG logfilehandle ds.w 1 ;Log file handle ENDC ;LZ77 compression ENABLELZ77CHECKSUM = 0 ;Set to 1 to test simple checksum after uncompress SECTION TEXT ;---------------------------------- ;Uncompress LZ77 data, a0.l as compressed data, a1.l as uncompressed buffer ;Corrupt d0-d4/a0-a2 lz77uncompress IFGT ENABLELZ77CHECKSUM move.l a0,-(sp) ;Store a0/a1 as need later for checksum move.l a1,-(sp) ENDC move.l (a0)+,d0 ;Read uncompressed byte total and checksum and.l #$00ffffff,d0 ;Mask out checksum .loop move.b (a0)+,d1 ;Read flag bit-mask moveq.w #8-1,d2 ;Loop on each flag bit .loopflags lsl.b #1,d1 ;Move upper bit into carry bcc.s .copybyte ;If carry is clear copy byte, else copy string .copystring moveq.l #0,d3 move.b (a0)+,d3 ;Read offset and length to d3 move.l d3,d4 ;Copy to d4 and.b #$f0,d3 ;Mask 12-bit offset lsl.w #4,d3 move.b (a0)+,d3 ;Combine with lower 8-bits of offset neg.w d3 lea -1(a1,d3.w),a2 ;Set a2 as dst-offset-1 to copy from and.w #$f,d4 ;Mask and get length+3 addq.w #3,d4 sub.l d4,d0 ;Decrement total bytes add.w d4,d4 ;Get length as word-offset neg.w d4 jmp .endcopystring(pc,d4.w) ;Jump ahead into unrolled loop move.b (a2)+,(a1)+ ;Copy previous string bytes move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ move.b (a2)+,(a1)+ .endcopystring tst.l d0 ble.s .done ;Have uncompressed all bytes? dbra.w d2,.loopflags bra.s .loop .copybyte move.b (a0)+,(a1)+ ;Copy single byte subq.l #1,d0 ;Decrement total bytes ble.s .done ;Have uncompressed all bytes? dbra.w d2,.loopflags bra.s .loop .done IFGT ENABLELZ77CHECKSUM tst.l d0 :Check how many we uncompressed bne errorlz77sizemismatch ;Error if uncompress too many bytes move.l (sp)+,a1 ;Restore pointers move.l (sp)+,a0 bsr lz77testchecksum ;Test checksum ENDC rts ;---------------------------------- ;Test LZ77 checksum, a0.l as compressed data, a1.l as uncompressed buffer lz77testchecksum IFGT ENABLELZ77CHECKSUM move.l (a0),d0 ;Read uncompressed byte total and checksum move.l d0,d1 and.l #$00ffffff,d0 ;Mask d0 as total bytes rol.l #8,d1 and.l #$ff,d1 ;Get d1 as source checksum byte moveq.b #0,d2 ;d2 as uncompressed checksum .loop add.b (a1)+,d2 ;Add to checksum subq.l #1,d0 ;Decrement total bytes bgt.s .loop ;Have checked all bytes? cmp.b d2,d1 ;Compare final checksum values bne errorlz77checksumfail ;Error if different ENDC rts ;'Game Over' screen GAMEOVERTIMEOUT = 30*50 ;Return to title screen after 30 seconds @ 50Hz SECTION TEXT ;---------------------------------- ;Initialise 'Medal' screen medalinit bra medalreset ;(does RTS) ;---------------------------------- ;Reset for 'Game Over' screen medalreset moveq.l #0,d0 move.l d0,bcddisplayscore move.w d0,newbest move.w d0,awardmedal move.w d0,medalcount move.w d0,medaltimeout move.l d0,medalpalette move.l d0,medalpalette+4 move.w d0,exitcount lea sparkles,a0 bsr medalrandomsparkle lea SPARKLE_SIZE(a0),a0 bra medalrandomsparkle ;(does RTS) ;---------------------------------- ;'Medal' screen handlers medalhandler move.w #RASTERSET_MEDAL,nextrasterset bsr medaldrawscreen addq.w #1,medalcount bra medalcountscore ;(does RTS) medalcompletehandler bsr medaldrawscreen addq.w #1,medaltimeout move.w flapbutton,d0 ;Read input beq.s .noinput lea gameoversfx,a0 bsr soundplay0 move.w #RASTERSET_BLACKOUT,nextrasterset move.l #medalgetreadyhandler,handler rts ;Return here so don't check time-out .noinput cmp.w #GAMEOVERTIMEOUT,medaltimeout ;Time-out and go back to title bne.s .notimeout move.w #RASTERSET_BLACKOUT,nextrasterset move.l #medaltitlehandler,handler .notimeout rts medalgetreadyhandler move.w newbest,d0 ;Write high-score to file if new beq.s .nohighscore bsr highscorewrite .nohighscore bsr skyrandomsky ;Random day or night sky bsr gamebuildscreen ;Rebuild screen on both swap buffer while palette is black bsr birdrandompalette bsr getreadyreset move.l #getreadyhandler,handler rts medaltitlehandler move.w newbest,d0 beq.s .nohighscore bsr highscorewrite .nohighscore bsr skyrandomsky bsr gamebuildscreen bsr birdrandompalette bsr titlereset move.l #titlehandler,handler rts ;---------------------------------- ;Draw 'Game Over' screen medaldrawscreen bsr medaldrawbkgnd bsr medaldrawgameover move.w awardmedal,d0 bsr medaldraw move.w awardmedal,d0 ;Draw sparkles if have medal beq.s .nosparkles lea sparkles,a0 bsr medaldrawsparkle lea sparkles+SPARKLE_SIZE,a0 bsr medaldrawsparkle .nosparkles move.l bcddisplayscore,d1 ;Score in 32-bit BCD format move.l offscreenbse,a0 lea 160*65(a0),a0 bsr medaldrawscore move.l bcdhighscore,d1 ;High-score in 32-bit BCD format move.l offscreenbse,a0 lea 160*86(a0),a0 bra medaldrawscore ;(does RTS) ;---------------------------------- ;State to count up score and give award/high-score medalcountscore ;Check input to skip count up sequence move.w flapbutton,d0 ;Read input beq.s .noinput move.l bcdscore,bcddisplayscore .noinput ;Latch for counting up score (vary speed by value of score) moveq.w #3,d1 ;Slow speed move.l bcdscore,d0 cmp.l #50,d0 ;Is score <50? Count slow bls.s .checklatch ;d0<= (unsigned) moveq.w #1,d1 ;Normal speed cmp.l #100,d0  ;Is score <100? Count normal bls.s .checklatch ;d0<= (unsigned) bra.s .countup ;Fast speed .checklatch move.w medalcount,d0 ;Check latch to add one to count and.w d1,d0 beq.s .countup rts .countup move.l bcddisplayscore,d0 ;Read 32-bit BCD scores move.l bcdscore,d1 cmp.l d0,d1 ;Does display score match player score? beq.s .giveaward lea bcddisplayscore,a0 ;Increment display score bra gamescoreinc ;(does RTS) .giveaward ;Set medal as 20 for bronze, 40 silver, 60 gold and 80+ plantuim move.l bcdscore,d0 ;Read 32-bit BCD score lsr.l #4,d0 ;Skip last digit cmp.l #8,d0 ;Clamp 0...8 bls.s .clamp ;d0<= (unsigned) moveq.l #8,d0 .clamp lsr.w #1,d0 ;Divide by 2 for medal index 0...4 move.w d0,awardmedal lsl.w #3,d0 lea medalpalettes(pc,d0.w),a1 ;Source medal palettes lea medalpalette,a2 ;Destination palette move.l (a1)+,(a2)+ ;Copy 4 colours move.l (a1),(a2) ;Set new high-score move.l bcdhighscore,d0 ;Check if is new high-score move.l bcdscore,d1 cmp.l d0,d1 bls.s .nohigh ;d1<=d0 (unsigned) move.w #1,newbest ;Set as new high-score move.l bcdscore,bcdhighscore .nohigh move.l #medalcompletehandler,handler rts ;---------------------------------- medalpalettes dc.w $000,$000,$000,$000 ;None dc.w $521,$631,$740,$661 ;Bronze dc.w $222,$333,$555,$666 ;Silver dc.w $530,$651,$661,$671 ;Gold dc.w $333,$555,$666,$777 ;Platinum ;---------------------------------- ;Draw medal score, pass d1.w as score and a0.l as screen address medaldrawscore bsr scoresmalllength ;Get length of score in d0.w neg.w d0 add.w #204,d0 ;Right justified bra drawscoresmall ;(does RTS) ;---------------------------------- ;Draw 'Game Over' sprite medaldrawgameover ;7840 cycles, 15 rasters move.l offscreenbse,a1 ;20 lea 160*8+40(a1),a1 ;8 INCLUDE "\SRC\DATA\GAMEOVER.INC" ;Compiled sprite, 7812 cycles rts ;---------------------------------- ;Draw medal background medaldrawbkgnd ;32 rasters move.l offscreenbse,a0 ;20 lea 160*48+48(a0),a0 ;8 INCLUDE "\SRC\DATA\MEDALBKG.INC" ;Compiled sprite rts ;---------------------------------- medals dc.l medalsimg+(368*0) dc.l medalsimg+(368*1) dc.l medalsimg+(368*2) dc.l medalsimg+(368*3) dc.l medalsimg+(368*4) ;---------------------------------- ;Draw medal, d0.w is medal index medaldraw ;2084 cycles, 4 rasters lsl.w #2,d0 ;12 move.l medals(pc,d0.w),a0 ;20 ;Source medal image move.l offscreenbse,a1 ;20 lea 160*70+56(a1),a1 ;8 REPT 23 ;2024 move.l (a0)+,(a1)+ ;20 ;Copy 32 pixels by 23 lines move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1) lea 160-12(a1),a1 ;8 ;Next line ENDR rts ;---------------------------------- ;Start random sparkle, pass a0.l as sparkle structure medalrandomsparkle move.w #0,SPARKLE_FRAME(a0) ;Reset animation frame bsr utilrandbyte ;Get random value in d0.b and.w #$3f,d0 add.w #16,d0 move.w d0,SPARKLE_TIME(a0) ;Store random time before show sparkle bsr utilrandword ;Get random value in d0.w move.w d0,d1 and.w #$7,d1 ;Set 0...7 move.w d1,SPARKLE_XSET(a0) lsr.w #3,d0 and.w #$f,d0 ;Range 0...15 add.w #71,d0 ;Screen Y add.w d0,d0 ;Look up screen line offset lea screenlines,a1 move.w (a1,d0.w),SPARKLE_YOFFSET(a0) ;And store rts ;---------------------------------- sparkleanim dc.l sparklepreshift+(480*0),sparklepreshift+(480*1),sparklepreshift+(480*2),sparklepreshift+(480*1),sparklepreshift+(480*0) sparklesets dc.w 60*0,56 dc.w 60*1,56 dc.w 60*2,56 dc.w 60*3,56 dc.w 60*4,64 dc.w 60*5,64 dc.w 60*6,64 dc.w 60*7,64 ;---------------------------------- ;Animate and draw sparkle, pass a0.l as sparkle structure medaldrawsparkle ;778 cycles, 1.5 rasters move.w SPARKLE_TIME(a0),d0 ;12 ;Count down time delay or draw sparkle ble.s .draw ;10/8 subq.w #1,d0 ;4 move.w d0,SPARKLE_TIME(a0) ;12 rts .draw move.w SPARKLE_FRAME(a0),d0 ;12 addq.w #1,d0 ;4 ;Advance sparkle frame cmp.w #5*4,d0 ;8 ;Have shown all frames? bge medalrandomsparkle ;10/8 ;Yes, random next sparkle (does RTS) move.w d0,SPARKLE_FRAME(a0) ;12 and.w #$fffc,d0 ;8 ;Get index move.l sparkleanim(pc,d0.w),a2 ;20 ;Look up sprite frame move.w SPARKLE_XSET(a0),d0 ;12 lsl.w #2,d0 ;12 lea sparklesets(pc,d0.w),a3 ;12 add.w (a3)+,a2  ;12 ;Offset preshift for X move.l offscreenbse,a1 ;20 add.w (a3)+,a1 ;12 ;Offset screen for X add.w SPARKLE_YOFFSET(a0),a1 ;6 ;And Y REPT 5 ;600 movem.l (a2)+,d0-d2 ;36 ;Read Mask and Planes 1+2+3+4 and.l d0,(a1) ;20 ;Mask and write Planes 1+2+3 or.l d1,(a1)+ ;20 and.l d0,(a1) ;20 or.w d2,(a1) ;16 lea 160-4(a1),a1 ;8 ENDR rts ;---------------------------------- ;Sparkle structure RSRESET SPARKLE_FRAME rs.w 1 ;Animation frame SPARKLE_TIME rs.w 1 ;Frames before show sparkle SPARKLE_XSET rs.w 1 ;X set (one of 8 preshifts) SPARKLE_YOFFSET rs.w 1 ;Y screen line offset SPARKLE_SIZE = 8 NUMSPARKLES = 2 ;We have 2 sparkles on screen ;---------------------------------- SECTION BSS bcddisplayscore ds.l 1 ;32-bit BCD display score newbest ds.w 1 ;!=0 if have new high-score awardmedal ds.w 1 ;Awarded medal, ie 0-none, 1-bronze, 2-silver, 3-gold, 4-platinum medalcount ds.w 1 ;Display score count latch medaltimeout ds.w 1 ;Counter to time-out and return to title screen medalpalette ds.w 4 ;Palette of 4 colours used for medal sparkles ds.b SPARKLE_SIZE*NUMSPARKLES ;Pipe drawing using preshifts for scrolling ENABLECOLLISION = 1 ;Set to 1 to enable collision ENABLEPIPESCROLL = 1 ;Set to 1 to enable pipe scrolling ENABLESCROLLCHECK = 0 ;Set to 1 to enable scrolling check for all Y offsets SECTION TEXT ;---------------------------------- ;Initialise pipes pipeinit move.w #70,pipecheck ;Check scroll for pipe Y offsets of 70...0 bra pipereset ;(does RTS) ;---------------------------------- ;Reset pipe positions for start of game pipereset lea pipes,a0 move.w #340,d2 ;Starting position off-screen for first pipe moveq.w #NUMPIPES-1,d3 .loop move.w d2,PIPE_X(a0) bsr piperandomoffset bsr pipeset lea PIPE_SIZE(a0),a0 add.w #PIPEXGAP,d2 dbra.w d3,.loop rts ;---------------------------------- ;Return d0.w as random gap Y offset (0...70 inclusive) piperandomoffset bsr utilrandword ;Random value in d0.w move.w d0,d1 and.w #63,d0 ;0...63 lsr.w #6,d1 and.w #7,d1 ;0...7 add.w d1,d0 ;Range is 0...70 inclusive rts ;---------------------------------- ;Set pipe details, pass d0.w as gap Y offset (0...70 inclusive) and a0.l as pipe structure pipeset IFGT ENABLESCROLLCHECK move.w pipecheck,d0 ;Read and decrement each Y offset to check scroller subq.w #1,pipecheck bge.s .checkok move.w #0,pipecheck .checkok ENDC lea pipedetails,a1 move.w d0,d1 ;Store Y line for end of top pipe (ie gap) add.w #20,d1 ;End of top pipe ranges 20...90 move.w d1,PIPE_Y(a0) add.w d0,d0 add.w pipedetailstbl(pc,d0.w),a1 ;*52 move.w (a1)+,PIPE_LINEOFFSET(a0) ;Copy pipe details for Y offset move.w (a1)+,PIPE_CAPOFFSET(a0) move.w (a1)+,PIPE_SKYOFFSET(a0) move.w (a1)+,PIPE_SKY1OFFSET(a0) move.w (a1)+,PIPE_SKY2OFFSET(a0) move.w (a1)+,PIPE_SKY3OFFSET(a0) move.l (a1)+,PIPE_FUNCTOP(a0) move.l (a1)+,PIPE_FUNCTOP1(a0) move.l (a1)+,PIPE_FUNCTOP2(a0) move.l (a1)+,PIPE_FUNCTOP3(a0) move.l (a1)+,PIPE_FUNCTOP4(a0) move.l (a1)+,PIPE_FUNCBOTTOM(a0) move.l (a1)+,PIPE_FUNCBOTTOM1(a0) move.l (a1)+,PIPE_FUNCBOTTOM2(a0) move.l (a1)+,PIPE_FUNCBOTTOM3(a0) move.l (a1)+,PIPE_FUNCBOTTOM4(a0) rts ;---------------------------------- pipedetailstbl dc.w 52*0,52*1,52*2,52*3,52*4,52*5,52*6,52*7,52*8,52*9,52*10,52*11,52*12 dc.w 52*13,52*14,52*15,52*16,52*17,52*18,52*19,52*20,52*21,52*22,52*23,52*24,52*25 dc.w 52*26,52*27,52*28,52*29,52*30,52*31,52*32,52*33,52*34,52*35,52*36,52*37,52*38 dc.w 52*39,52*40,52*41,52*42,52*43,52*44,52*45,52*46,52*47,52*48,52*49,52*50,52*51 dc.w 52*52,52*53,52*54,52*55,52*56,52*57,52*58,52*59,52*60,52*61,52*62,52*63,52*64 dc.w 52*65,52*66,52*67,52*68,52*69,52*70 ;---------------------------------- ;Scroll pipes and recycle back on screen pipeupdate lea pipes,a0 moveq.w #NUMPIPES-1,d2 .loop move.w PIPE_X(a0),d0 IFGT ENABLEPIPESCROLL subq.w #1,d0 ;Scroll pipe left a pixel ENDC cmp.w #-48,d0 ;Moved left off-screen? ble.s .wrappipe ;Yes, wrap back on right hand side  move.w d0,PIPE_X(a0) cmp.w #PIPEXSCORE,d0 ;Have passed through pipe? bne.s .continue move.l a0,-(sp) ;Yes, increment score by 1 and play sound lea bcdscore,a0 bsr gamescoreinc lea pointsfx,a0 bsr soundplay1 move.l (sp)+,a0 .continue lea PIPE_SIZE(a0),a0 dbra.w d2,.loop rts .wrappipe add.w #NUMPIPES*PIPEXGAP,d0 ;Move pipe to end move.w d0,PIPE_X(a0) bsr piperandomoffset ;Random new pipe Y position bsr pipeset bra.s .continue ;---------------------------------- ;Check if bird collides with any pipe, returns d0.w as 1 if hit pipe or 2 if hit floor (on first collision), otherwise 0 pipecheckcollision move.w birdx,d0 ;Read bird position move.w birdy,d1 cmp.w #160-13,d1 ;Always check floor collision bge.s .hitfloor IFGT ENABLECOLLISION move.w birdhit,d2 ;Is player alive? bne.s .done ;No, skip collision checks lea pipes,a0 moveq.w #NUMPIPES-1,d3 .loop ;Check if bird collision box is outside pipe on X axis move.w PIPE_X(a0),d2 ;Screen X of left edge of pipe sub.w #20,d2 ;Offset for right of bird collision box cmp.w d0,d2 bge.s .nocollision add.w #35,d2 ;Offset for left of bird collision box cmp.w d0,d2 ble.s .nocollision ;Check if bird collision box is within pipe on Y move.w PIPE_Y(a0),d2 ;Screen Y of last line on top pipe sub.w #4,d2 ;Offset for top of bird collision box cmp.w d1,d2 bge.s .hitpipe .notopcol add.w #40,d2 ;Bottom of collision box cmp.w d1,d2 ble.s .hitpipe .nobottomcol .nocollision lea PIPE_SIZE(a0),a0 dbra.w d3,.loop .done ENDC moveq.w #0,d0 ;Return no collision rts .hitfloor move.w #160-13,birdy ;Put on floor moveq.w #2,d0 ;Return floor collision move.w d0,birdhit ;Set as collision rts .hitpipe moveq.w #1,d0 ;Return pipe collision move.w d0,birdhit rts ;---------------------------------- ;Draw all pipes to screen pipedrawall lea pipes,a0 moveq.w #NUMPIPES-1,d0 .loop move.w d0,-(sp) move.l a0,-(sp) bsr pipedraw move.l (sp)+,a0 move.w (sp)+,d0 lea PIPE_SIZE(a0),a0 dbra.w d0,.loop rts ;---------------------------------- ;Draw pipe, pass a0.l as pipe structure pipedraw move.w PIPE_X(a0),d0 cmp.w #-32,d0 ;Culled left? ble.s .offscreen cmp.w #-16,d0 ;Clipped left? blt pipedrawtopclip1 cmp.w #0,d0 blt pipedrawtopclip2 cmp.w #320,d0 ;Culled right? bge.s .offscreen cmp.w #304,d0 ;Clipped right? bge pipedrawtopclip4 cmp.w #288,d0 bge pipedrawtopclip3 bra pipedrawtop ;Fully on-screen .offscreen rts ;---------------------------------- ;Draw top pipe, with cap pipedrawtop ;1712-5912 cycles, 3-12 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 move.w d0,d1 ;4 ;Add X screen offset lsr.w #1,d1 ;8 and.w #$fff8,d1 ;8 add.w d1,a1 ;8 sub.w PIPE_LINEOFFSET(a0),a1 ;16 ;Offset Y lea pipetopscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l (a2)+,d0-d5 ;60 ;Read Planes 1+2+3+4 for pipe column move.l PIPE_FUNCTOP(a0),a6 ;16 jmp (a6) ;8 a0 movem.l d0-d5,160*10(a1) ;60 ;Draw pipe column, up to 4680 cycles a1 movem.l d0-d5,160*11(a1) a2 movem.l d0-d5,160*12(a1) a3 movem.l d0-d5,160*13(a1) a4 movem.l d0-d5,160*14(a1) a5 movem.l d0-d5,160*15(a1) a6 movem.l d0-d5,160*16(a1) a7 movem.l d0-d5,160*17(a1) a8 movem.l d0-d5,160*18(a1) a9 movem.l d0-d5,160*19(a1) a10 movem.l d0-d5,160*20(a1) a11 movem.l d0-d5,160*21(a1) a12 movem.l d0-d5,160*22(a1) a13 movem.l d0-d5,160*23(a1) a14 movem.l d0-d5,160*24(a1) a15 movem.l d0-d5,160*25(a1) a16 movem.l d0-d5,160*26(a1) a17 movem.l d0-d5,160*27(a1) a18 movem.l d0-d5,160*28(a1) a19 movem.l d0-d5,160*29(a1) a20 movem.l d0-d5,160*30(a1) a21 movem.l d0-d5,160*31(a1) a22 movem.l d0-d5,160*32(a1) a23 movem.l d0-d5,160*33(a1) a24 movem.l d0-d5,160*34(a1) a25 movem.l d0-d5,160*35(a1) a26 movem.l d0-d5,160*36(a1) a27 movem.l d0-d5,160*37(a1) a28 movem.l d0-d5,160*38(a1) a29 movem.l d0-d5,160*39(a1) a30 movem.l d0-d5,160*40(a1) a31 movem.l d0-d5,160*41(a1) a32 movem.l d0-d5,160*42(a1) a33 movem.l d0-d5,160*43(a1) a34 movem.l d0-d5,160*44(a1) a35 movem.l d0-d5,160*45(a1) a36 movem.l d0-d5,160*46(a1) a37 movem.l d0-d5,160*47(a1) a38 movem.l d0-d5,160*48(a1) a39 movem.l d0-d5,160*49(a1) a40 movem.l d0-d5,160*50(a1) a41 movem.l d0-d5,160*51(a1) a42 movem.l d0-d5,160*52(a1) a43 movem.l d0-d5,160*53(a1) a44 movem.l d0-d5,160*54(a1) a45 movem.l d0-d5,160*55(a1) a46 movem.l d0-d5,160*56(a1) a47 movem.l d0-d5,160*57(a1) a48 movem.l d0-d5,160*58(a1) a49 movem.l d0-d5,160*59(a1) a50 movem.l d0-d5,160*60(a1) a51 movem.l d0-d5,160*61(a1) a52 movem.l d0-d5,160*62(a1) a53 movem.l d0-d5,160*63(a1) a54 movem.l d0-d5,160*64(a1) a55 movem.l d0-d5,160*65(a1) a56 movem.l d0-d5,160*66(a1) a57 movem.l d0-d5,160*67(a1) a58 movem.l d0-d5,160*68(a1) a59 movem.l d0-d5,160*69(a1) a60 movem.l d0-d5,160*70(a1) a61 movem.l d0-d5,160*71(a1) a62 movem.l d0-d5,160*72(a1) a63 movem.l d0-d5,160*73(a1) a64 movem.l d0-d5,160*74(a1) a65 movem.l d0-d5,160*75(a1) a66 movem.l d0-d5,160*76(a1) a67 movem.l d0-d5,160*77(a1) a68 movem.l d0-d5,160*78(a1) a69 movem.l d0-d5,160*79(a1) a70 movem.l d0-d5,160*80(a1) movem.l d0-d5,160*81(a1) movem.l d0-d5,160*82(a1) movem.l d0-d5,160*83(a1) movem.l d0-d5,160*84(a1) movem.l d0-d5,160*85(a1) movem.l d0-d5,160*86(a1) movem.l d0-d5,160*87(a1) movem.l (a2)+,d0-d5 ;60 ;Draw pipe cap, 1020 cycles movem.l d0-d5,160*88(a1) ;60 movem.l (a2)+,d0-d5 movem.l d0-d5,160*89(a1) movem.l (a2)+,d0-d5 movem.l d0-d5,160*90(a1) movem.l d0-d5,160*91(a1) movem.l d0-d5,160*92(a1) movem.l d0-d5,160*93(a1) movem.l d0-d5,160*94(a1) movem.l d0-d5,160*95(a1) movem.l d0-d5,160*96(a1) movem.l d0-d5,160*97(a1) movem.l (a2)+,d0-d5 movem.l d0-d5,160*98(a1) movem.l (a2),d0-d5 movem.l d0-d5,160*99(a1) bra pipedrawbottom ;---------------------------------- ;Draw top pipe, with cap, clipped for X of -32...-16 pipedrawtopclip1 ;900-2860 cycles, 2-6 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 sub.w PIPE_LINEOFFSET(a0),a1 ;16 ;Offset Y lea pipetopscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;16 moveq.w #16,d6 ;4 ;Offset for source add.w d6,a2 ;8 movem.l (a2)+,d4-d5 ;28 ;Read Planes 1+2+3+4 for pipe column move.l PIPE_FUNCTOP1(a0),a6 ;16 jmp (a6) ;8 b0 movem.l d4-d5,160*10(a1) ;28 ;Draw pipe column, 2184 cycles b1 movem.l d4-d5,160*11(a1) b2 movem.l d4-d5,160*12(a1) b3 movem.l d4-d5,160*13(a1) b4 movem.l d4-d5,160*14(a1) b5 movem.l d4-d5,160*15(a1) b6 movem.l d4-d5,160*16(a1) b7 movem.l d4-d5,160*17(a1) b8 movem.l d4-d5,160*18(a1) b9 movem.l d4-d5,160*19(a1) b10 movem.l d4-d5,160*20(a1) b11 movem.l d4-d5,160*21(a1) b12 movem.l d4-d5,160*22(a1) b13 movem.l d4-d5,160*23(a1) b14 movem.l d4-d5,160*24(a1) b15 movem.l d4-d5,160*25(a1) b16 movem.l d4-d5,160*26(a1) b17 movem.l d4-d5,160*27(a1) b18 movem.l d4-d5,160*28(a1) b19 movem.l d4-d5,160*29(a1) b20 movem.l d4-d5,160*30(a1) b21 movem.l d4-d5,160*31(a1) b22 movem.l d4-d5,160*32(a1) b23 movem.l d4-d5,160*33(a1) b24 movem.l d4-d5,160*34(a1) b25 movem.l d4-d5,160*35(a1) b26 movem.l d4-d5,160*36(a1) b27 movem.l d4-d5,160*37(a1) b28 movem.l d4-d5,160*38(a1) b29 movem.l d4-d5,160*39(a1) b30 movem.l d4-d5,160*40(a1) b31 movem.l d4-d5,160*41(a1) b32 movem.l d4-d5,160*42(a1) b33 movem.l d4-d5,160*43(a1) b34 movem.l d4-d5,160*44(a1) b35 movem.l d4-d5,160*45(a1) b36 movem.l d4-d5,160*46(a1) b37 movem.l d4-d5,160*47(a1) b38 movem.l d4-d5,160*48(a1) b39 movem.l d4-d5,160*49(a1) b40 movem.l d4-d5,160*50(a1) b41 movem.l d4-d5,160*51(a1) b42 movem.l d4-d5,160*52(a1) b43 movem.l d4-d5,160*53(a1) b44 movem.l d4-d5,160*54(a1) b45 movem.l d4-d5,160*55(a1) b46 movem.l d4-d5,160*56(a1) b47 movem.l d4-d5,160*57(a1) b48 movem.l d4-d5,160*58(a1) b49 movem.l d4-d5,160*59(a1) b50 movem.l d4-d5,160*60(a1) b51 movem.l d4-d5,160*61(a1) b52 movem.l d4-d5,160*62(a1) b53 movem.l d4-d5,160*63(a1) b54 movem.l d4-d5,160*64(a1) b55 movem.l d4-d5,160*65(a1) b56 movem.l d4-d5,160*66(a1) b57 movem.l d4-d5,160*67(a1) b58 movem.l d4-d5,160*68(a1) b59 movem.l d4-d5,160*69(a1) b60 movem.l d4-d5,160*70(a1) b61 movem.l d4-d5,160*71(a1) b62 movem.l d4-d5,160*72(a1) b63 movem.l d4-d5,160*73(a1) b64 movem.l d4-d5,160*74(a1) b65 movem.l d4-d5,160*75(a1) b66 movem.l d4-d5,160*76(a1) b67 movem.l d4-d5,160*77(a1) b68 movem.l d4-d5,160*78(a1) b69 movem.l d4-d5,160*79(a1) b70 movem.l d4-d5,160*80(a1) movem.l d4-d5,160*81(a1) movem.l d4-d5,160*82(a1) movem.l d4-d5,160*83(a1) movem.l d4-d5,160*84(a1) movem.l d4-d5,160*85(a1) movem.l d4-d5,160*86(a1) movem.l d4-d5,160*87(a1) add.w d6,a2 ;8 ;Draw pipe cap, 516 cycles movem.l (a2)+,d4-d5 ;28 movem.l d4-d5,160*88(a1) ;28 add.w d6,a2 movem.l (a2)+,d4-d5 movem.l d4-d5,160*89(a1) add.w d6,a2 movem.l (a2)+,d4-d5 movem.l d4-d5,160*90(a1) movem.l d4-d5,160*91(a1) movem.l d4-d5,160*92(a1) movem.l d4-d5,160*93(a1) movem.l d4-d5,160*94(a1) movem.l d4-d5,160*95(a1) movem.l d4-d5,160*96(a1) movem.l d4-d5,160*97(a1) add.w d6,a2 movem.l (a2)+,d4-d5 movem.l d4-d5,160*98(a1) add.w d6,a2 movem.l (a2),d4-d5 movem.l d4-d5,160*99(a1) bra pipedrawbottomclip1 ;---------------------------------- ;Draw top pipe, with cap, clipped for X of -16...0 pipedrawtopclip2 ;1316-4396 cycles, 3-9 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 sub.w PIPE_LINEOFFSET(a0),a1 ;16 ;Offset Y lea pipetopscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;16 moveq.w #8,d6 ;4 ;Offset for source add.w d6,a2 ;8 movem.l (a2)+,d2-d5 ;44 ;Read Planes 1+2+3+4 for pipe column move.l PIPE_FUNCTOP2(a0),a6 ;16 jmp (a6) ;8 c0 movem.l d2-d5,160*10(a1) ;44 ;Draw pipe column, 3432 cycles c1 movem.l d2-d5,160*11(a1) c2 movem.l d2-d5,160*12(a1) c3 movem.l d2-d5,160*13(a1) c4 movem.l d2-d5,160*14(a1) c5 movem.l d2-d5,160*15(a1) c6 movem.l d2-d5,160*16(a1) c7 movem.l d2-d5,160*17(a1) c8 movem.l d2-d5,160*18(a1) c9 movem.l d2-d5,160*19(a1) c10 movem.l d2-d5,160*20(a1) c11 movem.l d2-d5,160*21(a1) c12 movem.l d2-d5,160*22(a1) c13 movem.l d2-d5,160*23(a1) c14 movem.l d2-d5,160*24(a1) c15 movem.l d2-d5,160*25(a1) c16 movem.l d2-d5,160*26(a1) c17 movem.l d2-d5,160*27(a1) c18 movem.l d2-d5,160*28(a1) c19 movem.l d2-d5,160*29(a1) c20 movem.l d2-d5,160*30(a1) c21 movem.l d2-d5,160*31(a1) c22 movem.l d2-d5,160*32(a1) c23 movem.l d2-d5,160*33(a1) c24 movem.l d2-d5,160*34(a1) c25 movem.l d2-d5,160*35(a1) c26 movem.l d2-d5,160*36(a1) c27 movem.l d2-d5,160*37(a1) c28 movem.l d2-d5,160*38(a1) c29 movem.l d2-d5,160*39(a1) c30 movem.l d2-d5,160*40(a1) c31 movem.l d2-d5,160*41(a1) c32 movem.l d2-d5,160*42(a1) c33 movem.l d2-d5,160*43(a1) c34 movem.l d2-d5,160*44(a1) c35 movem.l d2-d5,160*45(a1) c36 movem.l d2-d5,160*46(a1) c37 movem.l d2-d5,160*47(a1) c38 movem.l d2-d5,160*48(a1) c39 movem.l d2-d5,160*49(a1) c40 movem.l d2-d5,160*50(a1) c41 movem.l d2-d5,160*51(a1) c42 movem.l d2-d5,160*52(a1) c43 movem.l d2-d5,160*53(a1) c44 movem.l d2-d5,160*54(a1) c45 movem.l d2-d5,160*55(a1) c46 movem.l d2-d5,160*56(a1) c47 movem.l d2-d5,160*57(a1) c48 movem.l d2-d5,160*58(a1) c49 movem.l d2-d5,160*59(a1) c50 movem.l d2-d5,160*60(a1) c51 movem.l d2-d5,160*61(a1) c52 movem.l d2-d5,160*62(a1) c53 movem.l d2-d5,160*63(a1) c54 movem.l d2-d5,160*64(a1) c55 movem.l d2-d5,160*65(a1) c56 movem.l d2-d5,160*66(a1) c57 movem.l d2-d5,160*67(a1) c58 movem.l d2-d5,160*68(a1) c59 movem.l d2-d5,160*69(a1) c60 movem.l d2-d5,160*70(a1) c61 movem.l d2-d5,160*71(a1) c62 movem.l d2-d5,160*72(a1) c63 movem.l d2-d5,160*73(a1) c64 movem.l d2-d5,160*74(a1) c65 movem.l d2-d5,160*75(a1) c66 movem.l d2-d5,160*76(a1) c67 movem.l d2-d5,160*77(a1) c68 movem.l d2-d5,160*78(a1) c69 movem.l d2-d5,160*79(a1) c70 movem.l d2-d5,160*80(a1) movem.l d2-d5,160*81(a1) movem.l d2-d5,160*82(a1) movem.l d2-d5,160*83(a1) movem.l d2-d5,160*84(a1) movem.l d2-d5,160*85(a1) movem.l d2-d5,160*86(a1) movem.l d2-d5,160*87(a1) add.w d6,a2 ;8 ;Draw pipe cap, 788 cycles movem.l (a2)+,d2-d5 ;44 movem.l d2-d5,160*88(a1) ;44 add.w d6,a2 movem.l (a2)+,d2-d5 movem.l d2-d5,160*89(a1) add.w d6,a2 movem.l (a2)+,d2-d5 movem.l d2-d5,160*90(a1) movem.l d2-d5,160*91(a1) movem.l d2-d5,160*92(a1) movem.l d2-d5,160*93(a1) movem.l d2-d5,160*94(a1) movem.l d2-d5,160*95(a1) movem.l d2-d5,160*96(a1) movem.l d2-d5,160*97(a1) add.w d6,a2 movem.l (a2)+,d2-d5 movem.l d2-d5,160*98(a1) add.w d6,a2 movem.l (a2),d2-d5 movem.l d2-d5,160*99(a1) bra pipedrawbottomclip2 ;---------------------------------- ;Draw top pipe, with cap, clipped for X of 288...304 pipedrawtopclip3 ;1316-4396 cycles, 3-9 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-16(a1),a1 ;8 ;Add X screen offset sub.w PIPE_LINEOFFSET(a0),a1 ;16 ;Offset Y lea pipetopscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;16 moveq.w #8,d6 ;4 ;Offset for source movem.l (a2)+,d0-d3 ;44 ;Read Planes 1+2+3+4 for pipe column add.w d6,a2 ;8 move.l PIPE_FUNCTOP3(a0),a6 ;16 jmp (a6) ;8 d0 movem.l d0-d3,160*10(a1) ;44 ;Draw pipe column, 3432 cycles d1 movem.l d0-d3,160*11(a1) d2 movem.l d0-d3,160*12(a1) d3 movem.l d0-d3,160*13(a1) d4 movem.l d0-d3,160*14(a1) d5 movem.l d0-d3,160*15(a1) d6 movem.l d0-d3,160*16(a1) d7 movem.l d0-d3,160*17(a1) d8 movem.l d0-d3,160*18(a1) d9 movem.l d0-d3,160*19(a1) d10 movem.l d0-d3,160*20(a1) d11 movem.l d0-d3,160*21(a1) d12 movem.l d0-d3,160*22(a1) d13 movem.l d0-d3,160*23(a1) d14 movem.l d0-d3,160*24(a1) d15 movem.l d0-d3,160*25(a1) d16 movem.l d0-d3,160*26(a1) d17 movem.l d0-d3,160*27(a1) d18 movem.l d0-d3,160*28(a1) d19 movem.l d0-d3,160*29(a1) d20 movem.l d0-d3,160*30(a1) d21 movem.l d0-d3,160*31(a1) d22 movem.l d0-d3,160*32(a1) d23 movem.l d0-d3,160*33(a1) d24 movem.l d0-d3,160*34(a1) d25 movem.l d0-d3,160*35(a1) d26 movem.l d0-d3,160*36(a1) d27 movem.l d0-d3,160*37(a1) d28 movem.l d0-d3,160*38(a1) d29 movem.l d0-d3,160*39(a1) d30 movem.l d0-d3,160*40(a1) d31 movem.l d0-d3,160*41(a1) d32 movem.l d0-d3,160*42(a1) d33 movem.l d0-d3,160*43(a1) d34 movem.l d0-d3,160*44(a1) d35 movem.l d0-d3,160*45(a1) d36 movem.l d0-d3,160*46(a1) d37 movem.l d0-d3,160*47(a1) d38 movem.l d0-d3,160*48(a1) d39 movem.l d0-d3,160*49(a1) d40 movem.l d0-d3,160*50(a1) d41 movem.l d0-d3,160*51(a1) d42 movem.l d0-d3,160*52(a1) d43 movem.l d0-d3,160*53(a1) d44 movem.l d0-d3,160*54(a1) d45 movem.l d0-d3,160*55(a1) d46 movem.l d0-d3,160*56(a1) d47 movem.l d0-d3,160*57(a1) d48 movem.l d0-d3,160*58(a1) d49 movem.l d0-d3,160*59(a1) d50 movem.l d0-d3,160*60(a1) d51 movem.l d0-d3,160*61(a1) d52 movem.l d0-d3,160*62(a1) d53 movem.l d0-d3,160*63(a1) d54 movem.l d0-d3,160*64(a1) d55 movem.l d0-d3,160*65(a1) d56 movem.l d0-d3,160*66(a1) d57 movem.l d0-d3,160*67(a1) d58 movem.l d0-d3,160*68(a1) d59 movem.l d0-d3,160*69(a1) d60 movem.l d0-d3,160*70(a1) d61 movem.l d0-d3,160*71(a1) d62 movem.l d0-d3,160*72(a1) d63 movem.l d0-d3,160*73(a1) d64 movem.l d0-d3,160*74(a1) d65 movem.l d0-d3,160*75(a1) d66 movem.l d0-d3,160*76(a1) d67 movem.l d0-d3,160*77(a1) d68 movem.l d0-d3,160*78(a1) d69 movem.l d0-d3,160*79(a1) d70 movem.l d0-d3,160*80(a1) movem.l d0-d3,160*81(a1) movem.l d0-d3,160*82(a1) movem.l d0-d3,160*83(a1) movem.l d0-d3,160*84(a1) movem.l d0-d3,160*85(a1) movem.l d0-d3,160*86(a1) movem.l d0-d3,160*87(a1) movem.l (a2)+,d0-d3 ;44 ;Draw pipe cap, 780 cycles add.w d6,a2 ;8 movem.l d0-d3,160*88(a1) ;44 movem.l (a2)+,d0-d3 add.w d6,a2 movem.l d0-d3,160*89(a1) movem.l (a2)+,d0-d3 add.w d6,a2 movem.l d0-d3,160*90(a1) movem.l d0-d3,160*91(a1) movem.l d0-d3,160*92(a1) movem.l d0-d3,160*93(a1) movem.l d0-d3,160*94(a1) movem.l d0-d3,160*95(a1) movem.l d0-d3,160*96(a1) movem.l d0-d3,160*97(a1) movem.l (a2)+,d0-d3 add.w d6,a2 movem.l d0-d3,160*98(a1) movem.l (a2),d0-d3 movem.l d0-d3,160*99(a1) bra pipedrawbottomclip3 ;---------------------------------- ;Draw top pipe, with cap, clipped for X of 304...320 pipedrawtopclip4 ;900-2860 cycles, 2-6 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-8(a1),a1 ;8 ;Add X screen offset sub.w PIPE_LINEOFFSET(a0),a1 ;16 ;Offset Y lea pipetopscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;16 moveq.w #16,d6 ;4 ;Offset for source movem.l (a2)+,d0-d1 ;28 ;Read Planes 1+2+3+4 for pipe column add.w d6,a2 ;8 move.l PIPE_FUNCTOP4(a0),a6 ;16 jmp (a6) ;8 e0 movem.l d0-d1,160*10(a1) ;28 ;Draw pipe column, 2184 cycles e1 movem.l d0-d1,160*11(a1) e2 movem.l d0-d1,160*12(a1) e3 movem.l d0-d1,160*13(a1) e4 movem.l d0-d1,160*14(a1) e5 movem.l d0-d1,160*15(a1) e6 movem.l d0-d1,160*16(a1) e7 movem.l d0-d1,160*17(a1) e8 movem.l d0-d1,160*18(a1) e9 movem.l d0-d1,160*19(a1) e10 movem.l d0-d1,160*20(a1) e11 movem.l d0-d1,160*21(a1) e12 movem.l d0-d1,160*22(a1) e13 movem.l d0-d1,160*23(a1) e14 movem.l d0-d1,160*24(a1) e15 movem.l d0-d1,160*25(a1) e16 movem.l d0-d1,160*26(a1) e17 movem.l d0-d1,160*27(a1) e18 movem.l d0-d1,160*28(a1) e19 movem.l d0-d1,160*29(a1) e20 movem.l d0-d1,160*30(a1) e21 movem.l d0-d1,160*31(a1) e22 movem.l d0-d1,160*32(a1) e23 movem.l d0-d1,160*33(a1) e24 movem.l d0-d1,160*34(a1) e25 movem.l d0-d1,160*35(a1) e26 movem.l d0-d1,160*36(a1) e27 movem.l d0-d1,160*37(a1) e28 movem.l d0-d1,160*38(a1) e29 movem.l d0-d1,160*39(a1) e30 movem.l d0-d1,160*40(a1) e31 movem.l d0-d1,160*41(a1) e32 movem.l d0-d1,160*42(a1) e33 movem.l d0-d1,160*43(a1) e34 movem.l d0-d1,160*44(a1) e35 movem.l d0-d1,160*45(a1) e36 movem.l d0-d1,160*46(a1) e37 movem.l d0-d1,160*47(a1) e38 movem.l d0-d1,160*48(a1) e39 movem.l d0-d1,160*49(a1) e40 movem.l d0-d1,160*50(a1) e41 movem.l d0-d1,160*51(a1) e42 movem.l d0-d1,160*52(a1) e43 movem.l d0-d1,160*53(a1) e44 movem.l d0-d1,160*54(a1) e45 movem.l d0-d1,160*55(a1) e46 movem.l d0-d1,160*56(a1) e47 movem.l d0-d1,160*57(a1) e48 movem.l d0-d1,160*58(a1) e49 movem.l d0-d1,160*59(a1) e50 movem.l d0-d1,160*60(a1) e51 movem.l d0-d1,160*61(a1) e52 movem.l d0-d1,160*62(a1) e53 movem.l d0-d1,160*63(a1) e54 movem.l d0-d1,160*64(a1) e55 movem.l d0-d1,160*65(a1) e56 movem.l d0-d1,160*66(a1) e57 movem.l d0-d1,160*67(a1) e58 movem.l d0-d1,160*68(a1) e59 movem.l d0-d1,160*69(a1) e60 movem.l d0-d1,160*70(a1) e61 movem.l d0-d1,160*71(a1) e62 movem.l d0-d1,160*72(a1) e63 movem.l d0-d1,160*73(a1) e64 movem.l d0-d1,160*74(a1) e65 movem.l d0-d1,160*75(a1) e66 movem.l d0-d1,160*76(a1) e67 movem.l d0-d1,160*77(a1) e68 movem.l d0-d1,160*78(a1) e69 movem.l d0-d1,160*79(a1) e70 movem.l d0-d1,160*80(a1) movem.l d0-d1,160*81(a1) movem.l d0-d1,160*82(a1) movem.l d0-d1,160*83(a1) movem.l d0-d1,160*84(a1) movem.l d0-d1,160*85(a1) movem.l d0-d1,160*86(a1) movem.l d0-d1,160*87(a1) movem.l (a2)+,d0-d1 ;28 ;Draw pipe cap, 508 cycles add.w d6,a2 ;8 movem.l d0-d1,160*88(a1) ;28 movem.l (a2)+,d0-d1 add.w d6,a2 movem.l d0-d1,160*89(a1) movem.l (a2)+,d0-d1 add.w d6,a2 movem.l d0-d1,160*90(a1) movem.l d0-d1,160*91(a1) movem.l d0-d1,160*92(a1) movem.l d0-d1,160*93(a1) movem.l d0-d1,160*94(a1) movem.l d0-d1,160*95(a1) movem.l d0-d1,160*96(a1) movem.l d0-d1,160*97(a1) movem.l (a2)+,d0-d1 add.w d6,a2 movem.l d0-d1,160*98(a1) movem.l (a2),d0-d1 movem.l d0-d1,160*99(a1) bra pipedrawbottomclip4 ;---------------------------------- ;Draw bottom pipe pipedrawbottom ;996-7476 cycles, 2-15 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 move.w d0,d1 ;4 ;Add X screen offset lsr.w #1,d1 ;8 and.w #$fff8,d1 ;8 add.w d1,a1 ;8 lea pipeskyscrolltbl,a6 ;12 ;Get preshifts for X position and.w #127,d0 ;8 lsl.w #3,d0 ;12 add.w d0,a6 ;8 lea pipetoppreshift,a2 ;12 add.w (a6)+,a2 ;12 lea pipesky1preshift,a3 ;12 moveq.l #0,d0 ;4 ;Offset for sky1 is unsigned move.w (a6)+,d0 ;8 add.l d0,a3 ;8 add.w PIPE_SKY1OFFSET(a0),a3 ;16 lea pipesky2preshift,a4 ;12 add.w (a6)+,a4 ;12 add.w PIPE_SKY2OFFSET(a0),a4 ;16 lea pipesky3preshift,a5 ;12 add.w (a6),a5 ;12 add.w PIPE_SKY3OFFSET(a0),a5 ;16 movem.l (a2),d0-d5 ;60 ;Read Planes 1+2+3+4 for pipe column movem.l d0-d5,160*151(a1) ;60 ;Draw very bottom of pipe first, 540 cycles movem.l d0-d5,160*152(a1) movem.l d0-d5,160*153(a1) movem.l d0-d5,160*154(a1) movem.l d0-d5,160*155(a1) movem.l d0-d5,160*156(a1) movem.l d0-d5,160*157(a1) movem.l d0-d5,160*158(a1) movem.l d0-d5,160*159(a1) move.l PIPE_FUNCBOTTOM(a0),a6 ;16 jmp (a6) ;8 f0 movem.l d0-d5,160*80(a1) ;60 ;Draw pipe column, 1920 cycles f1 movem.l d0-d5,160*81(a1) f2 movem.l d0-d5,160*82(a1) f3 movem.l d0-d5,160*83(a1) f4 movem.l d0-d5,160*84(a1) f5 movem.l d0-d5,160*85(a1) f6 movem.l d0-d5,160*86(a1) f7 movem.l d0-d5,160*87(a1) f8 movem.l d0-d5,160*88(a1) f9 movem.l d0-d5,160*89(a1) f10 movem.l d0-d5,160*90(a1) f11 movem.l d0-d5,160*91(a1) f12 movem.l d0-d5,160*92(a1) f13 movem.l d0-d5,160*93(a1) f14 movem.l d0-d5,160*94(a1) f15 movem.l d0-d5,160*95(a1) f16 movem.l d0-d5,160*96(a1) f17 movem.l d0-d5,160*97(a1) f18 movem.l d0-d5,160*98(a1) f19 movem.l d0-d5,160*99(a1) f20 movem.l d0-d5,160*100(a1) f21 movem.l d0-d5,160*101(a1) f22 movem.l d0-d5,160*102(a1) f23 movem.l d0-d5,160*103(a1) f24 movem.l d0-d5,160*104(a1) f25 movem.l d0-d5,160*105(a1) f26 movem.l d0-d5,160*106(a1) f27 movem.l d0-d5,160*107(a1) f28 movem.l d0-d5,160*108(a1) f29 movem.l d0-d5,160*109(a1) f30 movem.l d0-d5,160*110(a1) f31 movem.l d0-d5,160*111(a1) f32 movem.l (a3)+,d0-d5 ;60 ;Sky top, 1320 cycles movem.l d0-d5,160*112(a1) ;60 f33 movem.l (a3)+,d0-d5 movem.l d0-d5,160*113(a1) f34 movem.l (a3)+,d0-d5 movem.l d0-d5,160*114(a1) f35 movem.l (a3)+,d0-d5 movem.l d0-d5,160*115(a1) f36 movem.l (a3)+,d0-d5 movem.l d0-d5,160*116(a1) f37 movem.l (a3)+,d0-d5 movem.l d0-d5,160*117(a1) f38 movem.l (a3)+,d0-d5 movem.l d0-d5,160*118(a1) f39 movem.l (a3)+,d0-d5 movem.l d0-d5,160*119(a1) f40 movem.l (a3)+,d0-d5 movem.l d0-d5,160*120(a1) f41 movem.l (a3)+,d0-d5 movem.l d0-d5,160*121(a1) f42 movem.l (a3),d0-d5 movem.l d0-d5,160*122(a1) f43 movem.l (a4)+,d0-d5 ;60 ;Buildings, 2280 cycles movem.l d0-d5,160*123(a1) ;60 f44 movem.l (a4)+,d0-d5 movem.l d0-d5,160*124(a1) f45 movem.l (a4)+,d0-d5 movem.l d0-d5,160*125(a1) f46 movem.l (a4)+,d0-d5 movem.l d0-d5,160*126(a1) f47 movem.l (a4)+,d0-d5 movem.l d0-d5,160*127(a1) f48 movem.l (a4)+,d0-d5 movem.l d0-d5,160*128(a1) f49 movem.l (a4)+,d0-d5 movem.l d0-d5,160*129(a1) f50 movem.l (a4)+,d0-d5 movem.l d0-d5,160*130(a1) f51 movem.l (a4)+,d0-d5 movem.l d0-d5,160*131(a1) f52 movem.l (a4)+,d0-d5 movem.l d0-d5,160*132(a1) f53 movem.l (a4)+,d0-d5 movem.l d0-d5,160*133(a1) f54 movem.l (a4)+,d0-d5 movem.l d0-d5,160*134(a1) f55 movem.l (a4)+,d0-d5 movem.l d0-d5,160*135(a1) f56 movem.l (a4)+,d0-d5 movem.l d0-d5,160*136(a1) f57 movem.l (a4)+,d0-d5 movem.l d0-d5,160*137(a1) f58 movem.l (a4)+,d0-d5 movem.l d0-d5,160*138(a1) f59 movem.l (a4)+,d0-d5 movem.l d0-d5,160*139(a1) f60 movem.l (a4)+,d0-d5 movem.l d0-d5,160*140(a1) f61 movem.l (a4),d0-d5 movem.l d0-d5,160*141(a1) f62 movem.l (a5)+,d0-d5 ;60 ;Grass, 1080 cycles movem.l d0-d5,160*142(a1) ;60 f63 movem.l (a5)+,d0-d5 movem.l d0-d5,160*143(a1) f64 movem.l (a5)+,d0-d5 movem.l d0-d5,160*144(a1) f65 movem.l (a5)+,d0-d5 movem.l d0-d5,160*145(a1) f66 movem.l (a5)+,d0-d5 movem.l d0-d5,160*146(a1) f67 movem.l (a5)+,d0-d5 movem.l d0-d5,160*147(a1) f68 movem.l (a5)+,d0-d5 movem.l d0-d5,160*148(a1) f69 movem.l (a5)+,d0-d5 movem.l d0-d5,160*149(a1) f70 movem.l (a5),d0-d5 movem.l d0-d5,160*150(a1) bra pipedrawbottomcap ;---------------------------------- ;Draw bottom pipe clipped for X of -32...-16 pipedrawbottomclip1 ;604-3932 cycles, 1-8 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea pipeskyscrolltbl,a6 ;12 ;Get preshifts for X position and.w #127,d0 ;8 lsl.w #3,d0 ;12 add.w d0,a6 ;8 lea pipetoppreshift,a2 ;12 add.w (a6)+,a2 ;12 lea pipesky1preshift,a3 ;12 moveq.l #0,d0 ;4 ;Offset for sky1 is unsigned move.w (a6)+,d0 ;8 add.l d0,a3 ;8 add.w PIPE_SKY1OFFSET(a0),a3 ;16 lea pipesky2preshift,a4 ;12 add.w (a6)+,a4 ;12 add.w PIPE_SKY2OFFSET(a0),a4 ;16 lea pipesky3preshift,a5 ;12 add.w (a6),a5 ;12 add.w PIPE_SKY3OFFSET(a0),a5 ;16 moveq.w #16,d6 ;4 ;Offset for sky source movem.l (a2,d6.w),d4-d5 ;36 ;Read Planes 1+2+3+4 for pipe column movem.l d4-d5,160*151(a1) ;28 ;Draw very bottom of pipe first, 252 cycles movem.l d4-d5,160*152(a1) movem.l d4-d5,160*153(a1) movem.l d4-d5,160*154(a1) movem.l d4-d5,160*155(a1) movem.l d4-d5,160*156(a1) movem.l d4-d5,160*157(a1) movem.l d4-d5,160*158(a1) movem.l d4-d5,160*159(a1) move.l PIPE_FUNCBOTTOM1(a0),a6 ;16 jmp (a6) ;8 g0 movem.l d4-d5,160*80(a1) ;28 ;Draw pipe column, 896 cycles g1 movem.l d4-d5,160*81(a1) g2 movem.l d4-d5,160*82(a1) g3 movem.l d4-d5,160*83(a1) g4 movem.l d4-d5,160*84(a1) g5 movem.l d4-d5,160*85(a1) g6 movem.l d4-d5,160*86(a1) g7 movem.l d4-d5,160*87(a1) g8 movem.l d4-d5,160*88(a1) g9 movem.l d4-d5,160*89(a1) g10 movem.l d4-d5,160*90(a1) g11 movem.l d4-d5,160*91(a1) g12 movem.l d4-d5,160*92(a1) g13 movem.l d4-d5,160*93(a1) g14 movem.l d4-d5,160*94(a1) g15 movem.l d4-d5,160*95(a1) g16 movem.l d4-d5,160*96(a1) g17 movem.l d4-d5,160*97(a1) g18 movem.l d4-d5,160*98(a1) g19 movem.l d4-d5,160*99(a1) g20 movem.l d4-d5,160*100(a1) g21 movem.l d4-d5,160*101(a1) g22 movem.l d4-d5,160*102(a1) g23 movem.l d4-d5,160*103(a1) g24 movem.l d4-d5,160*104(a1) g25 movem.l d4-d5,160*105(a1) g26 movem.l d4-d5,160*106(a1) g27 movem.l d4-d5,160*107(a1) g28 movem.l d4-d5,160*108(a1) g29 movem.l d4-d5,160*109(a1) g30 movem.l d4-d5,160*110(a1) g31 movem.l d4-d5,160*111(a1) g32 add.w d6,a3 ;8 ;Sky top, 704 cycles movem.l (a3)+,d4-d5 ;28 movem.l d4-d5,160*112(a1) ;28 g33 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*113(a1) g34 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*114(a1) g35 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*115(a1) g36 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*116(a1) g37 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*117(a1) g38 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*118(a1) g39 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*119(a1) g40 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*120(a1) g41 add.w d6,a3 movem.l (a3)+,d4-d5 movem.l d4-d5,160*121(a1) g42 add.w d6,a3 movem.l (a3),d4-d5 movem.l d4-d5,160*122(a1) g43 add.w d6,a4 ;8 ;Buildings, 1216 cycles movem.l (a4)+,d4-d5 ;28 movem.l d4-d5,160*123(a1) ;28 g44 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*124(a1) g45 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*125(a1) g46 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*126(a1) g47 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*127(a1) g48 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*128(a1) g49 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*129(a1) g50 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*130(a1) g51 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*131(a1) g52 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*132(a1) g53 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*133(a1) g54 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*134(a1) g55 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*135(a1) g56 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*136(a1) g57 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*137(a1) g58 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*138(a1) g59 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*139(a1) g60 add.w d6,a4 movem.l (a4)+,d4-d5 movem.l d4-d5,160*140(a1) g61 add.w d6,a4 movem.l (a4),d4-d5 movem.l d4-d5,160*141(a1) g62 add.w d6,a5 ;8 ;Grass, 576 cycles movem.l (a5)+,d4-d5 ;28 movem.l d4-d5,160*142(a1) ;28 g63 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*143(a1) g64 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*144(a1) g65 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*145(a1) g66 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*146(a1) g67 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*147(a1) g68 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*148(a1) g69 add.w d6,a5 movem.l (a5)+,d4-d5 movem.l d4-d5,160*149(a1) g70 add.w d6,a5 movem.l (a5),d4-d5 movem.l d4-d5,160*150(a1) bra pipedrawbottomcapclip1 ;---------------------------------- ;Draw bottom pipe clipped for X of -16...0 pipedrawbottomclip2 ;756-5852 cycles, 2-12 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea pipeskyscrolltbl,a6 ;12 ;Get preshifts for X position and.w #127,d0 ;8 lsl.w #3,d0 ;12 add.w d0,a6 ;8 lea pipetoppreshift,a2 ;12 add.w (a6)+,a2 ;12 lea pipesky1preshift,a3 ;12 moveq.l #0,d0 ;4 ;Offset for sky1 is unsigned move.w (a6)+,d0 ;8 add.l d0,a3 ;8 add.w PIPE_SKY1OFFSET(a0),a3 ;16 lea pipesky2preshift,a4 ;12 add.w (a6)+,a4 ;12 add.w PIPE_SKY2OFFSET(a0),a4 ;16 lea pipesky3preshift,a5 ;12 add.w (a6),a5 ;12 add.w PIPE_SKY3OFFSET(a0),a5 ;16 moveq.w #8,d6 ;4 ;Offset for sky source movem.l (a2,d6.w),d2-d5 ;52 ;Read Planes 1+2+3+4 for pipe column movem.l d2-d5,160*151(a1) ;44 ;Draw very bottom of pipe first, 396 cycles movem.l d2-d5,160*152(a1) movem.l d2-d5,160*153(a1) movem.l d2-d5,160*154(a1) movem.l d2-d5,160*155(a1) movem.l d2-d5,160*156(a1) movem.l d2-d5,160*157(a1) movem.l d2-d5,160*158(a1) movem.l d2-d5,160*159(a1) move.l PIPE_FUNCBOTTOM2(a0),a6 ;16 jmp (a6) ;8 h0 movem.l d2-d5,160*80(a1) ;44 ;Draw pipe column, 1408 cycles h1 movem.l d2-d5,160*81(a1) h2 movem.l d2-d5,160*82(a1) h3 movem.l d2-d5,160*83(a1) h4 movem.l d2-d5,160*84(a1) h5 movem.l d2-d5,160*85(a1) h6 movem.l d2-d5,160*86(a1) h7 movem.l d2-d5,160*87(a1) h8 movem.l d2-d5,160*88(a1) h9 movem.l d2-d5,160*89(a1) h10 movem.l d2-d5,160*90(a1) h11 movem.l d2-d5,160*91(a1) h12 movem.l d2-d5,160*92(a1) h13 movem.l d2-d5,160*93(a1) h14 movem.l d2-d5,160*94(a1) h15 movem.l d2-d5,160*95(a1) h16 movem.l d2-d5,160*96(a1) h17 movem.l d2-d5,160*97(a1) h18 movem.l d2-d5,160*98(a1) h19 movem.l d2-d5,160*99(a1) h20 movem.l d2-d5,160*100(a1) h21 movem.l d2-d5,160*101(a1) h22 movem.l d2-d5,160*102(a1) h23 movem.l d2-d5,160*103(a1) h24 movem.l d2-d5,160*104(a1) h25 movem.l d2-d5,160*105(a1) h26 movem.l d2-d5,160*106(a1) h27 movem.l d2-d5,160*107(a1) h28 movem.l d2-d5,160*108(a1) h29 movem.l d2-d5,160*109(a1) h30 movem.l d2-d5,160*110(a1) h31 movem.l d2-d5,160*111(a1) h32 add.w d6,a3 ;8 ;Sky top, 1056 cycles movem.l (a3)+,d2-d5 ;44 movem.l d2-d5,160*112(a1) ;44 h33 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*113(a1) h34 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*114(a1) h35 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*115(a1) h36 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*116(a1) h37 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*117(a1) h38 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*118(a1) h39 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*119(a1) h40 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*120(a1) h41 add.w d6,a3 movem.l (a3)+,d2-d5 movem.l d2-d5,160*121(a1) h42 add.w d6,a3 movem.l (a3),d2-d5 movem.l d2-d5,160*122(a1) h43 add.w d6,a4 ;8 ;Buildings, 1824 cycles movem.l (a4)+,d2-d5 ;44 movem.l d2-d5,160*123(a1) ;44 h44 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*124(a1) h45 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*125(a1) h46 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*126(a1) h47 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*127(a1) h48 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*128(a1) h49 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*129(a1) h50 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*130(a1) h51 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*131(a1) h52 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*132(a1) h53 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*133(a1) h54 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*134(a1) h55 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*135(a1) h56 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*136(a1) h57 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*137(a1) h58 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*138(a1) h59 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*139(a1) h60 add.w d6,a4 movem.l (a4)+,d2-d5 movem.l d2-d5,160*140(a1) h61 add.w d6,a4 movem.l (a4),d2-d5 movem.l d2-d5,160*141(a1) h62 add.w d6,a5 ;8 ;Grass, 864 cycles movem.l (a5)+,d2-d5 ;44 movem.l d2-d5,160*142(a1) ;44 h63 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*143(a1) h64 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*144(a1) h65 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*145(a1) h66 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*146(a1) h67 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*147(a1) h68 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*148(a1) h69 add.w d6,a5 movem.l (a5)+,d2-d5 movem.l d2-d5,160*149(a1) h70 add.w d6,a5 movem.l (a5),d2-d5 movem.l d2-d5,160*150(a1) bra pipedrawbottomcapclip2 ;---------------------------------- ;Draw bottom pipe clipped for X of 288...304 pipedrawbottomclip3 ;748-5828 cycles, 2-12 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-16(a1),a1 ;8 ;Add X screen offset lea pipeskyscrolltbl,a6 ;12 ;Get preshifts for X position and.w #127,d0 ;8 lsl.w #3,d0 ;12 add.w d0,a6 ;8 lea pipetoppreshift,a2 ;12 add.w (a6)+,a2 ;12 lea pipesky1preshift,a3 ;12 moveq.l #0,d0 ;4 ;Offset for sky1 is unsigned move.w (a6)+,d0 ;8 add.l d0,a3 ;8 add.w PIPE_SKY1OFFSET(a0),a3 ;16 lea pipesky2preshift,a4 ;12 add.w (a6)+,a4 ;12 add.w PIPE_SKY2OFFSET(a0),a4 ;16 lea pipesky3preshift,a5 ;12 add.w (a6),a5 ;12 add.w PIPE_SKY3OFFSET(a0),a5 ;16 moveq.w #8,d6 ;4 ;Offset for sky source movem.l (a2),d0-d3 ;44 ;Read Planes 1+2+3+4 for pipe column movem.l d0-d3,160*151(a1) ;44 ;Draw very bottom of pipe first, 396 cycles movem.l d0-d3,160*152(a1) movem.l d0-d3,160*153(a1) movem.l d0-d3,160*154(a1) movem.l d0-d3,160*155(a1) movem.l d0-d3,160*156(a1) movem.l d0-d3,160*157(a1) movem.l d0-d3,160*158(a1) movem.l d0-d3,160*159(a1) move.l PIPE_FUNCBOTTOM3(a0),a6 ;16 jmp (a6) ;8 i0 movem.l d0-d3,160*80(a1) ;44 ;Draw pipe column, 1408 cycles i1 movem.l d0-d3,160*81(a1) i2 movem.l d0-d3,160*82(a1) i3 movem.l d0-d3,160*83(a1) i4 movem.l d0-d3,160*84(a1) i5 movem.l d0-d3,160*85(a1) i6 movem.l d0-d3,160*86(a1) i7 movem.l d0-d3,160*87(a1) i8 movem.l d0-d3,160*88(a1) i9 movem.l d0-d3,160*89(a1) i10 movem.l d0-d3,160*90(a1) i11 movem.l d0-d3,160*91(a1) i12 movem.l d0-d3,160*92(a1) i13 movem.l d0-d3,160*93(a1) i14 movem.l d0-d3,160*94(a1) i15 movem.l d0-d3,160*95(a1) i16 movem.l d0-d3,160*96(a1) i17 movem.l d0-d3,160*97(a1) i18 movem.l d0-d3,160*98(a1) i19 movem.l d0-d3,160*99(a1) i20 movem.l d0-d3,160*100(a1) i21 movem.l d0-d3,160*101(a1) i22 movem.l d0-d3,160*102(a1) i23 movem.l d0-d3,160*103(a1) i24 movem.l d0-d3,160*104(a1) i25 movem.l d0-d3,160*105(a1) i26 movem.l d0-d3,160*106(a1) i27 movem.l d0-d3,160*107(a1) i28 movem.l d0-d3,160*108(a1) i29 movem.l d0-d3,160*109(a1) i30 movem.l d0-d3,160*110(a1) i31 movem.l d0-d3,160*111(a1) i32 movem.l (a3)+,d0-d3 ;44 ;Sky top, 1048 cycles add.w d6,a3 ;8 movem.l d0-d3,160*112(a1) ;44 i33 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*113(a1) i34 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*114(a1) i35 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*115(a1) i36 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*116(a1) i37 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*117(a1) i38 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*118(a1) i39 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*119(a1) i40 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*120(a1) i41 movem.l (a3)+,d0-d3 add.w d6,a3 movem.l d0-d3,160*121(a1) i42 movem.l (a3),d0-d3 movem.l d0-d3,160*122(a1) i43 movem.l (a4)+,d0-d3 ;44 ;Buildings, 1816 cycles add.w d6,a4 ;8 movem.l d0-d3,160*123(a1) ;44 i44 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*124(a1) i45 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*125(a1) i46 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*126(a1) i47 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*127(a1) i48 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*128(a1) i49 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*129(a1) i50 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*130(a1) i51 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*131(a1) i52 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*132(a1) i53 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*133(a1) i54 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*134(a1) i55 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*135(a1) i56 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*136(a1) i57 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*137(a1) i58 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*138(a1) i59 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*139(a1) i60 movem.l (a4)+,d0-d3 add.w d6,a4 movem.l d0-d3,160*140(a1) i61 movem.l (a4),d0-d3 movem.l d0-d3,160*141(a1) i62 movem.l (a5)+,d0-d3 ;44 ;Grass, 856 cycles add.w d6,a5 ;8 movem.l d0-d3,160*142(a1) ;44 i63 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*143(a1) i64 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*144(a1) i65 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*145(a1) i66 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*146(a1) i67 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*147(a1) i68 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*148(a1) i69 movem.l (a5)+,d0-d3 add.w d6,a5 movem.l d0-d3,160*149(a1) i70 movem.l (a5),d0-d3 movem.l d0-d3,160*150(a1) bra pipedrawbottomcapclip3 ;---------------------------------- ;Draw bottom pipe clipped for X of 304...320 pipedrawbottomclip4 ;596-3908 cycles, 1-8 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-8(a1),a1 ;8 ;Add X screen offset lea pipeskyscrolltbl,a6 ;12 ;Get preshifts for X position and.w #127,d0 ;8 lsl.w #3,d0 ;12 add.w d0,a6 ;8 lea pipetoppreshift,a2 ;12 add.w (a6)+,a2 ;12 lea pipesky1preshift,a3 ;12 moveq.l #0,d0 ;4 ;Offset for sky1 is unsigned move.w (a6)+,d0 ;8 add.l d0,a3 ;8 add.w PIPE_SKY1OFFSET(a0),a3 ;16 lea pipesky2preshift,a4 ;12 add.w (a6)+,a4 ;12 add.w PIPE_SKY2OFFSET(a0),a4 ;16 lea pipesky3preshift,a5 ;12 add.w (a6),a5 ;12 add.w PIPE_SKY3OFFSET(a0),a5 ;16 moveq.w #16,d6 ;4 ;Offset for sky source movem.l (a2),d0-d1 ;28 ;Read Planes 1+2+3+4 for pipe column movem.l d0-d1,160*151(a1) ;28 ;Draw very bottom of pipe first, 252 cycles movem.l d0-d1,160*152(a1) movem.l d0-d1,160*153(a1) movem.l d0-d1,160*154(a1) movem.l d0-d1,160*155(a1) movem.l d0-d1,160*156(a1) movem.l d0-d1,160*157(a1) movem.l d0-d1,160*158(a1) movem.l d0-d1,160*159(a1) move.l PIPE_FUNCBOTTOM4(a0),a6 ;16 jmp (a6) ;8 j0 movem.l d0-d1,160*80(a1) ;28 ;Draw pipe column, 896 cycles j1 movem.l d0-d1,160*81(a1) j2 movem.l d0-d1,160*82(a1) j3 movem.l d0-d1,160*83(a1) j4 movem.l d0-d1,160*84(a1) j5 movem.l d0-d1,160*85(a1) j6 movem.l d0-d1,160*86(a1) j7 movem.l d0-d1,160*87(a1) j8 movem.l d0-d1,160*88(a1) j9 movem.l d0-d1,160*89(a1) j10 movem.l d0-d1,160*90(a1) j11 movem.l d0-d1,160*91(a1) j12 movem.l d0-d1,160*92(a1) j13 movem.l d0-d1,160*93(a1) j14 movem.l d0-d1,160*94(a1) j15 movem.l d0-d1,160*95(a1) j16 movem.l d0-d1,160*96(a1) j17 movem.l d0-d1,160*97(a1) j18 movem.l d0-d1,160*98(a1) j19 movem.l d0-d1,160*99(a1) j20 movem.l d0-d1,160*100(a1) j21 movem.l d0-d1,160*101(a1) j22 movem.l d0-d1,160*102(a1) j23 movem.l d0-d1,160*103(a1) j24 movem.l d0-d1,160*104(a1) j25 movem.l d0-d1,160*105(a1) j26 movem.l d0-d1,160*106(a1) j27 movem.l d0-d1,160*107(a1) j28 movem.l d0-d1,160*108(a1) j29 movem.l d0-d1,160*109(a1) j30 movem.l d0-d1,160*110(a1) j31 movem.l d0-d1,160*111(a1) j32 movem.l (a3)+,d0-d1 ;28 ;Sky top, 696 cycles add.w d6,a3 ;8 movem.l d0-d1,160*112(a1) ;28 j33 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*113(a1) j34 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*114(a1) j35 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*115(a1) j36 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*116(a1) j37 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*117(a1) j38 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*118(a1) j39 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*119(a1) j40 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*120(a1) j41 movem.l (a3)+,d0-d1 add.w d6,a3 movem.l d0-d1,160*121(a1) j42 movem.l (a3),d0-d1 movem.l d0-d1,160*122(a1) j43 movem.l (a4)+,d0-d1 ;28 ;Buildings, 1208 cycles add.w d6,a4 ;8 movem.l d0-d1,160*123(a1) ;28 j44 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*124(a1) j45 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*125(a1) j46 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*126(a1) j47 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*127(a1) j48 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*128(a1) j49 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*129(a1) j50 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*130(a1) j51 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*131(a1) j52 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*132(a1) j53 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*133(a1) j54 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*134(a1) j55 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*135(a1) j56 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*136(a1) j57 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*137(a1) j58 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*138(a1) j59 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*139(a1) j60 movem.l (a4)+,d0-d1 add.w d6,a4 movem.l d0-d1,160*140(a1) j61 movem.l (a4),d0-d1 movem.l d0-d1,160*141(a1) j62 movem.l (a5)+,d0-d1 ;28 ;Grass, 568 cycles add.w d6,a5 ;8 movem.l d0-d1,160*142(a1) ;28 j63 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*143(a1) j64 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*144(a1) j65 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*145(a1) j66 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*146(a1) j67 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*147(a1) j68 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*148(a1) j69 movem.l (a5)+,d0-d1 add.w d6,a5 movem.l d0-d1,160*149(a1) j70 movem.l (a5),d0-d1 movem.l d0-d1,160*150(a1) bra pipedrawbottomcapclip4 ;---------------------------------- ;Routines to draw bottom cap CAPLINE1 MACRO ;224 cycles movem.l \1(a3),d0-d5 ;64 ;Read sky for 48 pixels move.l (a2),d6 ;12 and.l d6,d0 ;8 and.l d6,d1 ;8 move.l 12(a2),d6 ;16 and.l d6,d2 ;8 and.l d6,d3 ;8 move.l 24(a2),d6 ;16 and.l d6,d4 ;8 and.l d6,d5 ;8 lea 36(a2),a2 ;8 movem.l d0-d5,\2(a1) ;60 ;Write ENDM CAPLINE2 MACRO ;304 cycles movem.l \1(a3),d0-d5 ;64 move.l (a2)+,d6 ;12 and.l d6,d0 ;8 and.l d6,d1 ;8 or.l (a2)+,d0 ;16 or.l (a2)+,d1 ;16 move.l (a2)+,d6 ;12 and.l d6,d2 ;8 and.l d6,d3 ;8 or.l (a2)+,d2 ;16 or.l (a2)+,d3 ;16 move.l (a2)+,d6 ;12 and.l d6,d4 ;8 and.l d6,d5 ;8 or.l (a2)+,d4 ;16 or.l (a2)+,d5 ;16 movem.l d0-d5,\2(a1) ;60 ENDM CAPLINE3 MACRO ;168 cycles movem.l \1(a3),d0-d3 ;48 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 move.l a4,d7 ;4 and.l d7,d2 ;8 and.l d7,d3 ;8 move.l a5,d7 ;4 or.l d7,d2 ;8 move.l a6,d7 ;4 or.l d7,d3 ;8 movem.l d0-d3,\2(a1) ;44 ENDM CAPLINE4 MACRO ;92 cycles movem.l \1(a3),d0-d1 ;32 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 movem.l d0-d1,\2(a1) ;28 ENDM ;---------------------------------- ;Draw bottom pipe cap pipedrawbottomcap  ;1164-3448 cycles, 2-7 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 move.w d0,d1 ;4 ;Add X screen offset lsr.w #1,d1 ;8 and.w #$fff8,d1 ;8 add.w d1,a1 ;8 add.w PIPE_CAPOFFSET(a0),a1 ;16 ;Offset Y move.w PIPE_SKYOFFSET(a0),d1 ;12 ;Offset to line in sky beq.w .fasterversion ;10/12 ;If over solid sky colour use faster routine move.l skyimg,a3 ;20 ;Source sky add.w d1,a3 ;8 move.w d0,d1 ;4 ;Add X sky offset 0...63 sub.w #96,d1 ;8 lsr.w #1,d1 ;8 and.w #$38,d1 ;8 add.w d1,a3 ;8 lea pipecapscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 CAPLINE1 80*0,160*0 ;224 CAPLINE2 80*1,160*1 ;304 movem.l (a2)+,d4-d6/a4-a6 ;60 ;Read pipe Mask and Planes 1+2+3+4 for 32 pixels CAPLINE3 80*2,160*2 ;168 ;8 lines, 1344 cycles CAPLINE3 80*3,160*3 CAPLINE3 80*4,160*4 CAPLINE3 80*5,160*5 CAPLINE3 80*6,160*6 CAPLINE3 80*7,160*7 CAPLINE3 80*8,160*8 CAPLINE3 80*9,160*9 movem.l (a2)+,d4-d6 ;36 ;Read pipe Mask and Planes 1+2+3+4 for 16 pixels CAPLINE4 80*2+16,160*2+16 ;92 ;8 lines, 736 cycles CAPLINE4 80*3+16,160*3+16 CAPLINE4 80*4+16,160*4+16 CAPLINE4 80*5+16,160*5+16 CAPLINE4 80*6+16,160*6+16 CAPLINE4 80*7+16,160*7+16 CAPLINE4 80*8+16,160*8+16 CAPLINE4 80*9+16,160*9+16 CAPLINE2 80*10,160*10 ;304 CAPLINE1 80*11,160*11 ;224 rts .fasterversion lea pipebottomscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l (a2)+,d0-d5 ;60 ;Draw pipe cap, 1016 cycles movem.l d0-d5,(a1) ;56 movem.l (a2)+,d0-d5 ;60 movem.l d0-d5,160*1(a1) ;60 movem.l (a2)+,d0-d5 movem.l d0-d5,160*2(a1) movem.l d0-d5,160*3(a1) movem.l d0-d5,160*4(a1) movem.l d0-d5,160*5(a1) movem.l d0-d5,160*6(a1) movem.l d0-d5,160*7(a1) movem.l d0-d5,160*8(a1) movem.l d0-d5,160*9(a1) movem.l (a2)+,d0-d5 movem.l d0-d5,160*10(a1) movem.l (a2),d0-d5 movem.l d0-d5,160*11(a1) rts ;---------------------------------- ;Routines to draw bottom cap CAPCLIP1LINE1 MACRO ;100 cycles movem.l \1+16(a3),d0-d1 ;32 ;Read sky for 16 pixels move.l 24(a2),d2 ;16 and.l d2,d0 ;8 and.l d2,d1 ;8 lea 36(a2),a2 ;8 movem.l d0-d1,\2(a1) ;28 ;Write ENDM CAPCLIP1LINE2 MACRO ;128 cycles movem.l \1+16(a3),d0-d1 ;32 lea 24(a2),a2 ;8 move.l (a2)+,d2 ;12 and.l d2,d0 ;8 and.l d2,d1 ;8 or.l (a2)+,d0 ;16 or.l (a2)+,d1 ;16 movem.l d0-d1,\2(a1) ;28 ENDM CAPCLIP1LINE3 MACRO ;92 cycles movem.l \1+16(a3),d0-d1 ;32 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 movem.l d0-d1,\2(a1) ;28 ENDM ;---------------------------------- ;Draw bottom pipe cap, clipped for X of -32...-16 pipedrawbottomcapclip1 ;616-1388 cycles, 1-3 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 add.w PIPE_CAPOFFSET(a0),a1 ;16 ;Offset Y move.w PIPE_SKYOFFSET(a0),d1 ;12 ;Offset to line in sky beq.w .fasterversion ;10/12 ;If over solid sky colour use faster routine move.l skyimg,a3 ;20 ;Source sky add.w d1,a3 ;8 ;And add X sky offset lea pipecapscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 CAPCLIP1LINE1 80*0,160*0 ;100 CAPCLIP1LINE2 80*1,160*1 ;128 lea 24(a2),a2 ;8 movem.l (a2)+,d4-d6 ;36 ;Read pipe Mask and Planes 1+2+3+4 for 16 pixels CAPCLIP1LINE3 80*2,160*2 ;92 ;8 lines, 736 cycles CAPCLIP1LINE3 80*3,160*3 CAPCLIP1LINE3 80*4,160*4 CAPCLIP1LINE3 80*5,160*5 CAPCLIP1LINE3 80*6,160*6 CAPCLIP1LINE3 80*7,160*7 CAPCLIP1LINE3 80*8,160*8 CAPCLIP1LINE3 80*9,160*9 CAPCLIP1LINE2 80*10,160*10 ;128 CAPCLIP1LINE1 80*11,160*11 ;100 rts .fasterversion lea pipebottomscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l 16(a2),d0-d1 ;32 ;Draw pipe cap, 492 cycles movem.l d0-d1,(a1) ;24 movem.l 40(a2),d0-d1 ;32 movem.l d0-d1,160*1(a1) ;28 movem.l 64(a2),d0-d1 movem.l d0-d1,160*2(a1) movem.l d0-d1,160*3(a1) movem.l d0-d1,160*4(a1) movem.l d0-d1,160*5(a1) movem.l d0-d1,160*6(a1) movem.l d0-d1,160*7(a1) movem.l d0-d1,160*8(a1) movem.l d0-d1,160*9(a1) movem.l 88(a2),d0-d1 movem.l d0-d1,160*10(a1) movem.l 112(a2),d0-d1 movem.l d0-d1,160*11(a1) rts ;---------------------------------- ;Routines to draw bottom cap CAPCLIP2LINE1 MACRO ;164 cycles movem.l \1+8(a3),d0-d3 ;48 ;Read sky for 32 pixels move.l 12(a2),d4 ;16 and.l d4,d0 ;8 and.l d4,d1 ;8 move.l 24(a2),d4 ;16 and.l d4,d2 ;8 and.l d4,d3 ;8 lea 36(a2),a2 ;8 movem.l d0-d3,\2(a1) ;44 ;Write ENDM CAPCLIP2LINE2 MACRO ;220 cycles movem.l \1+8(a3),d0-d3 ;48 lea 12(a2),a2 ;8 move.l (a2)+,d4 ;12 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l (a2)+,d0 ;16 or.l (a2)+,d1 ;16 move.l (a2)+,d4 ;12 and.l d4,d2 ;8 and.l d4,d3 ;8 or.l (a2)+,d2 ;16 or.l (a2)+,d3 ;16 movem.l d0-d3,\2(a1) ;44 ENDM CAPCLIP2LINE3 MACRO ;168 cycles movem.l \1+8(a3),d0-d3 ;48 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 move.l a4,d7 ;4 and.l d7,d2 ;8 and.l d7,d3 ;8 move.l a5,d7 ;4 or.l d7,d2 ;8 move.l a6,d7 ;4 or.l d7,d3 ;8 movem.l d0-d3,\2(a1) ;44 ENDM ;---------------------------------- ;Draw bottom pipe cap, clipped for X of -16...0 pipedrawbottomcapclip2 ;888-2336 cycles, 2-5 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 add.w PIPE_CAPOFFSET(a0),a1 ;16 ;Offset Y move.w PIPE_SKYOFFSET(a0),d1 ;12 ;Offset to line in sky beq.w .fasterversion ;10/12 ;If over solid sky colour use faster routine move.l skyimg,a3 ;20 ;Source sky lea 8(a3,d1.w),a3 ;12 ;And add X sky offset lea pipecapscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 CAPCLIP2LINE1 80*0,160*0 ;164 CAPCLIP2LINE2 80*1,160*1 ;220 lea 12(a2),a2 ;8 movem.l (a2)+,d4-d6/a4-a6 ;60 ;Read pipe Mask and Planes 1+2+3+4 for 32 pixels CAPCLIP2LINE3 80*2,160*2 ;168 ;8 lines, 1344 cycles CAPCLIP2LINE3 80*3,160*3 CAPCLIP2LINE3 80*4,160*4 CAPCLIP2LINE3 80*5,160*5 CAPCLIP2LINE3 80*6,160*6 CAPCLIP2LINE3 80*7,160*7 CAPCLIP2LINE3 80*8,160*8 CAPCLIP2LINE3 80*9,160*9 CAPCLIP2LINE2 80*10,160*10 ;220 CAPCLIP2LINE1 80*11,160*11 ;164 rts .fasterversion lea pipebottomscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l 8(a2),d0-d3 ;48 ;Draw pipe cap, 764 cycles movem.l d0-d3,(a1) ;40 movem.l 32(a2),d0-d3 ;48 movem.l d0-d3,160*1(a1) ;44 movem.l 56(a2),d0-d3 movem.l d0-d3,160*2(a1) movem.l d0-d3,160*3(a1) movem.l d0-d3,160*4(a1) movem.l d0-d3,160*5(a1) movem.l d0-d3,160*6(a1) movem.l d0-d3,160*7(a1) movem.l d0-d3,160*8(a1) movem.l d0-d3,160*9(a1) movem.l 80(a2),d0-d3 movem.l d0-d3,160*10(a1) movem.l 104(a2),d0-d3 movem.l d0-d3,160*11(a1) rts ;---------------------------------- ;Routines to draw bottom cap CAPCLIP3LINE1 MACRO ;160 cycles movem.l \1(a3),d0-d3 ;48 ;Read sky for 32 pixels move.l (a2),d4 ;12 and.l d4,d0 ;8 and.l d4,d1 ;8 move.l 12(a2),d4 ;16 and.l d4,d2 ;8 and.l d4,d3 ;8 lea 36(a2),a2 ;8 movem.l d0-d3,\2(a1) ;44 ;Write ENDM CAPCLIP3LINE2 MACRO ;220 cycles movem.l \1(a3),d0-d3 ;48 move.l (a2)+,d4 ;12 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l (a2)+,d0 ;16 or.l (a2)+,d1 ;16 move.l (a2)+,d4 ;12 and.l d4,d2 ;8 and.l d4,d3 ;8 or.l (a2)+,d2 ;16 or.l (a2)+,d3 ;16 lea 12(a2),a2 ;8 movem.l d0-d3,\2(a1) ;44 ENDM CAPCLIP3LINE3 MACRO ;168 cycles movem.l \1(a3),d0-d3 ;48 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 move.l a4,d7 ;4 and.l d7,d2 ;8 and.l d7,d3 ;8 move.l a5,d7 ;4 or.l d7,d2 ;8 move.l a6,d7 ;4 or.l d7,d3 ;8 movem.l d0-d3,\2(a1) ;44 ENDM ;---------------------------------- ;Draw bottom pipe cap, clipped for X of 288...304 pipedrawbottomcapclip3 ;892-2136 cycles, 2-4 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-16(a1),a1 ;8 ;Add X screen offset add.w PIPE_CAPOFFSET(a0),a1 ;16 ;Offset Y move.w PIPE_SKYOFFSET(a0),d1 ;12 ;Offset to line in sky beq.w .fasterversion ;10/12 ;If over solid sky colour use faster routine move.l skyimg,a3 ;20 ;Source sky lea 32(a3,d1.w),a3 ;12 ;And add X sky offset lea pipecapscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 CAPCLIP3LINE1 80*0,160*0 ;160 CAPCLIP3LINE2 80*1,160*1 ;220 movem.l (a2)+,d4-d6/a4-a6 ;60 ;Read pipe Mask and Planes 1+2+3+4 for 32 pixels lea 12(a2),a2 ;8 CAPCLIP3LINE3 80*2,160*2 ;168 ;8 lines, 1344 cycles CAPCLIP3LINE3 80*3,160*3 CAPCLIP3LINE3 80*4,160*4 CAPCLIP3LINE3 80*5,160*5 CAPCLIP3LINE3 80*6,160*6 CAPCLIP3LINE3 80*7,160*7 CAPCLIP3LINE3 80*8,160*8 CAPCLIP3LINE3 80*9,160*9 CAPCLIP3LINE2 80*10,160*10 ;220 CAPCLIP3LINE1 80*11,160*11 ;160 rts .fasterversion lea pipebottomscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l (a2),d0-d3 ;44 ;Draw pipe cap, 760 cycles movem.l d0-d3,(a1) ;40 movem.l 24(a2),d0-d3 ;48 movem.l d0-d3,160*1(a1) ;44 movem.l 48(a2),d0-d3 movem.l d0-d3,160*2(a1) movem.l d0-d3,160*3(a1) movem.l d0-d3,160*4(a1) movem.l d0-d3,160*5(a1) movem.l d0-d3,160*6(a1) movem.l d0-d3,160*7(a1) movem.l d0-d3,160*8(a1) movem.l d0-d3,160*9(a1) movem.l 72(a2),d0-d3 movem.l d0-d3,160*10(a1) movem.l 96(a2),d0-d3 movem.l d0-d3,160*11(a1) rts ;---------------------------------- ;Routines to draw bottom cap CAPCLIP4LINE1 MACRO ;96 cycles movem.l \1(a3),d0-d1 ;32 ;Read sky for 16 pixels move.l (a2),d2 ;12 and.l d2,d0 ;8 and.l d2,d1 ;8 lea 36(a2),a2 ;8 movem.l d0-d1,\2(a1) ;28 ;Write ENDM CAPCLIP4LINE2 MACRO ;128 cycles movem.l \1(a3),d0-d1 ;32 move.l (a2)+,d2 ;12 and.l d2,d0 ;8 and.l d2,d1 ;8 or.l (a2)+,d0 ;16 or.l (a2)+,d1 ;16 lea 24(a2),a2 ;8 movem.l d0-d1,\2(a1) ;28 ENDM CAPCLIP4LINE3 MACRO ;92 cycles movem.l \1(a3),d0-d1 ;32 and.l d4,d0 ;8 and.l d4,d1 ;8 or.l d5,d0 ;8 or.l d6,d1 ;8 movem.l d0-d1,\2(a1) ;28 ENDM ;---------------------------------- ;Draw bottom pipe cap, clipped for X of 304...320 pipedrawbottomcapclip4 ;620-1392 cycles, 1-3 rasters move.l offscreenbse,a1 ;20 move.w PIPE_X(a0),d0 ;12 lea 160-8(a1),a1 ;8 ;Add X screen offset add.w PIPE_CAPOFFSET(a0),a1 ;16 ;Offset Y move.w PIPE_SKYOFFSET(a0),d1 ;12 ;Offset to line in sky beq.w .fasterversion ;10/12 ;If over solid sky colour use faster routine move.l skyimg,a3 ;20 ;Source sky lea 40(a3,d1.w),a3 ;12 ;And add X sky offset lea pipecapscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 CAPCLIP4LINE1 80*0,160*0 ;96 CAPCLIP4LINE2 80*1,160*1 ;128 movem.l (a2)+,d4-d6 ;36 ;Read pipe Mask and Planes 1+2+3+4 for 16 pixels lea 24(a2),a2 ;8 CAPCLIP4LINE3 80*2,160*2 ;92 ;8 lines, 736 cycles CAPCLIP4LINE3 80*3,160*3 CAPCLIP4LINE3 80*4,160*4 CAPCLIP4LINE3 80*5,160*5 CAPCLIP4LINE3 80*6,160*6 CAPCLIP4LINE3 80*7,160*7 CAPCLIP4LINE3 80*8,160*8 CAPCLIP4LINE3 80*9,160*9 CAPCLIP4LINE2 80*10,160*10 ;128 CAPCLIP4LINE1 80*11,160*11 ;96 rts .fasterversion lea pipebottomscrolltbl,a6 ;12 ;Look up preshift to X position and.w #15,d0 ;8 lsl.w #2,d0 ;12 move.l (a6,d0.w),a2 ;20 movem.l (a2),d0-d1 ;28 ;Draw pipe cap, 488 cycles movem.l d0-d1,(a1) ;24 movem.l 24(a2),d0-d1 ;32 movem.l d0-d1,160*1(a1) ;28 movem.l 48(a2),d0-d1 movem.l d0-d1,160*2(a1) movem.l d0-d1,160*3(a1) movem.l d0-d1,160*4(a1) movem.l d0-d1,160*5(a1) movem.l d0-d1,160*6(a1) movem.l d0-d1,160*7(a1) movem.l d0-d1,160*8(a1) movem.l d0-d1,160*9(a1) movem.l 72(a2),d0-d1 movem.l d0-d1,160*10(a1) movem.l 96(a2),d0-d1 movem.l d0-d1,160*11(a1) rts ;---------------------------------- ;Pipe structure RSRESET PIPE_X rs.w 1 ;Pipe X coordinate PIPE_Y rs.w 1 ;Y offset (0...70 inclusive) PIPE_LINEOFFSET rs.w 1 ;Screen offset for first line PIPE_CAPOFFSET rs.w 1 ;Screen offset for bottom cap PIPE_SKYOFFSET rs.w 1 ;Offset into sky for bottom cap PIPE_SKY1OFFSET rs.w 1 ;Offset into sky preshift images PIPE_SKY2OFFSET rs.w 1 PIPE_SKY3OFFSET rs.w 1 PIPE_FUNCTOP rs.l 1 ;Functions for top pipe drawing PIPE_FUNCTOP1 rs.l 1 PIPE_FUNCTOP2 rs.l 1 PIPE_FUNCTOP3 rs.l 1 PIPE_FUNCTOP4 rs.l 1 PIPE_FUNCBOTTOM rs.l 1 ;Functions for bottom pipe drawing PIPE_FUNCBOTTOM1 rs.l 1 PIPE_FUNCBOTTOM2 rs.l 1 PIPE_FUNCBOTTOM3 rs.l 1 PIPE_FUNCBOTTOM4 rs.l 1 PIPE_SIZE = 60 NUMPIPES = 5 ;We have up to 5 pipes on screen PIPEXGAP = 80 ;Pixels between each pixel across screen PIPEYGAP = 48 ;Vertical pixel gap in pipe PIPEXSCORE = 118 ;Award score if pipe passes this X position ;---------------------------------- SECTION DATA ;List of details to set pipe for Y of 20...90 (ie 71 different height offsets) pipedetails dc.w 160*80,160*68,80*0,0,0,0 ;20 dc.l a70,b70,c70,d70,e70, f0,g0,h0,i0,j0 dc.w 160*79,160*69,80*0,0,0,0 ;21 dc.l a69,b69,c69,d69,e69, f1,g1,h1,i1,j1 dc.w 160*78,160*70,80*0,0,0,0 ;22 dc.l a68,b68,c68,d68,e68, f2,g2,h2,i2,j2 dc.w 160*77,160*71,80*0,0,0,0 ;23 dc.l a67,b67,c67,d67,e67, f3,g3,h3,i3,j3 dc.w 160*76,160*72,80*0,0,0,0 ;24 dc.l a66,b66,c66,d66,e66, f4,g4,h4,i4,j4 dc.w 160*75,160*73,80*0,0,0,0 ;25 dc.l a65,b65,c65,d65,e65, f5,g5,h5,i5,j5 dc.w 160*74,160*74,80*0,0,0,0 ;26 dc.l a64,b64,c64,d64,e64, f6,g6,h6,i6,j6 dc.w 160*73,160*75,80*0,0,0,0 ;27 dc.l a63,b63,c63,d63,e63, f7,g7,h7,i7,j7 dc.w 160*72,160*76,80*0,0,0,0 ;28 dc.l a62,b62,c62,d62,e62, f8,g8,h8,i8,j8 dc.w 160*71,160*77,80*0,0,0,0 ;29 dc.l a61,b61,c61,d61,e61, f9,g9,h9,i9,j9 dc.w 160*70,160*78,80*0,0,0,0 ;30 dc.l a60,b60,c60,d60,e60, f10,g10,h10,i10,j10 dc.w 160*69,160*79,80*0,0,0,0 ;31 dc.l a59,b59,c59,d59,e59, f11,g11,h11,i11,j11 dc.w 160*68,160*80,80*0,0,0,0 ;32 dc.l a58,b58,c58,d58,e58, f12,g12,h12,i12,j12 dc.w 160*67,160*81,80*0,0,0,0 ;33 dc.l a57,b57,c57,d57,e57, f13,g13,h13,i13,j13 dc.w 160*66,160*82,80*0,0,0,0 ;34 dc.l a56,b56,c56,d56,e56, f14,g14,h14,i14,j14 dc.w 160*65,160*83,80*0,0,0,0 ;35 dc.l a55,b55,c55,d55,e55, f15,g15,h15,i15,j15 dc.w 160*64,160*84,80*0,0,0,0 ;36 dc.l a54,b54,c54,d54,e54, f16,g16,h16,i16,j16 dc.w 160*63,160*85,80*0,0,0,0 ;37 dc.l a53,b53,c53,d53,e53, f17,g17,h17,i17,j17 dc.w 160*62,160*86,80*0,0,0,0 ;38 dc.l a52,b52,c52,d52,e52, f18,g18,h18,i18,j18 dc.w 160*61,160*87,80*0,0,0,0 ;39 dc.l a51,b51,c51,d51,e51, f19,g19,h19,i19,j19 dc.w 160*60,160*88,80*0,0,0,0 ;40 dc.l a50,b50,c50,d50,e50, f20,g20,h20,i20,j20 dc.w 160*59,160*89,80*0,0,0,0 ;41 dc.l a49,b49,c49,d49,e49, f21,g21,h21,i21,j21 dc.w 160*58,160*90,80*0,0,0,0 ;42 dc.l a48,b48,c48,d48,e48, f22,g22,h22,i22,j22 dc.w 160*57,160*91,80*0,0,0,0 ;43 dc.l a47,b47,c47,d47,e47, f23,g23,h23,i23,j23 dc.w 160*56,160*92,80*0,0,0,0 ;44 dc.l a46,b46,c46,d46,e46, f24,g24,h24,i24,j24 dc.w 160*55,160*93,80*0,0,0,0 ;45 dc.l a45,b45,c45,d45,e45, f25,g25,h25,i25,j25 dc.w 160*54,160*94,80*0,0,0,0 ;46 dc.l a44,b44,c44,d44,e44, f26,g26,h26,i26,j26 dc.w 160*53,160*95,80*0,0,0,0 ;47 dc.l a43,b43,c43,d43,e43, f27,g27,h27,i27,j27 dc.w 160*52,160*96,80*0,0,0,0 ;48 dc.l a42,b42,c42,d42,e42, f28,g28,h28,i28,j28 dc.w 160*51,160*97,80*0,0,0,0 ;49 dc.l a41,b41,c41,d41,e41, f29,g29,h29,i29,j29 dc.w 160*50,160*98,80*0,0,0,0 ;50 dc.l a40,b40,c40,d40,e40, f30,g30,h30,i30,j30 dc.w 160*49,160*99,80*0,0,0,0 ;51 dc.l a39,b39,c39,d39,e39, f31,g31,h31,i31,j31 dc.w 160*48,160*100,80*0,24*0,0,0 ;52 dc.l a38,b38,c38,d38,e38, f32,g32,h32,i32,j32 dc.w 160*47,160*101,80*6,24*1,0,0 ;53 dc.l a37,b37,c37,d37,e37, f33,g33,h33,i33,j33 dc.w 160*46,160*102,80*7,24*2,0,0 ;54 dc.l a36,b36,c36,d36,e36, f34,g34,h34,i34,j34 dc.w 160*45,160*103,80*8,24*3,0,0 ;55 dc.l a35,b35,c35,d35,e35, f35,g35,h35,i35,j35 dc.w 160*44,160*104,80*9,24*4,0,0 ;56 dc.l a34,b34,c34,d34,e34, f36,g36,h36,i36,j36 dc.w 160*43,160*105,80*10,24*5,0,0 ;57 dc.l a33,b33,c33,d33,e33, f37,g37,h37,i37,j37 dc.w 160*42,160*106,80*11,24*6,0,0 ;58 dc.l a32,b32,c32,d32,e32, f38,g38,h38,i38,j38 dc.w 160*41,160*107,80*12,24*7,0,0 ;59 dc.l a31,b31,c31,d31,e31, f39,g39,h39,i39,j39 dc.w 160*40,160*108,80*13,24*8,0,0 ;60 dc.l a30,b30,c30,d30,e30, f40,g40,h40,i40,j40 dc.w 160*39,160*109,80*14,24*9,0,0 ;61 dc.l a29,b29,c29,d29,e29, f41,g41,h41,i41,j41 dc.w 160*38,160*110,80*15,24*10,0,0 ;62 dc.l a28,b28,c28,d28,e28, f42,g42,h42,i42,j42 dc.w 160*37,160*111,80*16,0,24*0,0 ;63 dc.l a27,b27,c27,d27,e27, f43,g43,h43,i43,j43 dc.w 160*36,160*112,80*17,0,24*1,0 ;64 dc.l a26,b26,c26,d26,e26, f44,g44,h44,i44,j44 dc.w 160*35,160*113,80*18,0,24*2,0 ;65 dc.l a25,b25,c25,d25,e25, f45,g45,h45,i45,j45 dc.w 160*34,160*114,80*19,0,24*3,0 ;66 dc.l a24,b24,c24,d24,e24, f46,g46,h46,i46,j46 dc.w 160*33,160*115,80*20,0,24*4,0 ;67 dc.l a23,b23,c23,d23,e23, f47,g47,h47,i47,j47 dc.w 160*32,160*116,80*21,0,24*5,0 ;68 dc.l a22,b22,c22,d22,e22, f48,g48,h48,i48,j48 dc.w 160*31,160*117,80*22,0,24*6,0 ;69 dc.l a21,b21,c21,d21,e21, f49,g49,h49,i49,j49 dc.w 160*30,160*118,80*23,0,24*7,0 ;70 dc.l a20,b20,c20,d20,e20, f50,g50,h50,i50,j50 dc.w 160*29,160*119,80*24,0,24*8,0 ;71 dc.l a19,b19,c19,d19,e19, f51,g51,h51,i51,j51 dc.w 160*28,160*120,80*25,0,24*9,0 ;72 dc.l a18,b18,c18,d18,e18, f52,g52,h52,i52,j52 dc.w 160*27,160*121,80*26,0,24*10,0 ;73 dc.l a17,b17,c17,d17,e17, f53,g53,h53,i53,j53 dc.w 160*26,160*122,80*27,0,24*11,0 ;74 dc.l a16,b16,c16,d16,e16, f54,g54,h54,i54,j54 dc.w 160*25,160*123,80*28,0,24*12,0 ;75 dc.l a15,b15,c15,d15,e15, f55,g55,h55,i55,j55 dc.w 160*24,160*124,80*29,0,24*13,0 ;76 dc.l a14,b14,c14,d14,e14, f56,g56,h56,i56,j56 dc.w 160*23,160*125,80*30,0,24*14,0 ;77 dc.l a13,b13,c13,d13,e13, f57,g57,h57,i57,j57 dc.w 160*22,160*126,80*31,0,24*15,0 ;78 dc.l a12,b12,c12,d12,e12, f58,g58,h58,i58,j58 dc.w 160*21,160*127,80*32,0,24*16,0 ;79 dc.l a11,b11,c11,d11,e11, f59,g59,h59,i59,j59 dc.w 160*20,160*128,80*33,0,24*17,0 ;80 dc.l a10,b10,c10,d10,e10, f60,g60,h60,i60,j60 dc.w 160*19,160*129,80*34,0,24*18,0 ;81 dc.l a9,b9,c9,d9,e9, f61,g61,h61,i61,j61 dc.w 160*18,160*130,80*35,0,0,24*0 ;82 dc.l a8,b8,c8,d8,e8, f62,g62,h62,i62,j62 dc.w 160*17,160*131,80*36,0,0,24*1 ;83 dc.l a7,b7,c7,d7,e7, f63,g63,h63,i63,j63 dc.w 160*16,160*132,80*37,0,0,24*2 ;84 dc.l a6,b6,c6,d6,e6, f64,g64,h64,i64,j64 dc.w 160*15,160*133,80*38,0,0,24*3 ;85 dc.l a5,b5,c5,d5,e5, f65,g65,h65,i65,j65 dc.w 160*14,160*134,80*39,0,0,24*4 ;86 dc.l a4,b4,c4,d4,e4, f66,g66,h66,i66,j66 dc.w 160*13,160*135,80*40,0,0,24*5 ;87 dc.l a3,b3,c3,d3,e3, f67,g67,h67,i67,j67 dc.w 160*12,160*136,80*41,0,0,24*6 ;88 dc.l a2,b2,c2,d2,e2, f68,g68,h68,i68,j68 dc.w 160*11,160*137,80*42,0,0,24*7 ;89 dc.l a1,b1,c1,d1,e1, f69,g69,h69,i69,j69 dc.w 160*10,160*138,80*43,0,0,24*8 ;90 dc.l a0,b0,c0,d0,e0, f70,g70,h70,i70,j70 pipetopscrolltbl dc.l pipetoppreshift+(144*0) dc.l pipetoppreshift+(144*1) dc.l pipetoppreshift+(144*2) dc.l pipetoppreshift+(144*3) dc.l pipetoppreshift+(144*4) dc.l pipetoppreshift+(144*5) dc.l pipetoppreshift+(144*6) dc.l pipetoppreshift+(144*7) dc.l pipetoppreshift+(144*8) dc.l pipetoppreshift+(144*9) dc.l pipetoppreshift+(144*10) dc.l pipetoppreshift+(144*11) dc.l pipetoppreshift+(144*12) dc.l pipetoppreshift+(144*13) dc.l pipetoppreshift+(144*14) dc.l pipetoppreshift+(144*15) pipebottomscrolltbl dc.l pipebottompreshift+(120*0) dc.l pipebottompreshift+(120*1) dc.l pipebottompreshift+(120*2) dc.l pipebottompreshift+(120*3) dc.l pipebottompreshift+(120*4) dc.l pipebottompreshift+(120*5) dc.l pipebottompreshift+(120*6) dc.l pipebottompreshift+(120*7) dc.l pipebottompreshift+(120*8) dc.l pipebottompreshift+(120*9) dc.l pipebottompreshift+(120*10) dc.l pipebottompreshift+(120*11) dc.l pipebottompreshift+(120*12) dc.l pipebottompreshift+(120*13) dc.l pipebottompreshift+(120*14) dc.l pipebottompreshift+(120*15) pipecapscrolltbl dc.l pipecappreshift+(180*0) dc.l pipecappreshift+(180*1) dc.l pipecappreshift+(180*2) dc.l pipecappreshift+(180*3) dc.l pipecappreshift+(180*4) dc.l pipecappreshift+(180*5) dc.l pipecappreshift+(180*6) dc.l pipecappreshift+(180*7) dc.l pipecappreshift+(180*8) dc.l pipecappreshift+(180*9) dc.l pipecappreshift+(180*10) dc.l pipecappreshift+(180*11) dc.l pipecappreshift+(180*12) dc.l pipecappreshift+(180*13) dc.l pipecappreshift+(180*14) dc.l pipecappreshift+(180*15) pipeskyscrolltbl dc.w 144*0,264*0,456*0,216*0 dc.w 144*1,264*1,456*1,216*1 dc.w 144*2,264*2,456*2,216*2 dc.w 144*3,264*3,456*3,216*3 dc.w 144*4,264*4,456*4,216*4 dc.w 144*5,264*5,456*5,216*5 dc.w 144*6,264*6,456*6,216*6 dc.w 144*7,264*7,456*7,216*7 dc.w 144*8,264*8,456*8,216*8 dc.w 144*9,264*9,456*9,216*9 dc.w 144*10,264*10,456*10,216*10 dc.w 144*11,264*11,456*11,216*11 dc.w 144*12,264*12,456*12,216*12 dc.w 144*13,264*13,456*13,216*13 dc.w 144*14,264*14,456*14,216*14 dc.w 144*15,264*15,456*15,216*15 dc.w 144*0,264*16,456*16,216*16 dc.w 144*1,264*17,456*17,216*17 dc.w 144*2,264*18,456*18,216*18 dc.w 144*3,264*19,456*19,216*19 dc.w 144*4,264*20,456*20,216*20 dc.w 144*5,264*21,456*21,216*21 dc.w 144*6,264*22,456*22,216*22 dc.w 144*7,264*23,456*23,216*23 dc.w 144*8,264*24,456*24,216*24 dc.w 144*9,264*25,456*25,216*25 dc.w 144*10,264*26,456*26,216*26 dc.w 144*11,264*27,456*27,216*27 dc.w 144*12,264*28,456*28,216*28 dc.w 144*13,264*29,456*29,216*29 dc.w 144*14,264*30,456*30,216*30 dc.w 144*15,264*31,456*31,216*31 dc.w 144*0,264*32,456*0,216*32 dc.w 144*1,264*33,456*1,216*33 dc.w 144*2,264*34,456*2,216*34 dc.w 144*3,264*35,456*3,216*35 dc.w 144*4,264*36,456*4,216*36 dc.w 144*5,264*37,456*5,216*37 dc.w 144*6,264*38,456*6,216*38 dc.w 144*7,264*39,456*7,216*39 dc.w 144*8,264*40,456*8,216*40 dc.w 144*9,264*41,456*9,216*41 dc.w 144*10,264*42,456*10,216*42 dc.w 144*11,264*43,456*11,216*43 dc.w 144*12,264*44,456*12,216*44 dc.w 144*13,264*45,456*13,216*45 dc.w 144*14,264*46,456*14,216*46 dc.w 144*15,264*47,456*15,216*47 dc.w 144*0,264*48,456*16,216*48 dc.w 144*1,264*49,456*17,216*49 dc.w 144*2,264*50,456*18,216*50 dc.w 144*3,264*51,456*19,216*51 dc.w 144*4,264*52,456*20,216*52 dc.w 144*5,264*53,456*21,216*53 dc.w 144*6,264*54,456*22,216*54 dc.w 144*7,264*55,456*23,216*55 dc.w 144*8,264*56,456*24,216*56 dc.w 144*9,264*57,456*25,216*57 dc.w 144*10,264*58,456*26,216*58 dc.w 144*11,264*59,456*27,216*59 dc.w 144*12,264*60,456*28,216*60 dc.w 144*13,264*61,456*29,216*61 dc.w 144*14,264*62,456*30,216*62 dc.w 144*15,264*63,456*31,216*63 dc.w 144*0,264*64,456*0,216*0 dc.w 144*1,264*65,456*1,216*1 dc.w 144*2,264*66,456*2,216*2 dc.w 144*3,264*67,456*3,216*3 dc.w 144*4,264*68,456*4,216*4 dc.w 144*5,264*69,456*5,216*5 dc.w 144*6,264*70,456*6,216*6 dc.w 144*7,264*71,456*7,216*7 dc.w 144*8,264*72,456*8,216*8 dc.w 144*9,264*73,456*9,216*9 dc.w 144*10,264*74,456*10,216*10 dc.w 144*11,264*75,456*11,216*11 dc.w 144*12,264*76,456*12,216*12 dc.w 144*13,264*77,456*13,216*13 dc.w 144*14,264*78,456*14,216*14 dc.w 144*15,264*79,456*15,216*15 dc.w 144*0,264*80,456*16,216*16 dc.w 144*1,264*81,456*17,216*17 dc.w 144*2,264*82,456*18,216*18 dc.w 144*3,264*83,456*19,216*19 dc.w 144*4,264*84,456*20,216*20 dc.w 144*5,264*85,456*21,216*21 dc.w 144*6,264*86,456*22,216*22 dc.w 144*7,264*87,456*23,216*23 dc.w 144*8,264*88,456*24,216*24 dc.w 144*9,264*89,456*25,216*25 dc.w 144*10,264*90,456*26,216*26 dc.w 144*11,264*91,456*27,216*27 dc.w 144*12,264*92,456*28,216*28 dc.w 144*13,264*93,456*29,216*29 dc.w 144*14,264*94,456*30,216*30 dc.w 144*15,264*95,456*31,216*31 dc.w 144*0,264*96,456*0,216*32 dc.w 144*1,264*97,456*1,216*33 dc.w 144*2,264*98,456*2,216*34 dc.w 144*3,264*99,456*3,216*35 dc.w 144*4,264*100,456*4,216*36 dc.w 144*5,264*101,456*5,216*37 dc.w 144*6,264*102,456*6,216*38 dc.w 144*7,264*103,456*7,216*39 dc.w 144*8,264*104,456*8,216*40 dc.w 144*9,264*105,456*9,216*41 dc.w 144*10,264*106,456*10,216*42 dc.w 144*11,264*107,456*11,216*43 dc.w 144*12,264*108,456*12,216*44 dc.w 144*13,264*109,456*13,216*45 dc.w 144*14,264*110,456*14,216*46 dc.w 144*15,264*111,456*15,216*47 dc.w 144*0,264*112,456*16,216*48 dc.w 144*1,264*113,456*17,216*49 dc.w 144*2,264*114,456*18,216*50 dc.w 144*3,264*115,456*19,216*51 dc.w 144*4,264*116,456*20,216*52 dc.w 144*5,264*117,456*21,216*53 dc.w 144*6,264*118,456*22,216*54 dc.w 144*7,264*119,456*23,216*55 dc.w 144*8,264*120,456*24,216*56 dc.w 144*9,264*121,456*25,216*57 dc.w 144*10,264*122,456*26,216*58 dc.w 144*11,264*123,456*27,216*59 dc.w 144*12,264*124,456*28,216*60 dc.w 144*13,264*125,456*29,216*61 dc.w 144*14,264*126,456*30,216*62 dc.w 144*15,264*127,456*31,216*63 ;---------------------------------- SECTION BSS pipecheck ds.w 1 ;Y offset scroller check value pipes ds.b PIPE_SIZE*NUMPIPES ;Pipe structures EVEN ;Create preshifted graphics used for fonts and scroller SECTION TEXT ;---------------------------------- ;Create preshifts preshiftinit bsr preshiftcalcscorelarge ;Create score font preshifts bsr preshiftcalcscoresmall bsr preshiftcalcsparkles ;Create sparkle preshifts moveq.w #6,d0 ;Create constant preshifts for pipes lea pipetopimg,a0 lea pipetoppreshift,a1 bsr preshiftcalcpipe moveq.w #5,d0 lea pipebottomimg,a0 lea pipebottompreshift,a1 bsr preshiftcalcpipe moveq.w #5,d0 lea pipecapspr,a0 lea pipecappreshift,a1 bra preshiftcalcpipespr ;(does RTS) ;---------------------------------- ;Preshift large score font preshiftcalcscorelarge lea scorelargespr,a0 lea scorelargepreshift,a1 moveq.w #10-1,d2 ;10 digits .loop moveq.w #18-1,d3 ;Font height .loop2 move.l #$ffff0000,d0 ;Clear Mask and Plane 1 registers moveq.l #0,d1 move.w (a0)+,d0 ;Read Mask and Plane 1 move.w (a0)+,d1 move.l a1,a2  ;Copy destination for preshift loop moveq.w #8-1,d4 ;Preshift line for each X offset (even) .loop3 move.w d0,(a2)+ ;Write first word of Mask move.w d1,(a2)+ ;Write first word of Plane 1 swap d0 ;Swap to upper words swap d1 move.w d0,(a2)+ ;Write second word of Mask move.w d1,(a2) ;Write second word of Plane 1 swap d0 ;Swap words back swap d1 ror.l #2,d0 ;Shift Mask and Plane 1 by 2 pixels ror.l #2,d1 lea 144-6(a2),a2 ;Next preshift digit, each is 144 bytes dbra.w d4,.loop3 addq.l #8,a1 ;Next destination line dbra.w d3,.loop2 lea 1152-144(a1),a1 ;Next destination digit, each preshift is 1152 bytes dbra.w d2,.loop rts ;---------------------------------- ;Preshift small score font preshiftcalcscoresmall lea scoresmallspr,a0 lea scoresmallpreshift,a1 moveq.w #10-1,d2 ;10 digits .loop moveq.w #10-1,d3 ;Font height .loop2 move.l #$ffff0000,d0 ;Clear Mask and Plane 1 registers moveq.l #0,d1 move.w (a0)+,d0 ;Read Mask and Plane 1 move.w (a0)+,d1 move.l a1,a2 ;Copy destination for preshift loop moveq.w #8-1,d4 ;Preshift line for each X offset (even) .loop3 move.w d0,(a2)+ ;Write first word of Mask move.w d1,(a2)+ ;Write first word of Plane 1 swap d0 ;Swap to upper words swap d1 move.w d0,(a2)+ ;Write second word of Mask move.w d1,(a2) ;Write second word of Plane 1 swap d0 ;Swap words back swap d1 ror.l #2,d0 ;Shift Mask and Plane 1 by 2 pixels ror.l #2,d1 lea 80-6(a2),a2 ;Next preshift digit, each is 80 bytes dbra.w d4,.loop3 addq.l #8,a1 ;Next destination line dbra.w d3,.loop2 lea 640-80(a1),a1 ;Next destination digit, each preshift is 640 bytes dbra.w d2,.loop rts ;---------------------------------- ;Preshift sparkles preshiftcalcsparkles lea sparklespr,a0 lea sparklepreshift,a1 moveq.w #3-1,d4 ;3 frames .loop moveq.w #5-1,d3 ;5 pixels high .loop2 move.l #$ffff0000,d0 ;Read Mask and Planes 1+2+3 move.w (a0)+,d0 move.l (a0)+,d1 moveq.l #0,d2 move.w (a0)+,d2 move.l a1,a2 ;Copy destination for preshift loop moveq.l #11,d5 ;Halfway shift value moveq.w #8-1,d6 ;Preshift line for each X set (within word) .loop3 move.w d0,(a2)+ ;Write Mask as long move.w d0,(a2)+ move.l d1,(a2)+ ;Write Planes 1+2+3+4 move.l d2,(a2) cmp.w #4,d6 ;Halfway through? bne.s .nothalfway rol.l d5,d0 ;Shift back to top bit for next set rol.l d5,d1 rol.l d5,d2 or.l #$ffff0000,d0 ;Fix Mask bra.s .continue .nothalfway ror.l #2,d0 ;Shift Mask and Plane 1+2+3+4 by 2 pixels ror.l #2,d1 ror.l #2,d2 .continue lea 60-8(a2),a2 ;Next preshift digit, each is 60 bytes dbra.w d6,.loop3 lea 12(a1),a1 ;Next destination line dbra.w d3,.loop2 lea 480-60(a1),a1 ;Next destination sparkle, each preshift is 480 bytes dbra.w d4,.loop rts ;---------------------------------- ;Preshift 48 pixel wide pipe, pass d0.w as height, a0.l as source, a1.l as preshift destination preshiftcalcpipe move.w d0,d1 subq.w #1,d1 move.w d1,preshiftheight ;Store height-1 for loops ;Copy source as our first frame move.l a1,a2 ;Keep pointer as last frame move.w preshiftheight,d0 .loop move.l (a0)+,(a1)+ ;Planes 1+2+3+4 for 48 pixels move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbra.w d0,.loop ;Create preshifts moveq.w #15-1,d3 ;Preshift 15 times .loop2 ;Copy the last frame to our current one move.l a1,a3 move.w preshiftheight,d0 .loop3 move.l (a2)+,(a1)+ ;Copy 48 pixels move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ dbra.w d0,.loop3 move.l a3,a1 ;Shift current image right by 1 pixel move.l a1,a2 ;Store pointer as last frame move.w preshiftheight,d2 .loop4 moveq.w #4-1,d0 ;Shift Planes 1+2+3+4 .loop5 move.w 16(a1),d1 ;Wrap pixel on far right back to start using X bit roxr.w #1,d1 roxr.w (a1) roxr.w 8(a1) roxr.w 16(a1) addq.w #2,a1 ;Next plane dbra.w d0,.loop5 lea 24-8(a1),a1 ;Next line dbra.w d2,.loop4 dbra.w d3,.loop2 rts ;---------------------------------- ;Preshift 48 pixel wide pipe sprite, pass d0.w as height, a0.l as source, a1.l as preshift destination preshiftcalcpipespr move.w d0,d1 subq.w #1,d1 move.w d1,preshiftheight ;Store height-1 for loops ;Copy source as our first frame move.l a1,a2 ;Keep pointer as last frame move.w preshiftheight,d0 .loop move.l (a0)+,(a1)+ ;Mask and Planes 1+2+3+4 for 48 pixels move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbra.w d0,.loop ;Create preshifts moveq.w #15-1,d3 ;Preshift 15 times .loop2 ;Copy the last frame to our current one move.l a1,a3 move.w preshiftheight,d0 .loop3 move.l (a2)+,(a1)+ ;Copy 48 pixels move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ move.l (a2)+,(a1)+ dbra.w d0,.loop3 move.l a3,a1 ;Shift current image right by 1 pixel move.l a1,a2 ;Store pointer as last frame move.w preshiftheight,d2 .loop4 moveq.w #6-1,d0 ;Shift Mask and Planes 1+2+3+4 .loop5 move.w 24(a1),d1 ;Wrap pixel on far right back to start using X bit roxr.w #1,d1 roxr.w (a1) roxr.w 12(a1) roxr.w 24(a1) addq.w #2,a1 ;Next plane dbra.w d0,.loop5 lea 36-12(a1),a1 ;Next line dbra.w d2,.loop4 dbra.w d3,.loop2 rts ;---------------------------------- ;Preshift pipe with sky, pass d0.w as height, a0.l as pipe source, a1.l as sky source and a2.l as preshift destination preshiftcalcpipesky move.w d0,d2 subq.w #1,d2 move.w d2,preshiftheight ;Store height-1 for loops move.w d0,d2 lsl.w #3,d2 ;*8 move.w d2,d3 add.w d3,d3 ;*16 add.w d3,d2 ;=*24 move.w d2,preshiftsize ;Store size of one preshift, 24*height moveq.w #8,d5 ;Start X offset in sky subq.w #1,d1 ;Number of copies-1 for loop .loopy move.w d1,-(sp) ;Copy pipesky as Mask long+Planes 1+2+3+4 for 48 pixels to workspace lea preshiftpipesky,a3 move.l (a0)+,(a3)+ ;48 pixels Mask and Planes 1+2+3+4 move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ move.l (a0)+,(a3)+ sub.w #36,a0 moveq.w #16-1,d7 ;16 preshifts .loop move.w d5,-(sp) move.l a2,-(sp) lea preshiftpipesky,a3 moveq.w #3-1,d6 ;Write out 48 pixels .loop1 move.l (a3)+,d0 ;Mask move.l (a3)+,d1 ;Planes 1+2 move.l (a3)+,d2 ;Planes 3+4 addq.w #8,d5 ;Next 16 pixels in sky source and.w #63,d5 ;Wrap sky on pixels 0...128 ;Output vertical line of sky movem.l d6/a1-a2,-(sp) move.w preshiftheight,d6 .loop2 movem.l (a1,d5.w),d3-d4 ;Sky and.l d0,d3 ;Combine with pipe and.l d0,d4 or.l d1,d3 or.l d2,d4 movem.l d3-d4,(a2) ;Write output lea 80(a1),a1 ;Next sky line lea 24(a2),a2 ;Next output line dbra.w d6,.loop2 movem.l (sp)+,d6/a1-a2 addq.w #8,a2 ;Move to next 16 pixels in output dbra.w d6,.loop1 move.l (sp)+,a2 move.w (sp)+,d5 add.w preshiftsize,a2 ;Next destination preshift ;Shift pipe source right by one pixel lea preshiftpipesky,a3 moveq.w #6-1,d0 ;Shift Mask and Planes 1+2+3+4 .loop3 move.w 24(a3),d1 ;Wrap pixel on far right back to start using X bit roxr.w #1,d1 roxr.w (a3) roxr.w 12(a3) roxr.w 24(a3) addq.w #2,a3 ;Next plane dbra.w d0,.loop3 dbra.w d7,.loop addq.w #8,d5 ;Move to next 16 pixels in sky move.w (sp)+,d1 dbra.w d1,.loopy rts ;---------------------------------- SECTION BSS preshiftheight ds.w 1 ;Height-1 of preshift preshiftsize ds.w 1 ;Size in bytes of a single preshift preshiftpipesky ds.b 36 ;Workspace for shifted pipe column ;Preshifts, total 88672 bytes pipesky3preshift ds.b 24*9*4*16 ;48x8 pixels, 13824 bytes pipesky2preshift ds.b 24*19*2*16 ;48x8 pixels, 14592 bytes pipesky1preshift ds.b 24*11*8*16 ;48x8 pixels, 33792 bytes pipecappreshift ds.b 36*5*16 ;48x5 pixels, 2880 bytes pipebottompreshift ds.b 24*5*16 ;48x5 pixels, 1920 bytes pipetoppreshift ds.b 24*6*16 ;48x6 pixels, 2304 bytes sparklepreshift ds.b 60*3*8 ;3 sparkles preshifted 8 times, total 1440 bytes scoresmallpreshift ds.b 80*10*8 ;10 digits preshifted 8 times, total 6400 bytes scorelargepreshift ds.b 144*10*8 ;10 digits preshifted 8 times, total 11520 bytes EVEN  ;Routines to handler Timer B colour palette effects ;Timer B is allowed to interrupt IKBD and also the sound running on Timer D ;As MOVEM can delay the execution of the Timer B vector (causing a glitch in the sky) ;we sync the game loop to the last Timer B rather than the VBL allowing the code to ;run and complete before the starting Timer B on the next retrace ;NOTE - we need to keep Timer C running (for TOS 2.06 or later) but it causes a glitch ;in the sky as the Timer B vector is delayed so we disable the timer for the duration of ;our Timer B raster effects and then enable it again RASTERSET_BLACKOUT = 0 ;List of different raster effect settings RASTERSET_TITLE = 1 RASTERSET_GETREADY = 2 RASTERSET_GAME = 3 RASTERSET_MEDAL = 4 SKYDAY1 = $137 ;Sky day RGB raster colours SKYDAY2 = $147 SKYDAY3 = $157 SKYDAY4 = $167 SKYDAY5 = $177 SKYNIGHT1 = $017 ;Sky night SKYNIGHT2 = $027 SKYNIGHT3 = $037 SKYNIGHT4 = $047 SKYNIGHT5 = $057 SKYBRIGHT = $080 ;STe enhanced palette bit for sky SECTION TEXT ;---------------------------------- ;Initialise Timer B palette raster effects rastersinit move.l #0,timerbhandler ;Clear Timer B VBL handler move.b $fffffa1d.w,d0 ;Read Timer C+D Control and.b #$70,d0 ;Keep just Timer C control bits 4-6 move.b d0,rastertimerccontrol rts ;---------------------------------- ;End Timer B rasterendtimerb addq.l #1,blankingcount ;Increment Display Blanking counter move.b #0,$fffffa1b.w ;Stop Timer B bclr #0,$fffffa0f.w ;Clear bit 0 (TimerB) in Interrupt In-Service A move.w d0,-(sp) move.b rastertimerccontrol,d0 or.b d0,$fffffa1d.w ;Start Timer C in Timer C+D Control move.w (sp)+,d0 rte ;---------------------------------- ;Sky skyhandler and.b #$8f,$fffffa1d.w ;Stop Timer C in Timer C+D Control so cannot trigger during effects cmp.w #RASTERSET_BLACKOUT,rasterset bne.s .noblackout moveq.l #0,d0 ;We're safe to corrupt d0 and a0 in this handler lea $ffff8240.w,a0 move.l d0,(a0)+ ;Black out entire palette move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.b #0,$fffffa1b.w ;Stop Timer B to set new count move.l #rasterendtimerb,$120.w ;Set new Timer B vector move.b #161,$fffffa21.w ;Set Timer B Data with lines to count bra.s .starttimerb .noblackout move.w skydaynight,d0 ;Set sky day or night rasters bne.s .nightsky move.l #skyday1,$120.w ;Set new Timer B vector move.w #SKYDAY1,$ffff8242.w ;Reset palette (not index 0) bra.s .daysky .nightsky move.l #skynight1,$120.w move.w #SKYNIGHT1,$ffff8242.w .daysky move.l #$07770444,$ffff8244.w ;Set game palette move.l #$01200240,$ffff8248.w move.l #$03610774,$ffff824c.w move.l #$00300161,$ffff8250.w move.l #$07000721,$ffff8254.w move.l birdpalette,$ffff8258.w move.l birdpalette+4,$ffff825c.w move.b #0,$fffffa1b.w ;Stop Timer B to set new count move.b #7,$fffffa21.w ;Set Timer B Data with lines to count .starttimerb move.b #8,$fffffa1b.w ;Set Timer B for Event Count Mode bset #0,$fffffa07.w ;Enable Timer B in Interrupt Enable A bset #0,$fffffa13.w ;Mask Timer B in Interrupt Mask A rts ;---------------------------------- ;Set next Timer B vector and line count RASTERSET MACRO move.b #0,$fffffa1b.w ;Stop Timer B to set new count move.l \1,$120.w ;Set new Timer B vector move.b #\2,$fffffa21.w ;Set Timer B Data with lines to count move.b #8,$fffffa1b.w ;Set Timer B for Event Count Mode bclr #0,$fffffa0f.w ;Clear bit 0 (TimerB) in Interrupt In-Service A ENDM ;---------------------------------- ;Sky day skyday1 ;Line 7, 'Game Over' move.w #SKYDAY1+SKYBRIGHT,$ffff8242.w cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal1 move.l #$06100740,$ffff8250.w ;Dark orange, index 8 and Orange, index 9 move.l #$07770777,$ffff8254.w ;White, index 10 and White, index 11 .nomedal1 RASTERSET #skyday2,1 rte skyday2 ;Line 8 move.w #SKYDAY1,$ffff8242.w RASTERSET #skyday3,1 rte skyday3 ;Line 9 move.w #SKYDAY1+SKYBRIGHT,$ffff8242.w RASTERSET #skyday4,19 rte skyday4 ;Line 28 move.w #SKYDAY2,$ffff8242.w RASTERSET #skyday5,1 rte skyday5 ;Line 29 move.w #SKYDAY1+SKYBRIGHT,$ffff8242.w RASTERSET #skyday6,1 rte skyday6 ;Line 30 move.w #SKYDAY2,$ffff8242.w RASTERSET #skyday7,16 rte skyday7 ;Line 46 move.w #SKYDAY2+SKYBRIGHT,$ffff8242.w RASTERSET #skyday8,1 rte skyday8 ;Line 47, 'Medal' move.w #SKYDAY2,$ffff8242.w cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal2 move.l #$06630552,$ffff8250.w ;Beige, index 8 and Dark beige, index 9 move.l #$07000721,$ffff8254.w ;Red, index 10 and Light red, index 11 move.l medalpalette,$ffff8258.w move.l medalpalette+4,$ffff825c.w .nomedal2 RASTERSET #skyday9,1 rte skyday9 ;Line 48 move.w #SKYDAY2+SKYBRIGHT,$ffff8242.w RASTERSET #skyday10,14 rte skyday10 ;Line 62 move.w #SKYDAY3,$ffff8242.w RASTERSET #skyday11,1 rte skyday11 ;Line 63 move.w #SKYDAY2+SKYBRIGHT,$ffff8242.w RASTERSET #skyday12,1 rte skyday12 ;Line 64 move.w #SKYDAY3,$ffff8242.w RASTERSET #skyday13,12 rte skyday13 ;Line 76 move.w #SKYDAY3+SKYBRIGHT,$ffff8242.w RASTERSET #skyday14,1 rte skyday14 ;Line 77 move.w #SKYDAY3,$ffff8242.w RASTERSET #skyday15,1 rte skyday15 ;Line 78 move.w #SKYDAY3+SKYBRIGHT,$ffff8242.w cmp.w #RASTERSET_GETREADY,rasterset bne.s .nofiretoflap move.w #$0700,$ffff8254.w ;Red, index 10 .nofiretoflap RASTERSET #skyday16,9 rte skyday16 ;Line 87 move.w #SKYDAY4,$ffff8242.w RASTERSET #skyday17,1 rte skyday17 ;Line 88 move.w #SKYDAY3+SKYBRIGHT,$ffff8242.w RASTERSET #skyday18,1 rte skyday18 ;Line 89 move.w #SKYDAY4,$ffff8242.w RASTERSET #skyday19,8 rte skyday19 ;Line 97 move.w #SKYDAY4+SKYBRIGHT,$ffff8242.w RASTERSET #skyday20,1 rte skyday20 ;Line 98 move.w #SKYDAY4,$ffff8242.w RASTERSET #skyday21,1 rte skyday21 ;Line 99 move.w #SKYDAY4+SKYBRIGHT,$ffff8242.w RASTERSET #skyday22,7 rte skyday22 ;Line 106 move.w #SKYDAY5,$ffff8242.w RASTERSET #skyday23,1 rte skyday23 ;Line 107 move.w #SKYDAY4+SKYBRIGHT,$ffff8242.w RASTERSET #skyday24,1 rte skyday24 ;Line 108, 'Sky' move.w #SKYDAY5,$ffff8242.w cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal3 move.l birdpalette,$ffff8258.w ;Reset bird palette under medal move.l birdpalette+4,$ffff825c.w .nomedal3 RASTERSET #skyday25,17 rte skyday25 ;Line 125 move.w #$262,$ffff8242.w ;Light green, index 1 move.l #$03660565,$ffff8250.w ;Blue, index 8 and Light blue, index 9 move.l #$06750252,$ffff8254.w ;Grey, index 10 and Dark green, index 11 RASTERSET #skyday26,16 rte skyday26 ;Line 141 RASTERSET #skyday27,20 rte skyday27 ;Line 161, 'Floor' move.l #$02400361,$ffff8250.w ;Green, index 8 and Light green, index 9 move.l #$05310663,$ffff8254.w ;Dark beige, index 10 and Beige, index 11 addq.l #1,blankingcount ;Increment Display Blanking counter move.b #0,$fffffa1b.w ;Stop Timer B bclr #0,$fffffa0f.w ;Clear bit 0 (TimerB) in Interrupt In-Service A rte ;---------------------------------- ;Sky night skynight1 ;Line 7, 'Game Over' move.w #SKYNIGHT1+SKYBRIGHT,$ffff8242.w cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal1 move.l #$06100740,$ffff8250.w ;Dark orange, index 8 and Orange, index 9 move.l #$07770777,$ffff8254.w ;White, index 10 and White, index 11 .nomedal1 RASTERSET #skynight2,1 rte skynight2 ;Line 8 move.w #SKYNIGHT1,$ffff8242.w RASTERSET #skynight3,1 rte skynight3 ;Line 9 move.w #SKYNIGHT1+SKYBRIGHT,$ffff8242.w RASTERSET #skynight4,19 rte skynight4 ;Line 28 move.w #SKYNIGHT2,$ffff8242.w RASTERSET #skynight5,1 rte skynight5 ;Line 29 move.w #SKYNIGHT1+SKYBRIGHT,$ffff8242.w RASTERSET #skynight6,1 rte skynight6 ;Line 30 move.w #SKYNIGHT2,$ffff8242.w RASTERSET #skynight7,16 rte skynight7 ;Line 46 move.w #SKYNIGHT2+SKYBRIGHT,$ffff8242.w RASTERSET #skynight8,1 rte skynight8 ;Line 47, 'Medal' move.w #SKYNIGHT2,$ffff8242.w cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal2 move.l #$06630552,$ffff8250.w ;Beige, index 8 and Dark beige, index 9 move.l #$07000721,$ffff8254.w ;Red, index 10 and Light red, index 11 move.l medalpalette,$ffff8258.w move.l medalpalette+4,$ffff825c.w .nomedal2 RASTERSET #skynight9,1 rte skynight9 ;Line 48 move.w #SKYNIGHT2+SKYBRIGHT,$ffff8242.w RASTERSET #skynight10,14 rte skynight10 ;Line 62 move.w #SKYNIGHT3,$ffff8242.w RASTERSET #skynight11,1 rte skynight11 ;Line 63 move.w #SKYNIGHT2+SKYBRIGHT,$ffff8242.w RASTERSET #skynight12,1 rte skynight12 ;Line 64 move.w #SKYNIGHT3,$ffff8242.w RASTERSET #skynight13,12 rte skynight13 ;Line 76 move.w #SKYNIGHT3+SKYBRIGHT,$ffff8242.w RASTERSET #skynight14,1 rte skynight14 ;Line 77 move.w #SKYNIGHT3,$ffff8242.w RASTERSET #skynight15,1 rte skynight15 ;Line 78 move.w #SKYNIGHT3+SKYBRIGHT,$ffff8242.w cmp.w #RASTERSET_GETREADY,rasterset bne.s .nofiretoflap move.w #$0700,$ffff8254.w ;Red, index 10 .nofiretoflap RASTERSET #skynight16,9 rte skynight16 ;Line 87 move.w #SKYNIGHT4,$ffff8242.w RASTERSET #skynight17,1 rte skynight17 ;Line 88 move.w #SKYNIGHT3+SKYBRIGHT,$ffff8242.w RASTERSET #skynight18,1 rte skynight18 ;Line 89 move.w #SKYNIGHT4,$ffff8242.w RASTERSET #skynight19,8 rte skynight19 ;Line 97 move.w #SKYNIGHT4+SKYBRIGHT,$ffff8242.w RASTERSET #skynight20,1 rte skynight20 ;Line 98 move.w #SKYNIGHT4,$ffff8242.w RASTERSET #skynight21,1 rte skynight21 ;Line 99 move.w #SKYNIGHT4+SKYBRIGHT,$ffff8242.w RASTERSET #skynight22,7 rte skynight22 ;Line 106 move.w #SKYNIGHT5,$ffff8242.w RASTERSET #skynight23,1 rte skynight23 ;Line 107 move.w #SKYNIGHT4+SKYBRIGHT,$ffff8242.w RASTERSET #skynight24,1 rte skynight24 ;Line 108, 'Sky' move.w #SKYNIGHT5,$ffff8242.w move.w #$167,$ffff8256.w ;Sky blue, index 11 cmp.w #RASTERSET_MEDAL,rasterset bne.s .nomedal3 move.l birdpalette,$ffff8258.w ;Reset bird palette under medal move.l birdpalette+4,$ffff825c.w .nomedal3 RASTERSET #skynight25,17 rte skynight25 ;Line 125 move.w #$050,$ffff8242.w ;Dark green, index 1 move.l #$00340770,$ffff8250.w ;Dark blue, index 8 and Yellow, index 9 move.w #$045,$ffff8254.w ;Light blue, index 10 RASTERSET #skynight26,16 rte skynight26 ;Line 141 move.w #$0060,$ffff8256.w ;Light green, index 11 RASTERSET #skynight27,20 rte skynight27 ;Line 161, 'Floor' move.l #$02400361,$ffff8250.w ;Green, index 8 and Light green, index 9 move.l #$05310663,$ffff8254.w ;Dark beige, index 10 and Beige, index 11 addq.l #1,blankingcount ;Increment Display Blanking counter move.b #0,$fffffa1b.w ;Stop Timer B bclr #0,$fffffa0f.w ;Clear bit 0 (TimerB) in Interrupt In-Service A rte ;---------------------------------- SECTION BSS timerbhandler ds.l 1 ;Address of routine to handle Timer B from VBL (can be 0) rastertimerccontrol ds.b 1 ;MFP Timer C control bits 4-6 EVEN ;Draw large score font SECTION TEXT ;---------------------------------- ;Return pixel length of score in d0.w, pass 32-bit BCD value in d1.l scorelargelength moveq.w #0,d0 ;Length in pixels move.l d1,d2 ;Scan to skip leading zeroes moveq.w #8-1,d4 ;Check all 8 digits .loop rol.l #4,d2 move.w d2,d3 and.w #$f,d3 ;Get BCD digit bne.s .start ;Start with first non-zero digit dbra.w d4,.loop moveq.w #10,d0 ;Score is 0 rts ;Return length of '0' digit ;Loop and total width of each digit .loop2 rol.l #4,d2 move.w d2,d3 and.w #$f,d3 ;Get BCD digit .start add.w #10,d0 ;Each digit has width of 10 pixels cmp.w #1,d3 ;Except '1' which is just 6 pixels bne.s .notone subq.w #4,d0 .notone dbra.w d4,.loop2 rts ;---------------------------------- ;Draw line of large score font, 156 cycles SCORELARGELINE MACRO movem.w (a2)+,d4-d7 ;28 ;Using words is same speed as reading 32-bit mask to use and.l and.w d4,(a1)+ ;12 and.w d4,(a1) ;12 or.w d5,(a1)+ ;12 and.w d4,(a1)+ ;12 and.w d4,(a1)+ ;12 and.w d6,(a1)+ ;12 and.w d6,(a1) ;12 or.w d7,(a1)+ ;12 and.w d6,(a1)+ ;12 and.w d6,(a1) ;12 lea 160-14(a1),a1 ;8 ENDM ;---------------------------------- ;Draw large score, pass d0.w as screen X, d1.l as 32-bit BCD and a0.l as screen address drawscorelarge ;Scan to skip leading zeroes moveq.w #8-1,d2 ;4 ;Draw all 8 digits .loop rol.l #4,d1 ;16 move.w d1,d3 ;4 and.w #$f,d3 ;8 ;Get BCD digit bne.s .start ;10/8 ;Found first non-zero digit dbra.w d2,.loop ;10/14 moveq.w #1-1,d2 ;4 ;Set loop to draw single digit moveq.l #0,d1 ;4 ;Score is 0 ;Loop and draw digits .loop2 rol.l #4,d1 ;16 move.w d1,d3 ;4 and.w #$f,d3 ;8 ;Get BCD digit .start moveq.w #10,d4 ;4 ;Each digit has width of 10 pixels cmp.w #1,d3 ;8 ;Except '1' which is just 6 pixels bne.s .notone ;10/8 moveq.w #6,d4 ;4 .notone lsl.w #4,d3 ;16 ;*16 for index move.w d0,d5 ;4 ;Copy X and.w #$e,d5 ;8 ;Mask so X is 0...15 and always even add.w d5,d3 ;4 lea scorelargepreshift,a2 ;12 lea largepreshifttbl,a3 ;12 add.w (a3,d3.w),a2 ;20 ;Preshifted source move.w d0,d5 ;4 ;Copy X lsr.w #1,d5 ;8 and.w #$fff8,d5 ;8 ;Offset for X lea 0(a0,d5.w),a1 ;12 ;Screen destination add.w d4,d0 ;4 ;Offset X by width of digit REPT 18 SCORELARGELINE ;156 ;Draw lines of digit, 2808 cycles ENDR dbra.w d2,.loop2 ;10/14 rts ;---------------------------------- SECTION DATA largepreshifttbl ;Index table into preshifted font dc.w (0*1152)+(144*0) ;0 dc.w (0*1152)+(144*1) dc.w (0*1152)+(144*2) dc.w (0*1152)+(144*3) dc.w (0*1152)+(144*4) dc.w (0*1152)+(144*5) dc.w (0*1152)+(144*6) dc.w (0*1152)+(144*7) dc.w (1*1152)+(144*0) ;1 dc.w (1*1152)+(144*1) dc.w (1*1152)+(144*2) dc.w (1*1152)+(144*3) dc.w (1*1152)+(144*4) dc.w (1*1152)+(144*5) dc.w (1*1152)+(144*6) dc.w (1*1152)+(144*7) dc.w (2*1152)+(144*0) ;2 dc.w (2*1152)+(144*1) dc.w (2*1152)+(144*2) dc.w (2*1152)+(144*3) dc.w (2*1152)+(144*4) dc.w (2*1152)+(144*5) dc.w (2*1152)+(144*6) dc.w (2*1152)+(144*7) dc.w (3*1152)+(144*0) ;3 dc.w (3*1152)+(144*1) dc.w (3*1152)+(144*2) dc.w (3*1152)+(144*3) dc.w (3*1152)+(144*4) dc.w (3*1152)+(144*5) dc.w (3*1152)+(144*6) dc.w (3*1152)+(144*7) dc.w (4*1152)+(144*0) ;4 dc.w (4*1152)+(144*1) dc.w (4*1152)+(144*2) dc.w (4*1152)+(144*3) dc.w (4*1152)+(144*4) dc.w (4*1152)+(144*5) dc.w (4*1152)+(144*6) dc.w (4*1152)+(144*7) dc.w (5*1152)+(144*0) ;5 dc.w (5*1152)+(144*1) dc.w (5*1152)+(144*2) dc.w (5*1152)+(144*3) dc.w (5*1152)+(144*4) dc.w (5*1152)+(144*5) dc.w (5*1152)+(144*6) dc.w (5*1152)+(144*7) dc.w (6*1152)+(144*0) ;6 dc.w (6*1152)+(144*1) dc.w (6*1152)+(144*2) dc.w (6*1152)+(144*3) dc.w (6*1152)+(144*4) dc.w (6*1152)+(144*5) dc.w (6*1152)+(144*6) dc.w (6*1152)+(144*7) dc.w (7*1152)+(144*0) ;7 dc.w (7*1152)+(144*1) dc.w (7*1152)+(144*2) dc.w (7*1152)+(144*3) dc.w (7*1152)+(144*4) dc.w (7*1152)+(144*5) dc.w (7*1152)+(144*6) dc.w (7*1152)+(144*7) dc.w (8*1152)+(144*0) ;8 dc.w (8*1152)+(144*1) dc.w (8*1152)+(144*2) dc.w (8*1152)+(144*3) dc.w (8*1152)+(144*4) dc.w (8*1152)+(144*5) dc.w (8*1152)+(144*6) dc.w (8*1152)+(144*7) dc.w (9*1152)+(144*0) ;9 dc.w (9*1152)+(144*1) dc.w (9*1152)+(144*2) dc.w (9*1152)+(144*3) dc.w (9*1152)+(144*4) dc.w (9*1152)+(144*5) dc.w (9*1152)+(144*6) dc.w (9*1152)+(144*7) ;Draw small score font SECTION TEXT ;---------------------------------- ;Return pixel length of score in d0.w, pass 32-bit BCD value in d1.l scoresmalllength moveq.w #0,d0 ;Length in pixels move.l d1,d2 ;Scan to skip leading zeroes moveq.w #8-1,d4 ;Check all 8 digits .loop rol.l #4,d2 move.w d2,d3 and.w #$f,d3 ;Get BCD digit bne.s .start ;Start with first non-zero digit dbra.w d4,.loop moveq.w #6,d0 ;Score is 0 rts ;Return length of '0' digit ;Loop and total width of each digit .loop2 rol.l #4,d2 move.w d2,d3 and.w #$f,d3 ;Get BCD digit .start addq.w #6,d0 ;Each digit has width of 6 pixels cmp.w #1,d3 ;Except '1' which is just 4 pixels bne.s .notone subq.w #2,d0 .notone dbra.w d4,.loop2 rts ;---------------------------------- ;Draw line of small score font, 92 cycles SCORESMALLLINE MACRO movem.w (a2)+,d4-d7 ;28 or.w d5,\1+2(a1) ;16 ;Write on background colour 8 and.w d4,\1+6(a1) ;16 or.w d7,\1+10(a1) ;16 and.w d6,\1+14(a1) ;16 ENDM ;---------------------------------- ;Draw small score, pass d0.w as screen X, d1.l as 32-bit BCD and a0.l as screen address drawscoresmall ;Scan to skip leading zeroes moveq.w #8-1,d2 ;4 ;Draw all 8 digits .loop rol.l #4,d1 ;16 move.w d1,d3 ;4 and.w #$f,d3 ;8 ;Get BCD digit bne.s .start ;10/8 ;Found first non-zero digit dbra.w d2,.loop ;10/14 moveq.w #1-1,d2 ;4 ;Set loop to draw single digit moveq.l #0,d1 ;4 ;Score is 0 ;Loop and draw digits .loop2 rol.l #4,d1 ;16 move.w d1,d3 ;4 and.w #$f,d3 ;8 ;Get BCD digit .start moveq.w #6,d4 ;4 ;Each digit has width of 6 pixels cmp.w #1,d3 ;8 ;Except '1' which is just 4 pixels bne.s .notone ;10/8 moveq.w #4,d4 ;4 .notone lsl.w #4,d3 ;16 ;*16 for index move.w d0,d5 ;4 ;Copy X and.w #$e,d5 ;8 ;Mask so X is 0...15 and always even add.w d5,d3 ;4 lea scoresmallpreshift,a2 ;12 lea smallpreshifttbl,a3 ;12 add.w (a3,d3.w),a2 ;20 ;Preshifted source move.w d0,d5 ;4 ;Copy X lsr.w #1,d5 ;8 and.w #$fff8,d5 ;8 ;Offset for X lea 0(a0,d5.w),a1 ;12 ;Screen destination add.w d4,d0 ;4 ;Offset X by width of digit SCORESMALLLINE 160*0 ;92 ;Draw lines of digit, 920 cycles SCORESMALLLINE 160*1 SCORESMALLLINE 160*2 SCORESMALLLINE 160*3 SCORESMALLLINE 160*4 SCORESMALLLINE 160*5 SCORESMALLLINE 160*6 SCORESMALLLINE 160*7 SCORESMALLLINE 160*8 SCORESMALLLINE 160*9 dbra.w d2,.loop2 ;10/14 rts ;---------------------------------- SECTION DATA smallpreshifttbl ;Index table into preshifted font dc.w (0*640)+(80*0) ;0 dc.w (0*640)+(80*1) dc.w (0*640)+(80*2) dc.w (0*640)+(80*3) dc.w (0*640)+(80*4) dc.w (0*640)+(80*5) dc.w (0*640)+(80*6) dc.w (0*640)+(80*7) dc.w (1*640)+(80*0) ;1 dc.w (1*640)+(80*1) dc.w (1*640)+(80*2) dc.w (1*640)+(80*3) dc.w (1*640)+(80*4) dc.w (1*640)+(80*5) dc.w (1*640)+(80*6) dc.w (1*640)+(80*7) dc.w (2*640)+(80*0) ;2 dc.w (2*640)+(80*1) dc.w (2*640)+(80*2) dc.w (2*640)+(80*3) dc.w (2*640)+(80*4) dc.w (2*640)+(80*5) dc.w (2*640)+(80*6) dc.w (2*640)+(80*7) dc.w (3*640)+(80*0) ;3 dc.w (3*640)+(80*1) dc.w (3*640)+(80*2) dc.w (3*640)+(80*3) dc.w (3*640)+(80*4) dc.w (3*640)+(80*5) dc.w (3*640)+(80*6) dc.w (3*640)+(80*7) dc.w (4*640)+(80*0) ;4 dc.w (4*640)+(80*1) dc.w (4*640)+(80*2) dc.w (4*640)+(80*3) dc.w (4*640)+(80*4) dc.w (4*640)+(80*5) dc.w (4*640)+(80*6) dc.w (4*640)+(80*7) dc.w (5*640)+(80*0) ;5 dc.w (5*640)+(80*1) dc.w (5*640)+(80*2) dc.w (5*640)+(80*3) dc.w (5*640)+(80*4) dc.w (5*640)+(80*5) dc.w (5*640)+(80*6) dc.w (5*640)+(80*7) dc.w (6*640)+(80*0) ;6 dc.w (6*640)+(80*1) dc.w (6*640)+(80*2) dc.w (6*640)+(80*3) dc.w (6*640)+(80*4) dc.w (6*640)+(80*5) dc.w (6*640)+(80*6) dc.w (6*640)+(80*7) dc.w (7*640)+(80*0) ;7 dc.w (7*640)+(80*1) dc.w (7*640)+(80*2) dc.w (7*640)+(80*3) dc.w (7*640)+(80*4) dc.w (7*640)+(80*5) dc.w (7*640)+(80*6) dc.w (7*640)+(80*7) dc.w (8*640)+(80*0) ;8 dc.w (8*640)+(80*1) dc.w (8*640)+(80*2) dc.w (8*640)+(80*3) dc.w (8*640)+(80*4) dc.w (8*640)+(80*5) dc.w (8*640)+(80*6) dc.w (8*640)+(80*7) dc.w (9*640)+(80*0) ;9 dc.w (9*640)+(80*1) dc.w (9*640)+(80*2) dc.w (9*640)+(80*3) dc.w (9*640)+(80*4) dc.w (9*640)+(80*5) dc.w (9*640)+(80*6) dc.w (9*640)+(80*7) ;Sky SECTION TEXT ;---------------------------------- ;Initialise sky skyinit move.w #0,skydaynight ;Always start with day sky move.l #skydayimg,skyimg bra skycreatepreshift ;(does RTS) ;---------------------------------- ;Create random sky skyrandomsky bsr utilrandbyte ;Get random value in d0.b and.w #3,d0 ;25% chance of night sky beq.s .nightsky move.w #0,skydaynight move.l #skydayimg,skyimg bra skycreatepreshift ;(does RTS) .nightsky move.w #1,skydaynight move.l #skynightimg,skyimg bra skycreatepreshift ;(does RTS) ;---------------------------------- ;Create sky preshifts combined with pipe column skycreatepreshift moveq.w #11,d0 ;Height moveq.w #8,d1 ;Number of copies (ie repeat) lea pipeskyspr,a0 ;Source pipe column sprite move.l skyimg,a1 ;Source sky lea 80*17(a1),a1 ;Starting line for clouds lea pipesky1preshift,a2 ;Destination preshift bsr preshiftcalcpipesky moveq.w #19,d0 moveq.w #2,d1 lea pipeskyspr,a0 move.l skyimg,a1 lea 80*28(a1),a1 lea pipesky2preshift,a2 bsr preshiftcalcpipesky moveq.w #9,d0 moveq.w #4,d1 lea pipeskyspr,a0 move.l skyimg,a1 lea 80*47(a1),a1 lea pipesky3preshift,a2 bra preshiftcalcpipesky ;(does RTS) ;---------------------------------- SECTION BSS skydaynight ds.w 1 ;0 for day, 1 for night skyimg ds.l 1 ;Sky image, ie skydayimg or skynightimg ;Sound interrupt using Timer D ;Uses Timer D, rather than the normal Timer A, as this has a lower priority on the MFP allowing Timer B ;to interrupt the routine as palette effects are more important/visible ;NOTE - the timer handler uses move.w #$2500,sr to allow higher priority MFP interrupts to run (ie Timer B) ;NOTE - some sound players use MOVEM to access mirror registers after $ff8800/$ff8802 but these do not exist ;on all machines so we must access the hardware byte registers correctly ;NOTE - ensure PSG register #7 always leaves PortA+B set as output otherwise disc access is disabled ENABLESOUND = 1 ;Set to 1 to enable sound SECTION TEXT ;---------------------------------- ;Set sound interrupt on 50Hz Timer D soundinit moveq.l #0,d0 move.l d0,soundsfx0 move.l d0,soundsfx1 IFGT ENABLESOUND move.w #$2700,sr ;Disable interrupts bclr.b #4,$fffffa0d.w ;Clear Timer D in Interrupt Pending B move.l #inttimerd,$110.w ;Set new Timer D vector and.b #$f8,$fffffa1d.w ;Set Timer D for Delay Mode Div 200 (ie 50Hz) or.b #$07,$fffffa1d.w bset.b #4,$fffffa09.w ;Enable Timer D in Interrupt Enable B move.b #245,$fffffa25.w ;Set Timer D Data as close to 50Hz as we can get bset.b #4,$fffffa15.w ;Mask Timer D in Interrupt Mask B move.w #$2300,sr ;Enable interrupts ENDC rts ;---------------------------------- ;Stop all sounds on exit soundstopall move.b #7,$ffff8800.w move.b #$ff,$ffff8802.w ;Turn off all channels, ensure PortA+B are set as output rts ;---------------------------------- ;Timer D sound interrupt handler inttimerd move.w #$2500,sr ;Allow higher priority MFP Timer B interrupt this routine IFGT ENABLESOUND movem.l d0/a0-a2,-(sp) ;40 lea $ffff8800.w,a1 ;8 ;PSG register lea 2(a1),a2 ;8 ;PSG value move.l soundsfx0,d0 ;20 ;Read sound data pointer beq.s .nosound0 ;10/8 ;Do have playing sound? move.l d0,a0 ;4 bsr soundsetpsg ;20 ;Set PSG values move.l a0,soundsfx0 ;20 ;Update playing sound pointer (set to 0 if finished) .nosound0 move.l soundsfx1,d0 beq.s .nosound1 move.l d0,a0 bsr soundsetpsg move.l a0,soundsfx1 .nosound1 movem.l (sp)+,d0/a0-a2 ;44 ENDC bclr.b #4,$fffffa11.w ;Clear bit 4 (Timer D) in Interrupt In-Service B rte ;---------------------------------- ;Set PSG registers from sound data, pass a0.l as sound data and return a0.l (0 if sound has finished) soundsetpsg moveq.w #0,d0 ;4 move.b (a0)+,d0 ;8 ;Jump table offset jmp .setpsg(pc,d0.w) ;16 ;Jump ahead into unrolled loop .setpsg move.b (a0)+,(a1) ;12 ;PSG register move.b (a0)+,(a2) ;12 ;PSG value move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0)+,(a1) move.b (a0)+,(a2) move.b (a0),d0 ;8 ;Jump table offset for next frame beq.s .soundend ;10/8 ;Has reached end of sound? rts .soundend move.l #0,a0 ;12 ;Return zero rts ;---------------------------------- ;Play sound in slot 0, pass a0.l as sound data to play soundplay0 move.l a0,soundsfx0 ;Store pointer to be picked up safely by interrupt rts ;---------------------------------- ;Play sound in slot 1, pass a0.l as sound data to play soundplay1 move.l a0,soundsfx1 rts ;---------------------------------- SECTION DATA ;Sound effects hitsfx dc.b 32, 4,$84,5,$08,6,$03,7,$F1,8,$0D,10,$0F dc.b 44, 4,$DE,6,$0C,8,$0F dc.b 36, 4,$38,5,$09,6,$14,8,$0E,10,$0E dc.b 40, 4,$92,6,$1D,8,$0D,10,$0D dc.b 40, 4,$EC,6,$06,8,$0C,10,$0C dc.b 40, 4,$46,5,$0A,6,$0F,8,$0A dc.b 40, 4,$A0,6,$17,8,$09,10,$0B dc.b 40, 4,$FA,6,$00,8,$08,10,$0A dc.b 36, 4,$54,5,$0B,6,$09,8,$07,10,$09 dc.b 44, 4,$AE,6,$12,8,$05 dc.b 36, 4,$08,5,$0C,6,$1A,8,$04,10,$08 dc.b 40, 4,$62,6,$03,8,$03,10,$07 dc.b 40, 4,$BC,6,$0C,8,$02,10,$06 dc.b 40, 4,$16,5,$0D,6,$15,8,$00 dc.b 44, 4,$70,6,$1D,10,$05 dc.b 48, 4,$CA,10,$04 dc.b 44, 4,$24,5,$0E,10,$03 dc.b 52, 4,$7E dc.b 48, 4,$D8,10,$02 dc.b 44, 4,$32,5,$0F,10,$01 dc.b 48, 4,$8C,10,$00 dc.b 0 flapsfx dc.b 40, 6,$1F,7,$F1,8,$02,10,$00 dc.b 52, 8,$04 dc.b 52, 8,$07 dc.b 48, 6,$1C,8,$09 dc.b 52, 8,$0A dc.b 52, 8,$0E dc.b 48, 6,$19,8,$0D dc.b 52, 8,$0C dc.b 52, 8,$0B dc.b 48, 6,$16,8,$0A dc.b 52, 8,$09 dc.b 52, 8,$08 dc.b 48, 6,$13,8,$07 dc.b 52, 8,$06 dc.b 52, 8,$05 dc.b 52, 6,$10 dc.b 56 dc.b 52, 8,$04 dc.b 52, 6,$0C dc.b 52, 8,$03 dc.b 56 dc.b 52, 6,$08 dc.b 52, 8,$02 dc.b 56 dc.b 52, 6,$04 dc.b 52, 8,$01 dc.b 56 dc.b 52, 6,$00 dc.b 56 dc.b 52, 8,$00 dc.b 56 dc.b 0 gameoversfx dc.b 40, 6,$18,7,$F1,8,$02,10,$00 dc.b 48, 6,$19,8,$04 dc.b 48, 6,$18,8,$06 dc.b 48, 6,$17,8,$08 dc.b 48, 6,$16,8,$0A dc.b 48, 6,$15,8,$0D dc.b 56 dc.b 48, 6,$14,8,$0C dc.b 56 dc.b 48, 6,$13,8,$0B dc.b 56 dc.b 48, 6,$12,8,$0A dc.b 56 dc.b 48, 6,$11,8,$09 dc.b 56 dc.b 48, 6,$10,8,$08 dc.b 56 dc.b 48, 6,$0F,8,$07 dc.b 56 dc.b 48, 6,$0E,8,$06 dc.b 56 dc.b 52, 6,$0D dc.b 52, 8,$05 dc.b 52, 6,$0C dc.b 56 dc.b 52, 6,$0B dc.b 56 dc.b 48, 6,$0A,8,$04 dc.b 56 dc.b 52, 6,$09 dc.b 56 dc.b 48, 6,$08,8,$03 dc.b 56 dc.b 52, 6,$07 dc.b 56 dc.b 52, 6,$05 dc.b 56 dc.b 48, 6,$04,8,$02 dc.b 56 dc.b 56 dc.b 52, 6,$03 dc.b 52, 6,$02 dc.b 52, 8,$01 dc.b 52, 6,$01 dc.b 56 dc.b 56 dc.b 56 dc.b 48, 6,$00,8,$00 dc.b 0 pointsfx dc.b 40, 2,$22,3,$00,7,$F1,9,$0D dc.b 48, 2,$3D,9,$0E dc.b 48, 2,$58,9,$0D dc.b 52, 2,$73 dc.b 48, 2,$64,9,$0E dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$0D dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$0C dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$0B dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$0A dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$09 dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$08 dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$07 dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$06 dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$05 dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$04 dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$03 dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$02 dc.b 52, 2,$75 dc.b 52, 2,$64 dc.b 52, 2,$53 dc.b 48, 2,$42,9,$01 dc.b 52, 2,$31 dc.b 52, 2,$42 dc.b 52, 2,$53 dc.b 48, 2,$64,9,$00 dc.b 0 fallsfx dc.b 40, 2,$6C,3,$01,7,$F1,9,$0D dc.b 52, 2,$6E dc.b 52, 2,$7C dc.b 52, 2,$7E dc.b 48, 2,$8C,9,$0C dc.b 52, 2,$8E dc.b 52, 2,$9C dc.b 52, 2,$9E dc.b 48, 2,$AC,9,$0B dc.b 52, 2,$AE dc.b 52, 2,$BC dc.b 52, 2,$BE dc.b 48, 2,$CC,9,$0A dc.b 52, 2,$CE dc.b 52, 2,$DC dc.b 52, 2,$DE dc.b 48, 2,$EC,9,$09 dc.b 52, 2,$EE dc.b 52, 2,$FC dc.b 52, 2,$FE dc.b 44, 2,$0C,3,$02,9,$08 dc.b 52, 2,$0E dc.b 52, 2,$1C dc.b 52, 2,$1E dc.b 48, 2,$2C,9,$07 dc.b 52, 2,$2E dc.b 52, 2,$3C dc.b 52, 2,$3E dc.b 48, 2,$4C,9,$06 dc.b 52, 2,$4E dc.b 52, 2,$5C dc.b 52, 2,$5E dc.b 48, 2,$6C,9,$05 dc.b 52, 2,$6E dc.b 52, 2,$7C dc.b 52, 2,$7E dc.b 48, 2,$8C,9,$04 dc.b 52, 2,$8E dc.b 52, 2,$9C dc.b 52, 2,$9E dc.b 48, 2,$AC,9,$03 dc.b 52, 2,$AE dc.b 52, 2,$BC dc.b 52, 2,$BE dc.b 48, 2,$CC,9,$02 dc.b 52, 2,$CE dc.b 52, 2,$DC dc.b 52, 2,$DE dc.b 48, 2,$EC,9,$01 dc.b 52, 2,$EE dc.b 52, 2,$FC dc.b 52, 2,$FE dc.b 52, 9,$00 dc.b 0 EVEN ;---------------------------------- SECTION BSS soundsfx0 ds.l 1 ;Sound data slots to play if !=0 soundsfx1 ds.l 1 ;Ticker message scrolling across bottom of screen MSGHISCOREOFFSET = 74 ;Offset of '00000000' in ticker message - MUST be even SECTION TEXT ;---------------------------------- ;Initialise ticker tickerinit move.l #tickermsg,currentmsg moveq.w #0,d0 move.b d0,tickergap move.w d0,tickerdelay bra tickerclear ;(does RTS) ;---------------------------------- ;Clear ticker workspace on initialise tickerclear lea ticker,a0 ;Ticker workspace moveq.w #0,d0 move.w #21*7-1,d1 ;Clear 320+16 pixels by 7 lines .loop move.w d0,(a0)+ dbra.w d1,.loop rts ;---------------------------------- ;Set highscore value in ticker message tickersethighscore lea tickermsg,a0 lea MSGHISCOREOFFSET(a0),a0 ;Start of '00000000' in message move.l #$01010101,(a0) ;Blank all 8 digits with empty character move.l #$01010101,4(a0) move.l bcdhighscore,d0 ;Read 32-bit BCD high-score ;Scan to skip leading zeroes moveq.w #8-1,d1 ;Scan all 8 digits .loop rol.l #4,d0 move.w d0,d2 and.w #$f,d2 ;Get BCD digit bne.s .go ;Found first non-zero digit dbra.w d1,.loop move.b #'0'-31,(a0)+ ;Write score '0' rts ;Loop and write digits .loop2 rol.l #4,d0 move.w d0,d2 and.w #$f,d2 ;Get BCD digit .go add.b #'0'-31,d2 move.b d2,(a0)+ ;Write digit dbra.w d1,.loop2 rts ;---------------------------------- ;Update ticker tickerupdate ;~=5 rasters move.w tickerdelay,d0 ;Are we in the middle of a delay? bne.s .delay ;Yes bsr tickerscroll ;Scroll by a pixel bra tickercheck ;Can add character to end of ticker? (does RTS) .delay subq.w #1,tickerdelay ;Count down delay rts ;---------------------------------- ;Check if can add next character at end of ticker tickercheck add.b #1,tickergap ;Add pixel gap after scroll move.l currentmsg,a0 moveq.w #0,d0 move.b (a0),d0 ;Read next character in message beq.s .endmsg ;Check 0 for end of message blt.s .startdelay ;Check <0 for delay move.b fontgaps(pc,d0.w),d1 ;Get gap needed for character cmp.b tickergap,d1 ;Is gap large enough? ble tickeraddchar ;Yes, add character in d0.w (does RTS) rts .endmsg move.l #tickermsg,currentmsg ;Wrap message back to start move.b #0,tickergap bra tickersethighscore ;Update message with new high-score (does RTS) .startdelay addq.l #1,currentmsg ;Skip delay character in message move.w #50*5,tickerdelay ;Delay for 5 seconds move.b #0,tickergap rts ;---------------------------------- fontgaps dc.b 0 dc.b 6,4,8,8,8,8,8,4,5,5,8,8,5,6,4,8 ; ! " # $ % & ' ( ) * + , - . / dc.b 8,5,8,8,8,8,8,8,8,8,4,5,7,6,7,8 ;0 1 2 3 4 5 6 7 8 9 : ; < = > ? dc.b 8,8,8,7,8,8,8,8,8,4,5,8,8,8,8,8 ;@ A B C D E F G H I J K L M N O dc.b 8,8,8,8,8,8,8,8,8,8,8,5,8,5,6,6 ;P Q R S T U V W X Y Z [ \ ] ^ _ dc.b 4,8,8,7,8,8,8,8,8,4,5,8,8,8,8,8 ;` a b c d e f g h i j k l m n o dc.b 8,8,8,8,8,8,8,8,8,8,8,6,4,6,7 ;p q r s t u v w x y z { | } ~ ;---------------------------------- ;Add character in d0.w to ticker tickeraddchar ;248 cycles, 0.5 rasters addq.l #1,currentmsg ;20 ;Skip character in message move.b #0,tickergap ;16 cmp.w #1,d0 ;8 ;Is character a space? ble.s .space ;10/8 ;Yes, skip lea tickerimg,a0 ;12 lsl.w #4,d0 ;16 ;Each character is 16 bytes add.w d0,a0 ;8 ;Source plane lea ticker,a1 ;12 ;Ticker workspace movem.w (a0),d0-d6 ;40 ;Write character or.w d0,(a1) ;12 or.w d1,42*1(a1) ;16 or.w d2,42*2(a1) ;16 or.w d3,42*3(a1) ;16 or.w d4,42*4(a1) ;16 or.w d5,42*5(a1) ;16 or.w d6,42*6(a1) ;16 .space rts ;---------------------------------- ;Scroll single plane ticker workspace by a pixel tickerscroll ;1920 cycles, 3.7 rasters lea ticker,a0 ;12 ;Ticker workspace moveq.w #7-1,d0 ;4 ;Plane workspace is 7 pixels high .loop moveq.w #0,d1 ;4 ;Clear X (faster than using CCR) neg.w d1 ;4 REPT 21 ;252 roxl.w (a0)+ ;Shift plane (stored right to left to allow (a0)+ as faster) ENDR dbra.w d0,.loop ;10/14 rts ;---------------------------------- ;Draw line of ticker to Plane 2, 328 cycles TICKERDRAWLINE MACRO addq.w #2,a0 ;8 ;Skip scroll-in word move.w (a0)+,\1+154(a1) ;16 ;Copy line to Plane 2 (stored right to left) move.w (a0)+,\1+146(a1) ;This is faster than using MOVEM move.w (a0)+,\1+138(a1) move.w (a0)+,\1+130(a1) move.w (a0)+,\1+122(a1) move.w (a0)+,\1+114(a1) move.w (a0)+,\1+106(a1) move.w (a0)+,\1+98(a1) move.w (a0)+,\1+90(a1) move.w (a0)+,\1+82(a1) move.w (a0)+,\1+74(a1) move.w (a0)+,\1+66(a1) move.w (a0)+,\1+58(a1) move.w (a0)+,\1+50(a1) move.w (a0)+,\1+42(a1) move.w (a0)+,\1+34(a1) move.w (a0)+,\1+26(a1) move.w (a0)+,\1+18(a1) move.w (a0)+,\1+10(a1) move.w (a0)+,\1+2(a1) ENDM ;---------------------------------- ;Draw ticker to screen tickerdraw ;2328 cycles, 4.5 rasters lea ticker,a0 ;12 ;Ticker workspace move.l offscreenbse,a1 ;20 TICKERDRAWLINE 160*192 ;328 ;Draw line of ticker to screen Plane 2 TICKERDRAWLINE 160*193 TICKERDRAWLINE 160*194 TICKERDRAWLINE 160*195 TICKERDRAWLINE 160*196 TICKERDRAWLINE 160*197 TICKERDRAWLINE 160*198 rts ;---------------------------------- SECTION BSS currentmsg ds.l 1 ;Pointer to current letter in ticker message tickergap ds.b 1 ;Gap, in pixels, to write in next letter EVEN tickerdelay ds.w 1 ;Delay countdown, in frames, when !=0 to hold ticker ticker ds.w 21*7 ;Space for 320+16 pixels by 7 lines or total 294 bytes ;'Flappybird' title screen SECTION TEXT ;---------------------------------- ;Initialise 'Flappybird' screen titleinit moveq.w #0,d0 move.w d0,titlewavebasey move.w d0,titlewave rts ;---------------------------------- ;Reset for 'Flappybird' screen titlereset bsr birdreset ;Reset bird move.w #144,birdx moveq.w #82,d0 move.w d0,birdy move.w d0,titlewavebasey moveq.w #0,d0 move.w d0,titlewave move.w d0,exitcount bra birdrandompalette ;(does RTS) ;---------------------------------- ;Repair screen after exit titlerepaironexit move.l #160*81+72,d0 ;Screen offset bra titleclearbird ;(does RTS) ;---------------------------------- ;'Flappybird' screen handler titlehandler move.w #RASTERSET_TITLE,nextrasterset bsr titledrawflappybird bsr titleanimbird move.l #160*81+72,d0 ;Screen offset bsr titleclearbird bsr birddraw bsr floorupdate move.w flapbutton,d0 ;Read input beq.s .noinput lea gameoversfx,a0 bsr soundplay0 bsr getreadyreset move.l #getreadyhandler,handler .noinput rts ;---------------------------------- ;Draw 'Flappybird' logo titledrawflappybird ;6064 cycles, 11.8 rasters lea flappybirdimg,a0 ;12 move.l offscreenbse,a1 ;20 lea 160*38+48(a1),a1 ;8 moveq.w #32-1,d7 ;4 .loop movem.l (a0)+,d0-d6/a2 ;76 ;Planes 1+2 for 128 pixels move.l d0,(a1) ;8 move.l d1,8(a1) ;12 move.l d2,16(a1) ;12 move.l d3,24(a1) ;12 move.l d4,32(a1) ;12 move.l d5,40(a1) ;12 move.l d6,48(a1) ;12 move.l a2,56(a1) ;12 lea 160(a1),a1 ;8 ;Next screen line dbra.w d7,.loop ;10/14 rts ;---------------------------------- ;Clear background behind animating bird, pass d0.w as screen offset titleclearbird ;840 cycles, 1.6 rasters move.l offscreenbse,a0 ;20 add.w d0,a0 ;8 ;Offset to screen move.l #$ffff0000,d0 ;12 ;Sky, colour index 1 moveq.l #0,d1 ;4 move.l d0,d2 ;4 move.l d1,d3 ;4 movem.l d0-d3,(a0) ;40 ;Clear 18 lines movem.l d0-d3,160(a0) ;44 movem.l d0-d3,320(a0) movem.l d0-d3,480(a0) movem.l d0-d3,640(a0) movem.l d0-d3,800(a0) movem.l d0-d3,960(a0) movem.l d0-d3,1120(a0) movem.l d0-d3,1280(a0) movem.l d0-d3,1440(a0) movem.l d0-d3,1600(a0) movem.l d0-d3,1760(a0) movem.l d0-d3,1920(a0) movem.l d0-d3,2080(a0) movem.l d0-d3,2240(a0) movem.l d0-d3,2400(a0) movem.l d0-d3,2560(a0) movem.l d0-d3,2720(a0) rts ;---------------------------------- ;Animate bird titleanimbird move.w titlewave,d0 ;Increment sine wave index addq.w #1,d0 move.w d0,titlewave lea titlewavey,a0 ;Set bird Y for sine wave and.w #$3e,d0 move.w titlewavebasey,d1 add.w titlewavey(pc,d0.w),d1 move.w d1,birdy bra birdanim ;(does RTS) ;---------------------------------- titlewavey dc.w 0,+1,+1,+2,+2,+2,+3,+3,+3,+3,+3,+2,+2,+2,+1,+1 dc.w 0,-1,-1,-2,-2,-2,-3,-3,-3,-3,-3,-2,-2,-2,-1,-1 ;---------------------------------- SECTION BSS titlewavebasey ds.w 1 ;Base Y sine wave titlewave ds.w 1 ;Index for Y sine wave ;Utility functions ;NOTE - we cannot disable Timer C on TOS 2.06 (or later) as it will cause ;problems with disc access and cause endless loops ENABLEVAPCHECK = 1 ;Set to 1 to enable VAP check (Hatari does not emulate on Falcon) MACHINE_ST = 0 ;Machine types MACHINE_STE = 1 MACHINE_TT = 2 MACHINE_FALCON = 3 SECTION TEXT ;---------------------------------- ;Initialise utility routines utilinit move.w #MACHINE_ST,machine bsr utilrandseed ;Create random seeds move.b rndseed8,rndnum8 move.w rndseed16,rndnum16 moveq.l #0,d0 move.l d0,vblcount move.l d0,blankingcount move.l d0,nextscreen move.l d0,nextpalette move.w d0,nextrasterset move.w d0,rasterset move.l d0,phybse move.l d0,logbse move.l d0,displaybse move.l d0,offscreenbse lea screenlines,a0 moveq.w #0,d0 ;Offset move.w #160,d1 ;Byte offset to next line (ie 320 pixels) move.w #200-1,d2 .loop move.w d0,(a0)+ ;Store offset for each screen line add.w d1,d0 dbra.w d2,.loop bra utilsfindmachinetype ;Find machine we're running on (does RTS) ;---------------------------------- ;Enter supervisor mode, pass a0.l as old super vector utilsupermode move.l a0,-(sp) move.w #$20,-(sp) trap #1 addq.l #6,sp rts ;---------------------------------- ;Set new VBL interrupt vector, pass a0.l as new interrupt routine utilsetvblvector move.w #$2700,sr ;Disable interrupts move.l a0,$70.w ;Set new VBL vector move.w #$2300,sr ;Enable interrupts rts ;---------------------------------- ;Store hardware state utilstorestate move.w #$2700,sr ;Disable interrupts move.l $8.w,oldbuserror ;Store vectors move.l $c.w,oldaddresserror move.l $10.w,oldillegalins move.l $14.w,olddivzero move.l $70.w,oldvbl move.l $110.w,oldtimerd move.l $114.w,oldtimerc move.l $118.w,oldikbd move.l $120.w,oldtimerb move.l $134.w,oldtimera move.l $404.w,oldgemdoserror move.b $fffffa07.w,oldintenablea ;Store MFP registers move.b $fffffa09.w,oldintenableb move.b $fffffa13.w,oldintmaska move.b $fffffa15.w,oldintmaskb move.b $fffffa19.w,oldtimeracontrol move.b $fffffa1b.w,oldtimerbcontrol move.b $fffffa1d.w,oldtimercdcontrol move.b $ffff8201.w,oldvideohighbyte move.b $ffff8203.w,oldvideomidbyte move.b $ffff820a.w,oldvideosync movem.l $ffff8240.w,d0-d7 ;Store 16 colour palette movem.l d0-d7,oldpalette move.w #$2300,sr ;Enable interrupts bra utilstopmfp ;Disable all MFP timers (does RTS) ;---------------------------------- ;Restore hardware state utilrestorestate bsr utilstopmfp ;Disable all MFP timers move.w #$2700,sr ;Disable interrupts move.l oldbuserror,$8.w ;Restore vectors move.l oldaddresserror,$c.w move.l oldillegalins,$10.w move.l olddivzero,$14.w move.l oldvbl,$70.w move.l oldtimerd,$110.w move.l oldtimerc,$114.w move.l oldikbd,$118.w move.l oldtimerb,$120.w move.l oldtimera,$134.w move.l oldgemdoserror,$404.w move.b oldvideohighbyte,$ffff8201.w move.b oldvideomidbyte,$ffff8203.w move.b oldvideosync,$ffff820a.w move.b oldtimeracontrol,$fffffa19.w move.b oldtimerbcontrol,$fffffa1b.w move.b oldtimercdcontrol,$fffffa1d.w move.b oldintmaska,$fffffa13.w move.b oldintmaskb,$fffffa15.w move.b oldintenablea,$fffffa07.w ;Restore MFP registers move.b oldintenableb,$fffffa09.w movem.l oldpalette,d0-d7 ;Restore palette movem.l d0-d7,$ffff8240.w move.w #$2300,sr ;Enable interrupts rts ;---------------------------------- ;Stop MFP timers utilstopmfp move.w #$2700,sr ;Disable interrupts move.b #0,$fffffa19.w ;Stop Timer A in Timer A Control move.b #0,$fffffa1b.w ;Stop Timer B in Timer B Control and.b #$f8,$fffffa1d.w ;Stop Timer D in Timer C+D Control (leave Timer C alone) bclr.b #5,$fffffa07.w ;Disable Timer A in Interrupt Enable A bclr.b #0,$fffffa07.w ;Disable Timer B in Interrupt Enable A bclr.b #4,$fffffa09.w ;Disable Timer D in Interrupt Enable B bclr.b #5,$fffffa13.w ;Mask Timer A in Interrupt Mask A bclr.b #0,$fffffa13.w ;Mask Timer B in Interrupt Mask A bclr.b #4,$fffffa15.w ;Mask Timer D in Interrupt Mask B bclr.b #5,$fffffa0b.w ;Clear Timer A in Interrupt Pending A bclr.b #0,$fffffa0b.w ;Clear Timer B in Interrupt Pending A bclr.b #4,$fffffa0d.w ;Clear Timer D in Interrupt Pending B move.w #$2300,sr ;Enable interrupts rts ;---------------------------------- ;Check cookie jar to find machine we're running on utilsfindmachinetype move.w #MACHINE_ST,machine ;Default to ST move.l $5a0.w,d0 ;Read cookie jar pointer beq.s .done ;If no cookie jar we're a basic ST move.l d0,a0 .loop move.l (a0)+,d0 ;Read cookie identifier beq.s .done ;Check for end of cookie jar move.l (a0)+,d1 ;Read cookie value cmp.l #'_MCH',d0 ;Check for '_MCH' beq.s .foundmachine ;Store machine type bra.s .loop .foundmachine swap d1 ;Get _MCH value 0=ST, 1=STe, 2=TT, 3=Falcon move.w d1,machine ;And store as MACHINE_xx .done rts ;---------------------------------- ;Set Atari ST low resolution utilsetlowres move.w #0,-(sp) ;Low resolution move.l #-1,-(sp) ;Retain physical screen base move.l #-1,-(sp) ;Retain logical screen base move.w #5,-(sp) ;Setscreen trap #14 adda.w #12,sp rts ;---------------------------------- ;Find physical screen address utilfindscreen move.w #2,-(sp) trap #14 addq.l #2,sp move.l d0,phybse ;Store as physical screen move.l d0,displaybse move.l d0,offscreenbse move.l #logscreen+255,d0 move.b #0,d0 move.l d0,logbse ;Get address of logical screen aligned to 256 bytes move.l d0,offscreenbse ;Set off-screen for screen swap rts ;---------------------------------- ;Set entire palette to black utilblackpalette lea $ffff8240.w,a0 moveq.l #0,d0 move.l d0,(a0)+ ;Clear 16 colours move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0) rts ;---------------------------------- ;Wait for next VBL utilwaitvbl move.l vblcount,d0 .loop cmp.l vblcount,d0 ;Wait for VBL counter to change beq.s .loop rts ;---------------------------------- ;Wait for next Display Blanking (ie last line of display) utilwaitdisplayblank move.l blankingcount,d0 .loop cmp.l blankingcount,d0 ;Wait for Display Blanking counter to change beq.s .loop rts ;---------------------------------- ;Wait for first display line to begin (call after VBL) ;NOTE - Hatari does not emulate this when running as a Falcon utilwaitdisplay IFGT ENABLEVAPCHECK lea $ffff8209.w,a0 ;Video Address Counter Low byte move.b (a0),d0 .loop cmp.b (a0),d0 ;Wait for it to change beq.s .loop ENDC rts ;---------------------------------- ;Example code to check/wait for the Video Address Counter to reach a set offset ;NOTE - Hatari does not emulate this when running as a Falcon utilwaitvideoaddress IFGT ENABLEVAPCHECK lea $ffff8201.w,a0 ;Video Base Address movep.w (a0),d0 ;Read High+Mid value add.w #$7d-1,d0 ;Mid byte offset for 32000-256, ie near end of visible display lea $ffff8205.w,a0 ;Video Address Counter .loop movep.w (a0),d1 ;Read High+Mid value cmp.w d0,d1 bls.s .loop ;Loop until counter is higher, ie d1<=d0 (unsigned) ENDC rts ;---------------------------------- ;Swap off-screen and display screens ;NOTE - on the ST/STe $ff8201 is loaded BEFORE the VBL interrupt so we can set it at anytime ;On the Falcon it is read AFTER the VBL interrupt (as it can be modified for each line) utilswapscreen move.l offscreenbse,d0 utilswapscreend0 cmp.w #MACHINE_FALCON,machine ;If running on a Falcon screen address is set on next VBL beq.s .setscreenfalcon ;Otherwise set VAP now as ST/STe loads on next retrace lea $ffff8201.w,a0 ;Video Base Address lsr.l #8,d0 ;Get off-screen address High+Mid movep.w d0,(a0) ;Write High+Mid value to be used on next retrace bra.s .setscreen .setscreenfalcon move.l d0,nextscreen ;Set off-screen address to write during next VBL .setscreen move.l offscreenbse,d0 ;Swap off-screen and display screen addresses move.l displaybse,offscreenbse move.l d0,displaybse rts ;---------------------------------- ;Wait for keypress using GEMDOS (does not print to output) utilwaitkey move.w #8,-(sp) trap #1 addq.l #2,sp rts ;---------------------------------- ;Check for keypress using GEMDOS, return d0.w as key (0 if no key is pressed) utilcheckkey move.w #$b,-(sp) trap #1 addq.l #2,sp rts ;---------------------------------- ;Fast clear screen, pass a0.l as screen address utilclearscreen lea 32000(a0),a0 ;Start at end of screen moveq.l #0,d1 ;Clear d1-d7/a1-a6 move.l d1,d2 move.l d1,d3 move.l d1,d4 move.l d1,d5 move.l d1,d6 move.l d1,d7 move.l d1,a1 move.l d1,a2 move.l d1,a3 move.l d1,a4 move.l d1,a5 move.l d1,a6 move.w #68-1,d0 ;Loop for 31824 bytes .loop movem.l d1-d7/a1-a6,-(a0) ;Clear 468 bytes movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) dbra.w d0,.loop movem.l d1-d7/a1-a6,-(a0) ;Clear remaining 176 bytes movem.l d1-d7/a1-a6,-(a0) movem.l d1-d7/a1-a6,-(a0) movem.l d1-d5,-(a0) rts ;---------------------------------- ;Fast copy screen, pass a0.l as source and a1.l as destination screen address utilcopyscreen move.w #333-1,d0 ;333*96 = 31968 bytes .loop movem.l (a0)+,d1-d7/a2-a6 ;Copy 96 bytes movem.l d1-d7/a2-a6,(a1) movem.l (a0)+,d1-d7/a2-a6 movem.l d1-d7/a2-a6,48(a1) lea 96(a1),a1 dbra.w d0,.loop movem.l (a0),d1-d7/a2 ;Copy remaining 32 bytes movem.l d1-d7/a2,(a1) rts ;---------------------------------- ;Function to force 60Hz utilset60hz bclr.b #1,$ffff820a.w ;Bit 1 is 0 for 60Hz or 1 for 50Hz rts ;---------------------------------- ;Function to force 50Hz utilset50hz bset.b #1,$ffff820a.w ;Set 50Hz rts ;---------------------------------- ;Generate random seeds on boot (use XBIOS for compatibility) utilrandseed move.w #17,-(sp) ;Random trap #14 addq.w #2,sp cmp.b #0,d0 ;Check if seed is invalid (ie 0) bne.s .setseed8 move.b #$23,d0 ;Force valid default seed .setseed8 move.b d0,rndseed8 move.w #17,-(sp) trap #14 addq.w #2,sp cmp.w #0,d0 bne.s .setseed16 move.w #$a67e,d0 .setseed16 move.w d0,rndseed16 rts ;---------------------------------- ;Randomise Xorshift (as Xorshift is a repeating sequence) utilrandomise move.b $ffff8209.w,d0 ;Read video address pointer add.b d0,rndnum8 ;Add to random numbers add.b d0,rndnum16 rts ;---------------------------------- ;Xorshift random number, return value in d0.b (range 0...255-1) utilrandbyte move.w d1,-(sp) move.b rndnum8,d0 move.b d0,d1 lsl.b #7,d1 eor.b d1,d0 ;y ^= (y<<7) move.b d0,d1 lsr.b #5,d1 eor.b d1,d0 ;y ^= (y>>5) move.b d0,d1 lsl.b #3,d1 eor.b d1,d0 ;y ^= (y<<3) beq.s .zero .reseed move.b d0,rndnum8 subq.b #1,d0 move.w (sp)+,d1 rts .zero move.b rndseed8,d0 ;Reset seed bra.s .reseed ;---------------------------------- ;Xorshift random number, return value in d0.w (range 0...65535-1) utilrandword move.w d1,-(sp) move.w rndnum16,d0 move.w d0,d1 lsl.w #8,d1 lsl.w #5,d1 eor.w d1,d0 ;y ^= (y<<13) move.w d0,d1 lsr.w #8,d1 lsr.w #1,d1 eor.w d1,d0 ;y ^= (y>>9) move.w d0,d1 lsl.w #7,d1 eor.w d1,d0 ;y ^= (y<<7) beq.s .zero .reseed move.w d0,rndnum16 subq.w #1,d0 move.w (sp)+,d1 rts .zero move.w rndseed16,d0 ;Reset seed bra.s .reseed ;---------------------------------- ;Print word to screen as HEX, pass value in d0.w utilprintword movem.l d0-d7/a0-a6,-(sp) lea textword,a0 ;Buffer to write digits bsr utilword2text ;Convert d0.w to text string move.l #textword,-(sp) move #$9,-(sp) ;Conws trap #1 addq.l #6,sp movem.l (sp)+,d0-d7/a0-a6 rts ;---------------------------------- ;Print long word to screen as HEX, pass value in d0.l utilprintlong movem.l d0-d7/a0-a6,-(sp) lea textlong,a0 ;Buffer to write digits bsr utillong2text ;Convert d0.l to text string move.l #textlong,-(sp) move #$9,-(sp) ;Conws trap #1 addq.l #6,sp movem.l (sp)+,d0-d7/a0-a6 rts ;---------------------------------- ;Convert word to HEX string, pass value in d0.w and string buffer in a0.l utilword2text movem.l d0-d2/a0,-(sp) moveq.w #4-1,d2 ;Write 4 digits .loop rol.w #4,d0 ;Put upper nibble in lowest bits move.w d0,d1 ;Copy value and.w #$f,d1 ;Mask nibble add.w #'0',d1 ;'0...9' cmp.w #'9',d1 ble.s .ok add.w #'A'-'9'-1,d1 ;'A...F' .ok move.b d1,(a0)+ ;Write digit dbra.w d2,.loop movem.l (sp)+,d0-d2/a0 rts ;---------------------------------- ;Convert long word to HEX string, pass value in d0.l and string buffer in a0.l utillong2text movem.l d0-d2/a0,-(sp) moveq.w #8-1,d2 ;Write 8 digits .loop rol.l #4,d0 ;Put upper nibble in lowest bits move.l d0,d1 ;Copy value and.l #$f,d1 ;Mask nibble add.w #'0',d1 ;'0...9' cmp.w #'9',d1 ble.s .ok add.w #'A'-'9'-1,d1 ;'A...F' .ok move.b d1,(a0)+ ;Write digit dbra.w d2,.loop movem.l (sp)+,d0-d2/a0 rts ;---------------------------------- ;Find available free memory from GEMDOS, returns size in d0.l utilavailablemem move.l #-1,-(sp) ;Pass -1 to find free memory move.w #$48,-(sp) ;Malloc trap #1 addq.w #6,sp rts ;---------------------------------- SECTION DATA textword dc.b "XXXX",0 ;Buffers for output when convert value to HEX strings, including trailing '\0' textlong dc.b "XXXXXXXX",0 EVEN ;---------------------------------- SECTION BSS machine ds.w 1 ;Machine type, ie MACHINE_xx rndseed8 ds.b 1 ;Random numbers rndnum8 ds.b 1 rndseed16 ds.w 1 rndnum16 ds.w 1 vblcount ds.l 1 ;VBL counter blankingcount ds.l 1 ;VBL IN counter nextscreen ds.l 1 ;Next screen address, set on VBL nextpalette ds.l 1 ;Next palette address, set on VBL nextrasterset ds.w 1 ;Next raster set, set on VBL rasterset ds.w 1 ;Raster set phybse ds.l 1 ;Physical and logical screen addresses logbse ds.l 1 displaybse ds.l 1 ;Current displayed screen address offscreenbse ds.l 1 ;Off-screen address screenlines ds.w 200 ;Offsets to each line in screen (ie y*160) logscreen ds.b 32256 ;320*200 32Kbyte logical screen, with 256 bytes for alignment oldsuper ds.l 1 ;Old supermode vector oldbuserror ds.l 1 ;$8 Bus Error vector oldaddresserror ds.l 1 ;$c Address Error vector oldillegalins ds.l 1 ;$10 Illegal Instruction olddivzero ds.l 1 ;$14 Divide By Zero oldvbl ds.l 1 ;$70 VBL vector oldtimerd ds.l 1 ;$110 MFP Timer D vector (low priority) oldtimerc ds.l 1 ;$114 MFP Timer C vector oldikbd ds.l 1 ;$114 MFP IKBD vector oldtimerb ds.l 1 ;$120 MDP Timer B vector oldtimera ds.l 1 ;$134 MFP Timer A vector (high priority) oldgemdoserror ds.l 1 ;$404 GEMDOS critical error handler oldintenablea ds.b 1 ;$fffa07 Interrupt Enable A oldintenableb ds.b 1 ;$fffa09 Interrupt Enable B oldintmaska ds.b 1 ;$fffa13 Interrupt Mask A oldintmaskb ds.b 1 ;$fffa15 Interrupt Mask B oldtimeracontrol ds.b 1 ;$fffa19 Timer A Control oldtimerbcontrol ds.b 1 ;$fffa1b Timer B Control oldtimercdcontrol ds.b 1 ;$fffa1d Timer C+D Control oldvideohighbyte ds.b 1 ;$ff8201 Video Base Address High oldvideomidbyte ds.b 1 ;$ff8203 Video Base Address Mid oldvideosync ds.b 1 ;$ff820a Video Shifter Sync Mode EVEN oldpalette ds.w 16 ;$ff8240 16-colour palette ޏ^H{Ya܇O';+8.Ub^nR$&q$ZG:D7qw{ SwezC/$e݈ib@-SExsRotu!}"M@Xz:h%Ǚ%[y3̟Cg