00001. ; Super Mario Bros. 3 Full Disassembly by Southbird 2012 
00002. ; For more info, see http://www.sonicepoch.com/sm3mix/ 
00003. ; 
00004. ; PLEASE INCLUDE A CREDIT TO THE SOUTHBIRD DISASSEMBLY 
00005. ; AND THE ABOVE LINK SOMEWHERE IN YOUR WORKS :) 
00006. ; 
00007. ; Original disassembler source generated by DCC6502 version v1.4 
00008. ; (With labels, comments, and some syntax corrections for nesasm by Southbird) 
00009. ; For more info about DCC6502, e-mail veilleux@ameth.org 
00010. ; 
00011. ; This source file last updated: 2012-02-13 22:44:39.225983982 -0600 
00012. ; Distribution package date: Fri Apr 6 23:46:16 UTC 2012 
00013. ;--------------------------------------------------------------------------- 
00014.  
00015. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00016. ; Player_DoLavaDonutArrowBounce 
00017. ; 
00018. ; Handles the Player coming into contact with lava, donut lifts, 
00019. ; or arrow platforms (supported in vertical level only) 
00020. ; This also checks to see if the Player should bounce because the 
00021. ; block beneath his feet bounced (by checking for the  
00022. ; TILEA_BLOCKBUMP_CLEAR tile...) 
00023. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00024.  
00025. ; Specifies which kind of arrow lift should be created relative to which tile 
00026. ; the Player stepped on. Note the zero near the end; if you look at tileset #8 
00027. ; the donut lift appears right between what would be the multidirectional lift. 
00028. ArrowPlat_ByTile: 
00029. .byte OBJ_ARROWONE, OBJ_ARROWONE, OBJ_ARROWONE, OBJ_ARROWONE, OBJ_ARROWONE, OBJ_ARROWONE, OBJ_ARROWANY, $00, OBJ_ARROWANY 
00030.  
00031. ; Sets the direction value as used by the arrow platform 
00032. ArrowPlat_DirByTile: 
00033. .byte $00, $00, $03, $03, $01, $01, $00, $00, $00 
00034.  
00035. ArrowPlat_XOff: 
00036. .byte 0, -16, 0, -16, 0, -16, 0, 0, -16 
00037.  
00038. Player_DoLavaDonutArrowBounce: 
00039. LDA <Player_IsDying  
00040. BNE PRG007_A06F ; If Player is dying, jump to PRG007_A06F (RTS) 
00041.  
00042. LDA Level_7Vertical 
00043. BEQ PRG007_A027 ; If this is NOT a vertically-oriented level, jump to PRG007_A027 
00044.  
00045. JMP PRG007_A0DE ; Otherwise, jump to PRG007_A0DE 
00046.  
00047. PRG007_A027: 
00048.  
00049. ; Not vertically oriented level... 
00050.  
00051. LDA <Player_Y ; Get Player Y 
00052. ADD #32 ; +32 
00053. AND #$f0 ; Align to tile grid 
00054. STA <Temp_Var5 ; -> Temp_Var5 
00055.  
00056. LDA <Player_YHi 
00057. BMI PRG007_A06F ; If Player is up off the top of the screen, jump to PRG007_A06F (RTS) 
00058.  
00059. ADC #$00 ; Apply carry 
00060. AND #$01 ; Only bit 0 is valid anyway in non-vertical mode 
00061. STA <Temp_Var3 ; -> Temp_Var3 
00062.  
00063. LDA <Player_X ; Get Player X 
00064. ADD #$08 ; +8 
00065. AND #$f0 ; Align to tile grid 
00066. STA <Temp_Var4 ; -> Temp_Var4 
00067.  
00068. LDA <Player_XHi 
00069. ADC #$00 ; Apply carry 
00070. STA <Temp_Var6 ; -> Temp_Var6 
00071.  
00072. CMP #16 ; 16 screens are the max!! 
00073. BCS PRG007_A06F ; If Player is really far to the right (somehow), jump to PRG007_A06F (RTS) 
00074.  
00075. ASL A ; 2 byte index for current screen 
00076. TAY ; -> 'Y' 
00077.  
00078. ; Store high byte of screen address -> Temp_Var1 
00079. LDA Tile_Mem_Addr,Y 
00080. STA <Temp_Var1  
00081.  
00082. ; Store low byte of screen address + Player's Y Hi -> Temp_Var2 
00083. LDA Tile_Mem_Addr+1,Y 
00084. ADD <Temp_Var3  
00085. STA <Temp_Var2 
00086.  
00087. ; Calculate a proper offset into the tile memory for the X/Y position of the Player 
00088. LDA <Temp_Var4 
00089. LSR A 
00090. LSR A 
00091. LSR A 
00092. LSR A 
00093. ORA <Temp_Var5 
00094. TAY ; -> 'Y' 
00095.  
00096. LDA [Temp_Var1],Y ; Get the tile here 
00097.  
00098. CMP #TILEA_BLOCKBUMP_CLEAR 
00099. BNE PRG007_A070 ; If this is not a bumped block tile, jump to PRG007_A070 
00100.  
00101. ; Otherwise, bounce Player! 
00102. LDA #-$30 
00103. STA <Player_YVel 
00104.  
00105. PRG007_A06F: 
00106. RTS ; Return 
00107.  
00108.  
00109. PRG007_A070: 
00110. CMP #TILE2_LAVATOP 
00111. BNE PRG007_A082 ; If this is not (possibly) a lava tile, jump to PRG007_A082 
00112.  
00113. LDY Level_Tileset 
00114. CPY #11 
00115. BEQ PRG007_A07F ; If this is tileset 11 (Giant World; Interesting! Green bubbly death here), jump to PRG007_A07F 
00116.  
00117. CPY #2 
00118. BNE PRG007_A082 ; If this is NOT tileset 2 (Fortress style), jump to PRG007_A082 
00119.  
00120. PRG007_A07F: 
00121. JMP PRG007_A183 ; Jump to PRG007_A183 (Player dies!) 
00122.  
00123. PRG007_A082: 
00124. CMP #TILE2_DONUTLIFT 
00125. BNE PRG007_A0DD ; If this is not (possibly) a Donut Lift, jump to PRG007_A0DD (RTS) 
00126.  
00127. PRG007_A086: 
00128. ; If this is tileset 4, 8, 12, or 2 (all valid for Donut Lift), jump to PRG007_A099, otherwise jump to PRG007_A06F (RTS) 
00129. LDY Level_Tileset 
00130. CPY #4 
00131. BEQ PRG007_A099 
00132.  
00133. CPY #8 
00134. BEQ PRG007_A099 
00135.  
00136. CPY #12 
00137. BEQ PRG007_A099 
00138.  
00139. CPY #2 
00140. BNE PRG007_A06F 
00141.  
00142. PRG007_A099: 
00143. LDA Level_ChgTileEvent 
00144. BNE PRG007_A06F ; If there's already a tile change event queued, jump to PRG007_A06F (RTS) 
00145.  
00146. JSR PrepareNewObjectOrAbort ; Prepare a new object or don't come back! 
00147.  
00148. ; This is a falling donut lift! 
00149. LDA #OBJ_DONUTLIFTSHAKEFALL 
00150. STA Level_ObjectID,X 
00151.  
00152. ; Set donut lift Y  
00153. LDA <Temp_Var5 
00154. SUB #$01 
00155. STA <Objects_Y,X 
00156. LDA <Temp_Var3 
00157. SBC #$00 
00158. STA <Objects_YHi,X 
00159.  
00160. ; Set donut lift X 
00161. LDA <Temp_Var4 
00162. STA <Objects_X,X 
00163. LDA <Temp_Var6 
00164. STA <Objects_XHi,X 
00165.  
00166. ; Set donut lift object's Var5 = $20 
00167. LDA #$20 
00168. STA <Objects_Var5,X 
00169.  
00170. ; Set sprite attribute = 3 
00171. LDA #$03 
00172. STA Objects_SprAttr,X 
00173.  
00174. ; Do tile change event to clear the tile version of the donut lift 
00175. LDA #$02 
00176. STA Level_ChgTileEvent 
00177. LDA <Temp_Var3  
00178. STA Level_BlockChgYHi 
00179. LDA <Temp_Var5  
00180. STA Level_BlockChgYLo 
00181. LDA <Temp_Var4  
00182. STA Level_BlockChgXLo 
00183. LDA <Temp_Var6  
00184. STA Level_BlockChgXHi 
00185.  
00186. PRG007_A0DD: 
00187. RTS ; Return 
00188.  
00189. PRG007_A0DE: 
00190.  
00191. ; Vertically oriented level... 
00192.  
00193. LDA <Player_Y ; Get Player Y 
00194. ADD #33 ; +33 
00195. AND #$f0 ; Aligned to tile grid 
00196. STA <Temp_Var1 ; -> Temp_Var1 
00197. STA <Temp_Var5 ; -> Temp_Var5 
00198.  
00199. LDA <Player_YHi 
00200. BMI PRG007_A0DD ; If Player is up off the top of the level, jump to PRG007_A0DD (RTS) 
00201.  
00202. ADC #$00 ; Apply carry 
00203. STA <Temp_Var3 ; -> Temp_Var3 
00204.  
00205. ; High byte of Tile_Mem -> Temp_Var2 
00206. ORA #HIGH(Tile_Mem) 
00207. STA <Temp_Var2 
00208.  
00209. LDA <Player_X ; Get Player X 
00210. ADD #$08 ; +8 
00211. AND #$f0 ; Aligned to tile grid 
00212. STA <Temp_Var4 ; -> Temp_Var4 
00213.  
00214. ; Construct tile offset 
00215. LSR A 
00216. LSR A 
00217. LSR A 
00218. LSR A 
00219. ORA <Temp_Var1 
00220. STA <Temp_Var1 
00221.  
00222. ; Temp_Var6 = 0 (would be "X Hi", which is always zero in vertical level) 
00223. LDY #$00 
00224. STY <Temp_Var6 
00225.  
00226. LDA [Temp_Var1],Y ; Get tile here 
00227.  
00228. CMP #TILE2_DONUTLIFT 
00229. BNE PRG007_A113 ; If this is not donut lift tile, jump to PRG007_A113 
00230.  
00231. JMP PRG007_A086 ; Otherwise, jump to PRG007_A086 
00232.  
00233. PRG007_A113: 
00234. LDY <Player_InAir 
00235. BNE PRG007_A0DD ; If Player is mid-air, jump to PRG007_A0DD (RTS) 
00236.  
00237. LDY ArrowPlat_IsActive 
00238. BNE PRG007_A0DD ; If an arrow platform is already active, jump to PRG007_A0DD (RTS) 
00239.  
00240. ; If not standing on some kind of arrow platform tile, jump to PRG007_A0DD (RTS) 
00241. CMP #TILE8_ARROWLIFT_UPL 
00242. BLT PRG007_A0DD 
00243. CMP #(TILE8_ARROWLIFT_RANDOMR+1) 
00244. BGE PRG007_A0DD 
00245.  
00246. SUB #TILE8_ARROWLIFT_UPL 
00247. TAY ; Y = relative index of tile for arrow platform 
00248.  
00249. ; Temp_Var3 = $FF 
00250. LDA #$ff 
00251. STA <Temp_Var3 
00252.  
00253. LDX #$04 ; X = 4 
00254. PRG007_A12E: 
00255. LDA Objects_State,X 
00256. BEQ PRG007_A144 ; If this object slot is dead/empty, jump to PRG007_A144 
00257.  
00258. ; If this object slot is not some type of arrow platform, jump to PRG007_A146 
00259. LDA Level_ObjectID,X 
00260. CMP #OBJ_ARROWONE 
00261. BLT PRG007_A146 
00262. CMP #(OBJ_ARROWANY+1) 
00263. BGE PRG007_A146 
00264.  
00265. ; There's another arrow platform already active in this slot... 
00266.  
00267. JSR Object_SetDeadEmpty ; Set this slot as dead/empty 
00268. JMP PRG007_A144 ; Jump to PRG007_A144 
00269.  
00270. ; ^ I think the above is partially a mistake; they probably wanted to jump to something 
00271. ; that would set 'X' and exit the loop. This logic works as-is, but it requires another 
00272. ; frame before the arrow lift will actually come into existence... unless another dead/ 
00273. ; empty object appears forward of this position... 
00274.  
00275. PRG007_A144: 
00276. STX <Temp_Var3 ; Temp_Var3 = index we just searched 
00277.  
00278. PRG007_A146: 
00279. DEX ; X-- 
00280. BPL PRG007_A12E ; While X >= 0, loop! 
00281.  
00282. LDX <Temp_Var3 ; X = free object slot! 
00283. BMI PRG007_A182 ; If no free object slot was found, jump to PRG007_A182 
00284.  
00285. ; Set this to "Normal!" 
00286. LDA #OBJSTATE_NORMAL 
00287. STA Objects_State,X 
00288.  
00289. ; Create the correct arrow platform by the tile 
00290. LDA ArrowPlat_ByTile,Y 
00291. STA Level_ObjectID,X 
00292.  
00293. ; Set the direction value by tile 
00294. LDA ArrowPlat_DirByTile,Y 
00295. STA <Objects_Var4,X 
00296.  
00297. ; Arrow platform Y 
00298. LDA <Temp_Var1 
00299. AND #$f0 
00300. SUB #$01 
00301. STA <Objects_Y,X 
00302. LDA <Temp_Var2 
00303. SBC #$00 
00304. AND #$0f 
00305. STA <Objects_YHi,X 
00306.  
00307. ; Arrow platform X 
00308. LDA <Temp_Var1 
00309. ASL A 
00310. ASL A 
00311. ASL A 
00312. ASL A 
00313. ADD ArrowPlat_XOff,Y 
00314. STA <Objects_X,X 
00315. LDA #$00 
00316. STA <Objects_XHi,X 
00317.  
00318. ; Arrow platform's Var5 (lifespan counter) = $FF 
00319. LDA #$ff 
00320. STA <Objects_Var5,X 
00321.  
00322. PRG007_A182: 
00323. RTS ; Return 
00324.  
00325. PRG007_A183: 
00326.  
00327. ; Player hit death tile! 
00328.  
00329. ; Zap suit 
00330. LDA #$01 
00331. STA Player_QueueSuit 
00332.  
00333. JMP Player_Die ; Player dies and don't come back! 
00334.  
00335.  
00336. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00337. ; ColorRotation_Do 
00338. ; 
00339. ; Performs the palette color rotation effects per RotatingColor_Cnt 
00340. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00341. ; The palette color forcefully applied in a color rotation 
00342. Rotation_Colors: 
00343. .byte $26, $2A, $22, $36 
00344.  
00345. ColorRotation_Do: 
00346. LDX Graphics_BufCnt ; X = Graphics_BufCnt 
00347.  
00348. LDA RotatingColor_Cnt 
00349. BEQ PRG007_A1EA ; If RotatingColor_Cnt = 0 (No color rotation active), jump to PRG007_A1EA (RTS) 
00350.  
00351. PHA ; Save rotation value 
00352.  
00353. AND #$03 
00354. TAY ; Y = 0 to 3, based on rotation value 
00355.  
00356. DEC RotatingColor_Cnt ; RotatingColor_Cnt-- 
00357.  
00358. PLA ; Restore rotation value 
00359. BPL PRG007_A1EB ; If bit 7 not set on rotation value, jump to PRG007_A1EB 
00360.  
00361. ; Bit 7 set on RotatingColor_Cnt 
00362.  
00363. AND #%01111111 ; Ignore bit 7 
00364. BNE PRG007_A1A8 ; If does not amount to zero, jump to PRG007_A1A8 
00365.  
00366. STA RotatingColor_Cnt ; Otherwise, clear RotatingColor_Cnt 
00367.  
00368. PRG007_A1A8: 
00369.  
00370. ; Address of palette to modify 
00371. LDA #$3f 
00372. STA Graphics_Buffer+$00,X 
00373. LDA #$04 
00374. STA Graphics_Buffer+$01,X 
00375.  
00376. ; 8 bytes to go 
00377. LDA #$08 
00378. STA Graphics_Buffer+$02,X 
00379.  
00380. ; Set the rotation colors into the buffer 
00381. LDA Rotation_Colors,Y 
00382. STA Graphics_Buffer+$04,X 
00383. STA Graphics_Buffer+$05,X 
00384. STA Graphics_Buffer+$06,X 
00385. STA Graphics_Buffer+$08,X 
00386.  
00387. LDA Palette_Buffer+$4 
00388. STA Graphics_Buffer+$03,X 
00389.  
00390. LDA Palette_Buffer+$8 
00391. STA Graphics_Buffer+$07,X 
00392.  
00393. LDA Palette_Buffer+$A 
00394. STA Graphics_Buffer+$09,X 
00395.  
00396. LDA Palette_Buffer+$B 
00397. STA Graphics_Buffer+$0A,X 
00398.  
00399. ; Terminator 
00400. LDA #$00 
00401. STA Graphics_Buffer+$0B,X 
00402.  
00403. ; Add to the graphics buffer counter 
00404. TXA 
00405. ADD #$0b 
00406. STA Graphics_BufCnt 
00407.  
00408. PRG007_A1EA: 
00409. RTS ; Return 
00410.  
00411.  
00412. PRG007_A1EB: 
00413.  
00414. ; Bit 7 not set on RotatingColor_Cnt 
00415.  
00416. LDA RotatingColor_Cnt 
00417. BEQ PRG007_A1F5 ; If RotatingColor_Cnt = 0, jump to PRG007_A1F5 
00418.  
00419. ; Set the rotation colors into the buffer 
00420. LDA Rotation_Colors,Y 
00421. BNE PRG007_A1F8 ; Jump (technically always) to PRG007_A1F8 
00422.  
00423. PRG007_A1F5: 
00424. LDA Palette_Buffer+$10 
00425.  
00426. PRG007_A1F8: 
00427. STA Graphics_Buffer+$03,X 
00428.  
00429. LDA #$10 
00430. STA Graphics_Buffer+$01,X 
00431.  
00432. LDA Palette_Buffer+$11 
00433. STA Graphics_Buffer+$04,X 
00434.  
00435. LDA Palette_Buffer+$12 
00436. STA Graphics_Buffer+$05,X 
00437.  
00438. LDA Palette_Buffer+$13 
00439. STA Graphics_Buffer+$06,X 
00440.  
00441. ; Address of palette to modify 
00442. LDA #$3f 
00443. STA Graphics_Buffer+$00,X 
00444. LDA #$04 
00445. STA Graphics_Buffer+$02,X 
00446.  
00447. ; Terminator 
00448. LDA #$00 
00449. STA Graphics_Buffer+$07,X 
00450.  
00451. ; Add to the graphics buffer counter 
00452. TXA 
00453. ADD #$07 
00454. STA Graphics_BufCnt 
00455.  
00456. RTS ; Return 
00457.  
00458. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00459. ; Gameplay_UpdateAndDrawMisc 
00460. ; 
00461. ; Color rotation effects, lava, donut lifts, arrow platforms, 
00462. ; brick busts, water/waterfall visual effects, bubbles, splashes, 
00463. ; pop-up coins, Special Objects, Cannon Fires, Player Projectiles, 
00464. ; and, last but not least (well, maybe least), "shell kill flashes"! 
00465. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00466. Gameplay_UpdateAndDrawMisc: 
00467. JSR ColorRotation_Do ; Do color rotation effects, if any 
00468. JSR Player_DoLavaDonutArrowBounce ; Handle Lava, Donut Lifts, and Arrow platforms 
00469. JSR BrickBusts_DrawAndUpdate ; Draw and update brick bust effects 
00470. JSR Player_WaterOrWaterfallVizFX ; Standing in a waterfall splashing or periodic bubbles underwater 
00471. JSR Bubbles_UpdateAndDraw ; Update and draw underwater bubbles 
00472. JSR Splash_UpdateAndDraw ; Update and draw water surface splashes 
00473. JSR CoinPUps_DrawAndUpdate ; Update and draw coins that have popped out of boxes 
00474. JSR SpecialObjs_UpdateAndDraw ; Update and draw Special objects 
00475. JSR CannonFire_UpdateAndDraw ; Update and draw the Cannon Fires 
00476. JSR PlayerProjs_UpdateAndDraw ; Update and draw Player's weapon projectiles 
00477.  
00478. LDA <Player_Suit 
00479. CMP #PLAYERSUIT_HAMMER 
00480. BEQ PRG007_A251 ; If Player is wearing a Hammer Suit, jump to PRG007_A251 
00481.  
00482. CMP #PLAYERSUIT_FIRE 
00483. BNE PRG007_A268 ; If Player is not Fire, jump to PRG007_A268 
00484.  
00485. PRG007_A251: 
00486.  
00487. ; Player wearing a Hammer Suit or Fire 
00488.  
00489. LDA Player_HaltTick ; If Player is not halted ... 
00490. ORA Player_IsDucking ; ... Player is ducking ... 
00491. ORA Player_Kick ; ... Player is kicking ... 
00492. ORA Player_InPipe ; ... Player is in a pipe ... 
00493. ORA <Player_HaltGame ; ... gameplay is halted ... 
00494. BNE PRG007_A268 ; ... then jump to PRG007_A268 
00495.  
00496. BIT <Pad_Input 
00497. BVC PRG007_A268 ; If Player is NOT pressing B, jump to PRG007_A268 
00498.  
00499. JSR PlayerProj_ThrowWeapon ; Player throws weapon, whatever's appropriate 
00500.  
00501. PRG007_A268: 
00502. LDA ShellKillFlash_Cnt 
00503. BEQ PRG007_A2AE ; If ShellKillFlash_Cnt = 0, jump to PRG007_A2AE (RTS) 
00504.  
00505. DEC ShellKillFlash_Cnt ; ShellKillFlash_Cnt-- 
00506.  
00507. LDY #$00 ; Y = 0 
00508.  
00509. ; Set the shell kill flash left/right sprite Y 
00510. LDA ShellKillFlash_Y 
00511. SUB Level_VertScroll 
00512. STA Sprite_RAM+$00,Y 
00513. STA Sprite_RAM+$04,Y 
00514.  
00515. ; Set left sprite X 
00516. LDA ShellKillFlash_X 
00517. SUB <Horz_Scroll 
00518. STA Sprite_RAM+$03,Y 
00519.  
00520. ; Set right sprite X 
00521. ADD #$08 
00522. STA Sprite_RAM+$07,Y 
00523.  
00524. ; Set left/right sprite pattern 
00525. LDA #$57 
00526. STA Sprite_RAM+$01,Y 
00527. STA Sprite_RAM+$05,Y 
00528.  
00529. ; Temp_Var1 = toggled vertical flip bit 
00530. LDA <Counter_1 
00531. LSR A 
00532. LSR A 
00533. LSR A 
00534. ROR A 
00535. AND #SPR_VFLIP 
00536. STA <Temp_Var1 
00537.  
00538. ; OR in a palette cycle 
00539. LDA <Counter_1 
00540. AND #$03 
00541. ORA <Temp_Var1 
00542.  
00543. ; Set left sprite attribute 
00544. STA Sprite_RAM+$02,Y 
00545.  
00546. ; Set right sprite attribute 
00547. EOR #(SPR_HFLIP | SPR_VFLIP) 
00548. STA Sprite_RAM+$06,Y 
00549.  
00550. PRG007_A2AE: 
00551. RTS ; Return 
00552.  
00553. PlayerProj_ThrowWeapon: 
00554. LDX #$01 ; X = 1 
00555. PRG007_A2B1: 
00556. LDA PlayerProj_ID,X 
00557. BEQ PRG007_A2BA ; If this Player projectile slot is free 
00558.  
00559. DEX ; X-- 
00560. BPL PRG007_A2B1 ; While X >= 0, loop! 
00561.  
00562. RTS ; Return 
00563.  
00564. PRG007_A2BA: 
00565.  
00566. ; Player "fire" sound 
00567. LDA Sound_QPlayer 
00568. ORA #SND_PLAYERFIRE 
00569. STA Sound_QPlayer 
00570.  
00571. ; Player should use "fire" frame! 
00572. LDA #$0b 
00573. STA Player_FireCount 
00574.  
00575. ; Set projectile X 
00576. LDA <Player_X 
00577. ADD #$04 
00578. STA PlayerProj_X,X 
00579.  
00580. ; Set projectile Y Hi 
00581. LDA <Player_Y 
00582. STA PlayerProj_Y,X 
00583. LDA <Player_YHi 
00584. STA PlayerProj_YHi,X 
00585.  
00586. LDA #$01 ; A = 1 
00587.  
00588. LDY <Player_Suit 
00589. CPY #PLAYERSUIT_HAMMER 
00590. SEC ; Set carry (if NOT wearing the hammer suit) 
00591. BNE PRG007_A2E3 ; If Player is NOT wearing the Hammer Suit, jump to PRG007_A2E3 
00592. ASL A ; Clears carry, also A = 2 
00593. PRG007_A2E3: 
00594. STA PlayerProj_ID,X ; Set projectile as type 1 or 2 
00595.  
00596. ; Set Player Projectile Y velocity 
00597. LDA #$03 ; A = $03 (Fireballs are thrown down) 
00598. BCS PRG007_A2EC ; If Player is NOT wearing Hammer Suit, jump to PRG007_A2EC 
00599. LDA #-$03 ; A = -$03 (Hammers are thrown up) 
00600. PRG007_A2EC: 
00601. STA PlayerProj_YVel,X 
00602.  
00603. ; Temp_Var1 = 0 (no offset for fireballs) 
00604. LDA #$00 
00605. STA <Temp_Var1 
00606.  
00607. LDA #$03 ; A = $03 (Fire) 
00608. BCS PRG007_A304 ; If Player is NOT wearing Hammer Suit, jump to PRG007_A304 
00609.  
00610. ; Calculate the hammer X velocity offset 
00611. LDA <Player_FlipBits ; Keep in mind this is generally only $00 or $40 since Player doesn't vertically flip/etc. 
00612. ASL A ; ... so this makes a positive or negative sign 
00613. EOR <Player_XVel ; XOR in the Player's X velocity 
00614. BPL PRG007_A302 ; If result is positive, jump to PRG007_A302 
00615.  
00616. ; Otherwise, set Temp_Var1 = Player_XVel 
00617. LDA <Player_XVel 
00618. STA <Temp_Var1 
00619.  
00620. PRG007_A302: 
00621. LDA #$10 ; A = $10 (Hammer) 
00622.  
00623. PRG007_A304: 
00624. LDY <Player_FlipBits ; Keep in mind this is generally only $00 or $40 since Player doesn't vertically flip/etc. 
00625. BNE PRG007_A30B ; If Player is horizontally flipped, jump to PRG007_A30B 
00626.  
00627. JSR Negate ; If Player is turned around, negate value 
00628.  
00629. PRG007_A30B: 
00630. ADD <Temp_Var1 ; Add Temp_Var1 (X Velocity offset, if applicable) 
00631. STA PlayerProj_XVel,X ; Store Projectile X velocity 
00632.  
00633. ; PlayerProj_Cnt = 0 
00634. LDA #$00 
00635. STA PlayerProj_Cnt,X 
00636.  
00637. RTS ; Return 
00638.  
00639.  
00640. PlayerFireball_Pats: .byte $65, $67, $65, $67 
00641. PlayerFireball_FlipBits: .byte SPR_PAL1, SPR_PAL1, SPR_PAL1 | SPR_HFLIP | SPR_VFLIP, SPR_PAL1 | SPR_HFLIP | SPR_VFLIP 
00642.  
00643. PlayerHammer_FlipBits: .byte $00, SPR_VFLIP, SPR_HFLIP | SPR_VFLIP, SPR_HFLIP 
00644. PlayerHammer_YOff: .byte $00 ; NOTE: Next three values overlap into following table) 
00645. PlayerHammer_XOff: .byte $06, $06, $00, $00 
00646.  
00647. PRG007_A328: 
00648. RTS 
00649.  
00650. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00651. ; PlayerProjs_UpdateAndDraw 
00652. ; 
00653. ; Update and draw Player Projectiles  
00654. ; (weapons, i.e. fireballs/hammers/fireball poofs) 
00655. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
00656. PlayerProjs_UpdateAndDraw: 
00657. LDX #$01 ; X = 1  
00658. STX <SlotIndexBackup ; SlotIndexBackup = 1 
00659.  
00660. JSR PlayerProj_UpdateAndDraw ; Update and draw this Player Projectile 
00661.  
00662. DEC <SlotIndexBackup ; SlotIndexBackup = 0 
00663. DEX ; X = 0 
00664.  
00665. PlayerProj_UpdateAndDraw: 
00666. LDA PlayerProj_ID,X 
00667. BEQ PRG007_A328 ; If Player Projectile slot is empty, jump to PRG007_A328 (RTS) 
00668.  
00669. CMP #$03 
00670. BLT PRG007_A33F ; If Player Projectile ID < 3 (not the fireball poof), jump to PRG007_A33F 
00671.  
00672. JMP PRG007_A705 ; Jump to PRG007_A705 
00673.  
00674. PRG007_A33F: 
00675.  
00676. ; Hammer or Fireball... 
00677.  
00678. LDA AScrlURDiag_WrapState_Copy 
00679. BEQ PRG007_A361 ; If diagonal scroller is not wrapping, jump to PRG007_A361 
00680.  
00681. LDA <Player_HaltGame 
00682. BNE PRG007_A361 ; If gameplay is halted, jump to PRG007_A361 
00683.  
00684. ; Offset Player projectile to compensate for the diagonal autoscroller's wrap 
00685. LDA PlayerProj_X,X 
00686. ADD AScrlURDiag_OffsetX 
00687. STA PlayerProj_X,X 
00688. LDA PlayerProj_Y,X 
00689. ADD AScrlURDiag_OffsetY 
00690. STA PlayerProj_Y,X 
00691.  
00692. BCC PRG007_A361 
00693. INC PlayerProj_YHi,X ; Apply carry 
00694.  
00695. PRG007_A361: 
00696. LDY <Player_HaltGame 
00697. BNE PRG007_A3DB ; If gameplay halted, jump to PRG007_A3DB 
00698.  
00699. LDA PlayerProj_YVel,X 
00700.  
00701. LDY Level_AScrlConfig 
00702. BEQ PRG007_A371 ; If no auto scroll effect is active, jump to PRG007_A371 
00703.  
00704. ADD Level_ScrollDiffV ; Add auto scroll's vertical delta to Player's Y velocity 
00705.  
00706. PRG007_A371: 
00707. PHA ; Save Projectile Y Velocity 
00708.  
00709. LDY #$00 ; Y = $00 (16-bit sign extension) 
00710.  
00711. PLA ; Restore Projectile Y Velocity 
00712. BPL PRG007_A378 ; If not negative, jump to PRG007_A378 
00713.  
00714. DEY ; Y = $FF (16-bit sign extension) 
00715.  
00716. PRG007_A378: 
00717. ADD PlayerProj_Y,X ; Apply Y velocity 
00718. STA PlayerProj_Y,X ; Update Y 
00719.  
00720. ; Cascade into Y Hi 
00721. TYA 
00722. ADC PlayerProj_YHi,X 
00723. STA PlayerProj_YHi,X 
00724.  
00725. INC PlayerProj_Cnt,X ; PlayerProj_Cnt++ 
00726.  
00727. LDA PlayerProj_ID,X 
00728. CMP #$02 
00729. BNE PRG007_A3C0 ; If this is NOT the hammer, jump to PRG007_A3C0 
00730.  
00731. ; Hammer specific velocity code... 
00732.  
00733. LDA PlayerProj_XVel,X 
00734. ASL A 
00735. ASL A 
00736. ASL A 
00737. ASL A ; Fractional part shifted up 
00738. ADD PlayerProj_XVelFrac,X 
00739. STA PlayerProj_XVelFrac,X ; Add to object's X vel fractional accumulator 
00740.  
00741. PHP ; Save CPU status 
00742.  
00743. LDA PlayerProj_XVel,X ; Get X Velocity 
00744. LSR A 
00745. LSR A 
00746. LSR A 
00747. LSR A ; Whole part shifted down (integer) 
00748. CMP #%00001000 ; Check the sign bit 
00749. BLT PRG007_A3AC ; If the value was not negatively signed, jump to PRG007_A3AC 
00750. ORA #%11110000 ; Otherwise, apply a sign extension 
00751. PRG007_A3AC: 
00752. PLP ; Restore CPU status 
00753.  
00754. ADC PlayerProj_X,X ; Apply X velocity 
00755. STA PlayerProj_X,X ; Update X 
00756.  
00757. LDA PlayerProj_Cnt,X 
00758. AND #$07 
00759. BNE PRG007_A3BD ; 1:8 ticks proceed, otherwise jump to PRG007_A3BD 
00760.  
00761. INC PlayerProj_YVel,X ; Increase Y velocity (gravity) 
00762.  
00763. PRG007_A3BD: 
00764. JMP PRG007_A3DB ; Jump to PRG007_A3DB 
00765.  
00766. PRG007_A3C0: 
00767.  
00768. ; Fireball specific velocity code... 
00769.  
00770. ; X velocity is applied as integer (no fractional accumulator) 
00771. LDA PlayerProj_X,X 
00772. ADD PlayerProj_XVel,X 
00773. STA PlayerProj_X,X 
00774.  
00775. LDA PlayerProj_YVel,X 
00776. CMP #$04 
00777. BEQ PRG007_A3DB ; If fireball's Y velocity = 4, jump to PRG007_A3DB 
00778.  
00779. LDA PlayerProj_Cnt,X 
00780. AND #$03 
00781. BNE PRG007_A3DB ; 1:4 ticks proceed, otherwise jump to PRG007_A3DB 
00782.  
00783. INC PlayerProj_YVel,X ; Increase Y velocity (gravity) 
00784.  
00785. PRG007_A3DB: 
00786.  
00787. ; Fireball/Hammer common... 
00788.  
00789. ; Temp_Var2 = scroll relative X 
00790. LDA PlayerProj_X,X 
00791. SUB <Horz_Scroll 
00792. STA <Temp_Var2  
00793.  
00794. ADD #11 
00795. CMP #19 
00796. BGE PRG007_A3F0 ; If Player Projectile X >= 19, jump to PRG007_A3F0 
00797.  
00798. PRG007_A3EA: 
00799. ; Otherwise remove it and let's get out of here! 
00800. LDA #$00 
00801. STA PlayerProj_ID,X 
00802.  
00803. PRG007_A3EF: 
00804. RTS ; Return 
00805.  
00806. PRG007_A3F0: 
00807. ADC #-$08 ; X Relative - 8 
00808. STA <Temp_Var14 ; -> Temp_Var14 
00809.  
00810. LDA PlayerProj_ID,X 
00811. CMP #$01 
00812. BNE PRG007_A400 ; If this is NOT the fireball, jump to PRG007_A400 
00813.  
00814. ; Fireball only... 
00815.  
00816. LDA PlayerProj_YVel,X 
00817. BMI PRG007_A40E ; If fireball is moving upward, jump to PRG007_A40E 
00818.  
00819. PRG007_A400: 
00820. LDA PlayerProj_Y,X 
00821. CMP Level_VertScroll 
00822. LDA PlayerProj_YHi,X 
00823. SBC Level_VertScrollH 
00824. BMI PRG007_A3EF ; If Player projectile is vertically off-screen, jump to PRG007_A3EF (RTS) 
00825.  
00826. PRG007_A40E: 
00827. TXA 
00828. ASL A 
00829. ASL A ; A = Player Projectile slot index * 4 
00830. ADD Object_SprRAM+6 ; Offset into high end Sprite RAM 
00831. TAY ; -> 'Y' 
00832.  
00833. ; Set projectile sprite X 
00834. LDA <Temp_Var2 
00835. STA Sprite_RAM+$03,Y 
00836.  
00837. LDA PlayerProj_Y,X 
00838. SUB Level_VertScroll 
00839. CMP #192 
00840. BGE PRG007_A3EA ; If projectile relative Y >= 192, jump to PRG007_A3EA (too low, remove projectile) 
00841.  
00842. ; Set projectile sprite Y 
00843. STA Sprite_RAM+$00,Y 
00844.  
00845. ADC #14 ; Y + 14 
00846. STA <Temp_Var13 ; -> Temp_Var13 
00847.  
00848. ; Temp_Var3 = initial sprite attribute by Player's travel direction 
00849. LDA PlayerProj_XVel,X 
00850. LSR A ; Sign bit shifted right 
00851. AND #SPR_HFLIP 
00852. STA <Temp_Var3 
00853.  
00854. LDA PlayerProj_ID,X 
00855. CMP #$02 
00856. BNE PRG007_A471 ; If this is NOT the hammer, jump to PRG007_A471 
00857.  
00858. ; Hammer only... 
00859.  
00860. LDA <Player_Suit 
00861. CMP #PLAYERSUIT_HAMMER 
00862. BNE PlayerProj_ChangeToPoof ; If Player is NOT wearing the Hammer Suit anymore (uh oh), jump to PlayerProj_ChangeToPoof 
00863.  
00864. LDA PlayerProj_Cnt,X 
00865. LSR A 
00866. LSR A 
00867. AND #$03 
00868. TAX ; X = 0 to 3 
00869.  
00870. LDA PlayerHammer_XOff,X ; Get X offset 
00871. BIT <Temp_Var3 ; Check for horizontal flip 
00872. BVC PRG007_A453 ; If no flip, jump to PRG007_A453 
00873.  
00874. EOR #$06 ; Otherwise, invert X offset 
00875.  
00876. PRG007_A453: 
00877. ADD <Temp_Var2 ; Apply X offset 
00878. STA Sprite_RAM+$03,Y ; Set Hammer X 
00879.  
00880. LDA PlayerHammer_YOff,X ; Get Y offset 
00881. ADD Sprite_RAM+$00,Y ; Add to Sprite Y 
00882. STA Sprite_RAM+$00,Y ; Update Sprite Y 
00883.  
00884. ; Hammer pattern 
00885. LDA #$d7 
00886. STA Sprite_RAM+$01,Y 
00887.  
00888. LDA <Temp_Var3 ; Get horizontal flip bit 
00889. EOR PlayerHammer_FlipBits,X ; XOR in the hammer flip bits 
00890.  
00891. SEC ; Set carry (hammer) 
00892. JMP PRG007_A485 ; Jump to PRG007_A485 
00893.  
00894. PRG007_A471: 
00895.  
00896. ; Fireball only... 
00897.  
00898. LDA Level_NoStopCnt 
00899. LSR A 
00900. LSR A 
00901. AND #$03 
00902. TAX ; X = 0 to 3 
00903.  
00904. ; Set fireball pattern 
00905. LDA PlayerFireball_Pats,X 
00906. STA Sprite_RAM+$01,Y 
00907.  
00908. ; Set fireball attributes 
00909. LDA <Temp_Var3 ; Get horizontal flip bit 
00910. EOR PlayerFireball_FlipBits,X ; XOR in the fireball flip bits 
00911.  
00912. CLC ; Clear carry (fireball) 
00913.  
00914. PRG007_A485: 
00915. LDX Player_Behind 
00916. BEQ PRG007_A48C ; If Player is not "behind the scenes", jump to PRG007_A48C 
00917.  
00918. ORA #SPR_BEHINDBG ; Set priority 
00919.  
00920. PRG007_A48C: 
00921. STA Sprite_RAM+$02,Y ; Set Player Projectile attributes 
00922.  
00923. LDX <SlotIndexBackup ; X = Player Projectile slot index 
00924.  
00925. LDA <Player_HaltGame 
00926. BNE PRG007_A4A2 ; If gameplay is halted, jump to PRG007_A4A2 
00927.  
00928. ; Gameplay not halted... 
00929.  
00930. BCS PRG007_A49A ; If this is the hammer, jump to PRG007_A49A (PlayerProj_HitEnemies) 
00931.  
00932. JSR Fireball_DetectWorld ; Hit tests for fireball (bounce, poof, etc.) 
00933.  
00934. PRG007_A49A: 
00935. JMP PlayerProj_HitEnemies ; Jump to PlayerProj_HitEnemies 
00936.  
00937. PlayerProj_ChangeToPoof: 
00938.  
00939. ; Change Player Projectile to "Poof" 
00940. LDA #$03 
00941. STA PlayerProj_ID,X 
00942.  
00943. PRG007_A4A2: 
00944. RTS ; Return 
00945.  
00946. Fireball_DetectWorld: 
00947. LDA Level_7Vertical 
00948. BEQ PRG007_A4CF ; If this is not a vertically oriented level, jump to PRG007_A4CF 
00949.  
00950. ; Vertical level... 
00951.  
00952. LDA <Temp_Var13 ; Detect Y of fireball 
00953. ADD Level_VertScroll ; Apply vertical scroll 
00954. STA <Temp_Var6 ; -> Temp_Var6 
00955.  
00956. AND #$f0 ; Aligned to grid row 
00957. STA <Temp_Var3 ; -> Temp_Var3 
00958.  
00959. ; Temp_Var2 = high byte of tile memory 
00960. LDA Level_VertScrollH ; Current vertical scroll high 
00961. ADC #HIGH(Tile_Mem) ; Add the upper byte of the Tile_Mem address 
00962. STA <Temp_Var2 ; -> Temp_Var2 
00963.  
00964. ; Temp_Var14 = fireball X + 4 
00965. LDA PlayerProj_X,X 
00966. ADC #$04 
00967. STA <Temp_Var14 
00968.  
00969. ; Temp_Var1 = Row/Column offset value 
00970. LSR A 
00971. LSR A 
00972. LSR A 
00973. LSR A 
00974. ORA <Temp_Var3 
00975. STA <Temp_Var1 
00976.  
00977. LDY #$00 ; Y = 0 (don't need additional offset) 
00978. JMP PRG007_A52D ; Jump to PRG007_A52D 
00979.  
00980. PRG007_A4CF: 
00981.  
00982. ; Non-vertical level... 
00983.  
00984. LDA Player_PartDetEn 
00985. BEQ PRG007_A4E7 ; If Player_PartDetEn is not enabled, jump to PRG007_A4E7 
00986.  
00987. ; When fireball Y >= 160, force detection of bottom two rows of tiles 
00988.  
00989. LDA <Temp_Var13 ; Detect Y of fireball 
00990. CMP #160 
00991. BLT PRG007_A4E9 ; If < 160, jump to PRG007_A4E9 
00992.  
00993. SBC #16 ; Detect Y - 16 
00994. STA <Temp_Var6 ; -> Temp_Var6 
00995.  
00996. AND #$f0 ; Aligned to grid row 
00997. STA <Temp_Var3 ; -> Temp_Var3 
00998.  
00999. LDA #$01 ; A = 1 (force bottom tiles) 
01000. JMP PRG007_A4F8 ; Jump to PRG007_A4F8 
01001.  
01002. PRG007_A4E7: 
01003. LDA <Temp_Var13 ; Detect Y of fireball 
01004.  
01005. PRG007_A4E9: 
01006. ADD Level_VertScroll ; Apply vertical scroll 
01007. STA <Temp_Var6 ; -> Temp_Var6 
01008.  
01009. AND #$f0 ; Aligned to grid row 
01010. STA <Temp_Var3 ; -> Temp_Var3 
01011.  
01012. LDA Level_VertScrollH ; Current vertical scroll high 
01013. ADC #$00 ; Apply carry 
01014.  
01015. PRG007_A4F8 
01016. STA <Temp_Var4 ; -> Temp_Var4 
01017. BEQ PRG007_A506 ; If vertical high = 0, jump to PRG007_A506 
01018.  
01019. CMP #$02 
01020. BGE PRG007_A557 ; If vertical high >= 2 (way too low), jump to PRG007_A557 
01021.  
01022. LDA <Temp_Var3 
01023. CMP #$B0 
01024. BGE PRG007_A557 ; If at or lower than $1B0 (too low), jump to PRG007_A557 
01025.  
01026. PRG007_A506: 
01027. LDA <Temp_Var14 ; Fireball detect X 
01028. ADD <Horz_Scroll ; Apply horizontal scroll 
01029. STA <Temp_Var5 ; -> Temp_Var5 
01030.  
01031. LDA <Horz_Scroll_Hi 
01032. ADC #$00 
01033. STA <Temp_Var7 ; High value -> Temp_Var7 
01034.  
01035. ASL A ; Multiply by 2 for Tile_Mem_Addr index 
01036. TAY ; -> 'Y' 
01037.  
01038. ; Temp_Var1 = low byte of Tile_Mem_Addr 
01039. LDA Tile_Mem_Addr,Y 
01040. STA <Temp_Var1 
01041.  
01042. ; Temp_Var2 = high byte of Tile_Mem_Addr 
01043. LDA <Temp_Var4 
01044. AND #$01 ; Only 0 or 1 is valid in non-vertical 
01045. ADD Tile_Mem_Addr+1,Y 
01046. STA <Temp_Var2 
01047.  
01048. ; Y = row/column offset index 
01049. LDA <Temp_Var5 
01050. LSR A 
01051. LSR A 
01052. LSR A 
01053. LSR A 
01054. ORA <Temp_Var3 
01055. TAY 
01056.  
01057. PRG007_A52D: 
01058. LDA [Temp_Var1],Y ; Get the tile at the Player Projectile  
01059. JSR PSwitch_SubstTileAndAttr ; Handle P-Switch changed tiles 
01060. PHA ; Save adjusted tile 
01061.  
01062. ASL A 
01063. ROL A 
01064. ROL A 
01065. AND #$03 
01066. TAY ; Y = quadrant of tile 
01067. STY <Temp_Var2 ; -> Temp_Var2 
01068.  
01069. PLA ; Restore adjusted tile 
01070. STA <Temp_Var1 ; -> Temp_Var1 
01071.  
01072. CMP Tile_AttrTable,Y 
01073. BLT PRG007_A557 ; If this tile is not solid on top, jump to PRG007_A557 
01074.  
01075. ; Tile is solid on top... 
01076.  
01077. CMP Tile_AttrTable+4,Y 
01078. BLT PRG007_A59F ; If this tile is not solid on the sides/bottom, jump to PRG007_A59F 
01079.  
01080. ; Tile is solid all around 
01081.  
01082. LDY Level_TilesetIdx 
01083. CPY #$0b 
01084. BNE PRG007_A566 ; If this is not an Ice level, jump to PRG007_A566 
01085.  
01086. CMP #TILE12_FROZENMUNCHER 
01087. BNE PRG007_A55D ; If the fireball did not hit a frozen muncher, jump to PRG007_A55D 
01088.  
01089. ; Fireball hit a frozen muncher! 
01090.  
01091. LDA #CHNGTILE_FROZENMUNCHER 
01092. BNE PRG007_A563 ; Jump (technically always) to PRG007_A563 
01093.  
01094. PRG007_A557: 
01095.  
01096. ; Fireball_HitChkPass = 0 
01097. LDA #$00 
01098. STA Fireball_HitChkPass,X 
01099.  
01100. RTS ; Return 
01101.  
01102. PRG007_A55D: 
01103. CMP #TILE12_FROZENCOIN 
01104. BNE PRG007_A566 ; If the fireball did not hit a frozen coin, jump to PRG007_A566 
01105.  
01106. ; Fireball hit a frozen coin! 
01107.  
01108. LDA #CHNGTILE_FROZENCOIN 
01109.  
01110. PRG007_A563: 
01111. JSR Fireball_ThawTile ; Thaw the frozen tile! 
01112.  
01113. PRG007_A566: 
01114. LDA <Temp_Var1 
01115.  
01116. LDY Level_SlopeEn 
01117. BEQ PRG007_A579 ; If this level is NOT sloped, jump to PRG007_A579 
01118.  
01119. ; If this is a slope level and fireball hit level ground, jump to PRG007_A594 
01120. CMP #TILE14_ABOVE_MIDGROUND 
01121. BEQ PRG007_A594 
01122. CMP #TILE3_MIDGROUND 
01123. BEQ PRG007_A594 
01124. CMP #TILE3_WMIDGROUND 
01125. BEQ PRG007_A594 
01126.  
01127. PRG007_A579: 
01128. INC Fireball_HitChkPass,X ; Fireball_HitChkPass++ 
01129.  
01130. LDA Fireball_HitChkPass,X 
01131. CMP #$02 
01132. BNE PRG007_A586 ; If Fireball_HitChkPass <> 2, jump to PRG007_A586 
01133.  
01134. ; Fireball has been through hit check too many times, it's obviously done 
01135.  
01136. JMP PRG007_A637 ; Jump to PRG007_A637 ("Poof" away, fireball..) 
01137.  
01138. PRG007_A586: 
01139.  
01140. ; Fireball Y -= 2 
01141. LDA PlayerProj_Y,X 
01142. SUB #$02 
01143. STA PlayerProj_Y,X 
01144. BCS PRG007_A594 
01145. DEC PlayerProj_YHi,X ; Apply carry 
01146. PRG007_A594: 
01147.  
01148. ; Bounce fireball! 
01149. LDA #-$03 
01150.  
01151. PRG007_A596: 
01152. STA PlayerProj_YVel,X 
01153.  
01154. ; Reset counter to 3 
01155. LDA #$03 
01156. STA PlayerProj_Cnt,X 
01157.  
01158. RTS ; Return 
01159.  
01160. PRG007_A59F: 
01161.  
01162. ; Tile not solid on sides/bottom... 
01163.  
01164. LDA Level_SlopeEn 
01165. BNE PRG007_A5DC ; If this is a sloped level, jump to PRG007_A5DC 
01166.  
01167. ; Not a sloped level... 
01168.  
01169. LDA <Temp_Var6 ; Relative Y of fireball 
01170. AND #$0f ; Within tile 
01171. CMP #$05  
01172. BLT PRG007_A594 ; If fireball is high enough on the top-solid-only tile, then bounce! (Jump to PRG007_A594) 
01173.  
01174. RTS ; Return 
01175.  
01176.  
01177. Fireball_ThawTile: 
01178. STA Level_ChgTileEvent ; Queue tile change event! 
01179.  
01180. JSR BrickBust_MoveOver ; Open up a brick bust 
01181.  
01182. ; Brick bust "poof" style (over top of the changing tile) 
01183. LDA #$01 
01184. STA BrickBust_En 
01185.  
01186. ; Set block change Y  
01187. LDA <Temp_Var3 
01188. STA Level_BlockChgYLo 
01189.  
01190. ; Set poof Y 
01191. SBC Level_VertScroll 
01192. STA BrickBust_YUpr 
01193.  
01194. ; Set block change Y Hi 
01195. LDA <Temp_Var4 
01196. STA Level_BlockChgYHi 
01197.  
01198. ; Set block change X 
01199. LDA <Temp_Var5 
01200. AND #$f0 
01201. STA Level_BlockChgXLo 
01202.  
01203. ; Set poof X 
01204. SBC <Horz_Scroll 
01205. STA BrickBust_X  
01206.  
01207. ; Set block change X Hi 
01208. LDA <Temp_Var7 
01209. STA Level_BlockChgXHi 
01210.  
01211. JMP PlayerProj_ChangeToPoof ; Change the projectile itself into a poof 
01212.  
01213.  
01214. PRG007_A5DC: 
01215.  
01216. ; Temp_Var6 will remain as "Y offset within tile" 
01217. LDA <Temp_Var6 
01218. AND #$0f 
01219. STA <Temp_Var6 
01220.  
01221. ; Temp_Var5 will remain as "X offset within tile" 
01222. LDA <Temp_Var5 
01223. AND #$0f 
01224. STA <Temp_Var5 
01225.  
01226. LDY <Temp_Var2 ; Y = tile quadrant 
01227. TYA 
01228. ASL A 
01229. TAX ; X = tile quadrant * 2 (2 byte index into Level_SlopeSetByQuad) 
01230.  
01231. ; Temp_Var3/4 pointer into appropriate Level_SlopeSetByQuad 
01232. LDA Level_SlopeSetByQuad,X 
01233. STA <Temp_Var3 
01234. LDA Level_SlopeSetByQuad+1,X 
01235. STA <Temp_Var4 
01236.  
01237. LDX <SlotIndexBackup ; X = Player Projectile index 
01238.  
01239. LDA <Temp_Var1 
01240. SUB Tile_AttrTable,Y 
01241. TAY ; Y = tile made relative to solid set 
01242.  
01243. LDA [Temp_Var3],Y 
01244. TAY ; Y = slope offset for this tile 
01245.  
01246. LDA Slope_ObjectVel_Effect,Y 
01247. CMP #$80 
01248. BEQ PRG007_A637 ; If this tile has no effect, jump to PRG007_A637 ("Poof" away, fireball..) 
01249.  
01250. STA <Temp_Var7 ; Effect value -> Temp_Var7 
01251.  
01252. TYA 
01253. ASL A 
01254. ASL A 
01255. ASL A 
01256. ASL A ; Multiply relative tile index by 16 (because 16 slope values exist across each 16x16 tile) 
01257. ADD <Temp_Var5 ; Add specific offset across tile 
01258. TAY ; -> 'Y' 
01259.  
01260. ; Lower 4 bits of Slope_LUT (the "sloped floor height" component) -> Temp_Var2 
01261. LDA Slope_LUT,Y 
01262. AND #$0f 
01263. STA <Temp_Var2 
01264.  
01265. LDA <Temp_Var6 
01266. CMP #12 
01267. BGE PRG007_A626 ; If fireball is deeper than 12 pixels into the tile, jump to PRG007_A626 
01268.  
01269. CMP <Temp_Var2 
01270. BLT PRG007_A645 ; If fireball is higher than the slope height, jump to PRG007_A645 (RTS) 
01271.  
01272. PRG007_A626: 
01273. LDA <Temp_Var7 
01274. BEQ PRG007_A642 ; If effect value = 0, jump to PRG007_A642 
01275.  
01276. LDY #-$05 ; Y = -$05 (high bounce velocity) 
01277. EOR PlayerProj_XVel,X 
01278. BMI PRG007_A633 
01279. LDY #-$02 ; Y = -$02 (low bounce velocity) 
01280. PRG007_A633: 
01281. TYA 
01282. JMP PRG007_A596 ; Jump to PRG007_A596 
01283.  
01284. PRG007_A637: 
01285.  
01286. ; "Bump" sound 
01287. LDA Sound_QPlayer 
01288. ORA #SND_PLAYERBUMP 
01289. STA Sound_QPlayer 
01290.  
01291. JMP PlayerProj_ChangeToPoof ; Turn into a "poof" and don't come back! 
01292.  
01293. PRG007_A642: 
01294. JMP PRG007_A594 ; Jump to PRG007_A594 (another pass through the hit routines, should cause it to "poof" out) 
01295.  
01296. PRG007_A645: 
01297. RTS ; Return 
01298.  
01299. PlayerProj_HitEnemies: 
01300.  
01301. ; Fireball/hammer common... 
01302.  
01303. LDY #$04 ; Y = 4 (enemies only exist in the lower slots) 
01304. PRG007_A648: 
01305. LDA Objects_SprHVis,Y 
01306. ORA Objects_SprVVis,Y 
01307. BNE PRG007_A667 ; If object has sprites horizontally or vertically off-screen, jump to PRG007_A667 (Forget it!) 
01308.  
01309. LDX Objects_State,Y ; X = object's state 
01310. LDA Obj2Obj_EnByState,X 
01311. BNE PRG007_A667 ; If this state does not support object-to-object (object-to-Projectile), jump to PRG007_A667 (Forget it!) 
01312.  
01313. LDX Level_ObjectID,Y ; X = object's ID 
01314. LDA Object_AttrFlags,X  
01315. STA <Temp_Var1 ; Object attribute flags -> Temp_Var1 
01316.  
01317. AND #OAT_WEAPONIMMUNITY 
01318. BNE PRG007_A667 ; If object is immune to Player weapons, jump to PRG007_A667 
01319.  
01320. JSR PlayerProj_HitObject ; See if Player Project hit an object and respond! 
01321.  
01322. PRG007_A667: 
01323. DEY ; Y-- 
01324. BPL PRG007_A648 ; While Y >= 0, loop 
01325.  
01326. LDX <SlotIndexBackup ; X = Player Projectile slot index 
01327.  
01328. PRG007_A66C: 
01329. RTS ; Return 
01330.  
01331. ; A Y range per bounding box index 
01332. Projectile_BBoxY: .byte $18, $18, $28, $18, $18, $18, $18, $18, $18, $18, $20, $18, $18, $28, $18, $18 
01333.  
01334. ; An X range per bounding box index 
01335. Projectile_BBoxX: .byte $10, $10, $10, $10, $10, $10, $10, $10, $10, $10, $10, $10, $10, $18, $10, $10 
01336.  
01337.  
01338. PlayerProj_HitObject: 
01339. LDA <Temp_Var1  
01340. AND #OAT_BOUNDBOXMASK 
01341. TAX ; X = Object's bounding box index 
01342. STX <Temp_Var2 ; -> Temp_var2 
01343.  
01344. LDA <Temp_Var13 ; Detect Y of projectile 
01345. SUB Objects_SpriteY,Y ; Difference against this object's Sprite Y 
01346. CMP Projectile_BBoxY,X 
01347. LDX <SlotIndexBackup ; X = Player Projectile slot index 
01348. BGE PRG007_A66C ; If projectile is out of range vertically, jump to PRG007_A66C (RTS) 
01349.  
01350. LDA <Temp_Var14 ; Detect X of projectile 
01351. SUB Objects_SpriteX,Y ; Difference against this object's Sprite X 
01352. LDX <Temp_Var2 ; X = bounding box index 
01353. CMP Projectile_BBoxX,X 
01354. LDX <SlotIndexBackup ; X = Player Projectile slot index 
01355. BGE PRG007_A6FD ; If projectile is out of range horizontally, jump to PRG007_A6FD (RTS) 
01356.  
01357. LDA PlayerProj_ID,X 
01358. CMP #$02 
01359. BEQ PRG007_A6BD ; If this is a hammer, jump to PRG007_A6BD 
01360.  
01361. JSR PlayerProj_ChangeToPoof ; "Poof" goes the fireball 
01362. JMP PRG007_A6C3 ; Jump to PRG007_A6C3 
01363.  
01364. PRG007_A6BD: 
01365.  
01366. ; Hammer hit... 
01367.  
01368. LDA <Temp_Var1 ; Object's attributes 
01369. BMI PRG007_A6FD ; If OAT_HITNOTKILL is set, jump to PRG007_A6FD (RTS) 
01370. BPL PRG007_A6C9 ; Otherwise, jump to PRG007_A6C9 
01371.  
01372. PRG007_A6C3: 
01373.  
01374. ; Fireball only... 
01375.  
01376. LDA <Temp_Var1 
01377. AND #OAT_FIREIMMUNITY 
01378. BNE PRG007_A6FE ; If object is immune to fire, jump to PRG007_A6FE 
01379.  
01380. PRG007_A6C9: 
01381.  
01382. ; Weapon successfully hit! 
01383.  
01384. ; Play "kick" sound 
01385. LDA Sound_QPlayer 
01386. ORA #SND_PLAYERKICK 
01387. STA Sound_QPlayer 
01388.  
01389. LDA Objects_HitCount,Y 
01390. BEQ PRG007_A6DD ; If enemy has no hits left, jump to PRG007_A6DD 
01391.  
01392. ; Otherwise, just remove a hit... 
01393. SUB #$01 
01394. STA Objects_HitCount,Y 
01395.  
01396. RTS ; Return 
01397.  
01398.  
01399. PRG007_A6DD: 
01400.  
01401. ; Enemy bounces upward a bit 
01402. LDA #-$34 
01403. STA Objects_YVel,Y 
01404.  
01405. ; Set object's velocity based on Player's velocity (sort of works) 
01406. LDA PlayerProj_XVel,X 
01407. ASL A 
01408. LDA #$0C 
01409. BCC PRG007_A6EC ; If Player's X Velocity is negative, jump to PRG007_A6EC 
01410. LDA #-$0C 
01411. PRG007_A6EC: 
01412. STA Objects_XVel,Y 
01413.  
01414. TYA 
01415. TAX ; object index -> 'X' 
01416.  
01417. ; 100 pts! 
01418. LDA #$05 
01419. JSR Score_PopUp 
01420.  
01421. LDX <SlotIndexBackup ; X = Player Projectile slot index 
01422.  
01423. ; But the enemy is killed... 
01424. LDA #OBJSTATE_KILLED 
01425. STA Objects_State,Y 
01426.  
01427. PRG007_A6FD: 
01428. RTS ; Return 
01429.  
01430. PRG007_A6FE: 
01431. JMP PRG007_A637 ; Jump to PRG007_A637 
01432.  
01433. Fireball_PoofPattern: .byte $45, $41, $43, $47 
01434.  
01435. PRG007_A705: 
01436.  
01437. ; Fireball poof! 
01438.  
01439. LDY <Player_HaltGame 
01440. BNE PRG007_A719 ; If gameplay halted, jump to PRG007_A719 
01441.  
01442. ; PlayerProj_ID is now the fireball poof counter for the remainder 
01443.  
01444. INC PlayerProj_ID,X ; PlayerProj_ID++ 
01445.  
01446. LDA PlayerProj_ID,X 
01447. CMP #$10 
01448. BNE PRG007_A719 ; If PlayerProj_ID <> $10, jump to PRG007_A719 
01449.  
01450. PRG007_A713: 
01451. ; Poof is over; clear it! 
01452. LDA #$00 
01453. STA PlayerProj_ID,X 
01454.  
01455. RTS ; Return 
01456.  
01457. PRG007_A719: 
01458. TXA 
01459. ADD <Counter_1 
01460. AND #$01 ; A = 0 or 1 
01461. ASL A 
01462. ASL A 
01463. ASL A ; A = 0 or 8 
01464. ADC #$18 ; A = $18 or $20 
01465. TAY ; -> 'Y' 
01466.  
01467. ; Set poof left sprite X 
01468. LDA PlayerProj_X,X 
01469. SBC #$04 
01470. SUB <Horz_Scroll 
01471. STA Sprite_RAM+$03,Y 
01472.  
01473. ; Set poof right sprite X 
01474. ADD #$08 
01475. STA Sprite_RAM+$07,Y 
01476.  
01477. LDA PlayerProj_Y,X 
01478. SUB Level_VertScroll 
01479. CMP #208 
01480. BGE PRG007_A713 ; If poof has fallen too low, jump to PRG007_A713 (remove it) 
01481.  
01482. ; Set left and right "poof" sprite Ys 
01483. STA Sprite_RAM+$00,Y 
01484. STA Sprite_RAM+$04,Y 
01485.  
01486. LDA PlayerProj_ID,X 
01487. LSR A 
01488. LSR A 
01489. TAX ; X = index into Fireball_PoofPattern 
01490. LDA Fireball_PoofPattern,X ; Get proper poof pattern 
01491.  
01492. ; Set left and right "poof" sprite pattern 
01493. STA Sprite_RAM+$01,Y 
01494. STA Sprite_RAM+$05,Y 
01495.  
01496. LDA #SPR_PAL1 
01497.  
01498. LDX Player_Behind 
01499. BEQ PRG007_A75F ; If Player is not behind the scenes, jump to PRG007_A75F 
01500.  
01501. ORA #SPR_BEHINDBG 
01502.  
01503. PRG007_A75F: 
01504. STA Sprite_RAM+$02,Y ; Set left sprite attributes 
01505. ORA #(SPR_HFLIP | SPR_VFLIP) 
01506. STA Sprite_RAM+$06,Y ; Set right sprite attributes 
01507.  
01508. LDX <SlotIndexBackup ; X = Player Projectile slot index 
01509.  
01510. RTS ; Return 
01511.  
01512.  
01513. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01514. ; Player_WaterOrWaterfallVizFX 
01515. ; 
01516. ; Visual effects for standing in a waterfall (splashing on head) 
01517. ; or the periodic bubbles underwater... 
01518. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01519.  
01520. ; Y offsets for periodic bubble generated by the Player while underwater 
01521. SwimBubble_YOff: 
01522. .byte $04, $04 ; Not a frog swimming frame 
01523. .byte $08, $08 ; Idle or left/right frog swimming 
01524. .byte $0D, $0D ; Down frog swim 
01525. .byte $00, $00 ; Up frog swim 
01526.  
01527. ; X offsets for periodic bubble generated by the Player while underwater (left is not horizontally flipped, right is h-flipped) 
01528. SwimBubble_XOff: 
01529. .byte $00, $0B ; Not a frog swimming frame 
01530. .byte $00, $0B ; Idle or left/right frog swimming 
01531. .byte $05, $05 ; Down frog swim 
01532. .byte $05, $05 ; Up frog swim 
01533.  
01534. Player_WaterOrWaterfallVizFX: 
01535. LDY Player_FlyTime 
01536. INY 
01537. BNE PRG007_A783 ; (Will be zero if Player_FlyTime = $FF, i.e. P-Wing) If not using P-Wing, jump to PRG007_A783 
01538.  
01539. ; Otherwise, clear kill tally (P-Wing does not net you 1-ups) 
01540. STY Kill_Tally 
01541.  
01542. PRG007_A783: 
01543. LDY <Player_HaltGame 
01544. BNE PRG007_A7F0 ; If gameplay halted, jump to PRG007_A7F0 (RTS) 
01545.  
01546. LDA Player_InWater 
01547. BEQ PRG007_A7F0 ; If Player is not underwater, jump to PRG007_A7F0 (RTS) 
01548.  
01549. ; Otherwise, clear kill tally (Being underwater also resets your chain stomping) 
01550. STY Kill_Tally 
01551.  
01552. CMP #$01 
01553. BEQ PRG007_A7F1 ; If Player_InWater = 1 (water, not waterfall), jump to PRG007_A7F1 
01554.  
01555. ; Player's in a waterfall! 
01556.  
01557. LDA <Player_YVel 
01558. CMP #$3c 
01559. BGS PRG007_A7A2 ; If Player's Y velocity >= $3C, jump to PRG007_A7A2 
01560.  
01561. INC <Player_YVel ; Player_YVel++ 
01562.  
01563. LDA <Counter_1 
01564. LSR A  
01565. BCC PRG007_A7A2 ; Every other tick, jump to PRG007_A7A2 
01566.  
01567. INC <Player_YVel ; Player_YVel++ 
01568.  
01569. PRG007_A7A2: 
01570. JSR Object_GetRandNearUnusedSpr 
01571. BEQ PRG007_A7F0 ; If no free sprite, jump to PRG007_A7F0 (RTS) 
01572.  
01573. LDA Player_OffScreen 
01574. BNE PRG007_A7F0 ; If Player is off-screen, jump to PRG007_A7F0 (RTS) 
01575.  
01576. ; Patterns for "splashing" effect seen above Player's head 
01577. LDA #$47 
01578. STA Sprite_RAM+$01,Y 
01579. STA Sprite_RAM+$05,Y 
01580.  
01581. LDA <Counter_1 
01582. LSR A 
01583. AND #$03 
01584. ADD #$05 ; Value of 5 to 8 
01585.  
01586. LDX Player_IsDucking 
01587. BNE PRG007_A7C6 ; If Player is ducking, jump to PRG007_A7C6 
01588.  
01589. LDX Player_Suit 
01590. BNE PRG007_A7C9 ; If Player is not small, jump to PRG007_A7C9 
01591.  
01592. PRG007_A7C6: 
01593. ADD #10 ; Small or ducking, +10 (15 to 18) 
01594.  
01595. PRG007_A7C9: 
01596. STA <Temp_Var1 ; -> Temp_Var1 
01597.  
01598. LDX <SlotIndexBackup ; Restore 'X' as slot index 
01599.  
01600. ; Sprite "splashing" effect Y 
01601. LDA <Player_SpriteY 
01602. ADD <Temp_Var1 
01603. SUB #10 
01604. STA Sprite_RAM+$00,Y 
01605. STA Sprite_RAM+$04,Y 
01606.  
01607. ; Sprite "splashing" effect X 
01608. LDA <Player_SpriteX 
01609. STA Sprite_RAM+$03,Y 
01610. ADD #$08 
01611. STA Sprite_RAM+$07,Y 
01612.  
01613. LDA <Counter_1 
01614. AND #$03 
01615. SUB #$02 ; A = -2 to 1 (spread value) 
01616.  
01617. JSR Draw_SpreadAndColorful ; Spreads out the two sprites and rotates the color palette 
01618.  
01619. PRG007_A7F0: 
01620. RTS ; Return 
01621.  
01622.  
01623. PRG007_A7F1: 
01624.  
01625. ; Player's in regular old water 
01626.  
01627. LDY #$7f ; Y = $7F ("slow" mask value for idle underwater player) 
01628.  
01629. LDA <Pad_Holding 
01630. AND #(PAD_A | PAD_LEFT | PAD_RIGHT) 
01631. BEQ PRG007_A7FB ; If Player is not pressing A, LEFT, or RIGHT (swim controls), jump to PRG007_A7FB 
01632.  
01633. LDY #$3f ; Y = $3F ("fast" mask value for idle underwater player) 
01634.  
01635. PRG007_A7FB: 
01636. TYA ; Mask -> 'Y' 
01637. AND <Counter_1 
01638. BNE PRG007_A80C ; Periodically jump to PRG007_A80C (RTS) 
01639.  
01640. ; SlotIndexBackup = 2 
01641. LDX #$02 
01642. PRG007_A802: 
01643. STX <SlotIndexBackup 
01644.  
01645. LDA Bubble_Cnt,X 
01646. BEQ PRG007_A80D ; If this bubble slot is empty, jump to PRG007_A80D 
01647.  
01648. DEX ; X-- 
01649. BPL PRG007_A802 ; While X >= 0, loop! 
01650.  
01651. PRG007_A80C: 
01652. RTS ; Return 
01653.  
01654.  
01655. PRG007_A80D: 
01656. LDA RandomN 
01657. ORA #$10 
01658. STA Bubble_Cnt,X ; Set random value -> Bubble_Cnt 
01659.  
01660. LDY #$00 ; Y = 0 
01661.  
01662. LDA <Player_Frame 
01663. CMP #PF_FROGSWIM_UPBASE 
01664. BLT PRG007_A835 ; If Player is not within the low end range of frog suit swim frames, jump to PRG007_A835 
01665.  
01666. LDY #$03 ; Otherwise, Y = 3 (pending this might be the "up" frame) 
01667.  
01668. CMP #PF_FROGHOP_BASE 
01669. BLT PRG007_A835 ; If frame < PF_FROGHOP_BASE (if true, then absolutely the "up" swim frame), jump to PRG007_A835 
01670.  
01671. LDY #$00 ; Otherwise, Y = 0 
01672.  
01673. CMP #PF_FROGSWIM_IDLEBASE 
01674. BLT PRG007_A835 ; If not possibly just the "idling" frog frames, jump to PRG007_A835 
01675.  
01676. INY ; Otherwise, Y = 1 (idle or left/right frog swim) 
01677.  
01678. CMP #PF_FROGSWIM_LRBASE+2 
01679. BLT PRG007_A835 ; Not a down swimming frame, jump to PRG007_A835 
01680.  
01681. INY ; Otherwise, Y = 2 (down frog swim) 
01682.  
01683. CMP #(PF_FROGSWIM_DOWNBASE+3) ; This is actually 1 passed the end of frog suit swim frames 
01684. BLT PRG007_A835 ; If within range of the last frog suit swim frame, jump to PRG007_A835 
01685.  
01686. LDY #$00 ; Otherwise, Y = 0 
01687.  
01688. PRG007_A835: 
01689.  
01690. ; Y *= 2 
01691. TYA 
01692. ASL A 
01693. TAY 
01694.  
01695. BIT <Player_FlipBits 
01696. BVC PRG007_A83D ; If Player is not horizontally flipped, jump to PRG007_A83D 
01697.  
01698. INY ; Otherwise, Y++ 
01699.  
01700. PRG007_A83D: 
01701. LDA #$00 ; A = 0 
01702.  
01703. LDX <Player_Suit 
01704. BNE PRG007_A845 ; If Player is not small, jump to PRG007_A845 
01705.  
01706. LDA #$08 ; Otherwise, A = 8 
01707.  
01708. PRG007_A845: 
01709. LDX <SlotIndexBackup ; X = slot backup 
01710.  
01711. ; Set Bubble Y 
01712. ADD <Player_Y 
01713. ADC SwimBubble_YOff,Y 
01714. STA Bubble_Y,X 
01715. LDA <Player_YHi 
01716. ADC #$00 
01717. STA Bubble_YHi,X 
01718.  
01719. ; Set Bubble X 
01720. LDA <Player_X 
01721. ADD SwimBubble_XOff,Y 
01722. STA Bubble_X,X 
01723. LDA <Player_XHi 
01724. ADC #$00 
01725. STA Bubble_XHi,X 
01726.  
01727. RTS ; Return 
01728.  
01729.  
01730. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01731. ; Bubbles_UpdateAndDraw 
01732. ; 
01733. ; Update and draw bubbles that appear underwater 
01734. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01735. Bubbles_UpdateAndDraw: 
01736. LDX #$03 ; X = 3 
01737. PRG007_A86A: 
01738. STX <SlotIndexBackup ; -> Slot index backup 
01739.  
01740. LDA Bubble_Cnt,X 
01741. BEQ PRG007_A874 ; If this bubble slot is not in use, jump to PRG007_A874 
01742.  
01743. JSR Bubble_UpdateAndDraw ; Update and draw this bubble 
01744.  
01745. PRG007_A874: 
01746. DEX ; X-- 
01747. BPL PRG007_A86A ; While X >= 0, loop! 
01748.  
01749. RTS ; Return 
01750.  
01751.  
01752. Bubble_UpdateAndDraw: 
01753. LDA <Player_HaltGame  
01754. BEQ PRG007_A87F ; If gameplay is not halted, juimp to PRG007_A89A 
01755.  
01756. JMP PRG007_A89A ; Otherwise, jump to PRG007_A89A 
01757.  
01758. PRG007_A87F: 
01759. INC Bubble_Cnt,X ; Bubble counter increment 
01760.  
01761. ; Fix bit 7 on bubble counter 
01762. LDA Bubble_Cnt,X 
01763. ORA #$80 
01764. STA Bubble_Cnt,X 
01765.  
01766. AND #%00110000 
01767. BEQ PRG007_A89A ; Periodically jump to PRG007_A89A 
01768.  
01769. DEC Bubble_Y,X ; Bubble Y -- 
01770.  
01771. LDY Bubble_Y,X 
01772. INY  
01773. BNE PRG007_A89A ; If no carry, jump to PRG007_A89A 
01774. DEC Bubble_YHi,X ; Apply carry 
01775.  
01776. PRG007_A89A: 
01777. LDA Level_7Vertical 
01778. BEQ PRG007_A8BF ; If this level is not vertical, jump to PRG007_A8F0 
01779.  
01780. ; Vertical level... 
01781.  
01782. LDA Bubble_Y,X 
01783. ADD #10 ; Bubble Y + 10 
01784. AND #$f0 
01785. STA <Temp_Var3 ; Temp_Var3 = bubble row (offset into tile memory) 
01786.  
01787. LDA Bubble_YHi,X 
01788. ADC #HIGH(Tile_Mem) 
01789. STA <Temp_Var2 ; Temp_Var2 = bubble high offset into tile memory 
01790.  
01791. ; Create row/column offset into tile memory for current screen of bubble -> Temp_var1 
01792. LDA Bubble_X,X 
01793. LSR A 
01794. LSR A 
01795. LSR A 
01796. LSR A 
01797. ORA <Temp_Var3 
01798. STA <Temp_Var1 
01799.  
01800. LDY #$00 ; Y = 0 (not using the offset like non-vertical does) 
01801. BEQ PRG007_A8F0 ; Jump (technically always) to PRG007_A8F0 
01802.  
01803. PRG007_A8BF: 
01804. LDA Bubble_Y,X 
01805. ADD #10 ; Bubble Y + 10 
01806. AND #$f0 
01807. STA <Temp_Var3 ; Temp_Var3 = bubble row (offset into tile memory) 
01808.  
01809. LDA Bubble_YHi,X 
01810. ADC #$00 ; Apply carry 
01811. PHA ; Save it 
01812.  
01813. ; Temp_Var5 = bubble X 
01814. LDA Bubble_X,X 
01815. STA <Temp_Var5 
01816.  
01817. LDA Bubble_XHi,X 
01818. ASL A ; 2 bytes per screen 
01819. TAY ; Y = offset into Tile_Mem_Addr 
01820.  
01821. LDA Tile_Mem_Addr,Y 
01822. STA <Temp_Var1 ; Temp_Var1 = low byte of this screen's tile memory address 
01823.  
01824. PLA ; Restore Bubble's Y Hi 
01825. AND #$01 ; Only 0/1 valid for non-vertical 
01826. ADD Tile_Mem_Addr+1,Y ; Add to high byte of address 
01827. STA <Temp_Var2 ; -> Temp_Var2 
01828.  
01829. ; Create row/column offset -> Temp_Var3 
01830. LDA <Temp_Var5 
01831. LSR A  
01832. LSR A  
01833. LSR A  
01834. LSR A  
01835. ORA <Temp_Var3 
01836.  
01837. TAY ; Y = this offset 
01838.  
01839. PRG007_A8F0: 
01840. LDA [Temp_Var1],Y ; Get the tile the bubble detects 
01841.  
01842. PHA ; Save it 
01843.  
01844. ; Get tile "quadrant" -> Temp_Var1 
01845. ASL A 
01846. ROL A 
01847. ROL A 
01848. AND #$03 
01849. STA <Temp_Var1 
01850.  
01851. PLA ; Restore specific tile 
01852. STA <Temp_Var2 ; -> Temp_Var2 
01853.  
01854. LDY <Temp_Var1 ; Y = tile quadrant 
01855. CMP Tile_AttrTable,Y 
01856. BGE PRG007_A91E ; If this tile is solid, jump to PRG007_A91E (destroy bubble) 
01857.  
01858. LDA Level_TilesetIdx 
01859. ASL A 
01860. ASL A ; Tileset index * 4 
01861. ADD <Temp_Var1 ; + quadrant 
01862. TAY ; -> 'Y' (offset into Level_MinTileUWByQuad) 
01863.  
01864. LDA <Temp_Var2 
01865. CMP #TILE1_WFALLTOP 
01866. BEQ PRG007_A91E ; If this is the top of a waterfall, jump to PRG007_A915 (indirect to PRG007_A91E) 
01867.  
01868. CMP #TILE1_WFALLMID 
01869.  
01870. PRG007_A915: 
01871. BEQ PRG007_A91E ; If this is the top or middle of a waterfall, jump to PRG007_A91E 
01872.  
01873. LDA Level_MinTileUWByQuad,Y 
01874. CMP <Temp_Var2 
01875. BLT Bubble_Draw ; If this tile is still considered underwater, jump to Bubble_Draw  
01876.  
01877. PRG007_A91E: 
01878.  
01879. ; Remove this bubble 
01880. LDA #$00 
01881. STA Bubble_Cnt,X 
01882.  
01883. RTS ; Return 
01884.  
01885. Bubble_XOff: .byte $00, $01, $00, -$01 
01886. Bubble_SprRAMOff: .byte $10, $14, $0C, $FF, $10, $14, $0C 
01887.  
01888. Bubble_Draw: 
01889. LDA Level_NoStopCnt 
01890. AND #%00001100 
01891. LSR A  
01892. LSR A  
01893. TAY ; Y = 0 to 3 
01894.  
01895. ; Temp_Var1 = bubble's X offset 
01896. LDA Bubble_XOff,Y 
01897. STA <Temp_Var1 
01898.  
01899. LDA <Counter_1 
01900. AND #%00000011 
01901. ADC <SlotIndexBackup  
01902. TAY ; Y = (0 to 3) + bubble's index 
01903.  
01904. LDA Bubble_SprRAMOff,Y 
01905. BMI PRG007_A978 ; If we hit the $FF value in Bubble_SprRAMOff, jump to PRG007_A978 (RTS) 
01906.  
01907. TAY ; -> 'Y' 
01908.  
01909. LDA Sprite_RAM+$00,Y 
01910. CMP #$f8 
01911. BNE PRG007_A978 ; If this sprite is not free, jump to PRG007_A978 (RTS) 
01912.  
01913. ; Bubble Y 
01914. LDA Bubble_Y,X 
01915. SUB Level_VertScroll 
01916. STA Sprite_RAM+$00,Y 
01917.  
01918. CMP #200 
01919. BGE PRG007_A91E ; If this bubble's sprite Y >= 200, jump to PRG007_A91E (destroy bubble) 
01920.  
01921. ; Bubble X 
01922. LDA Bubble_X,X 
01923. ADD <Temp_Var1 
01924. SUB <Horz_Scroll 
01925. STA Sprite_RAM+$03,Y 
01926.  
01927. CMP #248 
01928. BCS PRG007_A91E ; If this bubble's X >= 248, jump to PRG007_A91E (destroy bubble) 
01929.  
01930. ; Bubble's pattern 
01931. LDA #$17 
01932. STA Sprite_RAM+$01,Y 
01933.  
01934. ; Bubble's attributes 
01935. LDA #SPR_PAL1 
01936. STA Sprite_RAM+$02,Y 
01937.  
01938. PRG007_A978: 
01939. RTS ; Return 
01940.  
01941.  
01942. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01943. ; Splash_UpdateAndDraw 
01944. ; 
01945. ; Update and draw water surface splashes 
01946. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
01947. Splash_UpdateAndDraw: 
01948. LDX #$02 ; X = 2 
01949. PRG007_A97B: 
01950. STX <SlotIndexBackup ; -> Slot Index backup 
01951.  
01952. LDA Splash_Counter,X 
01953. BEQ PRG007_A9A0 ; If no splash is active here, jump to PRG007_A9A0 
01954.  
01955. LDA <Player_HaltGame 
01956.  
01957. ; This probably used to skip something if gameplay was halted, i.e. (BNE xxxx) 
01958. NOP 
01959. NOP 
01960.  
01961. INC Splash_Counter,X ; Splash counter++ 
01962.  
01963. LDA <Counter_1 
01964. LSR A 
01965. BCC PRG007_A991 ; Every other tick, jump to PRG007_A991 
01966.  
01967. INC Splash_Counter,X ; Splash counter++ 
01968.  
01969. PRG007_A991: 
01970. LDA Splash_Counter,X 
01971. CMP #$30 
01972. BLT PRG007_A99D ; If splash counter < $30, jump to PRG007_A99D 
01973.  
01974. JSR Splash_Remove ; Remove this splash 
01975. BEQ PRG007_A9A0 ; Jump (technically always) to PRG007_A9A0 
01976.  
01977. PRG007_A99D: 
01978. JSR Splash_Draw ; Draw this splash 
01979.  
01980. PRG007_A9A0: 
01981. DEX ; X-- 
01982. BPL PRG007_A97B ; While X >= 0, loop! 
01983.  
01984. RTS ; Return 
01985.  
01986. Splash_Patterns: 
01987. .byte $11, $13, $15, $47, $47, $47 
01988.  
01989. Splash_Remove: 
01990.  
01991. ; Remove this splash 
01992. LDA #$00  
01993. STA Splash_Counter,X 
01994.  
01995. PRG007_A9AF: 
01996. RTS ; Return 
01997.  
01998. Splash_Draw: 
01999. JSR Object_GetRandNearUnusedSpr  
02000. BEQ PRG007_A9AF ; If no sprite available, jump to PRG007_A9AF (RTS) 
02001.  
02002. STY <Temp_Var1 ; Sprite RAM offset -> Temp_Var1 
02003.  
02004. LDA Splash_X,X 
02005. SUB <Horz_Scroll ; Make scroll relative X for splash 
02006.  
02007. CMP #240 
02008. BGE Splash_Remove ; If splash X >= 240, jump to Splash_Remove 
02009.  
02010. STA Sprite_RAM+$03,Y ; Set left splash sprite X 
02011.  
02012. ADC #$08 ; +8 
02013. STA Sprite_RAM+$07,Y ; Set right splash sprite X 
02014.  
02015. LDA Splash_Y,X ; Get splash Y 
02016.  
02017. LDY Splash_NoScrollY,X 
02018. BNE PRG007_A9D5 ; If Splash_NoScrollY is set, do not make splash Y scroll relative 
02019.  
02020. SUB Level_VertScroll ; Make scroll relative Y for splash 
02021.  
02022. PRG007_A9D5: 
02023. LDY <Temp_Var1 ; Y = sprite RAM offset 
02024.  
02025. CMP #$ae 
02026. BGE Splash_Remove ; If splash sprite RAM offset >= $AE (?), jump to Splash_Remove (remove it!) 
02027.  
02028. ; Set splash sprites Y 
02029. STA Sprite_RAM+$00,Y 
02030. STA Sprite_RAM+$04,Y 
02031.  
02032. ; Set left splash sprite attributes 
02033. LDA #SPR_PAL1 
02034. STA Sprite_RAM+$02,Y 
02035.  
02036. ; Set right splash sprite attributes 
02037. LDA #(SPR_PAL1 | SPR_HFLIP) 
02038. STA Sprite_RAM+$06,Y 
02039.  
02040. LDA Splash_Counter,X 
02041. LSR A 
02042. LSR A 
02043. LSR A 
02044. TAX ; X = splash counter / 8 
02045. STX <Temp_Var1 ; -> Temp_Var1 
02046.  
02047. ; Set splash sprite patterns 
02048. LDA Splash_Patterns,X 
02049. STA Sprite_RAM+$01,Y 
02050. STA Sprite_RAM+$05,Y 
02051.  
02052. LDX <SlotIndexBackup ; X = splash index 
02053.  
02054. LDA <Temp_Var1 
02055. CMP #$03 
02056. BLT PRG007_AA4C ; If (splash counter / 8) < 3, jump to PRG007_AA4C (RTS) 
02057.  
02058. LDA <Counter_1 
02059. AND #$01 
02060. ORA <Player_HaltGame 
02061. BNE PRG007_AA10 ; Every other tick or gameplay halted, jump to  
02062.  
02063. INC Splash_Y,X ; Splash_Y++ 
02064.  
02065. PRG007_AA10: 
02066. LDA Splash_Counter,X 
02067. SUB #24 
02068. LSR A  
02069. LSR A  
02070. LSR A  
02071. AND #$03 ; A = (splash counter - 24) / 8 
02072.  
02073. Draw_SpreadAndColorful: 
02074. STA <Temp_Var1  
02075.  
02076. ; Subtract from sprite X 
02077. LDA Sprite_RAM+$03,Y 
02078. SUB <Temp_Var1  
02079. STA Sprite_RAM+$03,Y 
02080.  
02081. ; Add to other sprite X 
02082. LDA Sprite_RAM+$07,Y 
02083. ADD <Temp_Var1 
02084. STA Sprite_RAM+$07,Y 
02085.  
02086. ; Set attributes of two sprites 
02087. LDA #SPR_PAL1 
02088. STA Sprite_RAM+$06,Y 
02089.  
02090. ORA #SPR_HFLIP 
02091. STA Sprite_RAM+$02,Y 
02092.  
02093. LDA Level_NoStopCnt 
02094. AND #$02 
02095. BNE PRG007_AA4C ; 2 ticks on, 2 ticks off; jump to PRG007_AA4C (RTS) 
02096.  
02097. ; Mess with attributes for a little sparkly fun 
02098. LDA <Temp_Var1 
02099. ORA #SPR_VFLIP 
02100. STA Sprite_RAM+$02,Y 
02101.  
02102. ORA #SPR_HFLIP 
02103. STA Sprite_RAM+$06,Y 
02104.  
02105. PRG007_AA4C: 
02106. RTS ; Return 
02107.  
02108.  
02109. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02110. ; Scores_GiveAndDraw 
02111. ; 
02112. ; Gives awarded points and draws score sprites. Also caps  
02113. ; the Kill_Tally variable at a maximum value of 8. 
02114. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02115.  
02116. ; Patterns for the left and right sprites of the score sprite ($FF means "don't display") 
02117. ; 10 20 40 80 100 200 400 800 1000 2000 4000 8000 1-up 
02118. Score_PatternLeft: .byte $FF, $FF, $FF, $FF, $5B, $63, $6B, $6D, $5B, $63, $6B, $6D, $61 
02119. Score_PatternRight: .byte $5B, $63, $6B, $6D, $69, $69, $69, $69, $59, $59, $59, $59, $6F 
02120.  
02121. ; Score to add (low byte) 
02122. ScoreAdd_L: 
02123. .byte LOW( 1) ; 10 points 
02124. .byte LOW( 2) ; 20 points 
02125. .byte LOW( 4) ; 40 points 
02126. .byte LOW( 8) ; 80 points 
02127. .byte LOW( 10) ; 100 points 
02128. .byte LOW( 20) ; 200 points 
02129. .byte LOW( 40) ; 400 points 
02130. .byte LOW( 80) ; 800 points 
02131. .byte LOW(100) ; 1000 points 
02132. .byte LOW(200) ; 2000 points 
02133. .byte LOW(400) ; 4000 points 
02134. .byte LOW(800) ; 8000 points 
02135. .byte $00 ; 1-up (no score value) 
02136.  
02137. ; Score to add (high byte) 
02138. ScoreAdd_H: 
02139. .byte HIGH( 1) ; 10 points 
02140. .byte HIGH( 2) ; 20 points 
02141. .byte HIGH( 4) ; 40 points 
02142. .byte HIGH( 8) ; 80 points 
02143. .byte HIGH( 10) ; 100 points 
02144. .byte HIGH( 20) ; 200 points 
02145. .byte HIGH( 40) ; 400 points 
02146. .byte HIGH( 80) ; 800 points 
02147. .byte HIGH(100) ; 1000 points 
02148. .byte HIGH(200) ; 2000 points 
02149. .byte HIGH(400) ; 4000 points 
02150. .byte HIGH(800) ; 8000 points 
02151. .byte $00 ; 1-up (no score value) 
02152.  
02153.  
02154. Scores_GiveAndDraw: 
02155. LDA Kill_Tally  
02156. CMP #$08 
02157. BLT PRG007_AA8D ; If Kill_Tally < 8, jump to PRG007_AA8D 
02158.  
02159. ; Max Kill_Tally at 8 
02160. LDA #$08 
02161. STA Kill_Tally 
02162.  
02163. PRG007_AA8D: 
02164. LDX #$04 ; X = 4 (all five on-screen "scores") 
02165. PRG007_AA8F: 
02166. STX <SlotIndexBackup ; Update SlotIndexBackup 
02167.  
02168. LDA Scores_Value,X 
02169. AND #$7f ; Keep only lower 7 bits 
02170. BEQ PRG007_AAAD ; If this score's value is $00 or $80, jump to PRG007_AAAD 
02171.  
02172. CMP #$0D 
02173. BLT PRG007_AAA8 ; If score value < $0D (1-up), jump to PRG007_AAA8 
02174.  
02175. LDA Scores_Value,X 
02176. AND #$80 ; Keep bit 7 
02177. ORA #$0d ; Cap at 1-up ($0D) regardless of value 
02178. STA Scores_Value,X ; Update value 
02179.  
02180. AND #$7f ; Keep only lower 7 bits 
02181.  
02182. PRG007_AAA8: 
02183. STA <Temp_Var1 ; Score value -> Temp_Var1 
02184. JSR Score_GiveAndDraw ; Give awarded points and draw score sprites 
02185.  
02186. PRG007_AAAD: 
02187. DEX ; X-- 
02188. BPL PRG007_AA8F ; While X >= 0, loop! 
02189. RTS ; Return 
02190.  
02191. Score_GiveAndDraw: 
02192. LDA Player_Grow ; If Player is growing up... 
02193. ORA Player_StarOff ; ... is losing invincibility (?) ... 
02194. ORA Player_SuitLost ; ... or has lost their power-up ... 
02195. BNE PRG007_AAC0 ; ... then jump to PRG007_AAC0 
02196.  
02197. LDA <Player_HaltGame 
02198. BNE PRG007_AB1D ; If gameplay is halted, jump to PRG007_AB1D 
02199.  
02200. PRG007_AAC0: 
02201. LDA Scores_Counter,X 
02202. BNE PRG007_AACF ; If this score counter hasn't expired, jump to PRG007_AACF 
02203.  
02204. PRG007_AAC5: 
02205. ; Otherwise, this score is finished; clear it out! 
02206. LDA #$00 
02207. STA Scores_Value,X 
02208.  
02209. RTS ; Return 
02210.  
02211. ; Mask values that control how quickly the score rises 
02212. Score_RiseCounterMask: .byte $03, $01, $00, $00 
02213.  
02214. PRG007_AACF: 
02215. DEC Scores_Counter,X ; Decrement the score counter 
02216.  
02217. CMP #$2a 
02218. BNE PRG007_AB04 ; If score counter <> $2A, jump to PRG007_AB04 
02219.  
02220. ; Score counter = $2A... 
02221.  
02222. LDY <Temp_Var1 ; Y = score value 
02223.  
02224. ; Add Score's value to Score_Earned 
02225. LDA Score_Earned 
02226. ADD ScoreAdd_L-1,Y ; -1 because a score value of zero is "empty" 
02227. STA Score_Earned 
02228. LDA Score_Earned+1 
02229. ADC ScoreAdd_H-1,Y 
02230. STA Score_Earned+1 
02231.  
02232. CPY #$0d 
02233. BNE PRG007_AB02 ; If this is not 1-up level score, jump to PRG007_AB02 
02234.  
02235. ; Play 1-up sound! 
02236. LDA Sound_QLevel1 
02237. ORA #SND_LEVEL1UP 
02238. STA Sound_QLevel1 
02239.  
02240. LDX Player_Current ; X = current Player 
02241.  
02242. LDA Player_Lives,X 
02243. BMI PRG007_AB02 ; If this Player is dead (and how could we be here, hmm?), jump to PRG007_AB02 
02244.  
02245. INC Player_Lives,X ; Otherwise, give them the extra life! 
02246.  
02247. PRG007_AB02: 
02248. LDX <SlotIndexBackup ; X = score slot index 
02249.  
02250. PRG007_AB04: 
02251. LDA Scores_Counter,X 
02252. LSR A 
02253. LSR A 
02254. LSR A 
02255. LSR A 
02256. TAY ; Y = score counter / 16 
02257.  
02258. LDA <Counter_1 
02259. AND Score_RiseCounterMask,Y 
02260. BNE PRG007_AB1D ; Periodically jump to PRG007_AB1D 
02261.  
02262. LDA Scores_Y,X 
02263. CMP #$04 
02264. BLT PRG007_AB1D ; If this score's Y < 4, jump to PRG007_AB1D 
02265.  
02266. DEC Scores_Y,X ; Otherwise, rise up! 
02267.  
02268. PRG007_AB1D: 
02269.  
02270. ; Scroll score horizontally with screen 
02271. LDA Scores_X,X 
02272. SUB Level_ScrollDiffH 
02273. STA Scores_X,X 
02274.  
02275. CMP #248 
02276. BGE PRG007_AAC5 ; If score's X >= 248, jump to PRG007_AAC5 (get rid of it!) 
02277.  
02278. ; Scroll score vertically with screen 
02279. LDA Scores_Y,X 
02280. SUB Level_ScrollDiffV 
02281. STA Scores_Y,X 
02282.  
02283. CMP #248 
02284. BGE PRG007_AAC5 ; If score's Y >= 248, jump to PRG007_AAC5 (get rid of it!) 
02285.  
02286. LDA Scores_Value,X 
02287. BMI PRG007_AB53 ; If score value has bit 7 set, jump to PRG007_AB53 
02288.  
02289. ; Otherwise... 
02290.  
02291. ; This just takes from object sprite RAM 
02292. LDA Object_SprRAM,X 
02293. ADD #16 ; +16 (4 sprites over) 
02294. TAY ; Y = Sprite RAM offset 
02295. STY <Temp_Var5 ; -> Temp_Var5 
02296.  
02297. ADD #$04 ; +4 (1 sprite over) 
02298. STA <Temp_Var6 ; -> Temp_Var6 
02299.  
02300. LDA Sprite_RAM+$00,Y 
02301. CMP #$f8 
02302. BEQ PRG007_AB76 ; If this sprite is free, jump to PRG007_AB76 
02303.  
02304. PRG007_AB53: 
02305. JSR Object_GetRandNearUnusedSpr ; Sprite is not free; get a nearby one 
02306.  
02307. STY <Temp_Var5 ; -> Temp_Var5 
02308. BNE PRG007_AB70 ; As long as result wasn't zero, jump to PRG007_AB70 
02309.  
02310. ; No sprites available... 
02311.  
02312. ; Temp_Var6 = $FF 
02313. LDA #$ff 
02314. STA <Temp_Var6 
02315.  
02316. LDA <Counter_1 
02317. LSR A 
02318. BCC PRG007_AB6D ; Every other tick, jump to PRG007_AB6D 
02319.  
02320. ; Basically only one or the other half of the score will actually display 
02321. LDA <Temp_Var5 
02322. PHA 
02323. LDA <Temp_Var6 
02324. STA <Temp_Var5 
02325. PLA 
02326. STA <Temp_Var6 
02327.  
02328. PRG007_AB6D: 
02329. JMP PRG007_AB76 ; Jump to PRG007_AB76 
02330.  
02331. PRG007_AB70: 
02332. ; New sprite RAM offset selected... 
02333. TYA ; -> Y 
02334. ADD #$04 ; +4 (next sprite over) 
02335. STA <Temp_Var6 ; -> Temp_Var6 
02336.  
02337. PRG007_AB76:  
02338. LDY <Temp_Var5 
02339. CPY #$ff 
02340. BEQ PRG007_AB99 ; If this sprite RAM offset is invalid, jump to PRG007_AB99 
02341.  
02342. LDX <Temp_Var1 ; X = score value 
02343.  
02344. LDA Score_PatternLeft-1,X ; -1 because a score value of zero is "empty" 
02345.  
02346. LDX <SlotIndexBackup ; X = score slot index 
02347.  
02348. CMP #$ff 
02349. BEQ PRG007_AB99 ; If this is the "don't display" marker, jump to PRG007_AB99 
02350.  
02351. ; Otherwise, set the pattern 
02352. STA Sprite_RAM+$01,Y 
02353.  
02354. ; Score Sprite Y 
02355. LDA Scores_Y,X 
02356. STA Sprite_RAM+$00,Y 
02357.  
02358. ; Score Sprite X 
02359. LDA Scores_X,X 
02360. STA Sprite_RAM+$03,Y 
02361.  
02362. JSR Score_SetAttribute 
02363.  
02364. PRG007_AB99: 
02365. LDY <Temp_Var6 ; Y = second sprite offset 
02366. CPY #$ff 
02367. BEQ PRG007_ABC4 ; If this sprite is marked as "don't display", jump to PRG007_ABC4 
02368.  
02369. ; Score Sprite Y 
02370. LDA Scores_Y,X 
02371. STA Sprite_RAM+$00,Y 
02372.  
02373. ; Score Sprite X 
02374. LDA Scores_X,X 
02375. ADD #$08 
02376. STA Sprite_RAM+$03,Y 
02377.  
02378. LDX <Temp_Var1 ; X = score value 
02379.  
02380. ; Score Sprite pattern 
02381. LDA Score_PatternRight-1,X 
02382. STA Sprite_RAM+$01,Y 
02383.  
02384. Score_SetAttribute: 
02385. LDA <Temp_Var1 ; Get score value 
02386. CMP #$0d 
02387. LDA #$01 ; A = 1 
02388. BGE PRG007_ABBF ; If this is the 1-up, jump to PRG007_ABBF 
02389.  
02390. NOP ; Otherwise, do ... nothing! 
02391.  
02392. PRG007_ABBF: 
02393. ; Set attribute 
02394. STA Sprite_RAM+$02,Y 
02395.  
02396. LDX <SlotIndexBackup ; X = score slot index 
02397.  
02398. PRG007_ABC4: 
02399. RTS ; Return 
02400.  
02401.  
02402. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02403. ; BrickBusts_DrawAndUpdate 
02404. ; 
02405. ; Draws and updates the brick bust debris/poof effects 
02406. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02407. BrickBusts_DrawAndUpdate: 
02408. LDX #$01 ; X = 1 
02409. PRG007_ABC7: 
02410. STX <SlotIndexBackup ; -> SlotIndexBackup 
02411.  
02412. JSR BrickBust_DrawAndUpdate ; Draw and update this brick bust 
02413.  
02414. DEX ; X-- 
02415. BPL PRG007_ABC7 ; While X >= 0, loop 
02416.  
02417. PRG007_ABCF: 
02418. RTS ; Return 
02419.  
02420. BrickBust_SprRAMOff: .byte $08, $18 ; Four sprites required here 
02421. BrickPoof_SprRAMOff: .byte $08, $10 ; Only two sprites required here 
02422.  
02423. ; Draw and update the specific brick bust 
02424. BrickBust_DrawAndUpdate: 
02425. LDA BrickBust_En,X 
02426. BEQ PRG007_ABCF ; If this brick bust slot is not active, jump to PRG007_ABCF 
02427.  
02428. CMP #$02 
02429. BEQ PRG007_ABE0 ; If the bust type is 2 (typical), jump to PRG007_ABE0 
02430.  
02431. JMP PRG007_AD27 ; Otherwise, jump to PRG007_AD27 
02432.  
02433. PRG007_ABE0: 
02434. LDA <Player_HaltGame 
02435. BNE PRG007_ABED ; If gameplay halted, jump to PRG007_ABED 
02436.  
02437. LDA <Counter_1 
02438. AND #$03 
02439. BNE PRG007_ABED ; 1:4 proceed, otherwise jump to PRG007_ABED 
02440.  
02441. INC BrickBust_YVel,X ; BrickBust_YVel++ (gravity) 
02442.  
02443. PRG007_ABED: 
02444. LDA BrickBust_YUpr,X 
02445. PHA ; Save upper chunk Y 
02446.  
02447. CLC ; Clear carry (no point?) 
02448. SUB Level_ScrollDiffV ; Adjust Y based on vertical screen scroll 
02449.  
02450. LDY <Player_HaltGame 
02451. BNE PRG007_ABFE ; If gameplay is halted, jump to PRG007_ABFE 
02452.  
02453. ADD BrickBust_YVel,X ; Apply brick bust Y velocity 
02454.  
02455. PRG007_ABFE: 
02456. STA BrickBust_YUpr,X ; -> upper chunk Y 
02457.  
02458. PLA ; Restore original Y 
02459. EOR BrickBust_YUpr,X 
02460. BPL PRG007_AC1F ; If the sign hasn't changed, jump to PRG007_AC1F 
02461.  
02462. ; Sign changed; need to make sure the block bust debris didn't wrap 
02463.  
02464. LDA Level_ScrollDiffV 
02465.  
02466. LDY <Player_HaltGame 
02467. BNE PRG007_AC12 ; If gameplay halted, jump to PRG007_AC12 
02468.  
02469. SUB BrickBust_YVel,X ; Apply velocity in reverse 
02470.  
02471. PRG007_AC12: 
02472. EOR BrickBust_YUpr,X 
02473. BPL PRG007_AC1F ; If the sign didn't change, jump to PRG007_AC1F 
02474.  
02475. ; Otherwise, toggle the upper chunk disable 
02476. LDA BrickBust_HEn,X 
02477. EOR #$08 
02478. STA BrickBust_HEn,X 
02479.  
02480. PRG007_AC1F: 
02481. LDA BrickBust_YLwr,X 
02482. PHA ; Save lower chunk Y 
02483.  
02484. CLC ; Clear carry (no point?) 
02485. SUB Level_ScrollDiffV ; Adjust Y based on vertical screens croll 
02486.  
02487. LDY <Player_HaltGame 
02488. BNE PRG007_AC36 ; If gameplay is halted, jump to PRG007_AC36 
02489.  
02490. INC BrickBust_XDist,X ; Increase the chunk separation 
02491.  
02492. ADD BrickBust_YVel,X ; Apply Y velocity 
02493.  
02494. ADD #$02 ; More impact on lower chunk 
02495. PRG007_AC36: 
02496. STA BrickBust_YLwr,X 
02497.  
02498. PLA ; Restore lower chunk Y 
02499.  
02500. EOR BrickBust_YLwr,X 
02501. BPL PRG007_AC5A ; If the sign hasn't changed, jump to PRG007_AC5A 
02502.  
02503. ; Sign changed; need to make sure the block bust debris didn't wrap 
02504.  
02505. LDA Level_ScrollDiffV 
02506.  
02507. LDY <Player_HaltGame 
02508. BNE PRG007_AC4D ; If gameplay halted, jump to PRG007_AC4D 
02509.  
02510. SUB BrickBust_YVel,X ; Apply velocity in reverse 
02511. SUB #$02 ; With the greater impact 
02512.  
02513. PRG007_AC4D: 
02514. EOR BrickBust_YLwr,X 
02515. BPL PRG007_AC5A ; If sign didn't change, jump to PRG007_AC5A 
02516.  
02517. ; Otherwise, toggle the lower chunk disable 
02518. LDA BrickBust_HEn,X 
02519. EOR #$04 
02520. STA BrickBust_HEn,X 
02521.  
02522. PRG007_AC5A: 
02523.  
02524. ; Scroll brick bust debris horizontally with screen 
02525. LDA BrickBust_X,X 
02526. SUB Level_ScrollDiffH 
02527. STA BrickBust_X,X 
02528.  
02529. TXA ; Keeps things interesting 
02530. EOR <Counter_1 
02531. AND #$01 
02532. TAY ; Y = 0 or 1 
02533.  
02534. LDA BrickBust_SprRAMOff,Y 
02535. TAY ; Y = sprite RAM offset 
02536. CPY #$08  
02537. BNE PRG007_AC7A ; If NOT using the offset $08, jump to PRG007_AC7A 
02538.  
02539. LDA Sprite_RAM+$08 
02540. CMP #$f8 
02541. BEQ PRG007_AC7A ; If this sprite is not in use, jump to PRG007_AC7A 
02542.  
02543. RTS ; Return 
02544.  
02545. PRG007_AC7A: 
02546. LDA BrickBust_HEn,X 
02547. STA <Temp_Var4 ; Horizontal enable flag -> Var4 
02548.  
02549. CMP #$0c 
02550. BLT PRG007_AC91 ; If at least one of upper or lower are enabled, jump to PRG007_AC91 
02551.  
02552. ; Upper and lower are both disabled! 
02553.  
02554. LDA <Player_HaltGame 
02555. BNE PRG007_AC8E ; If gameplay halted, jump to PRG007_AC8E 
02556.  
02557. LDA BrickBust_YVel,X 
02558. CMP #$08 
02559. BLS PRG007_AC91 ; If brick bust Y velocity < $08, jump to PRG007_AC91 
02560.  
02561. PRG007_AC8E: 
02562. JMP PRG007_AD21 ; Otherwise, jump to PRG007_AD21 (disable this brick bust) 
02563.  
02564. PRG007_AC91: 
02565. LDA <Temp_Var4 
02566. AND #$08 
02567. BNE PRG007_ACA0 ; If upper bust chunks are disabled, jump to PRG007_ACA0 
02568.  
02569. ; Otherwise set sprite Y for left and right uppers 
02570. LDA BrickBust_YUpr,X 
02571. STA Sprite_RAM+$00,Y 
02572. STA Sprite_RAM+$04,Y 
02573.  
02574. PRG007_ACA0: 
02575. LDA <Temp_Var4 
02576. AND #$04 
02577. BNE PRG007_ACAF ; If lower bust chunks are disabled, jump to PRG007_ACAF 
02578.  
02579. ; Otherwise set sprite Y for left and right lowers 
02580. LDA BrickBust_YLwr,X 
02581. STA Sprite_RAM+$08,Y 
02582. STA Sprite_RAM+$0C,Y 
02583.  
02584. PRG007_ACAF: 
02585. LSR <Temp_Var4 
02586. BCC PRG007_ACBB ; If right bust chunks are NOT disabled, jump to PRG007_ACBB 
02587.  
02588. ; Hide right-hand bust chunks 
02589. LDA #$f8 
02590. STA Sprite_RAM+$00,Y 
02591. STA Sprite_RAM+$08,Y 
02592.  
02593. PRG007_ACBB: 
02594. LSR <Temp_Var4 
02595. BCC PRG007_ACC7 ; If left bust chunks are NOT disabled, jump to PRG007_ACC7 
02596.  
02597. ; Hide left-hand bust chunks 
02598. LDA #$f8 
02599. STA Sprite_RAM+$04,Y 
02600. STA Sprite_RAM+$0C,Y 
02601.  
02602. PRG007_ACC7: 
02603.  
02604. ; Pattern for bust chunks 
02605. LDA #$4b 
02606. STA Sprite_RAM+$01,Y 
02607. STA Sprite_RAM+$05,Y 
02608. STA Sprite_RAM+$09,Y 
02609. STA Sprite_RAM+$0D,Y 
02610.  
02611. LDA BrickBust_X,X 
02612. PHA ; Save chunk X 
02613. ADD BrickBust_XDist,X ; Add the distance 
02614. ADD #$08 ; +8 
02615. STA Sprite_RAM+$03,Y ; Set right upper chunk X 
02616. STA Sprite_RAM+$0B,Y ; Set right lower chunk X 
02617.  
02618. CMP #248 
02619. BLT PRG007_ACF2 ; If bust chunk X < 248, jump to PRG007_ACF2 
02620.  
02621. ; Otherwise, disable right chunks 
02622. LDA BrickBust_HEn,X 
02623. ORA #$01 
02624. STA BrickBust_HEn,X 
02625.  
02626. PRG007_ACF2: 
02627. PLA ; Restore chunk X 
02628. SUB BrickBust_XDist,X ; Subtract the distance 
02629. STA Sprite_RAM+$07,Y ; Set left upper chunk X 
02630. STA Sprite_RAM+$0F,Y ; Set left lower chunk X 
02631.  
02632. ; Seems like this should be a >= 8 check?? 
02633. CMP #244 
02634. BLT PRG007_AD09 ; If bust chunk X < 244 (??), jump to PRG007_AD09 
02635.  
02636. ; Otherwise, disable left chunks 
02637. LDA BrickBust_HEn,X 
02638. ORA #$02 
02639. STA BrickBust_HEn,X 
02640.  
02641. PRG007_AD09: 
02642.  
02643. ; Rotate the horizontal / vertical flips 
02644. LDA Level_NoStopCnt 
02645. AND #$06 
02646. LSR A 
02647. LSR A 
02648. ROR A 
02649. ROR A 
02650. ORA #SPR_PAL3 
02651. STA Sprite_RAM+$02,Y 
02652. STA Sprite_RAM+$06,Y 
02653. STA Sprite_RAM+$0A,Y 
02654. STA Sprite_RAM+$0E,Y 
02655.  
02656. RTS ; Return 
02657.  
02658. PRG007_AD21: 
02659.  
02660. ; Disable this brick bust 
02661. LDA #$00 
02662. STA BrickBust_En,X 
02663.  
02664. RTS ; Return 
02665.  
02666. PRG007_AD27: 
02667.  
02668. ; Brick bust type non-2 ("poof" away the tile) 
02669.  
02670. LDA BrickBust_HEn,X 
02671. BEQ PRG007_AD21 ; If BrickBust_HEn = 0 (poof expired), jump to PRG007_AD21 (disable this brick bust) 
02672.  
02673. LDA <Player_HaltGame 
02674. BNE PRG007_AD33 ; If gameplay is halted, jump to PRG007_AD33 
02675.  
02676. DEC BrickBust_HEn,X ; BrickBust_HEn-- (used as a counter here) 
02677.  
02678. PRG007_AD33: 
02679. LDA BrickBust_YUpr,X 
02680.  
02681. LDY Level_AScrlConfig 
02682. BNE PRG007_AD42 ; If raster enabled, jump to PRG007_AD42 
02683.  
02684. ; Otherwise, just be screen-scroll relative 
02685. SUB Level_ScrollDiffV 
02686. STA BrickBust_YUpr,X 
02687.  
02688. PRG007_AD42: 
02689. CMP #208 
02690. BGE PRG007_AD21 ; If the poof effect Y >= 208 (too low), jump to PRG007_AD21 (disable this brick bust) 
02691.  
02692. CPY #$00 
02693. BNE PRG007_AD54 ; If raster effects enabled, jump to PRG007_AD54 
02694.  
02695. ; Scroll poof horizontally 
02696. LDA BrickBust_X,X 
02697. SUB Level_ScrollDiffH 
02698. STA BrickBust_X,X 
02699.  
02700. PRG007_AD54: 
02701. CMP #240 
02702. BGE PRG007_AD21 ; If the poof effect X >= 24, jump to PRG007_AD21 (disable this brick bust) 
02703.  
02704. TXA ; Keep it interesting 
02705. EOR <Counter_1  
02706. AND #$01  
02707. TAY ; Y = 0 or 1 
02708.  
02709. LDA BrickPoof_SprRAMOff,Y 
02710. TAY ; Y = Sprite RAM offset 
02711.  
02712. LDA Sprite_RAM+$00,Y 
02713. CMP #$f8 
02714. BNE PRG007_ADA7 ; If this sprite is not free, jump to PRG007_ADA7 (RTS) 
02715.  
02716. ; Set left sprite X 
02717. LDA BrickBust_X,X 
02718. STA Sprite_RAM+$03,Y 
02719.  
02720. ; Set right sprite X 
02721. ADD #$08 ; +8 
02722. STA Sprite_RAM+$07,Y 
02723.  
02724. ; Set left/right sprite Y 
02725. LDA BrickBust_YUpr,X 
02726. STA Sprite_RAM+$00,Y 
02727. STA Sprite_RAM+$04,Y 
02728.  
02729. LDA Level_NoStopCnt 
02730. LSR A 
02731. LSR A 
02732. LSR A 
02733. ROR A 
02734. AND #SPR_VFLIP 
02735. STA <Temp_Var1 ; Periodically vertically flip 
02736.  
02737. ; Form attribute with sprite palette 1 for left half 
02738. LDA #SPR_PAL1 
02739. ORA <Temp_Var1 
02740. STA Sprite_RAM+$02,Y 
02741.  
02742. ; Right half uses opposite flips 
02743. EOR #(SPR_HFLIP | SPR_VFLIP) 
02744. STA Sprite_RAM+$06,Y 
02745.  
02746. LDA BrickBust_HEn,X 
02747. LSR A 
02748. LSR A 
02749. LSR A 
02750. TAX ; X = 0 to 3 
02751.  
02752. LDA Poof_Patterns,X ; Get appropriate "poof" pattern 
02753. STA Sprite_RAM+$01,Y ; Left 
02754. STA Sprite_RAM+$05,Y ; Right 
02755.  
02756. LDX <SlotIndexBackup ; X = restore slot index 
02757.  
02758. PRG007_ADA7: 
02759. RTS ; Return 
02760.  
02761. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02762. ; CoinPUp_DrawAndUpdate 
02763. ; 
02764. ; Draws and updates the coins which have popped out of blocks 
02765. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
02766.  
02767. CoinPUp_Patterns: .byte $49, $4F, $4D, $4F 
02768. CoinPUp_Attributes: .byte SPR_PAL3, SPR_PAL3 | SPR_HFLIP, SPR_PAL3, SPR_PAL3 
02769.  
02770. CoinPUps_DrawAndUpdate: 
02771. LDX #$03 ; X = 3 (all "power up" coin slots) 
02772. PRG007_ADB2:  
02773. STX <SlotIndexBackup ; -> slot index backup 
02774.  
02775. LDA CoinPUp_State,X 
02776. BEQ PRG007_ADBC ; If there's no active "powerup coin" here, jump to PRG007_ADBC 
02777.  
02778. JSR CoinPUp_UpdateAndDraw ; Update and draw powerup coin 
02779.  
02780. PRG007_ADBC: 
02781. DEX ; X-- 
02782. BPL PRG007_ADB2 ; While X >= 0, loop! 
02783.  
02784. RTS ; Return 
02785.  
02786. CoinPUp_UpdateAndDraw: 
02787. LDA <Player_HaltGame  
02788. BNE PRG007_ADF0 ; If gameplay is halted, jump to PRG007_ADF0 
02789.  
02790. INC CoinPUp_Counter,X ; counter++ 
02791.  
02792. ; Apply coin's Y velocity 
02793. LDA CoinPUp_Y,X 
02794. ADD CoinPUp_YVel,X 
02795. STA CoinPUp_Y,X 
02796.  
02797. LDA CoinPUp_Counter,X 
02798. AND #$03 
02799. BNE PRG007_ADE2 ; 1:4 ticks proceed, otherwise jump to PRG007_ADE2 
02800.  
02801. INC CoinPUp_YVel,X ; coin YVel ++ 
02802.  
02803. LDA CoinPUp_YVel,X 
02804. CMP #$05 
02805. BEQ PRG007_AE28 ; If coin's Y velocity = 5, jump to PRG007_AE28 
02806.  
02807. PRG007_ADE2: 
02808. LDA CoinPUp_X,X 
02809. SUB Level_ScrollDiffH ; Make relative coin X 
02810.  
02811. CMP #248 
02812. BGE PRG007_AE4A ; If coin X >= 248, jump to PRG007_AE4A (remove coin) 
02813.  
02814. STA CoinPUp_X,X ; Update coin X 
02815.  
02816. PRG007_ADF0: 
02817. LDA <Player_HaltGame 
02818. BEQ PRG007_AE02 ; If gameplay is not halted, jump to PRG007_AE02 
02819.  
02820. ; Move coin Y with vertical scroll 
02821. LDA CoinPUp_Y,X  
02822. SUB Level_ScrollDiffV 
02823. STA CoinPUp_Y,X  
02824.  
02825. CMP #197 
02826. BGE PRG007_AE4A ; If coin Y >= 197, jump to PRG007_AE4A (remove coin) 
02827.  
02828. PRG007_AE02: 
02829. JSR Object_GetRandNearUnusedSpr 
02830.  
02831. ; Set coin Y 
02832. LDA CoinPUp_Y,X 
02833. STA Sprite_RAM+$00,Y 
02834.  
02835. ; Set coin X 
02836. LDA CoinPUp_X,X 
02837. STA Sprite_RAM+$03,Y 
02838.  
02839. LDA CoinPUp_Counter,X 
02840. LSR A 
02841. LSR A 
02842. AND #$03 
02843. TAX ; X = 0 to 3 by coin counter 
02844.  
02845. ; Set pattern 
02846. LDA CoinPUp_Patterns,X 
02847. STA Sprite_RAM+$01,Y 
02848.  
02849. ; Set attribute 
02850. LDA CoinPUp_Attributes,X 
02851. STA Sprite_RAM+$02,Y 
02852.  
02853. LDX <SlotIndexBackup ; X = power up coin slot index 
02854.  
02855. RTS ; Return 
02856.  
02857. PRG007_AE28: 
02858. JSR Score_FindFreeSlot 
02859.  
02860. ; Get 100 pts 
02861. LDA #$85 
02862. STA Scores_Value,Y 
02863.  
02864. LDA #$30 
02865. STA Scores_Counter,Y 
02866.  
02867. LDA CoinPUp_Y,X 
02868. CMP #192 
02869. BLT PRG007_AE3E ; If the coin is not too low, jump to PRG007_AE3E 
02870.  
02871. LDA #$05 ; Otherwise use top of screen 
02872.  
02873. PRG007_AE3E: 
02874. STA Scores_Y,Y ; -> Scores_Y 
02875.  
02876. ; Center score above coin 
02877. LDA CoinPUp_X,X 
02878. SUB #$04 
02879. STA Scores_X,Y 
02880.  
02881. PRG007_AE4A: 
02882.  
02883. ; Remove coin 
02884. LDA #$00 
02885. STA CoinPUp_State,X 
02886.  
02887. RTS ; Return 
02888.  
02889.  
02890. ; Sets carry if solid was hit 
02891. SObj_CheckHitSolid: 
02892.  
02893. ; Flag Blooper Kid as out of water until determined otherwise 
02894. LDA #$01  
02895. STA SObjBlooperKid_OutOfWater,X 
02896.  
02897. ; Temp_Var6 = special object Y + 12 
02898. LDA SpecialObj_YLo,X 
02899. ADD #12 
02900. STA <Temp_Var6 
02901.  
02902. ; Aligned to grid -> Temp_Var3 
02903. AND #$f0 
02904. STA <Temp_Var3 
02905.  
02906. LDA SpecialObj_YHi,X 
02907. ADC #$00 ; Apply carry 
02908. PHA ; Save Y Hi 
02909.  
02910. ; Special object X + 4 -> Temp_Var5 
02911. LDA SpecialObj_XLo,X 
02912. ADD #$04 
02913. SUB <Horz_Scroll ; - 
02914. ADD <Horz_Scroll ; + ?? 
02915. STA <Temp_Var5 
02916.  
02917. LDA <Horz_Scroll_Hi 
02918. ADC #$00 ; Apply carry 
02919. ASL A ; 2 bytes per screen (for Tile_Mem_Addr) 
02920. TAY ; -> 'Y' 
02921.  
02922. ; Low byte of Tile_Mem_Addr -> Temp_Var1 
02923. LDA Tile_Mem_Addr,Y 
02924. STA <Temp_Var1 
02925.  
02926. PLA ; Restore Y Hi 
02927.  
02928. AND #$01 ; Only use 0 or 1 (only valid Y His in a non-vertical level) 
02929. ADD Tile_Mem_Addr+1,Y ; Add to the high byte of Tile_Mem_Addr 
02930. STA <Temp_Var2 ; -> Temp_Var2 
02931.  
02932. ; Form a row/column offset -> 'Y' 
02933. LDA <Temp_Var5 
02934. LSR A 
02935. LSR A 
02936. LSR A 
02937. LSR A 
02938. ORA <Temp_Var3 
02939. TAY 
02940.  
02941. LDA [Temp_Var1],Y ; Get the tile here 
02942. PHA ; Save it 
02943.  
02944. ASL A 
02945. ROL A 
02946. ROL A 
02947. AND #$03 
02948. TAY ; Y = tile quadrant 
02949. STY <Temp_Var2 ; -> Temp_Var2 
02950.  
02951. PLA ; Restore the tile value 
02952. STA <Temp_Var1 ; -> Temp_Var1 
02953.  
02954. CMP Tile_AttrTable,Y 
02955. BLT PRG007_AEE0 ; If this tile is not solid on top, jump to PRG007_AEE0 
02956.  
02957. CMP Tile_AttrTable+4,Y 
02958. BLT PRG007_AECF ; If this tile is not solid on the sides/bottom, jump to PRG007_AECF 
02959.  
02960. ; Tile is solid all around 
02961.  
02962. LDA SpecialObj_ID,X 
02963. CMP #SOBJ_FIREBROFIREBALL 
02964. BEQ PRG007_AEB3 ; If this a Fire Bro's fireball (the only one that bounces on the floor), jump to PRG007_AEB3 
02965.  
02966. SEC ; Set carry 
02967.  
02968. RTS ; Return 
02969.  
02970. PRG007_AEB3: 
02971. INC SpecialObj_Data,X ; SpecialObj_Data++ 
02972.  
02973. LDA SpecialObj_Data,X 
02974. CMP #$02 
02975. BNE PRG007_AEC0 ; If SpecialObj_Data <> 2, jump to PRG007_AEC0 
02976.  
02977. JMP PRG007_AF02 ; Jump to PRG007_AF02 
02978.  
02979. PRG007_AEC0: 
02980. ; Fireball's Y -= 3 
02981. DEC SpecialObj_YLo,X 
02982. DEC SpecialObj_YLo,X 
02983. DEC SpecialObj_YLo,X 
02984.  
02985. PRG007_AEC9: 
02986. ; Bounce fireball! 
02987. LDA #-$2C 
02988. STA SpecialObj_YVel,X 
02989.  
02990. PRG007_AECE: 
02991. RTS ; Return 
02992.  
02993. PRG007_AECF: 
02994.  
02995. ; Tile solid only on top 
02996.  
02997. LDA SpecialObj_ID,X 
02998. CMP #SOBJ_FIREBROFIREBALL 
02999.  
03000. CLC ; Clear carry 
03001.  
03002. BNE PRG007_AECE ; If this is not the Fire Bro's fireball, jump to PRG007_AECE 
03003.  
03004. LDA <Temp_Var6 
03005. AND #$0f ; Find Y relative to the tile 
03006. CMP #$05 
03007. BLT PRG007_AEC9 ; If it's less than 5 pixels from the top, count as hit the floor, and bounce! 
03008.  
03009. RTS ; Return 
03010.  
03011. PRG007_AEE0: 
03012.  
03013. ; Tile not solid on top (literally, but likely assumes not solid on the side/bottom either) 
03014.  
03015. LDA SpecialObj_ID,X 
03016. CMP #SOBJ_BLOOPERKID 
03017.  
03018. CLC ; Clear carry 
03019.  
03020. BNE PRG007_AEFC ; If this is not a Blooper Kid, jump to PRG007_AEFC 
03021.  
03022. ; Blooper kid only... 
03023.  
03024. LDA Level_TilesetIdx 
03025. ASL A 
03026. ASL A ; TilesetIdx * 4 
03027. ADD <Temp_Var2 ; Add the quadrant 
03028. TAY ; Y = offset into Level_MinTileUWByQuad 
03029.  
03030. LDA Level_MinTileUWByQuad,Y 
03031. CMP <Temp_Var1 
03032. BLT PRG007_AEFB ; If this tile is not considered underwater, jump to PRG007_AEFB (RTS) 
03033.  
03034. DEC SObjBlooperKid_OutOfWater,X ; Otherwise, SObjBlooperKid_OutOfWater = 0 (Blooper Kid is still in water!) 
03035.  
03036. PRG007_AEFB: 
03037. RTS ; Return 
03038.  
03039. PRG007_AEFC: 
03040.  
03041. ; SpecialObj_Data = 0 
03042. LDA #$00 
03043. STA SpecialObj_Data,X 
03044.  
03045. RTS ; Return 
03046.  
03047.  
03048. PRG007_AF02: 
03049.  
03050. ; impact sound 
03051. LDA Sound_QPlayer 
03052. ORA #SND_PLAYERBUMP 
03053. STA Sound_QPlayer 
03054.  
03055. ; Something removed here... 
03056. NOP 
03057. NOP 
03058. NOP 
03059. NOP 
03060. NOP 
03061. NOP 
03062. NOP 
03063.  
03064. JMP PRG007_B84C ; Jump to PRG007_B84C ("Poof" away the fireball) 
03065.  
03066.  
03067. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
03068. ; SpecialObjs_UpdateAndDraw 
03069. ; 
03070. ; Updates Special Objects and they draw as they will 
03071. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
03072. SpecialObjs_UpdateAndDraw: 
03073.  
03074. ; No Microgoomba stuck to Player until we say so... 
03075. LDA #$00  
03076. STA Player_Microgoomba 
03077.  
03078. LDX #$07 ; X = 7 
03079. PRG007_AF1B: 
03080. STX <SlotIndexBackup ; Store current checked index -> SlotIndexBackup 
03081.  
03082. JSR SpecialObj_UpdateAndDraw ; Does the update and draw routines of Special OBjects 
03083.  
03084. DEX ; X-- 
03085. BPL PRG007_AF1B ; While X >= 0, loop! 
03086.  
03087. SObj_DoNothing: 
03088. PRG007_AF23: 
03089. RTS ; Return 
03090.  
03091. SpecialObj_UpdateAndDraw: 
03092. LDA SpecialObj_ID,X  
03093. BEQ PRG007_AF23 ; If this special object slot is not in use, jump to PRG007_AF23 (RTS) 
03094.  
03095. LDA AScrlURDiag_WrapState_Copy 
03096. BEQ PRG007_AF4B ; If diagonal scroller is not wrapping, jump to PRG007_AF4B 
03097.  
03098. LDA <Player_HaltGame 
03099. BNE PRG007_AF4B ; If gameplay is halted, jump to PRG007_AF4B 
03100.  
03101. ; Offset special object to compensate for the diagonal autoscroller's wrap 
03102. LDA SpecialObj_XLo,X 
03103. ADD AScrlURDiag_OffsetX 
03104. STA SpecialObj_XLo,X 
03105. LDA SpecialObj_YLo,X 
03106. ADD AScrlURDiag_OffsetY 
03107. STA SpecialObj_YLo,X 
03108.  
03109. BCC PRG007_AF4B ; If no carry, jump to PRG007_AF4B 
03110. INC SpecialObj_YHi,X ; Apply carry 
03111. PRG007_AF4B: 
03112.  
03113. LDY <Player_HaltGame 
03114. BNE PRG007_AF57 ; If gameplay halted, jump to PRG007_AF57 
03115.  
03116. LDY SpecialObj_Timer,X 
03117. BEQ PRG007_AF57 ; If SpecialObj_Timer = 0, jump to PRG007_AF57 
03118. DEC SpecialObj_Timer,X ; SpecialObj_Timer-- 
03119. PRG007_AF57: 
03120.  
03121.  
03122. LDA SpecialObj_XLo,X 
03123. SUB <Horz_Scroll 
03124. CMP #248 
03125. BGE SpecialObj_RemoveInd ; If special object X >= 248, jump to SpecialObj_RemoveInd (remove special object) 
03126.  
03127. LDA SpecialObj_YLo,X 
03128. ADD #16 
03129. PHA ; Save Special object Y + 16 
03130.  
03131. LDA SpecialObj_YHi,X 
03132. ADC #$00 ; Apply carry 
03133. STA <Temp_Var1 ; -> Temp_Var1 
03134.  
03135. PLA ; Restore special object Y + 16 
03136.  
03137. CMP Level_VertScroll 
03138.  
03139. LDA <Temp_Var1 
03140. SBC Level_VertScrollH 
03141. STA <Temp_Var14 ; Temp_Var14 = 0 if special object is on same screen... 
03142.  
03143. BEQ PRG007_AF9E ; If Temp_Var14 = 0 (special object on same screen), jump to PRG007_AF9E 
03144.  
03145. ; A few select special objects can deal with existing on a different screen, 
03146. ; otherwise the object will be deleted immediately 
03147. LDA SpecialObj_ID,X 
03148.  
03149. CMP #SOBJ_BUBBLE 
03150. BEQ PRG007_AF97 
03151.  
03152. CMP #SOBJ_MICROGOOMBA 
03153. BEQ PRG007_AF97 
03154.  
03155. CMP #SOBJ_RECOVEREDWAND 
03156. BEQ PRG007_AF97  
03157.  
03158. CMP #SOBJ_BRICKDEBRIS 
03159. BEQ PRG007_AF97 
03160.  
03161. CMP #SOBJ_SPIKEBALL 
03162. BEQ PRG007_AF97 
03163.  
03164. CMP #SOBJ_HAMMER 
03165. BNE SpecialObj_RemoveInd 
03166.  
03167. PRG007_AF97: 
03168. LDA <Temp_Var14 
03169. BMI PRG007_AF9E ; If this select special object is above, keep it alive, jump to PRG007_AF9E 
03170.  
03171. SpecialObj_RemoveInd: 
03172. JMP SpecialObj_Remove ; Jump to SpecialObj_Remove 
03173.  
03174. PRG007_AF9E:  
03175. LDA SpecialObj_ID,X 
03176.  
03177. JSR DynJump 
03178.  
03179. ; THESE MUST FOLLOW DynJump FOR THE DYNAMIC JUMP TO WORK!! 
03180. .word SObj_DoNothing ; 00: EMPTY / NOT USED (should never get here anyway) 
03181. .word SObj_Hammer ; 01: Hammer Bro hammer 
03182. .word SObj_Boomerang ; 02: Boomerangs 
03183. .word SObj_UNKNOWN ; 03:  
03184. .word SObj_Fireball ; 04: Nipper fireball 
03185. .word SObj_Fireball ; 05: Piranha fireball 
03186. .word SObj_Microgoomba ; 06: Micro goombas 
03187. .word SObj_Spikeball ; 07: Spike/Patooie's spike ball 
03188. .word SObj_WandBlast ; 08: Koopaling wand blast 
03189. .word SObj_KuriboShoe ; 09: Lost Kuribo shoe 
03190. .word SObj_Wrench ; 0A: Rocky's Wrench 
03191. .word SObj_Cannonball ; 0B: Cannonball 
03192. .word SObj_Fireball ; 0C: Fire bro bouncing fireball 
03193. .word SObj_ExplodeStar ; 0D: Explosion star 
03194. .word SObj_Bubble ; 0E: Bubble 
03195. .word SObj_LavaLotusFire; 0F: Lava Lotus fire 
03196. .word SObj_Wand ; 10: Recovered wand 
03197. .word SObj_CoinOrDebris ; 11: Popped out coin 
03198. .word SObj_Fireball ; 12: Fire Chomp's fire 
03199. .word SObj_CoinOrDebris ; 13: Brick debris (e.g. from Piledriver Microgoomba) 
03200. .word SObj_BlooperKid ; 14: Blooper kid 
03201. .word SObj_Laser ; 15: Laser 
03202. .word SObj_Poof ; 16: Poof 
03203.  
03204. PUpCoin_Patterns: .byte $49, $4F, $4D, $4F 
03205. PUpCoin_Attributes: .byte SPR_PAL3, SPR_PAL3 | SPR_HFLIP, SPR_PAL3, SPR_PAL3 
03206.  
03207. SObj_Laser: 
03208.  
03209. ; Load patterns for laser 
03210. LDA #$12 
03211. STA PatTable_BankSel+4 
03212.  
03213. JSR Laser_PrepSpritesAndHit ; Prepare the laser sprites and hurt Player 
03214.  
03215. LDA <Player_HaltGame 
03216. BNE PRG007_B01F ; If gameplay is halted, jump to PRG007_B01F (RTS) 
03217.  
03218. ; Y += 8 
03219. LDA SpecialObj_YLo,X 
03220. ADD #$08 
03221. STA SpecialObj_YLo,X 
03222.  
03223. ; X += 8 
03224. LDA SpecialObj_XLo,X 
03225. SUB #$08 
03226. STA SpecialObj_XLo,X 
03227.  
03228. JSR SObj_CheckHitSolid 
03229. BCC PRG007_B01F ; If laser didn't hit solid, jump to PRG007_B01F (RTS) 
03230.  
03231. ; Laser hit floor! 
03232.  
03233. ; Align Y 
03234. LDA SpecialObj_YLo,X 
03235. AND #$f0 
03236. ADD #$05 
03237. STA SpecialObj_YLo,X 
03238.  
03239. ; Align X 
03240. LDA SpecialObj_XLo,X 
03241. AND #$f0 
03242. ADC #$0b 
03243. STA SpecialObj_XLo,X 
03244.  
03245. JSR SpecialObj_Remove ; Remove laser 
03246.  
03247. ; Generate puff via "brick bust" puff (atypical, but whatever) 
03248. LDY #$01 ; Y = 1 
03249. PRG007_B017: 
03250. LDA BrickBust_En,Y 
03251. BEQ PRG007_B020 ; If this brick bust slot is free, jump to PRG007_B020 
03252.  
03253. DEY ; Y-- 
03254. BPL PRG007_B017 ; While Y >= 0, loop! 
03255.  
03256. PRG007_B01F: 
03257. RTS ; Return 
03258.  
03259.  
03260. PRG007_B020: 
03261.  
03262. ; Enable this brick bust slot (poof style) 
03263. LDA #$01 
03264. STA BrickBust_En,Y 
03265.  
03266. ; Brick bust (poof) X 
03267. LDA SpecialObj_XLo,X 
03268. SUB #$08 
03269. SUB <Horz_Scroll 
03270. STA BrickBust_X,Y 
03271.  
03272. ; Brick bust (poof) Y 
03273. LDA SpecialObj_YLo,X 
03274. ADD #$04 
03275. SBC Level_VertScroll 
03276. STA BrickBust_YUpr,Y 
03277.  
03278. ; Poof counter 
03279. LDA #$17 
03280. STA BrickBust_HEn,Y 
03281.  
03282. RTS ; Return 
03283.  
03284.  
03285. Laser_PrepSpritesAndHit: 
03286. JSR SObj_GetSprRAMOffChkVScreen  
03287. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03288.  
03289. ; Set laser pattern 
03290. LDA #$b7 
03291. STA Sprite_RAM+$01,Y 
03292.  
03293. ; Use rotating color attributes 
03294. LDA <Counter_1 
03295. LSR A  
03296. LSR A  
03297. AND #$03 
03298. STA Sprite_RAM+$02,Y 
03299.  
03300. JMP SObj_PlayerCollide ; Do Player to laser collision and don't come back! 
03301.  
03302. PRG007_B058: 
03303. RTS ; Return 
03304.  
03305. BlooperKid_VelAccel: .byte $01, -$01 
03306. BlooperKid_VelLimit: .byte $10, -$10 
03307. BlooperKid_SpriteYOff: .byte $00, $01, $02, $03, $04, $05, $06, $07, $08, $07, $06, $05, $04, $03, $02, $01 
03308.  
03309. SObj_BlooperKid: 
03310. LDA <Player_HaltGame 
03311. BNE PRG007_B0BC ; If gameplay halted, jump to PRG007_B0BC 
03312.  
03313. LDA <Counter_1 
03314. AND #$07 
03315. BNE PRG007_B0A9 ; 1:8 ticks proceed, otherwise jump to PRG007_B0A9 
03316.  
03317. LDA SpecialObj_Data,X 
03318. AND #$01 
03319. TAY ; Y = 0 or 1 
03320.  
03321. ; Accelerate Blooper Kid Y 
03322. LDA SpecialObj_YVel,X 
03323. ADD BlooperKid_VelAccel,Y 
03324. STA SpecialObj_YVel,X 
03325.  
03326. CMP BlooperKid_VelLimit,Y 
03327. BNE PRG007_B091 ; If Blooper Kid has not hit Y velocity limit, jump to PRG007_B091 
03328.  
03329. INC SpecialObj_Data,X ; Otherwise change direction 
03330.  
03331. PRG007_B091: 
03332. LDA SpecialObj_Var1,X 
03333. AND #$01 
03334. TAY ; Y = 0 or 1 
03335.  
03336. ; Accelerate Blooper Kid X 
03337. LDA SpecialObj_XVel,X 
03338. ADD BlooperKid_VelAccel,Y 
03339. STA SpecialObj_XVel,X 
03340.  
03341. CMP BlooperKid_VelLimit,Y 
03342. BNE PRG007_B0A9 ; If Blooper Kid has not hit X velocity limit, jump to PRG007_B0A9 
03343.  
03344. INC SpecialObj_Var1,X ; Otherwise change direction 
03345.  
03346. PRG007_B0A9: 
03347. JSR SObj_AddXVelFrac ; Apply X Velocity 
03348.  
03349. LDA SpecialObj_YVel,X 
03350. BPL PRG007_B0B9 ; If Blooper Kid is moving downward, jump to PRG007_B0B9 
03351.  
03352. JSR SObj_CheckHitSolid ; Check if hit solid 
03353.  
03354. LDA SObjBlooperKid_OutOfWater,X 
03355. BEQ PRG007_B0BC ; If Blooper Kid is still in water, jump to PRG007_B0BC 
03356.  
03357. PRG007_B0B9: 
03358. JSR SObj_AddYVelFrac ; Apply Y velocity 
03359.  
03360. PRG007_B0BC: 
03361. LDA SpecialObj_Timer,X 
03362. BEQ PRG007_B0F7 ; If timer expired, jump to PRG007_B0F7 
03363.  
03364. CMP #$30 
03365. BGE PRG007_B0C9 ; If timer >= $30, jump to PRG007_B0C9 
03366.  
03367. ; Blooper Kid flickering away.. 
03368. AND #$02 
03369. BNE PRG007_B0F6 ; 2 ticks on, 2 ticks off; jump to PRG007_B0F6 (RTS) 
03370.  
03371. PRG007_B0C9: 
03372. JSR SObj_GetSprRAMOffChkVScreen 
03373.  
03374. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03375.  
03376. LDA Level_NoStopCnt 
03377. LSR A 
03378. AND #$0f 
03379. TAX ; X = 0 to 15 
03380.  
03381. ; Set Sprite Y 
03382. LDA Sprite_RAM+$00,Y 
03383. ADD BlooperKid_SpriteYOff,X 
03384. STA Sprite_RAM+$00,Y 
03385.  
03386. TXA 
03387.  
03388. LDX <SlotIndexBackup ; X = special object slot index 
03389.  
03390. CMP #$08 
03391. LDA #$b5 ; A = $B5 
03392. BLT PRG007_B0EB ; If only halfway through the animation cycle, jump to PRG007_B0EB 
03393.  
03394. LDA #$b7 ; A = $B7 
03395.  
03396. PRG007_B0EB: 
03397.  
03398. ; Set Blooper Kid pattern 
03399. STA Sprite_RAM+$01,Y 
03400.  
03401. ; Set Blooper Kid attributes 
03402. LDA #SPR_PAL1 
03403. STA Sprite_RAM+$02,Y 
03404.  
03405. JMP SObj_PlayerCollide ; Do Player to Blooper Kid collision and don't come back! 
03406.  
03407. PRG007_B0F6: 
03408. RTS ; Return 
03409.  
03410. PRG007_B0F7: 
03411. JMP SpecialObj_Remove ; Remove Blooper kid 
03412.  
03413. SObj_CoinOrDebris: 
03414. LDA <Player_HaltGame 
03415. BNE PRG007_B11F ; If gameplay halted, jump to PRG007_B11F 
03416.  
03417. INC SpecialObj_Var1,X ; Var1++ 
03418.  
03419. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
03420.  
03421. LDA SpecialObj_ID,X 
03422. CMP #SOBJ_BRICKDEBRIS 
03423. BNE PRG007_B11F ; If this is not brick debris, jump to PRG007_B11F 
03424.  
03425. ; Brick debris only... 
03426.  
03427. LDA SpecialObj_YVel,X 
03428. BMI PRG007_B114 ; If brick debris is moving upward, jump to PRG007_B114 
03429.  
03430. CMP #$70 
03431. BGE PRG007_B11F ; If brick debris is falling >= $70, jump to PRG007_B11F 
03432.  
03433. PRG007_B114: 
03434. LDA SpecialObj_Data,X 
03435. BNE PRG007_B11C ; If data <> 0, jump to PRG007_B11C (fall slower) 
03436.  
03437. INC SpecialObj_YVel,X ; YVel++ 
03438.  
03439. PRG007_B11C: 
03440. INC SpecialObj_YVel,X ; YVel++ 
03441.  
03442. PRG007_B11F: 
03443. JSR SObj_GetSprRAMOffChkVScreen 
03444.  
03445. LDA SpecialObj_ID,X 
03446. CMP #SOBJ_BRICKDEBRIS 
03447. BNE PRG007_B169 ; If this is not brick debris, jump to PRG007_B169 
03448.  
03449. ; Brick debris only... 
03450.  
03451. LDA SpecialObj_Data,X 
03452. BEQ PRG007_B153 ; If data = 0 (full giant world style brick rather than chunks), jump to PRG007_B153 
03453.  
03454. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03455.  
03456. ; Brick debris chunk pattern 
03457. LDA #$4b 
03458. STA Sprite_RAM+$01,Y 
03459.  
03460. ; Temp_Var1 = SPR_PAL3 
03461. LDA #SPR_PAL3 
03462. STA <Temp_Var1 
03463.  
03464. LDA SpecialObj_Timer,X 
03465. BEQ PRG007_B144 ; If timer expired, jump to PRG007_B144 
03466.  
03467. ; Rotating colors for Ice Brick debris 
03468. LSR A 
03469. AND #$03 
03470. STA <Temp_Var1 
03471.  
03472. PRG007_B144: 
03473.  
03474. ; Rotating effect 
03475. LDA Level_NoStopCnt 
03476. ASL A 
03477. ASL A 
03478. ASL A 
03479. ASL A 
03480. AND #(SPR_HFLIP | SPR_VFLIP) 
03481.  
03482. ; Set attributes 
03483. ORA <Temp_Var1 ; OR'd with palette 
03484. STA Sprite_RAM+$02,Y 
03485.  
03486. RTS ; Return 
03487.  
03488. PRG007_B153: 
03489. JSR SObj_Draw16x16 ; Draw full brick 
03490.  
03491. ; Set petterns 
03492. LDA #$75 
03493. STA Sprite_RAM+$01,Y 
03494. STA Sprite_RAM+$05,Y 
03495.  
03496. ; Set attributes on left sprite 
03497. LDA #SPR_PAL3 
03498. STA Sprite_RAM+$02,Y 
03499.  
03500. ; Set attributes on right sprite 
03501. LDA #(SPR_PAL3 | SPR_HFLIP) 
03502. STA Sprite_RAM+$06,Y 
03503.  
03504. RTS ; Return 
03505.  
03506. PRG007_B169: 
03507.  
03508. ; Popped out coin only 
03509.  
03510. LDA SpecialObj_YVel,X 
03511. CMP #$20 
03512. BMI PRG007_B17E ; If Y Velocity < $20, jump to PRG007_B17E 
03513.  
03514. ; Coin fell far enough.. 
03515.  
03516. JSR SpecialObj_Remove ; Remove it 
03517. INC Coins_Earned ; You get a coin 
03518.  
03519. JSR Score_FindFreeSlot 
03520. LDA #$89 ; Get 1000 pts; $80 just mixes up what sprite it uses 
03521. JMP PRG007_B44B ; Jump to PRG007_B44B 
03522.  
03523. PRG007_B17E: 
03524. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03525.  
03526. ; Set coin sprite Y 
03527. LDA Sprite_RAM+$03,Y 
03528. ADD #$04 
03529. STA Sprite_RAM+$03,Y 
03530.  
03531. LDA SpecialObj_Var1,X 
03532. LSR A 
03533. LSR A 
03534. AND #$03 
03535. TAX ; X = 0 to 3 
03536.  
03537. ; Set pattern 
03538. LDA PUpCoin_Patterns,X 
03539. STA Sprite_RAM+$01,Y  
03540.  
03541. ; Set attributes 
03542. LDA PUpCoin_Attributes,X 
03543. STA Sprite_RAM+$02,Y  
03544.  
03545. LDX <SlotIndexBackup ; X = special object slot index 
03546.  
03547. RTS ; Return 
03548.  
03549. ; Velocity gets applied at different rates (slower as timer decreases) 
03550. ExplodeStar_VelMask: 
03551. .byte $07, $03, $01, $00 
03552.  
03553.  
03554. SObj_ExplodeStar: 
03555. LDA SpecialObj_Data,X 
03556. BNE PRG007_B1DD ; If star's data <> 0, jump to PRG007_B1DD (RTS) 
03557.  
03558. LDA SpecialObj_Timer,X 
03559. BEQ PRG007_B1DE ; If timer expired, jump to PRG007_B1DE (RTS) 
03560.  
03561. LSR A 
03562. LSR A 
03563. LSR A 
03564. LSR A 
03565. AND #$03 
03566. TAY ; Y = 0 to 3, by timer 
03567.  
03568. ; Apply velocities at lower rates as timer decreases 
03569. LDA <Counter_1 
03570. AND ExplodeStar_VelMask,Y 
03571. BNE PRG007_B1C3 
03572.  
03573. JSR SObj_AddXVelFrac ; Apply X velocity 
03574. JSR SObj_AddYVelFrac ; Apply Y velocity 
03575.  
03576. PRG007_B1C3: 
03577. JSR SObj_GetSprRAMOffChkVScreen 
03578. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03579.  
03580. ; Set Explosion Star pattern 
03581. LDA #$73 
03582. STA Sprite_RAM+$01,Y 
03583.  
03584. ; Apply cycling palette attribute 
03585. LDA Level_NoStopCnt 
03586. LSR A 
03587. LSR A 
03588. NOP 
03589. ADD <SlotIndexBackup 
03590. AND #$03 ; A = 0 to 3 (palette select) 
03591. STA Sprite_RAM+$02,Y 
03592.  
03593. RTS ; Return 
03594.  
03595.  
03596. PRG007_B1DD: 
03597. RTS ; Return 
03598.  
03599. PRG007_B1DE: 
03600. JMP SpecialObj_Remove ; Remove special object and don't come back! 
03601.  
03602. Wand_Pattern1: .byte $99, $B9, $BD, $B9, $99, $BB, $BF, $BB 
03603. Wand_Pattern2: .byte $99, $BB, $BB, $BB, $99, $B9, $BD, $B9 
03604. Wand_Attributes: .byte SPR_PAL2, SPR_PAL2, SPR_PAL2, SPR_PAL2 | SPR_VFLIP, SPR_PAL2 | SPR_VFLIP, SPR_PAL2 | SPR_VFLIP, SPR_PAL2, SPR_PAL2 
03605.  
03606. SObj_Wand: 
03607.  
03608. ; Load wand graphics 
03609. LDA #$48 
03610. STA PatTable_BankSel+4 
03611.  
03612. LDA <Player_HaltGame 
03613. BNE PRG007_B254 ; If gameplay is halted, jump to PRG007_B254 
03614.  
03615. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
03616.  
03617. DEC SpecialObj_YVel,X 
03618.  
03619. ; Wand_FrameCnt += Var1 (spin rate) 
03620. LDA Wand_FrameCnt 
03621. ADD SpecialObj_Var1,X 
03622. STA Wand_FrameCnt 
03623. BCC PRG007_B217 ; If no carry, jump to PRG007_B217 
03624.  
03625. INC Wand_Frame ; Next wand frame 
03626.  
03627. PRG007_B217: 
03628.  
03629. JSR SObj_CheckHitSolid 
03630. BCC PRG007_B254 ; If wand has not hit solid surface, jump to PRG007_B254 
03631.  
03632. LDA SpecialObj_YVel,X 
03633. BMI PRG007_B254 ; If wand is moving upward, jump to PRG007_B254 
03634.  
03635. CMP #$20 
03636. BLT PRG007_B241 ; If wand Y Vel < $20, jump to PRG007_B241 
03637.  
03638. ; Wand bounces! 
03639. LSR A ; Divide by 2 
03640. JSR Negate ; Negate 
03641. STA SpecialObj_YVel,X 
03642.  
03643. ; Wand Y -= 2 
03644. DEC SpecialObj_YLo,X 
03645. DEC SpecialObj_YLo,X 
03646.  
03647. INC Wand_BounceFlag ; Wand_BounceFlag++ 
03648.  
03649. ; Var1 += $80 (rapid spin rate!) 
03650. LDA SpecialObj_Var1,X 
03651. ADD #$80 
03652. STA SpecialObj_Var1,X 
03653.  
03654. JMP PRG007_B254 ; Jump to PRG007_B254 
03655.  
03656. PRG007_B241: 
03657.  
03658. ; Wand has landed! 
03659. LDA #$00 
03660. STA SpecialObj_YVel,X 
03661. STA Wand_Frame ; Wand_Frame = 0 
03662.  
03663. ; Align wand Y to grid + 5 
03664. LDA SpecialObj_YLo,X 
03665. AND #$f0 
03666. ADD #$05 
03667. STA SpecialObj_YLo,X 
03668.  
03669. PRG007_B254: 
03670. JSR SObj_GetSprRAMOffChkVScreen 
03671. BNE PRG007_B291 ; If wand is not on vertical screen, jump to PRG007_B291 (RTS) 
03672.  
03673. JSR SObj_Draw16x16 ; Prepare wand sprite 
03674.  
03675. ; Subtract 4 from sprite Ys 
03676. LDA Sprite_RAM+$00,Y 
03677. SBC #$04 
03678. STA Sprite_RAM+$00,Y 
03679. STA Sprite_RAM+$04,Y 
03680.  
03681. LDA Wand_BounceFlag 
03682. LSR A ; Sets carry on odd bounces 
03683.  
03684. LDA Wand_Frame 
03685. AND #$07 ; A = 0 to 7 by Wand_Frame 
03686.  
03687. BCC PRG007_B274 ; If wand is not on an odd bounce, jump to PRG007_B274 
03688.  
03689. EOR #$07 ; Invert result (wand spin) 
03690.  
03691. PRG007_B274: 
03692. TAX ; Frame -> 'X' 
03693.  
03694. ; Set wand sprites patterns 
03695. LDA Wand_Pattern1,X 
03696. STA Sprite_RAM+$01,Y 
03697. LDA Wand_Pattern2,X 
03698. STA Sprite_RAM+$05,Y 
03699.  
03700. ; Set wand sprite attributes 
03701. LDA Wand_Attributes,X 
03702. STA Sprite_RAM+$02,Y 
03703. ORA #SPR_HFLIP 
03704. STA Sprite_RAM+$06,Y 
03705.  
03706. LDX <SlotIndexBackup ; X = special object slot index 
03707. JMP SObj_PlayerCollide ; Do Player-to-wand collision and don't come back! 
03708.  
03709. PRG007_B291: 
03710. RTS ; Return 
03711.  
03712. SObj_LavaLotusFire: 
03713.  
03714. ; Load Lava Lotus fire patterns 
03715. LDA #$1b 
03716. STA PatTable_BankSel+5 
03717.  
03718. LDA <Player_HaltGame 
03719. BNE PRG007_B2EE ; If gameplay halted, jump to PRG007_B2EE 
03720.  
03721. LDA SpecialObj_Var2,X 
03722. BEQ PRG007_B2A8 ; If Var2 (Lava Lotus fire "life" counter) = 0, jump to PRG007_B2A8 
03723.  
03724. LDA <Counter_1 
03725. LSR A  
03726. BCC PRG007_B2A8 ; Every other tick, jump to PRG007_B2A8 
03727.  
03728. DEC SpecialObj_Var2,X ; Var2-- 
03729.  
03730. PRG007_B2A8: 
03731. LDA SpecialObj_Data,X 
03732. BEQ PRG007_B2E2 ; If SpecialObj_Data = 0, jump to PRG007_B2E2 
03733.  
03734. LDY SpecialObj_Var1,X ; Y = Var1 (the parent Lava Lotus index) 
03735.  
03736. LDA Objects_State,Y 
03737. CMP #OBJSTATE_NORMAL 
03738. BNE PRG007_B2D8 ; If Lava Lotus is no longer in normal state, jump to PRG007_B2D8 
03739.  
03740. LDA Level_ObjectID,Y 
03741. CMP #OBJ_LAVALOTUS 
03742. BNE PRG007_B2D8 ; If this is no longer a Lava Lotus, jump to PRG007_B2D8 
03743.  
03744. LDA Objects_Var5,Y 
03745. CMP #$4f 
03746. BLT PRG007_B2D8 ; If Lava Lotus' Var5 < $4F, jump to PRG007_B2D8 
03747.  
03748. LDA Level_NoStopCnt 
03749.  
03750. INC SpecialObj_XLo,X ; X++ 
03751. AND #$02 
03752. BNE PRG007_B2D5 ; 2 ticks on, 2 ticks off; jump to PRG007_B2D5 
03753.  
03754. ; X -= 2 
03755. DEC SpecialObj_XLo,X 
03756. DEC SpecialObj_XLo,X 
03757.  
03758. PRG007_B2D5: 
03759. JMP PRG007_B2EE ; Jump to PRG007_B2EE 
03760.  
03761. PRG007_B2D8: 
03762.  
03763. ; SpecialObj_Data = 0 
03764. LDA #$00 
03765. STA SpecialObj_Data,X 
03766.  
03767. ; Var2 = $C0 
03768. LDA #$c0 
03769. STA SpecialObj_Var2,X 
03770.  
03771. PRG007_B2E2: 
03772. LDA <Counter_1 
03773. AND #$03 
03774. BNE PRG007_B2EE ; 1:4 ticks proceed, otherwise jump to PRG007_B2EE 
03775.  
03776. JSR SObj_AddXVelFrac ; Apply X Velocity 
03777. JSR SObj_AddYVelFrac ; Apply Y Velocity 
03778.  
03779. PRG007_B2EE: 
03780. LDA SpecialObj_Var2,X 
03781. BNE PRG007_B2F6 ; If Var2 <> 0 (fire still has life), jump to PRG007_B2F6 
03782.  
03783. JMP SpecialObj_Remove ; Otherwise, remove it and don't come back! 
03784.  
03785. PRG007_B2F6: 
03786. CMP #$30 
03787. BGE PRG007_B303 ; If Var2 >= 30, jump to PRG007_B303 
03788.  
03789. TXA ; A = special object slot index 
03790. ASL A ; * 2 
03791. ADC SpecialObj_Var2,X ; Add life counter 
03792. AND #$02 ; 0 or 2 
03793. BNE PRG007_B320 ; 2 ticks on, 2 ticks off; jump to PRG007_B320 (fire flickers away) (RTS) 
03794.  
03795. PRG007_B303: 
03796. JSR SObj_GetSprRAMOffChkVScreen  
03797.  
03798. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03799.  
03800. LDA Level_NoStopCnt 
03801. LSR A 
03802. LSR A 
03803. LSR A ; 8 ticks on/off 
03804.  
03805. LDA #$d9 ; A = $D9 
03806. BCC PRG007_B315 ; 8 ticks on, 8 ticks off; jump to PRG007_B315 
03807. LDA #$db ; A = $DB 
03808. PRG007_B315: 
03809.  
03810. ; Store pattern 
03811. STA Sprite_RAM+$01,Y 
03812.  
03813. ; Set attribute 
03814. LDA #SPR_PAL1 
03815. STA Sprite_RAM+$02,Y 
03816.  
03817. JMP SObj_PlayerCollide ; Do Player-to-fire collision and don't come back! 
03818.  
03819. PRG007_B320: 
03820. RTS ; Return 
03821.  
03822. SObj_Bubble: 
03823. LDA <Player_HaltGame 
03824. BNE PRG007_B364 ; If gameplay is halted, jump to PRG007_B364 
03825.  
03826. LDA SpecialObj_Timer,X 
03827. BNE PRG007_B32D ; If timer not expired, jump to PRG007_B32D 
03828.  
03829. JMP SpecialObj_Remove ; Otherwise, remove the bubble 
03830.  
03831. PRG007_B32D 
03832. LDA SpecialObj_Data,X 
03833. BNE PRG007_B352 ; If data <> 0, jump to PRG007_B352 
03834.  
03835. JSR SObj_AddYVelFrac ; Apply Y velocity 
03836.  
03837. LDA SpecialObj_YVel,X 
03838. BMI PRG007_B344 ; If bubble is moving upward, jump to PRG007_B344 
03839.  
03840. SUB #$07 ; Slow down (downward bubble) 
03841. STA SpecialObj_YVel,X 
03842. BPL PRG007_B34F ; If bubble is still moving downward, jump to PRG007_B34F 
03843. BMI PRG007_B34C ; Otherwise, jump to PRG007_B34C 
03844.  
03845. PRG007_B344: 
03846. ADD #$07 ; Slow down (upward bubble) 
03847. STA SpecialObj_YVel,X 
03848. BMI PRG007_B34F ; If bubble is still moving upward, jump to PRG007_B34F 
03849.  
03850. PRG007_B34C: 
03851. INC SpecialObj_Data,X ; Otherwise, set SpecialObj_Data 
03852.  
03853. PRG007_B34F: 
03854. JMP PRG007_B364 ; Jump to PRG007_B364 
03855.  
03856. PRG007_B352: 
03857. INC SpecialObj_Var1,X ; SpecialObj_Var1++ 
03858.  
03859. LDA SpecialObj_Var1,X 
03860. AND #%00110000 
03861. BEQ PRG007_B364 ; 48 ticks on, 48 ticks off; jump to PRG007_B364 
03862.  
03863. DEC SpecialObj_YLo,X ; Bubble Y -- 
03864. BNE PRG007_B364 
03865. DEC SpecialObj_YHi,X ; Apply carry 
03866. PRG007_B364: 
03867.  
03868. LDA Level_NoStopCnt 
03869. AND #%00001100 
03870. LSR A 
03871. LSR A 
03872. TAY ; Y = 0 or 3 
03873.  
03874. ; Bubble_XOff -> Temp_Var1 
03875. LDA Bubble_XOff,Y 
03876. STA <Temp_Var1 
03877.  
03878. JSR SObj_GetSprRAMOffChkVScreen 
03879. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
03880.  
03881. ; Set bubble X 
03882. LDA SpecialObj_XLo,X 
03883. ADD <Temp_Var1  
03884. SUB <Horz_Scroll 
03885. STA Sprite_RAM+$03,Y 
03886.  
03887. ; Set bubble pattern 
03888. LDA #$17 
03889. STA Sprite_RAM+$01,Y 
03890.  
03891. ; Set bubble attributes 
03892. LDA #SPR_PAL1 
03893. STA Sprite_RAM+$02,Y 
03894.  
03895. RTS ; Return 
03896.  
03897.  
03898. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
03899. ; SObj_ApplyXYVelsWithGravity 
03900. ; 
03901. ; Apply the special object X and Y velocity with gravity 
03902. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
03903. SObj_ApplyXYVelsWithGravity: 
03904. JSR SObj_AddXVelFrac ; Apply X velocity 
03905. JSR SObj_AddYVelFrac ; Apply Y velocity 
03906.  
03907. LDA SpecialObj_YVel,X 
03908. BMI PRG007_B39D ; If special object is moving upward, jump to PRG007_B39D 
03909.  
03910. CMP #$6e 
03911. BGE PRG007_B3A3 ; If special object Y velocity >= $6E, jump to PRG007_B3A3 (RTS) 
03912.  
03913. PRG007_B39D: 
03914.  
03915. ; Apply gravity 
03916. INC SpecialObj_YVel,X 
03917. INC SpecialObj_YVel,X 
03918.  
03919. PRG007_B3A3: 
03920. RTS ; Return 
03921.  
03922. Cannonball_YOffset: .byte 16, $00 
03923. Cannonball_YDiffLimit: .byte 16, 32 
03924.  
03925. SObj_Cannonball: 
03926.  
03927. ; Load cannonball graphics 
03928. LDA #$36 
03929. STA PatTable_BankSel+4 
03930.  
03931. LDA <Player_HaltGame 
03932. BNE PRG007_B3C2 ; If gameplay halted, jump to PRG007_B3C2 
03933.  
03934. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
03935. JSR SObj_OffsetYForRaster ; Offset the Y by raster effects, if any 
03936.  
03937. LDA SpecialObj_Data,X 
03938. BNE PRG007_B3C2 ; If data <> 0 (cannonball is stomped), jump to PRG007_B3C2 
03939.  
03940. ; Otherwise, Y Vel -= 2 (??) 
03941. DEC SpecialObj_YVel,X 
03942. DEC SpecialObj_YVel,X 
03943.  
03944. PRG007_B3C2: 
03945. JSR SObj_GetSprRAMOffChkVScreen 
03946. BNE PRG007_B3A3 ; If cannonball is vertically off-screen, jump to PRG007_B3A3 (RTS) 
03947.  
03948. JSR SObj_Draw16x16 ; Prep cannonball sprites 
03949.  
03950. ; Set cannon ball sprite attributes 
03951. LDA #SPR_PAL3 
03952. STA Sprite_RAM+$02,Y 
03953. STA Sprite_RAM+$06,Y 
03954.  
03955. ; Set left and right cannonball patterns 
03956. LDA #$af 
03957. STA Sprite_RAM+$05,Y 
03958. LDA #$ad 
03959. STA Sprite_RAM+$01,Y 
03960.  
03961. LDA SpecialObj_Data,X 
03962. ORA Player_IsDying 
03963. ORA Player_OffScreen 
03964. BNE PRG007_B445 ; If cannonon ball is already stomped, Player is dying, or Player is off-screen, jump to PRG007_B445 (RTS) 
03965.  
03966. LDY #$00 ; Y = 0 (Player is small or ducking) 
03967.  
03968. LDA <Player_Suit 
03969. BEQ PRG007_B3F3 ; If Player is small, jump to PRG007_B3F3 
03970.  
03971. LDA Player_IsDucking 
03972. BNE PRG007_B3F3 ; If Player is ducking, jump to PRG007_B3F3 
03973.  
03974. INY ; Y = 1 (Player not small/ducking) 
03975.  
03976. PRG007_B3F3: 
03977. LDA SpecialObj_YLo,X ; Cannonball Y 
03978. SUB <Player_Y ; Player Y 
03979. SUB Cannonball_YOffset,Y ; Offset 
03980. CMP Cannonball_YDiffLimit,Y 
03981. BGE PRG007_B445 ; If Player is not close enough to top of cannonball, jump to PRG007_B445 (RTS) 
03982.  
03983. LDA SpecialObj_XLo,X 
03984. ADD #$08 ; Cannonball X + 8 
03985. SUB <Player_X ; Diff against Player X 
03986. CMP #20 
03987. BGE PRG007_B445 ; If Player is not close enough horizontally to cannonball, jump to PRG007_B445 (RTS) 
03988.  
03989. LDA Player_StarInv 
03990. BNE PRG007_B426 ; If Player is invincible by Star Man, jump to PRG007_B426 
03991.  
03992. LDA <Player_YVel 
03993. BMI PRG007_B442 ; If Player is moving upward, jump to PRG007_B442 
03994.  
03995. LDA SpecialObj_YLo,X 
03996. SUB Level_VertScroll 
03997. SUB #19 
03998. CMP <Player_SpriteY 
03999. BLT PRG007_B442 ; If Player is close enough to bottom of cannonball, jump to PRG007_B442 
04000.  
04001. PRG007_B426: 
04002.  
04003. ; Flag cannonball as stomped! 
04004. LDA #$01 
04005. STA SpecialObj_Data,X 
04006.  
04007. ; Halt its movements 
04008. LDA #$00 
04009. STA SpecialObj_XVel,X 
04010. STA SpecialObj_YVel,X 
04011.  
04012. ; Player bounces off cannonball 
04013. LDA #-$30 
04014. STA <Player_YVel 
04015.  
04016. ; Cannonball kick sound 
04017. LDA Sound_QPlayer 
04018. ORA #SND_PLAYERKICK 
04019. STA Sound_QPlayer 
04020.  
04021. JMP PRG007_B446 ; Jump to PRG007_B446 
04022.  
04023. PRG007_B442: 
04024. JMP PRG007_B805 ; Jump to PRG007_B805 (remainder of Player hit checks) 
04025.  
04026. PRG007_B445: 
04027. RTS ; Return 
04028.  
04029.  
04030. PRG007_B446: 
04031. JSR Score_FindFreeSlot 
04032.  
04033. ; Set base score and add Kill_Tally 
04034. LDA #$85 ; Base 100 points; $80 just mixes up what sprite it uses 
04035.  
04036. PRG007_B44B: 
04037. ADD Kill_Tally 
04038. STA Scores_Value,Y 
04039.  
04040. INC Kill_Tally ; Kill_Tally++ 
04041.  
04042. ; Set the score counter 
04043. LDA #$30 
04044. STA Scores_Counter,Y 
04045.  
04046. LDA SpecialObj_YLo,X 
04047. SUB Level_VertScroll 
04048. SBC #$06 
04049. CMP #192 
04050. BLT PRG007_B469 ; If score Y < 192, jump to PRG007_B469 
04051.  
04052. LDA #$05 ; Otherwise, use Y = 5 
04053.  
04054. PRG007_B469: 
04055. STA Scores_Y,Y ; Set score Y 
04056.  
04057. ; Set score X 
04058. LDA SpecialObj_XLo,X 
04059. SUB <Horz_Scroll 
04060. STA Scores_X,Y 
04061.  
04062. RTS ; Return 
04063.  
04064.  
04065. SObj_OffsetYForRaster: 
04066. LDA Level_AScrlConfig 
04067. BEQ PRG007_B491 ; If there's no raster effect going on, jump to PRG007_B491 (RTS) 
04068.  
04069. LDY #$00 ; Y = $00 (16-bit sign extension) 
04070.  
04071. LDA Level_ScrollDiffV 
04072. BPL PRG007_B483 ; If vertical scroll difference is not negative, jump to PRG007_B483 
04073.  
04074. DEY ; Otherwise, Y = $FF (16-bit sign extension) 
04075.  
04076. PRG007_B483: 
04077. ADD SpecialObj_YLo,X 
04078. STA SpecialObj_YLo,X ; Apply raster offset to Special Object Y 
04079.  
04080. TYA 
04081.  
04082. ADC SpecialObj_YHi,X 
04083. STA SpecialObj_YHi,X ; Apply sign extension/carry 
04084.  
04085. PRG007_B491: 
04086. RTS ; Return 
04087.  
04088. Wrench_Patterns: .byte $A1, $95, $9F, $95 
04089. Wrench_Attributes: .byte SPR_PAL2, SPR_PAL2 | SPR_VFLIP, SPR_PAL2, SPR_PAL2 
04090.  
04091. SObj_Wrench: 
04092. LDA <Player_HaltGame  
04093. BNE PRG007_B4AF ; If gameplay halted, jump to PRG007_B4AF 
04094.  
04095. JSR SObj_OffsetYForRaster ; Offset Y with raster effects (if any) 
04096. JSR SObj_AddXVelFrac ; Apply X velocity 
04097.  
04098. LDA SpecialObj_YVel,X 
04099. BEQ PRG007_B4AC ; If wrench Y velocity = 0, jump to PRG007_B4AC 
04100.  
04101. INC SpecialObj_YVel,X ; Otherwise, Y Vel++ (fall?) 
04102.  
04103. PRG007_B4AC: 
04104. JSR SObj_AddYVelFrac ; Apply Y velocity 
04105.  
04106. PRG007_B4AF: 
04107. JSR SObj_PlayerCollide ; Do Player-to-wrench collision 
04108.  
04109. JSR SObj_GetSprRAMOffChkVScreen 
04110. BNE PRG007_B4EB ; If wrench is not vertically on-screen, jump to PRG007_B4EB (RTS) 
04111.  
04112. ; Set Temp_Var1 = $00 or $80, depending on sign bit of X velocity 
04113. LDA SpecialObj_XVel,X 
04114. AND #$80 
04115. STA <Temp_Var1 
04116.  
04117. LDA Level_NoStopCnt 
04118. LSR A 
04119. ADD <SlotIndexBackup 
04120. AND #$03 
04121. TAX ; X = 0 to 3 
04122.  
04123. ; Set wrench pattern 
04124. LDA Wrench_Patterns,X 
04125. STA Sprite_RAM+$01,Y 
04126.  
04127. ; Set wrench attributes 
04128. LDA Wrench_Attributes,X 
04129. EOR <Temp_Var1  
04130. STA Sprite_RAM+$02,Y 
04131.  
04132. LDX <SlotIndexBackup ; X = special object slot index 
04133.  
04134. SObj_SetSpriteXYRelative: 
04135. LDA SpecialObj_YLo,X 
04136. SUB Level_VertScroll 
04137. STA Sprite_RAM+$00,Y 
04138.  
04139. LDA SpecialObj_XLo,X 
04140. SUB <Horz_Scroll 
04141. STA Sprite_RAM+$03,Y 
04142.  
04143. PRG007_B4EB: 
04144. RTS ; Return 
04145.  
04146.  
04147. ; In the Japanese original, there were other power ups that "flew off" 
04148. ; when you lost them, and those are the additional values. None of 
04149. ; them display correctly anymore, however, because: 
04150. ; 
04151. ; The graphics for the fly-off sprite only exist with small Mario,  
04152. ; meaning when they added the "American" rule of returning to "super" 
04153. ; state, it didn't have the suit sprite graphics available! 
04154.  
04155. LostShoe_Pattern: .byte $A9, $AB ; 0 
04156. .byte $39, $39 ; 1 
04157. .byte $3B, $3B ; 2 
04158. .byte $3D, $3D ; 3 
04159. LostShoe_Attribute: .byte $02, $01, $01, $01 
04160.  
04161. SObj_WandBlast: 
04162. LDA <Player_HaltGame 
04163. BNE PRG007_B502 ; If gameplay is halted, jump to PRG007_B502 
04164.  
04165. JSR SObj_AddXVelFrac ; Apply X Velocity 
04166. JSR SObj_AddYVelFrac ; Apply Y Velocity 
04167.  
04168. PRG007_B502: 
04169. JSR SObj_GetSprRAMOffChkVScreen 
04170.  
04171. LDA SpecialObj_Timer,X 
04172. TAX ; Timer -> 'X' 
04173.  
04174. ; Select which pattern to use by timer 
04175. LDA #$fd ; A = $FD 
04176.  
04177. CPX #$e0 
04178. BGE PRG007_B517 ; If timer >= $E0, jump to PRG007_B517 
04179.  
04180. LDA #$f9 ; A = $F9 
04181.  
04182. CPX #$c0 
04183. BGE PRG007_B517 ; If timer >= $C0, jump to PRG007_B517 
04184.  
04185. LDA #$fb ; A = $FB 
04186.  
04187. PRG007_B517: 
04188. ; Set the wand blast pattern 
04189. STA Sprite_RAM+$01,Y 
04190.  
04191. LDX <SlotIndexBackup ; X = special object slot index 
04192.  
04193. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
04194.  
04195. TXA ; Special object slot index -> 'A' 
04196. LSR A ; Shift bit 0 into carry 
04197. ROR A ; Rotate it around to bit 7 
04198. AND #SPR_VFLIP 
04199. STA <Temp_Var1 ; Temp_Var1 = VFlip attribute or not 
04200.  
04201. LDA <Counter_1 
04202. LSR A  
04203. LSR A  
04204. LSR A  
04205. ROR A  
04206. AND #SPR_VFLIP 
04207. ORA #SPR_PAL1 
04208. EOR <Temp_Var1 ; Invert VFlip by Temp_Var1 
04209.  
04210. ; Set wand blast attribute 
04211. STA Sprite_RAM+$02,Y 
04212.  
04213. JMP SObj_PlayerCollide ; Do Player-to-wand blast collision and don't come back! 
04214.  
04215. RTS ; Return 
04216.  
04217. SObj_KuriboShoe: 
04218. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
04219.  
04220. JSR SObj_GetSprRAMOffChkVScreen 
04221.  
04222. LDA SpecialObj_Data,X 
04223. TAX ; SpecialObj_Data -> 'X' (NOTE: Will always be zero in US version, see notes at LostShoe_Pattern) 
04224.  
04225. ; Set left sprite attribute 
04226. LDA LostShoe_Attribute,X 
04227. STA Sprite_RAM+$02,Y 
04228.  
04229. CPX #$00 
04230. BEQ PRG007_B54F ; For the lost Kuribo's shoe only: Do not mirror sprite, jump to PRG007_B54F 
04231.  
04232. ORA #SPR_HFLIP ; Mirror sprite (NOTE: Used only in Japanese version for the "fly off" super suits!) 
04233.  
04234. PRG007_B54F: 
04235. STA Sprite_RAM+$06,Y ; Set attributes on right sprite 
04236.  
04237. ; X *= 2 (two patterns per suit, again generally unused in US version) 
04238. TXA 
04239. ASL A 
04240. TAX 
04241.  
04242. ; Pattern for left fly off sprite 
04243. LDA LostShoe_Pattern,X 
04244. STA Sprite_RAM+$01,Y 
04245.  
04246. ; Pattern for right fly off sprite 
04247. LDA LostShoe_Pattern+1,X 
04248. STA Sprite_RAM+$05,Y 
04249.  
04250. LDX <SlotIndexBackup ; X = special object slot index 
04251.  
04252. SObj_Draw16x16: 
04253. JSR SObj_SetSpriteXYRelative  
04254.  
04255. ; Copy sprite Y into right sprite 
04256. LDA Sprite_RAM+$00,Y 
04257. STA Sprite_RAM+$04,Y 
04258.  
04259. ; Right sprite is X + 8 
04260. LDA Sprite_RAM+$03,Y 
04261. ADD #$08 
04262. STA Sprite_RAM+$07,Y 
04263.  
04264. RTS ; Return 
04265.  
04266.  
04267. SObj_Spikeball: 
04268. LDA <Player_HaltGame 
04269. BNE PRG007_B588 ; If gameplay is halted, jump to PRG007_B588 
04270.  
04271. LDA SpecialObj_Data,X 
04272. BEQ PRG007_B585 ; If SpecialObj_Data = 0 (no gravity version, specifically Spike's spike ball), jump to PRG007_B585 
04273.  
04274. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
04275. JMP PRG007_B588 ; Jump to PRG007_B588 
04276.  
04277. PRG007_B585: 
04278. JSR SObj_AddXVelFrac ; Apply X velocity only 
04279.  
04280. PRG007_B588: 
04281. JSR SObj_GetSprRAMOffChkVScreen 
04282.  
04283. ; Spike ball pattern 
04284. LDA #$95 
04285. STA Sprite_RAM+$01,Y 
04286. STA Sprite_RAM+$05,Y 
04287.  
04288. JSR SObj_Draw16x16 ; Draw spike ball 
04289.  
04290. ; Set spike ball left attributes 
04291. LDA Level_NoStopCnt 
04292. LSR A 
04293. LSR A 
04294. LSR A 
04295. ROR A 
04296. AND #SPR_VFLIP ; Toggles which side is going to be vertically flipped 
04297. ORA #SPR_PAL2 
04298. STA Sprite_RAM+$02,Y 
04299.  
04300. ; Set opposite flips on right sprite 
04301. EOR #(SPR_HFLIP | SPR_VFLIP) 
04302. STA Sprite_RAM+$06,Y 
04303.  
04304. LDA SpecialObj_Data,X 
04305. BNE PRG007_B5B1 ; If SpecialObj_Data <> 0 (Gravity version, specifically Patooie's spike ball), jump to PRG007_B5B1 (RTS) 
04306.  
04307. JMP SObj_PlayerCollide ; Do Player to spike ball collision and don't come back! 
04308.  
04309. PRG007_B5B1: 
04310. RTS ; Return 
04311.  
04312. Microgoomba_XAccel: .byte $01, -$01 
04313. Microgoomba_XLimit: .byte $10, -$10 
04314.  
04315. Microgoomba_SprRAMAlt: .byte $00, $04, $08, $0C, $10, $14, $18, $1C, $20, $24 
04316.  
04317. SObj_Microgoomba: 
04318.  
04319. ; Load Microgoomba's graphics 
04320. LDA #$4f 
04321. STA PatTable_BankSel+5 
04322.  
04323. LDA <Player_HaltGame 
04324. BEQ PRG007_B5CC ; If gameplay is not halted, jump to PRG007_B5CC 
04325.  
04326. JMP Microgoomba_Draw ; Draw Microgoomba and don't come back! 
04327.  
04328. PRG007_B5CC: 
04329. LDA SpecialObj_Data,X 
04330. BNE PRG007_B5D4 ; If SpecialObj_Data <> 0, jump to PRG007_B5D4 
04331.  
04332. JMP PRG007_B660 ; Otherwise, jump to PRG007_B660 
04333.  
04334. PRG007_B5D4: 
04335. BPL PRG007_B5DC ; If SpecialObj_Data > 0, jump to PRG007_B5DC 
04336.  
04337. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
04338. JMP Microgoomba_Draw ; Draw Microgoomba and don't come back 
04339.  
04340. PRG007_B5DC: 
04341. LDY Player_StarInv 
04342. BNE PRG007_B601 ; If Player is invincible by Star Man, jump to PRG007_B601 
04343.  
04344. LDY Player_InWater 
04345. BNE PRG007_B601 ; If Player is in water, jump to PRG007_B601 
04346.  
04347. INC Player_UphillSpeedIdx ; Player_UphillSpeedIdx = 1 (Microgoomba stuck to Player) 
04348.  
04349. CMP #$05 
04350. BGE PRG007_B5F6 ; If Microgoomba is already at his maximum stickiness, jump to PRG007_B5F6 
04351.  
04352. ; Player is trying to shake him... 
04353.  
04354. LDA <Counter_1 
04355. AND #$0f 
04356. BNE PRG007_B5F6 ; 1:16 ticks proceed, otherwise, jump to PRG007_B5F6 
04357.  
04358. INC SpecialObj_Data,X ; SpecialObj_Data++ (Increase "stickiness", up to 5) 
04359.  
04360. PRG007_B5F6: 
04361. LDA <Pad_Input 
04362. AND #$ff ; This probably was intended to be a specific button rather than "everything" 
04363. BEQ PRG007_B617 ; If Player is not pressing anything, jump to PRG007_B617 
04364.  
04365. DEC SpecialObj_Data,X ; SpecialObj_Data-- 
04366. BNE PRG007_B617 ; If SpecialObj_Data > 0, jump to PRG007_B617 
04367.  
04368. PRG007_B601: 
04369.  
04370. ; Otherwise, SpecialObj_Data = $FF (Microgoomba's "death" value) 
04371. LDA #$ff 
04372. STA SpecialObj_Data,X 
04373.  
04374. ; Microgoomba flops off 
04375. LDA #-$20 
04376. STA SpecialObj_YVel,X 
04377.  
04378. LDA #$08 ; A = $08 
04379.  
04380. LDY RandomN,X 
04381. BPL PRG007_B614 ; 50/50 chance we jump to PRG007_B614 
04382.  
04383. LDA #-$08 ; A = -$08 
04384.  
04385. PRG007_B614: 
04386. STA SpecialObj_XVel,X ; Random X velocity 
04387.  
04388. PRG007_B617: 
04389. INC SpecialObj_Var1,X ; SpecialObj_Var1++ 
04390.  
04391. ; Set Microgoomba's Y... 
04392. LDA SpecialObj_Var1,X 
04393. LSR A 
04394. LSR A 
04395. AND #%00011111 
04396. CMP #%00010000 
04397. AND #%00001111 
04398. BCC PRG007_B62B ; 16 ticks on, 16 ticks off; jump to PRG007_B62B 
04399.  
04400. EOR #%00001111 
04401. ADC #$00 
04402.  
04403. PRG007_B62B: 
04404. CLC ; Clear carry 
04405.  
04406. LDY Player_IsDucking 
04407. BNE PRG007_B635 ; If Player is ducking, jump to PRG007_B635 
04408.  
04409. LDY <Player_Suit 
04410. BNE PRG007_B639 ; If Player is small, jump to PRG007_B639 
04411.  
04412. PRG007_B635: 
04413. LSR A 
04414. ADD #$08 
04415.  
04416. PRG007_B639: 
04417. ADC <Player_Y 
04418. STA SpecialObj_YLo,X 
04419. LDA <Player_YHi 
04420. ADC #$00 
04421. STA SpecialObj_YHi,X 
04422.  
04423.  
04424. ; Set Microgoomba's X... 
04425. LDA SpecialObj_Var1,X 
04426. AND #%00011111 
04427. CMP #%00010000 
04428. AND #%00001111 
04429. BLT PRG007_B654 ; 16 ticks on, 16 ticks off; jump to PRG007_B62B 
04430.  
04431. EOR #%00001111 
04432. ADC #$00 
04433.  
04434. PRG007_B654: 
04435. SUB #$03 
04436. ADD <Player_X 
04437. STA SpecialObj_XLo,X 
04438.  
04439. JMP Microgoomba_Draw ; Draw Microgoomba and don't come back 
04440.  
04441. PRG007_B660: 
04442.  
04443. ; SpecialObj_Data = 0... 
04444.  
04445. JSR SObj_AddXVelFrac ; Apply X Velocity 
04446. JSR SObj_AddYVelFrac ; Apply Y Velocity 
04447.  
04448. LDA SpecialObj_YVel,X 
04449. CMP #$10 
04450. BGS PRG007_B670 ; If Microgoomba's Y velocity >= 16, jump to PRG007_B670 
04451.  
04452. INC SpecialObj_YVel,X ; Otherwise, Y Vel++ 
04453.  
04454. PRG007_B670: 
04455. LDA <Counter_1 
04456. AND #$00 
04457. BNE Microgoomba_Draw ; Technically NEVER jump to Microgoomba_Draw (??) 
04458.  
04459. LDA SpecialObj_Var1,X 
04460. AND #$01 
04461. TAY ; Y = 0 or 1 
04462.  
04463. ; Accelerate Microgoomba 
04464. LDA SpecialObj_XVel,X 
04465. ADD Microgoomba_XAccel,Y 
04466. STA SpecialObj_XVel,X 
04467.  
04468. CMP Microgoomba_XLimit,Y 
04469. BNE Microgoomba_Draw ; If Microgoomba hasn't his X velocity limit, jump to Microgoomba_Draw 
04470.  
04471. INC SpecialObj_Var1,X ; Otherwise, SpecialObj_Var1++ (switch direction) 
04472.  
04473. Microgoomba_Draw: 
04474. JSR SObj_GetSprRAMOffChkVScreen 
04475. BNE PRG007_B6CE ; If Microgoomba is not on this vertical screen, jump to PRG007_B6CE (RTS) 
04476.  
04477. LDA SpecialObj_Data,X 
04478. BEQ PRG007_B6A9 
04479. BMI PRG007_B6A9 ; If SpecialObj_Data <= 0, jump to PRG007_B6A9 
04480.  
04481. TXA 
04482. ASL A 
04483. ASL A 
04484. ASL A 
04485. ASL A 
04486. EOR SpecialObj_Var1,X 
04487. AND #%00010000 
04488. BEQ PRG007_B6A9 ; Every 2 direction changes, jump to PRG007_B6A9 
04489.  
04490. ; Use alternate Sprite RAM offset periodically 
04491. LDY Microgoomba_SprRAMAlt,X ; Y = Microgoomba sprite RAM offset 
04492.  
04493. PRG007_B6A9: 
04494. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
04495.  
04496. ; Microgoomba pattern 
04497. LDA #$ff 
04498. STA Sprite_RAM+$01,Y 
04499.  
04500. LDX #SPR_PAL3 
04501.  
04502. LDA Level_NoStopCnt 
04503. AND #$08 
04504. BEQ PRG007_B6BC ; 8 ticks on, 8 ticks off; jump to PRG007_B6BC 
04505.  
04506. LDX #(SPR_PAL3 | SPR_HFLIP) 
04507.  
04508. PRG007_B6BC: 
04509.  
04510. ; Store selected attributes 
04511. TXA 
04512. STA Sprite_RAM+$02,Y 
04513.  
04514. LDX <SlotIndexBackup ; X = special object slot 
04515.  
04516. LDA SpecialObj_Data,X 
04517. BEQ PRG007_B6CF ; If SpecialObj_Data = 0, jump to PRG007_B6CF (Player to Microgoomba collision) 
04518. BPL PRG007_B6CE ; If SpecialObj_Data > 0 (Microgoomba still alive), jump to PRG007_B6CE (RTS) 
04519.  
04520. ; Microgoomba is dead; vertically flip 
04521. LDA #(SPR_PAL3 | SPR_VFLIP) 
04522. STA Sprite_RAM+$02,Y 
04523.  
04524. PRG007_B6CE: 
04525. RTS ; Return 
04526.  
04527. PRG007_B6CF: 
04528. JMP SObj_PlayerCollide ; Handle Player to Microgoomba collision and don't come back! 
04529.  
04530. ; The hammer starting X is offset 
04531. Hammer_XOff: 
04532. ; Not-HF HF (HF = Horizontally flipped) 
04533. .byte 8, -8 ; Non-Heavy Hammer hold offset 
04534. .byte 8, -8 ; Non-Heavy Boomerang hold offset 
04535. .byte 16, -8 ; Heavy Bro hold offset 
04536.  
04537. ; The hammer starting Y is offset 
04538. Hammer_YOff: 
04539. ; Not-HF HF (HF = Horizontally flipped) 
04540. .byte 3, 3 ; Non-Heavy Hammer hold offset 
04541. .byte 3, 3 ; Non-Heavy Boomerang hold offset 
04542. .byte -6, -6 ; Heavy Bro hold offset 
04543.  
04544. SObjYOff_PlayerSize: .byte 18, 10 ; Small vs not small 
04545. SObj_VLimit: .byte $10, $16 
04546. PRG007_B6E2: .byte $00, $10 
04547.  
04548. SObj_Hammer: 
04549. LDA <Player_HaltGame 
04550. BEQ PRG007_B6EB ; If gameplay is not halted, jump to PRG007_B6EB 
04551.  
04552. JMP PRG007_B773 ; Otherwise, jump to PRG007_B773 
04553.  
04554. PRG007_B6EB: 
04555.  
04556. ; SpecialObj_Data special purposes: 
04557. ; Bits 0-3: Decrement to zero 
04558. ; Bits 4-7: While lower 4 bits not zero, references an object which, if not in normal state or off-screen, destroys this object 
04559.  
04560. LDA SpecialObj_Data,X 
04561. AND #%00001111 ; Consider lowest 4 bits of SpecialObj_Data 
04562. BEQ PRG007_B76D ; If zero, jump to PRG007_B76D 
04563.  
04564. PRG007_B6F2: 
04565. ; Lowest 4 bits of SpecialObj_Data is non-zero 
04566.  
04567. DEC SpecialObj_Data,X ; SpecialObj_Data-- (mainly to effect the lowest 4 bits) 
04568.  
04569. LDA SpecialObj_Data,X 
04570. LSR A 
04571. LSR A 
04572. LSR A 
04573. LSR A 
04574. TAY ; Y = the upper 4 bits (an object slot index) 
04575. STY <Temp_Var2 ; -> Temp_Var2 
04576.  
04577. LDA Objects_State,Y 
04578. CMP #OBJSTATE_NORMAL 
04579. BNE PRG007_B70D ; If this object is not in normal state, jump to PRG007_B70D 
04580.  
04581. LDA Objects_SprHVis,Y 
04582. AND #%11000000 
04583. BEQ PRG007_B710 ; If this sprite does not have its two left sprites off-screen, jump to PRG007_B710 
04584.  
04585. PRG007_B70D: 
04586.  
04587. ; Referenced object is not in normal state or it is off-screen; destroy special object 
04588. JMP SpecialObj_Remove 
04589.  
04590. PRG007_B710: 
04591. LDA Objects_FlipBits,Y 
04592. AND #SPR_HFLIP 
04593. STA <Temp_Var3 ; Catch the horizontal flip bit of the referenced object -> Temp_Var3 
04594.  
04595. ; Temp_Var1 = 0 to 1, based on whether object is horizontally flipped 
04596. ASL A 
04597. ASL A 
04598. ROL A 
04599. AND #$01 
04600. STA <Temp_Var1 
04601.  
04602. LDA SpecialObj_ID,X 
04603. CMP #SOBJ_HAMMER 
04604. BEQ PRG007_B729 ; If this is a hammer, jump to PRG007_B729 
04605.  
04606. ; Otherwise, Temp_Var1 += 2 
04607. INC <Temp_Var1 
04608. INC <Temp_Var1 
04609.  
04610. PRG007_B729: 
04611. LDA Level_ObjectID,Y 
04612. CMP #OBJ_HEAVYBRO 
04613. BNE PRG007_B737 ; If this not a Heavy Bro, jump to PRG007_B737 
04614.  
04615. ; Otherwise, Temp_Var1 += 4 
04616. LDA <Temp_Var1 
04617. ADD #$04 
04618. STA <Temp_Var1 
04619.  
04620. PRG007_B737: 
04621.  
04622. ; Set hammer starting X 
04623. LDA Objects_X,Y 
04624. LDY <Temp_Var1  
04625. ADD Hammer_XOff,Y 
04626. STA SpecialObj_XLo,X 
04627.  
04628. LDY <Temp_Var2 ; Y = referenced object slot index 
04629.  
04630. ; Set hammer starting Y 
04631. LDA Objects_Y,Y 
04632. CLC 
04633. LDY <Temp_Var1 
04634. ADC Hammer_YOff,Y 
04635. STA SpecialObj_YLo,X 
04636.  
04637. LDA #$00 ; A = 0 
04638.  
04639. LDY SpecialObj_XVel,X 
04640. BMI PRG007_B75A ; If hammer is traveling to the left, jump to PRG007_B75A 
04641.  
04642. LDA #SPR_HFLIP ; A = SPR_HFLIP 
04643.  
04644. PRG007_B75A: 
04645. CMP <Temp_Var3 
04646. BEQ PRG007_B76A ; If hammer is flipped the same way as object, jump to PRG007_B76A 
04647.  
04648. ; Reverse X velocity 
04649. LDA SpecialObj_XVel,X 
04650. JSR Negate 
04651. STA SpecialObj_XVel,X 
04652.  
04653. INC SpecialObj_Var2,X 
04654.  
04655. PRG007_B76A: 
04656. JMP PRG007_B773 ; Jump to PRG007_B773 
04657.  
04658. PRG007_B76D: 
04659. INC SpecialObj_Var1,X ; SpecialObj_Var1++ 
04660.  
04661. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
04662.  
04663. PRG007_B773: 
04664. JSR SObj_GetSprRAMOffChkVScreen ; Get a sprite RAM offset 
04665. BEQ PRG007_B779 ; If object is on the same vertical screen (see Temp_Var14 calculation), jump to PRG007_B779 
04666.  
04667. RTS ; Return 
04668.  
04669. PRG007_B779: 
04670. STY <Temp_Var2 ; Sprite RAM offset -> 'Y' 
04671.  
04672. LDA SpecialObj_XVel,X 
04673.  
04674. LDY SpecialObj_ID,X 
04675. CPY #SOBJ_HAMMER 
04676. BEQ PRG007_B787 ; If this is a hammer, jump to PRG007_B787 
04677.  
04678. EOR #$80 ; Invert sign on X velocity 
04679.  
04680. PRG007_B787: 
04681. LSR A ; Shift down the bit 
04682. AND #SPR_HFLIP ; Horizontal flip bit 
04683. STA <Temp_Var1 ; -> Temp_Var1 
04684.  
04685. CPY #SOBJ_HAMMER 
04686. BNE PRG007_B798 ; If this is not a hammer, jump to PRG007_B798 
04687.  
04688. LDY <Temp_Var2 ; Y = Sprite RAM Offset 
04689.  
04690. JSR Hammer_Draw ; Draw hammer 
04691. JMP PRG007_B7C5 ; Jump to PRG007_B7C5 
04692.  
04693. PRG007_B798: 
04694. LDY <Temp_Var2 ; Y = Sprite RAM Offset 
04695.  
04696. LDA SpecialObj_Var1,X 
04697. AND #%00001100 
04698. LSR A 
04699. LSR A 
04700. TAX ; X = 0 to 3 
04701.  
04702. ; Set boomerang sprites attributes 
04703. LDA <Temp_Var1 
04704. EOR Boomerang_Attributes,X 
04705. ORA #SPR_PAL1 
04706. STA Sprite_RAM+$02,Y 
04707. STA Sprite_RAM+$06,Y 
04708.  
04709. LDA <Temp_Var1 
04710. BEQ PRG007_B7B5 ; If Temp_Var1 = 0, jump to PRG007_B7B5 
04711.  
04712. INX 
04713. INX 
04714.  
04715. PRG007_B7B5: 
04716. TXA 
04717. AND #$03 
04718. TAX 
04719.  
04720. ; Set boomerang sprites patterns 
04721. LDA Boomerang_Patterns,X 
04722. STA Sprite_RAM+$01,Y 
04723. LDA Boomerang_Patterns+2,X 
04724. STA Sprite_RAM+$05,Y 
04725.  
04726. PRG007_B7C5: 
04727. LDX <SlotIndexBackup ; X = special object slot index 
04728.  
04729. JSR SObj_Draw16x16 ; Draw Boomerang 
04730.  
04731. LDA SpecialObj_Data,X 
04732. AND #%00001111 
04733. BNE PRG007_B826 ; If lower 4 bits are not zero, jump to PRG007_B826 (RTS) 
04734.  
04735. SObj_PlayerCollide: 
04736.  
04737. ; Player to Special Object collision logic... 
04738.  
04739. TXA ; object slot index -> 'A' 
04740. ADD <Counter_1 ; Keep it interesting 
04741. LSR A 
04742. BCC PRG007_B826 ; Every other tick, jump to PRG007_B826 (RTS) 
04743.  
04744. LDY #$00 ; Y = 0 (small/ducking) 
04745.  
04746. LDA <Player_Suit 
04747. BEQ PRG007_B7E4 ; If Player is small, jump to PRG007_B7E4 
04748.  
04749. LDA Player_IsDucking 
04750. BNE PRG007_B7E4 ; If Player is ducking, jump to PRG007_B7E4 
04751.  
04752. INY ; Y = 1 (otherwise) 
04753.  
04754. PRG007_B7E4: 
04755. LDA SpecialObj_YLo,X ; Special object Y 
04756. ADD #$08 ; +8 
04757. SUB <Player_Y ; Subtract Player Y 
04758. SUB SObjYOff_PlayerSize,Y ; Subtract Player height offset 
04759. CMP SObj_VLimit,Y 
04760. BGE PRG007_B843 ; If result >= SObj_VLimit, jump to PRG007_B843 (RTS) 
04761.  
04762. LDA SpecialObj_XLo,X ; Special object X 
04763. ADD #$06 ; +6 
04764. SUB <Player_X ; Subtract Player X 
04765. SBC #$00 ; Carry? 
04766. CMP #16 
04767. BGE PRG007_B843 ; If result >= 16, jump to PRG007_B843 (RTS) 
04768.  
04769. PRG007_B805: 
04770. LDA Player_FlashInv ; If Player is flashing from being hit ... 
04771. ORA Player_Statue ; ... if Player is a statue ... 
04772. ORA <Player_HaltGame ; ... if gameplay is halted ... 
04773. ORA Player_IsDying ; ... Player is dying ... 
04774. ORA Player_OffScreen ; ... Player is off-screen ... 
04775. ORA Player_Behind_En ; ... Player is legitimately hidden behind the scenes ... 
04776. ORA <Temp_Var14 ; ... or special object is not vertically on-screen ... 
04777. BNE PRG007_B843 ; ... jump to Player_Behind_En (RTS) 
04778.  
04779. LDA SpecialObj_ID,X 
04780. CMP #SOBJ_MICROGOOMBA 
04781. BNE PRG007_B827 ; If this is not a microgoomba, jump to PRG007_B827 
04782.  
04783. ; Microgooma sets to 5 
04784. LDA #$05 
04785. STA SpecialObj_Data,X 
04786.  
04787. PRG007_B826: 
04788. RTS ; Return 
04789.  
04790.  
04791. PRG007_B827: 
04792. CMP #$10 
04793. BNE PRG007_B836 ; If this is not the recovered wand, jump to PRG007_B836 
04794.  
04795. ; Wand grabbed! 
04796.  
04797. INC Level_GetWandState ; Level_GetWandState++ 
04798.  
04799. ; Play victory music! 
04800. LDA #MUS1_BOSSVICTORY 
04801. STA Sound_QMusic1 
04802.  
04803. JMP SpecialObj_Remove ; Remove the wand and don't come back! 
04804.  
04805. PRG007_B836: 
04806. LDA Player_StarInv 
04807. BNE PRG007_B844 ; If Player is Star Man invincible, jump to PRG007_B844 
04808.  
04809. JMP Player_GetHurt ; Hurt Player and don't come back! 
04810.  
04811. SpecialObj_Remove: 
04812.  
04813. ; Remove special object 
04814. LDA #$00 
04815. STA SpecialObj_ID,X 
04816.  
04817. PRG007_B843: 
04818. RTS ; Return 
04819.  
04820. PRG007_B844: 
04821.  
04822. ; Player is invincible; destroy the special object! 
04823.  
04824. ; Play "kick" sound 
04825. LDA Sound_QPlayer 
04826. ORA #SND_PLAYERKICK 
04827. STA Sound_QPlayer 
04828.  
04829. PRG007_B84C: 
04830. ; Change to a "poof" 
04831. LDA #SOBJ_POOF 
04832. STA SpecialObj_ID,X 
04833.  
04834. ; SpecialObj_Data = $1F 
04835. LDA #$1f 
04836. STA SpecialObj_Data,X 
04837.  
04838. RTS ; Return 
04839.  
04840. Hammer_Attributes: .byte $00, SPR_HFLIP, SPR_HFLIP, SPR_HFLIP | SPR_VFLIP, SPR_HFLIP | SPR_VFLIP, SPR_VFLIP, SPR_VFLIP, $00 
04841.  
04842. Hammer_Patterns: 
04843. .byte $A1, $A3, $B9, $B9, $A3, $A1 
04844. .byte $AF, $AF, $A1, $A3, $B9, $B9 
04845.  
04846. Hammer_Draw: 
04847. LDA SpecialObj_Var1,X 
04848. AND #%00011100 
04849. LSR A 
04850. LSR A 
04851. TAX ; X = 0 to 7 (hammer's current frame) 
04852.  
04853. ; Set upper and lower sprite attributes 
04854. LDA <Temp_Var1 
04855. EOR Hammer_Attributes,X 
04856. ORA #SPR_PAL1 
04857. STA Sprite_RAM+$02,Y 
04858. STA Sprite_RAM+$06,Y 
04859.  
04860. LDA <Temp_Var1 
04861. BEQ PRG007_B888 ; If no flip, jump to PRG007_B888 
04862.  
04863. ; Otherwise, X += 4 (4 "frames" ahead on the hammer for the flip) 
04864. INX 
04865. INX 
04866. INX 
04867. INX 
04868.  
04869. PRG007_B888: 
04870.  
04871. ; Cap X 0 to 7 
04872. TXA 
04873. AND #$07 
04874. TAX 
04875.  
04876. ; Set upper sprite pattern 
04877. LDA Hammer_Patterns,X 
04878. STA Sprite_RAM+$01,Y 
04879.  
04880. ; Set bottom sprite pattern 
04881. LDA Hammer_Patterns+4,X 
04882. STA Sprite_RAM+$05,Y 
04883.  
04884. RTS ; Return 
04885.  
04886. Boomerang_XVelDelta: .byte $01, -$01 
04887. Boomerang_XVelLimit: .byte $20, $E0 
04888. Boomerang_YVelAccel: .byte $01, -$01 
04889. Boomerang_YVelLimit: .byte $12, -$12 
04890.  
04891. Boomerang_Attributes: .byte SPR_HFLIP | SPR_VFLIP, SPR_HFLIP | SPR_VFLIP, $00, $00 
04892.  
04893. Boomerang_Patterns: 
04894. .byte $8B, $8F, $89, $8D, $8B, $8F 
04895.  
04896.  
04897. SObj_Boomerang: 
04898.  
04899. ; Load Boomerang's graphics 
04900. LDA #$4e 
04901. STA PatTable_BankSel+4 
04902.  
04903. LDA <Player_HaltGame 
04904. BEQ PRG007_B8B7 ; If gameplay is not halted, jump to PRG007_B8B7 
04905.  
04906. JMP PRG007_B773 ; Jump to PRG007_B773 (Draw Boomerang) 
04907.  
04908. PRG007_B8B7: 
04909. LDA SpecialObj_Data,X 
04910. AND #%00001111 
04911. BEQ PRG007_B8C1 ; If lower 4 bits of SpecialObj_Data = 0, jump to PRG007_B8C1 
04912.  
04913. JMP PRG007_B6F2 ; Jump to PRG007_B6F2 
04914.  
04915. PRG007_B8C1: 
04916. INC SpecialObj_Var1,X ; Var1 ++ 
04917.  
04918. LDA SndCur_Level2 
04919. AND #SND_BOOMERANG 
04920. BNE PRG007_B8D3 ; If boomerang sound is currently playing, jump to PRG007_B8D3 
04921.  
04922. ; Player boomerang sound 
04923. LDA Sound_QLevel2 
04924. ORA #SND_BOOMERANG 
04925. STA Sound_QLevel2 
04926.  
04927. PRG007_B8D3: 
04928. LDA SpecialObj_Var2,X 
04929. BMI PRG007_B904 
04930.  
04931. LDA SpecialObj_Timer,X 
04932. BNE PRG007_B904 ; If timer not expired, jump to PRG007_B904 
04933.  
04934. LDA SpecialObj_Var2,X 
04935. AND #$01 
04936. TAY ; Y = 0 or 1 (Boomerang Direction) 
04937.  
04938. ; Accelerate Boomerang 
04939. LDA SpecialObj_XVel,X 
04940. ADD Boomerang_XVelDelta,Y 
04941. STA SpecialObj_XVel,X 
04942.  
04943. CMP Boomerang_XVelLimit,Y 
04944. BNE PRG007_B904 ; If boomerang has not hit limit, jump to PRG007_B904 
04945.  
04946. ; Set boomerang timer 
04947. LDA #$30 
04948. STA SpecialObj_Timer,X 
04949.  
04950. INC SpecialObj_Var2,X ; SpecialObj_Var2++ (change direction) 
04951.  
04952. LDA SpecialObj_Var3,X 
04953. BEQ PRG007_B904 ; If SpecialObj_Var3 = 0, jump to PRG007_B904 
04954.  
04955. ; Boomerang is on the return 
04956. LDA #$ff 
04957. STA SpecialObj_Var2,X 
04958.  
04959. PRG007_B904: 
04960. LDA <Counter_1 
04961. LSR A 
04962. BCS PRG007_B92A ; Every other tick, jump to PRG007_B92A 
04963.  
04964. LDA SpecialObj_Var3,X 
04965. CMP #$01 
04966. BLT PRG007_B915 
04967.  
04968. LDY SpecialObj_YVel,X 
04969. BEQ PRG007_B92A ; If Boomerang Y Vel = 0, jump to PRG007_B92A 
04970.  
04971. PRG007_B915: 
04972. AND #$01 
04973. TAY ; Y = 0 or 1 
04974.  
04975. ; Accelerate Boomerang Y Velocity 
04976. LDA SpecialObj_YVel,X 
04977. ADD Boomerang_YVelAccel,Y 
04978. STA SpecialObj_YVel,X 
04979.  
04980. CMP Boomerang_YVelLimit,Y 
04981. BNE PRG007_B92A ; If Boomerang Y Velocity is at limit, jump to PRG007_B92A 
04982.  
04983. INC SpecialObj_Var3,X ; SpecialObj_Var3++ 
04984.  
04985. PRG007_B92A: 
04986. JSR SObj_AddXVelFrac ; Apply X Velocity 
04987. JSR SObj_AddYVelFrac ; Apply Y Velocity 
04988. JSR PRG007_B773 ; Draw Boomerang 
04989.  
04990. LDA SpecialObj_Var2,X 
04991. BPL PRG007_B979 ; If SpecialObj_Var2 <> $FF, jump to PRG007_B979 
04992.  
04993. TXA ; Keep things interesting 
04994. ADD <Counter_1  
04995. LSR A  
04996. BCS PRG007_B979 ; Every other tick, jump to PRG007_B979 (RTS) 
04997.  
04998. LDA SpecialObj_Data,X 
04999. LSR A 
05000. LSR A 
05001. LSR A 
05002. LSR A 
05003. TAY ; Y = object slot index of boomerang thrower 
05004.  
05005. LDA Objects_State,Y 
05006. CMP #OBJSTATE_NORMAL 
05007. BNE PRG007_B979 ; If thrower's state <> Normal, jump to PRG007_B979 (RTS) 
05008.  
05009. LDA Level_ObjectID,Y 
05010. CMP #OBJ_BOOMERANGBRO 
05011. BNE PRG007_B979 ; If thrower's slot is not a boomerang brother (Anymore), jump to PRG007_B979 (RTS) 
05012.  
05013. ; This is for the Boomerang brother to "catch" 
05014.  
05015. LDA SpecialObj_YLo,X 
05016. ADD #8 
05017. SUB Objects_Y,Y 
05018. SUB #8 
05019. CMP #16 
05020. BGE PRG007_B979 ; If boomerang Y diff >= 16, jump to PRG007_B979 (RTS) 
05021.  
05022. LDA SpecialObj_XLo,X 
05023. ADD #8 
05024. SUB Objects_X,Y 
05025. SBC #0 
05026. CMP #16 
05027. BGE PRG007_B979 ; If boomerang X diff >= 16, jump to PRGO007_B979 (RTS) 
05028.  
05029. JMP SpecialObj_Remove ; Boomerang Bro caught boomerang 
05030.  
05031. PRG007_B979: 
05032. RTS ; Return 
05033.  
05034. SObj_UNKNOWN_XAccel: .byte $01, -$01 
05035. SObj_UNKNOWN_XLimit: .byte $20, $E0 
05036. SObj_UNKNOWN_YAccel: .byte $04, -$01 
05037. SObj_UNKNOWN_YLimit: .byte $0F, -$12 
05038.  
05039. SObj_UNKNOWN: 
05040. LDA <Player_HaltGame 
05041. BEQ PRG007_B989 ; If gameplay not halted, jump to PRG007_B989 
05042.  
05043. JMP PRG007_B773 ; Otherwise, jump to PRG007_B773 (Hammer/Boomerang draw routines??) 
05044.  
05045. PRG007_B989: 
05046. LDA SpecialObj_Data,X 
05047. AND #$0f 
05048. BEQ PRG007_B993 ; 1:16 ticks jump to PRG007_B993 
05049.  
05050. JMP PRG007_B6F2 ; Jump to PRG007_B6F2 
05051.  
05052. PRG007_B993: 
05053. DEC SpecialObj_Var1,X ; Var1-- 
05054.  
05055. LDY SpecialObj_Timer,X 
05056. BEQ PRG007_B9A1 ; If timer not expired, jump to PRG007_B9A1 
05057.  
05058. DEY ; Y-- 
05059.  
05060. BNE PRG007_B9C4 ; If timer still has at least 1 tick left, jump to PRG007_B9C4 
05061.  
05062. INC SpecialObj_Var3,X ; SpecialObj_Var3++ 
05063.  
05064. PRG007_B9A1: 
05065. LDA <Counter_1 
05066. AND #$00 ; ?? 
05067. BNE PRG007_B9C4 ; Jump technically NEVER to PRG007_B9C4 
05068.  
05069. LDA SpecialObj_Var2,X 
05070. AND #$01 
05071. TAY ; Y = 0 or 1 
05072.  
05073. ; Accelerate X 
05074. LDA SpecialObj_XVel,X 
05075. ADD SObj_UNKNOWN_XAccel,Y 
05076. STA SpecialObj_XVel,X 
05077.  
05078. CMP SObj_UNKNOWN_XLimit,Y 
05079. BNE PRG007_B9C4 ; If it hasn't hit its X velocity limit, jump to PRG007_B9C4 
05080.  
05081. ; Timer = $50 
05082. LDA #$50 
05083. STA SpecialObj_Timer,X 
05084.  
05085. INC SpecialObj_Var2,X ; Var2++ 
05086.  
05087. PRG007_B9C4: 
05088. LDA <Counter_1 
05089. AND #$03 
05090. BNE PRG007_B9ED ; 1:4 ticks proceed, otherwise jump to PRG007_B9ED 
05091.  
05092. LDA SpecialObj_Var3,X 
05093. BEQ PRG007_B9ED ; If SpecialObj_Var3 = 0, jump to PRG007_B9ED 
05094.  
05095. CMP #$03 
05096. BLT PRG007_B9D8 ; If SpecialObj_Var3 < 3, jump to PRG007_B9D8 
05097.  
05098. LDY SpecialObj_YVel,X 
05099. BEQ PRG007_B9ED ; If it is not moving vertically, jump to PRG007_B9ED 
05100.  
05101. PRG007_B9D8: 
05102. AND #$01 
05103. TAY ; Y = 0 or 1 
05104.  
05105. ; Accelerate Y 
05106. LDA SpecialObj_YVel,X 
05107. ADD SObj_UNKNOWN_YAccel,Y 
05108. STA SpecialObj_YVel,X 
05109.  
05110. CMP SObj_UNKNOWN_YLimit,Y 
05111. BNE PRG007_B9ED ; If it hasn't hit its Y velocity limit, jump to PRG007_B9ED 
05112.  
05113. INC SpecialObj_Var3,X ; SpecialObj_Var3++ 
05114.  
05115. PRG007_B9ED: 
05116. JMP PRG007_B92A ; Jump to PRG007_B92A (uses more Boomerang behavior) 
05117.  
05118. Fireball_Patterns: .byte $65, $67, $65, $67 
05119. Fireball_Attributes: .byte SPR_PAL1, SPR_PAL1, SPR_PAL1 | SPR_HFLIP | SPR_VFLIP, SPR_PAL1 | SPR_HFLIP | SPR_VFLIP 
05120.  
05121. SObj_Fireball: 
05122. LDA <Player_HaltGame 
05123. BNE PRG007_BA33 ; If gameplay halted, jump to PRG007_BA33 
05124.  
05125. ; Gameplay not halted... 
05126.  
05127. INC SpecialObj_Var1,X ; SpecialObj_Var1++ 
05128.  
05129. LDA SpecialObj_ID,X 
05130.  
05131. CMP #SOBJ_PIRANHAFIREBALL 
05132. BEQ PRG007_BA2D ; If this is a piranha's fireball, jump to PRG007_BA2D 
05133.  
05134. CMP #SOBJ_FIRECHOMPFIRE 
05135. BEQ PRG007_BA2D ; If this is a Fire Chomp's fireball, jump to PRG007_BA2D 
05136.  
05137. ; Not a piranha's or Fire Chomp's fireball 
05138.  
05139. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
05140.  
05141. LDA SpecialObj_YVel,X 
05142. CMP #$30 
05143. BPL PRG007_BA1A ; If fireball Y vel < $30, jump to PRG007_BA1A 
05144.  
05145. ; Heavier gravity 
05146. INC SpecialObj_YVel,X 
05147. INC SpecialObj_YVel,X 
05148.  
05149. PRG007_BA1A: 
05150. LDA SpecialObj_ID,X 
05151. CMP #SOBJ_FIREBROFIREBALL 
05152. BNE PRG007_BA24 ; If this is not Fire Bro's fireball, jump to PRG007_BA24 
05153.  
05154. JSR SObj_CheckHitSolid ; Bounce fireball off surfaces 
05155.  
05156. PRG007_BA24: 
05157. JMP PRG007_BA33 ; Jump to PRG007_BA33 
05158.  
05159. JSR SObj_ApplyXYVelsWithGravity ; Apply X and Y velocities with gravity 
05160. JMP PRG007_BA33 ; Jump to PRG007_BA33 
05161.  
05162. PRG007_BA2D: 
05163. JSR SObj_AddXVelFrac ; Apply X velocity 
05164. JSR SObj_AddYVelFrac ; Apply Y velocity 
05165.  
05166. PRG007_BA33: 
05167. JSR SObj_GetSprRAMOffChkVScreen 
05168. BNE PRG007_BA92 ; If fireball isn't vertically on-screen, jump to PRG007_BA92 
05169.  
05170. JSR SObj_SetSpriteXYRelative ; Special Object X/Y put to sprite, scroll-relative 
05171.  
05172. LDA SpecialObj_ID,X 
05173. CMP #SOBJ_FIRECHOMPFIRE 
05174. BNE PRG007_BA55 ; If this is not a Fire Chomp's fireball, jump to PRG007_BA55 
05175.  
05176. ; Fire Chomp's fireball only... 
05177.  
05178. LDA Level_NoStopCnt 
05179. LSR A 
05180. LSR A 
05181.  
05182. LDA #$89 ; A = $89 (first fireball pattern) 
05183.  
05184. BCC PRG007_BA4D ; 4 ticks on, 4 ticks off; jump to PRG007_BA4D 
05185.  
05186. LDA #$8b ; A = $8B (second fireball pattern) 
05187.  
05188. PRG007_BA4D: 
05189. STA Sprite_RAM+$01,Y ; Set fireball pattern 
05190.  
05191. LDA #$01 ; A = 1 
05192. JMP PRG007_BA6E ; Jump to PRG007_BA6E 
05193.  
05194. PRG007_BA55: 
05195. LDA SpecialObj_XVel,X 
05196. LSR A 
05197. AND #SPR_HFLIP ; Flip based on X velocity 
05198. PHA ; Save flip 
05199.  
05200. LDA SpecialObj_Var1,X 
05201. LSR A 
05202. LSR A 
05203. AND #$03 
05204. TAX ; X = 0 to 3 
05205.  
05206. ; Set fireball pattern 
05207. LDA Fireball_Patterns,X 
05208. STA Sprite_RAM+$01,Y 
05209.  
05210. PLA ; Restore flip 
05211. EOR Fireball_Attributes,X 
05212.  
05213. PRG007_BA6E: 
05214.  
05215. ; Set fireball attributes 
05216. STA Sprite_RAM+$02,Y 
05217.  
05218. LDX <SlotIndexBackup ; X = special object slot index 
05219.  
05220. LDA <Player_Suit 
05221. CMP #$06 
05222. BNE PRG007_BA8F ; If Player is not wearing the Hammer Suit, jump to PRG007_BA8F 
05223.  
05224. LDA Player_IsDucking 
05225. BEQ PRG007_BA8F ; If Player is NOT ducking (immunity to fireballs), jump to PRG007_BA8F 
05226.  
05227. LDA Player_StarInv 
05228. PHA ; Save Player's Star Man invincibility status 
05229.  
05230. ; Collide with it like Player were invincible! (Visually the shell protects him) 
05231. LDA #$10 
05232. STA Player_StarInv 
05233. JSR SObj_PlayerCollide 
05234.  
05235. ; Restore actual Star Man invincibility 
05236. PLA 
05237. STA Player_StarInv 
05238.  
05239. RTS ; Return 
05240.  
05241. PRG007_BA8F: 
05242. JMP SObj_PlayerCollide ; Do Player-to-Fireball collision and don't come back! 
05243.  
05244. PRG007_BA92: 
05245. RTS ; Return 
05246.  
05247. Poof_Patterns: .byte $47, $45, $43, $41 
05248.  
05249. SObj_Poof: 
05250. LDA SpecialObj_Data,X 
05251. BNE PRG007_BA9F ; If data > 0, jump to PRG007_BA9F 
05252.  
05253. JMP SpecialObj_Remove ; Otherwise, remove the puff 
05254.  
05255. PRG007_BA9F: 
05256. LDA <Player_HaltGame 
05257. BNE PRG007_BAA6 ; If gameplay halted, jump to PRG007_BAA6 
05258.  
05259. DEC SpecialObj_Data,X ; Data-- 
05260.  
05261. PRG007_BAA6: 
05262. JSR SObj_GetSprRAMOffChkVScreen 
05263. BNE PRG007_BAD6 ; If puff is vertically off-screen, jump to PRG007_BAD6 
05264.  
05265. JSR SObj_Draw16x16 ; Prep puff sprite 
05266.  
05267. ; Set puff attributes on left sprite 
05268. LDA Level_NoStopCnt 
05269. LSR A 
05270. LSR A 
05271. LSR A 
05272. ROR A 
05273. AND #SPR_VFLIP 
05274. STA <Temp_Var1 
05275. LDA #SPR_PAL1 
05276. ORA <Temp_Var1 
05277. STA Sprite_RAM+$02,Y 
05278.  
05279. ; Set puff attributes on right sprite 
05280. EOR #(SPR_HFLIP | SPR_VFLIP) 
05281. STA Sprite_RAM+$06,Y 
05282.  
05283. LDA SpecialObj_Data,X 
05284. LSR A 
05285. LSR A 
05286. LSR A 
05287. TAX 
05288.  
05289. ; Set poof patterns 
05290. LDA Poof_Patterns,X 
05291. STA Sprite_RAM+$01,Y 
05292. STA Sprite_RAM+$05,Y 
05293.  
05294. LDX <SlotIndexBackup ; X = special object slot index 
05295.  
05296. PRG007_BAD6: 
05297. RTS ; Return 
05298.  
05299.  
05300. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05301. ; SObj_GetSprRAMOffChkVScreen 
05302. ; 
05303. ; Gets an appropriate sprite RAM offset and also returns zero if 
05304. ; the object is on the same vertical screen as the Player 
05305. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05306. SObj_SprRAMBase: 
05307. .byte $08, $10, $00, $08, $10, $04, $0C, $14, $0C 
05308.  
05309. SObj_GetSprRAMOffChkVScreen: 
05310. LDY #$07 ; Y = 7 
05311.  
05312. CPX #$09 
05313. BEQ PRG007_BAED ; If special object slot = 9, jump to PRG007_BAED 
05314.  
05315. CPX #$03 
05316. BLT PRG007_BAED ; If special object slot < 3, jump to PRG007_BAED 
05317.  
05318. LDY #$08 ; Y = 8 
05319.  
05320. PRG007_BAED: 
05321. LDA SObj_SprRAMBase-1,X 
05322. ADD Object_SprRAM-1,Y 
05323. TAY ; Y = Sprite RAM offset 
05324.  
05325. CPX #$00 
05326. BNE PRG007_BB1A ; If special object slot 0, jump to PRG007_BB1A 
05327.  
05328. JSR Object_GetRandNearUnusedSpr 
05329. BNE PRG007_BB1A ; If sprite available, jump to PRG007_BB1A 
05330.  
05331. LDA SpecialObj_ID,X 
05332.  
05333. ; If this special object is empty, or is a Nipper fireball/Piranha Fireball/Microgoomba, jump to PRG007_BB1A 
05334.  
05335. CMP #SOBJ_NIPPERFIREBALL 
05336. BEQ PRG007_BB1A 
05337.  
05338. CMP #SOBJ_PIRANHAFIREBALL 
05339. BEQ PRG007_BB1A 
05340.  
05341. CMP #SOBJ_MICROGOOMBA 
05342. BEQ PRG007_BB1A 
05343.  
05344. CMP #$00 
05345. BEQ PRG007_BB1A 
05346.  
05347. LDA RandomN,X 
05348. AND #$03 ; 0 to 3 
05349. ASL A  
05350. ASL A  
05351. ASL A ; Multiply by 8 
05352. TAY ; Y = 0, 8, 16, 24 
05353.  
05354. PRG007_BB1A: 
05355. LDA <Temp_Var14 ; Return the relative Y Hi value 
05356.  
05357. RTS ; Return 
05358.  
05359. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05360. ; SObj_AddXVelFrac 
05361. ; 
05362. ; Adds the 4.4FP X velocity to X of special object 
05363. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05364. SObj_AddXVelFrac: 
05365. LDA SpecialObj_XVel,X ; Get X Velocity  
05366. ASL A 
05367. ASL A 
05368. ASL A 
05369. ASL A ; Fractional part shifted up 
05370. ADD SpecialObj_XVelFrac,X 
05371. STA SpecialObj_XVelFrac,X ; Add to special object's X vel fractional accumulator 
05372.  
05373. PHP ; Save CPU status 
05374.  
05375. ; Basically amounts to an arithmetic shift right 4 places 
05376. LDA SpecialObj_XVel,X ; Get X Velocity 
05377. LSR A 
05378. LSR A 
05379. LSR A 
05380. LSR A ; Whole part shifted down (integer) 
05381. CMP #%00001000 ; Check the sign bit 
05382. BLT PRG007_BB39 ; If the value was not negatively signed, jump to PRG007_BB39 
05383. ORA #%11110000 ; Otherwise, apply a sign extension 
05384. PRG007_BB39: 
05385.  
05386. PLP ; Restore CPU status 
05387.  
05388. ADC SpecialObj_XLo,X 
05389. STA SpecialObj_XLo,X ; Add with carry 
05390.  
05391. RTS ; Return 
05392.  
05393.  
05394. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05395. ; SObj_AddYVelFrac 
05396. ; 
05397. ; Adds the 4.4FP Y velocity to Y of special object 
05398. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05399. SObj_AddYVelFrac: 
05400. LDA SpecialObj_YVel,X ; Get Y Velocity 
05401. ASL A 
05402. ASL A 
05403. ASL A 
05404. ASL A ; Fractional part shifted up 
05405. ADD SpecialObj_YVelFrac,X 
05406. STA SpecialObj_YVelFrac,X ; Add to special object's X vel fractional accumulator 
05407.  
05408. PHP ; Save CPU status 
05409.  
05410. ; Basically amounts to an arithmetic shift right 4 places 
05411. LDA SpecialObj_YVel,X ; Get Y Velocity 
05412. LSR A 
05413. LSR A 
05414. LSR A 
05415. LSR A ; Whole part shifted down (integer) 
05416. CMP #%00001000 ; Check the sign bit 
05417. LDY #$00 ; Y = $00 (16-bit sign extension) 
05418. BLT PRG007_BB60 ; If the value was not negatively signed, jump to PRG007_BB60 
05419. ORA #%11110000 ; Otherwise, apply a sign extension 
05420.  
05421. DEY ; Y = $FF (16-bit sign extension) 
05422.  
05423. PRG007_BB60: 
05424. PLP ; Restore CPU status 
05425.  
05426. ADC SpecialObj_YLo,X 
05427. STA SpecialObj_YLo,X ; Add with carry 
05428.  
05429. TYA ; Sign extension 
05430.  
05431. ; Apply sign extension 
05432. ADC SpecialObj_YHi,X 
05433. STA SpecialObj_YHi,X 
05434.  
05435. RTS ; Return 
05436.  
05437.  
05438. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05439. ; CannonFire_UpdateAndDraw 
05440. ; 
05441. ; Updates and draws the Cannon Fires 
05442. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
05443. CannonFire_UpdateAndDraw: 
05444. LDA <Player_HaltGame  
05445. ORA EndCard_Flag 
05446. BNE PRG007_BB80 ; If gameplay halted or end level card grabbed, jump to PRG007_BB80 (RTS) 
05447.  
05448. LDX #$07 ; X = 7 
05449. PRG007_BB78: 
05450. STX <SlotIndexBackup ; Update index backup 
05451.  
05452. JSR CannonFire_DrawAndUpdate ; Draw and Update Cannon Fire 
05453.  
05454. DEX ; X-- 
05455. BPL PRG007_BB78 ; While X >= 0, loop! 
05456.  
05457. PRG007_BB80: 
05458. RTS ; Return 
05459.  
05460.  
05461. CannonFire_DrawAndUpdate: 
05462. LDA CannonFire_ID,X 
05463. BEQ PRG007_BB80 ; If this slot is unused/empty, jump to PRG007_BB80 (RTS) 
05464.  
05465. PHA ; Save ID 
05466.  
05467. ; Update CannonFire_Timer 
05468. LDA CannonFire_Timer,X 
05469. BEQ PRG007_BB8F ; If CannonFire_Timer = 0, jump to CannonFire_Timer 
05470. DEC CannonFire_Timer,X ; CannonFire_Timer-- 
05471. PRG007_BB8F: 
05472.  
05473. ; Update CannonFire_Timer2 
05474. LDA CannonFire_Timer2,X 
05475. BEQ PRG007_BB97 
05476. DEC CannonFire_Timer2,X 
05477. PRG007_BB97: 
05478.  
05479. PLA ; Restore ID 
05480. JSR DynJump 
05481.  
05482. ; THESE MUST FOLLOW DynJump FOR THE DYNAMIC JUMP TO WORK!! 
05483. .word PRG007_BB80 ; 00: Unused (would never get here anyway) 
05484. .word CFire_BulletBill ; 01: Bullet Bill cannon 
05485. .word CFire_BulletBill ; 02: Missile Bill (homing Bullet Bill) 
05486. .word CFire_RockyWrench ; 03: Creates Rocky Wrench 
05487. .word CFire_4Way ; 04: 4-way cannon 
05488. .word CFire_GoombaPipe ; 05: Goomba pipe (left output) 
05489. .word CFire_GoombaPipe ; 06: Goomba pipe (right output) 
05490. .word CFire_Cannonball ; 07: Fires cannonballs horizontally left 
05491. .word CFire_Cannonball ; 08: Fires BIG cannonballs horizontally left 
05492. .word CFire_Cannonball ; 09: Fires cannonballs diagonally, upper left 
05493. .word CFire_Cannonball ; 0A: Fires cannonballs diagonally, upper right 
05494. .word CFire_Cannonball ; 0B: Fires cannonballs diagonally, lower left 
05495. .word CFire_Cannonball ; 0C: Fires cannonballs diagonally, lower right 
05496. .word CFire_Cannonball ; 0D: 
05497. .word CFire_Cannonball ; 0E:  
05498. .word CFire_Cannonball ; 0F:  
05499. .word CFire_Cannonball ; 10: 
05500. .word CFire_Cannonball ; 11: Fires cannonballs horizontally right 
05501. .word CFire_Cannonball ; 12: Fires BIG cannonballs horizontally right 
05502. .word CFire_Cannonball ; 13: Launches fused Bob-ombs to the left 
05503. .word CFire_Cannonball ; 14: Launches fused Bob-ombs to the right 
05504. .word CFire_Laser ; 15: Laser fire 
05505.  
05506. CFire_Laser: 
05507. LDA CannonFire_X,X 
05508. CMP <Horz_Scroll 
05509. LDA CannonFire_XHi,X 
05510. SBC <Horz_Scroll_Hi 
05511. BNE PRG007_BBEB ; If the Cannon Fire laser is horizontally off-screen, jump to PRG007_BBEB (RTS) 
05512.  
05513. LDA CannonFire_X,X 
05514. SUB <Player_X 
05515. CMP #$38 
05516. BLT PRG007_BBEB ; If Player is too far left, jump to PRG007_BBEB (RTS) 
05517. CMP #$4c 
05518. BGE PRG007_BBEB ; If Player is too far right, jump to PRG007_BBEB (RTS) 
05519.  
05520. LDY #$07 ; Y = 7 
05521. PRG007_BBE3: 
05522. LDA SpecialObj_ID,Y 
05523. BEQ PRG007_BBEC ; If this special object slot is not in use, jump to PRG007_BBEC 
05524.  
05525. DEY ; Y-- 
05526. BPL PRG007_BBE3 ; While Y >= 0, loop! 
05527.  
05528. PRG007_BBEB: 
05529. RTS ; Return 
05530.  
05531. PRG007_BBEC: 
05532. LDA SndCur_Player 
05533. ORA Sound_QPlayer 
05534. AND #SND_PLAYERPIPE 
05535. BNE PRG007_BBFB ; If the pipe/shrink sound is queued or currently playing, jump to PRG007_BBFB 
05536.  
05537. ; Otherwise play the "bump" sound (which played rapidly makes the laser sound) 
05538. LDA #SND_PLAYERBUMP 
05539. STA Sound_QPlayer 
05540.  
05541. PRG007_BBFB: 
05542.  
05543. ; This is a laser! 
05544. LDA #SOBJ_LASER 
05545. STA SpecialObj_ID,Y 
05546.  
05547. ; Set laser X 
05548. LDA CannonFire_X,X 
05549. SUB #$08 
05550. STA SpecialObj_XLo,Y 
05551.  
05552. ; Set laser Y 
05553. LDA CannonFire_Y,X 
05554. ADD #$08 
05555. STA SpecialObj_YLo,Y 
05556. LDA CannonFire_YHi,X 
05557. STA SpecialObj_YHi,Y 
05558.  
05559. RTS ; Return 
05560.  
05561. CFire_Cannonball: 
05562.  
05563. ; Load cannonball graphics 
05564. LDA #$36 
05565. STA PatTable_BankSel+4 
05566.  
05567. LDA CannonFire_Timer,X 
05568. BNE PRG007_BC5B ; If timer not expired, jump to PRG007_BC5B (RTS) 
05569.  
05570. LDA CannonFire_X,X 
05571. CMP <Horz_Scroll 
05572. LDA CannonFire_XHi,X 
05573. SBC <Horz_Scroll_Hi 
05574. BNE PRG007_BC5B ; If Cannon Fire is off-screen left, jump to PRG007_BC5B (RTS) 
05575.  
05576. LDA CannonFire_X,X 
05577. SUB <Horz_Scroll 
05578. CMP #240 
05579. BGE PRG007_BC5B ; If Cannon Fire is off-screen right, jump to PRG007_BC5B (RTS) 
05580.  
05581. ; Reload timer = $87 
05582. LDA #$87 
05583. STA CannonFire_Timer,X 
05584.  
05585. ; Temp_Var1 = this particular Cannon Fire ID 
05586. LDA CannonFire_ID,X 
05587. STA <Temp_Var1 
05588.  
05589. CMP #CFIRE_HRBIGCANNON 
05590. BEQ PRG007_BC4B ; If this is the right-shooting BIG Cannon, jump to PRG007_BC4B 
05591.  
05592. CMP #CFIRE_HLBIGCANNON 
05593. BNE PRG007_BC4E ; If this is NOT the left-shooting BIG Cannon, jump to PRG007_BC4E 
05594.  
05595. PRG007_BC4B: 
05596. JMP PRG007_BC5C ; For all BIG Cannons, jump to PRG007_BC5C 
05597.  
05598. PRG007_BC4E: 
05599. CMP #CFIRE_LBOBOMBS 
05600. BLT PRG007_BC55 ; If this is not one of the Bob-omb cannons, jump to PRG007_BC55 
05601.  
05602. JMP PRG007_BCB4 ; For all Bob-omb cannons, jump to PRG007_BCB4 
05603.  
05604. PRG007_BC55:  
05605. ADD #(Cannons_CPXOff - CannonPoof_XOffs - CFIRE_HLCANNON) ; Offset to proper array index for this Cannon Fire 
05606. JMP PRG007_BE59 ; Jump to PRG007_BE59 (fire cannonball!) 
05607.  
05608. PRG007_BC5B: 
05609. RTS ; Return 
05610.  
05611.  
05612. PRG007_BC5C: 
05613.  
05614. ; Left/right BIG Cannons 
05615.  
05616. JSR PrepareNewObjectOrAbort ; Get me an object slot or don't come back! 
05617.  
05618. ; This is a BIG Cannon Ball! 
05619. LDA #OBJ_BIGCANNONBALL 
05620. STA Level_ObjectID,X 
05621.  
05622. ; Big Cannon Ball is BIG 
05623. INC Objects_IsGiant,X 
05624.  
05625. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
05626.  
05627. ; Set BIG Cannon Ball Y 
05628. LDA CannonFire_Y,Y 
05629. STA <Objects_Y,X 
05630. LDA CannonFire_YHi,Y 
05631. STA <Objects_YHi,X 
05632.  
05633. LDA <Temp_Var1 
05634. CMP #CFIRE_HRCANNON 
05635.  
05636. LDA #$30 ; A = $30 
05637. LDY #$12 ; Y = $12 
05638.  
05639. BGE PRG007_BC81 ; Basically if this is the right-shooting BIG Cannon, jump to PRG007_BC81 
05640.  
05641. LDY #$09 ; Y = $09 
05642. LDA #-$30 ; A = -$30 
05643.  
05644. PRG007_BC81: 
05645. STY <Temp_Var1 ; Temp_Var1 = $12 (if right-shooting) or $09 (if left-shooting) 
05646.  
05647. STA <Objects_XVel,X ; X velocity = -$30 or $30, depending on direction 
05648.  
05649. EOR #$80 ; Invert the sign bit 
05650.  
05651. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
05652.  
05653. ASL A ; Inverted sign bit -> carry 
05654.  
05655. ; Set BIG Cannon Ball X 
05656. LDA CannonFire_X,Y 
05657. BCS PRG007_BC92 ; If right-shooting, jump to PRG007_BC92 
05658. SUB #16 ; -16 for left-shooting 
05659. PRG007_BC92: 
05660. STA <Objects_X,X 
05661. LDA CannonFire_XHi,Y 
05662. SBC #$00 
05663. STA <Objects_XHi,X 
05664.  
05665. JSR PRG007_BD09 ; Set attribute and make noise and smoke! 
05666. JSR CannonFire_NoiseAndSmoke ; make more smoke!! 
05667.  
05668. ; +4 to this smoke though 
05669. LDA CannonFire_Y,X 
05670. SUB Level_VertScroll 
05671. ADD #$04 
05672. STA BrickBust_YUpr 
05673.  
05674. ; +8 to the other smoke 
05675. ADC #$08 
05676. STA BrickBust_YUpr+1 
05677.  
05678. RTS ; Return 
05679.  
05680. PRG007_BCB4: 
05681.  
05682. ; Bob-omb cannons! 
05683.  
05684. JSR PrepareNewObjectOrAbort 
05685.  
05686. ; It's a Bob-omb!! 
05687. LDA #OBJ_BOBOMBEXPLODE 
05688. STA Level_ObjectID,X 
05689.  
05690. ; Bobomb's Timer3 = $80 
05691. LDA #$80 
05692. STA Objects_Timer3,X 
05693.  
05694. INC Objects_Var7,X ; Bob-omb's Var7++ 
05695. INC Objects_Var1,X ; Bob-omb's Var1++ 
05696.  
05697. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
05698.  
05699. ; Set Bob-omb's Y 
05700. LDA CannonFire_Y,Y 
05701. SUB #$08 
05702. STA <Objects_Y,X 
05703. LDA CannonFire_YHi,Y 
05704. SBC #$00 
05705. STA <Objects_YHi,X 
05706.  
05707. ; Set Bob-omb's Y velocity 
05708. LDA #-$30 
05709. STA <Objects_YVel,X 
05710.  
05711. LDA <Temp_Var1 
05712. CMP #CFIRE_RBOBOMBS 
05713.  
05714. LDA #$10 ; A = $10 
05715. LDY #$0b ; Y = $0B 
05716. BCS PRG007_BCE9 ; If this is a right-shot Bob-omb, jump to PRG007_BCE9 
05717.  
05718. DEY ; Y = $0A 
05719. LDA #-$10 ; A = -$10 
05720.  
05721. PRG007_BCE9: 
05722. STY <Temp_Var1 ; Temp_Var1 = $0A or $0B 
05723. STA <Objects_XVel,X ; Set Bob-omb's X velocity (-$10 or $10) 
05724.  
05725. ASL A ; Shift sign bit into carry 
05726.  
05727. ; Temp_Var2 = $00 (16-bit sign extension) 
05728. LDA #$00 
05729. STA <Temp_Var2 
05730.  
05731. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
05732.  
05733. ; Set Bob-omb's X 
05734. LDA #$08 ; A = $08 
05735. BCC PRG007_BCFC ; If this is a right-shot Bob-omb, jump to PRG007_BCFC 
05736. LDA #-$08 ; A = -$08 
05737. DEC <Temp_Var2 ; Temp_Var2 = $FF (16-bit sign extension) 
05738. PRG007_BCFC: 
05739. ADD CannonFire_X,Y 
05740. STA <Objects_X,X 
05741. LDA CannonFire_XHi,Y 
05742. ADC <Temp_Var2  
05743. STA <Objects_XHi,X 
05744.  
05745.  
05746. PRG007_BD09: 
05747. ; Set Cannon Ball / Bob-omb attributes 
05748. LDA #SPR_PAL3 
05749. STA Objects_SprAttr,X 
05750.  
05751. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
05752. JMP CannonFire_NoiseAndSmoke ; Play cannon fire noise and make smoke 
05753.  
05754.  
05755. Goomba_InitFlipBits: .byte SPR_HFLIP, $00 
05756.  
05757. CFire_GoombaPipe: 
05758. LDA CannonFire_Timer,X 
05759. BNE PRG007_BD7A ; If timer not expired, jump to PRG007_BD7A (RTS) 
05760.  
05761. TXA 
05762. TAY ; Cannon Fire index -> 'Y' (this isn't really used) 
05763.  
05764. ; Set timer to $70 
05765. LDA #$70 
05766. STA CannonFire_Timer,Y ; (only used here, then it goes back to 'X' anyway) 
05767.  
05768. INC CannonFire_Var,X ; CannonFire_Var++ 
05769.  
05770. LDA CannonFire_Var,X 
05771. AND #$03 
05772. BEQ PRG007_BD7A ; 1:4 ticks proceed, otherwise jump to PRG007_BD7A (RTS) 
05773.  
05774. JSR PrepareNewObjectOrAbort ; Prepare me a Goomba! 
05775.  
05776. ; Set Goomba X 
05777. LDA CannonFire_X,Y 
05778. STA <Objects_X,X 
05779. LDA CannonFire_XHi,Y 
05780. STA <Objects_XHi,X 
05781.  
05782. JSR Level_ObjCalcXDiffs 
05783. STY <Temp_Var2 ; Store directional flag -> Temp_Var2 
05784.  
05785. LDY <SlotIndexBackup ; Y = Cannon Fire index 
05786.  
05787. LDA CannonFire_ID,Y 
05788.  
05789. LDY #$00 ; Y = 0 (right output Goomba pipe) 
05790.  
05791. CMP #CFIRE_GOOMBAPIPE_L 
05792. BNE PRG007_BD49 ; If this is not a left output Goomba pipe, jump to CFIRE_GOOMBAPIPE 
05793.  
05794. INY ; Y = 1 (left output Goomba pipe) 
05795.  
05796. PRG007_BD49: 
05797. CPY <Temp_Var2 
05798. BNE PRG007_BD7B ; If Player is on the wrong side of the Goomba pipe, jump to PRG007_BD7B 
05799.  
05800. ; Set Goomba's initial flip bits 
05801. LDA Goomba_InitFlipBits,Y 
05802. STA Objects_FlipBits,X 
05803.  
05804. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
05805.  
05806. ; Set Goomba's Y 
05807. LDA CannonFire_Y,Y 
05808. SUB #$03 
05809. STA <Objects_Y,X 
05810. LDA CannonFire_YHi,Y 
05811. SBC #$00 
05812. STA <Objects_YHi,X 
05813.  
05814. ; It's a Goomba 
05815. LDA #OBJ_GOOMBA 
05816. STA Level_ObjectID,X 
05817.  
05818. ; Set Goomba's color 
05819. LDA #SPR_PAL3 
05820. STA Objects_SprAttr,X 
05821.  
05822. ; Set Goomba's Var1 = $28 
05823. LDA #$28 
05824. STA Objects_Var1,X 
05825.  
05826. LDA #$ff 
05827. STA Objects_SprHVis,X 
05828.  
05829. PRG007_BD78: 
05830. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
05831.  
05832. PRG007_BD7A: 
05833. RTS ; Return 
05834.  
05835. PRG007_BD7B: 
05836.  
05837. ; Player's on the wrong side of the goomba pipe; kill goomba! :( 
05838. LDA #OBJSTATE_DEADEMPTY 
05839. STA Objects_State,X 
05840.  
05841. BEQ PRG007_BD78 ; Jump (technically always) to PRG007_BD78 
05842.  
05843. PRG007_BD82: 
05844. .byte $00, $08, $10, $18, $20, $28, $30, $38 
05845.  
05846. FourWay_CannonballXVel: .byte $00, $0B, $10, $0B, $00, -$0B, -$10, -$0B 
05847.  
05848. .byte $F0, $F0, $F5, $0B, $F5, $0B, $F5, $0B, $F5, $0B, $10, $10 
05849.  
05850. FourWay_CannonballYVel: .byte -$10, -$0B, $00, $0B, $10, $0B, $00, -$0B 
05851.  
05852. .byte $00, $00, $F5, $F5, $0B, $0B, $F5, $F5, $0B, $0B, $00, $00 
05853.  
05854. CannonPoof_XOffs: 
05855.  
05856. FourWay_CPXOff: .byte $08, $18, $1C, $18, $08, $F8, $F4, $F8 
05857.  
05858. Cannons_CPXOff: 
05859. .byte -$0C ; CFIRE_ULCANNON 
05860. .byte -$0C ; CFIRE_URCANNON 
05861. .byte -$08 ; CFIRE_LLCANNON 
05862. .byte $08 ; CFIRE_LRCANNON 
05863. .byte -$08 ; CFIRE_HLCANNON2 
05864. .byte $08 ; CFIRE_ULCANNON2 
05865. .byte $00 ; CFIRE_URCANNON2 
05866. .byte $00 ; CFIRE_LLCANNON2 
05867. .byte $00 ; CFIRE_HRCANNON 
05868. .byte $00 ; Not used? 
05869. .byte $0C ; CFIRE_LBOBOMBS 
05870. .byte $0C ; CFIRE_RBOBOMBS 
05871.  
05872.  
05873. Bill_CPXOff: .byte $0C, -$0C ; Bullet/Missile Bill 
05874.  
05875.  
05876. CannonPoof_YOffs: 
05877.  
05878. FourWay_CPYOff: .byte $F3, $F7, $07, $17, $1B, $17, $07, $F7 
05879.  
05880. Cannons_CPYOff: 
05881. .byte $00 ; CFIRE_ULCANNON 
05882. .byte $08 ; CFIRE_URCANNON 
05883. .byte -$08 ; CFIRE_LLCANNON 
05884. .byte -$08 ; CFIRE_LRCANNON 
05885. .byte $08 ; CFIRE_HLCANNON2 
05886. .byte $08 ; CFIRE_ULCANNON2 
05887. .byte $00 ; CFIRE_URCANNON2 
05888. .byte $00 ; CFIRE_LLCANNON2 
05889. .byte $00 ; CFIRE_HRCANNON 
05890. .byte $00 ; Not used? 
05891. .byte $00 ; CFIRE_LBOBOMBS 
05892. .byte $00 ; CFIRE_RBOBOMBS 
05893.  
05894. Bill_CPYOff: .byte $00, $00 ; Bullet/Missile Bill 
05895.  
05896.  
05897. CFire_4Way: 
05898.  
05899. ; Load graphics for 4-Way cannon 
05900. LDA #$36 
05901. STA PatTable_BankSel+4 
05902.  
05903. LDA CannonFire_Timer2,X 
05904. BNE PRG007_BE1C ; If timer2 has not expired, jump to PRG007_BE1C (RTS) 
05905.  
05906. ; Reset timer2 = $3D 
05907. LDA #$3d 
05908. STA CannonFire_Timer2,X 
05909.  
05910. LDA CannonFire_Y,X 
05911. CMP Level_VertScroll 
05912. LDA CannonFire_YHi,X 
05913. SBC Level_VertScrollH 
05914. BNE PRG007_BE42 ; If the 4-Way cannon is vertically off-screen, jump to PRG007_BE42 (RTS) 
05915.  
05916. LDA CannonFire_X,X 
05917. CMP <Horz_Scroll 
05918. LDA CannonFire_XHi,X 
05919. SBC <Horz_Scroll_Hi 
05920. BNE PRG007_BE42 ; If the 4-Way cannon is horizontally off-screen, jump to PRG007_BE42 (RTS) 
05921.  
05922. LDA CannonFire_X,X 
05923. SUB <Horz_Scroll 
05924. ADD #32 
05925. CMP #40 
05926. BLT PRG007_BE42 ; If the 4-Way cannon is too far left off-screen, jump to PRG007_BE42 (RTS) 
05927.  
05928. ; Reset cannon timer to $20 
05929. LDA #$20 
05930. STA CannonFire_Timer,X 
05931.  
05932. INC CannonFire_Var,X ; CannonFire_Var++ 
05933.  
05934. PRG007_BE1C: 
05935. LDA CannonFire_Timer,X 
05936. BEQ PRG007_BE42 ; If timer expired, jump to PRG007_BE42 (RTS) 
05937.  
05938. CMP #$1d 
05939. BNE PRG007_BE43 ; If timer <> $1D, jump to PRG007_BE43 
05940.  
05941. LDA #CHNGTILE_4WAYCANNON 
05942. STA Level_ChgTileEvent 
05943.  
05944. ; Set coordinates of change 
05945. LDA CannonFire_Y,X 
05946. STA Level_BlockChgYLo 
05947.  
05948. LDA CannonFire_YHi,X 
05949. STA Level_BlockChgYHi 
05950.  
05951. LDA CannonFire_X,X 
05952. STA Level_BlockChgXLo 
05953.  
05954. LDA CannonFire_XHi,X 
05955. STA Level_BlockChgXHi 
05956.  
05957. PRG007_BE42: 
05958. RTS ; Return 
05959.  
05960. PRG007_BE43: 
05961. CMP #$01 
05962. BNE PRG007_BEAA ; If timer <> 1, jump to PRG007_BEAA 
05963.  
05964. LDA CannonFire_Var,X 
05965. AND #$07 
05966. STA <Temp_Var1 ; Temp_Var1 = 0 to 7 
05967.  
05968. JSR FireCannonBall ; Fire cannon ball 
05969.  
05970. LDA CannonFire_Var,X 
05971. ADD #$04 
05972. AND #$07 ; +4 wrap around (fire the cannonball on the opposite side) 
05973.  
05974. PRG007_BE59: 
05975. STA <Temp_Var1 
05976. JMP FireCannonBall ; Fire the cannonball! 
05977.  
05978. FireCannonBall: 
05979. LDY #$05 ; Y = 5 
05980.  
05981. PRG007_BE60: 
05982. LDA SpecialObj_ID,Y 
05983. BEQ PRG007_BE69 ; If this special object slot is free, jump to PRG007_BE69 
05984.  
05985. DEY ; Y-- 
05986. BPL PRG007_BE60 ; While Y >= 0, loop! 
05987.  
05988. RTS ; Return 
05989.  
05990. PRG007_BE69: 
05991.  
05992. ; Set this as a cannon ball! 
05993. LDA #SOBJ_CANNONBALL 
05994. STA SpecialObj_ID,Y 
05995.  
05996. ; Set cannonball X 
05997. LDA CannonFire_X,X 
05998. CLC 
05999. LDX <Temp_Var1 ; X = 0 to 7 
06000. ADC CannonPoof_XOffs,X 
06001. STA SpecialObj_XLo,Y 
06002.  
06003. ; Set cannonball Y velocity 
06004. LDA FourWay_CannonballYVel,X 
06005. STA SpecialObj_YVel,Y 
06006.  
06007. ; Set cannonball X velocity 
06008. LDA FourWay_CannonballXVel,X 
06009. STA SpecialObj_XVel,Y 
06010.  
06011. ; Temp_Var3 = 0 (16-bit sign extension) 
06012. LDA #$00 
06013. STA <Temp_Var3 
06014.  
06015. LDA CannonPoof_YOffs,X 
06016. BPL PRG007_BE91 ; If Y offset is not negative, jump to PRG007_BE91 
06017.  
06018. DEC <Temp_Var3 ; Temp_Var3 = $FF (16-bit sign extension) 
06019.  
06020. PRG007_BE91: 
06021. CLC 
06022. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
06023. ADC CannonFire_Y,X 
06024. STA SpecialObj_YLo,Y 
06025. LDA CannonFire_YHi,X 
06026. ADC <Temp_Var3 ; 16-bit sign extension 
06027. STA SpecialObj_YHi,Y  
06028.  
06029. ; Data = 0 
06030. LDA #$00 
06031. STA SpecialObj_Data,Y 
06032.  
06033. JMP CannonFire_NoiseAndSmoke ; Play cannon fire noise and make smoke 
06034.  
06035. PRG007_BEAA: 
06036. RTS ; Return 
06037.  
06038. ; Produces the smoke resulting from cannon fire; specify X/Y offset 
06039. ; from Cannon Fire's position by Temp_Var1 which indexes CannonPoof_X/YOffs 
06040. CannonFire_NoiseAndSmoke: 
06041. ; Cannon firing noise 
06042. LDA Sound_QLevel1 
06043. ORA #SND_LEVELBABOOM 
06044. STA Sound_QLevel1 
06045.  
06046. JSR BrickBust_MoveOver ; Make room in first "brick bust" slot for poof 
06047.  
06048. ; Brick bust, poof style 
06049. LDA #$01 
06050. STA BrickBust_En 
06051.  
06052. ; Set poof X 
06053. LDA CannonFire_X,X ; Get Cannon Fire X 
06054. CLC 
06055. LDX <Temp_Var1 ; X = Temp_Var1 holds the index into CannonPoof_XOffs 
06056. ADC CannonPoof_XOffs,X ; + CannonPoof_XOffs[Temp_Var1] 
06057. SUB <Horz_Scroll ; Make relative to horizontal scroll 
06058. STA BrickBust_X ; Set X 
06059.  
06060. LDA CannonPoof_YOffs,X ; A = CannonPoof_YOffs[Temp_Var1] 
06061.  
06062. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
06063.  
06064. ADD CannonFire_Y,X ; + Cannon Fire Y 
06065. SUB Level_VertScroll ; Make relative to vertical scroll 
06066. STA BrickBust_YUpr ; Set Y 
06067.  
06068. ; Set poof counter 
06069. LDA #$1f 
06070. STA BrickBust_HEn 
06071.  
06072. RTS ; Return 
06073.  
06074.  
06075. Rocky_InitAttr: .byte SPR_HFLIP | SPR_BEHINDBG, SPR_BEHINDBG 
06076.  
06077. CFire_RockyWrench: 
06078. LDA CannonFire_Timer,X 
06079. BNE PRG007_BF28 ; If timer not expired, jump to PRG007_BF28 (RTS) 
06080.  
06081. ; Reset cannon timer to $C0 
06082. LDA #$c0 
06083. STA CannonFire_Timer,X 
06084.  
06085. JSR PrepareNewObjectOrAbort ; Get me a slot for Rocky Wrench or don't come back! 
06086.  
06087. LDY <SlotIndexBackup ; Y = Cannon Fire slot index 
06088.  
06089. ; This is a Rocky Wrench 
06090. LDA #OBJ_ROCKYWRENCH 
06091. STA Level_ObjectID,X 
06092.  
06093. ; Start at Cannon Fire Y - 6 
06094. LDA CannonFire_Y,Y 
06095. SUB #$06 
06096. STA <Objects_Y,X 
06097. LDA CannonFire_YHi,Y 
06098. SBC #$00 
06099. STA <Objects_YHi,X 
06100.  
06101. ; Set Rocky's X to Cannon Fire's X 
06102. LDA CannonFire_XHi,Y 
06103. STA <Objects_XHi,X 
06104. LDA CannonFire_X,Y 
06105. STA <Objects_X,X 
06106.  
06107. ; Var5 = 0 
06108. LDA #$00 
06109. STA <Objects_Var5,X 
06110.  
06111. ; Set Rocky's timer to $28 
06112. LDA #$28 
06113. STA Objects_Timer,X 
06114.  
06115. ; Set Rocky's attributes 
06116. LDA #SPR_PAL3 
06117. STA Objects_SprAttr,X 
06118.  
06119. ; Set Rocky's initial attributes towards Player 
06120. JSR Level_ObjCalcXDiffs 
06121. LDA Rocky_InitAttr,Y 
06122. STA Objects_FlipBits,X 
06123.  
06124. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
06125.  
06126. PRG007_BF28: 
06127. RTS ; Return 
06128.  
06129. Bill_XVelTowardsPlayer: .byte $18, -$18 
06130. Bill_FlipTowardsPlayer: .byte SPR_HFLIP, $00 
06131. Bill_Var4TowardsPlayer: .byte $01, $00 
06132.  
06133. CFire_BulletBill: 
06134. LDA CannonFire_Timer,X 
06135. BNE PRG007_BF28 ; If timer not expired, jump to PRG007_BF28 (RTS) 
06136.  
06137. LDA CannonFire_Y,X 
06138. CMP Level_VertScroll 
06139. LDA CannonFire_YHi,X 
06140. SBC Level_VertScrollH 
06141. BNE PRG007_BF28 ; If Cannon Fire has fallen off screen vertically, jump to PRG007_BF28 (RTS) 
06142.  
06143. LDA CannonFire_X,X 
06144. CMP <Horz_Scroll 
06145. LDA CannonFire_XHi,X 
06146. SBC <Horz_Scroll_Hi 
06147. BNE PRG007_BF28 ; If Cannon Fire has fallen off screen horizontally, jump to PRG007_BF28 (RTS) 
06148.  
06149. ; Reset Cannon Fire timer to $80-$9F, random 
06150. LDA RandomN,X 
06151. AND #$1f 
06152. ORA #$80 
06153. STA CannonFire_Timer,X 
06154.  
06155. LDA CannonFire_X,X 
06156. SUB <Horz_Scroll 
06157. ADD #16 
06158. CMP #32 
06159. BLT PRG007_BF28 ; If Cannon Fire X + 16 is less than 32 pixels from screen edge, jump to PRG007_BF28 (RTS) 
06160.  
06161. LDA <Player_X 
06162. SBC CannonFire_X,X 
06163. ADD #17 
06164. CMP #34 
06165. BLT PRG007_BF28 ; If Player is standing on Bullet Bill cannon, jump to PRG007_BF28 (RTS) 
06166.  
06167. JSR PrepareNewObjectOrAbort 
06168.  
06169. LDY <SlotIndexBackup ; Y = Cannon Fire object slot 
06170.  
06171. LDA CannonFire_ID,Y 
06172. LSR A ; Selects which Bill type 
06173.  
06174. LDA #OBJ_BULLETBILL 
06175.  
06176. BCS PRG007_BF80 ; If carry set, jump to PRG007_BF80 
06177.  
06178. LDA #OBJ_BULLETBILLHOMING 
06179.  
06180. PRG007_BF80: 
06181. STA Level_ObjectID,X ; Store Bill's ID 
06182.  
06183. ; Set Bill's palette 
06184. LDA #SPR_PAL3 
06185. STA Objects_SprAttr,X 
06186.  
06187. ; Set Bill's Y 
06188. LDA CannonFire_Y,Y 
06189. SUB #$01 
06190. STA <Objects_Y,X 
06191. LDA CannonFire_YHi,Y 
06192. SBC #$00 
06193. STA <Objects_YHi,X 
06194.  
06195. ; Set Bill's X 
06196. LDA CannonFire_XHi,Y 
06197. STA <Objects_XHi,X 
06198. LDA CannonFire_X,Y 
06199. STA <Objects_X,X 
06200. STA Objects_Var13,X ; original X hold 
06201.  
06202. ; Bill's timer = $0C 
06203. LDA #$0c 
06204. STA Objects_Timer,X 
06205.  
06206. ; Bill's Var3 = $20 
06207. LDA #$20 
06208. STA Objects_Var3,X 
06209.  
06210. JSR Level_ObjCalcXDiffs 
06211.  
06212. ; Bill fires towards Player 
06213. LDA Bill_XVelTowardsPlayer,Y 
06214. STA <Objects_XVel,X 
06215.  
06216. ; Bill faces Player 
06217. LDA Bill_FlipTowardsPlayer,Y 
06218. STA Objects_FlipBits,X 
06219.  
06220. ; Set Bill's direction flag 
06221. LDA Bill_Var4TowardsPlayer,Y 
06222. STA <Objects_Var4,X 
06223.  
06224. LDX <SlotIndexBackup ; X = Cannon Fire slot index 
06225.  
06226. TYA ; 0 or 1 
06227. ADD #(Bill_CPXOff - CannonPoof_XOffs) 
06228. STA <Temp_Var1 ; -> Temp_Var1 
06229.  
06230. JSR CannonFire_NoiseAndSmoke ; Play cannon fire noise and make smoke 
06231.  
06232. RTS ; Return 
06233.  
06234.  
06235. ; Provides a newly prepared object or does not return to caller! 
06236. PrepareNewObjectOrAbort: 
06237. LDX #$04 ; X = 4 
06238. PRG007_BFCF: 
06239. LDA Objects_State,X 
06240. BEQ PRG007_BFDC ; If this object state = 0 (Dead/Empty), jump to PRG007_BFDC 
06241.  
06242. DEX ; X-- 
06243. BPL PRG007_BFCF ; While X >= 0, loop! 
06244.  
06245. ; No object slots available; do not return to caller!! 
06246. PLA 
06247. PLA 
06248.  
06249. LDX <SlotIndexBackup ; Restore 'X' to its slot index value 
06250.  
06251. RTS ; Return 
06252.  
06253. PRG007_BFDC: 
06254. JSR Level_PrepareNewObject ; Prepare this new object 
06255.  
06256. ; Set to normal state 
06257. LDA #OBJSTATE_NORMAL 
06258. STA Objects_State,X 
06259.  
06260. RTS ; Return 
06261.  
06262. ; Rest of ROM bank was empty 
06263.  
06264.