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.