?login_element?

Subversion Repositories NedoOS

Rev

Rev 414 | Blame | Compare with Previous | Last modification | View Log | Download

  1.  
  2. ;SMBDIS.ASM - A COMPREHENSIVE SUPER MARIO BROS. DISASSEMBLY (Super Mario Bros (JU))
  3. ;by doppelganger (doppelheathen@gmail.com)
  4.  
  5. ;This file is provided for your own use as-is.  It will require the character rom data
  6. ;and an iNES file header to get it to work.
  7.  
  8. ;There are so many people I have to thank for this, that taking all the credit for
  9. ;myself would be an unforgivable act of arrogance. Without their help this would
  10. ;probably not be possible.  So I thank all the peeps in the nesdev scene whose insight into
  11. ;the 6502 and the NES helped me learn how it works (you guys know who you are, there's no
  12. ;way I could have done this without your help), as well as the authors of x816 and SMB
  13. ;Utility, and the reverse-engineers who did the original Super Mario Bros. Hacking Project,
  14. ;which I compared notes with but did not copy from.  Last but certainly not least, I thank
  15. ;Nintendo for creating this game and the NES, without which this disassembly would
  16. ;only be theory.
  17.  
  18. ;Assembles with x816.
  19.  
  20. ;< LOW  low byte
  21. ;> HIGH  high byte
  22.  
  23. ;-------------------------------------------------------------------------------------
  24. ;DIRECTIVES
  25.  
  26.         if Z80==0
  27.        .index 8
  28.        .mem 8
  29.  
  30.        .org $8000
  31.         endif
  32.  
  33. ;-------------------------------------------------------------------------------------
  34.  
  35. Start:
  36.         if Z80==0
  37.              sei                          ;pretty standard 6502 type init here
  38.              cld
  39.              ldan ++%00010000               ;init PPU control register 1
  40.              sta PPU_CTRL_REG1
  41.              ldxn ++$ff                     ;reset stack pointer
  42.              txs
  43. VBlank1:     lda PPU_STATUS               ;wait two frames
  44.          checka
  45.              bpl VBlank1
  46. VBlank2:     lda PPU_STATUS
  47.          checka
  48.              bpl VBlank2
  49.         endif
  50.              ldyn16 ++MEMDATA_end-AREADATA;ColdBootOffset          ;load default cold boot pointer
  51.              ldxn ++$05                     ;this is where we check for a warm boot
  52. WBootCheck:  
  53.         if Z80==0
  54.              ldax TopScoreDisplay,x        ;check each score digit in the top score
  55.              cmpn ++10                      ;to see if we have a valid digit
  56.               cmpcy
  57.              bcs ColdBoot                 ;if not, give up and proceed with cold boot
  58.              dex                      
  59.              bpl WBootCheck
  60.              lda WarmBootValidation       ;second checkpoint, check to see if
  61.              cmpn ++$a5                     ;another location has a specific value
  62.              bne ColdBoot  
  63.              ldyn16 ++WARMMEMDATA_end-AREADATA;WarmBootOffset          ;if passed both, load warm boot pointer
  64.         endif
  65. ColdBoot:    jsr InitializeMemory         ;clear memory using pointer in Y
  66.              sta SND_DELTA_REG+1          ;reset delta counter load register
  67.              sta OperMode                 ;reset primary mode of operation
  68.              ldan ++$a5                     ;set warm boot flag
  69.              sta WarmBootValidation    
  70.              sta PseudoRandomBitReg       ;set seed for pseudorandom register
  71.              ldan ++%00001111
  72.              sta SND_MASTERCTRL_REG       ;enable all sound channels except dmc
  73.         if Z80==0
  74.              ldan ++%00000110
  75.              sta PPU_CTRL_REG2            ;turn off clipping for OAM and background
  76.         endif
  77.              jsr MoveAllSpritesOffscreen
  78.              jsr InitializeNameTables     ;initialize both name tables
  79.              inci DisableScreenFlag        ;set flag to disable screen output
  80.         if Z80==0
  81.              lda Mirror_PPU_CTRL_REG1
  82.              oran ++%10000000               ;enable NMIs
  83.              jsr WritePPUReg1
  84.         endif
  85.        
  86.              call NonMaskableInterrupt
  87.         call gettimer ;hl=timer
  88.          ld (oldupdtimer),hl
  89.          
  90. EndlessLoop:
  91.         if Z80
  92.              call EmulatePPU
  93.         call gettimer ;hl=timer
  94. oldupdtimer=$+1
  95.          ld de,oldupdtimer
  96.          ld (oldupdtimer),hl
  97.              or a
  98.              sbc hl,de
  99.         if FASTDEMOBEFOREBREAKPOINT
  100.              ld c,1
  101.              jr z,c_logic0
  102.         else
  103.              jr z,nologic
  104.         endif
  105.              ld c,8
  106.              ld a,l
  107.              cp c
  108.              jr nc,$+3 ;сюы№°х с√трхЄ Єюы№ъю т сЁ ъяюшэЄрї
  109.              ld c,l
  110. c_logic0
  111.             ld hl,logicframe
  112.             ld (hl),c
  113.              ld b,0
  114.              ld d,b
  115. logic0
  116.              call NonMaskableInterrupt
  117.             ld hl,logicframe
  118.             dec (hl)
  119.             jr nz,logic0
  120.                 jr logicq
  121. nologic
  122.         ;jr $ ;Ёхры№эю эх яюярфрхь ё■фр яЁш эюЁьры№эющ шуЁх
  123.                 YIELD;halt
  124.              ld b,0
  125.              ld d,b
  126. logicq
  127.         endif
  128.              jmp EndlessLoop              ;endless loop, need I say more?
  129.  
  130.         if MUSICONINT
  131.         include "smbsound.asm"
  132.         include "smbmusic.asm"
  133.         ;display $,"<=0x8000"
  134.         endif
  135.  
  136. ;-------------------------------------------------------------------------------------
  137. ;$00 - vram buffer address table low, also used for pseudorandom bit
  138. ;$01 - vram buffer address table high
  139.  
  140. VRAM_AddrTable_Low:
  141.       .db LOW VRAM_Buffer1, LOW WaterPaletteData, LOW GroundPaletteData
  142.       .db LOW UndergroundPaletteData, LOW CastlePaletteData, LOW VRAM_Buffer1_Offset
  143.       .db LOW VRAM_Buffer2, LOW VRAM_Buffer2, LOW BowserPaletteData
  144.       .db LOW DaySnowPaletteData, LOW NightSnowPaletteData, LOW MushroomPaletteData
  145.       .db LOW MarioThanksMessage, LOW LuigiThanksMessage, LOW MushroomRetainerSaved
  146.       .db LOW PrincessSaved1, LOW PrincessSaved2, LOW WorldSelectMessage1
  147.       .db LOW WorldSelectMessage2
  148.  
  149. VRAM_AddrTable_High:
  150.       .db HIGH VRAM_Buffer1, HIGH WaterPaletteData, HIGH GroundPaletteData
  151.       .db HIGH UndergroundPaletteData, HIGH CastlePaletteData, HIGH VRAM_Buffer1_Offset
  152.       .db HIGH VRAM_Buffer2, HIGH VRAM_Buffer2, HIGH BowserPaletteData
  153.       .db HIGH DaySnowPaletteData, HIGH NightSnowPaletteData, HIGH MushroomPaletteData
  154.       .db HIGH MarioThanksMessage, HIGH LuigiThanksMessage, HIGH MushroomRetainerSaved
  155.       .db HIGH PrincessSaved1, HIGH PrincessSaved2, HIGH WorldSelectMessage1
  156.       .db HIGH WorldSelectMessage2
  157.  
  158.       if Z80
  159. tpalettes
  160.         dw waterpalette
  161.         dw groundpalette
  162.         dw undergroundpalette
  163.         dw castlepalette
  164.       endif
  165.      
  166. VRAM_Buffer_Offset:
  167.       .db LOW VRAM_Buffer1_Offset, LOW VRAM_Buffer2_Offset
  168.  
  169. NonMaskableInterrupt:
  170.         if Z80
  171.                ;ldx VRAM_Buffer_AddrCtrl  ;load control for pointer to buffer contents
  172.                ;ldax VRAM_AddrTable_High,x
  173.                ;ld d,a
  174.                ;ldax VRAM_AddrTable_Low,x
  175.                ;ld e,a
  176.                ;ex de,hl
  177.                ;ld de,PPU_SPRLIST
  178.                ;ld bc,0x100
  179.                ;ldir
  180.                ;ex de,hl
  181.                ;ld d,b;0
  182.                lda Mirror_PPU_CTRL_REG1  ;d0 = ёЄЁрэшЎр (фы  ёъЁюыыр)
  183.                sta PPU_CTRL_REG1
  184.         else
  185.                lda Mirror_PPU_CTRL_REG1  ;disable NMIs in mirror reg
  186.                andn ++%01111111            ;save all other bits
  187.                sta Mirror_PPU_CTRL_REG1
  188.                andn ++%01111110            ;alter name table address to be $2800 ;ўЄюс√ т√тюфшЄ№ тёхуфр ёЄЁрэшЎє ёю ёў╕Єюь
  189.                sta PPU_CTRL_REG1         ;(essentially $2000) but save other bits
  190.                lda Mirror_PPU_CTRL_REG2  ;disable OAM and background display by default
  191.                andn ++%11100110
  192.                ldy DisableScreenFlag     ;get screen disable flag
  193.          checky
  194.                bne ScreenOff             ;if set, used bits as-is
  195.                lda Mirror_PPU_CTRL_REG2  ;otherwise reenable bits and save them
  196.                oran ++%00011110
  197. ScreenOff:     sta Mirror_PPU_CTRL_REG2  ;save bits for later but not in register at the moment
  198.                andn ++%11100111            ;disable screen for now
  199.                sta PPU_CTRL_REG2
  200.                ldx PPU_STATUS            ;reset flip-flop and reset scroll registers to zero
  201.                ldan ++$00
  202.                jsr InitScroll ;яш°хЄ эєыш т ёъЁюыы√ (ўЄюс√ эх ёъЁюыышЄ№ ёў╕Є)
  203.                sta PPU_SPR_ADDR          ;reset spr-ram address register
  204.                ldan ++$02                  ;perform spr-ram DMA access on $0200-$02ff
  205.                sta SPR_DMA
  206.         endif
  207.                ldx VRAM_Buffer_AddrCtrl  ;load control for pointer to buffer contents
  208.                ldax VRAM_AddrTable_Low,x  ;set indirect at $00 to pointer
  209.                sta SCRATCHPAD+$00
  210.                ldax VRAM_AddrTable_High,x
  211.                sta SCRATCHPAD+$01
  212.               ;cp 0x03
  213.               ;jr nz,$
  214.                jsr UpdateScreen          ;update screen with buffer contents
  215.                ldyn ++$00
  216.                ldx VRAM_Buffer_AddrCtrl  ;check for usage of $0341 ;VRAM_Buffer2???
  217.                cpxn ++$06
  218.                bne InitBuffer
  219.                iny                       ;get offset based on usage
  220. InitBuffer:    ldxy VRAM_Buffer_Offset,y
  221.                ldan ++$00                  ;clear buffer header at last location
  222.                stax VRAM_Buffer1_Offset,x        
  223.                stax VRAM_Buffer1,x
  224.                sta VRAM_Buffer_AddrCtrl  ;reinit address control to $0301 ;VRAM_Buffer1???
  225.         if Z80==0
  226.                lda Mirror_PPU_CTRL_REG2  ;copy mirror of $2001 to register
  227.                sta PPU_CTRL_REG2
  228.         endif
  229.           if MUSICONINT==0
  230.                jsr SoundEngine           ;play sound
  231.           else
  232. soundenginepatch=$+1
  233.                call SoundEngine_noint           ;play sound logically
  234.           endif
  235.                jsr ReadJoypads           ;read joypads
  236.               if DEMO
  237.               ld a,(readdemo_stopflag)
  238.               or a
  239.               jr nz,randomskip;PauseSkip
  240.               endif
  241.                jsr PauseRoutine          ;handle pause ;яюўхьє-Єю хёыш т√°х, Єю яюёых т√їюфр шч фхь√ тъы■ўрхЄ ярєчє
  242.                jsr UpdateTopScore
  243.                lda GamePauseStatus       ;check for pause status
  244.                lsr
  245.                bcs PauseSkip
  246.               if Z80;OPT
  247.                ld a,(TimerControl)          ;if master timer control not set, decrement
  248.                or a
  249.                jr z,DecTimers             ;all frame and interval timers
  250.                dec a
  251.                ld (TimerControl),a
  252.                jr nz,NoDecTimers
  253. DecTimers:     ;xor a
  254.                ld b,21;ldxn ++$14                  ;load end offset for end of frame timers
  255.                ld hl,IntervalTimerControl
  256.                dec (hl) ;decrement interval timer control,
  257.                ld hl,Timers+20
  258.                jp p,DecTimersLoop         ;if not expired, only frame timers will decrement
  259.                ld a,20
  260.                ld (IntervalTimerControl),a  ;if control for interval timers expired, (21 frame rule???)
  261.                ld b,36;ldxn ++$23                  ;interval timers will decrement along with frame timers
  262.                ld hl,Timers+35
  263.                xor a
  264. DecTimersLoop: cp (hl);ldax Timers,x              ;check current timer
  265.                jr z,SkipExpTimer          ;if current timer expired, branch to skip,
  266.                dec (hl);decx Timers,x              ;otherwise decrement the current timer
  267. SkipExpTimer:  dec hl ;dex                       ;move onto next timer
  268.                djnz DecTimersLoop         ;do this until all timers are dealt with
  269. NoDecTimers:   ld hl,FrameCounter
  270.                inc (hl) ;increment frame counter
  271.               else ;~Z80
  272.                lda TimerControl          ;if master timer control not set, decrement
  273.          checka
  274.                beq DecTimers             ;all frame and interval timers
  275.                deci TimerControl
  276.                bne NoDecTimers
  277. DecTimers:     ldxn ++$14                  ;load end offset for end of frame timers
  278.                deci IntervalTimerControl  ;decrement interval timer control,
  279.                bpl DecTimersLoop         ;if not expired, only frame timers will decrement
  280.                ldan ++$14
  281.                sta IntervalTimerControl  ;if control for interval timers expired, (21 frame rule???)
  282.                ldxn ++$23                  ;interval timers will decrement along with frame timers
  283. DecTimersLoop: ldax Timers,x              ;check current timer
  284.          checka
  285.                beq SkipExpTimer          ;if current timer expired, branch to skip,
  286.                decx Timers,x              ;otherwise decrement the current timer
  287. SkipExpTimer:  dex                       ;move onto next timer
  288.                bpl DecTimersLoop         ;do this until all timers are dealt with
  289. NoDecTimers:   inci FrameCounter          ;increment frame counter
  290.               endif
  291. PauseSkip:     ldxn ++$00
  292.                ldyn ++$07
  293.                lda PseudoRandomBitReg    ;get first memory location of LSFR bytes
  294.                andn ++%00000010            ;mask out all but d1
  295.                sta SCRATCHPAD+$00                   ;save here
  296.                lda PseudoRandomBitReg+1  ;get second memory location
  297.                andn ++%00000010            ;mask out all but d1
  298.                eori SCRATCHPAD+$00                   ;perform exclusive-OR on d1 from first and second bytes
  299.                clc                       ;if neither or both are set, carry will be clear
  300.                beq RotPRandomBit
  301.                sec                       ;if one or the other is set, carry will be set
  302. RotPRandomBit: rorx PseudoRandomBitReg,x  ;rotate carry into d7, and rotate last bit into carry
  303.                inx                       ;increment to next byte
  304.                dey                       ;decrement for loop
  305.                bne RotPRandomBit
  306. randomskip              
  307.                lda Sprite0HitDetectFlag  ;check for flag here
  308.          checka
  309.                beq SkipSprite0
  310.                
  311.               if Z80==0
  312. Sprite0Clr:    lda PPU_STATUS            ;wait for sprite 0 flag to clear, which will
  313.                andn ++%01000000            ;not happen until vblank has ended
  314.                bne Sprite0Clr
  315.               endif
  316.               if DEMO
  317.               ld a,(readdemo_stopflag)
  318.               or a
  319.               jr nz,Sprite0Hit
  320.               endif
  321.                lda GamePauseStatus       ;if in pause mode, do not bother with sprites at all
  322.                lsr
  323.                bcs Sprite0Hit
  324.                jsr MoveSpritesOffscreen ;3443t (3 Goomba + 2 юўъш + ╠рЁшю)
  325.                jsr SpriteShuffler ;545t
  326. Sprite0Hit:
  327.               if Z80==0
  328.                lda PPU_STATUS            ;do sprite ++0 hit detection
  329.                andn ++%01000000
  330.                beq Sprite0Hit ;цф╕ь, ъюуфр сєфхЄ ъЁрщ ьюэхЄъш эртхЁїє ¤ъЁрэр - ¤Єю ъюэхЎ эхёъЁюыышЁєхьющ чюэ√
  331.                ldyn ++$14                  ;small delay, to wait until we hit horizontal blank time
  332. HBlankDelay:   dey
  333.                bne HBlankDelay
  334.               endif
  335.              
  336. SkipSprite0:   lda HorizontalScroll      ;set scroll registers from variables
  337.                sta PPU_SCROLL_REG_H
  338.                lda VerticalScroll
  339.                sta PPU_SCROLL_REG_V
  340.               if Z80==0
  341.                lda Mirror_PPU_CTRL_REG1  ;load saved mirror of $2000
  342.                pha
  343.                sta PPU_CTRL_REG1
  344.               endif
  345.               if DEMO
  346.               ld a,(readdemo_stopflag)
  347.               or a
  348.               jr nz,SkipMainOper
  349.               endif
  350.                lda GamePauseStatus       ;if in pause mode, do not perform operation mode stuff
  351.                lsr ;яюўхьє ь√ т Ёхцшьх ярєч√??? 1
  352.                bcs SkipMainOper
  353.                jsr OperModeExecutionTree ;otherwise do one of many, many possible subroutines ;49489t (3 Goomba + 2 юўъш + ╠рЁшю)
  354. SkipMainOper:
  355.               if Z80==0
  356.                lda PPU_STATUS            ;reset flip-flop
  357.                pla
  358.                oran ++%10000000            ;reactivate NMIs
  359.                sta PPU_CTRL_REG1
  360.               endif
  361.                rti                       ;we are done until the next frame!
  362.  
  363. ;-------------------------------------------------------------------------------------
  364.  
  365. PauseRoutine:
  366.                lda OperMode           ;are we in victory mode?
  367.                cmpn ++VictoryModeValue  ;if so, go ahead
  368.                beq ChkPauseTimer
  369.                cmpn ++GameModeValue     ;are we in game mode?
  370.                bne ExitPause          ;if not, leave
  371.                lda OperMode_Task      ;if we are in game mode, are we running game engine?
  372.                cmpn ++$03
  373.                bne ExitPause          ;if not, leave
  374. ChkPauseTimer: lda GamePauseTimer     ;check if pause timer is still counting down
  375.          checka
  376.                beq ChkStart
  377.                deci GamePauseTimer     ;if so, decrement and leave
  378.                rts
  379. ChkStart:      lda SavedJoypad1Bits   ;check to see if start is pressed
  380.                andn ++Start_Button      ;on controller 1
  381.                beq ClrPauseTimer
  382.                lda GamePauseStatus    ;check to see if timer flag is set
  383.                andn ++%10000000         ;and if so, do not reset timer (residual,
  384.                bne ExitPause          ;joypad reading routine makes this unnecessary)
  385.                ;jr $
  386.                ldan ++$2b               ;set pause timer
  387.                sta GamePauseTimer
  388.                lda GamePauseStatus
  389.                tay
  390.                iny                    ;set pause sfx queue for next pause mode
  391.                sty PauseSoundQueue
  392.                eorn ++%00000001         ;invert d0 and set d7
  393.                oran ++%10000000
  394.                bne SetPause           ;unconditional branch
  395. ClrPauseTimer: lda GamePauseStatus    ;clear timer flag if timer is at zero and start button
  396.                andn ++%01111111         ;is not pressed
  397. SetPause:      sta GamePauseStatus
  398. ExitPause:     rts
  399.  
  400. ;-------------------------------------------------------------------------------------
  401. ;$00 - used for preset value
  402.  
  403. SpriteShuffler:
  404.         if Z80
  405.         else
  406.                ldy AreaType                ;load level type, likely residual code
  407.                ldan ++$28                    ;load preset value which will put it at
  408.                sta SCRATCHPAD+$00                     ;sprite #10
  409.                ldxn ++$0e                    ;start at the end of OAM data offsets
  410.                
  411. ShuffleLoop:   ldax SprDataOffset,x         ;check for offset value against
  412.                cmpi SCRATCHPAD+$00                     ;the preset value
  413.               cmpcy
  414.                bcc NextSprOffset           ;if less, skip this part
  415.                ldy SprShuffleAmtOffset     ;get current offset to preset value we want to add
  416.                clc
  417.                adcy SprShuffleAmt,y         ;get shuffle amount, add to current sprite offset
  418.                bcc StrSprOffset            ;if not exceeded $ff, skip second add
  419.                clc
  420.                adci SCRATCHPAD+$00                     ;otherwise add preset value $28 to offset
  421. StrSprOffset:  stax SprDataOffset,x         ;store new offset here or old one if branched to here
  422. NextSprOffset: dex                         ;move backwards to next one
  423.                bpl ShuffleLoop
  424.                
  425.                ldx SprShuffleAmtOffset     ;load offset
  426.                inx
  427.                cpxn ++$03                    ;check if offset + 1 goes to 3
  428.                bne SetAmtOffset            ;if offset + 1 not 3, store
  429.                ldxn ++$00                    ;otherwise, init to 0
  430. SetAmtOffset:  stx SprShuffleAmtOffset
  431.         endif
  432.                ldxn ++$08                    ;load offsets for values and storage
  433.                ldyn ++$02
  434.                
  435. SetMiscOffset: lday SprDataOffset+5,y       ;load one of three OAM data offsets
  436.                stax Misc_SprDataOffset-2,x  ;store first one unmodified, but
  437.                clc                         ;add eight to the second and eight
  438.                adcn ++$08                    ;more to the third one
  439.                stax Misc_SprDataOffset-1,x  ;note that due to the way X is set up,
  440.                clc                         ;this code loads into the misc sprite offsets
  441.                adcn ++$08
  442.                stax Misc_SprDataOffset,x        
  443.                dex
  444.                dex
  445.                dex
  446.                dey
  447.                bpl SetMiscOffset           ;do this until all misc spr offsets are loaded (3 °Єєъш)
  448.                rts
  449.  
  450. ;-------------------------------------------------------------------------------------
  451.  
  452. OperModeExecutionTree:
  453.       lda OperMode     ;this is the heart of the entire program,
  454.       jsr JumpEngine   ;most of what goes on starts here
  455.  
  456.       .dw TitleScreenMode
  457.       .dw GameMode
  458.       .dw VictoryMode
  459.       .dw GameOverMode
  460.  
  461. ;-------------------------------------------------------------------------------------
  462.  
  463. MoveAllSpritesOffscreen:
  464.               ldyn ++$00                ;this routine moves all sprites off the screen
  465.               jr MoveSpritesOffscreen_go;.db $2c                 ;BIT instruction opcode
  466.  
  467. MoveSpritesOffscreen:
  468.               ldyn ++$04                ;this routine moves all but sprite 0
  469. MoveSpritesOffscreen_go
  470.               ldan ++$f8                ;off the screen
  471. SprInitLoop:  stay Sprite_Y_Position,y ;write 248 into OAM data's Y coordinate
  472.               iny                     ;which will move it off the screen
  473.               iny
  474.               iny
  475.               iny
  476.               bne SprInitLoop
  477.               rts
  478.  
  479. ;-------------------------------------------------------------------------------------
  480.  
  481. TitleScreenMode:
  482.       lda OperMode_Task
  483.       jsr JumpEngine
  484.  
  485.       .dw InitializeGame
  486.       .dw ScreenRoutines
  487.       .dw PrimaryGameSetup
  488.       .dw GameMenuRoutine
  489.  
  490. ;-------------------------------------------------------------------------------------
  491.  
  492. WSelectBufferTemplate:
  493.       .db $04, $20, $73, $01, $00, $00
  494.  
  495. GameMenuRoutine:
  496.         ;jr $
  497.               ldyn ++$00
  498.               lda SavedJoypad1Bits        ;check to see if either player pressed
  499.               orai SavedJoypad2Bits        ;only the start button (either joypad)
  500.               cmpn ++Start_Button
  501.               beq StartGame
  502.               cmpn ++A_Button+Start_Button  ;check to see if A + start was pressed
  503.               bne ChkSelect               ;if not, branch to check select button
  504. StartGame:    
  505.         ;jr $
  506.                 jmp ChkContinue             ;if either start or A + start, execute here
  507. ChkSelect:    cmpn ++Select_Button          ;check to see if the select button was pressed
  508.               beq SelectBLogic            ;if so, branch reset demo timer
  509.               ldx DemoTimer               ;otherwise check demo timer
  510.          checkx
  511.               bne ChkWorldSel             ;if demo timer not expired, branch to check world selection
  512.               sta SelectTimer             ;set controller bits here if running demo
  513.               jsr DemoEngine              ;run through the demo actions
  514.               bcs ResetTitle              ;if carry flag set, demo over, thus branch
  515.         ;jr $ ;ё■фр яюярфрхь
  516.               jmp RunDemo                 ;otherwise, run game engine for demo
  517. ChkWorldSel:  ldx WorldSelectEnableFlag   ;check to see if world selection has been enabled
  518.          checkx
  519.               beq NullJoypad
  520.               cmpn ++B_Button               ;if so, check to see if the B button was pressed
  521.               bne NullJoypad
  522.               iny                         ;if so, increment Y and execute same code as select
  523. SelectBLogic: lda DemoTimer               ;if select or B pressed, check demo timer one last time
  524.         ;jr $ ;ё■фр яюярфрхь яю select
  525.          checka
  526.               beq ResetTitle              ;if demo timer expired, branch to reset title screen mode
  527.         ;jr $ ;ё■фр яюярфрхь яю select Єюы№ъю ё яЁртшы№э√ьш ЄрщьхЁрьш
  528.               ldan ++$18                    ;otherwise reset demo timer
  529.               sta DemoTimer
  530.               lda SelectTimer             ;check select/B button timer
  531.          checka
  532.               bne NullJoypad              ;if not expired, branch
  533.               ldan ++$10                    ;otherwise reset select button timer
  534.               sta SelectTimer
  535.               cpyn ++$01                    ;was the B button pressed earlier?  if so, branch
  536.               beq IncWorldSel             ;note this will not be run if world selection is disabled
  537.         ;jr $ ;ё■фр яюярфрхь яю select Єюы№ъю ё яЁртшы№э√ьш ЄрщьхЁрьш
  538.               lda NumberOfPlayers         ;if no, must have been the select button, therefore
  539.               eorn ++%00000001              ;change number of players and draw icon accordingly
  540.               sta NumberOfPlayers
  541.               jsr DrawMushroomIcon
  542.               jmp NullJoypad
  543. IncWorldSel:  ldx WorldSelectNumber       ;increment world select number
  544.               inx
  545.               txa
  546.               andn ++%00000111              ;mask out higher bits
  547.               sta WorldSelectNumber       ;store as current world select number
  548.               jsr GoContinue
  549. UpdateShroom: ldax WSelectBufferTemplate,x ;write template for world select in vram buffer
  550.               stax VRAM_Buffer1-1,x        ;do this until all bytes are written
  551.               inx
  552.               cpxn ++$06
  553.               bmi UpdateShroom
  554.               ldy WorldNumber             ;get world number from variable and increment for
  555.               iny                         ;proper display, and put in blank byte before
  556.               sty VRAM_Buffer1+3          ;null terminator
  557. NullJoypad:   ldan ++$00                    ;clear joypad bits for player 1
  558.               sta SavedJoypad1Bits
  559. RunDemo:      jsr GameCoreRoutine         ;run game engine
  560.               lda GameEngineSubroutine    ;check to see if we're running lose life routine
  561.               cmpn ++$06
  562.               bne ExitMenu                ;if not, do not do all the resetting below
  563. ResetTitle:   ldan ++$00                    ;reset game modes, disable
  564.               sta OperMode                ;sprite 0 check and disable
  565.               sta OperMode_Task           ;screen output
  566.               sta Sprite0HitDetectFlag
  567.               inci DisableScreenFlag
  568.               rts
  569. ChkContinue:  ldy DemoTimer               ;if timer for demo has expired, reset modes
  570.          checky
  571.                 ;jr $
  572.               beq ResetTitle ;яюўхьє ьх°рхЄ фхьрь??? хёыш чръюььхэЄшЁютрЄ№, Єю шч фхь√ яю Start яюярфрхь эх т ьхэ■, р т шуЁє, ё сюы№°шь ╠рЁшю, хёыш юэ єцх сюы№°ющ
  573.               asl                         ;check to see if A button was also pushed
  574.               bcc StartWorld1             ;if not, don't load continue function's world number
  575.               lda ContinueWorld           ;load previously saved world number for secret
  576.               jsr GoContinue              ;continue function when pressing A + start
  577. StartWorld1:  jsr LoadAreaPointer
  578.  
  579.         ;jr $ ;ё■фр яюярфрхь яю start
  580.               inci Hidden1UpFlag           ;set 1-up box flag for both players
  581.               inci OffScr_Hidden1UpFlag
  582.               inci FetchNewGameTimerFlag   ;set fetch new game timer flag
  583.               inci OperMode                ;set next game mode
  584.               lda WorldSelectEnableFlag   ;if world select flag is on, then primary
  585.               sta PrimaryHardMode         ;hard mode must be on as well
  586.               ldan ++$00
  587.               sta OperMode_Task           ;set game mode here, and clear demo timer
  588.               sta DemoTimer
  589.               ldxn ++$17
  590.               ldan ++$00
  591. InitScores:   stax ScoreAndCoinDisplay,x   ;clear player scores and coin displays
  592.               dex
  593.               bpl InitScores
  594. ExitMenu:     rts
  595. GoContinue:   sta WorldNumber             ;start both players at the first area
  596.               sta OffScr_WorldNumber      ;of the previously saved world number
  597.               ldxn ++$00                    ;note that on power-up using this function
  598.               stx AreaNumber              ;will make no difference
  599.               stx OffScr_AreaNumber  
  600.               rts
  601.  
  602. ;-------------------------------------------------------------------------------------
  603.  
  604. MushroomIconData:
  605.       .db $07, $22, $49, $83, $ce, $24, $24, $00
  606.  
  607. DrawMushroomIcon:
  608.               ldyn ++$07                ;read eight bytes to be read by transfer routine
  609. IconDataRead: lday MushroomIconData,y  ;note that the default position is set for a
  610.               stay VRAM_Buffer1-1,y    ;1-player game
  611.               dey
  612.               bpl IconDataRead
  613.               lda NumberOfPlayers     ;check number of players
  614.          checka
  615.               beq ExitIcon            ;if set to 1-player game, we're done
  616.               ldan ++$24                ;otherwise, load blank tile in 1-player position
  617.               sta VRAM_Buffer1+3
  618.               ldan ++$ce                ;then load shroom icon tile in 2-player position
  619.               sta VRAM_Buffer1+5
  620. ExitIcon:     rts
  621.  
  622. ;-------------------------------------------------------------------------------------
  623.  
  624. DemoActionData:
  625.       .db $01, $80, $02, $81, $41, $80, $01
  626.       .db $42, $c2, $02, $80, $41, $c1, $41, $c1
  627.       .db $01, $c1, $01, $02, $80, $00
  628.  
  629. DemoTimingData:
  630.       .db $9b, $10, $18, $05, $2c, $20, $24
  631.       .db $15, $5a, $10, $20, $28, $30, $20, $10
  632.       .db $80, $20, $30, $30, $01, $ff, $00
  633.  
  634. DemoEngine:
  635.           ldx DemoAction         ;load current demo action
  636.           lda DemoActionTimer    ;load current action timer
  637.          checka
  638.           bne DoAction           ;if timer still counting down, skip
  639.           inx
  640.           inci DemoAction         ;if expired, increment action, X, and
  641.           sec                    ;set carry by default for demo over
  642.           ldax DemoTimingData-1,x ;get next timer
  643.         if Z80
  644.         sec
  645.         endif
  646.           sta DemoActionTimer    ;store as current timer
  647.          checka
  648.           beq DemoOver           ;if timer already at zero, skip
  649. DoAction: ldax DemoActionData-1,x ;get and perform action (current or next)
  650.           sta SavedJoypad1Bits
  651.           deci DemoActionTimer    ;decrement action timer
  652.           clc                    ;clear carry if demo still going
  653. DemoOver: rts
  654.  
  655. ;-------------------------------------------------------------------------------------
  656.  
  657. VictoryMode:
  658.             jsr VictoryModeSubroutines  ;run victory mode subroutines
  659.             lda OperMode_Task           ;get current task of victory mode
  660.          checka
  661.             beq AutoPlayer              ;if on bridge collapse, skip enemy processing
  662.             ldxn ++$00
  663.             stx ObjectOffset            ;otherwise reset enemy object offset
  664.             jsr EnemiesAndLoopsCore     ;and run enemy code
  665. AutoPlayer: jsr RelativePlayerPosition  ;get player's relative coordinates
  666.             jmp PlayerGfxHandler        ;draw the player, then leave
  667.  
  668. VictoryModeSubroutines:
  669.       lda OperMode_Task
  670.       jsr JumpEngine
  671.  
  672.       .dw BridgeCollapse
  673.       .dw SetupVictoryMode
  674.       .dw PlayerVictoryWalk
  675.       .dw PrintVictoryMessages
  676.       .dw PlayerEndWorld
  677.  
  678. ;-------------------------------------------------------------------------------------
  679.  
  680. SetupVictoryMode:
  681.       ldx ScreenRight_PageLoc  ;get page location of right side of screen
  682.       inx                      ;increment to next page
  683.       stx DestinationPageLoc   ;store here
  684.       ldan ++EndOfCastleMusic
  685.       sta EventMusicQueue      ;play win castle music
  686.       jmp IncModeTask_B        ;jump to set next major task in victory mode
  687.  
  688. ;-------------------------------------------------------------------------------------
  689.  
  690. PlayerVictoryWalk:
  691.              ldyn ++$00                ;set value here to not walk player by default
  692.              sty VictoryWalkControl
  693.              lda Player_PageLoc      ;get player's page location
  694.              cmpi DestinationPageLoc  ;compare with destination page location
  695.              bne PerformWalk         ;if page locations don't match, branch
  696.              lda Player_X_Position   ;otherwise get player's horizontal position
  697.              cmpn ++$60                ;compare with preset horizontal position
  698.               cmpcy
  699.              bcs DontWalk            ;if still on other page, branch ahead
  700. PerformWalk: inci VictoryWalkControl  ;otherwise increment value and Y
  701.              iny                     ;note Y will be used to walk the player
  702. DontWalk:    tya                     ;put contents of Y in A and
  703.              jsr AutoControlPlayer   ;use A to move player to the right or not
  704.              lda ScreenLeft_PageLoc  ;check page location of left side of screen
  705.              cmpi DestinationPageLoc  ;against set value here
  706.              beq ExitVWalk           ;branch if equal to change modes if necessary
  707.              lda ScrollFractional
  708.              clc                     ;do fixed point math on fractional part of scroll
  709.              adcn ++$80        
  710.              sta ScrollFractional    ;save fractional movement amount
  711.              ldan ++$01                ;set 1 pixel per frame
  712.              adcn ++$00                ;add carry from previous addition
  713.              tay                     ;use as scroll amount
  714.              jsr ScrollScreen        ;do sub to scroll the screen
  715.              jsr UpdScrollVar        ;do another sub to update screen and scroll variables
  716.              inci VictoryWalkControl  ;increment value to stay in this routine
  717. ExitVWalk:   lda VictoryWalkControl  ;load value set here
  718.          checka
  719.              beq IncModeTask_A       ;if zero, branch to change modes
  720.              rts                     ;otherwise leave
  721.  
  722. ;-------------------------------------------------------------------------------------
  723.  
  724. PrintVictoryMessages:
  725.                lda SecondaryMsgCounter   ;load secondary message counter
  726.          checka
  727.                bne IncMsgCounter         ;if set, branch to increment message counters
  728.                lda PrimaryMsgCounter     ;otherwise load primary message counter
  729.          checka
  730.                beq ThankPlayer           ;if set to zero, branch to print first message
  731.                cmpn ++$09                  ;if at 9 or above, branch elsewhere (this comparison
  732.               cmpcy
  733.                bcs IncMsgCounter         ;is residual code, counter never reaches 9)
  734.                ldy WorldNumber           ;check world number
  735.                cpyn ++World8
  736.                bne MRetainerMsg          ;if not at world 8, skip to next part
  737.                cmpn ++$03                  ;check primary message counter again
  738.               cmpcy
  739.                bcc IncMsgCounter         ;if not at 3 yet (world 8 only), branch to increment
  740.               cmpcy
  741.                sbcn ++$01                  ;otherwise subtract one
  742.                jmp ThankPlayer           ;and skip to next part
  743. MRetainerMsg:  cmpn ++$02                  ;check primary message counter
  744.               cmpcy
  745.                bcc IncMsgCounter         ;if not at 2 yet (world 1-7 only), branch
  746. ThankPlayer:   tay                       ;put primary message counter into Y
  747.          checka
  748.                bne SecondPartMsg         ;if counter nonzero, skip this part, do not print first message
  749.                lda CurrentPlayer         ;otherwise get player currently on the screen
  750.          checka
  751.                beq EvalForMusic          ;if mario, branch
  752.                iny                       ;otherwise increment Y once for luigi and
  753.                bne EvalForMusic          ;do an unconditional branch to the same place
  754. SecondPartMsg: iny                       ;increment Y to do world 8's message
  755.                lda WorldNumber
  756.                cmpn ++World8               ;check world number
  757.                beq EvalForMusic          ;if at world 8, branch to next part
  758.                dey                       ;otherwise decrement Y for world 1-7's message
  759.                cpyn ++$04                  ;if counter at 4 (world 1-7 only)
  760.               cmpcy
  761.                bcs SetEndTimer           ;branch to set victory end timer
  762.                cpyn ++$03                  ;if counter at 3 (world 1-7 only)
  763.               cmpcy
  764.                bcs IncMsgCounter         ;branch to keep counting
  765. EvalForMusic:  cpyn ++$03                  ;if counter not yet at 3 (world 8 only), branch
  766.                bne PrintMsg              ;to print message only (note world 1-7 will only
  767.                ldan ++VictoryMusic         ;reach this code if counter = 0, and will always branch)
  768.                sta EventMusicQueue       ;otherwise load victory music first (world 8 only)
  769. PrintMsg:      tya                       ;put primary message counter in A
  770.                clc                       ;add $0c or 12 to counter thus giving an appropriate value,
  771.                adcn ++$0c                  ;($0c-$0d = first), ($0e = world 1-7's), ($0f-$12 = world 8's)
  772.                sta VRAM_Buffer_AddrCtrl  ;write message counter to vram address controller
  773. IncMsgCounter: lda SecondaryMsgCounter
  774.                clc
  775.                adcn ++$04                      ;add four to secondary message counter
  776.                sta SecondaryMsgCounter
  777.                lda PrimaryMsgCounter
  778.                adcn ++$00                      ;add carry to primary message counter
  779.                sta PrimaryMsgCounter
  780.                cmpn ++$07                      ;check primary counter one more time
  781.               cmpcy
  782. SetEndTimer:
  783.                bcc ExitMsgs                  ;if not reached value yet, branch to leave
  784.                ldan ++$06
  785.                sta WorldEndTimer             ;otherwise set world end timer
  786. IncModeTask_A: inci OperMode_Task             ;move onto next task in mode
  787. ExitMsgs:      rts                           ;leave
  788.  
  789. ;-------------------------------------------------------------------------------------
  790.  
  791. PlayerEndWorld:
  792.                lda WorldEndTimer          ;check to see if world end timer expired
  793.          checka
  794.                bne EndExitOne             ;branch to leave if not
  795.                ldy WorldNumber            ;check world number
  796.                cpyn ++World8                ;if on world 8, player is done with game,
  797.               cmpcy
  798.                bcs EndChkBButton          ;thus branch to read controller
  799.                ldan ++$00
  800.                sta AreaNumber             ;otherwise initialize area number used as offset
  801.                sta LevelNumber            ;and level number control to start at area 1
  802.                sta OperMode_Task          ;initialize secondary mode of operation
  803.                inci WorldNumber            ;increment world number to move onto the next world
  804.                jsr LoadAreaPointer        ;get area address offset for the next area
  805.                inci FetchNewGameTimerFlag  ;set flag to load game timer from header
  806.                ldan ++GameModeValue
  807.                sta OperMode               ;set mode of operation to game mode
  808. EndExitOne:    rts                        ;and leave
  809. EndChkBButton: lda SavedJoypad1Bits
  810.                orai SavedJoypad2Bits       ;check to see if B button was pressed on
  811.                andn ++B_Button              ;either controller
  812.                beq EndExitTwo             ;branch to leave if not
  813.                ldan ++$01                   ;otherwise set world selection flag
  814.                sta WorldSelectEnableFlag
  815.                ldan ++$ff                   ;remove onscreen player's lives
  816.                sta NumberofLives
  817.                jsr TerminateGame          ;do sub to continue other player or end game
  818. EndExitTwo:    rts                        ;leave
  819.  
  820. ;-------------------------------------------------------------------------------------
  821.  
  822. ;data is used as tiles for numbers
  823. ;that appear when you defeat enemies
  824. FloateyNumTileData:
  825.       .db $ff, $ff ;dummy
  826.       .db $f6, $fb ; "100"
  827.       .db $f7, $fb ; "200"
  828.       .db $f8, $fb ; "400"
  829.       .db $f9, $fb ; "500"
  830.       .db $fa, $fb ; "800"
  831.       .db $f6, $50 ; "1000"
  832.       .db $f7, $50 ; "2000"
  833.       .db $f8, $50 ; "4000"
  834.       .db $f9, $50 ; "5000"
  835.       .db $fa, $50 ; "8000"
  836.       .db $fd, $fe ; "1-UP"
  837.  
  838. ;high nybble is digit number, low nybble is number to
  839. ;add to the digit of the player's score
  840. ScoreUpdateData:
  841.       .db $ff ;dummy
  842.       .db $41, $42, $44, $45, $48
  843.       .db $31, $32, $34, $35, $38, $00
  844.  
  845. FloateyNumbersRoutine:
  846.               ldax FloateyNum_Control,x     ;load control for floatey number
  847.          checka
  848.               beq EndExitOne               ;if zero, branch to leave
  849.               cmpn ++$0b                     ;if less than $0b, branch
  850.               cmpcy
  851.               bcc ChkNumTimer
  852.               ldan ++$0b                     ;otherwise set to $0b, thus keeping
  853.               stax FloateyNum_Control,x     ;it in range
  854. ChkNumTimer:  tay                          ;use as Y
  855.               ldax FloateyNum_Timer,x       ;check value here
  856.          checka
  857.               bne DecNumTimer              ;if nonzero, branch ahead
  858.               stax FloateyNum_Control,x     ;initialize floatey number control and leave
  859.               rts
  860. DecNumTimer:  decx FloateyNum_Timer,x       ;decrement value here
  861.               cmpn ++$2b                     ;if not reached a certain point, branch  
  862.               bne ChkTallEnemy
  863.               cpyn ++$0b                     ;check offset for $0b
  864.               bne LoadNumTiles             ;branch ahead if not found
  865.               inci NumberofLives            ;give player one extra life (1-up)
  866.               ldan ++Sfx_ExtraLife
  867.               sta Square2SoundQueue        ;and play the 1-up sound
  868. LoadNumTiles: lday ScoreUpdateData,y        ;load point value here
  869.               lsr                          ;move high nybble to low
  870.               lsr
  871.               lsr
  872.               lsr
  873.               tax                          ;use as X offset, essentially the digit
  874.               lday ScoreUpdateData,y        ;load again and this time
  875.               andn ++%00001111               ;mask out the high nybble
  876.               stax DigitModifier,x          ;store as amount to add to the digit
  877.               jsr AddToScore               ;update the score accordingly
  878. ChkTallEnemy: ldyx Enemy_SprDataOffset,x    ;get OAM data offset for enemy object
  879.               ldax Enemy_ID,x               ;get enemy object identifier
  880.               cmpn ++Spiny
  881.               beq FloateyPart              ;branch if spiny
  882.               cmpn ++PiranhaPlant
  883.               beq FloateyPart              ;branch if piranha plant
  884.               cmpn ++HammerBro
  885.               beq GetAltOffset             ;branch elsewhere if hammer bro
  886.               cmpn ++GreyCheepCheep
  887.               beq FloateyPart              ;branch if cheep-cheep of either color
  888.               cmpn ++RedCheepCheep
  889.               beq FloateyPart
  890.               cmpn ++TallEnemy
  891.               cmpcy
  892.               bcs GetAltOffset             ;branch elsewhere if enemy object =HIGH  $09
  893.               ldax Enemy_State,x
  894.               cmpn ++$02                     ;if enemy state defeated or otherwise
  895.               cmpcy
  896.               bcs FloateyPart              ;$02 or greater, branch beyond this part
  897. GetAltOffset: ldx SprDataOffset_Ctrl       ;load some kind of control bit
  898.               ldyx Alt_SprDataOffset,x      ;get alternate OAM data offset
  899.               ldx ObjectOffset             ;get enemy object offset again
  900. FloateyPart:  ldax FloateyNum_Y_Pos,x       ;get vertical coordinate for
  901.               cmpn ++$18                     ;floatey number, if coordinate in the
  902.               cmpcy
  903.               bcc SetupNumSpr              ;status bar, branch
  904.               cmpcy
  905.               sbcn ++$01
  906.               stax FloateyNum_Y_Pos,x       ;otherwise subtract one and store as new
  907. SetupNumSpr:  ldax FloateyNum_Y_Pos,x       ;get vertical coordinate
  908.              or a
  909.               sbcn ++$08                     ;subtract eight and dump into the
  910.               jsr DumpTwoSpr               ;left and right sprite's Y coordinates
  911.               ldax FloateyNum_X_Pos,x       ;get horizontal coordinate
  912.               stay Sprite_X_Position,y      ;store into X coordinate of left sprite
  913.               clc
  914.               adcn ++$08                     ;add eight pixels and store into X
  915.               stay Sprite_X_Position+4,y    ;coordinate of right sprite
  916.               ldan ++$02
  917.               stay Sprite_Attributes,y      ;set palette control in attribute bytes
  918.               stay Sprite_Attributes+4,y    ;of left and right sprites
  919.               ldax FloateyNum_Control,x
  920.               asl                          ;multiply our floatey number control by 2
  921.               tax                          ;and use as offset for look-up table
  922.               ldax FloateyNumTileData,x
  923.               stay Sprite_Tilenumber,y      ;display first half of number of points
  924.               ldax FloateyNumTileData+1,x
  925.               stay Sprite_Tilenumber+4,y    ;display the second half
  926.               ldx ObjectOffset             ;get enemy object offset and leave
  927.               rts
  928.  
  929. ;-------------------------------------------------------------------------------------
  930.  
  931. ScreenRoutines:
  932.       lda ScreenRoutineTask        ;run one of the following subroutines
  933.       jsr JumpEngine
  934.    
  935.       .dw InitScreen ;0
  936.       .dw SetupIntermediate ;1
  937.       .dw WriteTopStatusLine ;2
  938.       .dw WriteBottomStatusLine ;3
  939.       .dw DisplayTimeUp ;4
  940.       .dw ResetSpritesAndScreenTimer ;5
  941.       .dw DisplayIntermediate ;6
  942.       .dw ResetSpritesAndScreenTimer ;7
  943.       .dw AreaParserTaskControl ;8
  944.       .dw GetAreaPalette ;9
  945.       .dw GetBackgroundColor ;10
  946.       .dw GetAlternatePalette1 ;11
  947.       .dw DrawTitleScreen ;12
  948.       .dw ClearBuffersDrawIcon ;13
  949.       .dw WriteTopScore ;14
  950.  
  951. ;-------------------------------------------------------------------------------------
  952.  
  953. InitScreen:
  954.       jsr MoveAllSpritesOffscreen ;initialize all sprites including sprite ++0
  955.       jsr InitializeNameTables    ;and erase both name and attribute tables
  956.       lda OperMode
  957.          checka
  958.       beq NextSubtask             ;if mode still 0, do not load
  959.       ldxn ++$03                    ;into buffer pointer
  960.       jmp SetVRAMAddr_A
  961.  
  962. ;-------------------------------------------------------------------------------------
  963.  
  964. SetupIntermediate:
  965.       lda BackgroundColorCtrl  ;save current background color control
  966.       pha                      ;and player status to stack
  967.       lda PlayerStatus
  968.       pha
  969.       ldan ++$00                 ;set background color to black
  970.       sta PlayerStatus         ;and player status to not fiery
  971.       ldan ++$02                 ;this is the ONLY time background color control
  972.       sta BackgroundColorCtrl  ;is set to less than 4
  973.       jsr GetPlayerColors
  974.       pla                      ;we only execute this routine for
  975.       sta PlayerStatus         ;the intermediate lives display
  976.       pla                      ;and once we're done, we return bg
  977.       sta BackgroundColorCtrl  ;color ctrl and player status from stack
  978.       jmp IncSubtask           ;then move onto the next task
  979.  
  980. ;-------------------------------------------------------------------------------------
  981.  
  982.         if Z80==0
  983. AreaPalette:
  984.       .db $01, $02, $03, $04
  985.         endif
  986.  
  987. GetAreaPalette:
  988.         if Z80
  989.                 ld a,(AreaType)
  990.                 add a,a
  991.                 ld e,a
  992.                 ld hl,tpalettes
  993.                 add hl,de
  994.                 ld a,(hl)
  995.                 inc hl
  996.                 ld h,(hl)
  997.                 ld l,a
  998.                 ld (curpalette),hl
  999.                 jp IncSubtask           ;move onto next task
  1000.         else
  1001.                ldy AreaType             ;select appropriate palette to load
  1002.                ldxy AreaPalette,y        ;based on area type
  1003.         endif
  1004. SetVRAMAddr_A: stx VRAM_Buffer_AddrCtrl ;store offset into buffer control
  1005. NextSubtask:   jmp IncSubtask           ;move onto next task
  1006.  
  1007. ;-------------------------------------------------------------------------------------
  1008. ;$00 - used as temp counter in GetPlayerColors
  1009.  
  1010. BGColorCtrl_Addr:
  1011.       .db $00, $09, $0a, $04
  1012.  
  1013. BackgroundColors:
  1014.         if Z80BGCOLOR
  1015.         db 0xcc,0xcc,0xff,0xff ;used by area type if bg color ctrl not set
  1016.         db 0xff,0xcc,0xff,0xff ;used by background color control if set
  1017.         else
  1018.       .db $22, $22, $0f, $0f ;used by area type if bg color ctrl not set
  1019.       .db $0f, $22, $0f, $0f ;used by background color control if set
  1020.         endif
  1021.  
  1022. PlayerColors:
  1023.         if Z80MARIOCOLOR
  1024.       dw 0x3f3f,0xbdbd ;mario's colors
  1025.       dw 0x3f3f,0xefef ;luigi's colors
  1026.       dw 0x3f3f,0x0c0c ;fiery (used by both)
  1027.         else
  1028.       .db $22, $16, $27, $18 ;mario's colors
  1029.       .db $22, $30, $27, $19 ;luigi's colors
  1030.       .db $22, $37, $27, $16 ;fiery (used by both)
  1031.         endif
  1032.  
  1033. GetBackgroundColor:
  1034.            ldy BackgroundColorCtrl   ;check background color control
  1035.          checky
  1036.            beq NoBGColor             ;if not set, increment task and fetch palette
  1037.         if Z80BGCOLOR
  1038.         else
  1039.            lday BGColorCtrl_Addr-4,y  ;put appropriate palette into vram
  1040.            sta VRAM_Buffer_AddrCtrl  ;note that if set to 5-7, $0301 (VRAM_Buffer1) will not be read
  1041.         endif
  1042. NoBGColor: inci ScreenRoutineTask     ;increment to next subtask and plod on through
  1043.      
  1044. GetPlayerColors:
  1045.         if Z80MARIOCOLOR
  1046.                lda CurrentPlayer        ;check which player is on the screen
  1047.                ld de,PlayerColors
  1048.                or a
  1049.                beq ChkFiery
  1050.                ld de,PlayerColors+4;ldyn ++$04                 ;load offset for luigi
  1051. ChkFiery:      lda PlayerStatus         ;check player status
  1052.                cmpn ++$02
  1053.                bne StartClrGet          ;if fiery, load alternate offset for fiery player
  1054.                ld de,PlayerColors+8;ldyn ++$08
  1055. StartClrGet:
  1056.                ld hl,(curpalette)
  1057.                ld c,12*2
  1058.                add hl,bc
  1059.                ex de,hl
  1060.                ;c>=4
  1061.                ldi
  1062.                ldi
  1063.                inc de
  1064.                inc de
  1065.                ldi
  1066.                ldi
  1067.                ld (oldpalette),hl ;!=curpalette, ўЄюс√ ртЄюьрЄшўхёъш юсэютшырё№
  1068.  
  1069.                ld d,b
  1070.  
  1071.           if Z80BGCOLOR
  1072.                ldy BackgroundColorCtrl  ;if this value is four or greater, it will be set
  1073.          checky
  1074.                bne SetBGColor           ;therefore use it as offset to background color
  1075.                ldy AreaType             ;otherwise use area type bits from area offset as offset
  1076. SetBGColor:    lday BackgroundColors,y   ;to background color instead
  1077.                ;jr $
  1078.                ld hl,(curpalette)
  1079.                ld (hl),a
  1080.                inc hl
  1081.                ld (hl),a
  1082.           endif
  1083.  
  1084.                 ret
  1085.         else
  1086.                ldx VRAM_Buffer1_Offset  ;get current buffer offset
  1087.                ldyn ++$00
  1088.                lda CurrentPlayer        ;check which player is on the screen
  1089.          checka
  1090.                beq ChkFiery
  1091.                ldyn ++$04                 ;load offset for luigi
  1092. ChkFiery:      lda PlayerStatus         ;check player status
  1093.                cmpn ++$02
  1094.                bne StartClrGet          ;if fiery, load alternate offset for fiery player
  1095.                ldyn ++$08
  1096. StartClrGet:   ldan ++$03                 ;do four colors
  1097.                sta SCRATCHPAD+$00
  1098. ClrGetLoop:    lday PlayerColors,y       ;fetch player colors and store them
  1099.                stax VRAM_Buffer1+3,x     ;in the buffer
  1100.                iny
  1101.                inx
  1102.                deci SCRATCHPAD+$00
  1103.                bpl ClrGetLoop
  1104.                ldx VRAM_Buffer1_Offset  ;load original offset from before
  1105.                ldy BackgroundColorCtrl  ;if this value is four or greater, it will be set
  1106.          checky
  1107.                bne SetBGColor           ;therefore use it as offset to background color
  1108.                ldy AreaType             ;otherwise use area type bits from area offset as offset
  1109. SetBGColor:    lday BackgroundColors,y   ;to background color instead
  1110.                stax VRAM_Buffer1+3,x
  1111.                ldan ++HIGH PPU_SPRPAL;++$3f                 ;set for sprite palette address
  1112.                stax VRAM_Buffer1,x       ;save to buffer
  1113.                ldan ++LOW PPU_SPRPAL;++$10
  1114.                stax VRAM_Buffer1+1,x
  1115.                ldan ++$04                 ;write length byte to buffer
  1116.                stax VRAM_Buffer1+2,x
  1117.                ldan ++$00                 ;now the null terminator
  1118.                stax VRAM_Buffer1+7,x
  1119.                txa                      ;move the buffer pointer ahead 7 bytes
  1120.                clc                      ;in case we want to write anything else later
  1121.                adcn ++$07
  1122.         endif
  1123. SetVRAMOffset: sta VRAM_Buffer1_Offset  ;store as new vram buffer offset
  1124.                rts
  1125.  
  1126. ;-------------------------------------------------------------------------------------
  1127.  
  1128. GetAlternatePalette1:
  1129.                lda AreaStyle            ;check for mushroom level style
  1130.                cmpn ++$01
  1131.                bne NoAltPal
  1132.                ldan ++$0b                 ;if found, load appropriate palette
  1133. SetVRAMAddr_B: sta VRAM_Buffer_AddrCtrl
  1134. NoAltPal:      jmp IncSubtask           ;now onto the next task
  1135.  
  1136. ;-------------------------------------------------------------------------------------
  1137.  
  1138. WriteTopStatusLine:
  1139.       ldan ++$00          ;select main status bar
  1140.       jsr WriteGameText ;output it
  1141.       jmp IncSubtask    ;onto the next task
  1142.  
  1143. ;-------------------------------------------------------------------------------------
  1144.  
  1145. WriteBottomStatusLine:
  1146.       jsr GetSBNybbles        ;write player's score and coin tally to screen
  1147.       ldx VRAM_Buffer1_Offset
  1148.       ldan ++$20                ;write address for world-area number on screen
  1149.       stax VRAM_Buffer1,x
  1150.       ldan ++$73
  1151.       stax VRAM_Buffer1+1,x
  1152.       ldan ++$03                ;write length for it
  1153.       stax VRAM_Buffer1+2,x
  1154.       ldy WorldNumber         ;first the world number
  1155.       iny
  1156.       tya
  1157.       stax VRAM_Buffer1+3,x
  1158.       ldan ++$28                ;next the dash
  1159.       stax VRAM_Buffer1+4,x
  1160.       ldy LevelNumber         ;next the level number
  1161.       iny                     ;increment for proper number display
  1162.       tya
  1163.       stax VRAM_Buffer1+5,x    
  1164.       ldan ++$00                ;put null terminator on
  1165.       stax VRAM_Buffer1+6,x
  1166.       txa                     ;move the buffer offset up by 6 bytes
  1167.       clc
  1168.       adcn ++$06
  1169.       sta VRAM_Buffer1_Offset
  1170.       jmp IncSubtask
  1171.  
  1172. ;-------------------------------------------------------------------------------------
  1173.  
  1174. DisplayTimeUp:
  1175.           lda GameTimerExpiredFlag  ;if game timer not expired, increment task
  1176.          checka
  1177.           beq NoTimeUp              ;control 2 tasks forward, otherwise, stay here
  1178.           ldan ++$00
  1179.           sta GameTimerExpiredFlag  ;reset timer expiration flag
  1180.           ldan ++$02                  ;output time-up screen to buffer
  1181.           jmp OutputInter
  1182. NoTimeUp: inci ScreenRoutineTask     ;increment control task 2 tasks forward
  1183.           jmp IncSubtask
  1184.  
  1185. ;-------------------------------------------------------------------------------------
  1186.  
  1187. DisplayIntermediate:
  1188.                lda OperMode                 ;check primary mode of operation
  1189.          checka
  1190.                beq NoInter                  ;if in title screen mode, skip this
  1191.                cmpn ++GameOverModeValue       ;are we in game over mode?
  1192.                beq GameOverInter            ;if so, proceed to display game over screen
  1193.                lda AltEntranceControl       ;otherwise check for mode of alternate entry
  1194.          checka
  1195.                bne NoInter                  ;and branch if found
  1196.                ldy AreaType                 ;check if we are on castle level
  1197.                cpyn ++$03                     ;and if so, branch (possibly residual)
  1198.                beq PlayerInter
  1199.                lda DisableIntermediate      ;if this flag is set, skip intermediate lives display
  1200.          checka
  1201.                bne NoInter                  ;and jump to specific task, otherwise
  1202. PlayerInter:   jsr DrawPlayer_Intermediate  ;put player in appropriate place for
  1203.                ldan ++$01                     ;lives display, then output lives display to buffer
  1204. OutputInter:   jsr WriteGameText
  1205.                jsr ResetScreenTimer
  1206.                ldan ++$00
  1207.                sta DisableScreenFlag        ;reenable screen output
  1208.                rts
  1209. GameOverInter: ldan ++$12                     ;set screen timer
  1210.                sta ScreenTimer
  1211.                ldan ++$03                     ;output game over screen to buffer
  1212.                jsr WriteGameText
  1213.                jmp IncModeTask_B
  1214. NoInter:       ldan ++$08                     ;set for specific task (AreaParserTaskControl) and leave
  1215.                sta ScreenRoutineTask
  1216.                rts
  1217.  
  1218. ;-------------------------------------------------------------------------------------
  1219.  
  1220. AreaParserTaskControl:
  1221.            inci DisableScreenFlag     ;turn off screen
  1222. TaskLoop:  jsr AreaParserTaskHandler ;render column set of current area
  1223.            lda AreaParserTaskNum     ;check number of tasks
  1224.          checka
  1225.            bne TaskLoop              ;if tasks still not all done, do another one
  1226.            deci ColumnSets            ;do we need to render more column sets?
  1227.            bpl OutputCol
  1228.            inci ScreenRoutineTask     ;if not, move on to the next task
  1229. OutputCol: ldan ++$06                  ;set vram buffer to output rendered column set
  1230.            sta VRAM_Buffer_AddrCtrl  ;on next NMI
  1231.            rts
  1232.  
  1233. ;-------------------------------------------------------------------------------------
  1234.  
  1235. ;$00 - vram buffer address table low
  1236. ;$01 - vram buffer address table high
  1237.  
  1238. DrawTitleScreen:
  1239.         ;jr $
  1240.             lda OperMode                 ;are we in title screen mode?
  1241.          checka
  1242.             bne IncModeTask_B            ;if not, exit
  1243.         if Z80
  1244. DrawTitleScreen_go
  1245.             ld hl,TitleScreen
  1246.             ld de,VRAM_Buffer1_Offset
  1247.             ld bc,TitleScreenDataSize ;0x13a = 314 (ёЄЁрээюх ўшёыю???)
  1248.             ldir
  1249.             ld d,b;0
  1250.         else
  1251.             ldan ++HIGH TitleScreenDataOffset  ;load address $1ec0 into
  1252.             sta PPU_ADDRESS              ;the vram address register
  1253.             ldan ++LOW TitleScreenDataOffset
  1254.             sta PPU_ADDRESS
  1255.             ldan ++$03                     ;put address $0300 into
  1256.             sta SCRATCHPAD+$01                      ;the indirect at $00
  1257.             ldyn ++$00
  1258.             sty SCRATCHPAD+$00
  1259.             lda PPU_DATA                 ;do one garbage read
  1260. OutputTScr: lda PPU_DATA                 ;get title screen from chr-rom
  1261.             stayindirect (SCRATCHPAD+$00),y                  ;store 256 bytes into buffer
  1262.             iny
  1263.             bne ChkHiByte                ;if not past 256 bytes, do not increment
  1264.             inci SCRATCHPAD+$01                      ;otherwise increment high byte of indirect
  1265. ChkHiByte:  lda SCRATCHPAD+$01                      ;check high byte?
  1266.             cmpn ++$04                     ;at $0400?
  1267.             bne OutputTScr               ;if not, loop back and do another
  1268.             cpyn ++$3a                     ;check if offset points past end of data
  1269.               cmpcy
  1270.             bcc OutputTScr               ;if not, loop back and do another
  1271.         endif
  1272.             ldan ++$05                     ;set buffer transfer control to $0300,
  1273.             jmp SetVRAMAddr_B            ;increment task and exit
  1274.  
  1275. ;-------------------------------------------------------------------------------------
  1276.  
  1277. ClearBuffersDrawIcon:
  1278.              lda OperMode               ;check game mode
  1279.          checka
  1280.              bne IncModeTask_B          ;if not title screen mode, leave
  1281.              ldxn ++$00                   ;otherwise, clear buffer space
  1282. TScrClear:   stax VRAM_Buffer1-1,x
  1283.              stax VRAM_Buffer1-1+$100,x ;??? яюўхьє Єръ ьэюую?
  1284.              dex
  1285.              bne TScrClear
  1286.              jsr DrawMushroomIcon       ;draw player select icon
  1287. IncSubtask:  inci ScreenRoutineTask      ;move onto next task
  1288.              rts
  1289.  
  1290. ;-------------------------------------------------------------------------------------
  1291.  
  1292. WriteTopScore:
  1293.                ldan ++$fa           ;run display routine to display top score on title
  1294.                jsr UpdateNumber
  1295. IncModeTask_B: inci OperMode_Task  ;move onto next mode
  1296.                rts
  1297.  
  1298. ;-------------------------------------------------------------------------------------
  1299.  
  1300. GameText:
  1301. TopStatusBarLine:
  1302.   .db $20, $43, $05,  $16, $0a, $1b, $12, $18 ; "MARIO"
  1303.   .db $20, $52, $0b,  $20, $18, $1b, $15, $0d ; "WORLD  TIME"
  1304.   .db $24, $24, $1d,  $12, $16, $0e
  1305.   .db $20, $68, $05,  $00, $24, $24, $2e, $29 ; score trailing digit and coin display
  1306.   .db $23, $c0,  $7f, $aa ; attribute table data, clears name table 0 to palette 2
  1307.   .db $23, $c2, $01,  $ea ; attribute table data, used for coin icon in status bar
  1308.   .db $ff ; end of data block
  1309.  
  1310. WorldLivesDisplay:
  1311.   .db $21, $cd, $07,  $24, $24 ; cross with spaces used on
  1312.   .db $29, $24, $24,  $24, $24 ; lives display
  1313.   .db $21, $4b, $09,  $20, $18 ; "WORLD  - " used on lives display
  1314.   .db $1b, $15, $0d, $24, $24, $28, $24
  1315.   .db $22, $0c,  $47, $24 ; possibly used to clear time up
  1316.   .db $23, $dc, $01,  $ba ; attribute table data for crown if more than 9 lives
  1317.   .db $ff
  1318.  
  1319. TwoPlayerTimeUp:
  1320.   .db $21, $cd, $05,  $16, $0a, $1b, $12, $18 ; "MARIO"
  1321. OnePlayerTimeUp:
  1322.   .db $22, $0c, $07,  $1d, $12, $16, $0e, $24, $1e, $19 ; "TIME UP"
  1323.   .db $ff
  1324.  
  1325. TwoPlayerGameOver:
  1326.   .db $21, $cd, $05,  $16, $0a, $1b, $12, $18 ; "MARIO"
  1327. OnePlayerGameOver:
  1328.   .db $22, $0b, $09,  $10, $0a, $16, $0e, $24 ; "GAME OVER"
  1329.   .db $18, $1f, $0e, $1b
  1330.   .db $ff
  1331.  
  1332. WarpZoneWelcome:
  1333.   .db $25, $84, $15,  $20, $0e, $15, $0c, $18, $16 ; "WELCOME TO WARP ZONE!"
  1334.   .db $0e, $24, $1d, $18, $24, $20, $0a, $1b, $19
  1335.   .db $24, $23, $18, $17, $0e, $2b
  1336.   .db $26, $25, $01,  $24         ; placeholder for left pipe
  1337.   .db $26, $2d, $01,  $24         ; placeholder for middle pipe
  1338.   .db $26, $35, $01,  $24         ; placeholder for right pipe
  1339.   .db $27, $d9,  $46, $aa         ; attribute data
  1340.   .db $27, $e1,  $45, $aa
  1341.   .db $ff
  1342.  
  1343. LuigiName:
  1344.   .db $15, $1e, $12, $10, $12    ; "LUIGI", no address or length
  1345.  
  1346. WarpZoneNumbers:
  1347.   .db $04, $03, $02, $00         ; warp zone numbers, note spaces on middle
  1348.   .db $24, $05, $24, $00         ; zone, partly responsible for
  1349.   .db $08, $07, $06, $00         ; the minus world
  1350.  
  1351. GameTextOffsets:
  1352.   .db TopStatusBarLine-GameText, TopStatusBarLine-GameText
  1353.   .db WorldLivesDisplay-GameText, WorldLivesDisplay-GameText
  1354.   .db TwoPlayerTimeUp-GameText, OnePlayerTimeUp-GameText
  1355.   .db TwoPlayerGameOver-GameText, OnePlayerGameOver-GameText
  1356.   .db WarpZoneWelcome-GameText, WarpZoneWelcome-GameText
  1357.  
  1358. WriteGameText:
  1359.                pha                      ;save text number to stack
  1360.                asl
  1361.                tay                      ;multiply by 2 and use as offset
  1362.                cpyn ++$04                 ;if set to do top status bar or world/lives display,
  1363.               cmpcy
  1364.                bcc LdGameText           ;branch to use current offset as-is
  1365.                cpyn ++$08                 ;if set to do time-up or game over,
  1366.               cmpcy
  1367.                bcc Chk2Players          ;branch to check players
  1368.                ldyn ++$08                 ;otherwise warp zone, therefore set offset
  1369. Chk2Players:   lda NumberOfPlayers      ;check for number of players
  1370.          checka
  1371.                bne LdGameText           ;if there are two, use current offset to also print name
  1372.                iny                      ;otherwise increment offset by one to not print name
  1373. LdGameText:    ldxy GameTextOffsets,y    ;get offset to message we want to print
  1374.                ldyn ++$00
  1375. GameTextLoop:  ldax GameText,x           ;load message data
  1376.                cmpn ++$ff                 ;check for terminator
  1377.                beq EndGameText          ;branch to end text if found
  1378.                stay VRAM_Buffer1,y       ;otherwise write data to buffer
  1379.                inx                      ;and increment increment
  1380.                iny
  1381.                bne GameTextLoop         ;do this for 256 bytes if no terminator found
  1382. EndGameText:   ldan ++$00                 ;put null terminator at end
  1383.                stay VRAM_Buffer1,y
  1384.                pla                      ;pull original text number from stack
  1385.                tax
  1386.                cmpn ++$04                 ;are we printing warp zone?
  1387.               cmpcy
  1388.                bcs PrintWarpZoneNumbers
  1389.                dex                      ;are we printing the world/lives display?
  1390.                bne CheckPlayerName      ;if not, branch to check player's name
  1391.                lda NumberofLives        ;otherwise, check number of lives
  1392.                clc                      ;and increment by one for display
  1393.                adcn ++$01
  1394.                cmpn ++10                  ;more than 9 lives?
  1395.               cmpcy
  1396.                bcc PutLives
  1397.               cmpcy
  1398.                sbcn ++10                  ;if so, subtract 10 and put a crown tile
  1399.                ldyn ++$9f                 ;next to the difference...strange things happen if
  1400.                sty VRAM_Buffer1+7       ;the number of lives exceeds 19
  1401. PutLives:      sta VRAM_Buffer1+8
  1402.                ldy WorldNumber          ;write world and level numbers (incremented for display)
  1403.                iny                      ;to the buffer in the spaces surrounding the dash
  1404.                sty VRAM_Buffer1+19
  1405.                ldy LevelNumber
  1406.                iny
  1407.                sty VRAM_Buffer1+21      ;we're done here
  1408.                rts
  1409.  
  1410. CheckPlayerName:
  1411.              lda NumberOfPlayers    ;check number of players
  1412.          checka
  1413.              beq ExitChkName        ;if only 1 player, leave
  1414.              lda CurrentPlayer      ;load current player
  1415.              dex                    ;check to see if current message number is for time up
  1416.              bne ChkLuigi
  1417.              ldy OperMode           ;check for game over mode
  1418.              cpyn ++GameOverModeValue
  1419.              beq ChkLuigi
  1420.              eorn ++%00000001         ;if not, must be time up, invert d0 to do other player
  1421. ChkLuigi:    lsr
  1422.              bcc ExitChkName        ;if mario is current player, do not change the name
  1423.              ldyn ++$04
  1424. NameLoop:    lday LuigiName,y        ;otherwise, replace "MARIO" with "LUIGI"
  1425.              stay VRAM_Buffer1+3,y
  1426.              dey
  1427.              bpl NameLoop           ;do this until each letter is replaced
  1428. ExitChkName: rts
  1429.  
  1430. PrintWarpZoneNumbers:
  1431. ;CY = 0???
  1432.             or a
  1433.              sbcn ++$04               ;subtract 4 and then shift to the left
  1434.              asl                    ;twice to get proper warp zone number
  1435.              asl                    ;offset
  1436.              tax
  1437.              ldyn ++$00
  1438. WarpNumLoop: ldax WarpZoneNumbers,x  ;print warp zone numbers into the
  1439.              stay VRAM_Buffer1+27,y  ;placeholders from earlier
  1440.              inx
  1441.              iny                    ;put a number in every fourth space
  1442.              iny
  1443.              iny
  1444.              iny
  1445.              cpyn ++$0c
  1446.               cmpcy
  1447.              bcc WarpNumLoop
  1448.              ldan ++$2c               ;load new buffer pointer at end of message
  1449.              jmp SetVRAMOffset
  1450.  
  1451. ;-------------------------------------------------------------------------------------
  1452.  
  1453. ResetSpritesAndScreenTimer:
  1454.          lda ScreenTimer             ;check if screen timer has expired
  1455.          checka
  1456.          bne NoReset                 ;if not, branch to leave
  1457.          jsr MoveAllSpritesOffscreen ;otherwise reset sprites now
  1458.  
  1459. ResetScreenTimer:
  1460.          ldan ++$07                    ;reset timer again
  1461.          sta ScreenTimer
  1462.          inci ScreenRoutineTask       ;move onto next task
  1463. NoReset: rts
  1464.  
  1465. ;-------------------------------------------------------------------------------------
  1466. ;$00 - temp vram buffer offset
  1467. ;$01 - temp metatile buffer offset
  1468. ;$02 - temp metatile graphics table offset
  1469. ;$03 - used to store attribute bits
  1470. ;$04 - used to determine attribute table row
  1471. ;$05 - used to determine attribute table column
  1472. ;$06 - metatile graphics table address low
  1473. ;$07 - metatile graphics table address high
  1474.  
  1475. RenderAreaGraphics:
  1476.            if Z80OPT4
  1477.             ;lda CurrentColumnPos         ;store LSB of where we're at
  1478.             ;andn ++$01
  1479.             ;sta SCRATCHPAD+$05
  1480.             ldy VRAM_Buffer2_Offset      ;store vram buffer offset
  1481.             ld ix,VRAM_Buffer2
  1482.             add ix,de
  1483.             ld a,(CurrentNTAddr_Low)        ;get current name table address we're supposed to render
  1484.             ld (ix+1),a;stay VRAM_Buffer2+1,y
  1485.             ld a,(CurrentNTAddr_High)
  1486.             ld (ix+0),a;stay VRAM_Buffer2,y
  1487.             ld a,++$9a                     ;store length byte of 26 here with d7 set
  1488.             ld (ix+2),a;stay VRAM_Buffer2+2,y         ;to increment by 32 (in columns)            
  1489.             ld bc,MetatileBuffer;ld c,0                    ;row
  1490.             ld hy,13
  1491. ;row=0..12
  1492. DrawMTLoop:
  1493. ;фы  Z80 эх эєцэю ЇюЁьшЁютрЄ№ рЄЁшсєЄ√ - тёх Єрщы√ єцх яхЁхъЁр°хэ√
  1494.         ;ld hl,MetatileBuffer
  1495.         ;add hl,bc
  1496.         ld a,(bc);(hl);ldax MetatileBuffer,x         ;get first metatile number ;%xx000000 - attribute table bits, %00xxxxxx - metatile number
  1497.             ld e,d;0
  1498.             add a,a ;*2
  1499.             rl e
  1500.             add a,a ;*4
  1501.             rl e ;e=0..3
  1502.             ld hl,AreaParserTaskNum        ;get current task number for level processing and
  1503.             bit 0,(hl) ;get current task number for level processing and mask out all but LSB
  1504.             jr nz,$+4
  1505.              add a,2 ;multiply by 2, then add to the tile offset so we can draw either side of the metatiles
  1506.             ld hl,MetatileGraphics_Low
  1507.             add hl,de ;e=0..3
  1508.             add a,(hl);l,(iy)
  1509.             inc hl
  1510.             inc hl
  1511.             inc hl
  1512.             inc hl
  1513.            ;ld e,a
  1514.            ;adc a,(hl)
  1515.            ;sub e
  1516.            ;ld h,a
  1517.            ;ld l,e ;23t
  1518.               ld h,(hl);(iy+MetatileGraphics_High-MetatileGraphics_Low) ;get address to graphics table from here
  1519.               jr nc,$+3
  1520.               inc h
  1521.               ld l,a ;20.5t
  1522.              ld a,(hl);ldayindirect (SCRATCHPAD+$06),y ;get first tile number (top left or top right) and store
  1523.              ld (ix+3),a
  1524.              inc hl
  1525.              ld a,(hl) ;now get the second (bottom left or bottom right) and store
  1526.              ld (ix+4),a;stax VRAM_Buffer2+4,x
  1527.              inc ix;inci SCRATCHPAD+$00                      ;increment vram buffer offset by 2
  1528.              inc ix;inci SCRATCHPAD+$00
  1529.             inc bc ;next row                        
  1530.             ;ld a,c
  1531.             dec hy ;cp $0d ;check for the bottom of the screen
  1532.             jp nz,DrawMTLoop ;jp c,DrawMTLoop               ;if not there yet, loop back
  1533.             ld b,d;0
  1534.  
  1535. ;шЄюую ёфтшэєыш vram buffer offset эр 13*2, ёфтшэхь х∙╕ эр 3 ш ёюїЁрэшь:
  1536.             ld (ix+3),b;0       ;put null terminator at end of data for name table
  1537.             ld a,(VRAM_Buffer2_Offset)
  1538.             add a,13*2+3
  1539.             ld (VRAM_Buffer2_Offset),a ;store new buffer offset
  1540.             ld hl,CurrentNTAddr_Low
  1541.             inc (hl);inci CurrentNTAddr_Low        ;increment name table address low
  1542.             ld a,(hl);lda CurrentNTAddr_Low        ;check current low byte
  1543.             and ++%00011111               ;if no wraparound, just skip this part
  1544.             jr nz,ExitDrawM
  1545.             ;ld a,++$80                     ;if wraparound occurs, make sure low byte stays
  1546.             ld (hl),$80;sta CurrentNTAddr_Low        ;just under the status bar
  1547.             ld hl,CurrentNTAddr_High
  1548.             ld a,(hl);lda CurrentNTAddr_High       ;and then invert d2 of the name table address high
  1549.             xor ++%00000100               ;to move onto the next appropriate name table
  1550.             ld (hl),a;sta CurrentNTAddr_High
  1551. ExitDrawM:  ;jmp SetVRAMCtrl              ;jump to set buffer to $0341 (VRAM_Buffer2) and leave
  1552.              ldan ++$06
  1553.              sta VRAM_Buffer_AddrCtrl ;set buffer to $0341 (VRAM_Buffer2) and leave
  1554.              ret
  1555.  
  1556.            else ;~Z80
  1557.  
  1558.             lda CurrentColumnPos         ;store LSB of where we're at
  1559.             andn ++$01
  1560.             sta SCRATCHPAD+$05          
  1561.             ldy VRAM_Buffer2_Offset      ;store vram buffer offset
  1562.              sty SCRATCHPAD+$00
  1563.             lda CurrentNTAddr_Low        ;get current name table address we're supposed to render
  1564.             stay VRAM_Buffer2+1,y
  1565.             lda CurrentNTAddr_High
  1566.             stay VRAM_Buffer2,y
  1567.             ldan ++$9a                     ;store length byte of 26 here with d7 set
  1568.             stay VRAM_Buffer2+2,y         ;to increment by 32 (in columns)
  1569.             ldan ++$00                     ;init attribute row
  1570.             sta SCRATCHPAD+$04 ;current attribute row
  1571.             tax ;x=row
  1572. ;x=row=0..12
  1573. DrawMTLoop:
  1574.             stx SCRATCHPAD+$01                      ;store init value of 0 or incremented offset for buffer
  1575.             ldax MetatileBuffer,x         ;get first metatile number, and mask out all but 2 MSB
  1576.             andn ++%11000000
  1577.             sta SCRATCHPAD+$03                      ;store attribute table bits here
  1578.             asl                          ;note that metatile format is:
  1579.             rol                          ;%xx000000 - attribute table bits,
  1580.             rol                          ;%00xxxxxx - metatile number
  1581.             tay                          ;rotate bits to d1-d0 and use as offset here            
  1582.             lday MetatileGraphics_Low,y   ;get address to graphics table from here
  1583.             sta SCRATCHPAD+$06
  1584.             lday MetatileGraphics_High,y
  1585.             sta SCRATCHPAD+$07
  1586.             ldax MetatileBuffer,x         ;get metatile number again
  1587.             asl                          ;multiply by 4 and use as tile offset
  1588.             asl
  1589.             sta SCRATCHPAD+$02
  1590.             lda AreaParserTaskNum        ;get current task number for level processing and
  1591.             andn ++%00000001               ;mask out all but LSB, then invert LSB, multiply by 2
  1592.             eorn ++%00000001               ;to get the correct column position in the metatile,
  1593.             asl                          ;then add to the tile offset so we can draw either side
  1594.             adci SCRATCHPAD+$02                      ;of the metatiles
  1595.             tay
  1596.             ldx SCRATCHPAD+$00                      ;use vram buffer offset from before as X
  1597.             ldayindirect (SCRATCHPAD+$06),y
  1598.             stax VRAM_Buffer2+3,x         ;get first tile number (top left or top right) and store
  1599.             iny
  1600.             ldayindirect (SCRATCHPAD+$06),y                  ;now get the second (bottom left or bottom right) and store
  1601.             stax VRAM_Buffer2+4,x
  1602.  
  1603.             ldy SCRATCHPAD+$04                      ;get current attribute row
  1604.             lda SCRATCHPAD+$05                      ;get LSB of current column where we're at, and
  1605.          checka
  1606.             bne RightCheck               ;branch if set (clear = left attrib, set = right)
  1607.             lda SCRATCHPAD+$01                      ;get current row we're rendering
  1608.             lsr                          ;branch if LSB set (clear = top left, set = bottom left)
  1609.             bcs LLeft
  1610.             roli SCRATCHPAD+$03                      ;rotate attribute bits 3 to the left
  1611.             roli SCRATCHPAD+$03                      ;thus in d1-d0, for upper left square
  1612.             roli SCRATCHPAD+$03
  1613.             jmp SetAttrib
  1614. RightCheck: lda SCRATCHPAD+$01                      ;get LSB of current row we're rendering
  1615.             lsr                          ;branch if set (clear = top right, set = bottom right)
  1616.             bcs NextMTRow
  1617.             lsri SCRATCHPAD+$03                      ;shift attribute bits 4 to the right
  1618.             lsri SCRATCHPAD+$03                      ;thus in d3-d2, for upper right square
  1619.             lsri SCRATCHPAD+$03
  1620.             lsri SCRATCHPAD+$03
  1621.             jmp SetAttrib
  1622. LLeft:      lsri SCRATCHPAD+$03                      ;shift attribute bits 2 to the right
  1623.             lsri SCRATCHPAD+$03                      ;thus in d5-d4 for lower left square
  1624. NextMTRow:  inci SCRATCHPAD+$04                      ;move onto next attribute row  
  1625. SetAttrib:  lday AttributeBuffer,y        ;get previously saved bits from before
  1626.             orai SCRATCHPAD+$03                      ;if any, and put new bits, if any, onto
  1627.             stay AttributeBuffer,y        ;the old, and store
  1628.              inci SCRATCHPAD+$00                      ;increment vram buffer offset by 2
  1629.              inci SCRATCHPAD+$00
  1630.             ldx SCRATCHPAD+$01                      ;get current gfx buffer row, and check for
  1631.             inx                          ;the bottom of the screen
  1632.             cpxn ++$0d
  1633.               cmpcy
  1634.             bcc DrawMTLoop               ;if not there yet, loop back
  1635.            
  1636. ;шЄюую ёфтшэєыш vram buffer offset эр 13*2, ёфтшэхь х∙╕ эр 3 ш ёюїЁрэшь:          
  1637.             ldy SCRATCHPAD+$00                      ;get current vram buffer offset, increment by 3
  1638.             iny                          ;(for name table address and length bytes)
  1639.             iny
  1640.             iny
  1641.             ldan ++$00
  1642.             stay VRAM_Buffer2,y           ;put null terminator at end of data for name table
  1643.             sty VRAM_Buffer2_Offset      ;store new buffer offset
  1644.            
  1645.             inci CurrentNTAddr_Low        ;increment name table address low
  1646.             lda CurrentNTAddr_Low        ;check current low byte
  1647.             andn ++%00011111               ;if no wraparound, just skip this part
  1648.             bne ExitDrawM
  1649.             ldan ++$80                     ;if wraparound occurs, make sure low byte stays
  1650.             sta CurrentNTAddr_Low        ;just under the status bar
  1651.             lda CurrentNTAddr_High       ;and then invert d2 of the name table address high
  1652.             eorn ++%00000100               ;to move onto the next appropriate name table
  1653.             sta CurrentNTAddr_High
  1654. ExitDrawM:  jmp SetVRAMCtrl              ;jump to set buffer to $0341 (VRAM_Buffer2) and leave
  1655.            endif
  1656.  
  1657. ;-------------------------------------------------------------------------------------
  1658.              if Z80OPT4==0 ;фы  Z80 эх эєцэю ЇюЁьшЁютрЄ№ рЄЁшсєЄ√ - тёх Єрщы√ єцх яхЁхъЁр°хэ√
  1659. ;$00 - temp attribute table address high (big endian order this time!)
  1660. ;$01 - temp attribute table address low
  1661. RenderAttributeTables:
  1662.              lda CurrentNTAddr_Low    ;get low byte of next name table address
  1663.              andn ++%00011111           ;to be written to, mask out all but 5 LSB,
  1664.              secsub                      ;subtract four
  1665.              sbcn ++$04
  1666.               cmpcy
  1667.         if Z80
  1668.         push af
  1669.         endif
  1670.              andn ++%00011111           ;mask out bits again and store
  1671.              sta SCRATCHPAD+$01
  1672.         if Z80
  1673.         pop af
  1674.         endif
  1675.              lda CurrentNTAddr_High   ;get high byte and branch if borrow not set
  1676.              bcs SetATHigh
  1677.              eorn ++%00000100           ;otherwise invert d2
  1678. SetATHigh:   andn ++%00000100           ;mask out all other bits
  1679.              oran ++$23                 ;add $2300 to the high byte and store
  1680.              sta SCRATCHPAD+$00
  1681.              lda SCRATCHPAD+$01                  ;get low byte - 4, divide by 4, add offset for
  1682.              lsr                      ;attribute table and store
  1683.              lsr
  1684.              adcn ++$c0                 ;we should now have the appropriate block of
  1685.              sta SCRATCHPAD+$01                  ;attribute table in our temp address
  1686.              ldxn ++$00
  1687.              ldy VRAM_Buffer2_Offset  ;get buffer offset
  1688. AttribLoop:  lda SCRATCHPAD+$00
  1689.              stay VRAM_Buffer2,y       ;store high byte of attribute table address
  1690.              lda SCRATCHPAD+$01
  1691.              clc                      ;get low byte, add 8 because we want to start
  1692.              adcn ++$08                 ;below the status bar, and store
  1693.              stay VRAM_Buffer2+1,y
  1694.              sta SCRATCHPAD+$01                  ;also store in temp again
  1695.              ldax AttributeBuffer,x    ;fetch current attribute table byte and store
  1696.              stay VRAM_Buffer2+3,y     ;in the buffer
  1697.              ldan ++$01
  1698.              stay VRAM_Buffer2+2,y     ;store length of 1 in buffer
  1699.              lsr
  1700.              stax AttributeBuffer,x    ;clear current byte in attribute buffer
  1701.              iny                      ;increment buffer offset by 4 bytes
  1702.              iny
  1703.              iny
  1704.              iny
  1705.              inx                      ;increment attribute offset and check to see
  1706.              cpxn ++$07                 ;if we're at the end yet
  1707.               cmpcy
  1708.              bcc AttribLoop
  1709.              stay VRAM_Buffer2,y       ;put null terminator at the end
  1710.              sty VRAM_Buffer2_Offset  ;store offset in case we want to do any more
  1711. SetVRAMCtrl: ldan ++$06
  1712.              sta VRAM_Buffer_AddrCtrl ;set buffer to $0341 (VRAM_Buffer2) and leave
  1713.              rts
  1714.             endif
  1715.  
  1716. ;-------------------------------------------------------------------------------------
  1717.  
  1718. ;$00 - used as temporary counter in ColorRotation
  1719.  
  1720. ColorRotatePalette:
  1721.         if Z80COINCYCLECOLOR
  1722.         db 0xa1,0xa1,0xa1,0x31,0xf1,0x31
  1723.         else
  1724.        .db $27, $27, $27, $17, $07, $17
  1725.         endif
  1726.  
  1727. BlankPalette:
  1728.        .db $3f, $0c, $04, $ff, $ff, $ff, $ff, $00
  1729.  
  1730. ;used based on area type
  1731. Palette3Data:
  1732.        .db $0f, $07, $12, $0f
  1733.        .db $0f, $07, $17, $0f
  1734.        .db $0f, $07, $17, $1c
  1735.        .db $0f, $07, $17, $00
  1736.  
  1737. ColorRotation:
  1738.               lda FrameCounter         ;get frame counter
  1739.               andn ++$07                 ;mask out all but three LSB
  1740.         if Z80COINCYCLECOLOR
  1741.                 ret nz
  1742.               ;lda AreaType             ;get area type
  1743.               ;asl                      ;multiply by 4 to get proper offset
  1744.               ;asl
  1745.               ;tay                      ;save as offset here
  1746.               ;lday Palette3Data,y       ;fetch palette to be written based on area type
  1747.                
  1748.               ldy ColorRotateOffset    ;get color cycling offset
  1749.               lday ColorRotatePalette,y
  1750.                 ld hl,(curpalette)
  1751.                 ld e,11*2
  1752.                 add hl,de
  1753.                 ld (hl),a
  1754.                 inc hl
  1755.                 ld (hl),a
  1756.              
  1757.               inci ColorRotateOffset    ;increment color cycling offset
  1758.               lda ColorRotateOffset
  1759.               cmpn ++$06                 ;check to see if it's still in range
  1760.               ;cmpcy
  1761.               ret c;bcc ExitColorRot         ;if so, branch to leave
  1762.               xor a;ldan ++$00
  1763.               sta ColorRotateOffset    ;otherwise, init to keep it in range
  1764.                 ret
  1765.         else
  1766.               bne ExitColorRot         ;branch if not set to zero to do this every eighth frame
  1767.               ldx VRAM_Buffer1_Offset  ;check vram buffer offset
  1768.               cpxn ++$31
  1769.               cmpcy
  1770.               bcs ExitColorRot         ;if offset over 48 bytes, branch to leave
  1771.               tay                      ;otherwise use frame counter's 3 LSB as offset here
  1772. GetBlankPal:  lday BlankPalette,y       ;get blank palette for palette 3
  1773.               stax VRAM_Buffer1,x       ;store it in the vram buffer
  1774.               inx                      ;increment offsets
  1775.               iny
  1776.               cpyn ++$08
  1777.               cmpcy
  1778.               bcc GetBlankPal          ;do this until all bytes are copied
  1779.               ldx VRAM_Buffer1_Offset  ;get current vram buffer offset
  1780.               ldan ++$03
  1781.               sta SCRATCHPAD+$00                  ;set counter here
  1782.               lda AreaType             ;get area type
  1783.               asl                      ;multiply by 4 to get proper offset
  1784.               asl
  1785.               tay                      ;save as offset here
  1786. GetAreaPal:   lday Palette3Data,y       ;fetch palette to be written based on area type
  1787.               stax VRAM_Buffer1+3,x     ;store it to overwrite blank palette in vram buffer
  1788.               iny
  1789.               inx
  1790.               deci SCRATCHPAD+$00                  ;decrement counter
  1791.               bpl GetAreaPal           ;do this until the palette is all copied
  1792.               ldx VRAM_Buffer1_Offset  ;get current vram buffer offset
  1793.               ldy ColorRotateOffset    ;get color cycling offset
  1794.               lday ColorRotatePalette,y
  1795.               stax VRAM_Buffer1+4,x     ;get and store current color in second slot of palette
  1796.               lda VRAM_Buffer1_Offset
  1797.               clc                      ;add seven bytes to vram buffer offset
  1798.               adcn ++$07
  1799.               sta VRAM_Buffer1_Offset
  1800.               inci ColorRotateOffset    ;increment color cycling offset
  1801.               lda ColorRotateOffset
  1802.               cmpn ++$06                 ;check to see if it's still in range
  1803.               cmpcy
  1804.               bcc ExitColorRot         ;if so, branch to leave
  1805.               ldan ++$00
  1806.               sta ColorRotateOffset    ;otherwise, init to keep it in range
  1807. ExitColorRot: rts                      ;leave
  1808.         endif
  1809.  
  1810. ;-------------------------------------------------------------------------------------
  1811. ;$00 - temp store for offset control bit
  1812. ;$01 - temp vram buffer offset
  1813. ;$02 - temp store for vertical high nybble in block buffer routine
  1814. ;$03 - temp adder for high byte of name table address
  1815. ;$04, $05 - name table address low/high
  1816. ;$06, $07 - block buffer address low/high
  1817.  
  1818. BlockGfxData:
  1819.        .db $45, $45, $47, $47
  1820.        .db $47, $47, $47, $47
  1821.        .db $57, $58, $59, $5a
  1822.        .db $24, $24, $24, $24 ;blank metatile
  1823.        .db y26, y26, y26, y26 ;water/lava ;blank metatile for water
  1824.  
  1825. RemoveCoin_Axe:
  1826.               ldyn ++$41                 ;set low byte so offset points to $0341
  1827.               ldan ++$03                 ;load offset for default blank metatile
  1828.               ldx AreaType             ;check area type
  1829.          checkx
  1830.               bne WriteBlankMT         ;if not water type, use offset
  1831.               ldan ++$04                 ;otherwise load offset for blank metatile used in water
  1832. WriteBlankMT: jsr PutBlockMetatile     ;do a sub to write blank metatile to vram buffer
  1833.               ldan ++$06
  1834.               sta VRAM_Buffer_AddrCtrl ;set vram address controller to $0341 (VRAM_Buffer2) and leave
  1835.               rts
  1836.  
  1837. ReplaceBlockMetatile:
  1838.        jsr WriteBlockMetatile    ;write metatile to vram buffer to replace block object
  1839.        inci Block_ResidualCounter ;increment unused counter (residual code)
  1840.        decx Block_RepFlag,x       ;decrement flag (residual code)
  1841.        rts                       ;leave
  1842.  
  1843. DestroyBlockMetatile:
  1844.        ldan ++$00       ;force blank metatile if branched/jumped to this point
  1845.  
  1846. WriteBlockMetatile:
  1847.              ldyn ++$03                ;load offset for blank metatile
  1848.              cmpn ++$00                ;check contents of A for blank metatile
  1849.              beq UseBOffset          ;branch if found (unconditional if branched from 8a6b)
  1850.              ldyn ++$00                ;load offset for brick metatile w/ line
  1851.              cmpn ++$58
  1852.              beq UseBOffset          ;use offset if metatile is brick with coins (w/ line)
  1853.              cmpn ++$51
  1854.              beq UseBOffset          ;use offset if metatile is breakable brick w/ line
  1855.              iny                     ;increment offset for brick metatile w/o line
  1856.              cmpn ++$5d
  1857.              beq UseBOffset          ;use offset if metatile is brick with coins (w/o line)
  1858.              cmpn ++$52
  1859.              beq UseBOffset          ;use offset if metatile is breakable brick w/o line
  1860.              iny                     ;if any other metatile, increment offset for empty block
  1861. UseBOffset:  tya                     ;put Y in A
  1862.              ldy VRAM_Buffer1_Offset ;get vram buffer offset
  1863.              iny                     ;move onto next byte
  1864.              jsr PutBlockMetatile    ;get appropriate block data and write to vram buffer
  1865. MoveVOffset: dey                     ;decrement vram buffer offset
  1866.              tya                     ;add 10 bytes to it
  1867.              clc
  1868.              adcn ++10
  1869.              jmp SetVRAMOffset       ;branch to store as new vram buffer offset
  1870.  
  1871. PutBlockMetatile:
  1872.             stx SCRATCHPAD+$00               ;store control bit from SprDataOffset_Ctrl
  1873.             sty SCRATCHPAD+$01               ;store vram buffer offset for next byte
  1874.             asl
  1875.             asl                   ;multiply A by four and use as X
  1876.             tax
  1877.             ldyn ++$20              ;load high byte for name table 0
  1878.             lda SCRATCHPAD+$06               ;get low byte of block buffer pointer
  1879.             cmpn ++$d0              ;check to see if we're on odd-page block buffer
  1880.               cmpcy
  1881.             bcc SaveHAdder        ;if not, use current high byte
  1882.             ldyn ++$24              ;otherwise load high byte for name table 1
  1883. SaveHAdder: sty SCRATCHPAD+$03               ;save high byte here
  1884.             andn ++$0f              ;mask out high nybble of block buffer pointer
  1885.             asl                   ;multiply by 2 to get appropriate name table low byte
  1886.             sta SCRATCHPAD+$04               ;and then store it here
  1887.             ldan ++$00
  1888.             sta SCRATCHPAD+$05               ;initialize temp high byte
  1889.             lda SCRATCHPAD+$02               ;get vertical high nybble offset used in block buffer routine
  1890.             clc
  1891.             adcn ++$20              ;add 32 pixels for the status bar
  1892.             asl
  1893.             roli SCRATCHPAD+$05               ;shift and rotate d7 onto d0 and d6 into carry
  1894.             asl
  1895.             roli SCRATCHPAD+$05               ;shift and rotate d6 onto d0 and d5 into carry
  1896.             adci SCRATCHPAD+$04               ;add low byte of name table and carry to vertical high nybble
  1897.             sta SCRATCHPAD+$04               ;and store here
  1898.             lda SCRATCHPAD+$05               ;get whatever was in d7 and d6 of vertical high nybble
  1899.             adcn ++$00              ;add carry
  1900.             clc
  1901.             adci SCRATCHPAD+$03               ;then add high byte of name table
  1902.             sta SCRATCHPAD+$05               ;store here
  1903.             ldy SCRATCHPAD+$01               ;get vram buffer offset to be used
  1904. RemBridge:  ldax BlockGfxData,x    ;write top left and top right
  1905.             stay VRAM_Buffer1+2,y  ;tile numbers into first spot
  1906.             ldax BlockGfxData+1,x
  1907.             stay VRAM_Buffer1+3,y
  1908.             ldax BlockGfxData+2,x  ;write bottom left and bottom
  1909.             stay VRAM_Buffer1+7,y  ;right tiles numbers into
  1910.             ldax BlockGfxData+3,x  ;second spot
  1911.             stay VRAM_Buffer1+8,y
  1912.             lda SCRATCHPAD+$04
  1913.             stay VRAM_Buffer1,y    ;write low byte of name table
  1914.             clc                   ;into first slot as read
  1915.             adcn ++$20              ;add 32 bytes to value
  1916.             stay VRAM_Buffer1+5,y  ;write low byte of name table
  1917.             lda SCRATCHPAD+$05               ;plus 32 bytes into second slot
  1918.             stay VRAM_Buffer1-1,y  ;write high byte of name
  1919.             stay VRAM_Buffer1+4,y  ;table address to both slots
  1920.             ldan ++$02
  1921.             stay VRAM_Buffer1+1,y  ;put length of 2 in
  1922.             stay VRAM_Buffer1+6,y  ;both slots
  1923.             ldan ++$00
  1924.             stay VRAM_Buffer1+9,y  ;put null terminator at end
  1925.             ldx SCRATCHPAD+$00               ;get offset control bit here
  1926.             rts                   ;and leave
  1927.  
  1928. ;-------------------------------------------------------------------------------------
  1929. ;METATILE GRAPHICS TABLE
  1930.  
  1931. MetatileGraphics_Low:
  1932.   .db LOW Palette0_MTiles, LOW Palette1_MTiles, LOW Palette2_MTiles, LOW Palette3_MTiles
  1933.  
  1934. MetatileGraphics_High:
  1935.   .db HIGH Palette0_MTiles, HIGH Palette1_MTiles, HIGH Palette2_MTiles, HIGH Palette3_MTiles
  1936.  
  1937.   if Z80ATTR
  1938. xa0=0xec
  1939. xa1=0xed
  1940. xa2=0xee
  1941. xa3=0xef
  1942. x27=0xf0
  1943. xba=0xf1
  1944. xbb=0xf2
  1945. x86=0xf3
  1946. x87=0xf4
  1947. x8a=0xf5
  1948. x8b=0xf6
  1949. x8e=0xf7
  1950. x8f=0xf8
  1951. y25=0xf9
  1952. y26=0xfa
  1953. y35=0xfb
  1954. y36=0xfc
  1955. y37=0xfd
  1956. y38=0xfe
  1957. w26=10+('X'-'A')
  1958. ;(water pipe bottom):
  1959. x91=10+('J'-'A');0x91
  1960. x92=10+('F'-'A');0x92
  1961. ;шыш фы  уюЁшчюэЄры№э√ї ЄЁєс ёЎхяшЄ№ фтр Єрщыр яю тхЁЄшърыш ш ■чрЄ№ ъръ юфшэ?
  1962.   else
  1963. xa0=0xa0
  1964. xa1=0xa1
  1965. xa2=0xa2
  1966. xa3=0xa3
  1967. x27=0x27
  1968. xba=0xba
  1969. xbb=0xbb
  1970. x86=0x86
  1971. x87=0x87
  1972. x8a=0x8a
  1973. x8b=0x8b
  1974. x8e=0x8e
  1975. x8f=0x8f
  1976. y25=0x25
  1977. y26=0x26
  1978. y35=0x35
  1979. y36=0x36
  1980. y37=0x37
  1981. y38=0x38
  1982. w26=0x26
  1983. x91=0x91
  1984. x92=0x92
  1985.   endif
  1986.  
  1987. Palette0_MTiles:
  1988.   .db $24, $24, $24, $24 ;blank
  1989.   .db $27, $27, $27, $27 ;black metatile
  1990.   .db $24, $24, $24, $35 ;bush left
  1991.   .db $36, $25, $37, $25 ;bush middle
  1992.   .db $24, $38, $24, $24 ;bush right
  1993.   .db $24, $30, $30, w26 ;mountain left
  1994.   .db w26, w26, $34, w26 ;mountain left bottom/middle center
  1995.   .db $24, $31, $24, $32 ;mountain middle top
  1996.   .db $33, w26, $24, $33 ;mountain right
  1997.   .db $34, w26, w26, w26 ;mountain right bottom
  1998.   .db w26, w26, w26, w26 ;mountain middle bottom
  1999.   .db $24, $c0, $24, $c0 ;bridge guardrail
  2000.   .db $24, $7f, $7f, $24 ;chain
  2001.   .db $b8, $ba, $b9, $bb ;tall tree top, top half
  2002.   .db $b8, $bc, $b9, $bd ;short tree top
  2003.   .db $ba, $bc, $bb, $bd ;tall tree top, bottom half
  2004.   .db $60, $64, $61, $65 ;warp pipe end left, points up
  2005.   .db $62, $66, $63, $67 ;warp pipe end right, points up
  2006.   .db $60, $64, $61, $65 ;decoration pipe end left, points up
  2007.   .db $62, $66, $63, $67 ;decoration pipe end right, points up
  2008.   .db $68, $68, $69, $69 ;pipe shaft left
  2009.   .db w26, w26, $6a, $6a ;pipe shaft right
  2010.   .db $4b, $4c, $4d, $4e ;tree ledge left edge
  2011.   .db $4d, $4f, $4d, $4f ;tree ledge middle
  2012.   .db $4d, $4e, $50, $51 ;tree ledge right edge
  2013.   .db $6b, $70, $2c, $2d ;mushroom left edge
  2014.   .db $6c, $71, $6d, $72 ;mushroom middle
  2015.   .db $6e, $73, $6f, $74 ;mushroom right edge
  2016.   .db $86, $8a, $87, $8b ;sideways pipe end top ;$1c?
  2017.   .db $88, $8c, $88, $8c ;sideways pipe shaft top
  2018.   .db $89, $8d, $69, $69 ;sideways pipe joint top
  2019.   .db $8e, $91, $8f, $92 ;sideways pipe end bottom
  2020.   .db w26, $93, w26, $93 ;sideways pipe shaft bottom
  2021.   .db $90, $94, $69, $69 ;sideways pipe joint bottom
  2022.   .db $a4, $e9, $ea, $eb ;seaplant ;яюўхьє т 0-щ ярышЄЁх???
  2023.   .db $24, $24, $24, $24 ;blank, used on bricks or blocks that are hit
  2024.   .db $24, $2f, $24, $3d ;flagpole ball
  2025.   .db $a2, $a2, $a3, $a3 ;flagpole shaft
  2026.   .db $24, $24, $24, $24 ;blank, used in conjunction with vines
  2027.  
  2028.  
  2029. Palette1_MTiles:
  2030.   .db xa2, xa2, xa3, xa3 ;vertical rope
  2031.   .db $99, $24, $99, $24 ;horizontal rope
  2032.   .db $24, xa2, $3e, $3f ;left pulley
  2033.   .db $5b, $5c, $24, xa3 ;right pulley
  2034.   .db $24, $24, $24, $24 ;blank used for balance rope
  2035.   .db $9d, $47, $9e, $47 ;castle top
  2036.   .db $47, $47, x27, x27 ;castle window left
  2037.   .db $47, $47, $47, $47 ;castle brick wall
  2038.   .db x27, x27, $47, $47 ;castle window right
  2039.   .db $a9, $47, $aa, $47 ;castle top w/ brick
  2040.   .db $9b, x27, $9c, x27 ;entrance top
  2041.   .db x27, x27, x27, x27 ;entrance bottom
  2042.   .db $52, $52, $52, $52 ;green ledge stump
  2043.   .db $80, xa0, $81, xa1 ;fence
  2044.   .db $be, $be, $bf, $bf ;tree trunk
  2045.   .db $75, xba, $76, xbb ;mushroom stump top
  2046.   .db xba, xba, xbb, xbb ;mushroom stump bottom
  2047.   .db $45, $47, $45, $47 ;breakable brick w/ line
  2048.   .db $47, $47, $47, $47 ;breakable brick
  2049.   .db $45, $47, $45, $47 ;breakable brick (not used)
  2050.   .db $b4, $b6, $b5, $b7 ;cracked rock terrain
  2051.   .db $45, $47, $45, $47 ;brick with line (power-up)
  2052.   .db $45, $47, $45, $47 ;brick with line (vine)
  2053.   .db $45, $47, $45, $47 ;brick with line (star)
  2054.   .db $45, $47, $45, $47 ;brick with line (coins)
  2055.   .db $45, $47, $45, $47 ;brick with line (1-up)
  2056.   .db $47, $47, $47, $47 ;brick (power-up)
  2057.   .db $47, $47, $47, $47 ;brick (vine)
  2058.   .db $47, $47, $47, $47 ;brick (star)
  2059.   .db $47, $47, $47, $47 ;brick (coins)
  2060.   .db $47, $47, $47, $47 ;brick (1-up)
  2061.   .db $24, $24, $24, $24 ;hidden block (1 coin)
  2062.   .db $24, $24, $24, $24 ;hidden block (1-up)
  2063.   .db $ab, $ac, $ad, $ae ;solid block (3-d block)
  2064.   .db $5d, $5e, $5d, $5e ;solid block (white wall)
  2065.   .db $c1, $24, $c1, $24 ;bridge
  2066.   .db $c6, $c8, $c7, $c9 ;bullet bill cannon barrel
  2067.   .db $ca, $cc, $cb, $cd ;bullet bill cannon top
  2068.   .db $2a, $2a, $40, $40 ;bullet bill cannon bottom
  2069.   .db $24, $24, $24, $24 ;blank used for jumpspring
  2070.   .db $24, $47, $24, $47 ;half brick used for jumpspring
  2071.   .db $82, $83, $84, $85 ;solid block (water level, green rock)
  2072.   .db $24, $47, $24, $47 ;half brick (???)
  2073.   .db x86, x8a, x87, x8b ;water pipe top
  2074.   .db x8e, x91, x8f, x92 ;water pipe bottom
  2075.   .db $24, $2f, $24, $3d ;flag ball (residual object) ;эх яхЁхъЁр°штрхь???
  2076.  
  2077. Palette2_MTiles:
  2078.   .db $24, $24, $24, y35 ;cloud left
  2079.   .db y36, y25, y37, y25 ;cloud middle
  2080.   .db $24, y38, $24, $24 ;cloud right
  2081.   .db $24, $24, $39, $24 ;cloud bottom left
  2082.   .db $3a, $24, $3b, $24 ;cloud bottom middle
  2083.   .db $3c, $24, $24, $24 ;cloud bottom right
  2084.   .db $41, y26, $41, y26 ;water/lava top
  2085.   .db y26, y26, y26, y26 ;water/lava
  2086.   .db $b0, $b1, $b2, $b3 ;cloud level terrain
  2087.   .db $77, $79, $77, $79 ;bowser's bridge
  2088.      
  2089. Palette3_MTiles:
  2090.   .db $53, $55, $54, $56 ;question block (coin)
  2091.   .db $53, $55, $54, $56 ;question block (power-up)
  2092.   .db $a5, $a7, $a6, $a8 ;coin
  2093.   .db $c2, $c4, $c3, $c5 ;underwater coin ;яюўхьє т 3-хщ ярышЄЁх???
  2094.   .db $57, $59, $58, $5a ;empty block
  2095.   .db $7b, $7d, $7c, $7e ;axe
  2096.  
  2097. ;-------------------------------------------------------------------------------------
  2098. ;VRAM BUFFER DATA FOR LOCATIONS IN PRG-ROM
  2099.  
  2100. WaterPaletteData:
  2101.   .db $3f, $00, $20
  2102.   .db $0f, $15, $12, $25  
  2103.   .db $0f, $3a, $1a, $0f
  2104.   .db $0f, $30, $12, $0f
  2105.   .db $0f, $27, $12, $0f
  2106.   .db $22, $16, $27, $18
  2107.   .db $0f, $10, $30, $27
  2108.   .db $0f, $16, $30, $27
  2109.   .db $0f, $0f, $30, $10
  2110.   .db $00
  2111.  
  2112. GroundPaletteData:
  2113.   .db $3f, $00, $20
  2114.   .db $0f, $29, $1a, $0f
  2115.   .db $0f, $36, $17, $0f
  2116.   .db $0f, $30, $21, $0f
  2117.   .db $0f, $27, $17, $0f
  2118.   .db $0f, $16, $27, $18
  2119.   .db $0f, $1a, $30, $27
  2120.   .db $0f, $16, $30, $27
  2121.   .db $0f, $0f, $36, $17
  2122.   .db $00
  2123.  
  2124. UndergroundPaletteData:
  2125.   .db $3f, $00, $20
  2126.   .db $0f, $29, $1a, $09
  2127.   .db $0f, $3c, $1c, $0f
  2128.   .db $0f, $30, $21, $1c
  2129.   .db $0f, $27, $17, $1c
  2130.   .db $0f, $16, $27, $18
  2131.   .db $0f, $1c, $36, $17
  2132.   .db $0f, $16, $30, $27
  2133.   .db $0f, $0c, $3c, $1c
  2134.   .db $00
  2135.  
  2136. CastlePaletteData:
  2137.   .db $3f, $00, $20
  2138.   .db $0f, $30, $10, $00
  2139.   .db $0f, $30, $10, $00
  2140.   .db $0f, $30, $16, $00
  2141.   .db $0f, $27, $17, $00
  2142.   .db $0f, $16, $27, $18
  2143.   .db $0f, $1c, $36, $17
  2144.   .db $0f, $16, $30, $27
  2145.   .db $0f, $00, $30, $10
  2146.   .db $00
  2147.  
  2148. DaySnowPaletteData:
  2149.   .db $3f, $00, $04
  2150.   .db $22, $30, $00, $10
  2151.   .db $00
  2152.  
  2153. NightSnowPaletteData:
  2154.   .db $3f, $00, $04
  2155.   .db $0f, $30, $00, $10
  2156.   .db $00
  2157.  
  2158. MushroomPaletteData:
  2159.   .db $3f, $00, $04
  2160.   .db $22, $27, $16, $0f
  2161.   .db $00
  2162.  
  2163. BowserPaletteData:
  2164.   .db $3f, $14, $04
  2165.   .db $0f, $1a, $30, $27
  2166.   .db $00
  2167.  
  2168. MarioThanksMessage:
  2169. ;"THANK YOU MARIO!"
  2170.   .db $25, $48, $10
  2171.   .db $1d, $11, $0a, $17, $14, $24
  2172.   .db $22, $18, $1e, $24
  2173.   .db $16, $0a, $1b, $12, $18, $2b
  2174.   .db $00
  2175.  
  2176. LuigiThanksMessage:
  2177. ;"THANK YOU LUIGI!"
  2178.   .db $25, $48, $10
  2179.   .db $1d, $11, $0a, $17, $14, $24
  2180.   .db $22, $18, $1e, $24
  2181.   .db $15, $1e, $12, $10, $12, $2b
  2182.   .db $00
  2183.  
  2184. MushroomRetainerSaved:
  2185. ;"BUT OUR PRINCESS IS IN"
  2186.   .db $25, $c5, $16
  2187.   .db $0b, $1e, $1d, $24, $18, $1e, $1b, $24
  2188.   .db $19, $1b, $12, $17, $0c, $0e, $1c, $1c, $24
  2189.   .db $12, $1c, $24, $12, $17
  2190. ;"ANOTHER CASTLE!"
  2191.   .db $26, $05, $0f
  2192.   .db $0a, $17, $18, $1d, $11, $0e, $1b, $24
  2193.   .db $0c, $0a, $1c, $1d, $15, $0e, $2b, $00
  2194.  
  2195. PrincessSaved1:
  2196. ;"YOUR QUEST IS OVER."
  2197.   .db $25, $a7, $13
  2198.   .db $22, $18, $1e, $1b, $24
  2199.   .db $1a, $1e, $0e, $1c, $1d, $24
  2200.   .db $12, $1c, $24, $18, $1f, $0e, $1b, $af
  2201.   .db $00
  2202.  
  2203. PrincessSaved2:
  2204. ;"WE PRESENT YOU A NEW QUEST."
  2205.   .db $25, $e3, $1b
  2206.   .db $20, $0e, $24
  2207.   .db $19, $1b, $0e, $1c, $0e, $17, $1d, $24
  2208.   .db $22, $18, $1e, $24, $0a, $24, $17, $0e, $20, $24
  2209.   .db $1a, $1e, $0e, $1c, $1d, $af
  2210.   .db $00
  2211.  
  2212. WorldSelectMessage1:
  2213. ;"PUSH BUTTON B"
  2214.   .db $26, $4a, $0d
  2215.   .db $19, $1e, $1c, $11, $24
  2216.   .db $0b, $1e, $1d, $1d, $18, $17, $24, $0b
  2217.   .db $00
  2218.  
  2219. WorldSelectMessage2:
  2220. ;"TO SELECT A WORLD"
  2221.   .db $26, $88, $11
  2222.   .db $1d, $18, $24, $1c, $0e, $15, $0e, $0c, $1d, $24
  2223.   .db $0a, $24, $20, $18, $1b, $15, $0d
  2224.   .db $00
  2225.  
  2226. ;-------------------------------------------------------------------------------------
  2227. ;$04 - address low to jump address
  2228. ;$05 - address high to jump address
  2229. ;$06 - jump address low
  2230. ;$07 - jump address high
  2231.  
  2232. ;a=function number
  2233. ;addresses of functions follow the jsr
  2234. JumpEngine:
  2235.         if Z80
  2236.         add a,a
  2237.         pop hl ;pull saved return address from stack
  2238.         add a,l
  2239.         ld l,a
  2240.         adc a,h
  2241.         sub l
  2242.         ld h,a
  2243.         ld a,(hl)
  2244.         inc hl
  2245.         ld h,(hl)
  2246.         ld l,a
  2247.          or a ;CY=0 ;??? ;эх яюьюурхЄ т 1-2
  2248.         jp (hl)
  2249.        
  2250.         else
  2251.        asl          ;shift bit from contents of A
  2252.        tay
  2253.        pla          ;pull saved return address from stack
  2254.        sta SCRATCHPAD+$04      ;save to indirect
  2255.        pla
  2256.        sta SCRATCHPAD+$05 ;($04..05) = return addr???
  2257.        iny ;y = A*2 + 1???
  2258.        ldayindirect (SCRATCHPAD+$04),y  ;load pointer from indirect
  2259.        sta SCRATCHPAD+$06      ;note that if an RTS is performed in next routine
  2260.        iny ;y = A*2 + 2???          ;it will return to the execution before the sub
  2261.        ldayindirect (SCRATCHPAD+$04),y  ;that called this routine
  2262.        sta SCRATCHPAD+$07
  2263.        jmpindirect (SCRATCHPAD+$06)    ;jump to the address we loaded
  2264.         endif
  2265.  
  2266. ;-------------------------------------------------------------------------------------
  2267.  
  2268. InitializeNameTables:
  2269.         if Z80==0
  2270.               lda PPU_STATUS            ;reset flip-flop
  2271.               lda Mirror_PPU_CTRL_REG1  ;load mirror of ppu reg $2000
  2272.               oran ++%00010000            ;set sprites for first 4k and background for second 4k
  2273.               andn ++%11110000            ;clear rest of lower nybble, leave higher alone
  2274.               jsr WritePPUReg1
  2275.         endif
  2276.               ldan ++$24                  ;set vram address to start of name table 1
  2277.               jsr WriteNTAddr
  2278.               ldan ++$20                  ;and then set it to name table 0
  2279. WriteNTAddr:
  2280.         if Z80
  2281.               ld hx,a
  2282.               ld lx,0
  2283.         else
  2284.               sta PPU_ADDRESS
  2285.               ldan ++$00
  2286.               sta PPU_ADDRESS
  2287.         endif
  2288.               ldxn ++$04                  ;clear name table with blank tile #24
  2289.               ldyn ++$c0
  2290.               ldan ++$24
  2291. InitNTLoop:  
  2292.         if Z80
  2293.               ld (ix),a
  2294.               inc ix
  2295.         else
  2296.               sta PPU_DATA              ;count out exactly 768 tiles
  2297.         endif
  2298.               dey
  2299.               bne InitNTLoop
  2300.               dex
  2301.               bne InitNTLoop
  2302.               ldyn ++64                   ;now to clear the attribute table (with zero this time)
  2303.               txa
  2304.               sta VRAM_Buffer1_Offset   ;init vram buffer 1 offset
  2305.               sta VRAM_Buffer1          ;init vram buffer 1
  2306. InitATLoop:  
  2307.         if Z80
  2308.               ld (ix),a
  2309.               inc ix
  2310.         else
  2311.               sta PPU_DATA
  2312.         endif
  2313.               dey
  2314.               bne InitATLoop
  2315.               sta HorizontalScroll      ;reset scroll variables
  2316.               sta VerticalScroll
  2317.               jmp InitScroll            ;initialize scroll registers to zero
  2318.  
  2319. ;-------------------------------------------------------------------------------------
  2320. ;$00 - temp joypad bit
  2321.  
  2322. ;bit - button (ZX key)
  2323. ;7 - A (A)
  2324. ;6 - B (S)
  2325. ;5 - Select (Space)
  2326. ;4 - Start (Enter)
  2327. ;3 - Up (7)
  2328. ;2 - Down (6)
  2329. ;1 - Left (5)
  2330. ;0 - Right (8)
  2331. ReadJoypads:
  2332.               ldan ++$01               ;reset and clear strobe of joypad ports
  2333.               sta JOYPAD_PORT
  2334.               lsr
  2335.               tax                    ;start with joypad 1's port
  2336.               sta JOYPAD_PORT
  2337.               jsr ReadPortBits
  2338.               inx                    ;increment for joypad 2's port
  2339. ReadPortBits:
  2340.         if Z80
  2341.         push bc
  2342.         if OSCALLS
  2343.         OS_GETKEYMATRIX ;out: bcdehlix = яюыєЁ ф√ cs...space
  2344.         else
  2345.         ld bc,0x7ffe
  2346.         in a,(c)
  2347.         ld lx,a  ;lx=%???bnmS_
  2348.         ld b,0xbf
  2349.         in a,(c)
  2350.         ld hx,a  ;hx=%???hjklE
  2351.         ld b,0xdf
  2352.         in l,(c)  ;l=%???yuiop
  2353.         ld b,0xef
  2354.         in h,(c)  ;h=%???67890
  2355.         ld b,0xf7
  2356.         in e,(c)  ;e=%???54321
  2357.         ld b,0xfb
  2358.         in d,(c)  ;d=%???trewq
  2359.         ld a,0xfd
  2360.         in a,(0xfe);c=%???gfdsa
  2361.         ld b,c;0xfe
  2362.         in b,(c)  ;b=%???vcxzC
  2363.         ld c,a
  2364.         endif
  2365.         ld a,lx
  2366.         or b
  2367.         rra
  2368.         jp nc,quit
  2369.         if DEMO
  2370.          bit 3,b ;'c'
  2371.          call z,democontinue
  2372.          bit 2,c ;'d'
  2373.          call z,demooff
  2374.         endif
  2375.         rr c ;'a'
  2376.         rla ;A
  2377.         rr c ;'s'
  2378.         rla ;B
  2379.         ld c,lx
  2380.         rr c ;'Space'
  2381.         rla ;Select
  2382.         ld c,hx
  2383.         rr c ;'Enter'
  2384.         rla ;Start
  2385.         add a,a
  2386.         bit 3,h ;7
  2387.         jr z,$+3
  2388.         inc a ;Up
  2389.         add a,a
  2390.         bit 4,h ;6
  2391.         jr z,$+3
  2392.         inc a ;Down
  2393.         add a,a
  2394.         bit 4,e ;5
  2395.         jr z,$+3
  2396.         inc a ;Left
  2397.         add a,a
  2398.         bit 2,h ;8
  2399.         jr z,$+3
  2400.         inc a ;Right
  2401.         cpl
  2402.         if DEMO
  2403.          pop de ;x = joypad number
  2404.          push de
  2405.          dec e ;(фы  joy1/2)
  2406.         push bc
  2407.         call nz,readdemo ;юэю цх writedemo (фы  joy2)
  2408.         pop bc
  2409.         push af
  2410.          bit 4,b ;'v'
  2411.          call z,savedemo
  2412.         pop af
  2413.         endif
  2414.         ld d,0
  2415.         pop bc ;ld bc,0 ;x = joypad number
  2416.         else
  2417.  
  2418.               ldyn ++$08
  2419. PortLoop:     pha                    ;push previous bit onto stack
  2420.               ldax JOYPAD_PORT,x      ;read current bit on joypad port
  2421.               sta SCRATCHPAD+$00                ;check d1 and d0 of port output
  2422.               lsr                    ;this is necessary on the old
  2423.               orai SCRATCHPAD+$00                ;famicom systems in japan
  2424.               lsr
  2425.               ;pla                    ;read bits from stack
  2426.               ;rol                    ;rotate bit from carry flag
  2427.                plarol
  2428.               dey
  2429.               bne PortLoop           ;count down bits left
  2430.         endif
  2431.               stax SavedJoypadBits,x  ;save controller status here always
  2432.               pha
  2433.               andn ++%00110000         ;check for select or start
  2434.               andx JoypadBitMask,x    ;if neither saved state nor current state
  2435.               beq Save8Bits          ;have any of these two set, branch
  2436.               pla
  2437.               andn ++%11001111         ;otherwise store without select
  2438.               stax SavedJoypadBits,x  ;or start bits and leave
  2439.               rts
  2440. Save8Bits:    pla
  2441.               stax JoypadBitMask,x    ;save with all bits in another place and leave ;шёяюы№чєхЄё  Єюы№ъю т ¤Єющ яЁюЎхфєЁх
  2442.               rts
  2443.  
  2444. ;-------------------------------------------------------------------------------------
  2445. ;$00 - vram buffer address table low
  2446. ;$01 - vram buffer address table high
  2447.  
  2448. ;т сєЇхЁх:
  2449. ;addrH, addrL, [SRLLLLLL (S=inc32, R=repeat, L=length),] S0BBBBBB?
  2450.         if Z80
  2451. UpdateScreen:  
  2452.         ld hl,(SCRATCHPAD+$00)
  2453. UpdateScreen0:  
  2454.         ld a,(hl)
  2455.         or a
  2456.         ret z
  2457.                  ;cp 0x40
  2458.                  ;jr nc,$ ;ъюёЄ√ы№ - яюўхьє т яюЄюъх чэрўхэш  $42???
  2459.                 ld d,a
  2460.                 inc hl
  2461.                 ld e,(hl)           ;load next byte (second)
  2462.                 inc hl
  2463.                 ld a,(hl)            ;load next byte (third)
  2464.                 ex de,hl
  2465.                add a,a
  2466.                 ld c,32
  2467.                 jr c,$+4
  2468.                 ld c,1 ;if d7 of third byte was clear, ppu will only increment by 1
  2469.                add a,a
  2470.                jr nc,GetLength             ;if d6 of third byte was clear, do not repeat byte
  2471.                srl a
  2472.                rra
  2473.                 ld lx,a
  2474.                inc de
  2475.                 ld a,(de)
  2476. RepeatByte0:
  2477.                 ld (hl),a
  2478.                 add hl,bc
  2479.                 dec lx
  2480.                jp nz,RepeatByte0
  2481.                jp OutputToVRAM_q
  2482. GetLength:
  2483. ;CY=0
  2484.                 rra                       ;shift back to the right to get proper length
  2485.                 rra                      ;note that d1 will now be in carry
  2486.                 ld lx,a
  2487. OutputToVRAM0:
  2488.                 inc de
  2489.                 ld a,(de)
  2490.                 ld (hl),a
  2491.                 add hl,bc
  2492.                 dec lx
  2493.                jp nz,OutputToVRAM0
  2494. OutputToVRAM_q
  2495.                 ex de,hl
  2496.                ld d,b;0
  2497.                inc hl
  2498.                jp UpdateScreen0
  2499.         else
  2500. WriteBufferToScreen:
  2501. ;a=addrH
  2502. ;y=0
  2503.                sta PPU_ADDRESS           ;store high byte of vram address
  2504.                iny
  2505.                ldayindirect (SCRATCHPAD+$00),y               ;load next byte (second)
  2506.                sta PPU_ADDRESS           ;store low byte of vram address
  2507.                iny
  2508.                ldayindirect (SCRATCHPAD+$00),y               ;load next byte (third)
  2509.                asl                       ;shift to left and save in stack
  2510.                pha
  2511.                lda Mirror_PPU_CTRL_REG1  ;load mirror of $2000,
  2512.                oran ++%00000100            ;set ppu to increment by 32 by default
  2513.                bcs SetupWrites           ;if d7 of third byte was clear, ppu will
  2514.                andn ++%11111011            ;only increment by 1
  2515. SetupWrites:   jsr WritePPUReg1          ;write to register
  2516.                pla                       ;pull from stack and shift to left again
  2517.                asl
  2518.                bcc GetLength             ;if d6 of third byte was clear, do not repeat byte
  2519.                oran ++%00000010            ;otherwise set d1 and increment Y
  2520.                iny
  2521. GetLength:     lsr                       ;shift back to the right to get proper length
  2522.                lsr                       ;note that d1 will now be in carry
  2523.                tax
  2524. OutputToVRAM:  bcs RepeatByte            ;if carry set, repeat loading the same byte
  2525.                iny                       ;otherwise increment Y to load next byte
  2526. RepeatByte:    ldayindirect (SCRATCHPAD+$00),y               ;load more data from buffer and write to vram
  2527.                sta PPU_DATA
  2528.                dex                       ;done writing?
  2529.                bne OutputToVRAM
  2530.                sec          
  2531.                tya ;a=end shift
  2532.                adci SCRATCHPAD+$00                   ;add end length plus one to the indirect at $00
  2533.                sta SCRATCHPAD+$00                   ;to allow this routine to read another set of updates
  2534.                ldan ++$00
  2535.                adci SCRATCHPAD+$01
  2536.                sta SCRATCHPAD+$01
  2537.                ldan ++$3f                  ;sets vram address to $3f00 (ярышЄЁр Їюэр 16 срщЄ, ярышЄЁр ёяЁрщЄют 16 срщЄ) ;чрўхь???
  2538.                sta PPU_ADDRESS
  2539.                ldan ++$00
  2540.                sta PPU_ADDRESS
  2541.                sta PPU_ADDRESS           ;then reinitializes it for some reason ;чрўхь ЄхяхЁ№ т 0???
  2542.                sta PPU_ADDRESS
  2543. UpdateScreen:  
  2544.                ldx PPU_STATUS            ;reset flip-flop
  2545.                ldyn ++$00                  ;load first byte from indirect as a pointer
  2546.                ldayindirect (SCRATCHPAD+$00),y  
  2547.          checka
  2548.                bne WriteBufferToScreen   ;if byte is zero we have no further updates to make here
  2549.         endif
  2550. InitScroll:    sta PPU_SCROLL_REG_H        ;store contents of A into scroll registers
  2551.                sta PPU_SCROLL_REG_V        ;and end whatever subroutine led us here
  2552.                rts
  2553.  
  2554. ;-------------------------------------------------------------------------------------
  2555.  
  2556.         if Z80==0
  2557. WritePPUReg1:
  2558.                sta PPU_CTRL_REG1         ;write contents of A to PPU register 1
  2559.                sta Mirror_PPU_CTRL_REG1  ;and its mirror
  2560.                rts
  2561.         endif
  2562.  
  2563. ;-------------------------------------------------------------------------------------
  2564. ;$00 - used to store status bar nybbles
  2565. ;$02 - used as temp vram offset
  2566. ;$03 - used to store length of status bar number
  2567.  
  2568. ;status bar name table offset and length data
  2569. StatusBarData:
  2570.       .db $f0, $06 ; top score display on title screen
  2571.       .db $62, $06 ; player score
  2572.       .db $62, $06
  2573.       .db $6d, $02 ; coin tally
  2574.       .db $6d, $02
  2575.       .db $7a, $03 ; game timer
  2576.  
  2577. StatusBarOffset:
  2578.       .db $06, $0c, $12, $18, $1e, $24
  2579.  
  2580. PrintStatusBarNumbers:
  2581.       sta SCRATCHPAD+$00            ;store player-specific offset
  2582.       jsr OutputNumbers  ;use first nybble to print the coin display
  2583.       lda SCRATCHPAD+$00            ;move high nybble to low
  2584.       lsr                ;and print to score display
  2585.       lsr
  2586.       lsr
  2587.       lsr
  2588.  
  2589. OutputNumbers:
  2590.              clc                      ;add 1 to low nybble
  2591.              adcn ++$01
  2592.              andn ++%00001111           ;mask out high nybble
  2593.              cmpn ++$06
  2594.               cmpcy
  2595.              bcs ExitOutputN
  2596.              pha                      ;save incremented value to stack for now and
  2597.              asl                      ;shift to left and use as offset
  2598.              tay
  2599.              ldx VRAM_Buffer1_Offset  ;get current buffer pointer
  2600.              ldan ++$20                 ;put at top of screen by default
  2601.              cpyn ++$00                 ;are we writing top score on title screen?
  2602.              bne SetupNums
  2603.              ldan ++$22                 ;if so, put further down on the screen
  2604. SetupNums:   stax VRAM_Buffer1,x
  2605.              lday StatusBarData,y      ;write low vram address and length of thing
  2606.              stax VRAM_Buffer1+1,x     ;we're printing to the buffer
  2607.              lday StatusBarData+1,y
  2608.              stax VRAM_Buffer1+2,x
  2609.              sta SCRATCHPAD+$03                  ;save length byte in counter
  2610.              stx SCRATCHPAD+$02                  ;and buffer pointer elsewhere for now
  2611.              pla                      ;pull original incremented value from stack
  2612.              tax
  2613.              ldax StatusBarOffset,x    ;load offset to value we want to write
  2614.              secsub
  2615.              sbcy StatusBarData+1,y    ;subtract from length byte we read before
  2616.              tay                      ;use value as offset to display digits
  2617.              ldx SCRATCHPAD+$02
  2618. DigitPLoop:  lday DisplayDigits,y      ;write digits to the buffer
  2619.              stax VRAM_Buffer1+3,x    
  2620.              inx
  2621.              iny
  2622.              deci SCRATCHPAD+$03                  ;do this until all the digits are written
  2623.              bne DigitPLoop
  2624.              ldan ++$00                 ;put null terminator at end
  2625.              stax VRAM_Buffer1+3,x
  2626.              inx                      ;increment buffer pointer by 3
  2627.              inx
  2628.              inx
  2629.              stx VRAM_Buffer1_Offset  ;store it in case we want to use it again
  2630. ExitOutputN: rts
  2631.  
  2632. ;-------------------------------------------------------------------------------------
  2633.  
  2634. ;y=ёьх∙хэшх рфЁхёр
  2635. DigitsMathRoutine:
  2636.             lda OperMode              ;check mode of operation
  2637.             cmpn ++TitleScreenModeValue
  2638.             beq EraseDMods            ;if in title screen mode, branch to lock score
  2639.             ldxn ++$05
  2640. AddModLoop: ldax DigitModifier,x       ;load digit amount to increment
  2641.             clc
  2642.             adcy DisplayDigits,y       ;add to current digit
  2643.             bmi BorrowOne             ;if result is a negative number, branch to subtract
  2644.             cmpn ++10
  2645.               cmpcy
  2646.             bcs CarryOne              ;if digit greater than $09, branch to add
  2647. StoreNewD:  stay DisplayDigits,y       ;store as new score or game timer digit
  2648.             dey                       ;move onto next digits in score or game timer
  2649.             dex                       ;and digit amounts to increment
  2650.             bpl AddModLoop            ;loop back if we're not done yet
  2651. EraseDMods: ldan ++$00                  ;store zero here
  2652.             ldxn ++$06                  ;start with the last digit
  2653. EraseMLoop: stax DigitModifier-1,x     ;initialize the digit amounts to increment
  2654.             dex
  2655.             bpl EraseMLoop            ;do this until they're all reset, then leave
  2656.             rts
  2657. BorrowOne:  decx DigitModifier-1,x     ;decrement the previous digit, then put $09 in
  2658.             ldan ++$09                  ;the game timer digit we're currently on to "borrow
  2659.          checka
  2660.             bne StoreNewD             ;the one", then do an unconditional branch back
  2661. CarryOne:   secsub    ;яхЁхэюё т т√ўшЄрэшш шэтхЁёэ√щ???                   ;subtract ten from our digit to make it a
  2662.             sbcn ++10                   ;proper BCD number, then increment the digit
  2663.             incx DigitModifier-1,x     ;preceding current digit to "carry the one" properly
  2664.             jmp StoreNewD             ;go back to just after we branched here
  2665.  
  2666. ;-------------------------------------------------------------------------------------
  2667.  
  2668. UpdateTopScore:
  2669.       ldxn ++$05          ;start with mario's score
  2670.       jsr TopScoreCheck
  2671.       ldxn ++$0b          ;now do luigi's score
  2672.  
  2673. TopScoreCheck:
  2674.               ldyn ++$05                 ;start with the lowest digit
  2675.               secsub           ;яхЁхэюё т т√ўшЄрэшш шэтхЁёэ√щ???
  2676. GetScoreDiff: ldax PlayerScoreDisplay,x ;subtract each player digit from each high score digit
  2677.         if Z80
  2678.         secsub
  2679.         endif
  2680.               sbcy TopScoreDisplay,y    ;from lowest to highest, if any top score digit exceeds
  2681.               dex                      ;any player digit, borrow will be set until a subsequent
  2682.               dey                      ;subtraction clears it (player digit is higher than top)
  2683.               bpl GetScoreDiff      
  2684.               cmpcy
  2685.               bcc NoTopSc              ;check to see if borrow is still set, if so, no new high score
  2686.               inx                      ;increment X and Y once to the start of the score
  2687.               iny
  2688. CopyScore:    ldax PlayerScoreDisplay,x ;store player's score digits into high score memory area
  2689.               stay TopScoreDisplay,y
  2690.               inx
  2691.               iny
  2692.               cpyn ++$06                 ;do this until we have stored them all
  2693.               cmpcy
  2694.               bcc CopyScore
  2695. NoTopSc:      rts
  2696.  
  2697. ;-------------------------------------------------------------------------------------
  2698.  
  2699. DefaultSprOffsets:
  2700.       .db $04, $30, $48, $60, $78, $90, $a8, $c0
  2701.       .db $d8, $e8, $24, $f8, $fc, $28, $2c
  2702.  
  2703. Sprite0Data:
  2704.       .db $18, $ff, $23, $58
  2705.  
  2706. ;-------------------------------------------------------------------------------------
  2707.  
  2708. InitializeGame:
  2709.              ldyn16 ++GAMEDATA_end-AREADATA;++$6f              ;clear all memory as in initialization procedure,
  2710.              jsr InitializeMemory  ;but this time, clear only as far as $076f
  2711.              ldyn ++$1f
  2712. ClrSndLoop:  stay SoundMemory,y     ;clear out memory used
  2713.              dey                   ;by the sound engines
  2714.              bpl ClrSndLoop
  2715.              ldan ++$18              ;set demo timer
  2716.              sta DemoTimer
  2717.              jsr LoadAreaPointer
  2718.  
  2719. InitializeArea:
  2720.                ldyn16 ++AREADATA_end-AREADATA;++$4b                 ;clear all memory again, only as far as $074b
  2721.                jsr InitializeMemory     ;this is only necessary if branching from
  2722.                ldxn ++$21
  2723.                ldan ++$00
  2724. ClrTimersLoop: stax Timers,x             ;clear out memory between
  2725.                dex                      ;$0780 and $07a1
  2726.                bpl ClrTimersLoop
  2727.                lda HalfwayPage
  2728.                ldy AltEntranceControl   ;if AltEntranceControl not set, use halfway page, if any found
  2729.          checky
  2730.                beq StartPage
  2731.                lda EntrancePage         ;otherwise use saved entry page number here
  2732. StartPage:     sta ScreenLeft_PageLoc   ;set as value here
  2733.                sta CurrentPageLoc       ;also set as current page
  2734.                sta BackloadingFlag      ;set flag here if halfway page or saved entry page number found
  2735.                jsr GetScreenPosition    ;get pixel coordinates for screen borders
  2736.                ldyn ++$20                 ;if on odd numbered page, use $2480 as start of rendering
  2737.                andn ++%00000001           ;otherwise use $2080, this address used later as name table
  2738.                beq SetInitNTHigh        ;address for rendering of game area
  2739.                ldyn ++$24
  2740. SetInitNTHigh: sty CurrentNTAddr_High   ;store name table address
  2741.                ldyn ++$80
  2742.                sty CurrentNTAddr_Low
  2743.                asl                      ;store LSB of page number in high nybble
  2744.                asl                      ;of block buffer column position
  2745.                asl
  2746.                asl
  2747.                sta BlockBufferColumnPos
  2748.                deci AreaObjectLength     ;set area object lengths for all empty
  2749.                deci AreaObjectLength+1
  2750.                deci AreaObjectLength+2
  2751.                ldan ++$0b                 ;set value for renderer to update 12 column sets
  2752.                sta ColumnSets           ;12 column sets = 24 metatile columns = 1 1/2 screens
  2753.                jsr GetAreaDataAddrs     ;get enemy and level addresses and load header
  2754.                lda PrimaryHardMode      ;check to see if primary hard mode has been activated
  2755.          checka
  2756.                bne SetSecHard           ;if so, activate the secondary no matter where we're at
  2757.                lda WorldNumber          ;otherwise check world number
  2758.                cmpn ++World5              ;if less than 5, do not activate secondary
  2759.               cmpcy
  2760.                bcc CheckHalfway
  2761.                bne SetSecHard           ;if not equal to, then world HIGH  5, thus activate
  2762.                lda LevelNumber          ;otherwise, world 5, so check level number
  2763.                cmpn ++Level3              ;if 1 or 2, do not set secondary hard mode flag
  2764.               cmpcy
  2765.                bcc CheckHalfway
  2766. SetSecHard:    inci SecondaryHardMode    ;set secondary hard mode flag for areas 5-3 and beyond
  2767. CheckHalfway:  lda HalfwayPage
  2768.          checka
  2769.                beq DoneInitArea
  2770.                ldan ++$02                 ;if halfway page set, overwrite start position from header
  2771.                sta PlayerEntranceCtrl
  2772. DoneInitArea:  ldan ++Silence             ;silence music
  2773.                sta AreaMusicQueue
  2774.                ldan ++$01                 ;disable screen output
  2775.                sta DisableScreenFlag
  2776.                inci OperMode_Task        ;increment one of the modes
  2777.                rts
  2778.  
  2779. ;-------------------------------------------------------------------------------------
  2780.  
  2781. PrimaryGameSetup:
  2782.       ldan ++$01
  2783.       sta FetchNewGameTimerFlag   ;set flag to load game timer from header
  2784.       sta PlayerSize              ;set player's size to small
  2785.       ldan ++$02
  2786.       sta NumberofLives           ;give each player three lives
  2787.       sta OffScr_NumberofLives
  2788.  
  2789. SecondaryGameSetup:
  2790.              ldan ++$00
  2791.              sta DisableScreenFlag     ;enable screen output
  2792.              tay
  2793. ClearVRLoop: stay VRAM_Buffer1-1,y      ;clear buffer at $0300-$03ff
  2794.              iny
  2795.              bne ClearVRLoop
  2796.              sta GameTimerExpiredFlag  ;clear game timer exp flag
  2797.              sta DisableIntermediate   ;clear skip lives display flag
  2798.              sta BackloadingFlag       ;clear value here
  2799.              ldan ++$ff
  2800.              sta BalPlatformAlignment  ;initialize balance platform assignment flag
  2801.              lda ScreenLeft_PageLoc    ;get left side page location
  2802.              lsri Mirror_PPU_CTRL_REG1  ;shift LSB of ppu register #1 mirror out
  2803.         if Z80==0
  2804.              andn ++$01                  ;mask out all but LSB of page location
  2805.         endif
  2806.              ror                       ;rotate LSB of page location into carry then onto mirror
  2807.              roli Mirror_PPU_CTRL_REG1  ;this is to set the proper PPU name table
  2808.              jsr GetAreaMusic          ;load proper music into queue
  2809.              ldan ++$38                  ;load sprite shuffle amounts to be used later
  2810.              sta SprShuffleAmt+2
  2811.              ldan ++$48
  2812.              sta SprShuffleAmt+1
  2813.              ldan ++$58
  2814.              sta SprShuffleAmt
  2815.              ldxn ++$0e                  ;load default OAM offsets into $06e4-$06f2
  2816. ShufAmtLoop: ldax DefaultSprOffsets,x
  2817.              stax SprDataOffset,x
  2818.              dex                       ;do this until they're all set
  2819.              bpl ShufAmtLoop
  2820.              ldyn ++$03                  ;set up sprite #0
  2821. ISpr0Loop:   lday Sprite0Data,y
  2822.              stay Sprite_Data,y
  2823.              dey
  2824.              bpl ISpr0Loop
  2825.              jsr DoNothing2            ;these jsrs doesn't do anything useful
  2826.              jsr DoNothing1
  2827.              inci Sprite0HitDetectFlag  ;set sprite #0 check flag ;ЄхяхЁ№ сєфхЄ ЁрсюЄрЄ№ ёяышЄёъЁшэ ёю ёъЁюыыюь
  2828.              inci OperMode_Task         ;increment to next task
  2829.              rts
  2830.  
  2831. ;-------------------------------------------------------------------------------------
  2832.  
  2833. ;$06 - RAM address low
  2834. ;$07 - RAM address high
  2835.  
  2836. ;y = endaddr
  2837. ;out: a=0
  2838. InitializeMemory:
  2839.         if Z80
  2840.                 push de
  2841.                 ld hl,AREADATA
  2842.                 ld de,AREADATA+1
  2843.                 pop bc
  2844.                 dec bc
  2845.                 xor a
  2846.                 ld (hl),a
  2847.                 ldir
  2848.                 ld d,b;0
  2849.         else
  2850.               ldxn ++$07          ;set initial high byte to $0700-$07ff
  2851.               ldan ++$00          ;set initial low byte to start of page (at $00 of page)
  2852.               sta SCRATCHPAD+$06
  2853. InitPageLoop: stx SCRATCHPAD+$07
  2854. InitByteLoop: cpxn ++$01          ;check to see if we're on the stack ($0100-$01ff)
  2855.               bne InitByte      ;if not, go ahead anyway
  2856.               cpyn ++$60          ;otherwise, check to see if we're at $0160-$01ff
  2857.               cmpcy
  2858.               bcs SkipByte      ;if so, skip write
  2859. InitByte:     stayindirect (SCRATCHPAD+$06),y       ;otherwise, initialize byte with current low byte in Y
  2860. SkipByte:     dey
  2861.               cpyn ++$ff          ;do this until all bytes in page have been erased
  2862.               bne InitByteLoop
  2863.               dex               ;go onto the next page
  2864.               bpl InitPageLoop  ;do this until all pages of memory have been erased
  2865.         endif
  2866.               rts
  2867.  
  2868. ;-------------------------------------------------------------------------------------
  2869.  
  2870. MusicSelectData:
  2871.       .db WaterMusic, GroundMusic, UndergroundMusic, CastleMusic
  2872.       .db CloudMusic, PipeIntroMusic
  2873.  
  2874. GetAreaMusic:
  2875.              lda OperMode           ;if in title screen mode, leave
  2876.          checka
  2877.              beq ExitGetM
  2878.              lda AltEntranceControl ;check for specific alternate mode of entry
  2879.              cmpn ++$02               ;if found, branch without checking starting position
  2880.              beq ChkAreaType        ;from area object data header
  2881.              ldyn ++$05               ;select music for pipe intro scene by default
  2882.              lda PlayerEntranceCtrl ;check value from level header for certain values
  2883.              cmpn ++$06
  2884.              beq StoreMusic         ;load music for pipe intro scene if header
  2885.              cmpn ++$07               ;start position either value $06 or $07
  2886.              beq StoreMusic
  2887. ChkAreaType: ldy AreaType           ;load area type as offset for music bit
  2888.              lda CloudTypeOverride
  2889.          checka
  2890.              beq StoreMusic         ;check for cloud type override
  2891.              ldyn ++$04               ;select music for cloud type level if found
  2892. StoreMusic:  lday MusicSelectData,y  ;otherwise select appropriate music for level type
  2893.              sta AreaMusicQueue     ;store in queue and leave
  2894. ExitGetM:    rts
  2895.  
  2896. ;-------------------------------------------------------------------------------------
  2897.  
  2898. PlayerStarting_X_Pos:
  2899.       .db $28, $18
  2900.       .db $38, $28
  2901.  
  2902. AltYPosOffset:
  2903.       .db $08, $00
  2904.  
  2905. PlayerStarting_Y_Pos:
  2906.       .db $00, $20, $b0, $50, $00, $00, $b0, $b0
  2907.       .db $f0
  2908.  
  2909. PlayerBGPriorityData:
  2910.       .db $00, $20, $00, $00, $00, $00, $00, $00
  2911.  
  2912. GameTimerData:
  2913.       .db $20 ;dummy byte, used as part of bg priority data
  2914.       .db $04, $03, $02
  2915.  
  2916. Entrance_GameTimerSetup:
  2917.           lda ScreenLeft_PageLoc      ;set current page for area objects
  2918.           sta Player_PageLoc          ;as page location for player
  2919.           ldan ++$28                    ;store value here
  2920.           sta VerticalForceDown       ;for fractional movement downwards if necessary
  2921.           ldan ++$01                    ;set high byte of player position and
  2922.           sta PlayerFacingDir         ;set facing direction so that player faces right
  2923.           sta Player_Y_HighPos
  2924.           ldan ++$00                    ;set player state to on the ground by default
  2925.           sta Player_State
  2926.           deci Player_CollisionBits    ;initialize player's collision bits
  2927.           ldyn ++$00                    ;initialize halfway page
  2928.           sty HalfwayPage      
  2929.           lda AreaType                ;check area type
  2930.          checka
  2931.           bne ChkStPos                ;if water type, set swimming flag, otherwise do not set
  2932.           iny
  2933. ChkStPos: sty SwimmingFlag
  2934.           ldx PlayerEntranceCtrl      ;get starting position loaded from header
  2935.           ldy AltEntranceControl      ;check alternate mode of entry flag for 0 or 1
  2936.          checky
  2937.           beq SetStPos
  2938.           cpyn ++$01
  2939.           beq SetStPos
  2940.           ldxy AltYPosOffset-2,y       ;if not 0 or 1, override $0710 with new offset in X
  2941. SetStPos: lday PlayerStarting_X_Pos,y  ;load appropriate horizontal position
  2942.           sta Player_X_Position       ;and vertical positions for the player, using
  2943.           ldax PlayerStarting_Y_Pos,x  ;AltEntranceControl as offset for horizontal and either $0710
  2944.           sta Player_Y_Position       ;or value that overwrote $0710 as offset for vertical
  2945.           ldax PlayerBGPriorityData,x
  2946.           sta Player_SprAttrib        ;set player sprite attributes using offset in X
  2947.           jsr GetPlayerColors         ;get appropriate player palette
  2948.           ldy GameTimerSetting        ;get timer control value from header
  2949.          checky
  2950.           beq ChkOverR                ;if set to zero, branch (do not use dummy byte for this)
  2951.           lda FetchNewGameTimerFlag   ;do we need to set the game timer? if not, use
  2952.          checka
  2953.           beq ChkOverR                ;old game timer setting
  2954.           lday GameTimerData,y         ;if game timer is set and game timer flag is also set,
  2955.           sta GameTimerDisplay        ;use value of game timer control for first digit of game timer
  2956.           ldan ++$01
  2957.           sta GameTimerDisplay+2      ;set last digit of game timer to 1
  2958.           lsr
  2959.           sta GameTimerDisplay+1      ;set second digit of game timer
  2960.           sta FetchNewGameTimerFlag   ;clear flag for game timer reset
  2961.           sta StarInvincibleTimer     ;clear star mario timer
  2962. ChkOverR: ldy JoypadOverride          ;if controller bits not set, branch to skip this part
  2963.          checky
  2964.           beq ChkSwimE
  2965.           ldan ++$03                    ;set player state to climbing
  2966.           sta Player_State
  2967.           ldxn ++$00                    ;set offset for first slot, for block object
  2968.           jsr InitBlock_XY_Pos
  2969.           ldan ++$f0                    ;set vertical coordinate for block object
  2970.           sta Block_Y_Position
  2971.           ldxn ++$05                    ;set offset in X for last enemy object buffer slot
  2972.           ldyn ++$00                    ;set offset in Y for object coordinates used earlier
  2973.           jsr Setup_Vine              ;do a sub to grow vine
  2974. ChkSwimE: ldy AreaType                ;if level not water-type,
  2975.          checky
  2976.           bne SetPESub                ;skip this subroutine
  2977.           jsr SetupBubble             ;otherwise, execute sub to set up air bubbles
  2978. SetPESub: ldan ++$07                    ;set to run player entrance subroutine
  2979.           sta GameEngineSubroutine    ;on the next frame of game engine
  2980.           rts
  2981.  
  2982. ;-------------------------------------------------------------------------------------
  2983.  
  2984. ;page numbers are in order from -1 to -4
  2985. HalfwayPageNybbles:
  2986.       .db $56, $40
  2987.       .db $65, $70
  2988.       .db $66, $40
  2989.       .db $66, $40
  2990.       .db $66, $40
  2991.       .db $66, $60
  2992.       .db $65, $70
  2993.       .db $00, $00
  2994.  
  2995. PlayerLoseLife:
  2996.              inci DisableScreenFlag    ;disable screen and sprite 0 check
  2997.              ldan ++$00
  2998.              sta Sprite0HitDetectFlag
  2999.              ldan ++Silence             ;silence music
  3000.              sta EventMusicQueue
  3001.             if INFINITELIVES
  3002.              xor a
  3003.             else
  3004.              deci NumberofLives        ;take one life from player
  3005.             endif
  3006.              bpl StillInGame          ;if player still has lives, branch
  3007.              ldan ++$00
  3008.              sta OperMode_Task        ;initialize mode task,
  3009.              ldan ++GameOverModeValue   ;switch to game over mode
  3010.              sta OperMode             ;and leave
  3011.              rts
  3012. StillInGame: lda WorldNumber          ;multiply world number by 2 and use
  3013.              asl                      ;as offset
  3014.              tax
  3015.              lda LevelNumber          ;if in area -3 or -4, increment
  3016.              andn ++$02                 ;offset by one byte, otherwise
  3017.              beq GetHalfway           ;leave offset alone
  3018.              inx
  3019. GetHalfway:  ldyx HalfwayPageNybbles,x ;get halfway page number with offset
  3020.              lda LevelNumber          ;check area number's LSB
  3021.              lsr
  3022.              tya                      ;if in area -2 or -4, use lower nybble
  3023.              bcs MaskHPNyb
  3024.              lsr                      ;move higher nybble to lower if area
  3025.              lsr                      ;number is -1 or -3
  3026.              lsr
  3027.              lsr
  3028. MaskHPNyb:   andn ++%00001111           ;mask out all but lower nybble
  3029.              cmpi ScreenLeft_PageLoc
  3030.               cmpcy
  3031.              beq SetHalfway           ;left side of screen must be at the halfway page,
  3032.              bcc SetHalfway           ;otherwise player must start at the
  3033.              ldan ++$00                 ;beginning of the level
  3034. SetHalfway:  sta HalfwayPage          ;store as halfway page for player
  3035.              jsr TransposePlayers     ;switch players around if 2-player game
  3036.              jmp ContinueGame         ;continue the game
  3037.  
  3038. ;-------------------------------------------------------------------------------------
  3039.  
  3040. GameOverMode:
  3041.       lda OperMode_Task
  3042.       jsr JumpEngine
  3043.      
  3044.       .dw SetupGameOver
  3045.       .dw ScreenRoutines
  3046.       .dw RunGameOver
  3047.  
  3048. ;-------------------------------------------------------------------------------------
  3049.  
  3050. SetupGameOver:
  3051.       ldan ++$00                  ;reset screen routine task control for title screen, game,
  3052.       sta ScreenRoutineTask     ;and game over modes
  3053.       sta Sprite0HitDetectFlag  ;disable sprite 0 check
  3054.       ldan ++GameOverMusic
  3055.       sta EventMusicQueue       ;put game over music in secondary queue
  3056.       inci DisableScreenFlag     ;disable screen output
  3057.       inci OperMode_Task         ;set secondary mode to 1
  3058.       rts
  3059.  
  3060. ;-------------------------------------------------------------------------------------
  3061.  
  3062. RunGameOver:
  3063.       ldan ++$00              ;reenable screen
  3064.       sta DisableScreenFlag
  3065.       lda SavedJoypad1Bits  ;check controller for start pressed
  3066.       andn ++Start_Button
  3067.       bne TerminateGame
  3068.       lda ScreenTimer       ;if not pressed, wait for
  3069.          checka
  3070.       bne GameIsOn          ;screen timer to expire
  3071. TerminateGame:
  3072.       ldan ++Silence          ;silence music
  3073.       sta EventMusicQueue
  3074.       jsr TransposePlayers  ;check if other player can keep
  3075.       bcc ContinueGame      ;going, and do so if possible
  3076.       lda WorldNumber       ;otherwise put world number of current
  3077.       sta ContinueWorld     ;player into secret continue function variable
  3078.       ldan ++$00
  3079.       asl                   ;residual ASL instruction
  3080.       sta OperMode_Task     ;reset all modes to title screen and
  3081.       sta ScreenTimer       ;leave
  3082.       sta OperMode
  3083.       rts
  3084.  
  3085. ContinueGame:
  3086.            jsr LoadAreaPointer       ;update level pointer with
  3087.            ldan ++$01                  ;actual world and area numbers, then
  3088.            sta PlayerSize            ;reset player's size, status, and
  3089.            inci FetchNewGameTimerFlag ;set game timer flag to reload
  3090.            ldan ++$00                  ;game timer from header
  3091.            sta TimerControl          ;also set flag for timers to count again
  3092.            sta PlayerStatus
  3093.            sta GameEngineSubroutine  ;reset task for game core
  3094.            sta OperMode_Task         ;set modes and leave
  3095.            ldan ++$01                  ;if in game over mode, switch back to
  3096.            sta OperMode              ;game mode, because game is still on
  3097. GameIsOn:  rts
  3098.  
  3099. TransposePlayers:
  3100.            sec                       ;set carry flag by default to end game
  3101.            lda NumberOfPlayers       ;if only a 1 player game, leave
  3102.          checka
  3103.            beq ExTrans
  3104.            lda OffScr_NumberofLives  ;does offscreen player have any lives left?
  3105.          checka
  3106.            bmi ExTrans               ;branch if not
  3107.            lda CurrentPlayer         ;invert bit to update
  3108.            eorn ++%00000001            ;which player is on the screen
  3109.            sta CurrentPlayer
  3110.            ldxn ++$06
  3111. TransLoop: ldax OnscreenPlayerInfo,x    ;transpose the information
  3112.            pha                         ;of the onscreen player
  3113.            ldax OffscreenPlayerInfo,x   ;with that of the offscreen player
  3114.            stax OnscreenPlayerInfo,x
  3115.            pla
  3116.            stax OffscreenPlayerInfo,x
  3117.            dex
  3118.            bpl TransLoop
  3119.            clc            ;clear carry flag to get game going
  3120. ExTrans:   rts
  3121.  
  3122. ;-------------------------------------------------------------------------------------
  3123.  
  3124. DoNothing1:
  3125.       ldan ++$ff       ;this is residual code, this value is
  3126.       sta UnusedVariable;$06c9      ;not used anywhere in the program
  3127. DoNothing2:
  3128.       rts
  3129.  
  3130. ;-------------------------------------------------------------------------------------
  3131.  
  3132. AreaParserTaskHandler:
  3133.         ;ret
  3134.               ldy AreaParserTaskNum     ;check number of tasks here
  3135.          checky
  3136.               bne DoAPTasks             ;if already set, go ahead
  3137.               ldyn ++$08 ;яю эютюьє ъЁєує
  3138.               sty AreaParserTaskNum     ;otherwise, set eight by default
  3139. DoAPTasks:    dey
  3140.               tya
  3141.               jsr AreaParserTasks
  3142.               deci AreaParserTaskNum     ;if all tasks not complete do not
  3143.              if Z80OPT4==0
  3144.               bne SkipATRender          ;render attribute table yet
  3145.               jsr RenderAttributeTables ;т√ч√трхЄё  яюёых RenderAreaGraphics #1 (Є.х. 4-ую)?
  3146. SkipATRender:
  3147.              endif
  3148.               rts
  3149.  
  3150. AreaParserTasks:
  3151.       jsr JumpEngine
  3152. ;тёхуфр т√яюыэ ■Єё  7..0?
  3153.       .dw IncrementColumnPos ;0
  3154.       .dw RenderAreaGraphics ;1
  3155.       .dw RenderAreaGraphics ;2
  3156.       .dw AreaParserCore ;3
  3157.       .dw IncrementColumnPos ;4
  3158.       .dw RenderAreaGraphics ;5
  3159.       .dw RenderAreaGraphics ;6
  3160.       .dw AreaParserCore ;7
  3161.  
  3162. ;-------------------------------------------------------------------------------------
  3163.  
  3164. IncrementColumnPos:
  3165.            inci CurrentColumnPos     ;increment column where we're at
  3166.            lda CurrentColumnPos
  3167.            andn ++%00001111           ;mask out higher nybble
  3168.            bne NoColWrap
  3169.            sta CurrentColumnPos     ;if no bits left set, wrap back to zero (0-f)
  3170.            inci CurrentPageLoc       ;and increment page number where we're at
  3171. NoColWrap: inci BlockBufferColumnPos ;increment column offset where we're at
  3172.            lda BlockBufferColumnPos
  3173.            andn ++%00011111           ;mask out all but 5 LSB (0-1f)
  3174.            sta BlockBufferColumnPos ;and save
  3175.            rts
  3176.  
  3177. ;-------------------------------------------------------------------------------------
  3178. ;$00 - used as counter, store for low nybble for background, ceiling byte for terrain
  3179. ;$01 - used to store floor byte for terrain
  3180. ;$07 - used to store terrain metatile
  3181. ;$06-$07 - used to store block buffer address
  3182.  
  3183. BSceneDataOffsets:
  3184.       .db $00, $30, $60
  3185.  
  3186. BackSceneryData: ;metatiles???
  3187.    .db $93, $00, $00, $11, $12, $12, $13, $00 ;clouds (palette 2???)
  3188.    .db $00, $51, $52, $53, $00, $00, $00, $00
  3189.    .db $00, $00, $01, $02, $02, $03, $00, $00
  3190.    .db $00, $00, $00, $00, $91, $92, $93, $00
  3191.    .db $00, $00, $00, $51, $52, $53, $41, $42
  3192.    .db $43, $00, $00, $00, $00, $00, $91, $92
  3193.  
  3194.    .db $97, $87, $88, $89, $99, $00, $00, $00 ;mountains and bushes
  3195.    .db $11, $12, $13, $a4, $a5, $a5, $a5, $a6
  3196.    .db $97, $98, $99, $01, $02, $03, $00, $a4
  3197.    .db $a5, $a6, $00, $11, $12, $12, $12, $13
  3198.    .db $00, $00, $00, $00, $01, $02, $02, $03
  3199.    .db $00, $a4, $a5, $a5, $a6, $00, $00, $00
  3200.  
  3201.    .db $11, $12, $12, $13, $00, $00, $00, $00 ;trees and fences
  3202.    .db $00, $00, $00, $9c, $00, $8b, $aa, $aa
  3203.    .db $aa, $aa, $11, $12, $13, $8b, $00, $9c
  3204.    .db $9c, $00, $00, $01, $02, $03, $11, $12
  3205.    .db $12, $13, $00, $00, $00, $00, $aa, $aa
  3206.    .db $9c, $aa, $00, $8b, $00, $01, $02, $03
  3207.  
  3208. BackSceneryMetatiles:
  3209.    .db $80, $83, $00 ;cloud left
  3210.    .db $81, $84, $00 ;cloud middle
  3211.    .db $82, $85, $00 ;cloud right
  3212.    .db $02, $00, $00 ;bush left
  3213.    .db $03, $00, $00 ;bush middle
  3214.    .db $04, $00, $00 ;bush right
  3215.    .db $00, $05, $06 ;mountain left
  3216.    .db $07, $06, $0a ;mountain middle
  3217.    .db $00, $08, $09 ;mountain right
  3218.    .db $4d, $00, $00 ;fence
  3219.    .db $0d, $0f, $4e ;tall tree
  3220.    .db $0e, $4e, $4e ;short tree
  3221.  
  3222. FSceneDataOffsets:
  3223.       .db $00, $0d, $1a
  3224.  
  3225. ForeSceneryData:
  3226.    .db $86, $87, $87, $87, $87, $87, $87   ;in water
  3227.    .db $87, $87, $87, $87, $69, $69
  3228.  
  3229.    .db $00, $00, $00, $00, $00, $45, $47   ;wall
  3230.    .db $47, $47, $47, $47, $00, $00
  3231.  
  3232.    .db $00, $00, $00, $00, $00, $00, $00   ;over water
  3233.    .db $00, $00, $00, $00, $86, $87
  3234.  
  3235. TerrainMetatiles:
  3236.       .db $69, $54, $52, $62
  3237.  
  3238. TerrainRenderBits:
  3239.       .db %00000000, %00000000 ;no ceiling or floor
  3240.       .db %00000000, %00011000 ;no ceiling, floor 2
  3241.       .db %00000001, %00011000 ;ceiling 1, floor 2
  3242.       .db %00000111, %00011000 ;ceiling 3, floor 2
  3243.       .db %00001111, %00011000 ;ceiling 4, floor 2
  3244.       .db %11111111, %00011000 ;ceiling 8, floor 2
  3245.       .db %00000001, %00011111 ;ceiling 1, floor 5
  3246.       .db %00000111, %00011111 ;ceiling 3, floor 5
  3247.       .db %00001111, %00011111 ;ceiling 4, floor 5
  3248.       .db %10000001, %00011111 ;ceiling 1, floor 6
  3249.       .db %00000001, %00000000 ;ceiling 1, no floor
  3250.       .db %10001111, %00011111 ;ceiling 4, floor 6
  3251.       .db %11110001, %00011111 ;ceiling 1, floor 9
  3252.       .db %11111001, %00011000 ;ceiling 1, middle 5, floor 2
  3253.       .db %11110001, %00011000 ;ceiling 1, middle 4, floor 2
  3254.       .db %11111111, %00011111 ;completely solid top to bottom
  3255.  
  3256. AreaParserCore:
  3257.       lda BackloadingFlag       ;check to see if we are starting right of start
  3258.          checka
  3259.       beq RenderSceneryTerrain  ;if not, go ahead and render background, foreground and terrain
  3260.       jsr ProcessAreaData       ;otherwise skip ahead and load level data
  3261.  
  3262. RenderSceneryTerrain:
  3263.           ldxn ++$0c
  3264.           ldan ++$00
  3265. ClrMTBuf: stax MetatileBuffer,x       ;clear out metatile buffer
  3266.           dex
  3267.           bpl ClrMTBuf
  3268.         ;jr $
  3269.           ldy BackgroundScenery      ;do we need to render the background scenery?
  3270.          checky
  3271.           beq RendFore               ;if not, skip to check the foreground
  3272.           lda CurrentPageLoc         ;otherwise check for every third page
  3273. ThirdP:   cmpn ++$03
  3274.           bmi RendBack               ;if less than three we're there
  3275.           secsub
  3276.           sbcn ++$03                   ;if 3 or more, subtract 3 and
  3277.           bpl ThirdP                 ;do an unconditional branch
  3278. RendBack: asl                        ;move results to higher nybble
  3279.           asl
  3280.           asl
  3281.           asl
  3282.           adcy BSceneDataOffsets-1,y  ;add to it offset loaded from here
  3283.           adci CurrentColumnPos       ;add to the result our current column position
  3284.           tax
  3285.           ldax BackSceneryData,x      ;load data from sum of offsets
  3286.          checka
  3287.           beq RendFore               ;if zero, no scenery for that part
  3288.          pha
  3289.           andn ++$0f                   ;save to stack and clear high nybble
  3290.           secsub
  3291.           sbcn ++$01                   ;subtract one (because low nybble is $01-$0c)
  3292.           sta SCRATCHPAD+$00                    ;save low nybble
  3293.           asl                        ;multiply by three (shift to left and add result to old one)
  3294.           adci SCRATCHPAD+$00                    ;note that since d7 was nulled, the carry flag is always clear
  3295.           tax                        ;save as offset for background scenery metatile data
  3296.          pla                        ;get high nybble from stack, move low
  3297.           lsr
  3298.           lsr
  3299.           lsr
  3300.           lsr
  3301.           tay                        ;use as second offset (used to determine height)
  3302.           ldan ++$03                   ;use previously saved memory location for counter
  3303.           sta SCRATCHPAD+$00
  3304. SceLoop1: ldax BackSceneryMetatiles,x ;load metatile data from offset of (lsb - 1) * 3
  3305.           stay MetatileBuffer,y       ;store into buffer from offset of (msb / 16)
  3306.           inx
  3307.           iny
  3308.           cpyn ++$0b                   ;if at this location, leave loop
  3309.           beq RendFore
  3310.           deci SCRATCHPAD+$00                    ;decrement until counter expires, barring exception
  3311.           bne SceLoop1
  3312. RendFore: ldx ForegroundScenery      ;check for foreground data needed or not
  3313.          checkx
  3314.           beq RendTerr               ;if not, skip this part
  3315.           ldyx FSceneDataOffsets-1,x  ;load offset from location offset by header value, then
  3316.           ldxn ++$00                   ;reinit X
  3317. SceLoop2: lday ForeSceneryData,y      ;load data until counter expires
  3318.          checka
  3319.           beq NoFore                 ;do not store if zero found
  3320.           stax MetatileBuffer,x
  3321. NoFore:   iny
  3322.           inx
  3323.           cpxn ++$0d                   ;store up to end of metatile buffer
  3324.           bne SceLoop2
  3325. RendTerr: ldy AreaType               ;check world type for water level
  3326.          checky
  3327.           bne TerMTile               ;if not water level, skip this part
  3328.           lda WorldNumber            ;check world number, if not world number eight
  3329.           cmpn ++World8                ;then skip this part
  3330.           bne TerMTile
  3331.           ldan ++$62                   ;if set as water level and world number eight,
  3332.           jmp StoreMT                ;use castle wall metatile as terrain type
  3333. TerMTile: lday TerrainMetatiles,y     ;otherwise get appropriate metatile for area type
  3334.           ldy CloudTypeOverride      ;check for cloud type override
  3335.          checky
  3336.           beq StoreMT                ;if not set, keep value otherwise
  3337.           ldan ++$88                   ;use cloud block terrain
  3338. StoreMT:  sta SCRATCHPAD+$07                    ;store value here
  3339.           ldxn ++$00                   ;initialize X, use as metatile buffer offset
  3340.           lda TerrainControl         ;use yet another value from the header
  3341.           asl                        ;multiply by 2 and use as yet another offset
  3342.           tay
  3343. TerrLoop: lday TerrainRenderBits,y    ;get one of the terrain rendering bit data
  3344.           sta SCRATCHPAD+$00
  3345.           iny                        ;increment Y and use as offset next time around
  3346.           sty SCRATCHPAD+$01
  3347.           lda CloudTypeOverride      ;skip if value here is zero
  3348.          checka
  3349.           beq NoCloud2
  3350.           cpxn ++$00                   ;otherwise, check if we're doing the ceiling byte
  3351.           beq NoCloud2
  3352.           lda SCRATCHPAD+$00                    ;if not, mask out all but d3
  3353.           andn ++%00001000
  3354.           sta SCRATCHPAD+$00
  3355. NoCloud2: ldyn ++$00                   ;start at beginning of bitmasks
  3356. TerrBChk: lday Bitmasks,y             ;load bitmask, then perform AND on contents of first byte
  3357.           biti SCRATCHPAD+$00
  3358.           beq NextTBit               ;if not set, skip this part (do not write terrain to buffer)
  3359.           lda SCRATCHPAD+$07
  3360.           stax MetatileBuffer,x       ;load terrain type metatile number and store into buffer here
  3361. NextTBit: inx                        ;continue until end of buffer
  3362.           cpxn ++$0d
  3363.           beq RendBBuf               ;if we're at the end, break out of this loop
  3364.           lda AreaType               ;check world type for underground area
  3365.           cmpn ++$02
  3366.           bne EndUChk                ;if not underground, skip this part
  3367.           cpxn ++$0b
  3368.           bne EndUChk                ;if we're at the bottom of the screen, override
  3369.           ldan ++$54                   ;old terrain type with ground level terrain type
  3370.           sta SCRATCHPAD+$07
  3371. EndUChk:  iny                        ;increment bitmasks offset in Y
  3372.           cpyn ++$08
  3373.           bne TerrBChk               ;if not all bits checked, loop back    
  3374.           ldy SCRATCHPAD+$01
  3375.          checky
  3376.           bne TerrLoop               ;unconditional branch, use Y to load next byte
  3377. RendBBuf:
  3378.  
  3379.           jsr ProcessAreaData        ;do the area data loading routine now
  3380.          
  3381.         if Z80OPT
  3382.         ld a,(BlockBufferColumnPos)
  3383.         ld hl,Block_Buffer_1
  3384.         bit 4,a
  3385.         jr z,$+5
  3386.          ld hl,Block_Buffer_2
  3387.         and 0x0f
  3388.         ld c,a
  3389.         add hl,bc
  3390.         ld (SCRATCHPAD+$06),hl
  3391.         else
  3392.           lda BlockBufferColumnPos
  3393.           jsr GetBlockBufferAddr     ;get block buffer address from where we're at
  3394.         endif
  3395.          
  3396.           ldxn ++$00
  3397.           ldyn ++$00                   ;init index regs and start at beginning of smaller buffer
  3398. ChkMTLow: sty SCRATCHPAD+$00
  3399.           ldax MetatileBuffer,x       ;load stored metatile number
  3400.           andn ++%11000000             ;mask out all but 2 MSB
  3401.           asl
  3402.           rol                        ;make %xx000000 into %000000xx
  3403.           rol
  3404.           tay                        ;use as offset in Y
  3405.           ldax MetatileBuffer,x       ;reload original unmasked value here
  3406.           cmpy BlockBuffLowBounds,y   ;check for certain values depending on bits set
  3407.               cmpcy
  3408.           bcs StrBlock               ;if equal or greater, branch
  3409.           ldan ++$00                   ;if less, init value before storing
  3410. StrBlock: ldy SCRATCHPAD+$00                    ;get offset for block buffer
  3411.           stayindirect (SCRATCHPAD+$06),y                ;store value into block buffer ;$06$07 = Block_Buffer_1(2)+BlockBufferColumnPos
  3412.            ;jr $
  3413.           tya
  3414.           clc                        ;add 16 (move down one row) to offset
  3415.           adcn ++$10
  3416.           tay
  3417.           inx                        ;increment column value
  3418.           cpxn ++$0d ;13 ёЄЁюъ яю 16 сыюъют
  3419.               cmpcy
  3420.           bcc ChkMTLow               ;continue until we pass last row, then leave
  3421.           rts
  3422.  
  3423. ;numbers lower than these with the same attribute bits
  3424. ;will not be stored in the block buffer
  3425. BlockBuffLowBounds:
  3426.       .db $10, $51, $88, $c0
  3427.  
  3428. ;-------------------------------------------------------------------------------------
  3429. ;$00 - used to store area object identifier
  3430. ;$07 - used as adder to find proper area object code
  3431.  
  3432. ;TODO єёъюЁшЄ№
  3433.  
  3434. ProcessAreaData:
  3435.         if Z80OPT3
  3436.             ld c,++$02                 ;start at the end of area object buffer
  3437. ProcADLoop:
  3438.          if Z80OPT3ly
  3439.             ld ly,c;stx ObjectOffset ;шёяюы№чєхЄё  т DecodeAreaData
  3440.          else
  3441.             stx ObjectOffset ;шёяюы№чєхЄё  т DecodeAreaData
  3442.          endif
  3443.             xor a                ;reset flag
  3444.             ld (BehindAreaParserFlag),a
  3445.            ld hl,AreaDataOffset
  3446.            ld e,(hl)      ;get offset of area data pointer
  3447.             ld hl,AreaObjectLength
  3448.             add hl,bc
  3449.             bit 7,(hl)   ;check area object buffer flag
  3450.             jp z,RdyDecode_AreaObjectLength_positive            ;if buffer not negative, branch, otherwise
  3451.            ld ix,(AreaData)
  3452.            add ix,de ;TODO hl? хёыш єфюсэю сєфхЄ т DecodeAreaData
  3453.             ld a,(ix)      ;get first byte of area object
  3454.             cp ++$fd                 ;if end-of-area, skip all this crap
  3455.             jp z,RdyDecode_endofarea
  3456.            bit 7,(ix+1)      ;get second byte of area object
  3457.             jr z,Chk1Row13 ;check for page select bit (d7), branch if not set
  3458.             ld hl,AreaObjectPageSel
  3459.             inc (hl)    ;check page select
  3460.             dec (hl)
  3461.             jr nz,Chk1Row13
  3462.             inc (hl)   ;if not already set, set it now
  3463.             ld hl,AreaObjectPageLoc
  3464.             inc (hl)   ;and increment page location
  3465. Chk1Row13:  
  3466.            ;ld a,(ix)      ;reread first byte of level object
  3467.             and ++$0f                 ;mask out high nybble
  3468.             cp ++$0d                 ;row 13?
  3469.             jr nz,Chk1Row14
  3470.            bit 6,(ix+1) ;if so, reread second byte of level object
  3471.             jr nz,CheckRear ;check for d6 set (if not, object is page control)
  3472.             ld a,(AreaObjectPageSel)    ;if page select is set, do not reread
  3473.             or a
  3474.             jr nz,CheckRear
  3475.            ld a,(ix+1)                     ;if d6 not set, reread second byte
  3476.             and ++%00011111           ;mask out all but 5 LSB and store in page control
  3477.             ld (AreaObjectPageLoc),a
  3478.             ld hl,AreaObjectPageSel
  3479.             inc (hl)    ;increment page select
  3480.             jmp NextAObj
  3481. Chk1Row14:  cp ++$0e                 ;row 14?
  3482.             jr nz,CheckRear
  3483.             ld a,(BackloadingFlag)      ;check flag for saved page number and branch if set
  3484.             or a
  3485.             jr nz,RdyDecode            ;to render the object (otherwise bg might not look right)
  3486. CheckRear:  ld a,(AreaObjectPageLoc)    ;check to see if current page of level object is
  3487.             ld hl,CurrentPageLoc
  3488.             cp (hl)     ;behind current page of renderer
  3489.             jr c,SetBehind            ;if so branch
  3490. RdyDecode:  
  3491.             ;push ix
  3492.           ldayindirect (AreaData),y           ;get first byte of level object again
  3493.             call DecodeAreaData       ;do sub and do not turn on flag       ;y трцхэ!!!
  3494.             ;pop ix
  3495.             jp ChkLength
  3496. RdyDecode_AreaObjectLength_positive:
  3497.           ldyx AreaObjOffsetBuffer,x  ;if not, get offset from buffer
  3498.             ;push ix
  3499.           ldayindirect (AreaData),y           ;get first byte of level object again
  3500.             call DecodeAreaData       ;do sub and do not turn on flag       ;y трцхэ!!!
  3501.             ;pop ix
  3502.             jp ChkLength
  3503. SetBehind:  
  3504.             ld hl,BehindAreaParserFlag
  3505.             inc (hl) ;turn on flag if object is behind renderer
  3506. NextAObj:  
  3507.            ld hl,AreaDataOffset
  3508.            inc (hl)
  3509.            inc (hl) ;яю эхьє ЁрёёўшЄ√трхЄё  рфЁхё юс·хъЄр эр ёыхфє■∙хь яЁюїюфх
  3510.            xor a
  3511.            ld (AreaObjectPageSel),a
  3512.            
  3513. RdyDecode_endofarea:
  3514. ChkLength:  
  3515.          if Z80OPT3ly
  3516.             ;ld hl,ObjectOffset
  3517.             ld c,ly;ld c,(hl)       ;get buffer offset
  3518.          else
  3519.             ld hl,ObjectOffset
  3520.             ld c,(hl)       ;get buffer offset
  3521.          endif
  3522.             ld hl,AreaObjectLength
  3523.             add hl,bc
  3524.             ld a,(hl) ;check object length for anything stored here
  3525.             rla
  3526.             jr c,ProcLoopb            ;if not, branch to handle loopback
  3527.             dec (hl)   ;otherwise decrement length or get rid of it
  3528. ProcLoopb:  dec c                      ;decrement buffer offset
  3529.             jp p,ProcADLoop           ;and loopback unless exceeded buffer
  3530.             ld a,(BehindAreaParserFlag) ;check for flag set if objects were behind renderer
  3531.             or a
  3532.             jp nz,ProcessAreaData      ;branch if true to load more level data, otherwise
  3533.             ld a,(BackloadingFlag)      ;check for flag set if starting right of page $00
  3534.             or a
  3535.             jp nz,ProcessAreaData      ;branch if true to load more level data, otherwise leave
  3536.             ret
  3537.  
  3538.         else ;~Z80
  3539.  
  3540.             ldxn ++$02                 ;start at the end of area object buffer
  3541. ProcADLoop: stx ObjectOffset
  3542.             ldan ++$00                 ;reset flag
  3543.             sta BehindAreaParserFlag
  3544.             ldy AreaDataOffset       ;get offset of area data pointer
  3545.             ldayindirect (AreaData),y         ;get first byte of area object
  3546.             cmpn ++$fd                 ;if end-of-area, skip all this crap
  3547.             beq RdyDecode
  3548.             ldax AreaObjectLength,x   ;check area object buffer flag
  3549.          checka
  3550.             bpl RdyDecode            ;if buffer not negative, branch, otherwise
  3551.             iny
  3552.             ldayindirect (AreaData),y         ;get second byte of area object
  3553.             asl                      ;check for page select bit (d7), branch if not set
  3554.             bcc Chk1Row13
  3555.             lda AreaObjectPageSel    ;check page select
  3556.          checka
  3557.             bne Chk1Row13
  3558.             inci AreaObjectPageSel    ;if not already set, set it now
  3559.             inci AreaObjectPageLoc    ;and increment page location
  3560. Chk1Row13:  dey
  3561.             ldayindirect (AreaData),y         ;reread first byte of level object
  3562.             andn ++$0f                 ;mask out high nybble
  3563.             cmpn ++$0d                 ;row 13?
  3564.             bne Chk1Row14
  3565.             iny                      ;if so, reread second byte of level object
  3566.             ldayindirect (AreaData),y
  3567.             dey                      ;decrement to get ready to read first byte
  3568.             andn ++%01000000           ;check for d6 set (if not, object is page control)
  3569.             bne CheckRear
  3570.             lda AreaObjectPageSel    ;if page select is set, do not reread
  3571.            checka
  3572.             bne CheckRear
  3573.             iny                      ;if d6 not set, reread second byte
  3574.             ldayindirect (AreaData),y
  3575.             andn ++%00011111           ;mask out all but 5 LSB and store in page control
  3576.             sta AreaObjectPageLoc
  3577.             inci AreaObjectPageSel    ;increment page select
  3578.             jmp NextAObj
  3579. Chk1Row14:  cmpn ++$0e                 ;row 14?
  3580.             bne CheckRear
  3581.             lda BackloadingFlag      ;check flag for saved page number and branch if set
  3582.          checka
  3583.             bne RdyDecode            ;to render the object (otherwise bg might not look right)
  3584. CheckRear:  lda AreaObjectPageLoc    ;check to see if current page of level object is
  3585.             cmpi CurrentPageLoc       ;behind current page of renderer
  3586.               cmpcy
  3587.             bcc SetBehind            ;if so branch
  3588. RdyDecode:  jsr DecodeAreaData       ;do sub and do not turn on flag
  3589.             jmp ChkLength
  3590. SetBehind:  inci BehindAreaParserFlag ;turn on flag if object is behind renderer
  3591. NextAObj:  
  3592.             jsr IncAreaObjOffset     ;increment buffer offset and move on
  3593. ChkLength:  ldx ObjectOffset         ;get buffer offset
  3594.             ldax AreaObjectLength,x   ;check object length for anything stored here
  3595.          checka
  3596.             bmi ProcLoopb            ;if not, branch to handle loopback
  3597.             decx AreaObjectLength,x   ;otherwise decrement length or get rid of it
  3598. ProcLoopb:  dex                      ;decrement buffer offset
  3599.             bpl ProcADLoop           ;and loopback unless exceeded buffer
  3600.             lda BehindAreaParserFlag ;check for flag set if objects were behind renderer
  3601.          checka
  3602.             bne ProcessAreaData      ;branch if true to load more level data, otherwise
  3603.             lda BackloadingFlag      ;check for flag set if starting right of page $00
  3604.          checka
  3605.             bne ProcessAreaData      ;branch if true to load more level data, otherwise leave
  3606. EndAParse:  rts
  3607.  
  3608. IncAreaObjOffset:
  3609.       inci AreaDataOffset    ;increment offset of level pointer
  3610.       inci AreaDataOffset
  3611.       ldan ++$00              ;reset page select
  3612.       sta AreaObjectPageSel
  3613.       rts
  3614.         endif
  3615.  
  3616. ;x трцхэ!
  3617. ;y трцхэ!
  3618. DecodeAreaData:
  3619.         if Z80OPT3
  3620.         if 0
  3621.                 ld hl,AreaObjectLength
  3622.                 add hl,bc
  3623.                 ld a,(hl)    ;check current buffer flag
  3624.                 or a
  3625.                 bmi Chk1stB
  3626.                 ldyx AreaObjOffsetBuffer,x  ;if not, get offset from buffer
  3627. Chk1stB:
  3628.                 ldayindirect (AreaData),y           ;get first byte of level object again
  3629.                 cp ++$fd
  3630.                 ret z              ;if end of level, leave this routine
  3631.         endif
  3632.           and ++$0f                   ;otherwise, mask out low nybble
  3633.          sub 15;cp $0f                   ;row 15?
  3634.           jr z,ChkRow15ok               ;if so, keep the offset of 16
  3635.          inc a;cp $0e                   ;row 14?
  3636.           jr nz,ChkRow13
  3637. ChkRow14ok
  3638.           ld hy,a;0
  3639.         ld a,++$2e                   ;and load A with another value
  3640.         jp NormObj                ;unconditional branch
  3641. ChkRow15ok
  3642.         ld hy,16
  3643.         jp SpecObj
  3644. ChkRow12ok
  3645.         ld hy,8
  3646.         jp SpecObj
  3647. ChkRow13: inc a;cp $0d                   ;row 13?
  3648.           jr nz,ChkSRows
  3649. ChkRow13ok
  3650.         ld hy,34;sta SCRATCHPAD+$07  ;if so, load offset with 34
  3651.         iny                        ;get next byte
  3652.         ldayindirect (AreaData),y
  3653.         bit 6,a;and ++%01000000             ;mask out all but d6 (page control obj bit)
  3654.         ret z;jr z,LeavePar               ;if d6 clear, branch to leave (we handled this earlier)
  3655.         and ++%01111111             ;mask out d7
  3656.         cp ++$4b                   ;check for loop command in low nybble
  3657.         jr nz,Mask2MSB               ;(plus d6 set for object other than page control)
  3658.         inci LoopCommand            ;if loop command, set loop command flag
  3659. Mask2MSB
  3660.         and ++%00111111             ;mask out d7 and d6
  3661.         jp NormObj                ;and jump
  3662. ChkSRows:
  3663.          inc a;cp $0c                   ;row 12?
  3664.           jr z,ChkRow12ok               ;if so, keep the offset value of 8
  3665.           ld hy,0                   ;otherwise nullify value by default
  3666.          
  3667.           iny                        ;if not, get second byte of level object
  3668.           ldayindirect (AreaData),y
  3669.           and ++%01110000             ;mask out all but d6-d4
  3670.           jr nz,LrgObj                 ;if any bits set, branch to handle large object
  3671.           ld hy,22;sta SCRATCHPAD+$07    ;otherwise set offset of 22 for small object
  3672.           ldayindirect (AreaData),y           ;reload second byte of level object
  3673.           and ++%00001111             ;mask out higher nybble and jump
  3674.           jmp NormObj
  3675. LrgObj:    sta SCRATCHPAD+$00                    ;store value here (branch for large objects)
  3676.           cp ++$70                   ;check for vertical pipe object
  3677.           jr nz,NotWPipe
  3678.           ldayindirect (AreaData),y           ;if not, reload second byte
  3679.           bit 3,a;and ++%00001000             ;mask out all but d3 (usage control bit)
  3680.           jr z,NotWPipe               ;if d3 clear, branch to get original value
  3681.           ldan ++$00                   ;otherwise, nullify value for warp pipe
  3682.            sta SCRATCHPAD+$00
  3683. NotWPipe:  lda SCRATCHPAD+$00                    ;get value and jump ahead
  3684.           jmp MoveAOId
  3685. SpecObj:  iny                        ;branch here for rows 12-15
  3686.        if Z80OPT3hy
  3687.        else
  3688.         ld a,hy
  3689.         ld (SCRATCHPAD+$07),a
  3690.        endif
  3691.           ldayindirect (AreaData),y
  3692.           andn ++%01110000             ;get next byte and mask out all but d6-d4
  3693. MoveAOId: lsr                        ;move d6-d4 to lower nybble
  3694.           lsr
  3695.           lsr
  3696.           lsr
  3697. NormObj:   sta SCRATCHPAD+$00                    ;store value here (branch for small objects and rows 13 and 14)
  3698.        if Z80OPT3hy
  3699.        else
  3700.         ld a,hy
  3701.         ld (SCRATCHPAD+$07),a
  3702.        endif
  3703.           ldax AreaObjectLength,x     ;is there something stored here already?
  3704.           or a
  3705.           jp p,RunAObj                ;if so, branch to do its particular sub
  3706.           lda AreaObjectPageLoc      ;otherwise check to see if the object we've loaded is on the
  3707.           cmpi CurrentPageLoc         ;same page as the renderer, and if so, branch
  3708.           beq InitRear
  3709.           ldy AreaDataOffset         ;if not, get old offset of level pointer
  3710.           ldayindirect (AreaData),y           ;and reload first byte
  3711.           andn ++%00001111
  3712.           cmpn ++$0e                   ;row 14?
  3713.           ret nz
  3714.           lda BackloadingFlag        ;if so, check backloading flag
  3715.          checka
  3716.           bne StrAObj                ;if set, branch to render object, else leave
  3717.           ret
  3718. InitRear: lda BackloadingFlag        ;check backloading flag to see if it's been initialized
  3719.           or a
  3720.           jr z,BackColC               ;branch to column-wise check
  3721.           xor a;ldan ++$00                   ;if not, initialize both backloading and
  3722.           sta BackloadingFlag        ;behind-renderer flags and leave
  3723.           sta BehindAreaParserFlag
  3724.          if Z80OPT3ly
  3725.           ld ly,a;0;sta ObjectOffset
  3726.          else
  3727.           sta ObjectOffset
  3728.          endif
  3729. LoopCmdE: ret
  3730. BackColC: ldy AreaDataOffset         ;get first byte again
  3731.           ldayindirect (AreaData),y
  3732.           and ++%11110000             ;mask out low nybble and move high to low
  3733.           rrca
  3734.           rrca
  3735.           rrca
  3736.           rrca
  3737.           cmpi CurrentColumnPos       ;is this where we're at?
  3738.           ret nz        ;if not, branch to leave
  3739. StrAObj:  
  3740.         ld hl,AreaDataOffset
  3741.           ld a,(hl)        ;if so, load area obj offset and store in buffer
  3742.         inc (hl)
  3743.         inc (hl)
  3744.           stax AreaObjOffsetBuffer,x
  3745.         xor a
  3746.         ld (AreaObjectPageSel),a
  3747. RunAObj:
  3748. ;CY=0
  3749.           ld a,(SCRATCHPAD+$00)                    ;get stored value and add offset to it
  3750.        if Z80OPT3hy
  3751.           add a,hy ;adci SCRATCHPAD+$07
  3752.        else
  3753.           adci SCRATCHPAD+$07
  3754.        endif
  3755.           call JumpEngine
  3756.  
  3757.         else ;~Z80
  3758.  
  3759.           ldax AreaObjectLength,x     ;check current buffer flag
  3760.          checka
  3761.           bmi Chk1stB
  3762.           ldyx AreaObjOffsetBuffer,x  ;if not, get offset from buffer
  3763. Chk1stB:  ldxn ++$10                   ;load offset of 16 for special row 15
  3764.           ldayindirect (AreaData),y           ;get first byte of level object again
  3765.           cmpn ++$fd
  3766.           beq EndAParse              ;if end of level, leave this routine (TODO ret z)
  3767.           andn ++$0f                   ;otherwise, mask out low nybble
  3768.           cmpn ++$0f                   ;row 15?
  3769.           beq ChkRow14               ;if so, keep the offset of 16
  3770.           ldxn ++$08                   ;otherwise load offset of 8 for special row 12
  3771.           cmpn ++$0c                   ;row 12?
  3772.           beq ChkRow14               ;if so, keep the offset value of 8
  3773.           ldxn ++$00                   ;otherwise nullify value by default
  3774. ChkRow14:
  3775.          stx SCRATCHPAD+$07                    ;store whatever value we just loaded here
  3776.           ldx ObjectOffset           ;get object offset again
  3777.           cmpn ++$0e                   ;row 14?
  3778.           bne ChkRow13
  3779.           ldan ++$00                   ;if so, load offset with $00
  3780.           sta SCRATCHPAD+$07
  3781.           ldan ++$2e                   ;and load A with another value
  3782.          checka
  3783.           bne NormObj                ;unconditional branch
  3784. ChkRow13: cmpn ++$0d                   ;row 13?
  3785.           bne ChkSRows
  3786.           ldan ++$22                   ;if so, load offset with 34
  3787.           sta SCRATCHPAD+$07
  3788.           iny                        ;get next byte
  3789.           ldayindirect (AreaData),y
  3790.           andn ++%01000000             ;mask out all but d6 (page control obj bit)
  3791.           beq LeavePar               ;if d6 clear, branch to leave (we handled this earlier)
  3792.           ldayindirect (AreaData),y           ;otherwise, get byte again
  3793.           andn ++%01111111             ;mask out d7
  3794.           cmpn ++$4b                   ;check for loop command in low nybble
  3795.           bne Mask2MSB               ;(plus d6 set for object other than page control)
  3796.           inci LoopCommand            ;if loop command, set loop command flag
  3797. Mask2MSB: andn ++%00111111             ;mask out d7 and d6
  3798.           jmp NormObj                ;and jump
  3799. ChkSRows: cmpn ++$0c                   ;row 12-15?
  3800.               cmpcy
  3801.           bcs SpecObj
  3802.  
  3803.           iny                        ;if not, get second byte of level object
  3804.           ldayindirect (AreaData),y
  3805.           andn ++%01110000             ;mask out all but d6-d4
  3806.           bne LrgObj                 ;if any bits set, branch to handle large object
  3807.           ldan ++$16
  3808.           sta SCRATCHPAD+$07                    ;otherwise set offset of 24 for small object
  3809.           ldayindirect (AreaData),y           ;reload second byte of level object
  3810.           andn ++%00001111             ;mask out higher nybble and jump
  3811.           jmp NormObj
  3812. LrgObj:   sta SCRATCHPAD+$00                    ;store value here (branch for large objects)
  3813.           cmpn ++$70                   ;check for vertical pipe object
  3814.           bne NotWPipe
  3815.           ldayindirect (AreaData),y           ;if not, reload second byte
  3816.           andn ++%00001000             ;mask out all but d3 (usage control bit)
  3817.           beq NotWPipe               ;if d3 clear, branch to get original value
  3818.           ldan ++$00                   ;otherwise, nullify value for warp pipe
  3819.           sta SCRATCHPAD+$00
  3820. NotWPipe: lda SCRATCHPAD+$00                    ;get value and jump ahead
  3821.           jmp MoveAOId
  3822. SpecObj:  iny                        ;branch here for rows 12-15
  3823.           ldayindirect (AreaData),y
  3824.           andn ++%01110000             ;get next byte and mask out all but d6-d4
  3825. MoveAOId: lsr                        ;move d6-d4 to lower nybble
  3826.           lsr
  3827.           lsr
  3828.           lsr
  3829. NormObj:  sta SCRATCHPAD+$00                    ;store value here (branch for small objects and rows 13 and 14)
  3830.           ldax AreaObjectLength,x     ;is there something stored here already?
  3831.          checka
  3832.           bpl RunAObj                ;if so, branch to do its particular sub
  3833.           lda AreaObjectPageLoc      ;otherwise check to see if the object we've loaded is on the
  3834.           cmpi CurrentPageLoc         ;same page as the renderer, and if so, branch
  3835.           beq InitRear
  3836.           ldy AreaDataOffset         ;if not, get old offset of level pointer
  3837.           ldayindirect (AreaData),y           ;and reload first byte
  3838.           andn ++%00001111
  3839.           cmpn ++$0e                   ;row 14?
  3840.           bne LeavePar ;TODO ret nz
  3841.           lda BackloadingFlag        ;if so, check backloading flag
  3842.          checka
  3843.           bne StrAObj                ;if set, branch to render object, else leave
  3844. LeavePar: rts
  3845. InitRear: lda BackloadingFlag        ;check backloading flag to see if it's been initialized
  3846.          checka
  3847.           beq BackColC               ;branch to column-wise check
  3848.           ldan ++$00                   ;if not, initialize both backloading and
  3849.           sta BackloadingFlag        ;behind-renderer flags and leave
  3850.           sta BehindAreaParserFlag
  3851.           sta ObjectOffset
  3852. LoopCmdE: rts
  3853. BackColC: ldy AreaDataOffset         ;get first byte again
  3854.           ldayindirect (AreaData),y
  3855.           andn ++%11110000             ;mask out low nybble and move high to low
  3856.           lsr
  3857.           lsr
  3858.           lsr
  3859.           lsr
  3860.           cmpi CurrentColumnPos       ;is this where we're at?
  3861.           bne LeavePar               ;if not, branch to leave
  3862. StrAObj:  lda AreaDataOffset         ;if so, load area obj offset and store in buffer
  3863.           stax AreaObjOffsetBuffer,x
  3864.           jsr IncAreaObjOffset       ;do sub to increment to next object data
  3865. RunAObj:  lda SCRATCHPAD+$00                    ;get stored value and add offset to it
  3866.           clc                        ;then use the jump engine with current contents of A
  3867.           adci SCRATCHPAD+$07
  3868.           jsr JumpEngine
  3869.         endif
  3870.  
  3871. ;y=AreaData offset (фы  GetLrgObjAttrib)
  3872. ;x трцхэ т GetLrgObjAttrib
  3873. ;яюЄюь x схЁ╕Єё  шч hy;SCRATCHPAD+$07
  3874.  
  3875. ;large objects (rows $00-$0b or 00-11, d6-d4 set)
  3876.       .dw VerticalPipe         ;used by warp pipes
  3877.       .dw AreaStyleObject
  3878.       .dw RowOfBricks
  3879.       .dw RowOfSolidBlocks
  3880.       .dw RowOfCoins
  3881.       .dw ColumnOfBricks
  3882.       .dw ColumnOfSolidBlocks
  3883.       .dw VerticalPipe         ;used by decoration pipes
  3884.  
  3885. ;objects for special row $0c or 12
  3886.       .dw Hole_Empty
  3887.       .dw PulleyRopeObject
  3888.       .dw Bridge_High
  3889.       .dw Bridge_Middle
  3890.       .dw Bridge_Low
  3891.       .dw Hole_Water
  3892.       .dw QuestionBlockRow_High
  3893.       .dw QuestionBlockRow_Low
  3894.  
  3895. ;objects for special row $0f or 15
  3896.       .dw EndlessRope
  3897.       .dw BalancePlatRope
  3898.       .dw CastleObject
  3899.       .dw StaircaseObject
  3900.       .dw ExitPipe
  3901.       .dw FlagBalls_Residual
  3902.  
  3903. ;small objects (rows $00-$0b or 00-11, d6-d4 all clear)
  3904.       .dw QuestionBlock     ;power-up
  3905.       .dw QuestionBlock     ;coin
  3906.       .dw QuestionBlock     ;hidden, coin
  3907.       .dw Hidden1UpBlock    ;hidden, 1-up
  3908.       .dw BrickWithItem     ;brick, power-up
  3909.       .dw BrickWithItem     ;brick, vine
  3910.       .dw BrickWithItem     ;brick, star
  3911.       .dw BrickWithCoins    ;brick, coins
  3912.       .dw BrickWithItem     ;brick, 1-up
  3913.       .dw WaterPipe
  3914.       .dw EmptyBlock
  3915.       .dw Jumpspring
  3916.  
  3917. ;objects for special row $0d or 13 (d6 set)
  3918.       .dw IntroPipe
  3919.       .dw FlagpoleObject
  3920.       .dw AxeObj
  3921.       .dw ChainObj
  3922.       .dw CastleBridgeObj
  3923.       .dw ScrollLockObject_Warp
  3924.       .dw ScrollLockObject
  3925.       .dw ScrollLockObject
  3926.       .dw AreaFrenzy            ;flying cheep-cheeps
  3927.       .dw AreaFrenzy            ;bullet bills or swimming cheep-cheeps
  3928.       .dw AreaFrenzy            ;stop frenzy
  3929.       .dw LoopCmdE ;ret
  3930.  
  3931. ;object for special row $0e or 14
  3932.       .dw AlterAreaAttributes
  3933.  
  3934. ;-------------------------------------------------------------------------------------
  3935. ;(these apply to all area object subroutines in this section unless otherwise stated)
  3936. ;$00 - used to store offset used to find object code
  3937. ;$07 - starts with adder from area parser, used to store row offset
  3938.  
  3939. AlterAreaAttributes:
  3940.          ldyx AreaObjOffsetBuffer,x ;load offset for level object data saved in buffer
  3941.          iny                       ;load second byte
  3942.          ldayindirect (AreaData),y
  3943.          pha                       ;save in stack for now
  3944.          andn ++%01000000
  3945.          bne Alter2                ;branch if d6 is set
  3946.          pla
  3947.          pha                       ;pull and push offset to copy to A
  3948.          andn ++%00001111            ;mask out high nybble and store as
  3949.          sta TerrainControl        ;new terrain height type bits
  3950.          pla
  3951.          andn ++%00110000            ;pull and mask out all but d5 and d4
  3952.          lsr                       ;move bits to lower nybble and store
  3953.          lsr                       ;as new background scenery bits
  3954.          lsr
  3955.          lsr
  3956.          sta BackgroundScenery     ;then leave
  3957.          rts
  3958. Alter2:  pla
  3959.          andn ++%00000111            ;mask out all but 3 LSB
  3960.          cmpn ++$04                  ;if four or greater, set color control bits
  3961.               cmpcy
  3962.          bcc SetFore               ;and nullify foreground scenery bits
  3963.          sta BackgroundColorCtrl
  3964.          ldan ++$00
  3965. SetFore: sta ForegroundScenery     ;otherwise set new foreground scenery bits
  3966.          rts
  3967.  
  3968. ;--------------------------------
  3969.  
  3970. ScrollLockObject_Warp:
  3971.          ldxn ++$04            ;load value of 4 for game text routine as default
  3972.          lda WorldNumber     ;warp zone (4-3-2), then check world number
  3973.          checka
  3974.          beq WarpNum
  3975.          inx                 ;if world number HIGH  1, increment for next warp zone (5)
  3976.          ldy AreaType        ;check area type
  3977.          dey
  3978.          bne WarpNum         ;if ground area type, increment for last warp zone
  3979.          inx                 ;(8-7-6) and move on
  3980. WarpNum: txa
  3981.          sta WarpZoneControl ;store number here to be used by warp zone routine
  3982.          jsr WriteGameText   ;print text and warp zone numbers
  3983.          ldan ++PiranhaPlant
  3984.          jsr KillEnemies     ;load identifier for piranha plants and do sub
  3985.  
  3986. ScrollLockObject:
  3987.       lda ScrollLock      ;invert scroll lock to turn it on
  3988.       eorn ++%00000001
  3989.       sta ScrollLock
  3990.       rts
  3991.  
  3992. ;--------------------------------
  3993. ;$00 - used to store enemy identifier in KillEnemies
  3994.  
  3995. KillEnemies:
  3996.            sta SCRATCHPAD+$00           ;store identifier here
  3997.            ldan ++$00
  3998.            ldxn ++$04          ;check for identifier in enemy object buffer
  3999. KillELoop: ldyx Enemy_ID,x
  4000.            cpyi SCRATCHPAD+$00           ;if not found, branch
  4001.            bne NoKillE
  4002.            stax Enemy_Flag,x  ;if found, deactivate enemy object flag
  4003. NoKillE:   dex               ;do this until all slots are checked
  4004.            bpl KillELoop
  4005.            rts
  4006.  
  4007. ;--------------------------------
  4008.  
  4009. FrenzyIDData:
  4010.       .db FlyCheepCheepFrenzy, BBill_CCheep_Frenzy, Stop_Frenzy
  4011.  
  4012. AreaFrenzy:  ldx SCRATCHPAD+$00               ;use area object identifier bit as offset
  4013.              ldax FrenzyIDData-8,x  ;note that it starts at 8, thus weird address here
  4014.              ldyn ++$05
  4015. FreCompLoop: dey                   ;check regular slots of enemy object buffer
  4016.              bmi ExitAFrenzy       ;if all slots checked and enemy object not found, branch to store
  4017.              cmpy Enemy_ID,y    ;check for enemy object in buffer versus frenzy object
  4018.              bne FreCompLoop
  4019.              ldan ++$00              ;if enemy object already present, nullify queue and leave
  4020. ExitAFrenzy: sta EnemyFrenzyQueue  ;store enemy into frenzy queue
  4021.              rts
  4022.  
  4023. ;--------------------------------
  4024. ;$06 - used by MushroomLedge to store length
  4025.  
  4026. AreaStyleObject:
  4027.       lda AreaStyle        ;load level object style and jump to the right sub
  4028.       jsr JumpEngine
  4029.       .dw TreeLedge        ;also used for cloud type levels
  4030.       .dw MushroomLedge
  4031.       .dw BulletBillCannon
  4032.  
  4033. TreeLedge:
  4034.           jsr GetLrgObjAttrib     ;get row and length of green ledge
  4035.           ldax AreaObjectLength,x  ;check length counter for expiration
  4036.          checka
  4037.           beq EndTreeL  
  4038.           bpl MidTreeL
  4039.           tya
  4040.           stax AreaObjectLength,x  ;store lower nybble into buffer flag as length of ledge
  4041.           lda CurrentPageLoc
  4042.           orai CurrentColumnPos    ;are we at the start of the level?
  4043.           beq MidTreeL
  4044.           ldan ++$16                ;render start of tree ledge
  4045.           jmp NoUnder
  4046. MidTreeL:
  4047.         if Z80OPT3hy
  4048.           ld c,hy;ldx SCRATCHPAD+$07
  4049.         else
  4050.           ldx SCRATCHPAD+$07
  4051.         endif
  4052.           ldan ++$17                ;render middle of tree ledge
  4053.           stax MetatileBuffer,x    ;note that this is also used if ledge position is
  4054.           ldan ++$4c                ;at the start of level for continuous effect
  4055.           jmp AllUnder            ;now render the part underneath
  4056. EndTreeL: ldan ++$18                ;render end of tree ledge
  4057.           jmp NoUnder
  4058.  
  4059. MushroomLedge:
  4060.           jsr ChkLrgObjLength        ;get shroom dimensions
  4061.           sty SCRATCHPAD+$06                    ;store length here for now
  4062.           bcc EndMushL
  4063.           ldax AreaObjectLength,x     ;divide length by 2 and store elsewhere
  4064.           lsr
  4065.           stax MushroomLedgeHalfLen,x
  4066.           ldan ++$19                   ;render start of mushroom
  4067.           jmp NoUnder
  4068. EndMushL: ldan ++$1b                   ;if at the end, render end of mushroom
  4069.           ldyx AreaObjectLength,x
  4070.          checky
  4071.           beq NoUnder
  4072.           ldax MushroomLedgeHalfLen,x ;get divided length and store where length
  4073.           sta SCRATCHPAD+$06                    ;was stored originally
  4074.         if Z80OPT3hy
  4075.           ld c,hy;ldx SCRATCHPAD+$07
  4076.         else
  4077.           ldx SCRATCHPAD+$07
  4078.         endif
  4079.           ldan ++$1a
  4080.           stax MetatileBuffer,x       ;render middle of mushroom
  4081.           cpyi SCRATCHPAD+$06                    ;are we smack dab in the center?
  4082.           bne MushLExit              ;if not, branch to leave
  4083.           inx
  4084.           ldan ++$4f
  4085.           stax MetatileBuffer,x       ;render stem top of mushroom underneath the middle
  4086.           ldan ++$50
  4087. AllUnder: inx
  4088.           ldyn ++$0f                   ;set $0f to render all way down
  4089.           jmp RenderUnderPart       ;now render the stem of mushroom
  4090. NoUnder:  
  4091.         if Z80OPT3hy
  4092.           ld c,hy;ldx SCRATCHPAD+$07     ;load row of ledge
  4093.         else
  4094.           ldx SCRATCHPAD+$07                    ;load row of ledge
  4095.         endif
  4096.           ldyn ++$00                   ;set 0 for no bottom on this part
  4097.           jmp RenderUnderPart
  4098.  
  4099. ;--------------------------------
  4100.  
  4101. ;tiles used by pulleys and rope object
  4102. PulleyRopeMetatiles:
  4103.       .db $42, $41, $43
  4104.  
  4105. PulleyRopeObject:
  4106.            jsr ChkLrgObjLength       ;get length of pulley/rope object
  4107.            ldyn ++$00                  ;initialize metatile offset
  4108.            bcs RenderPul             ;if starting, render left pulley
  4109.            iny
  4110.            ldax AreaObjectLength,x    ;if not at the end, render rope
  4111.          checka
  4112.            bne RenderPul
  4113.            iny                       ;otherwise render right pulley
  4114. RenderPul: lday PulleyRopeMetatiles,y
  4115.            sta MetatileBuffer        ;render at the top of the screen
  4116. MushLExit: rts                       ;and leave
  4117.  
  4118. ;--------------------------------
  4119. ;$06 - used to store upper limit of rows for CastleObject
  4120.  
  4121. CastleMetatiles:
  4122.       .db $00, $45, $45, $45, $00
  4123.       .db $00, $48, $47, $46, $00
  4124.       .db $45, $49, $49, $49, $45
  4125.       .db $47, $47, $4a, $47, $47
  4126.       .db $47, $47, $4b, $47, $47
  4127.       .db $49, $49, $49, $49, $49
  4128.       .db $47, $4a, $47, $4a, $47
  4129.       .db $47, $4b, $47, $4b, $47
  4130.       .db $47, $47, $47, $47, $47
  4131.       .db $4a, $47, $4a, $47, $4a
  4132.       .db $4b, $47, $4b, $47, $4b
  4133.  
  4134. CastleObject:
  4135.             jsr GetLrgObjAttrib      ;save lower nybble as starting row
  4136.         if Z80OPT3hy
  4137.           ld hy,e;  sty SCRATCHPAD+$07                  ;if starting row is above $0a, game will crash!!!
  4138.         else
  4139.             sty SCRATCHPAD+$07                  ;if starting row is above $0a, game will crash!!!
  4140.         endif
  4141.             ldyn ++$04
  4142.             jsr ChkLrgObjFixedLength ;load length of castle if not already loaded
  4143.             txa                  
  4144.             pha                      ;save obj buffer offset to stack
  4145.             ldyx AreaObjectLength,x   ;use current length as offset for castle data
  4146.         if Z80OPT3hy
  4147.           ld c,hy;ldx SCRATCHPAD+$07     ;begin at starting row
  4148.         else
  4149.             ldx SCRATCHPAD+$07                  ;begin at starting row
  4150.         endif
  4151.             ldan ++$0b
  4152.             sta SCRATCHPAD+$06                  ;load upper limit of number of rows to print
  4153. CRendLoop:  lday CastleMetatiles,y    ;load current byte using offset
  4154.             stax MetatileBuffer,x
  4155.             inx                      ;store in buffer and increment buffer offset
  4156.             lda SCRATCHPAD+$06
  4157.          checka
  4158.             beq ChkCFloor            ;have we reached upper limit yet?
  4159.             iny                      ;if not, increment column-wise
  4160.             iny                      ;to byte in next row
  4161.             iny
  4162.             iny
  4163.             iny
  4164.             deci SCRATCHPAD+$06                  ;move closer to upper limit
  4165. ChkCFloor:  cpxn ++$0b                 ;have we reached the row just before floor?
  4166.             bne CRendLoop            ;if not, go back and do another row
  4167.             pla
  4168.             tax                      ;get obj buffer offset from before
  4169.             lda CurrentPageLoc
  4170.          checka
  4171.             beq ExitCastle           ;if we're at page 0, we do not need to do anything else
  4172.             ldax AreaObjectLength,x   ;check length
  4173.             cmpn ++$01                 ;if length almost about to expire, put brick at floor
  4174.             beq PlayerStop
  4175.         if Z80OPT3hy
  4176.          if Z80OPT3hybug
  4177.            ld c,hy;ldy SCRATCHPAD+$07                  ;check starting row for tall castle ($00) ;т Ёхышчх тъы■ўрЄ№ эх эрфю!
  4178.          else
  4179.            ld e,hy;ldy SCRATCHPAD+$07                  ;check starting row for tall castle ($00)
  4180.          endif
  4181.         else
  4182.             ldy SCRATCHPAD+$07                  ;check starting row for tall castle ($00)
  4183.         endif
  4184.          checky
  4185.             bne NotTall
  4186.             cmpn ++$03                 ;if found, then check to see if we're at the second column
  4187.             beq PlayerStop
  4188. NotTall:    cmpn ++$02                 ;if not tall castle, check to see if we're at the third column
  4189.             bne ExitCastle           ;if we aren't and the castle is tall, don't create flag yet
  4190.             jsr GetAreaObjXPosition  ;otherwise, obtain and save horizontal pixel coordinate
  4191.             pha
  4192.             jsr FindEmptyEnemySlot   ;find an empty place on the enemy object buffer
  4193.             pla
  4194.             stax Enemy_X_Position,x   ;then write horizontal coordinate for star flag
  4195.             lda CurrentPageLoc
  4196.             stax Enemy_PageLoc,x      ;set page location for star flag
  4197.             ldan ++$01
  4198.             stax Enemy_Y_HighPos,x    ;set vertical high byte
  4199.             stax Enemy_Flag,x         ;set flag for buffer
  4200.             ldan ++$90
  4201.             stax Enemy_Y_Position,x   ;set vertical coordinate
  4202.             ldan ++StarFlagObject      ;set star flag value in buffer itself
  4203.             stax Enemy_ID,x
  4204.             rts
  4205. PlayerStop: ldyn ++$52                 ;put brick at floor to stop player at end of level
  4206.             sty MetatileBuffer+10    ;this is only done if we're on the second column
  4207. ExitCastle: rts
  4208.  
  4209. ;--------------------------------
  4210.  
  4211. WaterPipe:
  4212.       jsr GetLrgObjAttrib     ;get row and lower nybble
  4213.       ldyx AreaObjectLength,x  ;get length (residual code, water pipe is 1 col thick)
  4214.         if Z80OPT3hy
  4215.       ld c,hy;ldx SCRATCHPAD+$07                 ;get row
  4216.         else
  4217.       ldx SCRATCHPAD+$07                 ;get row
  4218.         endif
  4219.       ldan ++$6b
  4220.       stax MetatileBuffer,x    ;draw something here and below it
  4221.       ldan ++$6c
  4222.       stax MetatileBuffer+1,x
  4223.       rts
  4224.  
  4225. ;--------------------------------
  4226. ;$05 - used to store length of vertical shaft in RenderSidewaysPipe
  4227. ;$06 - used to store leftover horizontal length in RenderSidewaysPipe
  4228. ; and vertical length in VerticalPipe and GetPipeHeight
  4229.  
  4230. IntroPipe:
  4231.                ldyn ++$03                 ;check if length set, if not set, set it
  4232.                jsr ChkLrgObjFixedLength
  4233.                ldyn ++$0a                 ;set fixed value and render the sideways part
  4234.                jsr RenderSidewaysPipe
  4235.                bcs NoBlankP             ;if carry flag set, not time to draw vertical pipe part
  4236.                ldxn ++$06                 ;blank everything above the vertical pipe part
  4237. VPipeSectLoop: ldan ++$00                 ;all the way to the top of the screen
  4238.                stax MetatileBuffer,x     ;because otherwise it will look like exit pipe
  4239.                dex
  4240.                bpl VPipeSectLoop
  4241.                lday VerticalPipeData,y   ;draw the end of the vertical pipe part
  4242.                sta MetatileBuffer+7
  4243. NoBlankP:      rts
  4244.  
  4245. SidePipeShaftData:
  4246.       .db $15, $14  ;used to control whether or not vertical pipe shaft
  4247.       .db $00, $00  ;is drawn, and if so, controls the metatile number
  4248. SidePipeTopPart:
  4249.       .db $15, $1e  ;top part of sideways part of pipe
  4250.       .db $1d, $1c
  4251. SidePipeBottomPart:
  4252.       .db $15, $21  ;bottom part of sideways part of pipe
  4253.       .db $20, $1f
  4254.  
  4255. ExitPipe:
  4256.       ldyn ++$03                 ;check if length set, if not set, set it
  4257.       jsr ChkLrgObjFixedLength
  4258.       jsr GetLrgObjAttrib      ;get vertical length, then plow on through RenderSidewaysPipe
  4259.  
  4260. RenderSidewaysPipe:
  4261.               dey                       ;decrement twice to make room for shaft at bottom
  4262.               dey                       ;and store here for now as vertical length
  4263.               sty SCRATCHPAD+$05
  4264.               ldyx AreaObjectLength,x    ;get length left over and store here
  4265.               sty SCRATCHPAD+$06
  4266.               ldx SCRATCHPAD+$05                   ;get vertical length plus one, use as buffer offset
  4267.               inx
  4268.               lday SidePipeShaftData,y   ;check for value $00 based on horizontal offset
  4269.               cmpn ++$00
  4270.                cmpcy
  4271.               beq DrawSidePart          ;if found, do not draw the vertical pipe shaft (CY6502=1)
  4272.               ldxn ++$00
  4273.               ldy SCRATCHPAD+$05                   ;init buffer offset and get vertical length
  4274.               jsr RenderUnderPart       ;and render vertical shaft using tile number in A
  4275.               clc                       ;clear carry flag to be used by IntroPipe
  4276. DrawSidePart:
  4277.                 push af
  4278.                 ldy SCRATCHPAD+$06                   ;render side pipe part at the bottom
  4279.               lday SidePipeTopPart,y
  4280.               stax MetatileBuffer,x      ;note that the pipe parts are stored
  4281.               lday SidePipeBottomPart,y  ;backwards horizontally
  4282.               stax MetatileBuffer+1,x
  4283.                pop af
  4284.               rts
  4285.  
  4286. VerticalPipeData:
  4287.       .db $11, $10 ;used by pipes that lead somewhere
  4288.       .db $15, $14
  4289.       .db $13, $12 ;used by decoration pipes
  4290.       .db $15, $14
  4291.  
  4292. VerticalPipe:
  4293.           jsr GetPipeHeight
  4294.           lda SCRATCHPAD+$00                  ;check to see if value was nullified earlier
  4295.          checka
  4296.           beq WarpPipe             ;(if d3, the usage control bit of second byte, was set)
  4297.           iny
  4298.           iny
  4299.           iny
  4300.           iny                      ;add four if usage control bit was not set
  4301. WarpPipe: tya                      ;save value in stack
  4302.           pha
  4303.           lda AreaNumber
  4304.           orai WorldNumber          ;if at world 1-1, do not add piranha plant ever
  4305.         if NOPIRANHAPLANT
  4306.         xor a
  4307.         endif
  4308.           beq DrawPipe
  4309.           ldyx AreaObjectLength,x   ;if on second column of pipe, branch
  4310.          checky
  4311.           beq DrawPipe             ;(because we only need to do this once)
  4312.           jsr FindEmptyEnemySlot   ;check for an empty moving data buffer space
  4313.           bcs DrawPipe             ;if not found, too many enemies, thus skip
  4314.           jsr GetAreaObjXPosition  ;get horizontal pixel coordinate
  4315.           clc
  4316.           adcn ++$08                 ;add eight to put the piranha plant in the center
  4317.          push af
  4318.           stax Enemy_X_Position,x   ;store as enemy's horizontal coordinate
  4319.           lda CurrentPageLoc       ;add carry to current page number
  4320.          ld h,a
  4321.          pop af
  4322.          ld a,h
  4323.           adcn ++$00
  4324.           stax Enemy_PageLoc,x      ;store as enemy's page coordinate
  4325.           ldan ++$01
  4326.           stax Enemy_Y_HighPos,x
  4327.           stax Enemy_Flag,x         ;activate enemy flag
  4328.           jsr GetAreaObjYPosition  ;get piranha plant's vertical coordinate and store here
  4329.           stax Enemy_Y_Position,x
  4330.           ldan ++PiranhaPlant        ;write piranha plant's value into buffer
  4331.           stax Enemy_ID,x
  4332.           jsr InitPiranhaPlant
  4333. DrawPipe: pla                      ;get value saved earlier and use as Y
  4334.           tay
  4335.         if Z80OPT3hy
  4336.           ld c,hy;ldx SCRATCHPAD+$07                  ;get buffer offset
  4337.         else
  4338.           ldx SCRATCHPAD+$07                  ;get buffer offset
  4339.         endif
  4340.           lday VerticalPipeData,y   ;draw the appropriate pipe with the Y we loaded earlier
  4341.           stax MetatileBuffer,x     ;render the top of the pipe
  4342.           inx
  4343.           lday VerticalPipeData+2,y ;render the rest of the pipe
  4344.           ldy SCRATCHPAD+$06                  ;subtract one from length and render the part underneath
  4345.           dey
  4346.           jmp RenderUnderPart
  4347.      
  4348. GetPipeHeight:
  4349.       ldyn ++$01       ;check for length loaded, if not, load
  4350.       jsr ChkLrgObjFixedLength ;pipe length of 2 (horizontal)
  4351.       jsr GetLrgObjAttrib
  4352.       tya            ;get saved lower nybble as height
  4353.       andn ++$07       ;save only the three lower bits as
  4354.       sta SCRATCHPAD+$06        ;vertical length, then load Y with
  4355.       ldyx AreaObjectLength,x    ;length left over
  4356.       rts
  4357.  
  4358. FindEmptyEnemySlot:
  4359.               ldxn ++$00          ;start at first enemy slot
  4360. EmptyChkLoop: clc               ;clear carry flag by default
  4361.               ldax Enemy_Flag,x  ;check enemy buffer for nonzero
  4362.          checka
  4363.               beq ExitEmptyChk  ;if zero, leave
  4364.               inx
  4365.               cpxn ++$05          ;if nonzero, check next value
  4366.               bne EmptyChkLoop
  4367. ExitEmptyChk: rts               ;if all values nonzero, carry flag is set
  4368.  
  4369. ;--------------------------------
  4370.  
  4371. Hole_Water:
  4372.       jsr ChkLrgObjLength   ;get low nybble and save as length
  4373.       ldan ++$86              ;render waves
  4374.       sta MetatileBuffer+10
  4375.       ldxn ++$0b
  4376.       ldyn ++$01              ;now render the water underneath
  4377.       ldan ++$87
  4378.       jmp RenderUnderPart
  4379.  
  4380. ;--------------------------------
  4381.  
  4382. QuestionBlockRow_High:
  4383.       ldan ++$03    ;start on the fourth row
  4384.       jr QuestionBlockRow_go;.db $2c     ;BIT instruction opcode
  4385.  
  4386. QuestionBlockRow_Low:
  4387.       ldan ++$07             ;start on the eighth row
  4388. QuestionBlockRow_go
  4389.       pha                  ;save whatever row to the stack for now
  4390.       jsr ChkLrgObjLength  ;get low nybble and save as length
  4391.       pla
  4392.       tax                  ;render question boxes with coins
  4393.       ldan ++$c0
  4394.       stax MetatileBuffer,x
  4395.       rts
  4396.  
  4397. ;--------------------------------
  4398.  
  4399. Bridge_High:
  4400.       ldan ++$06  ;start on the seventh row from top of screen
  4401.       jr Bridge_go;.db $2c   ;BIT instruction opcode
  4402.  
  4403. Bridge_Middle:
  4404.       ldan ++$07  ;start on the eighth row
  4405.       jr Bridge_go;.db $2c   ;BIT instruction opcode
  4406.  
  4407. Bridge_Low:
  4408.       ldan ++$09             ;start on the tenth row
  4409. Bridge_go
  4410.       pha                  ;save whatever row to the stack for now
  4411.       jsr ChkLrgObjLength  ;get low nybble and save as length
  4412.       pla
  4413.       tax                  ;render bridge railing
  4414.       ldan ++$0b
  4415.       stax MetatileBuffer,x
  4416.       inx
  4417.       ldyn ++$00             ;now render the bridge itself
  4418.       ldan ++$63
  4419.       jmp RenderUnderPart
  4420.  
  4421. ;--------------------------------
  4422.  
  4423. FlagBalls_Residual:
  4424.       jsr GetLrgObjAttrib  ;get low nybble from object byte
  4425.       ldxn ++$02             ;render flag balls on third row from top
  4426.       ldan ++$6d             ;of screen downwards based on low nybble
  4427.       jmp RenderUnderPart
  4428.  
  4429. ;--------------------------------
  4430.  
  4431. FlagpoleObject:
  4432.       ldan ++$24                 ;render flagpole ball on top
  4433.       sta MetatileBuffer
  4434.       ldxn ++$01                 ;now render the flagpole shaft
  4435.       ldyn ++$08
  4436.       ldan ++$25
  4437.       jsr RenderUnderPart
  4438.       ldan ++$61                 ;render solid block at the bottom
  4439.       sta MetatileBuffer+10
  4440.       jsr GetAreaObjXPosition
  4441.       secsub                      ;get pixel coordinate of where the flagpole is,
  4442.       sbcn ++$08                 ;subtract eight pixels and use as horizontal
  4443.       sta Enemy_X_Position+5   ;coordinate for the flag
  4444.       lda CurrentPageLoc
  4445.       sbcn ++$00                 ;subtract borrow from page location and use as
  4446.       sta Enemy_PageLoc+5      ;page location for the flag
  4447.       ldan ++$30
  4448.       sta Enemy_Y_Position+5   ;set vertical coordinate for flag
  4449.       ldan ++$b0
  4450.       sta FlagpoleFNum_Y_Pos   ;set initial vertical coordinate for flagpole's floatey number
  4451.       ldan ++FlagpoleFlagObject
  4452.       sta Enemy_ID+5           ;set flag identifier, note that identifier and coordinates
  4453.       inci Enemy_Flag+5         ;use last space in enemy object buffer
  4454.       rts
  4455.  
  4456. ;--------------------------------
  4457.  
  4458. EndlessRope:
  4459.       ldxn ++$00       ;render rope from the top to the bottom of screen
  4460.       ldyn ++$0f
  4461.       jmp DrawRope
  4462.  
  4463. BalancePlatRope:
  4464.           txa                 ;save object buffer offset for now
  4465.           pha
  4466.           ldxn ++$01            ;blank out all from second row to the bottom
  4467.           ldyn ++$0f            ;with blank used for balance platform rope
  4468.           ldan ++$44
  4469.           jsr RenderUnderPart
  4470.           pla                 ;get back object buffer offset
  4471.           tax
  4472.           jsr GetLrgObjAttrib ;get vertical length from lower nybble
  4473.           ldxn ++$01
  4474. DrawRope: ldan ++$40            ;render the actual rope
  4475.           jmp RenderUnderPart
  4476.  
  4477. ;--------------------------------
  4478.  
  4479. CoinMetatileData:
  4480.       .db $c3, $c2, $c2, $c2
  4481.  
  4482. RowOfCoins:
  4483.       ldy AreaType            ;get area type
  4484.       lday CoinMetatileData,y  ;load appropriate coin metatile
  4485.       jmp GetRow
  4486.  
  4487. ;--------------------------------
  4488.  
  4489. C_ObjectRow:
  4490.       .db $06, $07, $08
  4491.  
  4492. C_ObjectMetatile:
  4493.       .db $c5, $0c, $89
  4494.  
  4495. CastleBridgeObj:
  4496.       ldyn ++$0c                  ;load length of 13 columns
  4497.       jsr ChkLrgObjFixedLength
  4498.       jmp ChainObj
  4499.  
  4500. AxeObj:
  4501.       ldan ++$08                  ;load bowser's palette into sprite portion of palette
  4502.       sta VRAM_Buffer_AddrCtrl
  4503.  
  4504. ChainObj:
  4505.       ldy SCRATCHPAD+$00                   ;get value loaded earlier from decoder
  4506.       ldxy C_ObjectRow-2,y       ;get appropriate row and metatile for object
  4507.       lday C_ObjectMetatile-2,y
  4508.       jmp ColObj
  4509.  
  4510. EmptyBlock:
  4511.         jsr GetLrgObjAttrib  ;get row location
  4512.        if Z80OPT3hy
  4513.         ld c,hy;ldx SCRATCHPAD+$07
  4514.        else
  4515.         ldx SCRATCHPAD+$07
  4516.        endif
  4517.         ldan ++$c4
  4518. ColObj: ldyn ++$00             ;column length of 1
  4519.         jmp RenderUnderPart
  4520.  
  4521. ;--------------------------------
  4522.  
  4523. SolidBlockMetatiles:
  4524.       .db $69, $61, $61, $62
  4525.  
  4526. BrickMetatiles:
  4527.       .db $22, $51, $52, $52
  4528.       .db $88 ;used only by row of bricks object
  4529.  
  4530. RowOfBricks:
  4531.             ldy AreaType           ;load area type obtained from area offset pointer
  4532.             lda CloudTypeOverride  ;check for cloud type override
  4533.          checka
  4534.             beq DrawBricks
  4535.             ldyn ++$04               ;if cloud type, override area type
  4536. DrawBricks: lday BrickMetatiles,y   ;get appropriate metatile
  4537.             jmp GetRow             ;and go render it
  4538.  
  4539. RowOfSolidBlocks:
  4540.          ldy AreaType               ;load area type obtained from area offset pointer
  4541.          lday SolidBlockMetatiles,y  ;get metatile
  4542. GetRow:  pha                        ;store metatile here
  4543.          jsr ChkLrgObjLength        ;get row number, load length
  4544. DrawRow:
  4545.        if Z80OPT3hy
  4546.          ld c,hy;ldx SCRATCHPAD+$07
  4547.        else
  4548.          ldx SCRATCHPAD+$07
  4549.        endif
  4550.          ldyn ++$00                   ;set vertical height of 1
  4551.          pla
  4552.          jmp RenderUnderPart        ;render object
  4553.  
  4554. ColumnOfBricks:
  4555.       ldy AreaType          ;load area type obtained from area offset
  4556.       lday BrickMetatiles,y  ;get metatile (no cloud override as for row)
  4557.       jmp GetRow2
  4558.  
  4559. ColumnOfSolidBlocks:
  4560.          ldy AreaType               ;load area type obtained from area offset
  4561.          lday SolidBlockMetatiles,y  ;get metatile
  4562. GetRow2: pha                        ;save metatile to stack for now
  4563.          jsr GetLrgObjAttrib        ;get length and row
  4564.          pla                        ;restore metatile
  4565.        if Z80OPT3hy
  4566.          ld c,hy;ldx SCRATCHPAD+$07                    ;get starting row
  4567.        else
  4568.          ldx SCRATCHPAD+$07                    ;get starting row
  4569.        endif
  4570.          jmp RenderUnderPart        ;now render the column
  4571.  
  4572. ;--------------------------------
  4573.  
  4574. BulletBillCannon:
  4575.              jsr GetLrgObjAttrib      ;get row and length of bullet bill cannon
  4576.        if Z80OPT3hy
  4577.              ld c,hy;ldx SCRATCHPAD+$07                  ;start at first row
  4578.        else
  4579.              ldx SCRATCHPAD+$07                  ;start at first row
  4580.        endif
  4581.              ldan ++$64                 ;render bullet bill cannon
  4582.              stax MetatileBuffer,x
  4583.              inx
  4584.              dey                      ;done yet?
  4585.              bmi SetupCannon
  4586.              ldan ++$65                 ;if not, render middle part
  4587.              stax MetatileBuffer,x
  4588.              inx
  4589.              dey                      ;done yet?
  4590.              bmi SetupCannon
  4591.              ldan ++$66                 ;if not, render bottom until length expires
  4592.              jsr RenderUnderPart
  4593. SetupCannon: ldx Cannon_Offset        ;get offset for data used by cannons and whirlpools
  4594.              jsr GetAreaObjYPosition  ;get proper vertical coordinate for cannon
  4595.              stax Cannon_Y_Position,x  ;and store it here
  4596.              lda CurrentPageLoc
  4597.              stax Cannon_PageLoc,x     ;store page number for cannon here
  4598.              jsr GetAreaObjXPosition  ;get proper horizontal coordinate for cannon
  4599.              stax Cannon_X_Position,x  ;and store it here
  4600.              inx
  4601.              cpxn ++$06                 ;increment and check offset
  4602.               cmpcy
  4603.              bcc StrCOffset           ;if not yet reached sixth cannon, branch to save offset
  4604.              ldxn ++$00                 ;otherwise initialize it
  4605. StrCOffset:  stx Cannon_Offset        ;save new offset and leave
  4606.              rts
  4607.  
  4608. ;--------------------------------
  4609.  
  4610. StaircaseHeightData:
  4611.       .db $07, $07, $06, $05, $04, $03, $02, $01, $00
  4612.  
  4613. StaircaseRowData:
  4614.       .db $03, $03, $04, $05, $06, $07, $08, $09, $0a
  4615.  
  4616. StaircaseObject:
  4617.            jsr ChkLrgObjLength       ;check and load length
  4618.            bcc NextStair             ;if length already loaded, skip init part
  4619.            ldan ++$09                  ;start past the end for the bottom
  4620.            sta StaircaseControl      ;of the staircase
  4621. NextStair: deci StaircaseControl      ;move onto next step (or first if starting)
  4622.            ldy StaircaseControl
  4623.            ldxy StaircaseRowData,y    ;get starting row and height to render
  4624.            lday StaircaseHeightData,y
  4625.            tay
  4626.            ldan ++$61                  ;now render solid block staircase
  4627.            jmp RenderUnderPart
  4628.  
  4629. ;--------------------------------
  4630.  
  4631. Jumpspring:
  4632.       jsr GetLrgObjAttrib
  4633.       jsr FindEmptyEnemySlot      ;find empty space in enemy object buffer
  4634.       jsr GetAreaObjXPosition     ;get horizontal coordinate for jumpspring
  4635.       stax Enemy_X_Position,x      ;and store
  4636.       lda CurrentPageLoc          ;store page location of jumpspring
  4637.       stax Enemy_PageLoc,x
  4638.       jsr GetAreaObjYPosition     ;get vertical coordinate for jumpspring
  4639.       stax Enemy_Y_Position,x      ;and store
  4640.       stax Jumpspring_FixedYPos,x  ;store as permanent coordinate here
  4641.       ldan ++JumpspringObject
  4642.       stax Enemy_ID,x              ;write jumpspring object to enemy object buffer
  4643.       ldyn ++$01
  4644.       styx Enemy_Y_HighPos,x       ;store vertical high byte
  4645.       incx Enemy_Flag,x            ;set flag for enemy object buffer
  4646.        if Z80OPT3hy
  4647.       ld c,hy;ldx SCRATCHPAD+$07
  4648.        else
  4649.       ldx SCRATCHPAD+$07
  4650.        endif
  4651.       ldan ++$67                    ;draw metatiles in two rows where jumpspring is
  4652.       stax MetatileBuffer,x
  4653.       ldan ++$68
  4654.       stax MetatileBuffer+1,x
  4655.       rts
  4656.  
  4657. ;--------------------------------
  4658. ;$07 - used to save ID of brick object
  4659.  
  4660. Hidden1UpBlock:
  4661.       lda Hidden1UpFlag  ;if flag not set, do not render object
  4662.          checka
  4663.       beq ExitDecBlock
  4664.       ldan ++$00           ;if set, init for the next one
  4665.       sta Hidden1UpFlag
  4666.       jmp BrickWithItem  ;jump to code shared with unbreakable bricks
  4667.  
  4668. QuestionBlock:
  4669.       jsr GetAreaObjectID ;get value from level decoder routine
  4670.       jmp DrawQBlk        ;go to render it
  4671.  
  4672. BrickWithCoins:
  4673.       ldan ++$00                 ;initialize multi-coin timer flag
  4674.       sta BrickCoinTimerFlag
  4675.  
  4676. BrickWithItem:
  4677.           jsr GetAreaObjectID         ;save area object ID
  4678.        if Z80OPT3hy
  4679.           ld hy,e;sty SCRATCHPAD+$07              
  4680.        else
  4681.           sty SCRATCHPAD+$07              
  4682.        endif
  4683.           ldan ++$00                    ;load default adder for bricks with lines
  4684.           ldy AreaType                ;check level type for ground level
  4685.           dey
  4686.           beq BWithL                  ;if ground type, do not start with 5
  4687.           ldan ++$05                    ;otherwise use adder for bricks without lines
  4688. BWithL:  
  4689.        if Z80OPT3hy
  4690.           ;clc                         ;add object ID to adder
  4691.           add a,hy;adci SCRATCHPAD+$07
  4692.        else
  4693.           clc                         ;add object ID to adder
  4694.           adci SCRATCHPAD+$07
  4695.        endif
  4696.           tay                         ;use as offset for metatile
  4697. DrawQBlk: lday BrickQBlockMetatiles,y  ;get appropriate metatile for brick (question block
  4698.           pha                         ;if branched to here from question block routine)
  4699.           jsr GetLrgObjAttrib         ;get row from location byte
  4700.           jmp DrawRow                 ;now render the object
  4701.  
  4702. GetAreaObjectID:
  4703.               lda SCRATCHPAD+$00    ;get value saved from area parser routine
  4704.               secsub
  4705.               sbcn ++$00   ;possibly residual code
  4706.               tay        ;save to Y
  4707. ExitDecBlock: rts
  4708.  
  4709. ;--------------------------------
  4710.  
  4711. HoleMetatiles:
  4712.       .db $87, $00, $00, $00
  4713.  
  4714. Hole_Empty:
  4715.             jsr ChkLrgObjLength          ;get lower nybble and save as length
  4716.             bcc NoWhirlP                 ;skip this part if length already loaded
  4717.             lda AreaType                 ;check for water type level
  4718.          checka
  4719.             bne NoWhirlP                 ;if not water type, skip this part
  4720.             ldx Whirlpool_Offset         ;get offset for data used by cannons and whirlpools
  4721.             jsr GetAreaObjXPosition      ;get proper vertical coordinate of where we're at
  4722.             secsub
  4723.             sbcn ++$10                     ;subtract 16 pixels
  4724.            push af
  4725.             stax Whirlpool_LeftExtent,x   ;store as left extent of whirlpool
  4726.            pop af
  4727.             lda CurrentPageLoc           ;get page location of where we're at
  4728.             sbcn ++$00                     ;subtract borrow
  4729.             stax Whirlpool_PageLoc,x      ;save as page location of whirlpool
  4730.             iny
  4731.             iny                          ;increment length by 2
  4732.             tya
  4733.             asl                          ;multiply by 16 to get size of whirlpool
  4734.             asl                          ;note that whirlpool will always be
  4735.             asl                          ;two blocks bigger than actual size of hole
  4736.             asl                          ;and extend one block beyond each edge
  4737.             stax Whirlpool_Length,x       ;save size of whirlpool here
  4738.             inx
  4739.             cpxn ++$05                     ;increment and check offset
  4740.               cmpcy
  4741.             bcc StrWOffset               ;if not yet reached fifth whirlpool, branch to save offset
  4742.             ldxn ++$00                     ;otherwise initialize it
  4743. StrWOffset: stx Whirlpool_Offset         ;save new offset here
  4744. NoWhirlP:   ldx AreaType                 ;get appropriate metatile, then
  4745.             ldax HoleMetatiles,x          ;render the hole proper
  4746.             ldxn ++$08
  4747.             ldyn ++$0f                     ;start at ninth row and go to bottom, run RenderUnderPart
  4748.  
  4749. ;--------------------------------
  4750.  
  4751. RenderUnderPart:
  4752.              sty AreaObjectHeight  ;store vertical length to render
  4753.              ldyx MetatileBuffer,x  ;check current spot to see if there's something
  4754.          checky
  4755.              beq DrawThisRow       ;we need to keep, if nothing, go ahead
  4756.              cpyn ++$17
  4757.              beq WaitOneRow        ;if middle part (tree ledge), wait until next row
  4758.              cpyn ++$1a
  4759.              beq WaitOneRow        ;if middle part (mushroom ledge), wait until next row
  4760.              cpyn ++$c0
  4761.              beq DrawThisRow       ;if question block w/ coin, overwrite
  4762.              cpyn ++$c0
  4763.               cmpcy
  4764.              bcs WaitOneRow        ;if any other metatile with palette 3, wait until next row
  4765.              cpyn ++$54
  4766.              bne DrawThisRow       ;if cracked rock terrain, overwrite
  4767.              cmpn ++$50
  4768.              beq WaitOneRow        ;if stem top of mushroom, wait until next row
  4769. DrawThisRow: stax MetatileBuffer,x  ;render contents of A from routine that called this
  4770. WaitOneRow:  inx
  4771.              cpxn ++$0d              ;stop rendering if we're at the bottom of the screen
  4772.               cmpcy
  4773.              bcs ExitUPartR
  4774.              ldy AreaObjectHeight  ;decrement, and stop rendering if there is no more length
  4775.              dey
  4776.              bpl RenderUnderPart
  4777. ExitUPartR:  rts
  4778.  
  4779. ;--------------------------------
  4780.  
  4781. ChkLrgObjLength:
  4782.         jsr GetLrgObjAttrib     ;get row location and size (length if branched to from here)
  4783.  
  4784. ChkLrgObjFixedLength:
  4785.         ldax AreaObjectLength,x  ;check for set length counter
  4786.         clc                     ;clear carry flag for not just starting
  4787.          checka
  4788.         bpl LenSet              ;if counter not set, load it, otherwise leave alone
  4789.         tya                     ;save length into length counter
  4790.         stax AreaObjectLength,x
  4791.         sec                     ;set carry flag if just starting
  4792. LenSet: rts
  4793.  
  4794.  
  4795. GetLrgObjAttrib:
  4796. ;x=???
  4797. ;y=AreaData offset
  4798.       ldyx AreaObjOffsetBuffer,x ;get offset saved from area obj decoding routine
  4799.       ldayindirect (AreaData),y          ;get first byte of level object
  4800.       andn ++%00001111
  4801.        if Z80OPT3hy
  4802.       ld hy,a;sta SCRATCHPAD+$07                   ;save row location
  4803.        else
  4804.       sta SCRATCHPAD+$07                   ;save row location
  4805.        endif
  4806.       iny
  4807.       ldayindirect (AreaData),y          ;get next byte, save lower nybble (length or height)
  4808.       andn ++%00001111            ;as Y, then leave
  4809.       tay
  4810.       rts
  4811.  
  4812. ;--------------------------------
  4813.  
  4814. GetAreaObjXPosition:
  4815.       lda CurrentColumnPos    ;multiply current offset where we're at by 16
  4816.       asl                     ;to obtain horizontal pixel coordinate
  4817.       asl
  4818.       asl
  4819.       asl
  4820.       rts
  4821.  
  4822. ;--------------------------------
  4823.  
  4824. GetAreaObjYPosition:
  4825.        if Z80OPT3hy
  4826.       ld a,hy;lda SCRATCHPAD+$07
  4827.        else
  4828.       lda SCRATCHPAD+$07  
  4829.        endif
  4830.       asl     ;multiply value by 16
  4831.       asl      ;this will give us the proper vertical pixel coordinate
  4832.       asl
  4833.       asl
  4834.       clc
  4835.       adcn ++32  ;add 32 pixels for the status bar
  4836.       rts
  4837.  
  4838. ;-------------------------------------------------------------------------------------
  4839. ;$06-$07 - used to store block buffer address used as indirect
  4840.  
  4841.         if Z80OPT
  4842.         else
  4843. BlockBufferAddr:
  4844.       .db LOW Block_Buffer_1, LOW Block_Buffer_2
  4845.       .db HIGH Block_Buffer_1, HIGH Block_Buffer_2
  4846.  
  4847. ;a=%000hllll
  4848. ;out: $06$07 = BlockBufferAddr[i]+%llll
  4849. GetBlockBufferAddr:
  4850.      pha                      ;take value of A, save
  4851.       lsr                      ;move high nybble to low
  4852.       lsr
  4853.       lsr
  4854.       lsr
  4855.       tay                      ;use nybble as pointer to high byte
  4856.       lday BlockBufferAddr+2,y  ;of indirect here
  4857.       sta SCRATCHPAD+$07
  4858.      pla
  4859.       andn ++%00001111           ;pull from stack, mask out high nybble
  4860.       clc
  4861.       adcy BlockBufferAddr,y    ;add to low byte
  4862.       sta SCRATCHPAD+$06                  ;store here and leave
  4863.       rts
  4864.         endif
  4865.  
  4866. ;-------------------------------------------------------------------------------------
  4867.  
  4868. ;unused space
  4869.       .db $ff, $ff
  4870.  
  4871. ;-------------------------------------------------------------------------------------
  4872.  
  4873. AreaDataOfsLoopback:
  4874.       .db $12, $36, $0e, $0e, $0e, $32, $32, $32, $0a, $26, $40
  4875.  
  4876. ;-------------------------------------------------------------------------------------
  4877.  
  4878. LoadAreaPointer:
  4879.              jsr FindAreaPointer  ;find it and store it here
  4880.              sta AreaPointer
  4881. GetAreaType: andn ++%01100000       ;mask out all but d6 and d5
  4882.              asl
  4883.              rol
  4884.              rol
  4885.              rol                  ;make %0xx00000 into %000000xx
  4886.              sta AreaType         ;save 2 MSB as area type
  4887.              rts
  4888.  
  4889. FindAreaPointer:
  4890.       ldy WorldNumber        ;load offset from world variable
  4891.       lday WorldAddrOffsets,y
  4892.       clc                    ;add area number used to find data
  4893.       adci AreaNumber
  4894.       tay
  4895.       lday AreaAddrOffsets,y  ;from there we have our area pointer
  4896.       rts
  4897.  
  4898.  
  4899. GetAreaDataAddrs:
  4900.             lda AreaPointer          ;use 2 MSB for Y
  4901.             jsr GetAreaType
  4902.             tay
  4903.             lda AreaPointer          ;mask out all but 5 LSB
  4904.             andn ++%00011111
  4905.             sta AreaAddrsLOffset     ;save as low offset
  4906.             lday EnemyAddrHOffsets,y  ;load base value with 2 altered MSB,
  4907.             clc                      ;then add base value to 5 LSB, result
  4908.             adci AreaAddrsLOffset     ;becomes offset for level data
  4909.             tay
  4910.             lday EnemyDataAddrLow,y   ;use offset to load pointer
  4911.             sta EnemyDataLow
  4912.             lday EnemyDataAddrHigh,y
  4913.             sta EnemyDataHigh
  4914.             ldy AreaType             ;use area type as offset
  4915.             lday AreaDataHOffsets,y   ;do the same thing but with different base value
  4916.             clc
  4917.             adci AreaAddrsLOffset        
  4918.             tay
  4919.             lday AreaDataAddrLow,y    ;use this offset to load another pointer
  4920.             sta AreaDataLow
  4921.             lday AreaDataAddrHigh,y
  4922.             sta AreaDataHigh
  4923.             ldyn ++$00                 ;load first byte of header
  4924.             ldayindirect (AreaData),y    
  4925.             pha                      ;save it to the stack for now
  4926.             andn ++%00000111           ;save 3 LSB for foreground scenery or bg color control
  4927.             cmpn ++$04
  4928.               cmpcy
  4929.             bcc StoreFore
  4930.             sta BackgroundColorCtrl  ;if 4 or greater, save value here as bg color control
  4931.             ldan ++$00
  4932. StoreFore:  sta ForegroundScenery    ;if less, save value here as foreground scenery
  4933.             pla                      ;pull byte from stack and push it back
  4934.             pha
  4935.             andn ++%00111000           ;save player entrance control bits
  4936.             lsr                      ;shift bits over to LSBs
  4937.             lsr
  4938.             lsr
  4939.             sta PlayerEntranceCtrl       ;save value here as player entrance control
  4940.             pla                      ;pull byte again but do not push it back
  4941.             andn ++%11000000           ;save 2 MSB for game timer setting
  4942.             clc
  4943.             rol                      ;rotate bits over to LSBs
  4944.             rol
  4945.             rol
  4946.             sta GameTimerSetting     ;save value here as game timer setting
  4947.             iny
  4948.             ldayindirect (AreaData),y         ;load second byte of header
  4949.             pha                      ;save to stack
  4950.             andn ++%00001111           ;mask out all but lower nybble
  4951.             sta TerrainControl
  4952.             pla                      ;pull and push byte to copy it to A
  4953.             pha
  4954.             andn ++%00110000           ;save 2 MSB for background scenery type
  4955.             lsr
  4956.             lsr                      ;shift bits to LSBs
  4957.             lsr
  4958.             lsr
  4959.             sta BackgroundScenery    ;save as background scenery
  4960.             pla          
  4961.             andn ++%11000000
  4962.             clc
  4963.             rol                      ;rotate bits over to LSBs
  4964.             rol
  4965.             rol
  4966.             cmpn ++%00000011           ;if set to 3, store here
  4967.             bne StoreStyle           ;and nullify other value
  4968.             sta CloudTypeOverride    ;otherwise store value in other place
  4969.             ldan ++$00
  4970. StoreStyle: sta AreaStyle
  4971.             lda AreaDataLow          ;increment area data address by 2 bytes
  4972.             clc
  4973.             adcn ++$02
  4974.             sta AreaDataLow
  4975.             lda AreaDataHigh
  4976.             adcn ++$00
  4977.             sta AreaDataHigh
  4978.             rts
  4979.  
  4980. ;-------------------------------------------------------------------------------------
  4981. ;GAME LEVELS DATA
  4982.  
  4983. WorldAddrOffsets:
  4984.       .db World1Areas-AreaAddrOffsets, World2Areas-AreaAddrOffsets
  4985.       .db World3Areas-AreaAddrOffsets, World4Areas-AreaAddrOffsets
  4986.       .db World5Areas-AreaAddrOffsets, World6Areas-AreaAddrOffsets
  4987.       .db World7Areas-AreaAddrOffsets, World8Areas-AreaAddrOffsets
  4988.  
  4989. AreaAddrOffsets:
  4990. World1Areas: .db $25, $29, $c0, $26, $60
  4991. World2Areas: .db $28, $29, $01, $27, $62
  4992. World3Areas: .db $24, $35, $20, $63
  4993. World4Areas: .db $22, $29, $41, $2c, $61
  4994. World5Areas: .db $2a, $31, $26, $62
  4995. World6Areas: .db $2e, $23, $2d, $60
  4996. World7Areas: .db $33, $29, $01, $27, $64
  4997. World8Areas: .db $30, $32, $21, $65
  4998.  
  4999. ;bonus area data offsets, included here for comparison purposes
  5000. ;underground bonus area  - c2
  5001. ;cloud area 1 (day)      - 2b
  5002. ;cloud area 2 (night)    - 34
  5003. ;water area (5-2/6-2)    - 00
  5004. ;water area (8-4)        - 02
  5005. ;warp zone area (4-2)    - 2f
  5006.  
  5007. EnemyAddrHOffsets:
  5008.       .db $1f, $06, $1c, $00
  5009.  
  5010. EnemyDataAddrLow:
  5011.       .db LOW E_CastleArea1, LOW E_CastleArea2, LOW E_CastleArea3, LOW E_CastleArea4, LOW E_CastleArea5, LOW E_CastleArea6
  5012.       .db LOW E_GroundArea1, LOW E_GroundArea2, LOW E_GroundArea3, LOW E_GroundArea4, LOW E_GroundArea5, LOW E_GroundArea6
  5013.       .db LOW E_GroundArea7, LOW E_GroundArea8, LOW E_GroundArea9, LOW E_GroundArea10, LOW E_GroundArea11, LOW E_GroundArea12
  5014.       .db LOW E_GroundArea13, LOW E_GroundArea14, LOW E_GroundArea15, LOW E_GroundArea16, LOW E_GroundArea17, LOW E_GroundArea18
  5015.       .db LOW E_GroundArea19, LOW E_GroundArea20, LOW E_GroundArea21, LOW E_GroundArea22, LOW E_UndergroundArea1
  5016.       .db LOW E_UndergroundArea2, LOW E_UndergroundArea3, LOW E_WaterArea1, LOW E_WaterArea2, LOW E_WaterArea3
  5017.  
  5018. EnemyDataAddrHigh:
  5019.       .db HIGH E_CastleArea1, HIGH E_CastleArea2, HIGH E_CastleArea3, HIGH E_CastleArea4, HIGH E_CastleArea5, HIGH E_CastleArea6
  5020.       .db HIGH E_GroundArea1, HIGH E_GroundArea2, HIGH E_GroundArea3, HIGH E_GroundArea4, HIGH E_GroundArea5, HIGH E_GroundArea6
  5021.       .db HIGH E_GroundArea7, HIGH E_GroundArea8, HIGH E_GroundArea9, HIGH E_GroundArea10, HIGH E_GroundArea11, HIGH E_GroundArea12
  5022.       .db HIGH E_GroundArea13, HIGH E_GroundArea14, HIGH E_GroundArea15, HIGH E_GroundArea16, HIGH E_GroundArea17, HIGH E_GroundArea18
  5023.       .db HIGH E_GroundArea19, HIGH E_GroundArea20, HIGH E_GroundArea21, HIGH E_GroundArea22, HIGH E_UndergroundArea1
  5024.       .db HIGH E_UndergroundArea2, HIGH E_UndergroundArea3, HIGH E_WaterArea1, HIGH E_WaterArea2, HIGH E_WaterArea3
  5025.  
  5026. AreaDataHOffsets:
  5027.       .db $00, $03, $19, $1c
  5028.  
  5029. AreaDataAddrLow:
  5030.       .db LOW L_WaterArea1, LOW L_WaterArea2, LOW L_WaterArea3, LOW L_GroundArea1, LOW L_GroundArea2, LOW L_GroundArea3
  5031.       .db LOW L_GroundArea4, LOW L_GroundArea5, LOW L_GroundArea6, LOW L_GroundArea7, LOW L_GroundArea8, LOW L_GroundArea9
  5032.       .db LOW L_GroundArea10, LOW L_GroundArea11, LOW L_GroundArea12, LOW L_GroundArea13, LOW L_GroundArea14, LOW L_GroundArea15
  5033.       .db LOW L_GroundArea16, LOW L_GroundArea17, LOW L_GroundArea18, LOW L_GroundArea19, LOW L_GroundArea20, LOW L_GroundArea21
  5034.       .db LOW L_GroundArea22, LOW L_UndergroundArea1, LOW L_UndergroundArea2, LOW L_UndergroundArea3, LOW L_CastleArea1
  5035.       .db LOW L_CastleArea2, LOW L_CastleArea3, LOW L_CastleArea4, LOW L_CastleArea5, LOW L_CastleArea6
  5036.  
  5037. AreaDataAddrHigh:
  5038.       .db HIGH L_WaterArea1, HIGH L_WaterArea2, HIGH L_WaterArea3, HIGH L_GroundArea1, HIGH L_GroundArea2, HIGH L_GroundArea3
  5039.       .db HIGH L_GroundArea4, HIGH L_GroundArea5, HIGH L_GroundArea6, HIGH L_GroundArea7, HIGH L_GroundArea8, HIGH L_GroundArea9
  5040.       .db HIGH L_GroundArea10, HIGH L_GroundArea11, HIGH L_GroundArea12, HIGH L_GroundArea13, HIGH L_GroundArea14, HIGH L_GroundArea15
  5041.       .db HIGH L_GroundArea16, HIGH L_GroundArea17, HIGH L_GroundArea18, HIGH L_GroundArea19, HIGH L_GroundArea20, HIGH L_GroundArea21
  5042.       .db HIGH L_GroundArea22, HIGH L_UndergroundArea1, HIGH L_UndergroundArea2, HIGH L_UndergroundArea3, HIGH L_CastleArea1
  5043.       .db HIGH L_CastleArea2, HIGH L_CastleArea3, HIGH L_CastleArea4, HIGH L_CastleArea5, HIGH L_CastleArea6
  5044.  
  5045. ;ENEMY OBJECT DATA
  5046.  
  5047. ;level 1-4/6-4
  5048. E_CastleArea1:
  5049.       .db $76, $dd, $bb, $4c, $ea, $1d, $1b, $cc, $56, $5d
  5050.       .db $16, $9d, $c6, $1d, $36, $9d, $c9, $1d, $04, $db
  5051.       .db $49, $1d, $84, $1b, $c9, $5d, $88, $95, $0f, $08
  5052.       .db $30, $4c, $78, $2d, $a6, $28, $90, $b5
  5053.       .db $ff
  5054.  
  5055. ;level 4-4
  5056. E_CastleArea2:
  5057.       .db $0f, $03, $56, $1b, $c9, $1b, $0f, $07, $36, $1b
  5058.       .db $aa, $1b, $48, $95, $0f, $0a, $2a, $1b, $5b, $0c
  5059.       .db $78, $2d, $90, $b5
  5060.       .db $ff
  5061.  
  5062. ;level 2-4/5-4
  5063. E_CastleArea3:
  5064.       .db $0b, $8c, $4b, $4c, $77, $5f, $eb, $0c, $bd, $db
  5065.       .db $19, $9d, $75, $1d, $7d, $5b, $d9, $1d, $3d, $dd
  5066.       .db $99, $1d, $26, $9d, $5a, $2b, $8a, $2c, $ca, $1b
  5067.       .db $20, $95, $7b, $5c, $db, $4c, $1b, $cc, $3b, $cc
  5068.       .db $78, $2d, $a6, $28, $90, $b5
  5069.       .db $ff
  5070.  
  5071. ;level 3-4
  5072. E_CastleArea4:
  5073.       .db $0b, $8c, $3b, $1d, $8b, $1d, $ab, $0c, $db, $1d
  5074.       .db $0f, $03, $65, $1d, $6b, $1b, $05, $9d, $0b, $1b
  5075.       .db $05, $9b, $0b, $1d, $8b, $0c, $1b, $8c, $70, $15
  5076.       .db $7b, $0c, $db, $0c, $0f, $08, $78, $2d, $a6, $28
  5077.       .db $90, $b5
  5078.       .db $ff
  5079.  
  5080. ;level 7-4
  5081. E_CastleArea5:
  5082.       .db $27, $a9, $4b, $0c, $68, $29, $0f, $06, $77, $1b
  5083.       .db $0f, $0b, $60, $15, $4b, $8c, $78, $2d, $90, $b5
  5084.       .db $ff
  5085.  
  5086. ;level 8-4
  5087. E_CastleArea6:
  5088.       .db $0f, $03, $8e, $65, $e1, $bb, $38, $6d, $a8, $3e, $e5, $e7
  5089.       .db $0f, $08, $0b, $02, $2b, $02, $5e, $65, $e1, $bb, $0e
  5090.       .db $db, $0e, $bb, $8e, $db, $0e, $fe, $65, $ec, $0f, $0d
  5091.       .db $4e, $65, $e1, $0f, $0e, $4e, $02, $e0, $0f, $10, $fe, $e5, $e1
  5092.       .db $1b, $85, $7b, $0c, $5b, $95, $78, $2d, $90, $b5
  5093.       .db $ff
  5094.  
  5095. ;level 3-3
  5096. E_GroundArea1:
  5097.       .db $a5, $86, $e4, $28, $18, $a8, $45, $83, $69, $03
  5098.       .db $c6, $29, $9b, $83, $16, $a4, $88, $24, $e9, $28
  5099.       .db $05, $a8, $7b, $28, $24, $8f, $c8, $03, $e8, $03
  5100.       .db $46, $a8, $85, $24, $c8, $24
  5101.       .db $ff
  5102.  
  5103. ;level 8-3
  5104. E_GroundArea2:
  5105.       .db $eb, $8e, $0f, $03, $fb, $05, $17, $85, $db, $8e
  5106.       .db $0f, $07, $57, $05, $7b, $05, $9b, $80, $2b, $85
  5107.       .db $fb, $05, $0f, $0b, $1b, $05, $9b, $05
  5108.       .db $ff
  5109.  
  5110. ;level 4-1
  5111. E_GroundArea3:
  5112.       .db $2e, $c2, $66, $e2, $11, $0f, $07, $02, $11, $0f, $0c
  5113.       .db $12, $11
  5114.       .db $ff
  5115.  
  5116. ;level 6-2
  5117. E_GroundArea4:
  5118.       .db $0e, $c2, $a8, $ab, $00, $bb, $8e, $6b, $82, $de, $00, $a0
  5119.       .db $33, $86, $43, $06, $3e, $b4, $a0, $cb, $02, $0f, $07
  5120.       .db $7e, $42, $a6, $83, $02, $0f, $0a, $3b, $02, $cb, $37
  5121.       .db $0f, $0c, $e3, $0e
  5122.       .db $ff
  5123.  
  5124. ;level 3-1
  5125. E_GroundArea5:
  5126.       .db $9b, $8e, $ca, $0e, $ee, $42, $44, $5b, $86, $80, $b8
  5127.       .db $1b, $80, $50, $ba, $10, $b7, $5b, $00, $17, $85
  5128.       .db $4b, $05, $fe, $34, $40, $b7, $86, $c6, $06, $5b, $80
  5129.       .db $83, $00, $d0, $38, $5b, $8e, $8a, $0e, $a6, $00
  5130.       .db $bb, $0e, $c5, $80, $f3, $00
  5131.       .db $ff
  5132.  
  5133. ;level 1-1
  5134. E_GroundArea6:
  5135.       .db $1e, $c2, $00, $6b, $06, $8b, $86, $63, $b7, $0f, $05
  5136.       .db $03, $06, $23, $06, $4b, $b7, $bb, $00, $5b, $b7
  5137.       .db $fb, $37, $3b, $b7, $0f, $0b, $1b, $37
  5138.       .db $ff
  5139.  
  5140. ;level 1-3/5-3
  5141. E_GroundArea7:
  5142.       .db $2b, $d7, $e3, $03, $c2, $86, $e2, $06, $76, $a5
  5143.       .db $a3, $8f, $03, $86, $2b, $57, $68, $28, $e9, $28
  5144.       .db $e5, $83, $24, $8f, $36, $a8, $5b, $03
  5145.       .db $ff
  5146.  
  5147. ;level 2-3/7-3
  5148. E_GroundArea8:
  5149.       .db $0f, $02, $78, $40, $48, $ce, $f8, $c3, $f8, $c3
  5150.       .db $0f, $07, $7b, $43, $c6, $d0, $0f, $8a, $c8, $50
  5151.       .db $ff
  5152.  
  5153. ;level 2-1
  5154. E_GroundArea9:
  5155.       .db $85, $86, $0b, $80, $1b, $00, $db, $37, $77, $80
  5156.       .db $eb, $37, $fe, $2b, $20, $2b, $80, $7b, $38, $ab, $b8
  5157.       .db $77, $86, $fe, $42, $20, $49, $86, $8b, $06, $9b, $80
  5158.       .db $7b, $8e, $5b, $b7, $9b, $0e, $bb, $0e, $9b, $80
  5159. ;end of data terminator here is also used by pipe intro area
  5160. E_GroundArea10:
  5161.       .db $ff
  5162.  
  5163. ;level 5-1
  5164. E_GroundArea11:
  5165.       .db $0b, $80, $60, $38, $10, $b8, $c0, $3b, $db, $8e
  5166.       .db $40, $b8, $f0, $38, $7b, $8e, $a0, $b8, $c0, $b8
  5167.       .db $fb, $00, $a0, $b8, $30, $bb, $ee, $42, $88, $0f, $0b
  5168.       .db $2b, $0e, $67, $0e
  5169.       .db $ff
  5170.  
  5171. ;cloud level used in levels 2-1 and 5-2
  5172. E_GroundArea12:
  5173.       .db $0a, $aa, $0e, $28, $2a, $0e, $31, $88
  5174.       .db $ff
  5175.  
  5176. ;level 4-3
  5177. E_GroundArea13:
  5178.       .db $c7, $83, $d7, $03, $42, $8f, $7a, $03, $05, $a4
  5179.       .db $78, $24, $a6, $25, $e4, $25, $4b, $83, $e3, $03
  5180.       .db $05, $a4, $89, $24, $b5, $24, $09, $a4, $65, $24
  5181.       .db $c9, $24, $0f, $08, $85, $25
  5182.       .db $ff
  5183.  
  5184. ;level 6-3
  5185. E_GroundArea14:
  5186.       .db $cd, $a5, $b5, $a8, $07, $a8, $76, $28, $cc, $25
  5187.       .db $65, $a4, $a9, $24, $e5, $24, $19, $a4, $0f, $07
  5188.       .db $95, $28, $e6, $24, $19, $a4, $d7, $29, $16, $a9
  5189.       .db $58, $29, $97, $29
  5190.       .db $ff
  5191.  
  5192. ;level 6-1
  5193. E_GroundArea15:
  5194.       .db $0f, $02, $02, $11, $0f, $07, $02, $11
  5195.       .db $ff
  5196.  
  5197. ;warp zone area used in level 4-2
  5198. E_GroundArea16:
  5199.       .db $ff
  5200.  
  5201. ;level 8-1
  5202. E_GroundArea17:
  5203.       .db $2b, $82, $ab, $38, $de, $42, $e2, $1b, $b8, $eb
  5204.       .db $3b, $db, $80, $8b, $b8, $1b, $82, $fb, $b8, $7b
  5205.       .db $80, $fb, $3c, $5b, $bc, $7b, $b8, $1b, $8e, $cb
  5206.       .db $0e, $1b, $8e, $0f, $0d, $2b, $3b, $bb, $b8, $eb, $82
  5207.       .db $4b, $b8, $bb, $38, $3b, $b7, $bb, $02, $0f, $13
  5208.       .db $1b, $00, $cb, $80, $6b, $bc
  5209.       .db $ff
  5210.  
  5211. ;level 5-2
  5212. E_GroundArea18:
  5213.       .db $7b, $80, $ae, $00, $80, $8b, $8e, $e8, $05, $f9, $86
  5214.       .db $17, $86, $16, $85, $4e, $2b, $80, $ab, $8e, $87, $85
  5215.       .db $c3, $05, $8b, $82, $9b, $02, $ab, $02, $bb, $86
  5216.       .db $cb, $06, $d3, $03, $3b, $8e, $6b, $0e, $a7, $8e
  5217.       .db $ff
  5218.  
  5219. ;level 8-2
  5220. E_GroundArea19:
  5221.       .db $29, $8e, $52, $11, $83, $0e, $0f, $03, $9b, $0e
  5222.       .db $2b, $8e, $5b, $0e, $cb, $8e, $fb, $0e, $fb, $82
  5223.       .db $9b, $82, $bb, $02, $fe, $42, $e8, $bb, $8e, $0f, $0a
  5224.       .db $ab, $0e, $cb, $0e, $f9, $0e, $88, $86, $a6, $06
  5225.       .db $db, $02, $b6, $8e
  5226.       .db $ff
  5227.  
  5228. ;level 7-1
  5229. E_GroundArea20:
  5230.       .db $ab, $ce, $de, $42, $c0, $cb, $ce, $5b, $8e, $1b, $ce
  5231.       .db $4b, $85, $67, $45, $0f, $07, $2b, $00, $7b, $85
  5232.       .db $97, $05, $0f, $0a, $92, $02
  5233.       .db $ff
  5234.  
  5235. ;cloud level used in levels 3-1 and 6-2
  5236. E_GroundArea21:
  5237.       .db $0a, $aa, $0e, $24, $4a, $1e, $23, $aa
  5238.       .db $ff
  5239.  
  5240. ;level 3-2
  5241. E_GroundArea22:
  5242.       .db $1b, $80, $bb, $38, $4b, $bc, $eb, $3b, $0f, $04
  5243.       .db $2b, $00, $ab, $38, $eb, $00, $cb, $8e, $fb, $80
  5244.       .db $ab, $b8, $6b, $80, $fb, $3c, $9b, $bb, $5b, $bc
  5245.       .db $fb, $00, $6b, $b8, $fb, $38
  5246.       .db $ff
  5247.  
  5248. ;level 1-2
  5249. E_UndergroundArea1:
  5250.       .db $0b, $86, $1a, $06, $db, $06, $de, $c2, $02, $f0, $3b
  5251.       .db $bb, $80, $eb, $06, $0b, $86, $93, $06, $f0, $39
  5252.       .db $0f, $06, $60, $b8, $1b, $86, $a0, $b9, $b7, $27
  5253.       .db $bd, $27, $2b, $83, $a1, $26, $a9, $26, $ee, $25, $0b
  5254.       .db $27, $b4
  5255.       .db $ff
  5256.  
  5257. ;level 4-2
  5258. E_UndergroundArea2:
  5259.       .db $0f, $02, $1e, $2f, $60, $e0, $3a, $a5, $a7, $db, $80
  5260.       .db $3b, $82, $8b, $02, $fe, $42, $68, $70, $bb, $25, $a7
  5261.       .db $2c, $27, $b2, $26, $b9, $26, $9b, $80, $a8, $82
  5262.       .db $b5, $27, $bc, $27, $b0, $bb, $3b, $82, $87, $34
  5263.       .db $ee, $25, $6b
  5264.       .db $ff
  5265.  
  5266. ;underground bonus rooms area used in many levels
  5267. E_UndergroundArea3:
  5268.       .db $1e, $a5, $0a, $2e, $28, $27, $2e, $33, $c7, $0f, $03, $1e, $40, $07
  5269.       .db $2e, $30, $e7, $0f, $05, $1e, $24, $44, $0f, $07, $1e, $22, $6a
  5270.       .db $2e, $23, $ab, $0f, $09, $1e, $41, $68, $1e, $2a, $8a, $2e, $23, $a2
  5271.       .db $2e, $32, $ea
  5272.       .db $ff
  5273.  
  5274. ;water area used in levels 5-2 and 6-2
  5275. E_WaterArea1:
  5276.       .db $3b, $87, $66, $27, $cc, $27, $ee, $31, $87, $ee, $23, $a7
  5277.       .db $3b, $87, $db, $07
  5278.       .db $ff
  5279.  
  5280. ;level 2-2/7-2
  5281. E_WaterArea2:
  5282.       .db $0f, $01, $2e, $25, $2b, $2e, $25, $4b, $4e, $25, $cb, $6b, $07
  5283.       .db $97, $47, $e9, $87, $47, $c7, $7a, $07, $d6, $c7
  5284.       .db $78, $07, $38, $87, $ab, $47, $e3, $07, $9b, $87
  5285.       .db $0f, $09, $68, $47, $db, $c7, $3b, $c7
  5286.       .db $ff
  5287.  
  5288. ;water area used in level 8-4
  5289. E_WaterArea3:
  5290.       .db $47, $9b, $cb, $07, $fa, $1d, $86, $9b, $3a, $87
  5291.       .db $56, $07, $88, $1b, $07, $9d, $2e, $65, $f0
  5292.       .db $ff
  5293.  
  5294. ;AREA OBJECT DATA
  5295.  
  5296. ;level 1-4/6-4
  5297. L_CastleArea1:
  5298.       .db $9b, $07
  5299.       .db $05, $32, $06, $33, $07, $34, $ce, $03, $dc, $51
  5300.       .db $ee, $07, $73, $e0, $74, $0a, $7e, $06, $9e, $0a
  5301.       .db $ce, $06, $e4, $00, $e8, $0a, $fe, $0a, $2e, $89
  5302.       .db $4e, $0b, $54, $0a, $14, $8a, $c4, $0a, $34, $8a
  5303.       .db $7e, $06, $c7, $0a, $01, $e0, $02, $0a, $47, $0a
  5304.       .db $81, $60, $82, $0a, $c7, $0a, $0e, $87, $7e, $02
  5305.       .db $a7, $02, $b3, $02, $d7, $02, $e3, $02, $07, $82
  5306.       .db $13, $02, $3e, $06, $7e, $02, $ae, $07, $fe, $0a
  5307.       .db $0d, $c4, $cd, $43, $ce, $09, $de, $0b, $dd, $42
  5308.       .db $fe, $02, $5d, $c7
  5309.       .db $fd
  5310.  
  5311. ;level 4-4
  5312. L_CastleArea2:
  5313.       .db $5b, $07
  5314.       .db $05, $32, $06, $33, $07, $34, $5e, $0a, $68, $64
  5315.       .db $98, $64, $a8, $64, $ce, $06, $fe, $02, $0d, $01
  5316.       .db $1e, $0e, $7e, $02, $94, $63, $b4, $63, $d4, $63
  5317.       .db $f4, $63, $14, $e3, $2e, $0e, $5e, $02, $64, $35
  5318.       .db $88, $72, $be, $0e, $0d, $04, $ae, $02, $ce, $08
  5319.       .db $cd, $4b, $fe, $02, $0d, $05, $68, $31, $7e, $0a
  5320.       .db $96, $31, $a9, $63, $a8, $33, $d5, $30, $ee, $02
  5321.       .db $e6, $62, $f4, $61, $04, $b1, $08, $3f, $44, $33
  5322.       .db $94, $63, $a4, $31, $e4, $31, $04, $bf, $08, $3f
  5323.       .db $04, $bf, $08, $3f, $cd, $4b, $03, $e4, $0e, $03
  5324.       .db $2e, $01, $7e, $06, $be, $02, $de, $06, $fe, $0a
  5325.       .db $0d, $c4, $cd, $43, $ce, $09, $de, $0b, $dd, $42
  5326.       .db $fe, $02, $5d, $c7
  5327.       .db $fd
  5328.  
  5329. ;level 2-4/5-4
  5330. L_CastleArea3:
  5331.       .db $9b, $07
  5332.       .db $05, $32, $06, $33, $07, $34, $fe, $00, $27, $b1
  5333.       .db $65, $32, $75, $0a, $71, $00, $b7, $31, $08, $e4
  5334.       .db $18, $64, $1e, $04, $57, $3b, $bb, $0a, $17, $8a
  5335.       .db $27, $3a, $73, $0a, $7b, $0a, $d7, $0a, $e7, $3a
  5336.       .db $3b, $8a, $97, $0a, $fe, $08, $24, $8a, $2e, $00
  5337.       .db $3e, $40, $38, $64, $6f, $00, $9f, $00, $be, $43
  5338.       .db $c8, $0a, $c9, $63, $ce, $07, $fe, $07, $2e, $81
  5339.       .db $66, $42, $6a, $42, $79, $0a, $be, $00, $c8, $64
  5340.       .db $f8, $64, $08, $e4, $2e, $07, $7e, $03, $9e, $07
  5341.       .db $be, $03, $de, $07, $fe, $0a, $03, $a5, $0d, $44
  5342.       .db $cd, $43, $ce, $09, $dd, $42, $de, $0b, $fe, $02
  5343.       .db $5d, $c7
  5344.       .db $fd
  5345.  
  5346. ;level 3-4
  5347. L_CastleArea4:
  5348.       .db $9b, $07
  5349.       .db $05, $32, $06, $33, $07, $34, $fe, $06, $0c, $81
  5350.       .db $39, $0a, $5c, $01, $89, $0a, $ac, $01, $d9, $0a
  5351.       .db $fc, $01, $2e, $83, $a7, $01, $b7, $00, $c7, $01
  5352.       .db $de, $0a, $fe, $02, $4e, $83, $5a, $32, $63, $0a
  5353.       .db $69, $0a, $7e, $02, $ee, $03, $fa, $32, $03, $8a
  5354.       .db $09, $0a, $1e, $02, $ee, $03, $fa, $32, $03, $8a
  5355.       .db $09, $0a, $14, $42, $1e, $02, $7e, $0a, $9e, $07
  5356.       .db $fe, $0a, $2e, $86, $5e, $0a, $8e, $06, $be, $0a
  5357.       .db $ee, $07, $3e, $83, $5e, $07, $fe, $0a, $0d, $c4
  5358.       .db $41, $52, $51, $52, $cd, $43, $ce, $09, $de, $0b
  5359.       .db $dd, $42, $fe, $02, $5d, $c7
  5360.       .db $fd
  5361.  
  5362. ;level 7-4
  5363. L_CastleArea5:
  5364.       .db $5b, $07
  5365.       .db $05, $32, $06, $33, $07, $34, $fe, $0a, $ae, $86
  5366.       .db $be, $07, $fe, $02, $0d, $02, $27, $32, $46, $61
  5367.       .db $55, $62, $5e, $0e, $1e, $82, $68, $3c, $74, $3a
  5368.       .db $7d, $4b, $5e, $8e, $7d, $4b, $7e, $82, $84, $62
  5369.       .db $94, $61, $a4, $31, $bd, $4b, $ce, $06, $fe, $02
  5370.       .db $0d, $06, $34, $31, $3e, $0a, $64, $32, $75, $0a
  5371.       .db $7b, $61, $a4, $33, $ae, $02, $de, $0e, $3e, $82
  5372.       .db $64, $32, $78, $32, $b4, $36, $c8, $36, $dd, $4b
  5373.       .db $44, $b2, $58, $32, $94, $63, $a4, $3e, $ba, $30
  5374.       .db $c9, $61, $ce, $06, $dd, $4b, $ce, $86, $dd, $4b
  5375.       .db $fe, $02, $2e, $86, $5e, $02, $7e, $06, $fe, $02
  5376.       .db $1e, $86, $3e, $02, $5e, $06, $7e, $02, $9e, $06
  5377.       .db $fe, $0a, $0d, $c4, $cd, $43, $ce, $09, $de, $0b
  5378.       .db $dd, $42, $fe, $02, $5d, $c7
  5379.       .db $fd
  5380.  
  5381. ;level 8-4
  5382. L_CastleArea6:
  5383.       .db $5b, $06
  5384.       .db $05, $32, $06, $33, $07, $34, $5e, $0a, $ae, $02
  5385.       .db $0d, $01, $39, $73, $0d, $03, $39, $7b, $4d, $4b
  5386.       .db $de, $06, $1e, $8a, $ae, $06, $c4, $33, $16, $fe
  5387.       .db $a5, $77, $fe, $02, $fe, $82, $0d, $07, $39, $73
  5388.       .db $a8, $74, $ed, $4b, $49, $fb, $e8, $74, $fe, $0a
  5389.       .db $2e, $82, $67, $02, $84, $7a, $87, $31, $0d, $0b
  5390.       .db $fe, $02, $0d, $0c, $39, $73, $5e, $06, $c6, $76
  5391.       .db $45, $ff, $be, $0a, $dd, $48, $fe, $06, $3d, $cb
  5392.       .db $46, $7e, $ad, $4a, $fe, $82, $39, $f3, $a9, $7b
  5393.       .db $4e, $8a, $9e, $07, $fe, $0a, $0d, $c4, $cd, $43
  5394.       .db $ce, $09, $de, $0b, $dd, $42, $fe, $02, $5d, $c7
  5395.       .db $fd
  5396.  
  5397. ;level 3-3
  5398. L_GroundArea1:
  5399.       .db $94, $11
  5400.       .db $0f, $26, $fe, $10, $28, $94, $65, $15, $eb, $12
  5401.       .db $fa, $41, $4a, $96, $54, $40, $a4, $42, $b7, $13
  5402.       .db $e9, $19, $f5, $15, $11, $80, $47, $42, $71, $13
  5403.       .db $80, $41, $15, $92, $1b, $1f, $24, $40, $55, $12
  5404.       .db $64, $40, $95, $12, $a4, $40, $d2, $12, $e1, $40
  5405.       .db $13, $c0, $2c, $17, $2f, $12, $49, $13, $83, $40
  5406.       .db $9f, $14, $a3, $40, $17, $92, $83, $13, $92, $41
  5407.       .db $b9, $14, $c5, $12, $c8, $40, $d4, $40, $4b, $92
  5408.       .db $78, $1b, $9c, $94, $9f, $11, $df, $14, $fe, $11
  5409.       .db $7d, $c1, $9e, $42, $cf, $20
  5410.       .db $fd
  5411.  
  5412. ;level 8-3
  5413. L_GroundArea2:
  5414.       .db $90, $b1
  5415.       .db $0f, $26, $29, $91, $7e, $42, $fe, $40, $28, $92
  5416.       .db $4e, $42, $2e, $c0, $57, $73, $c3, $25, $c7, $27
  5417.       .db $23, $84, $33, $20, $5c, $01, $77, $63, $88, $62
  5418.       .db $99, $61, $aa, $60, $bc, $01, $ee, $42, $4e, $c0
  5419.       .db $69, $11, $7e, $42, $de, $40, $f8, $62, $0e, $c2
  5420.       .db $ae, $40, $d7, $63, $e7, $63, $33, $a7, $37, $27
  5421.       .db $43, $04, $cc, $01, $e7, $73, $0c, $81, $3e, $42
  5422.       .db $0d, $0a, $5e, $40, $88, $72, $be, $42, $e7, $87
  5423.       .db $fe, $40, $39, $e1, $4e, $00, $69, $60, $87, $60
  5424.       .db $a5, $60, $c3, $31, $fe, $31, $6d, $c1, $be, $42
  5425.       .db $ef, $20
  5426.       .db $fd
  5427.  
  5428. ;level 4-1
  5429. L_GroundArea3:
  5430.       .db $52, $21
  5431.       .db $0f, $20, $6e, $40, $58, $f2, $93, $01, $97, $00
  5432.       .db $0c, $81, $97, $40, $a6, $41, $c7, $40, $0d, $04
  5433.       .db $03, $01, $07, $01, $23, $01, $27, $01, $ec, $03
  5434.       .db $ac, $f3, $c3, $03, $78, $e2, $94, $43, $47, $f3
  5435.       .db $74, $43, $47, $fb, $74, $43, $2c, $f1, $4c, $63
  5436.       .db $47, $00, $57, $21, $5c, $01, $7c, $72, $39, $f1
  5437.       .db $ec, $02, $4c, $81, $d8, $62, $ec, $01, $0d, $0d
  5438.       .db $0f, $38, $c7, $07, $ed, $4a, $1d, $c1, $5f, $26
  5439.       .db $fd
  5440.  
  5441. ;level 6-2
  5442. L_GroundArea4:
  5443.       .db $54, $21
  5444.       .db $0f, $26, $a7, $22, $37, $fb, $73, $20, $83, $07
  5445.       .db $87, $02, $93, $20, $c7, $73, $04, $f1, $06, $31
  5446.       .db $39, $71, $59, $71, $e7, $73, $37, $a0, $47, $04
  5447.       .db $86, $7c, $e5, $71, $e7, $31, $33, $a4, $39, $71
  5448.       .db $a9, $71, $d3, $23, $08, $f2, $13, $05, $27, $02
  5449.       .db $49, $71, $75, $75, $e8, $72, $67, $f3, $99, $71
  5450.       .db $e7, $20, $f4, $72, $f7, $31, $17, $a0, $33, $20
  5451.       .db $39, $71, $73, $28, $bc, $05, $39, $f1, $79, $71
  5452.       .db $a6, $21, $c3, $06, $d3, $20, $dc, $00, $fc, $00
  5453.       .db $07, $a2, $13, $21, $5f, $32, $8c, $00, $98, $7a
  5454.       .db $c7, $63, $d9, $61, $03, $a2, $07, $22, $74, $72
  5455.       .db $77, $31, $e7, $73, $39, $f1, $58, $72, $77, $73
  5456.       .db $d8, $72, $7f, $b1, $97, $73, $b6, $64, $c5, $65
  5457.       .db $d4, $66, $e3, $67, $f3, $67, $8d, $c1, $cf, $26
  5458.       .db $fd
  5459.  
  5460. ;level 3-1
  5461. L_GroundArea5:
  5462.       .db $52, $31
  5463.       .db $0f, $20, $6e, $66, $07, $81, $36, $01, $66, $00
  5464.       .db $a7, $22, $08, $f2, $67, $7b, $dc, $02, $98, $f2
  5465.       .db $d7, $20, $39, $f1, $9f, $33, $dc, $27, $dc, $57
  5466.       .db $23, $83, $57, $63, $6c, $51, $87, $63, $99, $61
  5467.       .db $a3, $06, $b3, $21, $77, $f3, $f3, $21, $f7, $2a
  5468.       .db $13, $81, $23, $22, $53, $00, $63, $22, $e9, $0b
  5469.       .db $0c, $83, $13, $21, $16, $22, $33, $05, $8f, $35
  5470.       .db $ec, $01, $63, $a0, $67, $20, $73, $01, $77, $01
  5471.       .db $83, $20, $87, $20, $b3, $20, $b7, $20, $c3, $01
  5472.       .db $c7, $00, $d3, $20, $d7, $20, $67, $a0, $77, $07
  5473.       .db $87, $22, $e8, $62, $f5, $65, $1c, $82, $7f, $38
  5474.       .db $8d, $c1, $cf, $26
  5475.       .db $fd
  5476.  
  5477. ;level 1-1
  5478. L_GroundArea6:
  5479.       .db $50, $21
  5480.       .db $07, $81, $47, $24, $57, $00, $63, $01, $77, $01
  5481.       .db $c9, $71, $68, $f2, $e7, $73, $97, $fb, $06, $83
  5482.       .db $5c, $01, $d7, $22, $e7, $00, $03, $a7, $6c, $02
  5483.       .db $b3, $22, $e3, $01, $e7, $07, $47, $a0, $57, $06
  5484.       .db $a7, $01, $d3, $00, $d7, $01, $07, $81, $67, $20
  5485.       .db $93, $22, $03, $a3, $1c, $61, $17, $21, $6f, $33
  5486.       .db $c7, $63, $d8, $62, $e9, $61, $fa, $60, $4f, $b3
  5487.       .db $87, $63, $9c, $01, $b7, $63, $c8, $62, $d9, $61
  5488.       .db $ea, $60, $39, $f1, $87, $21, $a7, $01, $b7, $20
  5489.       .db $39, $f1, $5f, $38, $6d, $c1, $af, $26
  5490.       .db $fd
  5491.  
  5492. ;level 1-3/5-3
  5493. L_GroundArea7:
  5494.       .db $90, $11
  5495.       .db $0f, $26, $fe, $10, $2a, $93, $87, $17, $a3, $14
  5496.       .db $b2, $42, $0a, $92, $19, $40, $36, $14, $50, $41
  5497.       .db $82, $16, $2b, $93, $24, $41, $bb, $14, $b8, $00
  5498.       .db $c2, $43, $c3, $13, $1b, $94, $67, $12, $c4, $15
  5499.       .db $53, $c1, $d2, $41, $12, $c1, $29, $13, $85, $17
  5500.       .db $1b, $92, $1a, $42, $47, $13, $83, $41, $a7, $13
  5501.       .db $0e, $91, $a7, $63, $b7, $63, $c5, $65, $d5, $65
  5502.       .db $dd, $4a, $e3, $67, $f3, $67, $8d, $c1, $ae, $42
  5503.       .db $df, $20
  5504.       .db $fd
  5505.  
  5506. ;level 2-3/7-3
  5507. L_GroundArea8:
  5508.       .db $90, $11
  5509.       .db $0f, $26, $6e, $10, $8b, $17, $af, $32, $d8, $62
  5510.       .db $e8, $62, $fc, $3f, $ad, $c8, $f8, $64, $0c, $be
  5511.       .db $43, $43, $f8, $64, $0c, $bf, $73, $40, $84, $40
  5512.       .db $93, $40, $a4, $40, $b3, $40, $f8, $64, $48, $e4
  5513.       .db $5c, $39, $83, $40, $92, $41, $b3, $40, $f8, $64
  5514.       .db $48, $e4, $5c, $39, $f8, $64, $13, $c2, $37, $65
  5515.       .db $4c, $24, $63, $00, $97, $65, $c3, $42, $0b, $97
  5516.       .db $ac, $32, $f8, $64, $0c, $be, $53, $45, $9d, $48
  5517.       .db $f8, $64, $2a, $e2, $3c, $47, $56, $43, $ba, $62
  5518.       .db $f8, $64, $0c, $b7, $88, $64, $bc, $31, $d4, $45
  5519.       .db $fc, $31, $3c, $b1, $78, $64, $8c, $38, $0b, $9c
  5520.       .db $1a, $33, $18, $61, $28, $61, $39, $60, $5d, $4a
  5521.       .db $ee, $11, $0f, $b8, $1d, $c1, $3e, $42, $6f, $20
  5522.       .db $fd
  5523.  
  5524. ;level 2-1
  5525. L_GroundArea9:
  5526.       .db $52, $31
  5527.       .db $0f, $20, $6e, $40, $f7, $20, $07, $84, $17, $20
  5528.       .db $4f, $34, $c3, $03, $c7, $02, $d3, $22, $27, $e3
  5529.       .db $39, $61, $e7, $73, $5c, $e4, $57, $00, $6c, $73
  5530.       .db $47, $a0, $53, $06, $63, $22, $a7, $73, $fc, $73
  5531.       .db $13, $a1, $33, $05, $43, $21, $5c, $72, $c3, $23
  5532.       .db $cc, $03, $77, $fb, $ac, $02, $39, $f1, $a7, $73
  5533.       .db $d3, $04, $e8, $72, $e3, $22, $26, $f4, $bc, $02
  5534.       .db $8c, $81, $a8, $62, $17, $87, $43, $24, $a7, $01
  5535.       .db $c3, $04, $08, $f2, $97, $21, $a3, $02, $c9, $0b
  5536.       .db $e1, $69, $f1, $69, $8d, $c1, $cf, $26
  5537.       .db $fd
  5538.  
  5539. ;pipe intro area
  5540. L_GroundArea10:
  5541.       .db $38, $11
  5542.       .db $0f, $26, $ad, $40, $3d, $c7
  5543.       .db $fd
  5544.  
  5545. ;level 5-1
  5546. L_GroundArea11:
  5547.       .db $95, $b1
  5548.       .db $0f, $26, $0d, $02, $c8, $72, $1c, $81, $38, $72
  5549.       .db $0d, $05, $97, $34, $98, $62, $a3, $20, $b3, $06
  5550.       .db $c3, $20, $cc, $03, $f9, $91, $2c, $81, $48, $62
  5551.       .db $0d, $09, $37, $63, $47, $03, $57, $21, $8c, $02
  5552.       .db $c5, $79, $c7, $31, $f9, $11, $39, $f1, $a9, $11
  5553.       .db $6f, $b4, $d3, $65, $e3, $65, $7d, $c1, $bf, $26
  5554.       .db $fd
  5555.  
  5556. ;cloud level used in levels 2-1 and 5-2
  5557. L_GroundArea12:
  5558.       .db $00, $c1
  5559.       .db $4c, $00, $f4, $4f, $0d, $02, $02, $42, $43, $4f
  5560.       .db $52, $c2, $de, $00, $5a, $c2, $4d, $c7
  5561.       .db $fd
  5562.  
  5563. ;level 4-3
  5564. L_GroundArea13:
  5565.       .db $90, $51
  5566.       .db $0f, $26, $ee, $10, $0b, $94, $33, $14, $42, $42
  5567.       .db $77, $16, $86, $44, $02, $92, $4a, $16, $69, $42
  5568.       .db $73, $14, $b0, $00, $c7, $12, $05, $c0, $1c, $17
  5569.       .db $1f, $11, $36, $12, $8f, $14, $91, $40, $1b, $94
  5570.       .db $35, $12, $34, $42, $60, $42, $61, $12, $87, $12
  5571.       .db $96, $40, $a3, $14, $1c, $98, $1f, $11, $47, $12
  5572.       .db $9f, $15, $cc, $15, $cf, $11, $05, $c0, $1f, $15
  5573.       .db $39, $12, $7c, $16, $7f, $11, $82, $40, $98, $12
  5574.       .db $df, $15, $16, $c4, $17, $14, $54, $12, $9b, $16
  5575.       .db $28, $94, $ce, $01, $3d, $c1, $5e, $42, $8f, $20
  5576.       .db $fd
  5577.  
  5578. ;level 6-3
  5579. L_GroundArea14:
  5580.       .db $97, $11
  5581.       .db $0f, $26, $fe, $10, $2b, $92, $57, $12, $8b, $12
  5582.       .db $c0, $41, $f7, $13, $5b, $92, $69, $0b, $bb, $12
  5583.       .db $b2, $46, $19, $93, $71, $00, $17, $94, $7c, $14
  5584.       .db $7f, $11, $93, $41, $bf, $15, $fc, $13, $ff, $11
  5585.       .db $2f, $95, $50, $42, $51, $12, $58, $14, $a6, $12
  5586.       .db $db, $12, $1b, $93, $46, $43, $7b, $12, $8d, $49
  5587.       .db $b7, $14, $1b, $94, $49, $0b, $bb, $12, $fc, $13
  5588.       .db $ff, $12, $03, $c1, $2f, $15, $43, $12, $4b, $13
  5589.       .db $77, $13, $9d, $4a, $15, $c1, $a1, $41, $c3, $12
  5590.       .db $fe, $01, $7d, $c1, $9e, $42, $cf, $20
  5591.       .db $fd
  5592.  
  5593. ;level 6-1
  5594. L_GroundArea15:
  5595.       .db $52, $21
  5596.       .db $0f, $20, $6e, $44, $0c, $f1, $4c, $01, $aa, $35
  5597.       .db $d9, $34, $ee, $20, $08, $b3, $37, $32, $43, $04
  5598.       .db $4e, $21, $53, $20, $7c, $01, $97, $21, $b7, $07
  5599.       .db $9c, $81, $e7, $42, $5f, $b3, $97, $63, $ac, $02
  5600.       .db $c5, $41, $49, $e0, $58, $61, $76, $64, $85, $65
  5601.       .db $94, $66, $a4, $22, $a6, $03, $c8, $22, $dc, $02
  5602.       .db $68, $f2, $96, $42, $13, $82, $17, $02, $af, $34
  5603.       .db $f6, $21, $fc, $06, $26, $80, $2a, $24, $36, $01
  5604.       .db $8c, $00, $ff, $35, $4e, $a0, $55, $21, $77, $20
  5605.       .db $87, $07, $89, $22, $ae, $21, $4c, $82, $9f, $34
  5606.       .db $ec, $01, $03, $e7, $13, $67, $8d, $4a, $ad, $41
  5607.       .db $0f, $a6
  5608.       .db $fd
  5609.  
  5610. ;warp zone area used in level 4-2
  5611. L_GroundArea16:
  5612.       .db $10, $51
  5613.       .db $4c, $00, $c7, $12, $c6, $42, $03, $92, $02, $42
  5614.       .db $29, $12, $63, $12, $62, $42, $69, $14, $a5, $12
  5615.       .db $a4, $42, $e2, $14, $e1, $44, $f8, $16, $37, $c1
  5616.       .db $8f, $38, $02, $bb, $28, $7a, $68, $7a, $a8, $7a
  5617.       .db $e0, $6a, $f0, $6a, $6d, $c5
  5618.       .db $fd
  5619.  
  5620. ;level 8-1
  5621. L_GroundArea17:
  5622.       .db $92, $31
  5623.       .db $0f, $20, $6e, $40, $0d, $02, $37, $73, $ec, $00
  5624.       .db $0c, $80, $3c, $00, $6c, $00, $9c, $00, $06, $c0
  5625.       .db $c7, $73, $06, $83, $28, $72, $96, $40, $e7, $73
  5626.       .db $26, $c0, $87, $7b, $d2, $41, $39, $f1, $c8, $f2
  5627.       .db $97, $e3, $a3, $23, $e7, $02, $e3, $07, $f3, $22
  5628.       .db $37, $e3, $9c, $00, $bc, $00, $ec, $00, $0c, $80
  5629.       .db $3c, $00, $86, $21, $a6, $06, $b6, $24, $5c, $80
  5630.       .db $7c, $00, $9c, $00, $29, $e1, $dc, $05, $f6, $41
  5631.       .db $dc, $80, $e8, $72, $0c, $81, $27, $73, $4c, $01
  5632.       .db $66, $74, $0d, $11, $3f, $35, $b6, $41, $2c, $82
  5633.       .db $36, $40, $7c, $02, $86, $40, $f9, $61, $39, $e1
  5634.       .db $ac, $04, $c6, $41, $0c, $83, $16, $41, $88, $f2
  5635.       .db $39, $f1, $7c, $00, $89, $61, $9c, $00, $a7, $63
  5636.       .db $bc, $00, $c5, $65, $dc, $00, $e3, $67, $f3, $67
  5637.       .db $8d, $c1, $cf, $26
  5638.       .db $fd
  5639.  
  5640. ;level 5-2
  5641. L_GroundArea18:
  5642.       .db $55, $b1
  5643.       .db $0f, $26, $cf, $33, $07, $b2, $15, $11, $52, $42
  5644.       .db $99, $0b, $ac, $02, $d3, $24, $d6, $42, $d7, $25
  5645.       .db $23, $84, $cf, $33, $07, $e3, $19, $61, $78, $7a
  5646.       .db $ef, $33, $2c, $81, $46, $64, $55, $65, $65, $65
  5647.       .db $ec, $74, $47, $82, $53, $05, $63, $21, $62, $41
  5648.       .db $96, $22, $9a, $41, $cc, $03, $b9, $91, $39, $f1
  5649.       .db $63, $26, $67, $27, $d3, $06, $fc, $01, $18, $e2
  5650.       .db $d9, $07, $e9, $04, $0c, $86, $37, $22, $93, $24
  5651.       .db $87, $84, $ac, $02, $c2, $41, $c3, $23, $d9, $71
  5652.       .db $fc, $01, $7f, $b1, $9c, $00, $a7, $63, $b6, $64
  5653.       .db $cc, $00, $d4, $66, $e3, $67, $f3, $67, $8d, $c1
  5654.       .db $cf, $26
  5655.       .db $fd
  5656.  
  5657. ;level 8-2
  5658. L_GroundArea19:
  5659.       .db $50, $b1
  5660.       .db $0f, $26, $fc, $00, $1f, $b3, $5c, $00, $65, $65
  5661.       .db $74, $66, $83, $67, $93, $67, $dc, $73, $4c, $80
  5662.       .db $b3, $20, $c9, $0b, $c3, $08, $d3, $2f, $dc, $00
  5663.       .db $2c, $80, $4c, $00, $8c, $00, $d3, $2e, $ed, $4a
  5664.       .db $fc, $00, $d7, $a1, $ec, $01, $4c, $80, $59, $11
  5665.       .db $d8, $11, $da, $10, $37, $a0, $47, $04, $99, $11
  5666.       .db $e7, $21, $3a, $90, $67, $20, $76, $10, $77, $60
  5667.       .db $87, $07, $d8, $12, $39, $f1, $ac, $00, $e9, $71
  5668.       .db $0c, $80, $2c, $00, $4c, $05, $c7, $7b, $39, $f1
  5669.       .db $ec, $00, $f9, $11, $0c, $82, $6f, $34, $f8, $11
  5670.       .db $fa, $10, $7f, $b2, $ac, $00, $b6, $64, $cc, $01
  5671.       .db $e3, $67, $f3, $67, $8d, $c1, $cf, $26
  5672.       .db $fd
  5673.  
  5674. ;level 7-1
  5675. L_GroundArea20:
  5676.       .db $52, $b1
  5677.       .db $0f, $20, $6e, $45, $39, $91, $b3, $04, $c3, $21
  5678.       .db $c8, $11, $ca, $10, $49, $91, $7c, $73, $e8, $12
  5679.       .db $88, $91, $8a, $10, $e7, $21, $05, $91, $07, $30
  5680.       .db $17, $07, $27, $20, $49, $11, $9c, $01, $c8, $72
  5681.       .db $23, $a6, $27, $26, $d3, $03, $d8, $7a, $89, $91
  5682.       .db $d8, $72, $39, $f1, $a9, $11, $09, $f1, $63, $24
  5683.       .db $67, $24, $d8, $62, $28, $91, $2a, $10, $56, $21
  5684.       .db $70, $04, $79, $0b, $8c, $00, $94, $21, $9f, $35
  5685.       .db $2f, $b8, $3d, $c1, $7f, $26
  5686.       .db $fd
  5687.  
  5688. ;cloud level used in levels 3-1 and 6-2
  5689. L_GroundArea21:
  5690.       .db $06, $c1
  5691.       .db $4c, $00, $f4, $4f, $0d, $02, $06, $20, $24, $4f
  5692.       .db $35, $a0, $36, $20, $53, $46, $d5, $20, $d6, $20
  5693.       .db $34, $a1, $73, $49, $74, $20, $94, $20, $b4, $20
  5694.       .db $d4, $20, $f4, $20, $2e, $80, $59, $42, $4d, $c7
  5695.       .db $fd
  5696.  
  5697. ;level 3-2
  5698. L_GroundArea22:
  5699.       .db $96, $31
  5700.       .db $0f, $26, $0d, $03, $1a, $60, $77, $42, $c4, $00
  5701.       .db $c8, $62, $b9, $e1, $d3, $06, $d7, $07, $f9, $61
  5702.       .db $0c, $81, $4e, $b1, $8e, $b1, $bc, $01, $e4, $50
  5703.       .db $e9, $61, $0c, $81, $0d, $0a, $84, $43, $98, $72
  5704.       .db $0d, $0c, $0f, $38, $1d, $c1, $5f, $26
  5705.       .db $fd
  5706.  
  5707. ;level 1-2
  5708. L_UndergroundArea1:
  5709.       .db $48, $0f
  5710.       .db $0e, $01, $5e, $02, $a7, $00, $bc, $73, $1a, $e0
  5711.       .db $39, $61, $58, $62, $77, $63, $97, $63, $b8, $62
  5712.       .db $d6, $07, $f8, $62, $19, $e1, $75, $52, $86, $40
  5713.       .db $87, $50, $95, $52, $93, $43, $a5, $21, $c5, $52
  5714.       .db $d6, $40, $d7, $20, $e5, $06, $e6, $51, $3e, $8d
  5715.       .db $5e, $03, $67, $52, $77, $52, $7e, $02, $9e, $03
  5716.       .db $a6, $43, $a7, $23, $de, $05, $fe, $02, $1e, $83
  5717.       .db $33, $54, $46, $40, $47, $21, $56, $04, $5e, $02
  5718.       .db $83, $54, $93, $52, $96, $07, $97, $50, $be, $03
  5719.       .db $c7, $23, $fe, $02, $0c, $82, $43, $45, $45, $24
  5720.       .db $46, $24, $90, $08, $95, $51, $78, $fa, $d7, $73
  5721.       .db $39, $f1, $8c, $01, $a8, $52, $b8, $52, $cc, $01
  5722.       .db $5f, $b3, $97, $63, $9e, $00, $0e, $81, $16, $24
  5723.       .db $66, $04, $8e, $00, $fe, $01, $08, $d2, $0e, $06
  5724.       .db $6f, $47, $9e, $0f, $0e, $82, $2d, $47, $28, $7a
  5725.       .db $68, $7a, $a8, $7a, $ae, $01, $de, $0f, $6d, $c5
  5726.       .db $fd
  5727.  
  5728. ;level 4-2
  5729. L_UndergroundArea2:
  5730.       .db $48, $0f
  5731.       .db $0e, $01, $5e, $02, $bc, $01, $fc, $01, $2c, $82
  5732.       .db $41, $52, $4e, $04, $67, $25, $68, $24, $69, $24
  5733.       .db $ba, $42, $c7, $04, $de, $0b, $b2, $87, $fe, $02
  5734.       .db $2c, $e1, $2c, $71, $67, $01, $77, $00, $87, $01
  5735.       .db $8e, $00, $ee, $01, $f6, $02, $03, $85, $05, $02
  5736.       .db $13, $21, $16, $02, $27, $02, $2e, $02, $88, $72
  5737.       .db $c7, $20, $d7, $07, $e4, $76, $07, $a0, $17, $06
  5738.       .db $48, $7a, $76, $20, $98, $72, $79, $e1, $88, $62
  5739.       .db $9c, $01, $b7, $73, $dc, $01, $f8, $62, $fe, $01
  5740.       .db $08, $e2, $0e, $00, $6e, $02, $73, $20, $77, $23
  5741.       .db $83, $04, $93, $20, $ae, $00, $fe, $0a, $0e, $82
  5742.       .db $39, $71, $a8, $72, $e7, $73, $0c, $81, $8f, $32
  5743.       .db $ae, $00, $fe, $04, $04, $d1, $17, $04, $26, $49
  5744.       .db $27, $29, $df, $33, $fe, $02, $44, $f6, $7c, $01
  5745.       .db $8e, $06, $bf, $47, $ee, $0f, $4d, $c7, $0e, $82
  5746.       .db $68, $7a, $ae, $01, $de, $0f, $6d, $c5
  5747.       .db $fd
  5748.  
  5749. ;underground bonus rooms area used in many levels
  5750. L_UndergroundArea3:
  5751.       .db $48, $01
  5752.       .db $0e, $01, $00, $5a, $3e, $06, $45, $46, $47, $46
  5753.       .db $53, $44, $ae, $01, $df, $4a, $4d, $c7, $0e, $81
  5754.       .db $00, $5a, $2e, $04, $37, $28, $3a, $48, $46, $47
  5755.       .db $c7, $07, $ce, $0f, $df, $4a, $4d, $c7, $0e, $81
  5756.       .db $00, $5a, $33, $53, $43, $51, $46, $40, $47, $50
  5757.       .db $53, $04, $55, $40, $56, $50, $62, $43, $64, $40
  5758.       .db $65, $50, $71, $41, $73, $51, $83, $51, $94, $40
  5759.       .db $95, $50, $a3, $50, $a5, $40, $a6, $50, $b3, $51
  5760.       .db $b6, $40, $b7, $50, $c3, $53, $df, $4a, $4d, $c7
  5761.       .db $0e, $81, $00, $5a, $2e, $02, $36, $47, $37, $52
  5762.       .db $3a, $49, $47, $25, $a7, $52, $d7, $04, $df, $4a
  5763.       .db $4d, $c7, $0e, $81, $00, $5a, $3e, $02, $44, $51
  5764.       .db $53, $44, $54, $44, $55, $24, $a1, $54, $ae, $01
  5765.       .db $b4, $21, $df, $4a, $e5, $07, $4d, $c7
  5766.       .db $fd
  5767.  
  5768. ;water area used in levels 5-2 and 6-2
  5769. L_WaterArea1:
  5770.       .db $41, $01
  5771.       .db $b4, $34, $c8, $52, $f2, $51, $47, $d3, $6c, $03
  5772.       .db $65, $49, $9e, $07, $be, $01, $cc, $03, $fe, $07
  5773.       .db $0d, $c9, $1e, $01, $6c, $01, $62, $35, $63, $53
  5774.       .db $8a, $41, $ac, $01, $b3, $53, $e9, $51, $26, $c3
  5775.       .db $27, $33, $63, $43, $64, $33, $ba, $60, $c9, $61
  5776.       .db $ce, $0b, $e5, $09, $ee, $0f, $7d, $ca, $7d, $47
  5777.       .db $fd
  5778.  
  5779. ;level 2-2/7-2
  5780. L_WaterArea2:
  5781.       .db $41, $01
  5782.       .db $b8, $52, $ea, $41, $27, $b2, $b3, $42, $16, $d4
  5783.       .db $4a, $42, $a5, $51, $a7, $31, $27, $d3, $08, $e2
  5784.       .db $16, $64, $2c, $04, $38, $42, $76, $64, $88, $62
  5785.       .db $de, $07, $fe, $01, $0d, $c9, $23, $32, $31, $51
  5786.       .db $98, $52, $0d, $c9, $59, $42, $63, $53, $67, $31
  5787.       .db $14, $c2, $36, $31, $87, $53, $17, $e3, $29, $61
  5788.       .db $30, $62, $3c, $08, $42, $37, $59, $40, $6a, $42
  5789.       .db $99, $40, $c9, $61, $d7, $63, $39, $d1, $58, $52
  5790.       .db $c3, $67, $d3, $31, $dc, $06, $f7, $42, $fa, $42
  5791.       .db $23, $b1, $43, $67, $c3, $34, $c7, $34, $d1, $51
  5792.       .db $43, $b3, $47, $33, $9a, $30, $a9, $61, $b8, $62
  5793.       .db $be, $0b, $d5, $09, $de, $0f, $0d, $ca, $7d, $47
  5794.       .db $fd
  5795.  
  5796. ;water area used in level 8-4
  5797. L_WaterArea3:
  5798.       .db $49, $0f
  5799.       .db $1e, $01, $39, $73, $5e, $07, $ae, $0b, $1e, $82
  5800.       .db $6e, $88, $9e, $02, $0d, $04, $2e, $0b, $45, $09
  5801.       .db $4e, $0f, $ed, $47
  5802.       .db $fd
  5803.  
  5804. ;-------------------------------------------------------------------------------------
  5805.  
  5806.        if Z80==0
  5807. ;unused space
  5808.       .db $ff
  5809.        endif
  5810.  
  5811. ;-------------------------------------------------------------------------------------
  5812.  
  5813. ;indirect jump routine called when
  5814. ;$0770 is set to 1
  5815. GameMode:
  5816.       lda OperMode_Task
  5817.       jsr JumpEngine
  5818.  
  5819.       .dw InitializeArea
  5820.       .dw ScreenRoutines
  5821.       .dw SecondaryGameSetup
  5822.       .dw GameCoreRoutine
  5823.  
  5824. ;-------------------------------------------------------------------------------------
  5825.  
  5826. GameCoreRoutine:
  5827.       ldx CurrentPlayer          ;get which player is on the screen
  5828.       ldax SavedJoypadBits,x      ;use appropriate player's controller bits
  5829.        ;or a
  5830.        ;jr nz,$
  5831.       sta SavedJoypadBits        ;as the master controller bits
  5832.       jsr GameRoutines           ;execute one of many possible subs ;9907t (3 Goomba + 2 юўъш + ╠рЁшю)
  5833.       lda OperMode_Task          ;check major task of operating mode
  5834.       cmpn ++$03                   ;if we are supposed to be here,
  5835.               cmpcy
  5836.       bcs GameEngine             ;branch to the game engine itself
  5837.       rts
  5838.  
  5839. GameEngine:
  5840.               jsr ProcFireball_Bubble    ;process fireballs and air bubbles
  5841.               ldxn ++$00
  5842. ProcELoop:    stx ObjectOffset           ;put incremented offset in X as enemy object offset
  5843.               jsr EnemiesAndLoopsCore    ;process enemy objects  ;8639+8388+9593+999+999+404t (3 Goomba + 2 юўъш + ╠рЁшю) ;<------------
  5844.               jsr FloateyNumbersRoutine  ;process floatey numbers ;73+941+73+73+73+73t (3 Goomba + 2 юўъш + ╠рЁшю)
  5845.               inx
  5846.               cpxn ++$06                   ;do these two subroutines until the whole buffer is done
  5847.               bne ProcELoop
  5848.               jsr GetPlayerOffscreenBits ;get offscreen bits for player object ;726t (3 Goomba + 2 юўъш + ╠рЁшю)
  5849.               jsr RelativePlayerPosition ;get relative coordinates for player object ;228t (3 Goomba + 2 юўъш + ╠рЁшю)
  5850.            if 0;Z80
  5851.             ld hl,(logicframe)
  5852.             dec l
  5853.             call z,PlayerGfxHandler ;Єюы№ъю т яюёыхфэхь ърфЁх ыюушъш (эхяюёЁхфёЄтхээю яхЁхф юЄюсЁрцхэшхь) ;эх яюыєўрхЄё  - юўхэ№ ьхфыхээю шф╕Є ьшурэшх яЁш ЁюёЄх ш єьхэ№°хэшш
  5854.            else
  5855.               jsr PlayerGfxHandler       ;draw the player                               ;3074t (3 Goomba + 2 юўъш + ╠рЁшю) ;<--------------
  5856.            endif
  5857.               jsr BlockObjMT_Updater     ;replace block objects with metatiles if necessary ;250t (3 Goomba + 2 юўъш + ╠рЁшю)
  5858.               ldxn ++$01
  5859.               stx ObjectOffset           ;set offset for second
  5860.               jsr BlockObjectsCore       ;process second block object ;101t (3 Goomba + 2 юўъш + ╠рЁшю)
  5861.               dex
  5862.               stx ObjectOffset           ;set offset for first
  5863.               jsr BlockObjectsCore       ;process first block object ;101t (3 Goomba + 2 юўъш + ╠рЁшю)
  5864.               jsr MiscObjectsCore        ;process misc objects (hammer, jumping coins) ;3249t (3 Goomba + 2 юўъш + ╠рЁшю) ;<---------------
  5865.               jsr ProcessCannons         ;process bullet bill cannons ;431t (3 Goomba + 2 юўъш + ╠рЁшю)
  5866.               jsr ProcessWhirlpools      ;process whirlpools         ;58t (3 Goomba + 2 юўъш + ╠рЁшю)
  5867.               jsr FlagpoleRoutine        ;process the flagpole       ;96t (3 Goomba + 2 юўъш + ╠рЁшю)
  5868.               jsr RunGameTimer           ;count down the game timer ;174t (3 Goomba + 2 юўъш + ╠рЁшю)
  5869.               jsr ColorRotation          ;cycle one of the background colors ;57t (3 Goomba + 2 юўъш + ╠рЁшю)
  5870.               lda Player_Y_HighPos
  5871.               cmpn ++$02                   ;if player is below the screen, don't bother with the music
  5872.               bpl NoChgMus
  5873.               lda StarInvincibleTimer    ;if star mario invincibility timer at zero,
  5874.          checka
  5875.               beq ClrPlrPal              ;skip this part
  5876.               cmpn ++$04
  5877.               bne NoChgMus               ;if not yet at a certain point, continue
  5878.               lda IntervalTimerControl   ;if interval timer not yet expired,
  5879.          checka
  5880.               bne NoChgMus               ;branch ahead, don't bother with the music
  5881.               jsr GetAreaMusic           ;to re-attain appropriate level music
  5882. NoChgMus:     ldy StarInvincibleTimer    ;get invincibility timer
  5883.               lda FrameCounter           ;get frame counter
  5884.               cpyn ++$08                   ;if timer still above certain point,
  5885.               cmpcy
  5886.               bcs CycleTwo               ;branch to cycle player's palette quickly
  5887.               lsr                        ;otherwise, divide by 8 to cycle every eighth frame
  5888.               lsr
  5889. CycleTwo:     lsr                        ;if branched here, divide by 2 to cycle every other frame
  5890.               jsr CyclePlayerPalette     ;do sub to cycle the palette (note: shares fire flower code)
  5891.               jmp SaveAB                 ;then skip this sub to finish up the game engine
  5892. ClrPlrPal:    jsr ResetPalStar           ;do sub to clear player's palette bits in attributes
  5893. SaveAB:       lda A_B_Buttons            ;save current A and B button
  5894.               sta PreviousA_B_Buttons    ;into temp variable to be used on next frame
  5895.               ldan ++$00
  5896.               sta Left_Right_Buttons     ;nullify left and right buttons temp variable
  5897. UpdScrollVar: lda VRAM_Buffer_AddrCtrl
  5898.               cmpn ++$06                   ;if vram address controller set to 6 (one of two $0341s) (VRAM_Buffer2)
  5899.               beq ExitEng                ;then branch to leave
  5900.               lda AreaParserTaskNum      ;otherwise check number of tasks
  5901.          checka
  5902.               bne RunParser
  5903.               lda ScrollThirtyTwo        ;get horizontal scroll in 0-31 or $00-$20 range
  5904.               cmpn ++$20                   ;check to see if exceeded $21
  5905.               bmi ExitEng                ;branch to leave if not
  5906.               lda ScrollThirtyTwo
  5907.               sbcn ++$20                   ;otherwise subtract $20 to set appropriately
  5908.               sta ScrollThirtyTwo        ;and store
  5909.               ldan ++$00                   ;reset vram buffer offset used in conjunction with
  5910.               sta VRAM_Buffer2_Offset    ;level graphics buffer at $0341-$035f
  5911. RunParser:    jsr AreaParserTaskHandler  ;update the name table with more level graphics
  5912. ExitEng:      rts                        ;and after all that, we're finally done!
  5913.  
  5914. ;-------------------------------------------------------------------------------------
  5915.  
  5916. ScrollHandler:
  5917.             lda Player_X_Scroll       ;load value saved here
  5918.             clc
  5919.             adci Platform_X_Scroll     ;add value used by left/right platforms
  5920.             sta Player_X_Scroll       ;save as new value here to impose force on scroll
  5921.             lda ScrollLock            ;check scroll lock flag
  5922.          checka
  5923.             bne InitScrlAmt           ;skip a bunch of code here if set
  5924.             lda Player_Pos_ForScroll
  5925.             cmpn ++$50                  ;check player's horizontal screen position
  5926.               cmpcy
  5927.             bcc InitScrlAmt           ;if less than 80 pixels to the right, branch
  5928.             lda SideCollisionTimer    ;if timer related to player's side collision
  5929.          checka
  5930.             bne InitScrlAmt           ;not expired, branch
  5931.             ldy Player_X_Scroll       ;get value and decrement by one
  5932.             dey                       ;if value originally set to zero or otherwise
  5933.             bmi InitScrlAmt           ;negative for left movement, branch
  5934.             iny
  5935.             cpyn ++$02                  ;if value $01, branch and do not decrement
  5936.               cmpcy
  5937.             bcc ChkNearMid
  5938.             dey                       ;otherwise decrement by one
  5939. ChkNearMid: lda Player_Pos_ForScroll
  5940.             cmpn ++$70                  ;check player's horizontal screen position
  5941.               cmpcy
  5942.             bcc ScrollScreen          ;if less than 112 pixels to the right, branch
  5943.             ldy Player_X_Scroll       ;otherwise get original value undecremented
  5944.  
  5945. ScrollScreen:
  5946.               tya
  5947.               sta ScrollAmount          ;save value here
  5948.               clc
  5949.               adci ScrollThirtyTwo       ;add to value already set here
  5950.               sta ScrollThirtyTwo       ;save as new value here
  5951.               tya
  5952.               clc
  5953.               adci ScreenLeft_X_Pos      ;add to left side coordinate
  5954.               sta ScreenLeft_X_Pos      ;save as new left side coordinate
  5955.               sta HorizontalScroll      ;save here also
  5956.               lda ScreenLeft_PageLoc
  5957.               adcn ++$00                  ;add carry to page location for left
  5958.               sta ScreenLeft_PageLoc    ;side of the screen
  5959.               andn ++$01                  ;get LSB of page location
  5960.               sta SCRATCHPAD+$00                   ;save as temp variable for PPU register 1 mirror
  5961.               lda Mirror_PPU_CTRL_REG1  ;get PPU register 1 mirror
  5962.               andn ++%11111110            ;save all bits except d0
  5963.               orai SCRATCHPAD+$00                   ;get saved bit here and save in PPU register 1
  5964.               sta Mirror_PPU_CTRL_REG1  ;mirror to be used to set name table later
  5965.               jsr GetScreenPosition     ;figure out where the right side is
  5966.               ldan ++$08
  5967.               sta ScrollIntervalTimer   ;set scroll timer (residual, not used elsewhere)
  5968.               jmp ChkPOffscr            ;skip this part
  5969. InitScrlAmt:  ldan ++$00
  5970.               sta ScrollAmount          ;initialize value here
  5971. ChkPOffscr:   ldxn ++$00                  ;set X for player offset
  5972.               jsr GetXOffscreenBits     ;get horizontal offscreen bits for player
  5973.               sta SCRATCHPAD+$00                   ;save them here
  5974.               ldyn ++$00                  ;load default offset (left side)
  5975.               asl                       ;if d7 of offscreen bits are set, ;TODO >>4 т GetXOffscreenBits
  5976.               bcs KeepOnscr             ;branch with default offset
  5977.               iny                         ;otherwise use different offset (right side)
  5978.               lda SCRATCHPAD+$00
  5979.               andn ++%00100000              ;check offscreen bits for d5 set ;TODO >>4 т GetXOffscreenBits
  5980.               beq InitPlatScrl            ;if not set, branch ahead of this part
  5981. KeepOnscr:    lday ScreenEdge_X_Pos,y      ;get left or right side coordinate based on offset
  5982.               secsub
  5983.               sbcy X_SubtracterData,y      ;subtract amount based on offset
  5984.               sta Player_X_Position       ;store as player position to prevent movement further
  5985.               ldaykeepcy ScreenEdge_PageLoc,y    ;get left or right page location based on offset
  5986.               sbcn ++$00                    ;subtract borrow
  5987.               sta Player_PageLoc          ;save as player's page location
  5988.               lda Left_Right_Buttons      ;check saved controller bits
  5989.               cmpy OffscrJoypadBitsData,y  ;against bits based on offset
  5990.               beq InitPlatScrl            ;if not equal, branch
  5991.               ldan ++$00
  5992.               sta Player_X_Speed          ;otherwise nullify horizontal speed of player
  5993. InitPlatScrl: ldan ++$00                    ;nullify platform force imposed on scroll
  5994.               sta Platform_X_Scroll
  5995.               rts
  5996.  
  5997. X_SubtracterData:
  5998.       .db $00, $10
  5999.  
  6000. OffscrJoypadBitsData:
  6001.       .db $01, $02
  6002.  
  6003. ;-------------------------------------------------------------------------------------
  6004.  
  6005. GetScreenPosition:
  6006.       lda ScreenLeft_X_Pos    ;get coordinate of screen's left boundary
  6007.       clc
  6008.       adcn ++$ff                ;add 255 pixels
  6009.       sta ScreenRight_X_Pos   ;store as coordinate of screen's right boundary
  6010.       lda ScreenLeft_PageLoc  ;get page number where left boundary is
  6011.       adcn ++$00                ;add carry from before
  6012.       sta ScreenRight_PageLoc ;store as page number where right boundary is
  6013.       rts
  6014.  
  6015. ;-------------------------------------------------------------------------------------
  6016.  
  6017. GameRoutines:
  6018.       lda GameEngineSubroutine  ;run routine based on number (a few of these routines are  
  6019.       jsr JumpEngine            ;merely placeholders as conditions for other routines)
  6020.  
  6021.       .dw Entrance_GameTimerSetup
  6022.       .dw Vine_AutoClimb
  6023.       .dw SideExitPipeEntry
  6024.       .dw VerticalPipeEntry
  6025.       .dw FlagpoleSlide
  6026.       .dw PlayerEndLevel
  6027.       .dw PlayerLoseLife
  6028.       .dw PlayerEntrance
  6029.       .dw PlayerCtrlRoutine
  6030.       .dw PlayerChangeSize
  6031.       .dw PlayerInjuryBlink
  6032.       .dw PlayerDeath
  6033.       .dw PlayerFireFlower
  6034.  
  6035. ;-------------------------------------------------------------------------------------
  6036.  
  6037. PlayerEntrance:
  6038.             lda AltEntranceControl    ;check for mode of alternate entry
  6039.             cmpn ++$02
  6040.             beq EntrMode2             ;if found, branch to enter from pipe or with vine
  6041.             ldan ++$00      
  6042.             ldy Player_Y_Position     ;if vertical position above a certain
  6043.             cpyn ++$30                  ;point, nullify controller bits and continue
  6044.               cmpcy
  6045.             bcc AutoControlPlayer     ;with player movement code, do not return
  6046.             lda PlayerEntranceCtrl    ;check player entry bits from header
  6047.             cmpn ++$06
  6048.             beq ChkBehPipe            ;if set to 6 or 7, execute pipe intro code
  6049.             cmpn ++$07                  ;otherwise branch to normal entry
  6050.             bne PlayerRdy
  6051. ChkBehPipe: lda Player_SprAttrib      ;check for sprite attributes
  6052.          checka
  6053.             bne IntroEntr             ;branch if found
  6054.             ldan ++$01
  6055.             jmp AutoControlPlayer     ;force player to walk to the right
  6056. IntroEntr:  jsr EnterSidePipe         ;execute sub to move player to the right
  6057.             deci ChangeAreaTimer       ;decrement timer for change of area
  6058.             bne ExitEntr              ;branch to exit if not yet expired
  6059.             inci DisableIntermediate   ;set flag to skip world and lives display
  6060.             jmp NextArea              ;jump to increment to next area and set modes
  6061. EntrMode2:  lda JoypadOverride        ;if controller override bits set here,
  6062.          checka
  6063.             bne VineEntr              ;branch to enter with vine
  6064.             ldan ++$ff                  ;otherwise, set value here then execute sub
  6065.             jsr MovePlayerYAxis       ;to move player upwards (note $ff = -1)
  6066.             lda Player_Y_Position     ;check to see if player is at a specific coordinate
  6067.             cmpn ++$91                  ;if player risen to a certain point (this requires pipes
  6068.               cmpcy
  6069.             bcc PlayerRdy             ;to be at specific height to look/function right) branch
  6070.             rts                       ;to the last part, otherwise leave
  6071. VineEntr:   lda VineHeight
  6072.             cmpn ++$60                  ;check vine height
  6073.             bne ExitEntr              ;if vine not yet reached maximum height, branch to leave
  6074.             lda Player_Y_Position     ;get player's vertical coordinate
  6075.             cmpn ++$99                  ;check player's vertical coordinate against preset value
  6076.               cmpcy
  6077.             ldyn ++$00                  ;load default values to be written to
  6078.             ldan ++$01                  ;this value moves player to the right off the vine
  6079.             bcc OffVine               ;if vertical coordinate LOW  preset value, use defaults
  6080.             ldan ++$03
  6081.             sta Player_State          ;otherwise set player state to climbing
  6082.             iny                       ;increment value in Y
  6083.             ldan ++$08                  ;set block in block buffer to cover hole, then
  6084.             sta Block_Buffer_1+$b4    ;use same value to force player to climb
  6085. OffVine:    sty DisableCollisionDet   ;set collision detection disable flag
  6086.             jsr AutoControlPlayer     ;use contents of A to move player up or right, execute sub
  6087.             lda Player_X_Position
  6088.             cmpn ++$48                  ;check player's horizontal position
  6089.               cmpcy
  6090.             bcc ExitEntr              ;if not far enough to the right, branch to leave
  6091. PlayerRdy:  ldan ++$08                  ;set routine to be executed by game engine next frame
  6092.             sta GameEngineSubroutine
  6093.             ldan ++$01                  ;set to face player to the right
  6094.             sta PlayerFacingDir
  6095.             lsr                       ;init A
  6096.             sta AltEntranceControl    ;init mode of entry
  6097.             sta DisableCollisionDet   ;init collision detection disable flag
  6098.             sta JoypadOverride        ;nullify controller override bits
  6099. ExitEntr:   rts                       ;leave!
  6100.  
  6101. ;-------------------------------------------------------------------------------------
  6102. ;$07 - used to hold upper limit of high byte when player falls down hole
  6103.  
  6104. AutoControlPlayer:
  6105.       sta SavedJoypadBits         ;override controller bits with contents of A if executing here
  6106.  
  6107. PlayerCtrlRoutine:
  6108.             lda GameEngineSubroutine    ;check task here
  6109.             cmpn ++$0b                    ;if certain value is set, branch to skip controller bit loading (playerdeath)
  6110.             beq SizeChk
  6111.             lda AreaType                ;are we in a water type area? є эрё ёэрўрыр 1???
  6112.          checka
  6113.             bne SaveJoyp                ;if not, branch
  6114.             ldy Player_Y_HighPos
  6115.             dey                         ;if not in vertical area between
  6116.             bne DisJoyp                 ;status bar and bottom, branch
  6117.             lda Player_Y_Position
  6118.             cmpn ++$d0                    ;if nearing the bottom of the screen or
  6119.               cmpcy
  6120.             bcc SaveJoyp                ;not in the vertical area between status bar or bottom,
  6121. DisJoyp:    ldan ++$00                    ;disable controller bits
  6122.             sta SavedJoypadBits
  6123. SaveJoyp:   lda SavedJoypadBits         ;otherwise store A and B buttons in $0a
  6124.             andn ++%11000000
  6125.             sta A_B_Buttons
  6126.             lda SavedJoypadBits         ;store left and right buttons in $0c
  6127.             andn ++%00000011
  6128.             sta Left_Right_Buttons
  6129.             lda SavedJoypadBits         ;store up and down buttons in $0b
  6130.             andn ++%00001100
  6131.             sta Up_Down_Buttons
  6132.             andn ++%00000100              ;check for pressing down
  6133.             beq SizeChk                 ;if not, branch
  6134.             lda Player_State            ;check player's state
  6135.          checka
  6136.             bne SizeChk                 ;if not on the ground, branch
  6137.             ldy Left_Right_Buttons      ;check left and right
  6138.          checky
  6139.             beq SizeChk                 ;if neither pressed, branch
  6140.             ldan ++$00
  6141.             sta Left_Right_Buttons      ;if pressing down while on the ground,
  6142.             sta Up_Down_Buttons         ;nullify directional bits
  6143. SizeChk:    jsr PlayerMovementSubs      ;run movement subroutines
  6144.             ldyn ++$01                    ;is player small?
  6145.             lda PlayerSize
  6146.          checka
  6147.             bne ChkMoveDir
  6148.             ldyn ++$00                    ;check for if crouching
  6149.             lda CrouchingFlag
  6150.          checka
  6151.             beq ChkMoveDir              ;if not, branch ahead
  6152.             ldyn ++$02                    ;if big and crouching, load y with 2
  6153. ChkMoveDir: sty Player_BoundBoxCtrl     ;set contents of Y as player's bounding box size control
  6154.             ldan ++$01                    ;set moving direction to right by default
  6155.             ldy Player_X_Speed          ;check player's horizontal speed
  6156.          checky
  6157.             beq PlayerSubs              ;if not moving at all horizontally, skip this part
  6158.             bpl SetMoveDir              ;if moving to the right, use default moving direction
  6159.             asl                         ;otherwise change to move to the left
  6160. SetMoveDir: sta Player_MovingDir        ;set moving direction
  6161. PlayerSubs: jsr ScrollHandler           ;move the screen if necessary
  6162.             jsr GetPlayerOffscreenBits  ;get player's offscreen bits
  6163.             jsr RelativePlayerPosition  ;get coordinates relative to the screen
  6164.             ldxn ++$00                    ;set offset for player object
  6165.             jsr BoundingBoxCore         ;get player's bounding box coordinates
  6166.             jsr PlayerBGCollision       ;do collision detection and process
  6167.             lda Player_Y_Position
  6168.             cmpn ++$40                    ;check to see if player is higher than 64th pixel
  6169.               cmpcy
  6170.             bcc PlayerHole              ;if so, branch ahead
  6171.             lda GameEngineSubroutine
  6172.             cmpn ++$05                    ;if running end-of-level routine, branch ahead
  6173.             beq PlayerHole
  6174.             cmpn ++$07                    ;if running player entrance routine, branch ahead
  6175.             beq PlayerHole
  6176.             cmpn ++$04                    ;if running routines $00-$03, branch ahead
  6177.               cmpcy
  6178.             bcc PlayerHole
  6179.             lda Player_SprAttrib
  6180.             andn ++%11011111              ;otherwise nullify player's
  6181.             sta Player_SprAttrib        ;background priority flag
  6182. PlayerHole: lda Player_Y_HighPos        ;check player's vertical high byte
  6183.             cmpn ++$02                    ;for below the screen
  6184.             bmi ExitCtrl                ;branch to leave if not that far down
  6185.             ldxn ++$01
  6186.             stx ScrollLock              ;set scroll lock
  6187.             ldyn ++$04
  6188.             sty SCRATCHPAD+$07                     ;set value here
  6189.             ldxn ++$00                    ;use X as flag, and clear for cloud level
  6190.             ldy GameTimerExpiredFlag    ;check game timer expiration flag
  6191.          checky
  6192.             bne HoleDie                 ;if set, branch
  6193.             ldy CloudTypeOverride       ;check for cloud type override
  6194.          checky
  6195.             bne ChkHoleX                ;skip to last part if found
  6196. HoleDie:    inx                         ;set flag in X for player death
  6197.             ldy GameEngineSubroutine
  6198.             cpyn ++$0b                    ;check for some other routine running (playerdeath)
  6199.             beq ChkHoleX                ;if so, branch ahead
  6200.             ldy DeathMusicLoaded        ;check value here
  6201.          checky
  6202.             bne HoleBottom              ;if already set, branch to next part
  6203.             iny
  6204.             sty EventMusicQueue         ;otherwise play death music
  6205.             sty DeathMusicLoaded        ;and set value here
  6206. HoleBottom: ldyn ++$06
  6207.             sty SCRATCHPAD+$07                     ;change value here
  6208. ChkHoleX:   cmpi SCRATCHPAD+$07                     ;compare vertical high byte with value set here
  6209.             bmi ExitCtrl                ;if less, branch to leave
  6210.             dex                         ;otherwise decrement flag in X
  6211.             bmi CloudExit               ;if flag was clear, branch to set modes and other values
  6212.             ldy EventMusicBuffer        ;check to see if music is still playing
  6213.          checky
  6214.             bne ExitCtrl                ;branch to leave if so
  6215.             ldan ++$06                    ;otherwise set to run lose life routine
  6216.             sta GameEngineSubroutine    ;on next frame
  6217. ExitCtrl:   rts                         ;leave
  6218.  
  6219. CloudExit:
  6220.       ldan ++$00
  6221.       sta JoypadOverride      ;clear controller override bits if any are set
  6222.       jsr SetEntr             ;do sub to set secondary mode
  6223.       inci AltEntranceControl  ;set mode of entry to 3
  6224.       rts
  6225.  
  6226. ;-------------------------------------------------------------------------------------
  6227.  
  6228. Vine_AutoClimb:
  6229.            lda Player_Y_HighPos   ;check to see whether player reached position
  6230.          checka
  6231.            bne AutoClimb          ;above the status bar yet and if so, set modes
  6232.            lda Player_Y_Position
  6233.            cmpn ++$e4
  6234.               cmpcy
  6235.            bcc SetEntr
  6236. AutoClimb: ldan ++%00001000         ;set controller bits override to up
  6237.            sta JoypadOverride
  6238.            ldyn ++$03               ;set player state to climbing
  6239.            sty Player_State
  6240.            jmp AutoControlPlayer
  6241. SetEntr:   ldan ++$02               ;set starting position to override
  6242.            sta AltEntranceControl
  6243.            jmp ChgAreaMode        ;set modes
  6244.  
  6245. ;-------------------------------------------------------------------------------------
  6246.  
  6247. VerticalPipeEntry:
  6248.       ldan ++$01             ;set 1 as movement amount
  6249.       jsr MovePlayerYAxis  ;do sub to move player downwards
  6250.       jsr ScrollHandler    ;do sub to scroll screen with saved force if necessary
  6251.       ldyn ++$00             ;load default mode of entry
  6252.       lda WarpZoneControl  ;check warp zone control variable/flag
  6253.          checka
  6254.       bne ChgAreaPipe      ;if set, branch to use mode 0
  6255.       iny
  6256.       lda AreaType         ;check for castle level type
  6257.       cmpn ++$03
  6258.       bne ChgAreaPipe      ;if not castle type level, use mode 1
  6259.       iny
  6260.       jmp ChgAreaPipe      ;otherwise use mode 2
  6261.  
  6262. MovePlayerYAxis:
  6263.       clc
  6264.       adci Player_Y_Position ;add contents of A to player position
  6265.       sta Player_Y_Position
  6266.       rts
  6267.  
  6268. ;-------------------------------------------------------------------------------------
  6269.  
  6270. SideExitPipeEntry:
  6271.              jsr EnterSidePipe         ;execute sub to move player to the right
  6272.              ldyn ++$02
  6273. ChgAreaPipe: deci ChangeAreaTimer       ;decrement timer for change of area
  6274.              bne ExitCAPipe
  6275.              sty AltEntranceControl    ;when timer expires set mode of alternate entry
  6276. ChgAreaMode: inci DisableScreenFlag     ;set flag to disable screen output
  6277.              ldan ++$00
  6278.              sta OperMode_Task         ;set secondary mode of operation
  6279.              sta Sprite0HitDetectFlag  ;disable sprite 0 check
  6280. ExitCAPipe:  rts                       ;leave
  6281.  
  6282. EnterSidePipe:
  6283.            ldan ++$08               ;set player's horizontal speed
  6284.            sta Player_X_Speed
  6285.            ldyn ++$01               ;set controller right button by default
  6286.            lda Player_X_Position  ;mask out higher nybble of player's
  6287.            andn ++%00001111         ;horizontal position
  6288.            bne RightPipe
  6289.            sta Player_X_Speed     ;if lower nybble = 0, set as horizontal speed
  6290.            tay                    ;and nullify controller bit override here
  6291. RightPipe: tya                    ;use contents of Y to
  6292.            jsr AutoControlPlayer  ;execute player control routine with ctrl bits nulled
  6293.            rts
  6294.  
  6295. ;-------------------------------------------------------------------------------------
  6296.  
  6297. PlayerChangeSize:
  6298.              lda TimerControl    ;check master timer control
  6299.              cmpn ++$f8            ;for specific moment in time
  6300.              bne EndChgSize      ;branch if before or after that point
  6301.              jmp InitChangeSize  ;otherwise run code to get growing/shrinking going
  6302. EndChgSize:  cmpn ++$c4            ;check again for another specific moment
  6303.              bne ExitChgSize     ;and branch to leave if before or after that point
  6304.              jsr DonePlayerTask  ;otherwise do sub to init timer control and set routine
  6305. ExitChgSize: rts                 ;and then leave
  6306.  
  6307. ;-------------------------------------------------------------------------------------
  6308.  
  6309. PlayerInjuryBlink:
  6310.            lda TimerControl       ;check master timer control
  6311.            cmpn ++$f0               ;for specific moment in time
  6312.               cmpcy
  6313.            bcs ExitBlink          ;branch if before that point
  6314.            cmpn ++$c8               ;check again for another specific point
  6315.            beq DonePlayerTask     ;branch if at that point, and not before or after
  6316.            jmp PlayerCtrlRoutine  ;otherwise run player control routine
  6317. ExitBlink: bne ExitBoth           ;do unconditional branch to leave
  6318.  
  6319. InitChangeSize:
  6320.           ldy PlayerChangeSizeFlag  ;if growing/shrinking flag already set
  6321.          checky
  6322.           bne ExitBoth              ;then branch to leave
  6323.           sty PlayerAnimCtrl        ;otherwise initialize player's animation frame control
  6324.           inci PlayerChangeSizeFlag  ;set growing/shrinking flag
  6325.           lda PlayerSize
  6326.           eorn ++$01                  ;invert player's size
  6327.           sta PlayerSize
  6328. ExitBoth: rts                       ;leave
  6329.  
  6330. ;-------------------------------------------------------------------------------------
  6331. ;$00 - used in CyclePlayerPalette to store current palette to cycle
  6332.  
  6333. PlayerDeath:
  6334.       lda TimerControl       ;check master timer control
  6335.       cmpn ++$f0               ;for specific moment in time
  6336.               cmpcy
  6337.       bcs ExitDeath          ;branch to leave if before that point
  6338.       jmp PlayerCtrlRoutine  ;otherwise run player control routine
  6339.  
  6340. DonePlayerTask:
  6341.       ldan ++$00
  6342.       sta TimerControl          ;initialize master timer control to continue timers
  6343.       ldan ++$08
  6344.       sta GameEngineSubroutine  ;set player control routine to run next frame
  6345.       rts                       ;leave
  6346.  
  6347. PlayerFireFlower:
  6348.       lda TimerControl       ;check master timer control
  6349.       cmpn ++$c0               ;for specific moment in time
  6350.       beq ResetPalFireFlower ;branch if at moment, not before or after
  6351.       lda FrameCounter       ;get frame counter
  6352.       lsr
  6353.       lsr                    ;divide by four to change every four frames
  6354.  
  6355. CyclePlayerPalette:
  6356.         if Z80MARIOCYCLECOLOR
  6357.         ld hl,(curpalette)
  6358.         ld e,12*2
  6359.         add hl,de
  6360.         ld a,(hl)
  6361.         xor 0xf3
  6362.         ld (hl),a
  6363.         inc hl
  6364.         ld (hl),a
  6365.         inc hl
  6366.         inc hl
  6367.         inc hl
  6368.         ld a,(hl)
  6369.         xor 0xf3
  6370.         ld (hl),a
  6371.         inc hl
  6372.         ld (hl),a
  6373.         else
  6374.       andn ++$03              ;mask out all but d1-d0 (previously d3-d2)
  6375.       sta SCRATCHPAD+$00               ;store result here to use as palette bits
  6376.       lda Player_SprAttrib  ;get player attributes
  6377.       andn ++%11111100        ;save any other bits but palette bits
  6378.       orai SCRATCHPAD+$00               ;add palette bits
  6379.       sta Player_SprAttrib  ;store as new player attributes
  6380.         endif
  6381.       rts                   ;and leave
  6382.  
  6383. ResetPalFireFlower:
  6384.       jsr DonePlayerTask    ;do sub to init timer control and run player control routine
  6385.  
  6386. ResetPalStar:
  6387.         if Z80MARIOCYCLECOLOR
  6388.         if 1
  6389.         jp GetPlayerColors
  6390.         else
  6391.         ld hl,(curpalette)
  6392.         ld e,12*2
  6393.         add hl,de
  6394.         ld a,(hl)
  6395.         xor 0xf3
  6396.         ld (hl),a
  6397.         inc hl
  6398.         ld (hl),a
  6399.         inc hl
  6400.         inc hl
  6401.         inc hl
  6402.         ld a,(hl)
  6403.         xor 0xf3
  6404.         ld (hl),a
  6405.         inc hl
  6406.         ld (hl),a
  6407.         ret
  6408.         endif
  6409.         else
  6410.       lda Player_SprAttrib  ;get player attributes
  6411.       andn ++%11111100        ;mask out palette bits to force palette 0
  6412.       sta Player_SprAttrib  ;store as new player attributes
  6413.       rts                   ;and leave
  6414.         endif
  6415.  
  6416. ExitDeath:
  6417.       rts          ;leave from death routine
  6418.  
  6419. ;-------------------------------------------------------------------------------------
  6420.  
  6421. FlagpoleSlide:
  6422.              lda Enemy_ID+5           ;check special use enemy slot
  6423.              cmpn ++FlagpoleFlagObject  ;for flagpole flag object
  6424.              bne NoFPObj              ;if not found, branch to something residual
  6425.              lda FlagpoleSoundQueue   ;load flagpole sound
  6426.              sta Square1SoundQueue    ;into square 1's sfx queue
  6427.              ldan ++$00
  6428.              sta FlagpoleSoundQueue   ;init flagpole sound queue
  6429.              ldy Player_Y_Position
  6430.              cpyn ++$9e                 ;check to see if player has slid down
  6431.               cmpcy
  6432.              bcs SlidePlayer          ;far enough, and if so, branch with no controller bits set
  6433.              ldan ++$04                 ;otherwise force player to climb down (to slide)
  6434. SlidePlayer: jmp AutoControlPlayer    ;jump to player control routine
  6435. NoFPObj:     inci GameEngineSubroutine ;increment to next routine (this may
  6436.              rts                      ;be residual code)
  6437.  
  6438. ;-------------------------------------------------------------------------------------
  6439.  
  6440. Hidden1UpCoinAmts:
  6441.       .db $15, $23, $16, $1b, $17, $18, $23, $63
  6442.  
  6443. PlayerEndLevel:
  6444.         if MUSICONINT ;ъюёЄ√ы№: фхырхь фю т√їюфр шч єЁютэ  Ёхцшь MUSICONINT=0
  6445.      ;YIELD
  6446.      ;ld b,0
  6447.      ;ld d,b
  6448.      halt
  6449.         ;ld hl,0xffff
  6450.         ;ld (EventMusicQueue_noint),hl
  6451.         ld hl,SoundEngine
  6452.         ld (soundenginepatch),hl
  6453.         ld a,0x21
  6454.         ld (soundenginecall),a
  6455.         endif
  6456.           ldan ++$01                  ;force player to walk to the right
  6457.           jsr AutoControlPlayer
  6458.           lda Player_Y_Position     ;check player's vertical position
  6459.           cmpn ++$ae
  6460.               cmpcy
  6461.           bcc ChkStop               ;if player is not yet off the flagpole, skip this part
  6462.           lda ScrollLock            ;if scroll lock not set, branch ahead to next part
  6463.          checka
  6464.           beq ChkStop               ;because we only need to do this part once
  6465.           ldan ++EndOfLevelMusic
  6466.           sta EventMusicQueue       ;load win level music in event music queue
  6467.           ldan ++$00
  6468.           sta ScrollLock            ;turn off scroll lock to skip this part later
  6469. ChkStop:  lda Player_CollisionBits  ;get player collision bits
  6470.           lsr                       ;check for d0 set
  6471.           bcs RdyNextA              ;if d0 set, skip to next part
  6472.           lda StarFlagTaskControl   ;if star flag task control already set,
  6473.          checka
  6474.           bne InCastle              ;go ahead with the rest of the code
  6475.           inci StarFlagTaskControl   ;otherwise set task control now (this gets ball rolling!)
  6476. InCastle: ldan ++%00100000            ;set player's background priority bit to
  6477.           sta Player_SprAttrib      ;give illusion of being inside the castle
  6478. RdyNextA: lda StarFlagTaskControl
  6479.           cmpn ++$05                  ;if star flag task control not yet set
  6480.           bne ExitNA                ;beyond last valid task number, branch to leave
  6481.           inci LevelNumber           ;increment level number used for game logic
  6482.           lda LevelNumber
  6483.           cmpn ++$03                  ;check to see if we have yet reached level -4
  6484.           bne NextArea              ;and skip this last part here if not
  6485.           ldy WorldNumber           ;get world number as offset
  6486.           lda CoinTallyFor1Ups      ;check third area coin tally for bonus 1-ups
  6487.           cmpy Hidden1UpCoinAmts,y   ;against minimum value, if player has not collected
  6488.               cmpcy
  6489.           bcc NextArea              ;at least this number of coins, leave flag clear
  6490.           inci Hidden1UpFlag         ;otherwise set hidden 1-up box control flag
  6491. NextArea: inci AreaNumber            ;increment area number used for address loader
  6492.           jsr LoadAreaPointer       ;get new level pointer
  6493.           inci FetchNewGameTimerFlag ;set flag to load new game timer
  6494.           jsr ChgAreaMode           ;do sub to set secondary mode, disable screen and sprite 0
  6495.           sta HalfwayPage           ;reset halfway page to 0 (beginning)
  6496.           ldan ++Silence
  6497.           sta EventMusicQueue       ;silence music and leave
  6498. ExitNA:   rts
  6499.  
  6500. ;-------------------------------------------------------------------------------------
  6501.  
  6502. PlayerMovementSubs:
  6503.            ldan ++$00                  ;set A to init crouch flag by default
  6504.            ldy PlayerSize            ;is player small?
  6505.          checky
  6506.            bne SetCrouch             ;if so, branch
  6507.            lda Player_State          ;check state of player
  6508.          checka
  6509.            bne ProcMove              ;if not on the ground, branch
  6510.            lda Up_Down_Buttons       ;load controller bits for up and down
  6511.            andn ++%00000100            ;single out bit for down button
  6512. SetCrouch: sta CrouchingFlag         ;store value in crouch flag
  6513. ProcMove:  jsr PlayerPhysicsSub      ;run sub related to jumping and swimming
  6514.            lda PlayerChangeSizeFlag  ;if growing/shrinking flag set,
  6515.          checka
  6516.            bne NoMoveSub             ;branch to leave
  6517.            lda Player_State
  6518.            cmpn ++$03                  ;get player state
  6519.            beq MoveSubs              ;if climbing, branch ahead, leave timer unset
  6520.            ldyn ++$18
  6521.            sty ClimbSideTimer        ;otherwise reset timer now
  6522. MoveSubs:  jsr JumpEngine
  6523.  
  6524.       .dw OnGroundStateSub
  6525.       .dw JumpSwimSub
  6526.       .dw FallingSub
  6527.       .dw ClimbingSub
  6528.  
  6529. NoMoveSub: rts
  6530.  
  6531. ;-------------------------------------------------------------------------------------
  6532. ;$00 - used by ClimbingSub to store high vertical adder
  6533.  
  6534. OnGroundStateSub:
  6535.          jsr GetPlayerAnimSpeed     ;do a sub to set animation frame timing
  6536.          lda Left_Right_Buttons
  6537.          checka
  6538.          beq GndMove                ;if left/right controller bits not set, skip instruction
  6539.          ;jr $ ;ё■фр Ёхфъю яюярфрхь яю ъэюяърь left,right
  6540.          sta PlayerFacingDir        ;otherwise set new facing direction
  6541. GndMove: jsr ImposeFriction         ;do a sub to impose friction on player's walk/run
  6542.          jsr MovePlayerHorizontally ;do another sub to move player horizontally
  6543.          sta Player_X_Scroll        ;set returned value as player's movement speed for scroll
  6544.          rts
  6545.  
  6546. ;--------------------------------
  6547.  
  6548. FallingSub:
  6549.       lda VerticalForceDown
  6550.       sta VerticalForce      ;dump vertical movement force for falling into main one
  6551.       jmp LRAir              ;movement force, then skip ahead to process left/right movement
  6552.  
  6553. ;--------------------------------
  6554.  
  6555. JumpSwimSub:
  6556.           ldy Player_Y_Speed         ;if player's vertical speed zero
  6557.          checky
  6558.           bpl DumpFall               ;or moving downwards, branch to falling
  6559.           lda A_B_Buttons
  6560.           andn ++A_Button              ;check to see if A button is being pressed
  6561.           andi PreviousA_B_Buttons    ;and was pressed in previous frame
  6562.           bne ProcSwim               ;if so, branch elsewhere
  6563.           lda JumpOrigin_Y_Position  ;get vertical position player jumped from
  6564.           secsub
  6565.           sbci Player_Y_Position      ;subtract current from original vertical coordinate
  6566.           cmpi DiffToHaltJump         ;compare to value set here to see if player is in mid-jump
  6567.               cmpcy
  6568.           bcc ProcSwim               ;or just starting to jump, if just starting, skip ahead
  6569. DumpFall: lda VerticalForceDown      ;otherwise dump falling into main fractional
  6570.           sta VerticalForce
  6571. ProcSwim: lda SwimmingFlag           ;if swimming flag not set, ;є эрё ёэрўрыр 0???
  6572.          checka
  6573.           beq LRAir                  ;branch ahead to last part
  6574.           jsr GetPlayerAnimSpeed     ;do a sub to get animation frame timing
  6575.           lda Player_Y_Position
  6576.           cmpn ++$14                   ;check vertical position against preset value
  6577.               cmpcy
  6578.           bcs LRWater                ;if not yet reached a certain position, branch ahead
  6579.           ldan ++$18
  6580.           sta VerticalForce          ;otherwise set fractional
  6581. LRWater:  lda Left_Right_Buttons     ;check left/right controller bits (check for swimming)
  6582.          checka
  6583.           beq LRAir                  ;if not pressing any, skip
  6584.           sta PlayerFacingDir        ;otherwise set facing direction accordingly
  6585. ;ё■фр тїюф х∙╕ шч FallingSub
  6586. LRAir:    lda Left_Right_Buttons     ;check left/right controller bits (check for jumping/falling)
  6587.          checka
  6588.           beq JSMove                 ;if not pressing any, skip
  6589.           jsr ImposeFriction         ;otherwise process horizontal movement
  6590. JSMove:   jsr MovePlayerHorizontally ;do a sub to move player horizontally
  6591.           sta Player_X_Scroll        ;set player's speed here, to be used for scroll later
  6592.           lda GameEngineSubroutine
  6593.           cmpn ++$0b                   ;check for specific routine selected (playerdeath)
  6594.           bne ExitMov1               ;branch if not set to run
  6595.           ldan ++$28
  6596.           sta VerticalForce          ;otherwise set fractional
  6597. ExitMov1: jmp MovePlayerVertically   ;jump to move player vertically, then leave
  6598.  
  6599. ;--------------------------------
  6600.  
  6601. ClimbAdderLow:
  6602.       .db $0e, $04, $fc, $f2
  6603. ClimbAdderHigh:
  6604.       .db $00, $00, $ff, $ff
  6605.  
  6606. ClimbingSub:
  6607.              lda Player_YMF_Dummy
  6608.              clc                      ;add movement force to dummy variable
  6609.              adci Player_Y_MoveForce   ;save with carry
  6610.              sta Player_YMF_Dummy
  6611.              ldyn ++$00                 ;set default adder here
  6612.              lda Player_Y_Speed       ;get player's vertical speed
  6613.          checka
  6614.              bpl MoveOnVine           ;if not moving upwards, branch
  6615.              dey                      ;otherwise set adder to $ff
  6616. MoveOnVine:  sty SCRATCHPAD+$00                  ;store adder here
  6617.              adci Player_Y_Position    ;add carry to player's vertical position
  6618.              sta Player_Y_Position    ;and store to move player up or down
  6619.              lda Player_Y_HighPos
  6620.              adci SCRATCHPAD+$00                  ;add carry to player's page location
  6621.              sta Player_Y_HighPos     ;and store
  6622.              lda Left_Right_Buttons   ;compare left/right controller bits
  6623.              andi Player_CollisionBits ;to collision flag
  6624.              beq InitCSTimer          ;if not set, skip to end
  6625.              ldy ClimbSideTimer       ;otherwise check timer
  6626.          checky
  6627.              bne ExitCSub             ;if timer not expired, branch to leave
  6628.              ldyn ++$18
  6629.              sty ClimbSideTimer       ;otherwise set timer now
  6630.              ldxn ++$00                 ;set default offset here
  6631.              ldy PlayerFacingDir      ;get facing direction
  6632.              lsr                      ;move right button controller bit to carry
  6633.              bcs ClimbFD              ;if controller right pressed, branch ahead
  6634.              inx
  6635.              inx                      ;otherwise increment offset by 2 bytes
  6636. ClimbFD:     dey                      ;check to see if facing right
  6637.              beq CSetFDir             ;if so, branch, do not increment
  6638.              inx                      ;otherwise increment by 1 byte
  6639. CSetFDir:    lda Player_X_Position
  6640.              clc                      ;add or subtract from player's horizontal position
  6641.              adcx ClimbAdderLow,x      ;using value here as adder and X as offset
  6642.              sta Player_X_Position
  6643.              lda Player_PageLoc       ;add or subtract carry or borrow using value here
  6644.              adcx ClimbAdderHigh,x     ;from the player's page location
  6645.              sta Player_PageLoc
  6646.              lda Left_Right_Buttons   ;get left/right controller bits again
  6647.              eorn ++%00000011           ;invert them and store them while player
  6648.              sta PlayerFacingDir      ;is on vine to face player in opposite direction
  6649. ExitCSub:    rts                      ;then leave
  6650. InitCSTimer: sta ClimbSideTimer       ;initialize timer here
  6651.              rts
  6652.  
  6653. ;-------------------------------------------------------------------------------------
  6654. ;$00 - used to store offset to friction data
  6655.  
  6656. JumpMForceData:
  6657.       .db $20, $20, $1e, $28, $28, $0d, $04
  6658.  
  6659. FallMForceData:
  6660.       .db $70, $70, $60, $90, $90, $0a, $09
  6661.  
  6662. PlayerYSpdData:
  6663.       .db $fc, $fc, $fc, $fb, $fb, $fe, $ff
  6664.  
  6665. InitMForceData:
  6666.       .db $00, $00, $00, $00, $00, $80, $00
  6667.  
  6668. MaxLeftXSpdData:
  6669.       .db $d8, $e8, $f0
  6670.  
  6671. MaxRightXSpdData:
  6672.       .db $28, $18, $10
  6673.       .db $0c ;used for pipe intros
  6674.  
  6675. FrictionData:
  6676.       .db $e4, $98, $d0
  6677.  
  6678. Climb_Y_SpeedData:
  6679.       .db $00, $ff, $01
  6680.  
  6681. Climb_Y_MForceData:
  6682.       .db $00, $20, $ff
  6683.  
  6684. PlayerPhysicsSub:
  6685.            lda Player_State          ;check player state
  6686.            cmpn ++$03
  6687.            bne CheckForJumping       ;if not climbing, branch
  6688.            ldyn ++$00
  6689.            lda Up_Down_Buttons       ;get controller bits for up/down
  6690.            andi Player_CollisionBits  ;check against player's collision detection bits
  6691.            beq ProcClimb             ;if not pressing up or down, branch
  6692.            iny
  6693.            andn ++%00001000            ;check for pressing up
  6694.            bne ProcClimb
  6695.            iny
  6696. ProcClimb: ldxy Climb_Y_MForceData,y  ;load value here
  6697.            stx Player_Y_MoveForce    ;store as vertical movement force
  6698.            ldan ++$08                  ;load default animation timing
  6699.            ldxy Climb_Y_SpeedData,y   ;load some other value here
  6700.            stx Player_Y_Speed        ;store as vertical speed
  6701.          checkx
  6702.            bmi SetCAnim              ;if climbing down, use default animation timing value
  6703.            lsr                       ;otherwise divide timer setting by 2
  6704. SetCAnim:  sta PlayerAnimTimerSet    ;store animation timer setting and leave
  6705.            rts
  6706.  
  6707. CheckForJumping:
  6708.         lda JumpspringAnimCtrl    ;if jumpspring animating,
  6709.          checka
  6710.         bne NoJump                ;skip ahead to something else
  6711.         lda A_B_Buttons           ;check for A button press
  6712.         andn ++A_Button
  6713.         beq NoJump                ;if not, branch to something else
  6714.         andi PreviousA_B_Buttons   ;if button not pressed in previous frame, branch
  6715.         beq ProcJumping
  6716. NoJump: jmp X_Physics             ;otherwise, jump to something else
  6717.  
  6718. ProcJumping:
  6719.            lda Player_State           ;check player state
  6720.          checka
  6721.            beq InitJS                 ;if on the ground, branch
  6722.            lda SwimmingFlag           ;if swimming flag not set, jump to do something else
  6723.          checka
  6724.            beq NoJump                 ;to prevent midair jumping, otherwise continue
  6725.            lda JumpSwimTimer          ;if jump/swim timer nonzero, branch
  6726.          checka
  6727.            bne InitJS
  6728.            lda Player_Y_Speed         ;check player's vertical speed
  6729.          checka
  6730.            bpl InitJS                 ;if player's vertical speed motionless or down, branch
  6731.            jmp X_Physics              ;if timer at zero and player still rising, do not swim
  6732. InitJS:    ldan ++$20                   ;set jump/swim timer
  6733.            sta JumpSwimTimer
  6734.            ldyn ++$00                   ;initialize vertical force and dummy variable
  6735.            sty Player_YMF_Dummy
  6736.            sty Player_Y_MoveForce
  6737.            lda Player_Y_HighPos       ;get vertical high and low bytes of jump origin
  6738.            sta JumpOrigin_Y_HighPos   ;and store them next to each other here
  6739.            lda Player_Y_Position
  6740.            sta JumpOrigin_Y_Position
  6741.            ldan ++$01                   ;set player state to jumping/swimming
  6742.            sta Player_State
  6743.            lda Player_XSpeedAbsolute  ;check value related to walking/running speed
  6744.            cmpn ++$09
  6745.               cmpcy
  6746.            bcc ChkWtr                 ;branch if below certain values, increment Y
  6747.            iny                        ;for each amount equal or exceeded
  6748.            cmpn ++$10
  6749.               cmpcy
  6750.            bcc ChkWtr
  6751.            iny
  6752.            cmpn ++$19
  6753.               cmpcy
  6754.            bcc ChkWtr
  6755.            iny
  6756.            cmpn ++$1c
  6757.               cmpcy
  6758.            bcc ChkWtr                 ;note that for jumping, range is 0-4 for Y
  6759.            iny
  6760. ChkWtr:    ldan ++$01                   ;set value here (apparently always set to 1)
  6761.            sta DiffToHaltJump
  6762.            lda SwimmingFlag           ;if swimming flag disabled, branch
  6763.          checka
  6764.            beq GetYPhy
  6765.            ldyn ++$05                   ;otherwise set Y to 5, range is 5-6
  6766.            lda Whirlpool_Flag         ;if whirlpool flag not set, branch
  6767.          checka
  6768.            beq GetYPhy
  6769.            iny                        ;otherwise increment to 6
  6770. GetYPhy:   lday JumpMForceData,y       ;store appropriate jump/swim
  6771.            sta VerticalForce          ;data here
  6772.            lday FallMForceData,y
  6773.            sta VerticalForceDown
  6774.            lday InitMForceData,y
  6775.            sta Player_Y_MoveForce
  6776.            lday PlayerYSpdData,y
  6777.            sta Player_Y_Speed
  6778.            lda SwimmingFlag           ;if swimming flag disabled, branch
  6779.          checka
  6780.            beq PJumpSnd
  6781.            ldan ++Sfx_EnemyStomp        ;load swim/goomba stomp sound into
  6782.            sta Square1SoundQueue      ;square 1's sfx queue
  6783.            lda Player_Y_Position
  6784.            cmpn ++$14                   ;check vertical low byte of player position
  6785.               cmpcy
  6786.            bcs X_Physics              ;if below a certain point, branch
  6787.            ldan ++$00                   ;otherwise reset player's vertical speed
  6788.            sta Player_Y_Speed         ;and jump to something else to keep player
  6789.            jmp X_Physics              ;from swimming above water level
  6790. PJumpSnd:  ldan ++Sfx_BigJump           ;load big mario's jump sound by default
  6791.            ldy PlayerSize             ;is mario big?
  6792.          checky
  6793.            beq SJumpSnd
  6794.            ldan ++Sfx_SmallJump         ;if not, load small mario's jump sound
  6795. SJumpSnd:  sta Square1SoundQueue      ;store appropriate jump sound in square 1 sfx queue
  6796. X_Physics: ldyn ++$00
  6797.            sty SCRATCHPAD+$00                    ;init value here
  6798.            lda Player_State           ;if mario is on the ground, branch
  6799.          checka
  6800.            beq ProcPRun
  6801.            lda Player_XSpeedAbsolute  ;check something that seems to be related
  6802.            cmpn ++$19                   ;to mario's speed
  6803.               cmpcy
  6804.            bcs GetXPhy                ;if => $19 branch here
  6805.            bcc ChkRFast               ;if not branch elsewhere
  6806. ProcPRun:  iny                        ;if mario on the ground, increment Y
  6807.            lda AreaType               ;check area type
  6808.          checka
  6809.            beq ChkRFast               ;if water type, branch
  6810.            dey                        ;decrement Y by default for non-water type area
  6811.            lda Left_Right_Buttons     ;get left/right controller bits
  6812.            cmpi Player_MovingDir       ;check against moving direction
  6813.            bne ChkRFast               ;if controller bits <> moving direction, skip this part
  6814.            lda A_B_Buttons            ;check for b button pressed
  6815.            andn ++B_Button
  6816.            bne SetRTmr                ;if pressed, skip ahead to set timer
  6817.            lda RunningTimer           ;check for running timer set
  6818.          checka
  6819.            bne GetXPhy                ;if set, branch
  6820. ChkRFast:  iny                        ;if running timer not set or level type is water,
  6821.            inci SCRATCHPAD+$00                    ;increment Y again and temp variable in memory
  6822.            lda RunningSpeed
  6823.          checka
  6824.            bne FastXSp                ;if running speed set here, branch
  6825.            lda Player_XSpeedAbsolute
  6826.            cmpn ++$21                   ;otherwise check player's walking/running speed
  6827.               cmpcy
  6828.            bcc GetXPhy                ;if less than a certain amount, branch ahead
  6829. FastXSp:   inci SCRATCHPAD+$00                    ;if running speed set or speed => $21 increment $00
  6830.            jmp GetXPhy                ;and jump ahead
  6831. SetRTmr:   ldan ++$0a                   ;if b button pressed, set running timer
  6832.            sta RunningTimer
  6833. GetXPhy:   lday MaxLeftXSpdData,y      ;get maximum speed to the left
  6834.            sta MaximumLeftSpeed
  6835.            lda GameEngineSubroutine   ;check for specific routine running
  6836.            cmpn ++$07                   ;(player entrance)
  6837.            bne GetXPhy2               ;if not running, skip and use old value of Y
  6838.            ldyn ++$03                   ;otherwise set Y to 3
  6839. GetXPhy2:  lday MaxRightXSpdData,y     ;get maximum speed to the right
  6840.            sta MaximumRightSpeed
  6841.            ldy SCRATCHPAD+$00                    ;get other value in memory
  6842.            lday FrictionData,y         ;get value using value in memory as offset
  6843.            sta FrictionAdderLow
  6844.            ldan ++$00
  6845.            sta FrictionAdderHigh      ;init something here
  6846.            lda PlayerFacingDir
  6847.            cmpi Player_MovingDir       ;check facing direction against moving direction
  6848.            beq ExitPhy                ;if the same, branch to leave
  6849.            asli FrictionAdderLow       ;otherwise shift d7 of friction adder low into carry
  6850.            roli FrictionAdderHigh      ;then rotate carry onto d0 of friction adder high
  6851. ExitPhy:   rts                        ;and then leave
  6852.  
  6853. ;-------------------------------------------------------------------------------------
  6854.  
  6855. PlayerAnimTmrData:
  6856.       .db $02, $04, $07
  6857.  
  6858. GetPlayerAnimSpeed:
  6859.             ldyn ++$00                   ;initialize offset in Y
  6860.             lda Player_XSpeedAbsolute  ;check player's walking/running speed
  6861.             cmpn ++$1c                   ;against preset amount
  6862.               cmpcy
  6863.             bcs SetRunSpd              ;if greater than a certain amount, branch ahead
  6864.             iny                        ;otherwise increment Y
  6865.             cmpn ++$0e                   ;compare against lower amount
  6866.               cmpcy
  6867.             bcs ChkSkid                ;if greater than this but not greater than first, skip increment
  6868.             iny                        ;otherwise increment Y again
  6869. ChkSkid:    lda SavedJoypadBits        ;get controller bits
  6870.             andn ++%01111111             ;mask out A button
  6871.             beq SetAnimSpd             ;if no other buttons pressed, branch ahead of all this
  6872.             andn ++$03                   ;mask out all others except left and right
  6873.             cmpi Player_MovingDir       ;check against moving direction
  6874.             bne ProcSkid               ;if left/right controller bits <>  moving direction, branch
  6875.             ldan ++$00                   ;otherwise set zero value here
  6876. SetRunSpd:  sta RunningSpeed           ;store zero or running speed here
  6877.             jmp SetAnimSpd
  6878. ProcSkid:   lda Player_XSpeedAbsolute  ;check player's walking/running speed
  6879.             cmpn ++$0b                   ;against one last amount
  6880.               cmpcy
  6881.             bcs SetAnimSpd             ;if greater than this amount, branch
  6882.             lda PlayerFacingDir
  6883.             sta Player_MovingDir       ;otherwise use facing direction to set moving direction
  6884.             ldan ++$00
  6885.             sta Player_X_Speed         ;nullify player's horizontal speed
  6886.             sta Player_X_MoveForce     ;and dummy variable for player (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  6887. SetAnimSpd: lday PlayerAnimTmrData,y    ;get animation timer setting using Y as offset
  6888.             sta PlayerAnimTimerSet
  6889.             rts
  6890.  
  6891. ;-------------------------------------------------------------------------------------
  6892.  
  6893. ImposeFriction:
  6894.            andi Player_CollisionBits  ;perform AND between left/right controller bits and collision flag
  6895.            cmpn ++$00                  ;then compare to zero (this instruction is redundant)
  6896.            bne JoypFrict             ;if any bits set, branch to next part
  6897.            lda Player_X_Speed
  6898.          checka
  6899.            beq SetAbsSpd             ;if player has no horizontal speed, branch ahead to last part
  6900.            bpl RghtFrict             ;if player moving to the right, branch to slow
  6901.            bmi LeftFrict             ;otherwise logic dictates player moving left, branch to slow
  6902. JoypFrict: lsr                       ;put right controller bit into carry
  6903.            bcc RghtFrict             ;if left button pressed, carry = 0, thus branch
  6904. LeftFrict: lda Player_X_MoveForce    ;load value set here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  6905.            clc
  6906.            adci FrictionAdderLow      ;add to it another value set here (яюўхьє??? ¤Єю цх эх ьырф°р  ўрёЄ№ ёъюЁюёЄш!)
  6907.            sta Player_X_MoveForce    ;store here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  6908.            lda Player_X_Speed
  6909.            adci FrictionAdderHigh     ;add value plus carry to horizontal speed
  6910.            sta Player_X_Speed        ;set as new horizontal speed
  6911.            cmpi MaximumRightSpeed     ;compare against maximum value for right movement
  6912.            bmi XSpdSign              ;if horizontal speed greater negatively, branch
  6913.            lda MaximumRightSpeed     ;otherwise set preset value as horizontal speed
  6914.            sta Player_X_Speed        ;thus slowing the player's left movement down
  6915.            jmp SetAbsSpd             ;skip to the end
  6916. RghtFrict: lda Player_X_MoveForce    ;load value set here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  6917.            secsub
  6918.            sbci FrictionAdderLow      ;subtract from it another value set here (яюўхьє??? ¤Єю цх эх ьырф°р  ўрёЄ№ ёъюЁюёЄш!)
  6919.            sta Player_X_MoveForce    ;store here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  6920.            lda Player_X_Speed
  6921.            sbci FrictionAdderHigh     ;subtract value plus borrow from horizontal speed
  6922.            sta Player_X_Speed        ;set as new horizontal speed
  6923.            cmpi MaximumLeftSpeed      ;compare against maximum value for left movement
  6924.            bpl XSpdSign              ;if horizontal speed greater positively, branch
  6925.            lda MaximumLeftSpeed      ;otherwise set preset value as horizontal speed
  6926.            sta Player_X_Speed        ;thus slowing the player's right movement down
  6927. XSpdSign:  cmpn ++$00                  ;if player not moving or moving to the right,
  6928.            bpl SetAbsSpd             ;branch and leave horizontal speed value unmodified
  6929.            eorn ++$ff
  6930.            clc                       ;otherwise get two's compliment to get absolute
  6931.            adcn ++$01                  ;unsigned walking/running speed
  6932. SetAbsSpd: sta Player_XSpeedAbsolute ;store walking/running speed here and leave
  6933.            rts
  6934.  
  6935. ;-------------------------------------------------------------------------------------
  6936. ;$00 - used to store downward movement force in FireballObjCore
  6937. ;$02 - used to store maximum vertical speed in FireballObjCore
  6938. ;$07 - used to store pseudorandom bit in BubbleCheck
  6939.  
  6940. ProcFireball_Bubble:
  6941.       lda PlayerStatus           ;check player's status
  6942.       cmpn ++$02
  6943.               cmpcy
  6944.       bcc ProcAirBubbles         ;if not fiery, branch
  6945.       lda A_B_Buttons
  6946.       andn ++B_Button              ;check for b button pressed
  6947.       beq ProcFireballs          ;branch if not pressed
  6948.       andi PreviousA_B_Buttons
  6949.       bne ProcFireballs          ;if button pressed in previous frame, branch
  6950.       lda FireballCounter        ;load fireball counter
  6951.       andn ++%00000001             ;get LSB and use as offset for buffer
  6952.       tax
  6953.       ldax Fireball_State,x       ;load fireball state
  6954.          checka
  6955.       bne ProcFireballs          ;if not inactive, branch
  6956.       ldy Player_Y_HighPos       ;if player too high or too low, branch
  6957.       dey
  6958.       bne ProcFireballs
  6959.       lda CrouchingFlag          ;if player crouching, branch
  6960.          checka
  6961.       bne ProcFireballs
  6962.       lda Player_State           ;if player's state = climbing, branch
  6963.       cmpn ++$03
  6964.       beq ProcFireballs
  6965.       ldan ++Sfx_Fireball          ;play fireball sound effect
  6966.       sta Square1SoundQueue
  6967.       ldan ++$02                   ;load state
  6968.       stax Fireball_State,x
  6969.       ldy PlayerAnimTimerSet     ;copy animation frame timer setting
  6970.       sty FireballThrowingTimer  ;into fireball throwing timer
  6971.       dey
  6972.       sty PlayerAnimTimer        ;decrement and store in player's animation timer
  6973.       inci FireballCounter        ;increment fireball counter
  6974.  
  6975. ProcFireballs:
  6976.       ldxn ++$00
  6977.       jsr FireballObjCore  ;process first fireball object
  6978.       ldxn ++$01
  6979.       jsr FireballObjCore  ;process second fireball object, then do air bubbles
  6980.  
  6981. ProcAirBubbles:
  6982.           lda AreaType                ;if not water type level, skip the rest of this
  6983.          checka
  6984.           bne BublExit
  6985.           ldxn ++$02                    ;otherwise load counter and use as offset
  6986. BublLoop: stx ObjectOffset            ;store offset
  6987.           jsr BubbleCheck             ;check timers and coordinates, create air bubble
  6988.           jsr RelativeBubblePosition  ;get relative coordinates
  6989.           jsr GetBubbleOffscreenBits  ;get offscreen information
  6990.           jsr DrawBubble              ;draw the air bubble
  6991.           dex
  6992.           bpl BublLoop                ;do this until all three are handled
  6993. BublExit: rts                         ;then leave
  6994.  
  6995. FireballXSpdData:
  6996.       .db $40, $c0
  6997.  
  6998. FireballObjCore:
  6999.          stx ObjectOffset             ;store offset as current object
  7000.          ldax Fireball_State,x         ;check for d7 = 1
  7001.          asl
  7002.          bcs FireballExplosion        ;if so, branch to get relative coordinates and draw explosion
  7003.          ldyx Fireball_State,x         ;if fireball inactive, branch to leave
  7004.          checky
  7005.          beq NoFBall
  7006.          dey                          ;if fireball state set to 1, skip this part and just run it
  7007.          beq RunFB
  7008.          lda Player_X_Position        ;get player's horizontal position
  7009.         or a
  7010.          adcn ++$04                     ;add four pixels and store as fireball's horizontal position
  7011.         push af
  7012.          stax Fireball_X_Position,x
  7013.         pop af
  7014.          lda Player_PageLoc           ;get player's page location
  7015.          adcn ++$00                     ;add carry and store as fireball's page location
  7016.          stax Fireball_PageLoc,x
  7017.          lda Player_Y_Position        ;get player's vertical position and store
  7018.          stax Fireball_Y_Position,x
  7019.          ldan ++$01                     ;set high byte of vertical position
  7020.          stax Fireball_Y_HighPos,x
  7021.          ldy PlayerFacingDir          ;get player's facing direction
  7022.          dey                          ;decrement to use as offset here
  7023.          lday FireballXSpdData,y       ;set horizontal speed of fireball accordingly
  7024.          stax Fireball_X_Speed,x
  7025.          ldan ++$04                     ;set vertical speed of fireball
  7026.          stax Fireball_Y_Speed,x
  7027.          ldan ++$07
  7028.          stax Fireball_BoundBoxCtrl,x  ;set bounding box size control for fireball
  7029.          decx Fireball_State,x         ;decrement state to 1 to skip this part from now on
  7030. RunFB:   txa                          ;add 7 to offset to use
  7031.          clc                          ;as fireball offset for next routines
  7032.          adcn ++$07
  7033.          tax
  7034.          ldan ++$50                     ;set downward movement force here
  7035.          sta SCRATCHPAD+$00
  7036.          ldan ++$03                     ;set maximum speed here
  7037.          sta SCRATCHPAD+$02
  7038.          ldan ++$00
  7039.          jsr ImposeGravity            ;do sub here to impose gravity on fireball and move vertically
  7040.          jsr MoveObjectHorizontally   ;do another sub to move it horizontally
  7041.          ldx ObjectOffset             ;return fireball offset to X
  7042.          jsr RelativeFireballPosition ;get relative coordinates
  7043.          jsr GetFireballOffscreenBits ;get offscreen information
  7044.          jsr GetFireballBoundBox      ;get bounding box coordinates
  7045.          jsr FireballBGCollision      ;do fireball to background collision detection
  7046.          lda FBall_OffscreenBits      ;get fireball offscreen bits
  7047.          andn ++%11001100               ;mask out certain bits
  7048.          bne EraseFB                  ;if any bits still set, branch to kill fireball
  7049.          jsr FireballEnemyCollision   ;do fireball to enemy collision detection and deal with collisions
  7050.          jmp DrawFireball             ;draw fireball appropriately and leave
  7051. EraseFB: ldan ++$00                     ;erase fireball state
  7052.          stax Fireball_State,x
  7053. NoFBall: rts                          ;leave
  7054.  
  7055. FireballExplosion:
  7056.       jsr RelativeFireballPosition
  7057.       jmp DrawExplosion_Fireball
  7058.  
  7059. BubbleCheck:
  7060.       ldax PseudoRandomBitReg+1,x  ;get part of LSFR
  7061.       andn ++$01
  7062.       sta SCRATCHPAD+$07                     ;store pseudorandom bit here
  7063.       ldax Bubble_Y_Position,x     ;get vertical coordinate for air bubble
  7064.       cmpn ++$f8                    ;if offscreen coordinate not set,
  7065.       bne MoveBubl                ;branch to move air bubble
  7066.       lda AirBubbleTimer          ;if air bubble timer not expired,
  7067.          checka
  7068.       bne ExitBubl                ;branch to leave, otherwise create new air bubble
  7069.  
  7070. SetupBubble:
  7071.           ldyn ++$00                 ;load default value here
  7072.           lda PlayerFacingDir      ;get player's facing direction
  7073.           lsr                      ;move d0 to carry
  7074.           bcc PosBubl              ;branch to use default value if facing left
  7075.           ldyn ++$08                 ;otherwise load alternate value here
  7076. PosBubl:  tya                      ;use value loaded as adder
  7077.           adci Player_X_Position    ;add to player's horizontal position
  7078.          push af
  7079.           stax Bubble_X_Position,x  ;save as horizontal position for airbubble
  7080.          pop af
  7081.           lda Player_PageLoc
  7082.           adcn ++$00                 ;add carry to player's page location
  7083.           stax Bubble_PageLoc,x     ;save as page location for airbubble
  7084.           lda Player_Y_Position
  7085.           clc                      ;add eight pixels to player's vertical position
  7086.           adcn ++$08
  7087.           stax Bubble_Y_Position,x  ;save as vertical position for air bubble
  7088.           ldan ++$01
  7089.           stax Bubble_Y_HighPos,x   ;set vertical high byte for air bubble
  7090.           ldy SCRATCHPAD+$07                  ;get pseudorandom bit, use as offset
  7091.           lday BubbleTimerData,y    ;get data for air bubble timer
  7092.           sta AirBubbleTimer       ;set air bubble timer
  7093. MoveBubl: ldy SCRATCHPAD+$07                  ;get pseudorandom bit again, use as offset
  7094.           ldax Bubble_YMF_Dummy,x
  7095.           secsub                      ;subtract pseudorandom amount from dummy variable
  7096.           sbcy Bubble_MForceData,y
  7097.                push af
  7098.           stax Bubble_YMF_Dummy,x   ;save dummy variable
  7099.           ldax Bubble_Y_Position,x
  7100.                ld h,a
  7101.                pop af
  7102.                ld a,h
  7103.           sbcn ++$00                 ;subtract borrow from airbubble's vertical coordinate
  7104.           cmpn ++$20                 ;if below the status bar,
  7105.               cmpcy
  7106.           bcs Y_Bubl               ;branch to go ahead and use to move air bubble upwards
  7107.           ldan ++$f8                 ;otherwise set offscreen coordinate
  7108. Y_Bubl:   stax Bubble_Y_Position,x  ;store as new vertical coordinate for air bubble
  7109. ExitBubl: rts                      ;leave
  7110.  
  7111. Bubble_MForceData:
  7112.       .db $ff, $50
  7113.  
  7114. BubbleTimerData:
  7115.       .db $40, $20
  7116.  
  7117. ;-------------------------------------------------------------------------------------
  7118.  
  7119. RunGameTimer:
  7120.            lda OperMode               ;get primary mode of operation
  7121.          checka
  7122.            beq ExGTimer               ;branch to leave if in title screen mode
  7123.            lda GameEngineSubroutine
  7124.            cmpn ++$08                   ;if routine number less than eight running,
  7125.               cmpcy
  7126.            bcc ExGTimer               ;branch to leave
  7127.            cmpn ++$0b                   ;if running death routine,
  7128.            beq ExGTimer               ;branch to leave
  7129.            lda Player_Y_HighPos
  7130.            cmpn ++$02                   ;if player below the screen,
  7131.               cmpcy
  7132.            bcs ExGTimer               ;branch to leave regardless of level type
  7133.            lda GameTimerCtrlTimer     ;if game timer control not yet expired,
  7134.          checka
  7135.            bne ExGTimer               ;branch to leave
  7136.            lda GameTimerDisplay
  7137.            orai GameTimerDisplay+1     ;otherwise check game timer digits
  7138.            orai GameTimerDisplay+2
  7139.            beq TimeUpOn               ;if game timer digits at 000, branch to time-up code
  7140.            ldy GameTimerDisplay       ;otherwise check first digit
  7141.            dey                        ;if first digit not on 1,
  7142.            bne ResGTCtrl              ;branch to reset game timer control
  7143.            lda GameTimerDisplay+1     ;otherwise check second and third digits
  7144.            orai GameTimerDisplay+2
  7145.            bne ResGTCtrl              ;if timer not at 100, branch to reset game timer control
  7146.            ldan ++TimeRunningOutMusic
  7147.            sta EventMusicQueue        ;otherwise load time running out music
  7148. ResGTCtrl: ldan ++$18                   ;reset game timer control
  7149.            sta GameTimerCtrlTimer
  7150.            ldyn ++$23                   ;set offset for last digit
  7151.            ldan ++$ff                   ;set value to decrement game timer digit
  7152.            sta DigitModifier+5
  7153.            jsr DigitsMathRoutine      ;do sub to decrement game timer slowly
  7154.            ldan ++$a4                   ;set status nybbles to update game timer display
  7155.            jmp PrintStatusBarNumbers  ;do sub to update the display
  7156. TimeUpOn:  sta PlayerStatus           ;init player status (note A will always be zero here)
  7157.            jsr ForceInjury            ;do sub to kill the player (note player is small here)
  7158.            inci GameTimerExpiredFlag   ;set game timer expiration flag
  7159. ExGTimer:  rts                        ;leave
  7160.  
  7161. ;-------------------------------------------------------------------------------------
  7162.  
  7163. WarpZoneObject:
  7164.       lda ScrollLock         ;check for scroll lock flag
  7165.          checka
  7166.       beq ExGTimer           ;branch if not set to leave
  7167.       lda Player_Y_Position  ;check to see if player's vertical coordinate has
  7168.       andi Player_Y_HighPos   ;same bits set as in vertical high byte (why?)
  7169.       bne ExGTimer           ;if so, branch to leave
  7170.       sta ScrollLock         ;otherwise nullify scroll lock flag
  7171.       inci WarpZoneControl    ;increment warp zone flag to make warp pipes for warp zone
  7172.       jmp EraseEnemyObject   ;kill this object
  7173.  
  7174. ;-------------------------------------------------------------------------------------
  7175. ;$00 - used in WhirlpoolActivate to store whirlpool length / 2, page location of center of whirlpool
  7176. ;and also to store movement force exerted on player
  7177. ;$01 - used in ProcessWhirlpools to store page location of right extent of whirlpool
  7178. ;and in WhirlpoolActivate to store center of whirlpool
  7179. ;$02 - used in ProcessWhirlpools to store right extent of whirlpool and in
  7180. ;WhirlpoolActivate to store maximum vertical speed
  7181.  
  7182. ProcessWhirlpools:
  7183.         lda AreaType                ;check for water type level
  7184.          checka
  7185.         bne ExitWh                  ;branch to leave if not found
  7186.         sta Whirlpool_Flag          ;otherwise initialize whirlpool flag
  7187.         lda TimerControl            ;if master timer control set,
  7188.          checka
  7189.         bne ExitWh                  ;branch to leave
  7190.         ldyn ++$04                    ;otherwise start with last whirlpool data
  7191. WhLoop: lday Whirlpool_LeftExtent,y  ;get left extent of whirlpool
  7192.         clc
  7193.         adcy Whirlpool_Length,y      ;add length of whirlpool
  7194.         sta SCRATCHPAD+$02                     ;store result as right extent here
  7195.         ldaykeepcy Whirlpool_PageLoc,y     ;get page location
  7196.          checka
  7197.         beq NextWh                  ;if none or page 0, branch to get next data
  7198.         adcn ++$00                    ;add carry
  7199.         sta SCRATCHPAD+$01                     ;store result as page location of right extent here
  7200.         lda Player_X_Position       ;get player's horizontal position
  7201.         secsub
  7202.         sbcy Whirlpool_LeftExtent,y  ;subtract left extent
  7203.         lda Player_PageLoc          ;get player's page location
  7204.         sbcy Whirlpool_PageLoc,y     ;subtract borrow
  7205.         bmi NextWh                  ;if player too far left, branch to get next data
  7206.         lda SCRATCHPAD+$02                     ;otherwise get right extent
  7207.         secsub
  7208.         sbci Player_X_Position       ;subtract player's horizontal coordinate
  7209.         lda SCRATCHPAD+$01                     ;get right extent's page location
  7210.         sbci Player_PageLoc          ;subtract borrow
  7211.         bpl WhirlpoolActivate       ;if player within right extent, branch to whirlpool code
  7212. NextWh: dey                         ;move onto next whirlpool data
  7213.         bpl WhLoop                  ;do this until all whirlpools are checked
  7214. ExitWh: rts                         ;leave
  7215.  
  7216. WhirlpoolActivate:
  7217.         lday Whirlpool_Length,y      ;get length of whirlpool
  7218.         lsr                         ;divide by 2
  7219.         sta SCRATCHPAD+$00                     ;save here
  7220.         lday Whirlpool_LeftExtent,y  ;get left extent of whirlpool
  7221.         clc
  7222.         adci SCRATCHPAD+$00                     ;add length divided by 2
  7223.         sta SCRATCHPAD+$01                     ;save as center of whirlpool
  7224.         ldaykeepcy Whirlpool_PageLoc,y     ;get page location
  7225.         adcn ++$00                    ;add carry
  7226.         sta SCRATCHPAD+$00                     ;save as page location of whirlpool center
  7227.         lda FrameCounter            ;get frame counter
  7228.         lsr                         ;shift d0 into carry (to run on every other frame)
  7229.         bcc WhPull                  ;if d0 not set, branch to last part of code
  7230.         lda SCRATCHPAD+$01                     ;get center
  7231.         secsub
  7232.         sbci Player_X_Position       ;subtract player's horizontal coordinate
  7233.         lda SCRATCHPAD+$00                     ;get page location of center
  7234.         sbci Player_PageLoc          ;subtract borrow
  7235.         bpl LeftWh                  ;if player to the left of center, branch
  7236.         lda Player_X_Position       ;otherwise slowly pull player left, towards the center
  7237.         secsub
  7238.         sbcn ++$01                    ;subtract one pixel
  7239.         sta Player_X_Position       ;set player's new horizontal coordinate
  7240.         lda Player_PageLoc
  7241.         sbcn ++$00                    ;subtract borrow
  7242.         jmp SetPWh                  ;jump to set player's new page location
  7243. LeftWh: lda Player_CollisionBits    ;get player's collision bits
  7244.         lsr                         ;shift d0 into carry
  7245.         bcc WhPull                  ;if d0 not set, branch
  7246.         lda Player_X_Position       ;otherwise slowly pull player right, towards the center
  7247.         clc
  7248.         adcn ++$01                    ;add one pixel
  7249.         sta Player_X_Position       ;set player's new horizontal coordinate
  7250.         lda Player_PageLoc
  7251.         adcn ++$00                    ;add carry
  7252. SetPWh: sta Player_PageLoc          ;set player's new page location
  7253. WhPull: ldan ++$10
  7254.         sta SCRATCHPAD+$00                     ;set vertical movement force
  7255.         ldan ++$01
  7256.         sta Whirlpool_Flag          ;set whirlpool flag to be used later
  7257.         sta SCRATCHPAD+$02                     ;also set maximum vertical speed
  7258.         lsr
  7259.         tax                         ;set X for player offset
  7260.         jmp ImposeGravity           ;jump to put whirlpool effect on player vertically, do not return
  7261.  
  7262. ;-------------------------------------------------------------------------------------
  7263.  
  7264. FlagpoleScoreMods:
  7265.       .db $05, $02, $08, $04, $01
  7266.  
  7267. FlagpoleScoreDigits:
  7268.       .db $03, $03, $04, $04, $04
  7269.  
  7270. FlagpoleRoutine:
  7271.            ldxn ++$05                  ;set enemy object offset
  7272.            stx ObjectOffset          ;to special use slot
  7273.            ldax Enemy_ID,x
  7274.            cmpn ++FlagpoleFlagObject   ;if flagpole flag not found,
  7275.            bne ExitFlagP             ;branch to leave
  7276.            lda GameEngineSubroutine
  7277.            cmpn ++$04                  ;if flagpole slide routine not running,
  7278.            bne SkipScore             ;branch to near the end of code
  7279.            lda Player_State
  7280.            cmpn ++$03                  ;if player state not climbing,
  7281.            bne SkipScore             ;branch to near the end of code
  7282.            ldax Enemy_Y_Position,x    ;check flagpole flag's vertical coordinate
  7283.            cmpn ++$aa                  ;if flagpole flag down to a certain point,
  7284.               cmpcy
  7285.            bcs GiveFPScr             ;branch to end the level
  7286.            lda Player_Y_Position     ;check player's vertical coordinate
  7287.            cmpn ++$a2                  ;if player down to a certain point,
  7288.               cmpcy
  7289.            bcs GiveFPScr             ;branch to end the level
  7290.            ldax Enemy_YMF_Dummy,x
  7291.           or a
  7292.            adcn ++$ff                  ;add movement amount to dummy variable
  7293.           push af
  7294.            stax Enemy_YMF_Dummy,x     ;save dummy variable
  7295.            ldax Enemy_Y_Position,x    ;get flag's vertical coordinate
  7296.           ld h,a
  7297.           pop af
  7298.           ld a,h
  7299.            adcn ++$01                  ;add 1 plus carry to move flag, and
  7300.            stax Enemy_Y_Position,x    ;store vertical coordinate
  7301.            lda FlagpoleFNum_YMFDummy
  7302.            secsub                       ;subtract movement amount from dummy variable
  7303.            sbcn ++$ff
  7304.            sta FlagpoleFNum_YMFDummy ;save dummy variable
  7305.            lda FlagpoleFNum_Y_Pos
  7306.            sbcn ++$01                  ;subtract one plus borrow to move floatey number,
  7307.            sta FlagpoleFNum_Y_Pos    ;and store vertical coordinate here
  7308. SkipScore: jmp FPGfx                 ;jump to skip ahead and draw flag and floatey number
  7309. GiveFPScr: ldy FlagpoleScore         ;get score offset from earlier (when player touched flagpole)
  7310.            lday FlagpoleScoreMods,y   ;get amount to award player points
  7311.            ldxy FlagpoleScoreDigits,y ;get digit with which to award points
  7312.            stax DigitModifier,x       ;store in digit modifier
  7313.            jsr AddToScore            ;do sub to award player points depending on height of collision
  7314.            ldan ++$05
  7315.            sta GameEngineSubroutine  ;set to run end-of-level subroutine on next frame
  7316. FPGfx:     jsr GetEnemyOffscreenBits ;get offscreen information
  7317.            jsr RelativeEnemyPosition ;get relative coordinates
  7318.            jsr FlagpoleGfxHandler    ;draw flagpole flag and floatey number
  7319. ExitFlagP: rts
  7320.  
  7321. ;-------------------------------------------------------------------------------------
  7322.  
  7323. Jumpspring_Y_PosData:
  7324.       .db $08, $10, $08, $00
  7325.  
  7326. JumpspringHandler:
  7327.            jsr GetEnemyOffscreenBits   ;get offscreen information
  7328.            lda TimerControl            ;check master timer control
  7329.          checka
  7330.            bne DrawJSpr                ;branch to last section if set
  7331.            lda JumpspringAnimCtrl      ;check jumpspring frame control
  7332.          checka
  7333.            beq DrawJSpr                ;branch to last section if not set
  7334.            tay
  7335.            dey                         ;subtract one from frame control,
  7336.            tya                         ;the only way a poor nmos 6502 can
  7337.            andn ++%00000010              ;mask out all but d1, original value still in Y
  7338.            bne DownJSpr                ;if set, branch to move player up
  7339.            inci Player_Y_Position
  7340.            inci Player_Y_Position       ;move player's vertical position down two pixels
  7341.            jmp PosJSpr                 ;skip to next part
  7342. DownJSpr:  deci Player_Y_Position       ;move player's vertical position up two pixels
  7343.            deci Player_Y_Position
  7344. PosJSpr:   ldax Jumpspring_FixedYPos,x  ;get permanent vertical position
  7345.            clc
  7346.            adcy Jumpspring_Y_PosData,y  ;add value using frame control as offset
  7347.            stax Enemy_Y_Position,x      ;store as new vertical position
  7348.            cpyn ++$01                    ;check frame control offset (second frame is $00)
  7349.               cmpcy
  7350.            bcc BounceJS                ;if offset not yet at third frame ($01), skip to next part
  7351.            lda A_B_Buttons
  7352.            andn ++A_Button               ;check saved controller bits for A button press
  7353.            beq BounceJS                ;skip to next part if A not pressed
  7354.            andi PreviousA_B_Buttons     ;check for A button pressed in previous frame
  7355.            bne BounceJS                ;skip to next part if so
  7356.            ldan ++$f4
  7357.            sta JumpspringForce         ;otherwise write new jumpspring force here
  7358. BounceJS:  cpyn ++$03                    ;check frame control offset again
  7359.            bne DrawJSpr                ;skip to last part if not yet at fifth frame ($03)
  7360.            lda JumpspringForce
  7361.            sta Player_Y_Speed          ;store jumpspring force as player's new vertical speed
  7362.            ldan ++$00
  7363.            sta JumpspringAnimCtrl      ;initialize jumpspring frame control
  7364. DrawJSpr:  jsr RelativeEnemyPosition   ;get jumpspring's relative coordinates
  7365.            jsr EnemyGfxHandler         ;draw jumpspring
  7366.            jsr OffscreenBoundsCheck    ;check to see if we need to kill it
  7367.            lda JumpspringAnimCtrl      ;if frame control at zero, don't bother
  7368.          checka
  7369.            beq ExJSpring               ;trying to animate it, just leave
  7370.            lda JumpspringTimer
  7371.          checka
  7372.            bne ExJSpring               ;if jumpspring timer not expired yet, leave
  7373.            ldan ++$04
  7374.            sta JumpspringTimer         ;otherwise initialize jumpspring timer
  7375.            inci JumpspringAnimCtrl      ;increment frame control to animate jumpspring
  7376. ExJSpring: rts                         ;leave
  7377.  
  7378. ;-------------------------------------------------------------------------------------
  7379.  
  7380. Setup_Vine:
  7381.         ldan ++VineObject          ;load identifier for vine object
  7382.         stax Enemy_ID,x           ;store in buffer
  7383.         ldan ++$01
  7384.         stax Enemy_Flag,x         ;set flag for enemy object buffer
  7385.         lday Block_PageLoc,y
  7386.         stax Enemy_PageLoc,x      ;copy page location from previous object
  7387.         lday Block_X_Position,y
  7388.         stax Enemy_X_Position,x   ;copy horizontal coordinate from previous object
  7389.         lday Block_Y_Position,y
  7390.         stax Enemy_Y_Position,x   ;copy vertical coordinate from previous object
  7391.         ldy VineFlagOffset       ;load vine flag/offset to next available vine slot
  7392.          checky
  7393.         bne NextVO               ;if set at all, don't bother to store vertical
  7394.         sta VineStart_Y_Position ;otherwise store vertical coordinate here
  7395. NextVO: txa                      ;store object offset to next available vine slot
  7396.         stay VineObjOffset,y      ;using vine flag as offset
  7397.         inci VineFlagOffset       ;increment vine flag offset
  7398.         ldan ++Sfx_GrowVine
  7399.         sta Square2SoundQueue    ;load vine grow sound
  7400.         rts
  7401.  
  7402. ;-------------------------------------------------------------------------------------
  7403. ;$06-$07 - used as address to block buffer data
  7404. ;$02 - used as vertical high nybble of block buffer offset
  7405.  
  7406. VineHeightData:
  7407.       .db $30, $60
  7408.  
  7409. VineObjectHandler:
  7410.            cpxn ++$05                  ;check enemy offset for special use slot
  7411.            bne ExitVH                ;if not in last slot, branch to leave
  7412.            ldy VineFlagOffset
  7413.            dey                       ;decrement vine flag in Y, use as offset
  7414.            lda VineHeight
  7415.            cmpy VineHeightData,y      ;if vine has reached certain height,
  7416.            beq RunVSubs              ;branch ahead to skip this part
  7417.            lda FrameCounter          ;get frame counter
  7418.            lsr                       ;shift d1 into carry
  7419.            lsr
  7420.            bcc RunVSubs              ;if d1 not set (2 frames every 4) skip this part
  7421.            lda Enemy_Y_Position+5
  7422.           or a
  7423.            sbcn ++$01                  ;subtract vertical position of vine
  7424.            sta Enemy_Y_Position+5    ;one pixel every frame it's time
  7425.            inci VineHeight            ;increment vine height
  7426. RunVSubs:  lda VineHeight            ;if vine still very small,
  7427.            cmpn ++$08                  ;branch to leave
  7428.               cmpcy
  7429.            bcc ExitVH
  7430.            jsr RelativeEnemyPosition ;get relative coordinates of vine,
  7431.            jsr GetEnemyOffscreenBits ;and any offscreen bits
  7432.            ldyn ++$00                  ;initialize offset used in draw vine sub
  7433. VDrawLoop: jsr DrawVine              ;draw vine
  7434.            iny                       ;increment offset
  7435.            cpyi VineFlagOffset        ;if offset in Y and offset here
  7436.            bne VDrawLoop             ;do not yet match, loop back to draw more vine
  7437.            lda Enemy_OffscreenBits
  7438.            andn ++%00001100            ;mask offscreen bits
  7439.            beq WrCMTile              ;if none of the saved offscreen bits set, skip ahead
  7440.            dey                       ;otherwise decrement Y to get proper offset again
  7441. KillVine:  ldxy VineObjOffset,y       ;get enemy object offset for this vine object
  7442.            jsr EraseEnemyObject      ;kill this vine object
  7443.            dey                       ;decrement Y
  7444.            bpl KillVine              ;if any vine objects left, loop back to kill it
  7445.            sta VineFlagOffset        ;initialize vine flag/offset
  7446.            sta VineHeight            ;initialize vine height
  7447. WrCMTile:  lda VineHeight            ;check vine height
  7448.            cmpn ++$20                  ;if vine small (less than 32 pixels tall)
  7449.               cmpcy
  7450.            bcc ExitVH                ;then branch ahead to leave
  7451.            ldxn ++$06                  ;set offset in X to last enemy slot
  7452.            ldan ++$01                  ;set A to obtain horizontal in $04, but we don't care
  7453.            ldyn ++$1b                  ;set Y to offset to get block at ($04, $10) of coordinates
  7454.            jsr BlockBufferCollision  ;do a sub to get block buffer address set, return contents
  7455.            ldy SCRATCHPAD+$02
  7456.            cpyn ++$d0                  ;if vertical high nybble offset beyond extent of
  7457.               cmpcy
  7458.            bcs ExitVH                ;current block buffer, branch to leave, do not write
  7459.            ldayindirect (SCRATCHPAD+$06),y               ;otherwise check contents of block buffer at
  7460.          checka
  7461.            bne ExitVH                ;current offset, if not empty, branch to leave
  7462.            ldan ++$26
  7463.            stayindirect (SCRATCHPAD+$06),y               ;otherwise, write climbing metatile to block buffer
  7464. ExitVH:    ldx ObjectOffset          ;get enemy object offset and leave
  7465.            rts
  7466.  
  7467. ;-------------------------------------------------------------------------------------
  7468.  
  7469. CannonBitmasks:
  7470.       .db %00001111, %00000111
  7471.  
  7472. ProcessCannons:
  7473.            lda AreaType                ;get area type
  7474.          checka
  7475.            beq ExCannon                ;if water type area, branch to leave
  7476.            ldxn ++$02
  7477. ThreeSChk: stx ObjectOffset            ;start at third enemy slot
  7478.            ldax Enemy_Flag,x            ;check enemy buffer flag
  7479.          checka
  7480.            bne Chk_BB                  ;if set, branch to check enemy
  7481.            ldax PseudoRandomBitReg+1,x  ;otherwise get part of LSFR
  7482.            ldy SecondaryHardMode       ;get secondary hard mode flag, use as offset
  7483.            andy CannonBitmasks,y        ;mask out bits of LSFR as decided by flag
  7484.            cmpn ++$06                    ;check to see if lower nybble is above certain value
  7485.               cmpcy
  7486.            bcs Chk_BB                  ;if so, branch to check enemy
  7487.            tay                         ;transfer masked contents of LSFR to Y as pseudorandom offset
  7488.            lday Cannon_PageLoc,y        ;get page location
  7489.          checka
  7490.            beq Chk_BB                  ;if not set or on page 0, branch to check enemy
  7491.            lday Cannon_Timer,y          ;get cannon timer
  7492.          checka
  7493.            beq FireCannon              ;if expired, branch to fire cannon
  7494.           scf
  7495.            sbcn ++$00                    ;otherwise subtract borrow (note carry will always be clear here)
  7496.            stay Cannon_Timer,y          ;to count timer down
  7497.            jmp Chk_BB                  ;then jump ahead to check enemy
  7498.  
  7499. FireCannon:
  7500.           lda TimerControl           ;if master timer control set,
  7501.          checka
  7502.           bne Chk_BB                 ;branch to check enemy
  7503.           ldan ++$0e                   ;otherwise we start creating one
  7504.           stay Cannon_Timer,y         ;first, reset cannon timer
  7505.           lday Cannon_PageLoc,y       ;get page location of cannon
  7506.           stax Enemy_PageLoc,x        ;save as page location of bullet bill
  7507.           lday Cannon_X_Position,y    ;get horizontal coordinate of cannon
  7508.           stax Enemy_X_Position,x     ;save as horizontal coordinate of bullet bill
  7509.           lday Cannon_Y_Position,y    ;get vertical coordinate of cannon
  7510.           secsub
  7511.           sbcn ++$08                   ;subtract eight pixels (because enemies are 24 pixels tall)
  7512.           stax Enemy_Y_Position,x     ;save as vertical coordinate of bullet bill
  7513.           ldan ++$01
  7514.           stax Enemy_Y_HighPos,x      ;set vertical high byte of bullet bill
  7515.           stax Enemy_Flag,x           ;set buffer flag
  7516.           lsr                        ;shift right once to init A
  7517.           stax Enemy_State,x          ;then initialize enemy's state
  7518.           ldan ++$09
  7519.           stax Enemy_BoundBoxCtrl,x   ;set bounding box size control for bullet bill
  7520.           ldan ++BulletBill_CannonVar
  7521.           stax Enemy_ID,x             ;load identifier for bullet bill (cannon variant)
  7522.           jmp Next3Slt               ;move onto next slot
  7523. Chk_BB:   ldax Enemy_ID,x             ;check enemy identifier for bullet bill (cannon variant)
  7524.           cmpn ++BulletBill_CannonVar
  7525.           bne Next3Slt               ;if not found, branch to get next slot
  7526.           jsr OffscreenBoundsCheck   ;otherwise, check to see if it went offscreen
  7527.           ldax Enemy_Flag,x           ;check enemy buffer flag
  7528.          checka
  7529.           beq Next3Slt               ;if not set, branch to get next slot
  7530.           jsr GetEnemyOffscreenBits  ;otherwise, get offscreen information
  7531.           jsr BulletBillHandler      ;then do sub to handle bullet bill
  7532. Next3Slt: dex                        ;move onto next slot
  7533.           bpl ThreeSChk              ;do this until first three slots are checked
  7534. ExCannon: rts                        ;then leave
  7535.  
  7536. ;--------------------------------
  7537.  
  7538. BulletBillXSpdData:
  7539.       .db $18, $e8
  7540.  
  7541. BulletBillHandler:
  7542.            lda TimerControl          ;if master timer control set,
  7543.          checka
  7544.            bne RunBBSubs             ;branch to run subroutines except movement sub
  7545.            ldax Enemy_State,x
  7546.          checka
  7547.            bne ChkDSte               ;if bullet bill's state set, branch to check defeated state
  7548.            lda Enemy_OffscreenBits   ;otherwise load offscreen bits
  7549.            andn ++%00001100            ;mask out bits
  7550.            cmpn ++%00001100            ;check to see if all bits are set
  7551.            beq KillBB                ;if so, branch to kill this object
  7552.            ldyn ++$01                  ;set to move right by default
  7553.            jsr PlayerEnemyDiff       ;get horizontal difference between player and bullet bill
  7554.            bmi SetupBB               ;if enemy to the left of player, branch
  7555.            iny                       ;otherwise increment to move left
  7556. SetupBB:  
  7557.          push af
  7558.            styx Enemy_MovingDir,x     ;set bullet bill's moving direction
  7559.            dey                       ;decrement to use as offset
  7560.            lday BulletBillXSpdData,y  ;get horizontal speed based on moving direction
  7561.            stax Enemy_X_Speed,x       ;and store it
  7562.            lda SCRATCHPAD+$00                   ;get horizontal difference
  7563.          ld h,a
  7564.          pop af
  7565.          ld a,h
  7566.            adcn ++$28                  ;add 40 pixels
  7567.            cmpn ++$50                  ;if less than a certain amount, player is too close
  7568.               cmpcy
  7569.            bcc KillBB                ;to cannon either on left or right side, thus branch
  7570.            ldan ++$01
  7571.            stax Enemy_State,x         ;otherwise set bullet bill's state
  7572.            ldan ++$0a
  7573.            stax EnemyFrameTimer,x     ;set enemy frame timer
  7574.            ldan ++Sfx_Blast
  7575.            sta Square2SoundQueue     ;play fireworks/gunfire sound
  7576. ChkDSte:   ldax Enemy_State,x         ;check enemy state for d5 set
  7577.            andn ++%00100000
  7578.            beq BBFly                 ;if not set, skip to move horizontally
  7579.            jsr MoveD_EnemyVertically ;otherwise do sub to move bullet bill vertically
  7580. BBFly:     jsr MoveEnemyHorizontally ;do sub to move bullet bill horizontally
  7581. RunBBSubs: jsr GetEnemyOffscreenBits ;get offscreen information
  7582.            jsr RelativeEnemyPosition ;get relative coordinates
  7583.            jsr GetEnemyBoundBox      ;get bounding box coordinates
  7584.            jsr PlayerEnemyCollision  ;handle player to enemy collisions
  7585.            jmp EnemyGfxHandler       ;draw the bullet bill and leave
  7586. KillBB:    jsr EraseEnemyObject      ;kill bullet bill and leave
  7587.            rts
  7588.  
  7589. ;-------------------------------------------------------------------------------------
  7590.  
  7591. HammerEnemyOfsData:
  7592.       .db $04, $04, $04, $05, $05, $05
  7593.       .db $06, $06, $06
  7594.  
  7595. HammerXSpdData:
  7596.       .db $10, $f0
  7597.  
  7598. SpawnHammerObj:
  7599.           lda PseudoRandomBitReg+1 ;get pseudorandom bits from
  7600.           andn ++%00000111           ;second part of LSFR
  7601.           bne SetMOfs              ;if any bits are set, branch and use as offset
  7602.           lda PseudoRandomBitReg+1
  7603.           andn ++%00001000           ;get d3 from same part of LSFR
  7604. SetMOfs:  tay                      ;use either d3 or d2-d0 for offset here
  7605.           lday Misc_State,y         ;if any values loaded in
  7606.          checka
  7607.           bne NoHammer             ;$2a-$32 where offset is then leave with carry clear
  7608.           ldxy HammerEnemyOfsData,y ;get offset of enemy slot to check using Y as offset
  7609.           ldax Enemy_Flag,x         ;check enemy buffer flag at offset
  7610.          checka
  7611.           bne NoHammer             ;if buffer flag set, branch to leave with carry clear
  7612.           ldx ObjectOffset         ;get original enemy object offset
  7613.           txa
  7614.           stay HammerEnemyOffset,y  ;save here
  7615.           ldan ++$90
  7616.           stay Misc_State,y         ;save hammer's state here
  7617.           ldan ++$07
  7618.           stay Misc_BoundBoxCtrl,y  ;set something else entirely, here
  7619.           sec                      ;return with carry set
  7620.           rts
  7621. NoHammer: ldx ObjectOffset         ;get original enemy object offset
  7622.           clc                      ;return with carry clear
  7623.           rts
  7624.  
  7625. ;--------------------------------
  7626. ;$00 - used to set downward force
  7627. ;$01 - used to set upward force (residual)
  7628. ;$02 - used to set maximum speed
  7629.  
  7630. ProcHammerObj:
  7631.           lda TimerControl           ;if master timer control set
  7632.          checka
  7633.           bne RunHSubs               ;skip all of this code and go to last subs at the end
  7634.           ldax Misc_State,x           ;otherwise get hammer's state
  7635.           andn ++%01111111             ;mask out d7
  7636.           ldyx HammerEnemyOffset,x    ;get enemy object offset that spawned this hammer
  7637.           cmpn ++$02                   ;check hammer's state
  7638.               cmpcy
  7639.           beq SetHSpd                ;if currently at 2, branch
  7640.           bcs SetHPos                ;if greater than 2, branch elsewhere
  7641.           txa
  7642.           clc                        ;add 13 bytes to use
  7643.           adcn ++$0d                   ;proper misc object
  7644.           tax                        ;return offset to X
  7645.           ldan ++$10
  7646.           sta SCRATCHPAD+$00                    ;set downward movement force
  7647.           ldan ++$0f
  7648.           sta SCRATCHPAD+$01                    ;set upward movement force (not used)
  7649.           ldan ++$04
  7650.           sta SCRATCHPAD+$02                    ;set maximum vertical speed
  7651.           ldan ++$00                   ;set A to impose gravity on hammer
  7652.           jsr ImposeGravity          ;do sub to impose gravity on hammer and move vertically
  7653.           jsr MoveObjectHorizontally ;do sub to move it horizontally
  7654.           ldx ObjectOffset           ;get original misc object offset
  7655.           jmp RunAllH                ;branch to essential subroutines
  7656. SetHSpd:  ldan ++$fe
  7657.           stax Misc_Y_Speed,x         ;set hammer's vertical speed
  7658.           lday Enemy_State,y          ;get enemy object state
  7659.           andn ++%11110111             ;mask out d3
  7660.           stay Enemy_State,y          ;store new state
  7661.           ldxy Enemy_MovingDir,y      ;get enemy's moving direction
  7662.           dex                        ;decrement to use as offset
  7663.           ldax HammerXSpdData,x       ;get proper speed to use based on moving direction
  7664.           ldx ObjectOffset           ;reobtain hammer's buffer offset
  7665.           stax Misc_X_Speed,x         ;set hammer's horizontal speed
  7666. SetHPos:  decx Misc_State,x           ;decrement hammer's state
  7667.           lday Enemy_X_Position,y     ;get enemy's horizontal position
  7668.           clc
  7669.           adcn ++$02                   ;set position 2 pixels to the right
  7670.          push af
  7671.           stax Misc_X_Position,x      ;store as hammer's horizontal position
  7672.           lday Enemy_PageLoc,y        ;get enemy's page location
  7673.          ld h,a
  7674.          pop af
  7675.          ld a,h
  7676.           adcn ++$00                   ;add carry
  7677.           stax Misc_PageLoc,x         ;store as hammer's page location
  7678.           lday Enemy_Y_Position,y     ;get enemy's vertical position
  7679.           secsub
  7680.           sbcn ++$0a                   ;move position 10 pixels upward
  7681.           stax Misc_Y_Position,x      ;store as hammer's vertical position
  7682.           ldan ++$01
  7683.           stax Misc_Y_HighPos,x       ;set hammer's vertical high byte
  7684.          checka
  7685.           bne RunHSubs               ;unconditional branch to skip first routine
  7686. RunAllH:  jsr PlayerHammerCollision  ;handle collisions
  7687. RunHSubs: jsr GetMiscOffscreenBits   ;get offscreen information
  7688.           jsr RelativeMiscPosition   ;get relative coordinates
  7689.           jsr GetMiscBoundBox        ;get bounding box coordinates
  7690.           jsr DrawHammer             ;draw the hammer
  7691.           rts                        ;and we are done here
  7692.  
  7693. ;-------------------------------------------------------------------------------------
  7694. ;$02 - used to store vertical high nybble offset from block buffer routine
  7695. ;$06 - used to store low byte of block buffer address
  7696.  
  7697. CoinBlock:
  7698.       jsr FindEmptyMiscSlot   ;set offset for empty or last misc object buffer slot
  7699. ;CY = 1(no subtract borrow)???
  7700.       ldax Block_PageLoc,x     ;get page location of block object
  7701.       stay Misc_PageLoc,y      ;store as page location of misc object
  7702.       ldax Block_X_Position,x  ;get horizontal coordinate of block object
  7703.       oran ++$05                ;add 5 pixels
  7704.       stay Misc_X_Position,y   ;store as horizontal coordinate of misc object
  7705.       ldax Block_Y_Position,x  ;get vertical coordinate of block object
  7706.      or a ;???
  7707.       sbcn ++$10                ;subtract 16 pixels
  7708.       stay Misc_Y_Position,y   ;store as vertical coordinate of misc object
  7709.       jmp JCoinC              ;jump to rest of code as applies to this misc object
  7710.  
  7711. SetupJumpCoin:
  7712.         jsr FindEmptyMiscSlot  ;set offset for empty or last misc object buffer slot
  7713.         ldax Block_PageLoc2,x   ;get page location saved earlier
  7714.         stay Misc_PageLoc,y     ;and save as page location for misc object
  7715.         lda SCRATCHPAD+$06                ;get low byte of block buffer offset
  7716.         asl
  7717.         asl                    ;multiply by 16 to use lower nybble
  7718.         asl
  7719.         asl
  7720.        push af
  7721.         oran ++$05               ;add five pixels
  7722.         stay Misc_X_Position,y  ;save as horizontal coordinate for misc object
  7723.         lda SCRATCHPAD+$02                ;get vertical high nybble offset from earlier
  7724.        ld h,a
  7725.        pop af
  7726.        ld a,h
  7727.         adcn ++$20               ;add 32 pixels for the status bar
  7728.         stay Misc_Y_Position,y  ;store as vertical coordinate
  7729. JCoinC: ldan ++$fb
  7730.         stay Misc_Y_Speed,y     ;set vertical speed
  7731.         ldan ++$01
  7732.         stay Misc_Y_HighPos,y   ;set vertical high byte
  7733.         stay Misc_State,y       ;set state for misc object
  7734.         sta Square2SoundQueue  ;load coin grab sound
  7735.         stx ObjectOffset       ;store current control bit as misc object offset
  7736.         jsr GiveOneCoin        ;update coin tally on the screen and coin amount variable
  7737.         inci CoinTallyFor1Ups   ;increment coin tally used to activate 1-up block flag
  7738.         rts
  7739.  
  7740. FindEmptyMiscSlot:
  7741.            ldyn ++$08                ;start at end of misc objects buffer
  7742. FMiscLoop: lday Misc_State,y        ;get misc object state
  7743.          checka
  7744.            beq UseMiscS            ;branch if none found to use current offset
  7745.            dey                     ;decrement offset
  7746.            cpyn ++$05                ;do this for three slots
  7747.            bne FMiscLoop           ;do this until all slots are checked
  7748.            ldyn ++$08                ;if no empty slots found, use last slot
  7749. UseMiscS:  sty JumpCoinMiscOffset  ;store offset of misc object buffer here (residual)
  7750.            rts
  7751.  
  7752. ;-------------------------------------------------------------------------------------
  7753.  
  7754. MiscObjectsCore:
  7755.           ldxn ++$08          ;set at end of misc object buffer
  7756. MiscLoop: stx ObjectOffset  ;store misc object offset here
  7757.           ldax Misc_State,x  ;check misc object state
  7758.          checka
  7759.           beq MiscLoopBack  ;branch to check next slot
  7760.           asl               ;otherwise shift d7 into carry
  7761.           bcc ProcJumpCoin  ;if d7 not set, jumping coin, thus skip to rest of code here
  7762.           jsr ProcHammerObj ;otherwise go to process hammer,
  7763.           jmp MiscLoopBack  ;then check next slot
  7764.  
  7765. ;--------------------------------
  7766. ;$00 - used to set downward force
  7767. ;$01 - used to set upward force (residual)
  7768. ;$02 - used to set maximum speed
  7769.  
  7770. ProcJumpCoin:
  7771.            ldyx Misc_State,x          ;check misc object state
  7772.            dey                       ;decrement to see if it's set to 1
  7773.            beq JCoinRun              ;if so, branch to handle jumping coin
  7774.            incx Misc_State,x          ;otherwise increment state to either start off or as timer
  7775.            ldax Misc_X_Position,x     ;get horizontal coordinate for misc object
  7776.            clc                       ;whether its jumping coin (state 0 only) or floatey number
  7777.            adci ScrollAmount          ;add current scroll speed
  7778.           push af
  7779.            stax Misc_X_Position,x     ;store as new horizontal coordinate
  7780.            ldax Misc_PageLoc,x        ;get page location
  7781.           ld h,a
  7782.           pop af
  7783.           ld a,h
  7784.            adcn ++$00                  ;add carry
  7785.            stax Misc_PageLoc,x        ;store as new page location
  7786.            ldax Misc_State,x
  7787.            cmpn ++$30                  ;check state of object for preset value
  7788.            bne RunJCSubs             ;if not yet reached, branch to subroutines
  7789.            ldan ++$00
  7790.            stax Misc_State,x          ;otherwise nullify object state
  7791.            jmp MiscLoopBack          ;and move onto next slot
  7792. JCoinRun:  txa            
  7793.            clc                       ;add 13 bytes to offset for next subroutine
  7794.            adcn ++$0d
  7795.            tax
  7796.            ldan ++$50                  ;set downward movement amount
  7797.            sta SCRATCHPAD+$00
  7798.            ldan ++$06                  ;set maximum vertical speed
  7799.            sta SCRATCHPAD+$02
  7800.            lsr                       ;divide by 2 and set
  7801.            sta SCRATCHPAD+$01                   ;as upward movement amount (apparently residual)
  7802.            ldan ++$00                  ;set A to impose gravity on jumping coin
  7803.            jsr ImposeGravity         ;do sub to move coin vertically and impose gravity on it
  7804.            ldx ObjectOffset          ;get original misc object offset
  7805.            ldax Misc_Y_Speed,x        ;check vertical speed
  7806.            cmpn ++$05
  7807.            bne RunJCSubs             ;if not moving downward fast enough, keep state as-is
  7808.            incx Misc_State,x          ;otherwise increment state to change to floatey number
  7809. RunJCSubs: jsr RelativeMiscPosition  ;get relative coordinates
  7810.            jsr GetMiscOffscreenBits  ;get offscreen information
  7811.            jsr GetMiscBoundBox       ;get bounding box coordinates (why?)
  7812.            jsr JCoinGfxHandler       ;draw the coin or floatey number
  7813.  
  7814. MiscLoopBack:
  7815.            dex                       ;decrement misc object offset
  7816.            bpl MiscLoop              ;loop back until all misc objects handled
  7817.            rts                       ;then leave
  7818.  
  7819. ;-------------------------------------------------------------------------------------
  7820.  
  7821. CoinTallyOffsets:
  7822.       .db $17, $1d
  7823.  
  7824. ScoreOffsets:
  7825.       .db $0b, $11
  7826.  
  7827. StatusBarNybbles:
  7828.       .db $02, $13
  7829.  
  7830. GiveOneCoin:
  7831.       ldan ++$01               ;set digit modifier to add 1 coin
  7832.       sta DigitModifier+5    ;to the current player's coin tally
  7833.       ldx CurrentPlayer      ;get current player on the screen
  7834.       ldyx CoinTallyOffsets,x ;get offset for player's coin tally
  7835.       jsr DigitsMathRoutine  ;update the coin tally
  7836.       inci CoinTally          ;increment onscreen player's coin amount
  7837.       lda CoinTally
  7838.       cmpn ++100               ;does player have 100 coins yet?
  7839.       bne CoinPoints         ;if not, skip all of this
  7840.       ldan ++$00
  7841.       sta CoinTally          ;otherwise, reinitialize coin amount
  7842.       inci NumberofLives      ;give the player an extra life
  7843.       ldan ++Sfx_ExtraLife
  7844.       sta Square2SoundQueue  ;play 1-up sound
  7845.  
  7846. CoinPoints:
  7847.       ldan ++$02               ;set digit modifier to award
  7848.       sta DigitModifier+4    ;200 points to the player
  7849.  
  7850. AddToScore:
  7851.       ldx CurrentPlayer      ;get current player
  7852.       ldyx ScoreOffsets,x     ;get offset for player's score
  7853.       jsr DigitsMathRoutine  ;update the score internally with value in digit modifier
  7854.  
  7855. GetSBNybbles:
  7856.       ldy CurrentPlayer      ;get current player
  7857.       lday StatusBarNybbles,y ;get nybbles based on player, use to update score and coins
  7858.  
  7859. UpdateNumber:
  7860.         jsr PrintStatusBarNumbers ;print status bar numbers based on nybbles, whatever they be
  7861.         ldy VRAM_Buffer1_Offset  
  7862.         lday VRAM_Buffer1-6,y      ;check highest digit of score
  7863.          checka
  7864.         bne NoZSup                ;if zero, overwrite with space tile for zero suppression
  7865.         ldan ++$24
  7866.         stay VRAM_Buffer1-6,y
  7867. NoZSup: ldx ObjectOffset          ;get enemy object buffer offset
  7868.         rts
  7869.  
  7870. ;-------------------------------------------------------------------------------------
  7871.  
  7872. SetupPowerUp:
  7873.            ;jr $
  7874.            ldan ++PowerUpObject        ;load power-up identifier into
  7875.            sta Enemy_ID+5            ;special use slot of enemy object buffer
  7876.            ldax Block_PageLoc,x       ;store page location of block object
  7877.            sta Enemy_PageLoc+5       ;as page location of power-up object
  7878.            ldax Block_X_Position,x    ;store horizontal coordinate of block object
  7879.            sta Enemy_X_Position+5    ;as horizontal coordinate of power-up object
  7880.            ldan ++$01
  7881.            sta Enemy_Y_HighPos+5     ;set vertical high byte of power-up object
  7882.            ldax Block_Y_Position,x    ;get vertical coordinate of block object
  7883.            secsub
  7884.            sbcn ++$08                  ;subtract 8 pixels
  7885.            sta Enemy_Y_Position+5    ;and use as vertical coordinate of power-up object
  7886. PwrUpJmp:  ldan ++$01                  ;this is a residual jump point in enemy object jump table
  7887.            sta Enemy_State+5         ;set power-up object's state
  7888.            sta Enemy_Flag+5          ;set buffer flag
  7889.            ldan ++$03
  7890.            sta Enemy_BoundBoxCtrl+5  ;set bounding box size control for power-up object
  7891.            lda PowerUpType
  7892.            cmpn ++$02                  ;check currently loaded power-up type
  7893.               cmpcy
  7894.            bcs PutBehind             ;if star or 1-up, branch ahead
  7895.            lda PlayerStatus          ;otherwise check player's current status
  7896.            cmpn ++$02
  7897.               cmpcy
  7898.            bcc StrType               ;if player not fiery (<2), use status as power-up type
  7899.            ;jr $
  7900.            lsr                       ;otherwise shift right to force fire flower type
  7901. StrType:   sta PowerUpType           ;store type here
  7902. PutBehind: ldan ++%00100000
  7903.            sta Enemy_SprAttrib+5     ;set background priority bit
  7904.            ldan ++Sfx_GrowPowerUp
  7905.            sta Square2SoundQueue     ;load power-up reveal sound and leave
  7906.            rts
  7907.  
  7908. ;-------------------------------------------------------------------------------------
  7909.  
  7910. PowerUpObjHandler:
  7911.         ;jr $
  7912.          ldxn ++$05                   ;set object offset for last slot in enemy object buffer
  7913.          stx ObjectOffset
  7914.          lda Enemy_State+5          ;check power-up object's state
  7915.          checka
  7916.          beq ExitPUp                ;if not set, branch to leave
  7917.          asl                        ;shift to check if d7 was set in object state
  7918.          bcc GrowThePowerUp         ;if not set, branch ahead to skip this part
  7919.          lda TimerControl           ;if master timer control set,
  7920.          checka
  7921.          bne RunPUSubs              ;branch ahead to enemy object routines
  7922.          lda PowerUpType            ;check power-up type
  7923.          checka
  7924.          beq ShroomM                ;if normal mushroom, branch ahead to move it
  7925.          cmpn ++$03
  7926.          beq ShroomM                ;if 1-up mushroom, branch ahead to move it
  7927.          cmpn ++$02
  7928.          bne RunPUSubs              ;if not star, branch elsewhere to skip movement
  7929.          jsr MoveJumpingEnemy       ;otherwise impose gravity on star power-up and make it jump
  7930.          jsr EnemyJump              ;note that green paratroopa shares the same code here
  7931.          jmp RunPUSubs              ;then jump to other power-up subroutines
  7932. ShroomM: jsr MoveNormalEnemy        ;do sub to make mushrooms move
  7933.          jsr EnemyToBGCollisionDet  ;deal with collisions
  7934.          jmp RunPUSubs              ;run the other subroutines
  7935.  
  7936. GrowThePowerUp:
  7937.            lda FrameCounter           ;get frame counter
  7938.            andn ++$03                   ;mask out all but 2 LSB
  7939.            bne ChkPUSte               ;if any bits set here, branch
  7940.            deci Enemy_Y_Position+5     ;otherwise decrement vertical coordinate slowly
  7941.            lda Enemy_State+5          ;load power-up object state
  7942.            inci Enemy_State+5          ;increment state for next frame (to make power-up rise)
  7943.            cmpn ++$11                   ;if power-up object state not yet past 16th pixel,
  7944.               cmpcy
  7945.            bcc ChkPUSte               ;branch ahead to last part here
  7946.            ldan ++$10
  7947.            stax Enemy_X_Speed,x        ;otherwise set horizontal speed
  7948.            ldan ++%10000000
  7949.            sta Enemy_State+5          ;and then set d7 in power-up object's state
  7950.            asl                        ;shift once to init A
  7951.            sta Enemy_SprAttrib+5      ;initialize background priority bit set here
  7952.            rol                        ;rotate A to set right moving direction
  7953.            stax Enemy_MovingDir,x      ;set moving direction
  7954. ChkPUSte:  lda Enemy_State+5          ;check power-up object's state
  7955.            cmpn ++$06                   ;for if power-up has risen enough
  7956.               cmpcy
  7957.            bcc ExitPUp                ;if not, don't even bother running these routines
  7958. RunPUSubs: jsr RelativeEnemyPosition  ;get coordinates relative to screen
  7959.            jsr GetEnemyOffscreenBits  ;get offscreen bits
  7960.            jsr GetEnemyBoundBox       ;get bounding box coordinates
  7961.            jsr DrawPowerUp            ;draw the power-up object
  7962.            jsr PlayerEnemyCollision   ;check for collision with player
  7963.            jsr OffscreenBoundsCheck   ;check to see if it went offscreen
  7964. ExitPUp:   rts                        ;and we're done
  7965.  
  7966. ;-------------------------------------------------------------------------------------
  7967. ;These apply to all routines in this section unless otherwise noted:
  7968. ;$00 - used to store metatile from block buffer routine
  7969. ;$02 - used to store vertical high nybble offset from block buffer routine
  7970. ;$05 - used to store metatile stored in A at beginning of PlayerHeadCollision
  7971. ;$06-$07 - used as block buffer address indirect
  7972.  
  7973. BlockYPosAdderData:
  7974.       .db $04, $12
  7975.  
  7976. PlayerHeadCollision:
  7977.            pha                      ;store metatile number to stack
  7978.            ldan ++$11                 ;load unbreakable block object state by default
  7979.            ldx SprDataOffset_Ctrl   ;load offset control bit here
  7980.            ldy PlayerSize           ;check player's size
  7981.          checky
  7982.            bne DBlockSte            ;if small, branch
  7983.            ldan ++$12                 ;otherwise load breakable block object state
  7984. DBlockSte: stax Block_State,x        ;store into block object buffer
  7985.            jsr DestroyBlockMetatile ;store blank metatile in vram buffer to write to name table
  7986.            ldx SprDataOffset_Ctrl   ;load offset control bit
  7987.            lda SCRATCHPAD+$02                  ;get vertical high nybble offset used in block buffer routine
  7988.            stax Block_Orig_YPos,x    ;set as vertical coordinate for block object
  7989.            tay
  7990.            lda SCRATCHPAD+$06                  ;get low byte of block buffer address used in same routine
  7991.            stax Block_BBuf_Low,x     ;save as offset here to be used later
  7992.            ldayindirect (SCRATCHPAD+$06),y              ;get contents of block buffer at old address at $06, $07
  7993.            jsr BlockBumpedChk       ;do a sub to check which block player bumped head on
  7994.            sta SCRATCHPAD+$00                  ;store metatile here
  7995.            ldy PlayerSize           ;check player's size
  7996.          checky
  7997.            bne ChkBrick             ;if small, use metatile itself as contents of A
  7998.            tya                      ;otherwise init A (note: big = 0)
  7999. ChkBrick:  bcc PutMTileB            ;if no match was found in previous sub, skip ahead
  8000.         ;jr $ ;ё■фр яюярфрхь, хёыш Єюыъэєыш уюыютющ ърьхэ№
  8001.            ldyn ++$11                 ;otherwise load unbreakable state into block object buffer
  8002.            styx Block_State,x        ;note this applies to both player sizes
  8003.            ldan ++$c4                 ;load empty block metatile into A for now
  8004.            ldy SCRATCHPAD+$00                  ;get metatile from before
  8005.            cpyn ++$58                 ;is it brick with coins (with line)?
  8006.            beq StartBTmr            ;if so, branch
  8007.            cpyn ++$5d                 ;is it brick with coins (without line)?
  8008.            bne PutMTileB            ;if not, branch ahead to store empty block metatile
  8009. StartBTmr: lda BrickCoinTimerFlag   ;check brick coin timer flag
  8010.          checka
  8011.            bne ContBTmr             ;if set, timer expired or counting down, thus branch
  8012.            ldan ++$0b
  8013.            sta BrickCoinTimer       ;if not set, set brick coin timer
  8014.            inci BrickCoinTimerFlag   ;and set flag linked to it
  8015. ContBTmr:  lda BrickCoinTimer       ;check brick coin timer
  8016.          checka
  8017.            bne PutOldMT             ;if not yet expired, branch to use current metatile
  8018.            ldyn ++$c4                 ;otherwise use empty block metatile
  8019. PutOldMT:  tya                      ;put metatile into A
  8020. PutMTileB: stax Block_Metatile,x     ;store whatever metatile be appropriate here
  8021.            jsr InitBlock_XY_Pos     ;get block object horizontal coordinates saved
  8022.            ldy SCRATCHPAD+$02                  ;get vertical high nybble offset
  8023.            ldan ++$23
  8024.            stayindirect (SCRATCHPAD+$06),y              ;write blank metatile $23 to block buffer
  8025.            ldan ++$10
  8026.            sta BlockBounceTimer     ;set block bounce timer
  8027.            pla                      ;pull original metatile from stack
  8028.            sta SCRATCHPAD+$05                  ;and save here
  8029.            ldyn ++$00                 ;set default offset
  8030.            lda CrouchingFlag        ;is player crouching?
  8031.          checka
  8032.            bne SmallBP              ;if so, branch to increment offset
  8033.            lda PlayerSize           ;is player big?
  8034.          checka
  8035.            beq BigBP                ;if so, branch to use default offset
  8036. SmallBP:   iny                      ;increment for small or big and crouching
  8037. BigBP:     lda Player_Y_Position    ;get player's vertical coordinate
  8038.            clc
  8039.            adcy BlockYPosAdderData,y ;add value determined by size
  8040.            andn ++$f0                 ;mask out low nybble to get 16-pixel correspondence
  8041.            stax Block_Y_Position,x   ;save as vertical coordinate for block object
  8042.            ldyx Block_State,x        ;get block object state
  8043.            cpyn ++$11
  8044.            beq Unbreak              ;if set to value loaded for unbreakable, branch
  8045.            jsr BrickShatter         ;execute code for breakable brick
  8046.            jmp InvOBit              ;skip subroutine to do last part of code here
  8047. Unbreak:   jsr BumpBlock            ;execute code for unbreakable brick or question block
  8048. InvOBit:   lda SprDataOffset_Ctrl   ;invert control bit used by block objects
  8049.            eorn ++$01                 ;and floatey numbers
  8050.            sta SprDataOffset_Ctrl
  8051.            rts                      ;leave!
  8052.  
  8053. ;--------------------------------
  8054.  
  8055. InitBlock_XY_Pos:
  8056.       lda Player_X_Position   ;get player's horizontal coordinate
  8057.       clc
  8058.       adcn ++$08                ;add eight pixels
  8059.      push af
  8060.       andn ++$f0                ;mask out low nybble to give 16-pixel correspondence
  8061.       stax Block_X_Position,x  ;save as horizontal coordinate for block object
  8062.      pop af
  8063.       lda Player_PageLoc
  8064.       adcn ++$00                ;add carry to page location of player
  8065.       stax Block_PageLoc,x     ;save as page location of block object
  8066.       stax Block_PageLoc2,x    ;save elsewhere to be used later
  8067.       lda Player_Y_HighPos
  8068.       stax Block_Y_HighPos,x   ;save vertical high byte of player into
  8069.       rts                     ;vertical high byte of block object and leave
  8070.  
  8071. ;--------------------------------
  8072.  
  8073. BumpBlock:
  8074.            jsr CheckTopOfBlock     ;check to see if there's a coin directly above this block
  8075.            ldan ++Sfx_Bump
  8076.            sta Square1SoundQueue   ;play bump sound
  8077.            ldan ++$00
  8078.            stax Block_X_Speed,x     ;initialize horizontal speed for block object
  8079.            stax Block_Y_MoveForce,x ;init fractional movement force
  8080.            sta Player_Y_Speed      ;init player's vertical speed
  8081.            ldan ++$fe
  8082.            stax Block_Y_Speed,x     ;set vertical speed for block object
  8083.            lda SCRATCHPAD+$05                 ;get original metatile from stack
  8084.            jsr BlockBumpedChk      ;do a sub to check which block player bumped head on
  8085.            bcc ExitBlockChk        ;if no match was found, branch to leave
  8086.            tya                     ;move block number to A
  8087.            cmpn ++$09                ;if block number was within 0-8 range,
  8088.               cmpcy
  8089.            bcc BlockCode           ;branch to use current number
  8090.               cmpcy
  8091.            sbcn ++$05                ;otherwise subtract 5 for second set to get proper number
  8092. BlockCode: jsr JumpEngine          ;run appropriate subroutine depending on block number
  8093.  
  8094.       .dw MushFlowerBlock
  8095.       .dw CoinBlock
  8096.       .dw CoinBlock
  8097.       .dw ExtraLifeMushBlock
  8098.       .dw MushFlowerBlock
  8099.       .dw VineBlock
  8100.       .dw StarBlock
  8101.       .dw CoinBlock
  8102.       .dw ExtraLifeMushBlock
  8103.  
  8104. ;--------------------------------
  8105.  
  8106. MushFlowerBlock:
  8107.       ldan ++$00       ;load mushroom/fire flower into power-up type
  8108.       jr bonusblock_go;.db $2c        ;BIT instruction opcode
  8109.  
  8110. StarBlock:
  8111.       ldan ++$02       ;load star into power-up type
  8112.       jr bonusblock_go;.db $2c        ;BIT instruction opcode
  8113.  
  8114. ExtraLifeMushBlock:
  8115.       ldan ++$03         ;load 1-up mushroom into power-up type
  8116. bonusblock_go
  8117.       sta SCRATCHPAD+$39          ;store correct power-up type
  8118.       jmp SetupPowerUp
  8119.  
  8120. VineBlock:
  8121.       ldxn ++$05                ;load last slot for enemy object buffer
  8122.       ldy SprDataOffset_Ctrl  ;get control bit
  8123.       jsr Setup_Vine          ;set up vine object
  8124.  
  8125. ExitBlockChk:
  8126.       rts                     ;leave
  8127.  
  8128. ;--------------------------------
  8129.  
  8130. BrickQBlockMetatiles:
  8131.       .db $c1, $c0, $5f, $60 ;used by question blocks
  8132.  
  8133.       ;these two sets are functionally identical, but look different
  8134.       .db $55, $56, $57, $58, $59 ;used by ground level types
  8135.       .db $5a, $5b, $5c, $5d, $5e ;used by other level types
  8136.  
  8137. BlockBumpedChk:
  8138.              ldyn ++$0d                    ;start at end of metatile data
  8139. BumpChkLoop: cmpy BrickQBlockMetatiles,y  ;check to see if current metatile matches
  8140.              beq MatchBump               ;metatile found in block buffer, branch if so
  8141.              dey                         ;otherwise move onto next metatile
  8142.              bpl BumpChkLoop             ;do this until all metatiles are checked
  8143.              clc                         ;if none match, return with carry clear
  8144.             if Z80
  8145.              rts
  8146. MatchBump:
  8147.              scf
  8148.              ret
  8149.             else
  8150. MatchBump:   rts                         ;note carry is set if found match
  8151.             endif
  8152.  
  8153. ;--------------------------------
  8154.  
  8155. BrickShatter:
  8156.       jsr CheckTopOfBlock    ;check to see if there's a coin directly above this block
  8157.       ldan ++Sfx_BrickShatter
  8158.       stax Block_RepFlag,x    ;set flag for block object to immediately replace metatile
  8159.       sta NoiseSoundQueue    ;load brick shatter sound
  8160.       jsr SpawnBrickChunks   ;create brick chunk objects
  8161.       ldan ++$fe
  8162.       sta Player_Y_Speed     ;set vertical speed for player
  8163.       ldan ++$05
  8164.       sta DigitModifier+5    ;set digit modifier to give player 50 points
  8165.       jsr AddToScore         ;do sub to update the score
  8166.       ldx SprDataOffset_Ctrl ;load control bit and leave
  8167.       rts
  8168.  
  8169. ;--------------------------------
  8170.  
  8171. CheckTopOfBlock:
  8172.        ldx SprDataOffset_Ctrl  ;load control bit
  8173.        ldy SCRATCHPAD+$02                 ;get vertical high nybble offset used in block buffer
  8174.          checky
  8175.        beq TopEx               ;branch to leave if set to zero, because we're at the top
  8176.        tya                     ;otherwise set to A
  8177.        secsub
  8178.        sbcn ++$10                ;subtract $10 to move up one row in the block buffer
  8179.        sta SCRATCHPAD+$02                 ;store as new vertical high nybble offset
  8180.        tay
  8181.        ldayindirect (SCRATCHPAD+$06),y             ;get contents of block buffer in same column, one row up
  8182.        cmpn ++$c2                ;is it a coin? (not underwater)
  8183.        bne TopEx               ;if not, branch to leave
  8184.        ldan ++$00
  8185.        stayindirect (SCRATCHPAD+$06),y             ;otherwise put blank metatile where coin was
  8186.        jsr RemoveCoin_Axe      ;write blank metatile to vram buffer
  8187.        ldx SprDataOffset_Ctrl  ;get control bit
  8188.        jsr SetupJumpCoin       ;create jumping coin object and update coin variables
  8189. TopEx: rts                     ;leave!
  8190.  
  8191. ;--------------------------------
  8192.  
  8193. SpawnBrickChunks:
  8194.       ldax Block_X_Position,x     ;set horizontal coordinate of block object
  8195.       stax Block_Orig_XPos,x      ;as original horizontal coordinate here
  8196.       ldan ++$f0
  8197.       stax Block_X_Speed,x        ;set horizontal speed for brick chunk objects
  8198.       stax Block_X_Speed+2,x
  8199.       ldan ++$fa
  8200.       stax Block_Y_Speed,x        ;set vertical speed for one
  8201.       ldan ++$fc
  8202.       stax Block_Y_Speed+2,x      ;set lower vertical speed for the other
  8203.       ldan ++$00
  8204.       stax Block_Y_MoveForce,x    ;init fractional movement force for both
  8205.       stax Block_Y_MoveForce+2,x
  8206.       ldax Block_PageLoc,x
  8207.       stax Block_PageLoc+2,x      ;copy page location
  8208.       ldax Block_X_Position,x
  8209.       stax Block_X_Position+2,x   ;copy horizontal coordinate
  8210.       ldax Block_Y_Position,x
  8211.       clc                        ;add 8 pixels to vertical coordinate
  8212.       adcn ++$08                   ;and save as vertical coordinate for one of them
  8213.       stax Block_Y_Position+2,x
  8214.       ldan ++$fa
  8215.       stax Block_Y_Speed,x        ;set vertical speed...again??? (redundant)
  8216.       rts
  8217.  
  8218. ;-------------------------------------------------------------------------------------
  8219.  
  8220. BlockObjectsCore:
  8221.         ldax Block_State,x           ;get state of block object
  8222.          checka
  8223.         beq UpdSte                  ;if not set, branch to leave
  8224.         andn ++$0f                    ;mask out high nybble
  8225.         pha                         ;push to stack
  8226.         tay                         ;put in Y for now
  8227.         txa
  8228.         clc
  8229.         adcn ++$09                    ;add 9 bytes to offset (note two block objects are created
  8230.         tax                         ;when using brick chunks, but only one offset for both) ;эрўшэр  ё юс·хъЄр #9 шфєЄ misc objects (ўЄю ¤Єю???)
  8231.         dey                         ;decrement Y to check for solid block state
  8232.         beq BouncingBlockHandler    ;branch if found, otherwise continue for brick chunks
  8233.         jsr ImposeGravityBlock      ;do sub to impose gravity on one block object object
  8234.         jsr MoveObjectHorizontally  ;do another sub to move horizontally
  8235.         txa
  8236.         clc                         ;move onto next block object
  8237.         adcn ++$02
  8238.         tax
  8239.         jsr ImposeGravityBlock      ;do sub to impose gravity on other block object
  8240.         jsr MoveObjectHorizontally  ;do another sub to move horizontally
  8241.         ldx ObjectOffset            ;get block object offset used for both
  8242.         jsr RelativeBlockPosition   ;get relative coordinates
  8243.         jsr GetBlockOffscreenBits   ;get offscreen information
  8244.         jsr DrawBrickChunks         ;draw the brick chunks
  8245.         pla                         ;get lower nybble of saved state
  8246.         ldyx Block_Y_HighPos,x       ;check vertical high byte of block object
  8247.          checky
  8248.         beq UpdSte                  ;if above the screen, branch to kill it
  8249.         pha                         ;otherwise save state back into stack
  8250.         ldan ++$f0
  8251.         cmpx Block_Y_Position+2,x    ;check to see if bottom block object went
  8252.               cmpcy
  8253.         bcs ChkTop                  ;to the bottom of the screen, and branch if not
  8254.         stax Block_Y_Position+2,x    ;otherwise set offscreen coordinate
  8255. ChkTop: ldax Block_Y_Position,x      ;get top block object's vertical coordinate
  8256.         cmpn ++$f0                    ;see if it went to the bottom of the screen
  8257.         plakeepcy                         ;pull block object state from stack
  8258.               cmpcy
  8259.         bcc UpdSte                  ;if not, branch to save state
  8260.         bcs KillBlock               ;otherwise do unconditional branch to kill it
  8261.  
  8262. BouncingBlockHandler:
  8263.            jsr ImposeGravityBlock     ;do sub to impose gravity on block object
  8264.            ldx ObjectOffset           ;get block object offset
  8265.            jsr RelativeBlockPosition  ;get relative coordinates
  8266.            jsr GetBlockOffscreenBits  ;get offscreen information
  8267.            jsr DrawBlock              ;draw the block
  8268.            ldax Block_Y_Position,x     ;get vertical coordinate
  8269.            andn ++$0f                   ;mask out high nybble
  8270.            cmpn ++$05                   ;check to see if low nybble wrapped around
  8271.               cmpcy
  8272.            plakeepcy                        ;pull state from stack
  8273.            bcs UpdSte                 ;if still above amount, not time to kill block yet, thus branch
  8274.            ldan ++$01
  8275.            stax Block_RepFlag,x        ;otherwise set flag to replace metatile
  8276. KillBlock: ldan ++$00                   ;if branched here, nullify object state
  8277. UpdSte:    stax Block_State,x          ;store contents of A in block object state
  8278.            rts
  8279.  
  8280. ;-------------------------------------------------------------------------------------
  8281. ;$02 - used to store offset to block buffer
  8282. ;$06-$07 - used to store block buffer address
  8283.  
  8284. BlockObjMT_Updater:
  8285.             ldxn ++$01                  ;set offset to start with second block object
  8286. UpdateLoop: stx ObjectOffset          ;set offset here
  8287.             lda VRAM_Buffer1          ;if vram buffer already being used here,
  8288.          checka
  8289.             bne NextBUpd              ;branch to move onto next block object
  8290.             ldax Block_RepFlag,x       ;if flag for block object already clear,
  8291.          checka
  8292.             beq NextBUpd              ;branch to move onto next block object
  8293.             ldax Block_BBuf_Low,x      ;get low byte of block buffer
  8294.             sta SCRATCHPAD+$06                   ;store into block buffer address
  8295.             ldan ++$05
  8296.             sta SCRATCHPAD+$07                   ;set high byte of block buffer address
  8297.             ldax Block_Orig_YPos,x     ;get original vertical coordinate of block object
  8298.             sta SCRATCHPAD+$02                   ;store here and use as offset to block buffer
  8299.             tay
  8300.             ldax Block_Metatile,x      ;get metatile to be written
  8301.             stayindirect (SCRATCHPAD+$06),y               ;write it to the block buffer
  8302.             jsr ReplaceBlockMetatile  ;do sub to replace metatile where block object is
  8303.             ldan ++$00
  8304.             stax Block_RepFlag,x       ;clear block object flag
  8305. NextBUpd:   dex                       ;decrement block object offset
  8306.             bpl UpdateLoop            ;do this until both block objects are dealt with
  8307.             rts                       ;then leave
  8308.  
  8309. ;-------------------------------------------------------------------------------------
  8310. ;$00 - used to store high nybble of horizontal speed as adder
  8311. ;$01 - used to store low nybble of horizontal speed
  8312. ;$02 - used to store adder to page location
  8313.  
  8314. MoveEnemyHorizontally:
  8315.       inx                         ;increment offset for enemy offset
  8316.       jsr MoveObjectHorizontally  ;position object horizontally according to
  8317.       ldx ObjectOffset            ;counters, return with saved value in A,
  8318.       rts                         ;put enemy offset back in X and leave
  8319.  
  8320. MovePlayerHorizontally:
  8321.       lda JumpspringAnimCtrl  ;if jumpspring currently animating,
  8322.         if Z80OPT
  8323.       or a
  8324.       ret nz                ;branch to leave
  8325.         else
  8326.       checka
  8327.       bne ExXMove             ;branch to leave
  8328.         endif
  8329.       tax                     ;otherwise set zero for offset to use player's stuff
  8330.  
  8331. MoveObjectHorizontally:
  8332. ;PageLoc_XPosition_XMoveforce += 16*Xspeed (signed)
  8333. ;out: a=ёьх∙хэшх X-ъююЁфшэрЄ√ юЄэюёшЄхы№эю яЁю°ыющ яючшЎшш (шёяюы№чєхЄё  Єюы№ъю фы  яырЄЇюЁь? эхяюэ Єэю - чрўхь?)
  8334. ;CY эх трцхэ
  8335. ;ьюцэю яюЁЄшЄ№ y
  8336. ;ьюцэю эх яшёрЄ№ т SCRATCHPAD+0,1,2
  8337.         if Z80OPT
  8338.           ld ix,SprObject_X_Speed
  8339.           add ix,bc
  8340.           ld a,(ix)
  8341.           add a,a
  8342.           ld l,a
  8343.           sbc a,a
  8344.           ld h,a ;Ёрё°шЁхэшх чэрър
  8345.           ld e,a ;ёюїЁрэ хь чэръ
  8346.           add hl,hl
  8347.           add hl,hl
  8348.           add hl,hl
  8349.           ld a,l
  8350.           ld d,h
  8351.           ld hl,SprObject_X_MoveForce
  8352.           add hl,bc
  8353.           add a,(hl) ;get whatever number's here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)  ;add low nybble moved to high
  8354.           ld (hl),a ;store result here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  8355.           ld a,(ix+SprObject_X_Position-SprObject_X_Speed)
  8356.           ld l,a
  8357.           adc a,d        ;add carry plus saved value (high nybble moved to low
  8358.           ld d,b;0
  8359.           ld h,a ;plus $f0 if necessary) to object's horizontal position
  8360.           ld a,(ix+SprObject_PageLoc-SprObject_X_Speed)
  8361.           adc a,e                                           ;add carry plus other saved value to the
  8362.           ld (ix+SprObject_PageLoc-SprObject_X_Speed),a     ;object's page location and save
  8363.           ld a,h
  8364.           sub l;(ix+SprObject_X_Position-SprObject_X_Speed) ;(яюыєўрхЄё  ёьх∙хэшх X-ъююЁфшэрЄ√ юЄэюёшЄхы№эю яЁю°ыющ яючшЎшш)
  8365.           ld (ix+SprObject_X_Position-SprObject_X_Speed),h
  8366.           ret
  8367.         else ;~Z80
  8368.           ldax SprObject_X_Speed,x     ;get currently saved value (horizontal
  8369.           asl                         ;speed, secondary counter, whatever)
  8370.           asl                         ;and move low nybble to high
  8371.           asl
  8372.           asl
  8373.           sta SCRATCHPAD+$01                     ;store result here
  8374.           ldax SprObject_X_Speed,x     ;get saved value again
  8375.           lsr                         ;move high nybble to low
  8376.           lsr
  8377.           lsr
  8378.           lsr
  8379.           cmpn ++$08                    ;if < 8, branch, do not change
  8380.               cmpcy
  8381.           bcc SaveXSpd
  8382.           oran ++%11110000              ;otherwise alter high nybble (Ёрё°шЁхэшх чэрър)
  8383. SaveXSpd: sta SCRATCHPAD+$00                     ;save result here
  8384.           ldyn ++$00                    ;load default Y value here
  8385.           cmpn ++$00                    ;if result positive, leave Y alone
  8386.           bpl UseAdder
  8387.           dey                         ;otherwise decrement Y
  8388. UseAdder: sty SCRATCHPAD+$02                     ;save Y here (яюыєўшыё  чэръ ёъюЁюёЄш 0/-1)
  8389.           ldax SprObject_X_MoveForce,x ;get whatever number's here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  8390.           clc
  8391.           adci SCRATCHPAD+$01                     ;add low nybble moved to high
  8392.          push af
  8393.           stax SprObject_X_MoveForce,x ;store result here (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  8394.          pop af
  8395.           ldan ++$00                    ;init A
  8396.           rol                         ;rotate carry into d0
  8397.        pha                         ;push onto stack (ёюїЁрэ хь Їыру яхЁхэюёр яюёых ёыюцхэш  ьырф°хщ ўрёЄш X-ъююЁфшэрЄ√)
  8398.           ror                         ;rotate d0 back onto carry
  8399.           ldaxkeepcy SprObject_X_Position,x
  8400.           adci SCRATCHPAD+$00                     ;add carry plus saved value (high nybble moved to low
  8401.          push af
  8402.           stax SprObject_X_Position,x  ;plus $f0 if necessary) to object's horizontal position
  8403.           ldax SprObject_PageLoc,x
  8404.          ld h,a
  8405.          pop af
  8406.          ld a,h
  8407.           adci SCRATCHPAD+$02                     ;add carry plus other saved value to the
  8408.           stax SprObject_PageLoc,x     ;object's page location and save
  8409.        pla
  8410.           clc                         ;pull old carry from stack (Їыру яхЁхэюёр яюёых ёыюцхэш  ьырф°хщ ўрёЄш X-ъююЁфшэрЄ√) and add
  8411.           adci SCRATCHPAD+$00                     ;to high nybble moved to low (яюыєўрхЄё  ёьх∙хэшх X-ъююЁфшэрЄ√ юЄэюёшЄхы№эю яЁю°ыющ яючшЎшш)
  8412. ExXMove:  rts                         ;and leave
  8413.         endif
  8414.  
  8415. ;-------------------------------------------------------------------------------------
  8416. ;$00 - used for downward force
  8417. ;$01 - used for upward force
  8418. ;$02 - used for maximum vertical speed
  8419.  
  8420. MovePlayerVertically:
  8421.          ldxn ++$00                ;set X for player offset
  8422.          lda TimerControl
  8423.          checka
  8424.          bne NoJSChk             ;if master timer control set, branch ahead
  8425.          lda JumpspringAnimCtrl  ;otherwise check to see if jumpspring is animating
  8426.         if Z80OPT
  8427.          or a
  8428.          ret nz ;branch to leave if so
  8429.         else
  8430.          checka
  8431.          bne ExXMove             ;branch to leave if so
  8432.         endif
  8433. NoJSChk: lda VerticalForce       ;dump vertical force
  8434.          sta SCRATCHPAD+$00
  8435.          ldan ++$04                ;set maximum vertical speed here
  8436.          jmp ImposeGravitySprObj ;then jump to move player vertically
  8437.  
  8438. ;--------------------------------
  8439.  
  8440. MoveD_EnemyVertically:
  8441.       ldyn ++$3d           ;set quick movement amount downwards
  8442.       ldax Enemy_State,x  ;then check enemy state
  8443.       cmpn ++$05           ;if not set to unique state for spiny's egg, go ahead
  8444.       bne ContVMove      ;and use, otherwise set different movement amount, continue on
  8445.  
  8446. MoveFallingPlatform:
  8447.            ldyn ++$20       ;set movement amount
  8448. ContVMove: jmp SetHiMax   ;jump to skip the rest of this
  8449.  
  8450. ;--------------------------------
  8451.  
  8452. MoveRedPTroopaDown:
  8453.       ldyn ++$00            ;set Y to move downwards
  8454.       jmp MoveRedPTroopa  ;skip to movement routine
  8455.  
  8456. MoveRedPTroopaUp:
  8457.       ldyn ++$01            ;set Y to move upwards
  8458.  
  8459. MoveRedPTroopa:
  8460.       inx                 ;increment X for enemy offset
  8461.       ldan ++$03
  8462.       sta SCRATCHPAD+$00             ;set downward movement amount here
  8463.       ldan ++$06
  8464.       sta SCRATCHPAD+$01             ;set upward movement amount here
  8465.       ldan ++$02
  8466.       sta SCRATCHPAD+$02             ;set maximum speed here
  8467.       tya                 ;set movement direction in A, and
  8468.       jmp RedPTroopaGrav  ;jump to move this thing
  8469.  
  8470. ;--------------------------------
  8471.  
  8472. MoveDropPlatform:
  8473.       ldyn ++$7f      ;set movement amount for drop platform
  8474.          checky
  8475.       bne SetMdMax  ;skip ahead of other value set here
  8476.  
  8477. MoveEnemySlowVert:
  8478.           ldyn ++$0f         ;set movement amount for bowser/other objects
  8479. SetMdMax: ldan ++$02         ;set maximum speed in A
  8480.          checka
  8481.           bne SetXMoveAmt  ;unconditional branch
  8482.  
  8483. ;--------------------------------
  8484.  
  8485. MoveJ_EnemyVertically:
  8486.              ldyn ++$1c                ;set movement amount for podoboo/other objects
  8487. SetHiMax:    ldan ++$03                ;set maximum speed in A
  8488. SetXMoveAmt: sty SCRATCHPAD+$00                 ;set movement amount here
  8489.              inx                     ;increment X for enemy offset
  8490.              jsr ImposeGravitySprObj ;do a sub to move enemy object downwards
  8491.              ldx ObjectOffset        ;get enemy object buffer offset and leave
  8492.              rts
  8493.  
  8494. ;--------------------------------
  8495.  
  8496. MaxSpdBlockData:
  8497.       .db $06, $08
  8498.  
  8499. ResidualGravityCode:
  8500.       ldyn ++$00       ;this part appears to be residual,
  8501.       jr ImposeGravityBlock_go;.db $2c        ;no code branches or jumps to it...
  8502.  
  8503. ImposeGravityBlock:
  8504.       ldyn ++$01       ;set offset for maximum speed
  8505. ImposeGravityBlock_go
  8506.       ldan ++$50       ;set movement amount here
  8507.       sta SCRATCHPAD+$00
  8508.       lday MaxSpdBlockData,y    ;get maximum speed
  8509.  
  8510. ImposeGravitySprObj:
  8511.       sta SCRATCHPAD+$02            ;set maximum speed here
  8512.       ldan ++$00           ;set value to move downwards
  8513.       jmp ImposeGravity  ;jump to the code that actually moves it
  8514.  
  8515. ;--------------------------------
  8516.  
  8517. MovePlatformDown:
  8518.       ldan ++$00    ;save value to stack (if branching here, execute next
  8519.       jr MovePlatform_go;.db $2c     ;part as BIT instruction)
  8520.  
  8521. MovePlatformUp:
  8522.            ldan ++$01        ;save value to stack
  8523. MovePlatform_go
  8524.            pha
  8525.            ldyx Enemy_ID,x  ;get enemy object identifier
  8526.            inx             ;increment offset for enemy object
  8527.            ldan ++$05        ;load default value here
  8528.            cpyn ++$29        ;residual comparison, object ++29 never executes
  8529.            bne SetDplSpd   ;this code, thus unconditional branch here
  8530.            ldan ++$09        ;residual code
  8531. SetDplSpd: sta SCRATCHPAD+$00         ;save downward movement amount here
  8532.            ldan ++$0a        ;save upward movement amount here
  8533.            sta SCRATCHPAD+$01
  8534.            ldan ++$03        ;save maximum vertical speed here
  8535.            sta SCRATCHPAD+$02
  8536.            pla             ;get value from stack
  8537.            tay             ;use as Y, then move onto code shared by red koopa
  8538.  
  8539. RedPTroopaGrav:
  8540.       jsr ImposeGravity  ;do a sub to move object gradually
  8541.       ldx ObjectOffset   ;get enemy object offset and leave
  8542.       rts
  8543.  
  8544. ;-------------------------------------------------------------------------------------
  8545. ;$00 - used for downward force
  8546. ;$01 - used for upward force
  8547. ;$07 - used as adder for vertical position
  8548.  
  8549. ImposeGravity:
  8550.          pha                          ;push value to stack
  8551.          ldax SprObject_YMF_Dummy,x
  8552.          clc                          ;add value in movement force to contents of dummy variable
  8553.          adcx SprObject_Y_MoveForce,x
  8554.           push af
  8555.          stax SprObject_YMF_Dummy,x
  8556.          ldyn ++$00                     ;set Y to zero by default
  8557.          ldax SprObject_Y_Speed,x      ;get current vertical speed
  8558.           ld h,a
  8559.           pop af
  8560.           ld a,h
  8561.          checka
  8562.          bpl AlterYP                  ;if currently moving downwards, do not decrement Y
  8563.          dey                          ;otherwise decrement Y
  8564. AlterYP: sty SCRATCHPAD+$07                      ;store Y here
  8565.          adcx SprObject_Y_Position,x   ;add vertical position to vertical speed plus carry
  8566.           push af
  8567.          stax SprObject_Y_Position,x   ;store as new vertical position
  8568.          ldax SprObject_Y_HighPos,x
  8569.           ld h,a
  8570.           pop af
  8571.           ld a,h
  8572.          adci SCRATCHPAD+$07                      ;add carry plus contents of $07 to vertical high byte
  8573.          stax SprObject_Y_HighPos,x    ;store as new vertical high byte
  8574.          ldax SprObject_Y_MoveForce,x
  8575.          clc
  8576.          adci SCRATCHPAD+$00                      ;add downward movement amount to contents of $0433
  8577.           push af
  8578.          stax SprObject_Y_MoveForce,x
  8579.          ldax SprObject_Y_Speed,x      ;add carry to vertical speed and store
  8580.           ld h,a
  8581.           pop af
  8582.           ld a,h
  8583.          adcn ++$00
  8584.          stax SprObject_Y_Speed,x
  8585.          cmpi SCRATCHPAD+$02                      ;compare to maximum speed
  8586.          bmi ChkUpM                   ;if less than preset value, skip this part
  8587.          ldax SprObject_Y_MoveForce,x
  8588.          cmpn ++$80                     ;if less positively than preset maximum, skip this part
  8589.               cmpcy
  8590.          bcc ChkUpM
  8591.          lda SCRATCHPAD+$02
  8592.          stax SprObject_Y_Speed,x      ;keep vertical speed within maximum value
  8593.          ldan ++$00
  8594.          stax SprObject_Y_MoveForce,x  ;clear fractional
  8595. ChkUpM:  pla                          ;get value from stack
  8596.          checka
  8597.          beq ExVMove                  ;if set to zero, branch to leave
  8598.          lda SCRATCHPAD+$02
  8599.          eorn ++%11111111               ;otherwise get two's compliment of maximum speed
  8600.          tay
  8601.          iny
  8602.          sty SCRATCHPAD+$07                      ;store two's compliment here
  8603.          ldax SprObject_Y_MoveForce,x
  8604.          secsub                          ;subtract upward movement amount from contents
  8605.          sbci SCRATCHPAD+$01                      ;of movement force, note that $01 is twice as large as $00,
  8606.           push af
  8607.          stax SprObject_Y_MoveForce,x  ;thus it effectively undoes add we did earlier
  8608.          ldax SprObject_Y_Speed,x
  8609.           ld h,a
  8610.           pop af
  8611.           ld a,h
  8612.          sbcn ++$00                     ;subtract borrow from vertical speed and store
  8613.          stax SprObject_Y_Speed,x
  8614.          cmpi SCRATCHPAD+$07                      ;compare vertical speed to two's compliment
  8615.          bpl ExVMove                  ;if less negatively than preset maximum, skip this part
  8616.          ldax SprObject_Y_MoveForce,x
  8617.          cmpn ++$80                     ;check if fractional part is above certain amount,
  8618.               cmpcy
  8619.          bcs ExVMove                  ;and if so, branch to leave
  8620.          lda SCRATCHPAD+$07
  8621.          stax SprObject_Y_Speed,x      ;keep vertical speed within maximum value
  8622.          ldan ++$ff
  8623.          stax SprObject_Y_MoveForce,x  ;clear fractional
  8624. ExVMove: rts                          ;leave!
  8625.  
  8626. ;-------------------------------------------------------------------------------------
  8627.  
  8628. EnemiesAndLoopsCore:
  8629.             ldax Enemy_Flag,x         ;check data here for MSB set
  8630.             pha                      ;save in stack
  8631.             asl
  8632.             bcs ChkBowserF           ;if MSB set in enemy flag, branch ahead of jumps
  8633.             pla                      ;get from stack
  8634.          checka
  8635.             beq ChkAreaTsk           ;if data zero, branch
  8636.             jmp RunEnemyObjectsCore  ;otherwise, jump to run enemy subroutines
  8637. ChkAreaTsk: lda AreaParserTaskNum    ;check number of tasks to perform
  8638.             andn ++$07
  8639.             cmpn ++$07                 ;if at a specific task, jump and leave
  8640.             beq ExitELCore
  8641.             jmp ProcLoopCommand      ;otherwise, jump to process loop command/load enemies
  8642. ChkBowserF: pla                      ;get data from stack
  8643.             andn ++%00001111           ;mask out high nybble
  8644.             tay
  8645.             lday Enemy_Flag,y         ;use as pointer and load same place with different offset
  8646.          checka
  8647.             bne ExitELCore
  8648.             stax Enemy_Flag,x         ;if second enemy flag not set, also clear first one
  8649. ExitELCore: rts
  8650.  
  8651. ;--------------------------------
  8652.  
  8653. ;loop command data
  8654. LoopCmdWorldNumber:
  8655.       .db $03, $03, $06, $06, $06, $06, $06, $06, $07, $07, $07
  8656.  
  8657. LoopCmdPageNumber:
  8658.       .db $05, $09, $04, $05, $06, $08, $09, $0a, $06, $0b, $10
  8659.  
  8660. LoopCmdYPosition:
  8661.       .db $40, $b0, $b0, $80, $40, $40, $80, $40, $f0, $f0, $f0
  8662.  
  8663. ExecGameLoopback:
  8664.       lda Player_PageLoc        ;send player back four pages
  8665.       secsub
  8666.       sbcn ++$04
  8667.       sta Player_PageLoc
  8668.       lda CurrentPageLoc        ;send current page back four pages
  8669.       secsub
  8670.       sbcn ++$04
  8671.       sta CurrentPageLoc
  8672.       lda ScreenLeft_PageLoc    ;subtract four from page location
  8673.       secsub                       ;of screen's left border
  8674.       sbcn ++$04
  8675.       sta ScreenLeft_PageLoc
  8676.       lda ScreenRight_PageLoc   ;do the same for the page location
  8677.       secsub                       ;of screen's right border
  8678.       sbcn ++$04
  8679.       sta ScreenRight_PageLoc
  8680.       lda AreaObjectPageLoc     ;subtract four from page control
  8681.       secsub                       ;for area objects
  8682.       sbcn ++$04
  8683.       sta AreaObjectPageLoc
  8684.       ldan ++$00                  ;initialize page select for both
  8685.       sta EnemyObjectPageSel    ;area and enemy objects
  8686.       sta AreaObjectPageSel
  8687.       sta EnemyDataOffset       ;initialize enemy object data offset
  8688.       sta EnemyObjectPageLoc    ;and enemy object page control
  8689.       lday AreaDataOfsLoopback,y ;adjust area object offset based on
  8690.       sta AreaDataOffset        ;which loop command we encountered
  8691.       rts
  8692.  
  8693. ProcLoopCommand:
  8694.           lda LoopCommand           ;check if loop command was found
  8695.          checka
  8696.           beq ChkEnemyFrenzy
  8697.           lda CurrentColumnPos      ;check to see if we're still on the first page
  8698.          checka
  8699.           bne ChkEnemyFrenzy        ;if not, do not loop yet
  8700.           ldyn ++$0b                  ;start at the end of each set of loop data
  8701. FindLoop: dey
  8702.           bmi ChkEnemyFrenzy        ;if all data is checked and not match, do not loop
  8703.           lda WorldNumber           ;check to see if one of the world numbers
  8704.           cmpy LoopCmdWorldNumber,y  ;matches our current world number
  8705.           bne FindLoop
  8706.           lda CurrentPageLoc        ;check to see if one of the page numbers
  8707.           cmpy LoopCmdPageNumber,y   ;matches the page we're currently on
  8708.           bne FindLoop
  8709.           lda Player_Y_Position     ;check to see if the player is at the correct position
  8710.           cmpy LoopCmdYPosition,y    ;if not, branch to check for world 7
  8711.           bne WrongChk
  8712.           lda Player_State          ;check to see if the player is
  8713.           cmpn ++$00                  ;on solid ground (i.e. not jumping or falling)
  8714.           bne WrongChk              ;if not, player fails to pass loop, and loopback
  8715.           lda WorldNumber           ;are we in world 7? (check performed on correct
  8716.           cmpn ++World7               ;vertical position and on solid ground)
  8717.           bne InitMLp               ;if not, initialize flags used there, otherwise
  8718.           inci MultiLoopCorrectCntr  ;increment counter for correct progression
  8719. IncMLoop: inci MultiLoopPassCntr     ;increment master multi-part counter
  8720.           lda MultiLoopPassCntr     ;have we done all three parts?
  8721.           cmpn ++$03
  8722.           bne InitLCmd              ;if not, skip this part
  8723.           lda MultiLoopCorrectCntr  ;if so, have we done them all correctly?
  8724.           cmpn ++$03
  8725.           beq InitMLp               ;if so, branch past unnecessary check here
  8726.           bne DoLpBack              ;unconditional branch if previous branch fails
  8727. WrongChk: lda WorldNumber           ;are we in world 7? (check performed on
  8728.           cmpn ++World7               ;incorrect vertical position or not on solid ground)
  8729.           beq IncMLoop
  8730. DoLpBack: jsr ExecGameLoopback      ;if player is not in right place, loop back
  8731.           jsr KillAllEnemies
  8732. InitMLp:  ldan ++$00                  ;initialize counters used for multi-part loop commands
  8733.           sta MultiLoopPassCntr
  8734.           sta MultiLoopCorrectCntr
  8735. InitLCmd: ldan ++$00                  ;initialize loop command flag
  8736.           sta LoopCommand
  8737.  
  8738. ;--------------------------------
  8739.  
  8740. ChkEnemyFrenzy:
  8741.       lda EnemyFrenzyQueue  ;check for enemy object in frenzy queue
  8742.          checka
  8743.       beq ProcessEnemyData  ;if not, skip this part
  8744.       stax Enemy_ID,x        ;store as enemy object identifier here
  8745.       ldan ++$01
  8746.       stax Enemy_Flag,x      ;activate enemy object flag
  8747.       ldan ++$00
  8748.       stax Enemy_State,x     ;initialize state and frenzy queue
  8749.       sta EnemyFrenzyQueue
  8750.       jmp InitEnemyObject   ;and then jump to deal with this enemy
  8751.  
  8752. ;--------------------------------
  8753. ;$06 - used to hold page location of extended right boundary
  8754. ;$07 - used to hold high nybble of position of extended right boundary
  8755.  
  8756. ProcessEnemyData:
  8757.         ldy EnemyDataOffset      ;get offset of enemy object data
  8758.         ldayindirect (EnemyData),y        ;load first byte
  8759.         cmpn ++$ff                 ;check for EOD terminator
  8760.         bne CheckEndofBuffer
  8761.         jmp CheckFrenzyBuffer    ;if found, jump to check frenzy buffer, otherwise
  8762.  
  8763. CheckEndofBuffer:
  8764.         andn ++%00001111           ;check for special row $0e
  8765.         cmpn ++$0e
  8766.         beq CheckRightBounds     ;if found, branch, otherwise
  8767.         cpxn ++$05                 ;check for end of buffer
  8768.               cmpcy
  8769.         bcc CheckRightBounds     ;if not at end of buffer, branch
  8770.         iny
  8771.         ldayindirect (EnemyData),y        ;check for specific value here
  8772.         andn ++%00111111           ;not sure what this was intended for, exactly
  8773.         cmpn ++$2e                 ;this part is quite possibly residual code
  8774.         beq CheckRightBounds     ;but it has the effect of keeping enemies out of
  8775.         rts                      ;the sixth slot
  8776.  
  8777. CheckRightBounds:
  8778.         lda ScreenRight_X_Pos    ;add 48 to pixel coordinate of right boundary
  8779.         clc
  8780.         adcn ++$30
  8781.           push af
  8782.         andn ++%11110000           ;store high nybble
  8783.         sta SCRATCHPAD+$07
  8784.         lda ScreenRight_PageLoc  ;add carry to page location of right boundary
  8785.           ld h,a
  8786.           pop af
  8787.           ld a,h
  8788.         adcn ++$00
  8789.         sta SCRATCHPAD+$06                  ;store page location + carry
  8790.         ldy EnemyDataOffset
  8791.         iny
  8792.         ldayindirect (EnemyData),y        ;if MSB of enemy object is clear, branch to check for row $0f
  8793.         asl
  8794.         bcc CheckPageCtrlRow
  8795.         lda EnemyObjectPageSel   ;if page select already set, do not set again
  8796.          checka
  8797.         bne CheckPageCtrlRow
  8798.         inci EnemyObjectPageSel   ;otherwise, if MSB is set, set page select
  8799.         inci EnemyObjectPageLoc   ;and increment page control
  8800.  
  8801. CheckPageCtrlRow:
  8802.         dey
  8803.         ldayindirect (EnemyData),y        ;reread first byte
  8804.         andn ++$0f
  8805.         cmpn ++$0f                 ;check for special row $0f
  8806.         bne PositionEnemyObj     ;if not found, branch to position enemy object
  8807.         lda EnemyObjectPageSel   ;if page select set,
  8808.          checka
  8809.         bne PositionEnemyObj     ;branch without reading second byte
  8810.         iny
  8811.         ldayindirect (EnemyData),y        ;otherwise, get second byte, mask out 2 MSB
  8812.         andn ++%00111111
  8813.         sta EnemyObjectPageLoc   ;store as page control for enemy object data
  8814.         inci EnemyDataOffset      ;increment enemy object data offset 2 bytes
  8815.         inci EnemyDataOffset
  8816.         inci EnemyObjectPageSel   ;set page select for enemy object data and
  8817.         jmp ProcLoopCommand      ;jump back to process loop commands again
  8818.  
  8819. PositionEnemyObj:
  8820.         lda EnemyObjectPageLoc   ;store page control as page location
  8821.         stax Enemy_PageLoc,x      ;for enemy object
  8822.         ldayindirect (EnemyData),y        ;get first byte of enemy object
  8823.         andn ++%11110000
  8824.         stax Enemy_X_Position,x   ;store column position
  8825.         cmpi ScreenRight_X_Pos    ;check column position against right boundary
  8826.         ldaxkeepcy Enemy_PageLoc,x      ;without subtracting, then subtract borrow
  8827.         sbci ScreenRight_PageLoc  ;from page location
  8828.               cmpcy
  8829.         bcs CheckRightExtBounds  ;if enemy object beyond or at boundary, branch
  8830.         ldayindirect (EnemyData),y
  8831.         andn ++%00001111           ;check for special row $0e
  8832.         cmpn ++$0e                 ;if found, jump elsewhere
  8833.         beq ParseRow0e
  8834.         jmp CheckThreeBytes      ;if not found, unconditional jump
  8835.  
  8836. CheckRightExtBounds:
  8837.         lda SCRATCHPAD+$07                  ;check right boundary + 48 against
  8838.         cmpx Enemy_X_Position,x   ;column position without subtracting,
  8839.         lda SCRATCHPAD+$06                  ;then subtract borrow from page control temp
  8840.         sbcx Enemy_PageLoc,x      ;plus carry
  8841.               cmpcy
  8842.         bcc CheckFrenzyBuffer    ;if enemy object beyond extended boundary, branch
  8843.         ldan ++$01                 ;store value in vertical high byte
  8844.         stax Enemy_Y_HighPos,x
  8845.         ldayindirect (EnemyData),y        ;get first byte again
  8846.         asl                      ;multiply by four to get the vertical
  8847.         asl                      ;coordinate
  8848.         asl
  8849.         asl
  8850.         stax Enemy_Y_Position,x
  8851.         cmpn ++$e0                 ;do one last check for special row $0e
  8852.         beq ParseRow0e           ;(necessary if branched to $c1cb)
  8853.         iny
  8854.         ldayindirect (EnemyData),y        ;get second byte of object
  8855.         andn ++%01000000           ;check to see if hard mode bit is set
  8856.         beq CheckForEnemyGroup   ;if not, branch to check for group enemy objects
  8857.         lda SecondaryHardMode    ;if set, check to see if secondary hard mode flag
  8858.          checka
  8859.         beq Inc2B                ;is on, and if not, branch to skip this object completely
  8860.  
  8861. CheckForEnemyGroup:
  8862.         ldayindirect (EnemyData),y      ;get second byte and mask out 2 MSB
  8863.         andn ++%00111111
  8864.         cmpn ++$37               ;check for value below $37
  8865.               cmpcy
  8866.         bcc BuzzyBeetleMutate
  8867.         cmpn ++$3f               ;if $37 or greater, check for value
  8868.               cmpcy
  8869.         bcc DoGroup            ;below $3f, branch if below $3f
  8870.  
  8871. BuzzyBeetleMutate:
  8872.         cmpn ++Goomba          ;if below $37, check for goomba
  8873.         bne StrID            ;value ($3f or more always fails)
  8874.         ldy PrimaryHardMode  ;check if primary hard mode flag is set
  8875.          checky
  8876.         beq StrID            ;and if so, change goomba to buzzy beetle
  8877.         ldan ++BuzzyBeetle
  8878. StrID:  stax Enemy_ID,x       ;store enemy object number into buffer
  8879.         ldan ++$01
  8880.         stax Enemy_Flag,x     ;set flag for enemy in buffer
  8881.         jsr InitEnemyObject
  8882.         ldax Enemy_Flag,x     ;check to see if flag is set
  8883.          checka
  8884.         bne Inc2B            ;if not, leave, otherwise branch
  8885.         rts
  8886.  
  8887. CheckFrenzyBuffer:
  8888.         lda EnemyFrenzyBuffer    ;if enemy object stored in frenzy buffer
  8889.          checka
  8890.         bne StrFre               ;then branch ahead to store in enemy object buffer
  8891.         lda VineFlagOffset       ;otherwise check vine flag offset
  8892.         cmpn ++$01
  8893.         bne ExEPar               ;if other value LOW HIGH  1, leave
  8894.         ldan ++VineObject          ;otherwise put vine in enemy identifier
  8895. StrFre: stax Enemy_ID,x           ;store contents of frenzy buffer into enemy identifier value
  8896.  
  8897. InitEnemyObject:
  8898.         ldan ++$00                 ;initialize enemy state
  8899.         stax Enemy_State,x
  8900.         jsr CheckpointEnemyID    ;jump ahead to run jump engine and subroutines
  8901. ExEPar: rts                      ;then leave
  8902.  
  8903. DoGroup:
  8904.         jmp HandleGroupEnemies   ;handle enemy group objects
  8905.  
  8906. ParseRow0e:
  8907.         iny                      ;increment Y to load third byte of object
  8908.         iny
  8909.         ldayindirect (EnemyData),y
  8910.         lsr                      ;move 3 MSB to the bottom, effectively
  8911.         lsr                      ;making %xxx00000 into %00000xxx
  8912.         lsr
  8913.         lsr
  8914.         lsr
  8915.         cmpi WorldNumber          ;is it the same world number as we're on?
  8916.         bne NotUse               ;if not, do not use (this allows multiple uses
  8917.         dey                      ;of the same area, like the underground bonus areas)
  8918.         ldayindirect (EnemyData),y        ;otherwise, get second byte and use as offset
  8919.         sta AreaPointer          ;to addresses for level and enemy object data
  8920.         iny
  8921.         ldayindirect (EnemyData),y        ;get third byte again, and this time mask out
  8922.         andn ++%00011111           ;the 3 MSB from before, save as page number to be
  8923.         sta EntrancePage         ;used upon entry to area, if area is entered
  8924. NotUse: jmp Inc3B
  8925.  
  8926. CheckThreeBytes:
  8927.         ldy EnemyDataOffset      ;load current offset for enemy object data
  8928.         ldayindirect (EnemyData),y        ;get first byte
  8929.         andn ++%00001111           ;check for special row $0e
  8930.         cmpn ++$0e
  8931.         bne Inc2B
  8932. Inc3B:  inci EnemyDataOffset      ;if row = $0e, increment three bytes
  8933. Inc2B:  inci EnemyDataOffset      ;otherwise increment two bytes
  8934.         inci EnemyDataOffset
  8935.         ldan ++$00                 ;init page select for enemy objects
  8936.         sta EnemyObjectPageSel
  8937.         ldx ObjectOffset         ;reload current offset in enemy buffers
  8938.         rts                      ;and leave
  8939.  
  8940. CheckpointEnemyID:
  8941.         ldax Enemy_ID,x
  8942.         cmpn ++$15                     ;check enemy object identifier for $15 or greater
  8943.               cmpcy
  8944.         bcs InitEnemyRoutines        ;and branch straight to the jump engine if found
  8945.         tay                          ;save identifier in Y register for now
  8946.         ldax Enemy_Y_Position,x
  8947.          or a
  8948.         adcn ++$08                     ;add eight pixels to what will eventually be the
  8949.         stax Enemy_Y_Position,x       ;enemy object's vertical coordinate ($00-$14 only)
  8950.         ldan ++$01
  8951.         stax EnemyOffscrBitsMasked,x  ;set offscreen masked bit
  8952.         tya                          ;get identifier back and use as offset for jump engine
  8953.  
  8954. InitEnemyRoutines:
  8955.         jsr JumpEngine
  8956.      
  8957. ;jump engine table for newly loaded enemy objects
  8958.  
  8959.       .dw InitNormalEnemy  ;for objects $00-$0f
  8960.       .dw InitNormalEnemy
  8961.       .dw InitNormalEnemy
  8962.       .dw InitRedKoopa
  8963.       .dw NoInitCode
  8964.       .dw InitHammerBro
  8965.       .dw InitGoomba
  8966.       .dw InitBloober
  8967.       .dw InitBulletBill
  8968.       .dw NoInitCode
  8969.       .dw InitCheepCheep
  8970.       .dw InitCheepCheep
  8971.       .dw InitPodoboo
  8972.       .dw InitPiranhaPlant
  8973.       .dw InitJumpGPTroopa
  8974.       .dw InitRedPTroopa
  8975.  
  8976.       .dw InitHorizFlySwimEnemy  ;for objects $10-$1f
  8977.       .dw InitLakitu
  8978.       .dw InitEnemyFrenzy
  8979.       .dw NoInitCode
  8980.       .dw InitEnemyFrenzy
  8981.       .dw InitEnemyFrenzy
  8982.       .dw InitEnemyFrenzy
  8983.       .dw InitEnemyFrenzy
  8984.       .dw EndFrenzy
  8985.       .dw NoInitCode
  8986.       .dw NoInitCode
  8987.       .dw InitShortFirebar
  8988.       .dw InitShortFirebar
  8989.       .dw InitShortFirebar
  8990.       .dw InitShortFirebar
  8991.       .dw InitLongFirebar
  8992.  
  8993.       .dw NoInitCode ;for objects $20-$2f
  8994.       .dw NoInitCode
  8995.       .dw NoInitCode
  8996.       .dw NoInitCode
  8997.       .dw InitBalPlatform
  8998.       .dw InitVertPlatform
  8999.       .dw LargeLiftUp
  9000.       .dw LargeLiftDown
  9001.       .dw InitHoriPlatform
  9002.       .dw InitDropPlatform
  9003.       .dw InitHoriPlatform
  9004.       .dw PlatLiftUp
  9005.       .dw PlatLiftDown
  9006.       .dw InitBowser
  9007.       .dw PwrUpJmp   ;possibly dummy value
  9008.       .dw Setup_Vine
  9009.  
  9010.       .dw NoInitCode ;for objects $30-$36
  9011.       .dw NoInitCode
  9012.       .dw NoInitCode
  9013.       .dw NoInitCode
  9014.       .dw NoInitCode
  9015.       .dw InitRetainerObj
  9016.       .dw EndOfEnemyInitCode
  9017.  
  9018. ;-------------------------------------------------------------------------------------
  9019.  
  9020. NoInitCode:
  9021.       rts               ;this executed when enemy object has no init code
  9022.  
  9023. ;--------------------------------
  9024.  
  9025. InitGoomba:
  9026.       jsr InitNormalEnemy  ;set appropriate horizontal speed
  9027.       jmp SmallBBox        ;set $09 as bounding box control, set other values
  9028.  
  9029. ;--------------------------------
  9030.  
  9031. InitPodoboo:
  9032.       ldan ++$02                  ;set enemy position to below
  9033.       stax Enemy_Y_HighPos,x     ;the bottom of the screen
  9034.       stax Enemy_Y_Position,x
  9035.       lsr
  9036.       stax EnemyIntervalTimer,x  ;set timer for enemy
  9037.       lsr
  9038.       stax Enemy_State,x         ;initialize enemy state, then jump to use
  9039.       jmp SmallBBox             ;$09 as bounding box size and set other things
  9040.  
  9041. ;--------------------------------
  9042.  
  9043. InitRetainerObj:
  9044.       ldan ++$b8                ;set fixed vertical position for
  9045.       stax Enemy_Y_Position,x  ;princess/mushroom retainer object
  9046.       rts
  9047.  
  9048. ;--------------------------------
  9049.  
  9050. NormalXSpdData:
  9051.       .db $f8, $f4
  9052.  
  9053. InitNormalEnemy:
  9054.          ldyn ++$01              ;load offset of 1 by default
  9055.          lda PrimaryHardMode   ;check for primary hard mode flag set
  9056.          checka
  9057.          bne GetESpd
  9058.          dey                   ;if not set, decrement offset
  9059. GetESpd: lday NormalXSpdData,y  ;get appropriate horizontal speed
  9060. SetESpd: stax Enemy_X_Speed,x   ;store as speed for enemy object
  9061.          jmp TallBBox          ;branch to set bounding box control and other data
  9062.  
  9063. ;--------------------------------
  9064.  
  9065. InitRedKoopa:
  9066.       jsr InitNormalEnemy   ;load appropriate horizontal speed
  9067.       ldan ++$01              ;set enemy state for red koopa troopa $03
  9068.       stax Enemy_State,x
  9069.       rts
  9070.  
  9071. ;--------------------------------
  9072.  
  9073. HBroWalkingTimerData:
  9074.       .db $80, $50
  9075.  
  9076. InitHammerBro:
  9077.       ldan ++$00                    ;init horizontal speed and timer used by hammer bro
  9078.       stax HammerThrowingTimer,x   ;apparently to time hammer throwing
  9079.       stax Enemy_X_Speed,x
  9080.       ldy SecondaryHardMode       ;get secondary hard mode flag
  9081.       lday HBroWalkingTimerData,y
  9082.       stax EnemyIntervalTimer,x    ;set value as delay for hammer bro to walk left
  9083.       ldan ++$0b                    ;set specific value for bounding box size control
  9084.       jmp SetBBox
  9085.  
  9086. ;--------------------------------
  9087.  
  9088. InitHorizFlySwimEnemy:
  9089.       ldan ++$00        ;initialize horizontal speed
  9090.       jmp SetESpd
  9091.  
  9092. ;--------------------------------
  9093.  
  9094. InitBloober:
  9095.            ldan ++$00               ;initialize horizontal speed
  9096.            stax BlooperMoveSpeed,x
  9097. SmallBBox: ldan ++$09               ;set specific bounding box size control
  9098.          checka
  9099.            bne SetBBox            ;unconditional branch
  9100.  
  9101. ;--------------------------------
  9102.  
  9103. InitRedPTroopa:
  9104. ;CY = 0 after JumpEngine ???
  9105.         or a ;???
  9106.         push af
  9107.           ldyn ++$30                    ;load central position adder for 48 pixels down
  9108.           ldax Enemy_Y_Position,x      ;set vertical coordinate into location to
  9109.           stax RedPTroopaOrigXPos,x    ;be used as original vertical coordinate
  9110.         ld h,a
  9111.         pop af
  9112.         ld a,h
  9113.          checka
  9114.           bpl GetCent                 ;if vertical coordinate LOW  $80
  9115.           ldyn ++$e0                    ;if =HIGH  $80, load position adder for 32 pixels up
  9116. GetCent:  tya                         ;send central position adder to A
  9117.           adcx Enemy_Y_Position,x      ;add to current vertical coordinate
  9118.           stax RedPTroopaCenterYPos,x  ;store as central vertical coordinate
  9119. TallBBox: ldan ++$03                    ;set specific bounding box size control
  9120. SetBBox:  stax Enemy_BoundBoxCtrl,x    ;set bounding box control here
  9121.           ldan ++$02                    ;set moving direction for left
  9122.           stax Enemy_MovingDir,x
  9123. InitVStf: ldan ++$00                    ;initialize vertical speed
  9124.           stax Enemy_Y_Speed,x         ;and movement force
  9125.           stax Enemy_Y_MoveForce,x
  9126.           rts
  9127.  
  9128. ;--------------------------------
  9129.  
  9130. InitBulletBill:
  9131.       ldan ++$02                  ;set moving direction for left
  9132.       stax Enemy_MovingDir,x
  9133.       ldan ++$09                  ;set bounding box control for $09
  9134.       stax Enemy_BoundBoxCtrl,x
  9135.       rts
  9136.  
  9137. ;--------------------------------
  9138.  
  9139. InitCheepCheep:
  9140.       jsr SmallBBox              ;set vertical bounding box, speed, init others
  9141.       ldax PseudoRandomBitReg,x   ;check one portion of LSFR
  9142.       andn ++%00010000             ;get d4 from it
  9143.       stax CheepCheepMoveMFlag,x  ;save as movement flag of some sort
  9144.       ldax Enemy_Y_Position,x
  9145.       stax CheepCheepOrigYPos,x   ;save original vertical coordinate here
  9146.       rts
  9147.  
  9148. ;--------------------------------
  9149.  
  9150. InitLakitu:
  9151.       lda EnemyFrenzyBuffer      ;check to see if an enemy is already in
  9152.          checka
  9153.       bne KillLakitu             ;the frenzy buffer, and branch to kill lakitu if so
  9154.  
  9155. SetupLakitu:
  9156.       ldan ++$00                   ;erase counter for lakitu's reappearance
  9157.       sta LakituReappearTimer
  9158.       jsr InitHorizFlySwimEnemy  ;set $03 as bounding box, set other attributes
  9159.       jmp TallBBox2              ;set $03 as bounding box again (not necessary) and leave
  9160.  
  9161. KillLakitu:
  9162.       jmp EraseEnemyObject
  9163.  
  9164. ;--------------------------------
  9165. ;$01-$03 - used to hold pseudorandom difference adjusters
  9166.  
  9167. PRDiffAdjustData:
  9168.       .db $26, $2c, $32, $38
  9169.       .db $20, $22, $24, $26
  9170.       .db $13, $14, $15, $16
  9171.  
  9172. LakituAndSpinyHandler:
  9173.           lda FrenzyEnemyTimer    ;if timer here not expired, leave
  9174.          checka
  9175.           bne ExLSHand
  9176.           cpxn ++$05                ;if we are on the special use slot, leave
  9177.               cmpcy
  9178.           bcs ExLSHand
  9179.           ldan ++$80                ;set timer
  9180.           sta FrenzyEnemyTimer
  9181.           ldyn ++$04                ;start with the last enemy slot
  9182. ChkLak:   lday Enemy_ID,y          ;check all enemy slots to see
  9183.           cmpn ++Lakitu             ;if lakitu is on one of them
  9184.           beq CreateSpiny         ;if so, branch out of this loop
  9185.           dey                     ;otherwise check another slot
  9186.           bpl ChkLak              ;loop until all slots are checked
  9187.           inci LakituReappearTimer ;increment reappearance timer
  9188.           lda LakituReappearTimer
  9189.           cmpn ++$07                ;check to see if we're up to a certain value yet
  9190.               cmpcy
  9191.           bcc ExLSHand            ;if not, leave
  9192.           ldxn ++$04                ;start with the last enemy slot again
  9193. ChkNoEn:  ldax Enemy_Flag,x        ;check enemy buffer flag for non-active enemy slot
  9194.          checka
  9195.           beq CreateL             ;branch out of loop if found
  9196.           dex                     ;otherwise check next slot
  9197.           bpl ChkNoEn             ;branch until all slots are checked
  9198.           bmi RetEOfs             ;if no empty slots were found, branch to leave
  9199. CreateL:  ldan ++$00                ;initialize enemy state
  9200.           stax Enemy_State,x
  9201.           ldan ++Lakitu             ;create lakitu enemy object
  9202.           stax Enemy_ID,x
  9203.           jsr SetupLakitu         ;do a sub to set up lakitu
  9204.           ldan ++$20
  9205.           jsr PutAtRightExtent    ;finish setting up lakitu
  9206. RetEOfs:  ldx ObjectOffset        ;get enemy object buffer offset again and leave
  9207. ExLSHand: rts
  9208.  
  9209. ;--------------------------------
  9210.  
  9211. CreateSpiny:
  9212.           lda Player_Y_Position      ;if player above a certain point, branch to leave
  9213.           cmpn ++$2c
  9214.               cmpcy
  9215.           bcc ExLSHand
  9216.           lday Enemy_State,y          ;if lakitu is not in normal state, branch to leave
  9217.          checka
  9218.           bne ExLSHand
  9219.           lday Enemy_PageLoc,y        ;store horizontal coordinates (high and low) of lakitu
  9220.           stax Enemy_PageLoc,x        ;into the coordinates of the spiny we're going to create
  9221.           lday Enemy_X_Position,y
  9222.           stax Enemy_X_Position,x
  9223.           ldan ++$01                   ;put spiny within vertical screen unit
  9224.           stax Enemy_Y_HighPos,x
  9225.           lday Enemy_Y_Position,y     ;put spiny eight pixels above where lakitu is
  9226.           secsub
  9227.           sbcn ++$08
  9228.           stax Enemy_Y_Position,x
  9229.           ldax PseudoRandomBitReg,x   ;get 2 LSB of LSFR and save to Y
  9230.           andn ++%00000011
  9231.           tay
  9232.           ldxn ++$02
  9233. DifLoop:  lday PRDiffAdjustData,y     ;get three values and save them
  9234.           stax SCRATCHPAD+$01,x                  ;to $01-$03
  9235.           iny
  9236.           iny                        ;increment Y four bytes for each value
  9237.           iny
  9238.           iny
  9239.           dex                        ;decrement X for each one
  9240.           bpl DifLoop                ;loop until all three are written
  9241.           ldx ObjectOffset           ;get enemy object buffer offset
  9242.           jsr PlayerLakituDiff       ;move enemy, change direction, get value - difference
  9243.           ldy Player_X_Speed         ;check player's horizontal speed
  9244.           cpyn ++$08
  9245.               cmpcy
  9246.           bcs SetSpSpd               ;if moving faster than a certain amount, branch elsewhere
  9247.           tay                        ;otherwise save value in A to Y for now
  9248.           ldax PseudoRandomBitReg+1,x
  9249.           andn ++%00000011             ;get one of the LSFR parts and save the 2 LSB
  9250.           beq UsePosv                ;branch if neither bits are set
  9251.           tya
  9252.           eorn ++%11111111             ;otherwise get two's compliment of Y
  9253.           tay
  9254.           iny
  9255. UsePosv:  tya                        ;put value from A in Y back to A (they will be lost anyway)
  9256. SetSpSpd: jsr SmallBBox              ;set bounding box control, init attributes, lose contents of A
  9257.           ldyn ++$02
  9258.           stax Enemy_X_Speed,x        ;set horizontal speed to zero because previous contents
  9259.           cmpn ++$00                   ;of A were lost...branch here will never be taken for
  9260.           bmi SpinyRte               ;the same reason
  9261.           dey
  9262. SpinyRte: styx Enemy_MovingDir,x      ;set moving direction to the right
  9263.           ldan ++$fd
  9264.           stax Enemy_Y_Speed,x        ;set vertical speed to move upwards
  9265.           ldan ++$01
  9266.           stax Enemy_Flag,x           ;enable enemy object by setting flag
  9267.           ldan ++$05
  9268.           stax Enemy_State,x          ;put spiny in egg state and leave
  9269. ChpChpEx: rts
  9270.  
  9271. ;--------------------------------
  9272.  
  9273. FirebarSpinSpdData:
  9274.       .db $28, $38, $28, $38, $28
  9275.  
  9276. FirebarSpinDirData:
  9277.       .db $00, $00, $10, $10, $00
  9278.  
  9279. InitLongFirebar:
  9280.       jsr DuplicateEnemyObj       ;create enemy object for long firebar
  9281.  
  9282. InitShortFirebar:
  9283.       ldan ++$00                    ;initialize low byte of spin state
  9284.       stax FirebarSpinState_Low,x
  9285.       ldax Enemy_ID,x              ;subtract $1b from enemy identifier
  9286.       secsub                         ;to get proper offset for firebar data
  9287.       sbcn ++$1b
  9288.       tay
  9289.       lday FirebarSpinSpdData,y    ;get spinning speed of firebar
  9290.       stax FirebarSpinSpeed,x
  9291.       lday FirebarSpinDirData,y    ;get spinning direction of firebar
  9292.       stax FirebarSpinDirection,x
  9293.       ldax Enemy_Y_Position,x
  9294.       clc                         ;add four pixels to vertical coordinate
  9295.       adcn ++$04
  9296.       stax Enemy_Y_Position,x
  9297.       ldax Enemy_X_Position,x
  9298.       clc                         ;add four pixels to horizontal coordinate
  9299.       adcn ++$04
  9300.           push af
  9301.       stax Enemy_X_Position,x
  9302.       ldax Enemy_PageLoc,x
  9303.           ld h,a
  9304.           pop af
  9305.           ld a,h
  9306.       adcn ++$00                    ;add carry to page location
  9307.       stax Enemy_PageLoc,x
  9308.       jmp TallBBox2               ;set bounding box control (not used) and leave
  9309.  
  9310. ;--------------------------------
  9311. ;$00-$01 - used to hold pseudorandom bits
  9312.  
  9313. FlyCCXPositionData:
  9314.       .db $80, $30, $40, $80
  9315.       .db $30, $50, $50, $70
  9316.       .db $20, $40, $80, $a0
  9317.       .db $70, $40, $90, $68
  9318.  
  9319. FlyCCXSpeedData:
  9320.       .db $0e, $05, $06, $0e
  9321.       .db $1c, $20, $10, $0c
  9322.       .db $1e, $22, $18, $14
  9323.  
  9324. FlyCCTimerData:
  9325.       .db $10, $60, $20, $48
  9326.  
  9327. InitFlyingCheepCheep:
  9328.          lda FrenzyEnemyTimer       ;if timer here not expired yet, branch to leave
  9329.          checka
  9330.          bne ChpChpEx
  9331.          jsr SmallBBox              ;jump to set bounding box size $09 and init other values
  9332.          ldax PseudoRandomBitReg+1,x
  9333.          andn ++%00000011             ;set pseudorandom offset here
  9334.          tay
  9335.          lday FlyCCTimerData,y       ;load timer with pseudorandom offset
  9336.          sta FrenzyEnemyTimer
  9337.          ldyn ++$03                   ;load Y with default value
  9338.          lda SecondaryHardMode
  9339.          checka
  9340.          beq MaxCC                  ;if secondary hard mode flag not set, do not increment Y
  9341.          iny                        ;otherwise, increment Y to allow as many as four onscreen
  9342. MaxCC:   sty SCRATCHPAD+$00                    ;store whatever pseudorandom bits are in Y
  9343.          cpxi SCRATCHPAD+$00                    ;compare enemy object buffer offset with Y
  9344.               cmpcy
  9345.          bcs ChpChpEx               ;if X =HIGH  Y, branch to leave
  9346.          ldax PseudoRandomBitReg,x
  9347.          andn ++%00000011             ;get last two bits of LSFR, first part
  9348.          sta SCRATCHPAD+$00                    ;and store in two places
  9349.          sta SCRATCHPAD+$01
  9350.          ldan ++$fb                   ;set vertical speed for cheep-cheep
  9351.          stax Enemy_Y_Speed,x
  9352.          ldan ++$00                   ;load default value
  9353.          ldy Player_X_Speed         ;check player's horizontal speed
  9354.          checky
  9355.          beq GSeed                  ;if player not moving left or right, skip this part
  9356.          ldan ++$04
  9357.          cpyn ++$19                   ;if moving to the right but not very quickly,
  9358.               cmpcy
  9359.          bcc GSeed                  ;do not change A
  9360.          asl                        ;otherwise, multiply A by 2
  9361. GSeed:   pha                        ;save to stack
  9362.          clc
  9363.          adci SCRATCHPAD+$00                    ;add to last two bits of LSFR we saved earlier
  9364.          sta SCRATCHPAD+$00                    ;save it there
  9365.          ldax PseudoRandomBitReg+1,x
  9366.          andn ++%00000011             ;if neither of the last two bits of second LSFR set,
  9367.          beq RSeed                  ;skip this part and save contents of $00
  9368.          ldax PseudoRandomBitReg+2,x
  9369.          andn ++%00001111             ;otherwise overwrite with lower nybble of
  9370.          sta SCRATCHPAD+$00                    ;third LSFR part
  9371. RSeed:   pla                        ;get value from stack we saved earlier
  9372.          clc
  9373.          adci SCRATCHPAD+$01                    ;add to last two bits of LSFR we saved in other place
  9374.          tay                        ;use as pseudorandom offset here
  9375.          lday FlyCCXSpeedData,y      ;get horizontal speed using pseudorandom offset
  9376.          stax Enemy_X_Speed,x
  9377.          ldan ++$01                   ;set to move towards the right
  9378.          stax Enemy_MovingDir,x
  9379.          lda Player_X_Speed         ;if player moving left or right, branch ahead of this part
  9380.          checka
  9381.          bne D2XPos1
  9382.          ldy SCRATCHPAD+$00                    ;get first LSFR or third LSFR lower nybble
  9383.          tya                        ;and check for d1 set
  9384.          andn ++%00000010
  9385.          beq D2XPos1                ;if d1 not set, branch
  9386.          ldax Enemy_X_Speed,x
  9387.          eorn ++$ff                   ;if d1 set, change horizontal speed
  9388.          clc                        ;into two's compliment, thus moving in the opposite
  9389.          adcn ++$01                   ;direction
  9390.          stax Enemy_X_Speed,x
  9391.          incx Enemy_MovingDir,x      ;increment to move towards the left
  9392. D2XPos1: tya                        ;get first LSFR or third LSFR lower nybble again
  9393.          andn ++%00000010
  9394.          beq D2XPos2                ;check for d1 set again, branch again if not set
  9395.          lda Player_X_Position      ;get player's horizontal position
  9396.          clc
  9397.          adcy FlyCCXPositionData,y   ;if d1 set, add value obtained from pseudorandom offset
  9398.           push af
  9399.          stax Enemy_X_Position,x     ;and save as enemy's horizontal position
  9400.           pop af
  9401.          lda Player_PageLoc         ;get player's page location
  9402.          adcn ++$00                   ;add carry and jump past this part
  9403.          jmp FinCCSt
  9404. D2XPos2: lda Player_X_Position      ;get player's horizontal position
  9405.          secsub
  9406.          sbcy FlyCCXPositionData,y   ;if d1 not set, subtract value obtained from pseudorandom
  9407.           push af
  9408.          stax Enemy_X_Position,x     ;offset and save as enemy's horizontal position
  9409.           pop af
  9410.          lda Player_PageLoc         ;get player's page location
  9411.          sbcn ++$00                   ;subtract borrow
  9412. FinCCSt: stax Enemy_PageLoc,x        ;save as enemy's page location
  9413.          ldan ++$01
  9414.          stax Enemy_Flag,x           ;set enemy's buffer flag
  9415.          stax Enemy_Y_HighPos,x      ;set enemy's high vertical byte
  9416.          ldan ++$f8
  9417.          stax Enemy_Y_Position,x     ;put enemy below the screen, and we are done
  9418.          rts
  9419.  
  9420. ;--------------------------------
  9421.  
  9422. InitBowser:
  9423.       jsr DuplicateEnemyObj     ;jump to create another bowser object
  9424.       stx BowserFront_Offset    ;save offset of first here
  9425.       ldan ++$00
  9426.       sta BowserBodyControls    ;initialize bowser's body controls
  9427.       sta BridgeCollapseOffset  ;and bridge collapse offset
  9428.       ldax Enemy_X_Position,x
  9429.       sta BowserOrigXPos        ;store original horizontal position here
  9430.       ldan ++$df
  9431.       sta BowserFireBreathTimer ;store something here
  9432.       stax Enemy_MovingDir,x     ;and in moving direction
  9433.       ldan ++$20
  9434.       sta BowserFeetCounter     ;set bowser's feet timer and in enemy timer
  9435.       stax EnemyFrameTimer,x
  9436.       ldan ++$05
  9437.       sta BowserHitPoints       ;give bowser 5 hit points
  9438.       lsr
  9439.       sta BowserMovementSpeed   ;set default movement speed here
  9440.       rts
  9441.  
  9442. ;--------------------------------
  9443.  
  9444. DuplicateEnemyObj:
  9445.         ldyn ++$ff                ;start at beginning of enemy slots
  9446. FSLoop: iny                     ;increment one slot
  9447.         lday Enemy_Flag,y        ;check enemy buffer flag for empty slot
  9448.          checka
  9449.         bne FSLoop              ;if set, branch and keep checking
  9450.         sty DuplicateObj_Offset ;otherwise set offset here
  9451.         txa                     ;transfer original enemy buffer offset
  9452.         oran ++%10000000          ;store with d7 set as flag in new enemy
  9453.         stay Enemy_Flag,y        ;slot as well as enemy offset
  9454.         ldax Enemy_PageLoc,x
  9455.         stay Enemy_PageLoc,y     ;copy page location and horizontal coordinates
  9456.         ldax Enemy_X_Position,x  ;from original enemy to new enemy
  9457.         stay Enemy_X_Position,y
  9458.         ldan ++$01
  9459.         stax Enemy_Flag,x        ;set flag as normal for original enemy
  9460.         stay Enemy_Y_HighPos,y   ;set high vertical byte for new enemy
  9461.         ldax Enemy_Y_Position,x
  9462.         stay Enemy_Y_Position,y  ;copy vertical coordinate from original to new
  9463. FlmEx:  rts                     ;and then leave
  9464.  
  9465. ;--------------------------------
  9466.  
  9467. FlameYPosData:
  9468.       .db $90, $80, $70, $90
  9469.  
  9470. FlameYMFAdderData:
  9471.       .db $ff, $01
  9472.  
  9473. InitBowserFlame:
  9474.         lda FrenzyEnemyTimer        ;if timer not expired yet, branch to leave
  9475.          checka
  9476.         bne FlmEx
  9477.         stax Enemy_Y_MoveForce,x     ;reset something here
  9478.         lda NoiseSoundQueue
  9479.         oran ++Sfx_BowserFlame        ;load bowser's flame sound into queue
  9480.         sta NoiseSoundQueue
  9481.         ldy BowserFront_Offset      ;get bowser's buffer offset
  9482.         lday Enemy_ID,y              ;check for bowser
  9483.         cmpn ++Bowser
  9484.         beq SpawnFromMouth          ;branch if found
  9485.         jsr SetFlameTimer           ;get timer data based on flame counter
  9486.         clc
  9487.         adcn ++$20                    ;add 32 frames by default
  9488.         ldy SecondaryHardMode
  9489.          checky
  9490.         beq SetFrT                  ;if secondary mode flag not set, use as timer setting
  9491.         secsub
  9492.         sbcn ++$10                    ;otherwise subtract 16 frames for secondary hard mode
  9493. SetFrT: sta FrenzyEnemyTimer        ;set timer accordingly
  9494.         ldax PseudoRandomBitReg,x
  9495.         andn ++%00000011              ;get 2 LSB from first part of LSFR
  9496.         stax BowserFlamePRandomOfs,x ;set here
  9497.         tay                         ;use as offset
  9498.         lday FlameYPosData,y         ;load vertical position based on pseudorandom offset
  9499.  
  9500. PutAtRightExtent:
  9501.       stax Enemy_Y_Position,x    ;set vertical position
  9502.       lda ScreenRight_X_Pos
  9503.       clc
  9504.       adcn ++$20                  ;place enemy 32 pixels beyond right side of screen
  9505.        push af
  9506.       stax Enemy_X_Position,x
  9507.        pop af
  9508.       lda ScreenRight_PageLoc
  9509.       adcn ++$00                  ;add carry
  9510.       stax Enemy_PageLoc,x
  9511.       jmp FinishFlame           ;skip this part to finish setting values
  9512.  
  9513. SpawnFromMouth:
  9514.        lday Enemy_X_Position,y    ;get bowser's horizontal position
  9515.        secsub
  9516.        sbcn ++$0e                  ;subtract 14 pixels
  9517.        stax Enemy_X_Position,x    ;save as flame's horizontal position
  9518.        lday Enemy_PageLoc,y
  9519.        stax Enemy_PageLoc,x       ;copy page location from bowser to flame
  9520.        lday Enemy_Y_Position,y
  9521.        clc                       ;add 8 pixels to bowser's vertical position
  9522.        adcn ++$08
  9523.        stax Enemy_Y_Position,x    ;save as flame's vertical position
  9524.        ldax PseudoRandomBitReg,x
  9525.        andn ++%00000011            ;get 2 LSB from first part of LSFR
  9526.        stax Enemy_YMF_Dummy,x     ;save here
  9527.        tay                       ;use as offset
  9528.        lday FlameYPosData,y       ;get value here using bits as offset
  9529.        ldyn ++$00                  ;load default offset
  9530.        cmpx Enemy_Y_Position,x    ;compare value to flame's current vertical position
  9531.               cmpcy
  9532.        bcc SetMF                 ;if less, do not increment offset
  9533.        iny                       ;otherwise increment now
  9534. SetMF: lday FlameYMFAdderData,y   ;get value here and save
  9535.        stax Enemy_Y_MoveForce,x   ;to vertical movement force
  9536.        ldan ++$00
  9537.        sta EnemyFrenzyBuffer     ;clear enemy frenzy buffer
  9538.  
  9539. FinishFlame:
  9540.       ldan ++$08                 ;set $08 for bounding box control
  9541.       stax Enemy_BoundBoxCtrl,x
  9542.       ldan ++$01                 ;set high byte of vertical and
  9543.       stax Enemy_Y_HighPos,x    ;enemy buffer flag
  9544.       stax Enemy_Flag,x
  9545.       lsr
  9546.       stax Enemy_X_MoveForce,x  ;initialize horizontal movement force (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√), and
  9547.       stax Enemy_State,x        ;enemy state
  9548.       rts
  9549.  
  9550. ;--------------------------------
  9551.  
  9552. FireworksXPosData:
  9553.       .db $00, $30, $60, $60, $00, $20
  9554.  
  9555. FireworksYPosData:
  9556.       .db $60, $40, $70, $40, $60, $30
  9557.  
  9558. InitFireworks:
  9559.           lda FrenzyEnemyTimer         ;if timer not expired yet, branch to leave
  9560.          checka
  9561.           bne ExitFWk
  9562.           ldan ++$20                     ;otherwise reset timer
  9563.           sta FrenzyEnemyTimer
  9564.           deci FireworksCounter         ;decrement for each explosion
  9565.           ldyn ++$06                     ;start at last slot
  9566. StarFChk: dey
  9567.           lday Enemy_ID,y               ;check for presence of star flag object
  9568.           cmpn ++StarFlagObject          ;if there isn't a star flag object,
  9569.           bne StarFChk                 ;routine goes into infinite loop = crash
  9570.           lday Enemy_X_Position,y
  9571.           secsub                          ;get horizontal coordinate of star flag object, then
  9572.           sbcn ++$30                     ;subtract 48 pixels from it and save to
  9573.           pha                          ;the stack
  9574.           ldaykeepcy Enemy_PageLoc,y
  9575.           sbcn ++$00                     ;subtract the carry from the page location
  9576.           sta SCRATCHPAD+$00                      ;of the star flag object
  9577.           lda FireworksCounter         ;get fireworks counter
  9578.           clc
  9579.           adcy Enemy_State,y            ;add state of star flag object (possibly not necessary)
  9580.           tay                          ;use as offset
  9581.           pla                          ;get saved horizontal coordinate of star flag - 48 pixels
  9582.           clc
  9583.           adcy FireworksXPosData,y      ;add number based on offset of fireworks counter
  9584.            push af
  9585.           stax Enemy_X_Position,x       ;store as the fireworks object horizontal coordinate
  9586.            pop af
  9587.           lda SCRATCHPAD+$00
  9588.           adcn ++$00                     ;add carry and store as page location for
  9589.           stax Enemy_PageLoc,x          ;the fireworks object
  9590.           lday FireworksYPosData,y      ;get vertical position using same offset
  9591.           stax Enemy_Y_Position,x       ;and store as vertical coordinate for fireworks object
  9592.           ldan ++$01
  9593.           stax Enemy_Y_HighPos,x        ;store in vertical high byte
  9594.           stax Enemy_Flag,x             ;and activate enemy buffer flag
  9595.           lsr
  9596.           stax ExplosionGfxCounter,x    ;initialize explosion counter
  9597.           ldan ++$08
  9598.           stax ExplosionTimerCounter,x  ;set explosion timing counter
  9599. ExitFWk:  rts
  9600.  
  9601. ;--------------------------------
  9602.  
  9603. Bitmasks:
  9604.       .db %00000001, %00000010, %00000100, %00001000, %00010000, %00100000, %01000000, %10000000
  9605.  
  9606. Enemy17YPosData:
  9607.       .db $40, $30, $90, $50, $20, $60, $a0, $70
  9608.  
  9609. SwimCC_IDData:
  9610.       .db $0a, $0b
  9611.  
  9612. BulletBillCheepCheep:
  9613.          lda FrenzyEnemyTimer      ;if timer not expired yet, branch to leave
  9614.          checka
  9615.          bne ExF17
  9616.          lda AreaType              ;are we in a water-type level?
  9617.          checka
  9618.          bne DoBulletBills         ;if not, branch elsewhere
  9619.          cpxn ++$03                  ;are we past third enemy slot?
  9620.               cmpcy
  9621.          bcs ExF17                 ;if so, branch to leave
  9622.          ldyn ++$00                  ;load default offset
  9623.          ldax PseudoRandomBitReg,x
  9624.          cmpn ++$aa                  ;check first part of LSFR against preset value
  9625.               cmpcy
  9626.          bcc ChkW2                 ;if less than preset, do not increment offset
  9627.          iny                       ;otherwise increment
  9628. ChkW2:   lda WorldNumber           ;check world number
  9629.          cmpn ++World2
  9630.          beq Get17ID               ;if we're on world 2, do not increment offset
  9631.          iny                       ;otherwise increment
  9632. Get17ID: tya
  9633.          andn ++%00000001            ;mask out all but last bit of offset
  9634.          tay
  9635.          lday SwimCC_IDData,y       ;load identifier for cheep-cheeps
  9636. Set17ID: stax Enemy_ID,x            ;store whatever's in A as enemy identifier
  9637.          lda BitMFilter
  9638.          cmpn ++$ff                  ;if not all bits set, skip init part and compare bits
  9639.          bne GetRBit
  9640.          ldan ++$00                  ;initialize vertical position filter
  9641.          sta BitMFilter
  9642. GetRBit: ldax PseudoRandomBitReg,x  ;get first part of LSFR
  9643.          andn ++%00000111            ;mask out all but 3 LSB
  9644. ChkRBit: tay                       ;use as offset
  9645.          lday Bitmasks,y            ;load bitmask
  9646.          biti BitMFilter            ;perform AND on filter without changing it
  9647.          beq AddFBit
  9648.          iny                       ;increment offset
  9649.          tya
  9650.          andn ++%00000111            ;mask out all but 3 LSB thus keeping it 0-7
  9651.          jmp ChkRBit               ;do another check
  9652. AddFBit: orai BitMFilter            ;add bit to already set bits in filter
  9653.          sta BitMFilter            ;and store
  9654.          lday Enemy17YPosData,y     ;load vertical position using offset
  9655.          jsr PutAtRightExtent      ;set vertical position and other values
  9656.          stax Enemy_YMF_Dummy,x     ;initialize dummy variable
  9657.          ldan ++$20                  ;set timer
  9658.          sta FrenzyEnemyTimer
  9659.          jmp CheckpointEnemyID     ;process our new enemy object
  9660.  
  9661. DoBulletBills:
  9662.           ldyn ++$ff                   ;start at beginning of enemy slots
  9663. BB_SLoop: iny                        ;move onto the next slot
  9664.           cpyn ++$05                   ;branch to play sound if we've done all slots
  9665.               cmpcy
  9666.           bcs FireBulletBill
  9667.           lday Enemy_Flag,y           ;if enemy buffer flag not set,
  9668.          checka
  9669.           beq BB_SLoop               ;loop back and check another slot
  9670.           lday Enemy_ID,y
  9671.           cmpn ++BulletBill_FrenzyVar  ;check enemy identifier for
  9672.           bne BB_SLoop               ;bullet bill object (frenzy variant)
  9673. ExF17:    rts                        ;if found, leave
  9674.  
  9675. FireBulletBill:
  9676.       lda Square2SoundQueue
  9677.       oran ++Sfx_Blast            ;play fireworks/gunfire sound
  9678.       sta Square2SoundQueue
  9679.       ldan ++BulletBill_FrenzyVar ;load identifier for bullet bill object
  9680.          checka
  9681.       bne Set17ID               ;unconditional branch
  9682.  
  9683. ;--------------------------------
  9684. ;$00 - used to store Y position of group enemies
  9685. ;$01 - used to store enemy ID
  9686. ;$02 - used to store page location of right side of screen
  9687. ;$03 - used to store X position of right side of screen
  9688.  
  9689. HandleGroupEnemies:
  9690.         ldyn ++$00                  ;load value for green koopa troopa
  9691.         secsub
  9692.         sbcn ++$37                  ;subtract $37 from second byte read
  9693.         pha                       ;save result in stack for now
  9694.         cmpn ++$04                  ;was byte in $3b-$3e range?
  9695.               cmpcy
  9696.         bcs SnglID                ;if so, branch
  9697.         pha                       ;save another copy to stack
  9698.         ldyn ++Goomba               ;load value for goomba enemy
  9699.         lda PrimaryHardMode       ;if primary hard mode flag not set,
  9700.          checka
  9701.         beq PullID                ;branch, otherwise change to value
  9702.         ldyn ++BuzzyBeetle          ;for buzzy beetle
  9703. PullID: pla                       ;get second copy from stack
  9704. SnglID: sty SCRATCHPAD+$01                   ;save enemy id here
  9705.         ldyn ++$b0                  ;load default y coordinate
  9706.         andn ++$02                  ;check to see if d1 was set
  9707.         beq SetYGp                ;if so, move y coordinate up,
  9708.         ldyn ++$70                  ;otherwise branch and use default
  9709. SetYGp: sty SCRATCHPAD+$00                   ;save y coordinate here
  9710.         lda ScreenRight_PageLoc   ;get page number of right edge of screen
  9711.         sta SCRATCHPAD+$02                   ;save here
  9712.         lda ScreenRight_X_Pos     ;get pixel coordinate of right edge
  9713.         sta SCRATCHPAD+$03                   ;save here
  9714.         ldyn ++$02                  ;load two enemies by default
  9715.         pla                       ;get first copy from stack
  9716.         lsr                       ;check to see if d0 was set
  9717.         bcc CntGrp                ;if not, use default value
  9718.         iny                       ;otherwise increment to three enemies
  9719. CntGrp: sty NumberofGroupEnemies  ;save number of enemies here
  9720. GrLoop: ldxn ++$ff                  ;start at beginning of enemy buffers
  9721. GSltLp: inx                       ;increment and branch if past
  9722.         cpxn ++$05                  ;end of buffers
  9723.               cmpcy
  9724.         bcs NextED
  9725.         ldax Enemy_Flag,x          ;check to see if enemy is already
  9726.          checka
  9727.         bne GSltLp                ;stored in buffer, and branch if so
  9728.         lda SCRATCHPAD+$01
  9729.         stax Enemy_ID,x            ;store enemy object identifier
  9730.         lda SCRATCHPAD+$02
  9731.         stax Enemy_PageLoc,x       ;store page location for enemy object
  9732.         lda SCRATCHPAD+$03
  9733.         stax Enemy_X_Position,x    ;store x coordinate for enemy object
  9734.         clc
  9735.         adcn ++$18                  ;add 24 pixels for next enemy
  9736.         sta SCRATCHPAD+$03
  9737.         lda SCRATCHPAD+$02                   ;add carry to page location for
  9738.         adcn ++$00                  ;next enemy
  9739.         sta SCRATCHPAD+$02
  9740.         lda SCRATCHPAD+$00                   ;store y coordinate for enemy object
  9741.         stax Enemy_Y_Position,x
  9742.         ldan ++$01                  ;activate flag for buffer, and
  9743.         stax Enemy_Y_HighPos,x     ;put enemy within the screen vertically
  9744.         stax Enemy_Flag,x
  9745.         jsr CheckpointEnemyID     ;process each enemy object separately
  9746.         deci NumberofGroupEnemies  ;do this until we run out of enemy objects
  9747.         bne GrLoop
  9748. NextED: jmp Inc2B                 ;jump to increment data offset and leave
  9749.  
  9750. ;--------------------------------
  9751.  
  9752. InitPiranhaPlant:
  9753.       ldan ++$01                     ;set initial speed
  9754.       stax PiranhaPlant_Y_Speed,x
  9755.       lsr
  9756.       stax Enemy_State,x            ;initialize enemy state and what would normally
  9757.       stax PiranhaPlant_MoveFlag,x  ;be used as vertical speed, but not in this case
  9758.       ldax Enemy_Y_Position,x
  9759.       stax PiranhaPlantDownYPos,x   ;save original vertical coordinate here
  9760.       secsub
  9761.       sbcn ++$18
  9762.       stax PiranhaPlantUpYPos,x     ;save original vertical coordinate - 24 pixels here
  9763.       ldan ++$09
  9764.       jmp SetBBox2                 ;set specific value for bounding box control ;эрўшэр  ё юс·хъЄр #9 шфєЄ misc objects (ўЄю ¤Єю???)
  9765.  
  9766. ;--------------------------------
  9767.  
  9768. InitEnemyFrenzy:
  9769.       ldax Enemy_ID,x        ;load enemy identifier
  9770.       sta EnemyFrenzyBuffer ;save in enemy frenzy buffer
  9771.       secsub
  9772.       sbcn ++$12              ;subtract 12 and use as offset for jump engine
  9773.       jsr JumpEngine
  9774.  
  9775. ;frenzy object jump table
  9776.       .dw LakituAndSpinyHandler
  9777.       .dw NoFrenzyCode
  9778.       .dw InitFlyingCheepCheep
  9779.       .dw InitBowserFlame
  9780.       .dw InitFireworks
  9781.       .dw BulletBillCheepCheep
  9782.  
  9783. ;--------------------------------
  9784.  
  9785. NoFrenzyCode:
  9786.       rts
  9787.  
  9788. ;--------------------------------
  9789.  
  9790. EndFrenzy:
  9791.            ldyn ++$05               ;start at last slot
  9792. LakituChk: lday Enemy_ID,y         ;check enemy identifiers
  9793.            cmpn ++Lakitu            ;for lakitu
  9794.            bne NextFSlot
  9795.            ldan ++$01               ;if found, set state
  9796.            stay Enemy_State,y
  9797. NextFSlot: dey                    ;move onto the next slot
  9798.            bpl LakituChk          ;do this until all slots are checked
  9799.            ldan ++$00
  9800.            sta EnemyFrenzyBuffer  ;empty enemy frenzy buffer
  9801.            stax Enemy_Flag,x       ;disable enemy buffer flag for this object
  9802.            rts
  9803.  
  9804. ;--------------------------------
  9805.  
  9806. InitJumpGPTroopa:
  9807.            ldan ++$02                  ;set for movement to the left
  9808.            stax Enemy_MovingDir,x
  9809.            ldan ++$f8                  ;set horizontal speed
  9810.            stax Enemy_X_Speed,x
  9811. TallBBox2: ldan ++$03                  ;set specific value for bounding box control
  9812. SetBBox2:  stax Enemy_BoundBoxCtrl,x  ;set bounding box control then leave
  9813.            rts
  9814.  
  9815. ;--------------------------------
  9816.  
  9817. InitBalPlatform:
  9818.         decx Enemy_Y_Position,x    ;raise vertical position by two pixels
  9819.         decx Enemy_Y_Position,x
  9820.         ldy SecondaryHardMode     ;if secondary hard mode flag not set,
  9821.          checky
  9822.         bne AlignP                ;branch ahead
  9823.         ldyn ++$02                  ;otherwise set value here
  9824.         jsr PosPlatform           ;do a sub to add or subtract pixels
  9825. AlignP: ldyn ++$ff                  ;set default value here for now
  9826.         lda BalPlatformAlignment  ;get current balance platform alignment
  9827.         stax Enemy_State,x         ;set platform alignment to object state here
  9828.          checka
  9829.         bpl SetBPA                ;if old alignment $ff, put $ff as alignment for negative
  9830.         txa                       ;if old contents already $ff, put
  9831.         tay                       ;object offset as alignment to make next positive
  9832. SetBPA: sty BalPlatformAlignment  ;store whatever value's in Y here
  9833.         ldan ++$00
  9834.         stax Enemy_MovingDir,x     ;init moving direction
  9835.         tay                       ;init Y
  9836.         jsr PosPlatform           ;do a sub to add 8 pixels, then run shared code here
  9837.  
  9838. ;--------------------------------
  9839.  
  9840. InitDropPlatform:
  9841.       ldan ++$ff
  9842.       stax PlatformCollisionFlag,x  ;set some value here
  9843.       jmp CommonPlatCode           ;then jump ahead to execute more code
  9844.  
  9845. ;--------------------------------
  9846.  
  9847. InitHoriPlatform:
  9848.       ldan ++$00
  9849.       stax XMoveSecondaryCounter,x  ;init one of the moving counters
  9850.       jmp CommonPlatCode           ;jump ahead to execute more code
  9851.  
  9852. ;--------------------------------
  9853.  
  9854. InitVertPlatform:
  9855.        ldyn ++$40                    ;set default value here
  9856.        ldax Enemy_Y_Position,x      ;check vertical position
  9857.          checka
  9858.        bpl SetYO                   ;if above a certain point, skip this part
  9859.        eorn ++$ff
  9860.        clc                         ;otherwise get two's compliment
  9861.        adcn ++$01
  9862.        ldyn ++$c0                    ;get alternate value to add to vertical position
  9863. SetYO: stax YPlatformTopYPos,x      ;save as top vertical position
  9864.        tya
  9865.        clc                         ;load value from earlier, add number of pixels
  9866.        adcx Enemy_Y_Position,x      ;to vertical position
  9867.        stax YPlatformCenterYPos,x   ;save result as central vertical position
  9868.  
  9869. ;--------------------------------
  9870.  
  9871. CommonPlatCode:
  9872.         jsr InitVStf              ;do a sub to init certain other values
  9873. SPBBox: ldan ++$05                  ;set default bounding box size control
  9874.         ldy AreaType
  9875.         cpyn ++$03                  ;check for castle-type level
  9876.         beq CasPBB                ;use default value if found
  9877.         ldy SecondaryHardMode     ;otherwise check for secondary hard mode flag
  9878.          checky
  9879.         bne CasPBB                ;if set, use default value
  9880.         ldan ++$06                  ;use alternate value if not castle or secondary not set
  9881. CasPBB: stax Enemy_BoundBoxCtrl,x  ;set bounding box size control here and leave
  9882.         rts
  9883.  
  9884. ;--------------------------------
  9885.  
  9886. LargeLiftUp:
  9887.       jsr PlatLiftUp       ;execute code for platforms going up
  9888.       jmp LargeLiftBBox    ;overwrite bounding box for large platforms
  9889.  
  9890. LargeLiftDown:
  9891.       jsr PlatLiftDown     ;execute code for platforms going down
  9892.  
  9893. LargeLiftBBox:
  9894.       jmp SPBBox           ;jump to overwrite bounding box size control
  9895.  
  9896. ;--------------------------------
  9897.  
  9898. PlatLiftUp:
  9899.       ldan ++$10                 ;set movement amount here
  9900.       stax Enemy_Y_MoveForce,x
  9901.       ldan ++$ff                 ;set moving speed for platforms going up
  9902.       stax Enemy_Y_Speed,x
  9903.       jmp CommonSmallLift      ;skip ahead to part we should be executing
  9904.  
  9905. ;--------------------------------
  9906.  
  9907. PlatLiftDown:
  9908.       ldan ++$f0                 ;set movement amount here
  9909.       stax Enemy_Y_MoveForce,x
  9910.       ldan ++$00                 ;set moving speed for platforms going down
  9911.       stax Enemy_Y_Speed,x
  9912.  
  9913. ;--------------------------------
  9914.  
  9915. CommonSmallLift:
  9916.       ldyn ++$01
  9917.       jsr PosPlatform           ;do a sub to add 12 pixels due to preset value  
  9918.       ldan ++$04
  9919.       stax Enemy_BoundBoxCtrl,x  ;set bounding box control for small platforms
  9920.       rts
  9921.  
  9922. ;--------------------------------
  9923.  
  9924. PlatPosDataLow:
  9925.       .db $08,$0c,$f8
  9926.  
  9927. PlatPosDataHigh:
  9928.       .db $00,$00,$ff
  9929.  
  9930. PosPlatform:
  9931.       ldax Enemy_X_Position,x  ;get horizontal coordinate
  9932.       clc
  9933.       adcy PlatPosDataLow,y    ;add or subtract pixels depending on offset
  9934.           push af
  9935.       stax Enemy_X_Position,x  ;store as new horizontal coordinate
  9936.       ldax Enemy_PageLoc,x
  9937.           ld h,a
  9938.           pop af
  9939.           ld a,h
  9940.       adcy PlatPosDataHigh,y   ;add or subtract page location depending on offset
  9941.       stax Enemy_PageLoc,x     ;store as new page location
  9942.       rts                     ;and go back
  9943.  
  9944. ;--------------------------------
  9945.  
  9946. EndOfEnemyInitCode:
  9947.       rts
  9948.  
  9949. ;-------------------------------------------------------------------------------------
  9950.  
  9951. RunEnemyObjectsCore:
  9952.         ;jr $
  9953.        ldx ObjectOffset  ;get offset for enemy object buffer
  9954.        ldan ++$00          ;load value 0 for jump engine by default
  9955.        ldyx Enemy_ID,x
  9956.        cpyn ++$15          ;if enemy object LOW  $15, use default value
  9957.               cmpcy
  9958.        bcc JmpEO
  9959.        tya               ;otherwise subtract $14 from the value and use
  9960.               cmpcy
  9961.        sbcn ++$14          ;as value for jump engine
  9962. JmpEO: jsr JumpEngine
  9963.      
  9964.       .dw RunNormalEnemies  ;for objects $00-$14
  9965.  
  9966.       .dw RunBowserFlame    ;for objects $15-$1f
  9967.       .dw RunFireworks
  9968.       .dw NoRunCode
  9969.       .dw NoRunCode
  9970.       .dw NoRunCode
  9971.       .dw NoRunCode
  9972.       .dw RunFirebarObj
  9973.       .dw RunFirebarObj
  9974.       .dw RunFirebarObj
  9975.       .dw RunFirebarObj
  9976.       .dw RunFirebarObj
  9977.  
  9978.       .dw RunFirebarObj     ;for objects $20-$2f
  9979.       .dw RunFirebarObj
  9980.       .dw RunFirebarObj
  9981.       .dw NoRunCode
  9982.       .dw RunLargePlatform
  9983.       .dw RunLargePlatform
  9984.       .dw RunLargePlatform
  9985.       .dw RunLargePlatform
  9986.       .dw RunLargePlatform
  9987.       .dw RunLargePlatform
  9988.       .dw RunLargePlatform
  9989.       .dw RunSmallPlatform
  9990.       .dw RunSmallPlatform
  9991.       .dw RunBowser
  9992.       .dw PowerUpObjHandler
  9993.       .dw VineObjectHandler
  9994.  
  9995.       .dw NoRunCode         ;for objects $30-$35
  9996.       .dw RunStarFlagObj
  9997.       .dw JumpspringHandler
  9998.       .dw NoRunCode
  9999.       .dw WarpZoneObject
  10000.       .dw RunRetainerObj
  10001.  
  10002. ;--------------------------------
  10003.  
  10004. NoRunCode:
  10005.       rts
  10006.  
  10007. ;--------------------------------
  10008.  
  10009. RunRetainerObj:
  10010.       jsr GetEnemyOffscreenBits
  10011.       jsr RelativeEnemyPosition
  10012.       jmp EnemyGfxHandler
  10013.  
  10014. ;--------------------------------
  10015.  
  10016. RunNormalEnemies:
  10017. ;TODO ёє∙хёЄтхээю єёъюЁшЄ№ ¤Єю
  10018.           ldan ++$00                  ;init sprite attributes
  10019.           stax Enemy_SprAttrib,x
  10020.           ;jr $
  10021.           jsr GetEnemyOffscreenBits ;1589t (497 opt)
  10022.           jsr RelativeEnemyPosition ;316t (274 opt)
  10023.          if Z80
  10024. logicframe=$+1
  10025.             ld l,0
  10026.             dec l
  10027.             call z,EnemyGfxHandler ;Єюы№ъю т яюёыхфэхь ърфЁх ыюушъш (эхяюёЁхфёЄтхээю яхЁхф юЄюсЁрцхэшхь)
  10028.          else
  10029.           jsr EnemyGfxHandler ;4939t (тэєЄЁш 3 т√чютр яю 768t) (3280 opt) <----- TODO эх т√ч√трЄ№, хёыш ¤Єю эх яюёыхфэшщ ърфЁ ыюушъш?
  10030.          endif
  10031.           jsr GetEnemyBoundBox ;631t (452 opt)
  10032.           jsr EnemyToBGCollisionDet ;3500t (тэєЄЁш ChkUnderEnemy (cc46) = 1193t, BlockBufferChk_Enemy (cf18) = 1159t) (2058 opt) <-----
  10033.           jsr EnemiesCollision ;45/230t (ьюцхЄ с√Є№ ъєфр сюы№°х) (209 opt)
  10034.           jsr PlayerEnemyCollision ;230t (58 opt)
  10035.           ldy TimerControl          ;if master timer control set, skip to last routine
  10036.          checky
  10037.           bne SkipMove
  10038.           jsr EnemyMovementSubs ;1408t (833 opt)
  10039. SkipMove: jmp OffscreenBoundsCheck
  10040.  
  10041. EnemyMovementSubs:
  10042.       ldax Enemy_ID,x
  10043.       jsr JumpEngine
  10044.  
  10045.       .dw MoveNormalEnemy      ;only objects $00-$14 use this table
  10046.       .dw MoveNormalEnemy
  10047.       .dw MoveNormalEnemy
  10048.       .dw MoveNormalEnemy
  10049.       .dw MoveNormalEnemy
  10050.       .dw ProcHammerBro
  10051.       .dw MoveNormalEnemy
  10052.       .dw MoveBloober
  10053.       .dw MoveBulletBill
  10054.       .dw NoMoveCode
  10055.       .dw MoveSwimmingCheepCheep
  10056.       .dw MoveSwimmingCheepCheep
  10057.       .dw MovePodoboo
  10058.       .dw MovePiranhaPlant
  10059.       .dw MoveJumpingEnemy
  10060.       .dw ProcMoveRedPTroopa
  10061.       .dw MoveFlyGreenPTroopa
  10062.       .dw MoveLakitu
  10063.       .dw MoveNormalEnemy
  10064.       .dw NoMoveCode   ;dummy
  10065.       .dw MoveFlyingCheepCheep
  10066.  
  10067. ;--------------------------------
  10068.  
  10069. NoMoveCode:
  10070.       rts
  10071.  
  10072. ;--------------------------------
  10073.  
  10074. RunBowserFlame:
  10075.       jsr ProcBowserFlame
  10076.       jsr GetEnemyOffscreenBits
  10077.       jsr RelativeEnemyPosition
  10078.       jsr GetEnemyBoundBox
  10079.       jsr PlayerEnemyCollision
  10080.       jmp OffscreenBoundsCheck
  10081.  
  10082. ;--------------------------------
  10083.  
  10084. RunFirebarObj:
  10085.       jsr ProcFirebar
  10086.       jmp OffscreenBoundsCheck
  10087.  
  10088. ;--------------------------------
  10089.  
  10090. RunSmallPlatform:
  10091.       jsr GetEnemyOffscreenBits
  10092.       jsr RelativeEnemyPosition
  10093.       jsr SmallPlatformBoundBox
  10094.       jsr SmallPlatformCollision
  10095.       jsr RelativeEnemyPosition
  10096.       jsr DrawSmallPlatform
  10097.       jsr MoveSmallPlatform
  10098.       jmp OffscreenBoundsCheck
  10099.  
  10100. ;--------------------------------
  10101.  
  10102. RunLargePlatform:
  10103.         jsr GetEnemyOffscreenBits
  10104.         jsr RelativeEnemyPosition
  10105.         jsr LargePlatformBoundBox
  10106.         jsr LargePlatformCollision
  10107.         lda TimerControl             ;if master timer control set,
  10108.          checka
  10109.         bne SkipPT                   ;skip subroutine tree
  10110.         jsr LargePlatformSubroutines
  10111. SkipPT: jsr RelativeEnemyPosition
  10112.         jsr DrawLargePlatform
  10113.         jmp OffscreenBoundsCheck
  10114.  
  10115. ;--------------------------------
  10116.  
  10117. LargePlatformSubroutines:
  10118.       ldax Enemy_ID,x  ;subtract $24 to get proper offset for jump table
  10119.       secsub
  10120.       sbcn ++$24
  10121.       jsr JumpEngine
  10122.  
  10123.       .dw BalancePlatform   ;table used by objects $24-$2a
  10124.       .dw YMovingPlatform
  10125.       .dw MoveLargeLiftPlat
  10126.       .dw MoveLargeLiftPlat
  10127.       .dw XMovingPlatform
  10128.       .dw DropPlatform
  10129.       .dw RightPlatform
  10130.  
  10131. ;-------------------------------------------------------------------------------------
  10132.  
  10133. EraseEnemyObject:
  10134. ;TODO ix
  10135.       ldan ++$00                 ;clear all enemy object variables
  10136.       stax Enemy_Flag,x
  10137.       stax Enemy_ID,x
  10138.       stax Enemy_State,x
  10139.       stax FloateyNum_Control,x
  10140.       stax EnemyIntervalTimer,x
  10141.       stax ShellChainCounter,x
  10142.       stax Enemy_SprAttrib,x
  10143.       stax EnemyFrameTimer,x
  10144.       rts
  10145.  
  10146. ;-------------------------------------------------------------------------------------
  10147.  
  10148. MovePodoboo:
  10149.       ldax EnemyIntervalTimer,x   ;check enemy timer
  10150.          checka
  10151.       bne PdbM                   ;branch to move enemy if not expired
  10152.       jsr InitPodoboo            ;otherwise set up podoboo again
  10153.       ldax PseudoRandomBitReg+1,x ;get part of LSFR
  10154.       oran ++%10000000             ;set d7
  10155.       stax Enemy_Y_MoveForce,x    ;store as movement force
  10156.       andn ++%00001111             ;mask out high nybble
  10157.       oran ++$06                   ;set for at least six intervals
  10158.       stax EnemyIntervalTimer,x   ;store as new enemy timer
  10159.       ldan ++$f9
  10160.       stax Enemy_Y_Speed,x        ;set vertical speed to move podoboo upwards
  10161. PdbM: jmp MoveJ_EnemyVertically  ;branch to impose gravity on podoboo
  10162.  
  10163. ;--------------------------------
  10164. ;$00 - used in HammerBroJumpCode as bitmask
  10165.  
  10166. HammerThrowTmrData:
  10167.       .db $30, $1c
  10168.  
  10169. XSpeedAdderData:
  10170.       .db $00, $e8, $00, $18
  10171.  
  10172. RevivedXSpeed:
  10173.       .db $08, $f8, $0c, $f4
  10174.  
  10175. ProcHammerBro:
  10176.        ldax Enemy_State,x          ;check hammer bro's enemy state for d5 set
  10177.        andn ++%00100000
  10178.        beq ChkJH                  ;if not set, go ahead with code
  10179.        jmp MoveDefeatedEnemy      ;otherwise jump to something else
  10180. ChkJH: ldax HammerBroJumpTimer,x   ;check jump timer
  10181.          checka
  10182.        beq HammerBroJumpCode      ;if expired, branch to jump
  10183.        decx HammerBroJumpTimer,x   ;otherwise decrement jump timer
  10184.        lda Enemy_OffscreenBits
  10185.        andn ++%00001100             ;check offscreen bits
  10186.        bne MoveHammerBroXDir      ;if hammer bro a little offscreen, skip to movement code
  10187.        ldax HammerThrowingTimer,x  ;check hammer throwing timer
  10188.          checka
  10189.        bne DecHT                  ;if not expired, skip ahead, do not throw hammer
  10190.        ldy SecondaryHardMode      ;otherwise get secondary hard mode flag
  10191.        lday HammerThrowTmrData,y   ;get timer data using flag as offset
  10192.        stax HammerThrowingTimer,x  ;set as new timer
  10193.        jsr SpawnHammerObj         ;do a sub here to spawn hammer object
  10194.        bcc DecHT                  ;if carry clear, hammer not spawned, skip to decrement timer
  10195.        ldax Enemy_State,x
  10196.        oran ++%00001000             ;set d3 in enemy state for hammer throw
  10197.        stax Enemy_State,x
  10198.        jmp MoveHammerBroXDir      ;jump to move hammer bro
  10199. DecHT: decx HammerThrowingTimer,x  ;decrement timer
  10200.        jmp MoveHammerBroXDir      ;jump to move hammer bro
  10201.  
  10202. HammerBroJumpLData:
  10203.       .db $20, $37
  10204.  
  10205. HammerBroJumpCode:
  10206.        ldax Enemy_State,x           ;get hammer bro's enemy state
  10207.        andn ++%00000111              ;mask out all but 3 LSB
  10208.        cmpn ++$01                    ;check for d0 set (for jumping)
  10209.        beq MoveHammerBroXDir       ;if set, branch ahead to moving code
  10210.        ldan ++$00                    ;load default value here
  10211.        sta SCRATCHPAD+$00                     ;save into temp variable for now
  10212.        ldyn ++$fa                    ;set default vertical speed
  10213.        ldax Enemy_Y_Position,x      ;check hammer bro's vertical coordinate
  10214.          checka
  10215.        bmi SetHJ                   ;if on the bottom half of the screen, use current speed
  10216.        ldyn ++$fd                    ;otherwise set alternate vertical speed
  10217.        cmpn ++$70                    ;check to see if hammer bro is above the middle of screen
  10218.               cmpcy
  10219.        inci SCRATCHPAD+$00                     ;increment preset value to $01
  10220.        bcc SetHJ                   ;if above the middle of the screen, use current speed and $01
  10221.        deci SCRATCHPAD+$00                     ;otherwise return value to $00
  10222.        ldax PseudoRandomBitReg+1,x  ;get part of LSFR, mask out all but LSB
  10223.        andn ++$01
  10224.        bne SetHJ                   ;if d0 of LSFR set, branch and use current speed and $00
  10225.        ldyn ++$fa                    ;otherwise reset to default vertical speed
  10226. SetHJ: styx Enemy_Y_Speed,x         ;set vertical speed for jumping
  10227.        ldax Enemy_State,x           ;set d0 in enemy state for jumping
  10228.        oran ++$01
  10229.        stax Enemy_State,x
  10230.        lda SCRATCHPAD+$00                     ;load preset value here to use as bitmask
  10231.        andx PseudoRandomBitReg+2,x  ;and do bit-wise comparison with part of LSFR
  10232.        tay                         ;then use as offset
  10233.        lda SecondaryHardMode       ;check secondary hard mode flag
  10234.          checka
  10235.        bne HJump
  10236.        tay                         ;if secondary hard mode flag clear, set offset to 0
  10237. HJump: lday HammerBroJumpLData,y    ;get jump length timer data using offset from before
  10238.        stax EnemyFrameTimer,x       ;save in enemy timer
  10239.        ldax PseudoRandomBitReg+1,x
  10240.        oran ++%11000000              ;get contents of part of LSFR, set d7 and d6, then
  10241.        stax HammerBroJumpTimer,x    ;store in jump timer
  10242.  
  10243. MoveHammerBroXDir:
  10244.          ldyn ++$fc                  ;move hammer bro a little to the left
  10245.          lda FrameCounter
  10246.          andn ++%01000000            ;change hammer bro's direction every 64 frames
  10247.          bne Shimmy
  10248.          ldyn ++$04                  ;if d6 set in counter, move him a little to the right
  10249. Shimmy:  styx Enemy_X_Speed,x       ;store horizontal speed
  10250.          ldyn ++$01                  ;set to face right by default
  10251.          jsr PlayerEnemyDiff       ;get horizontal difference between player and hammer bro
  10252.          bmi SetShim               ;if enemy to the left of player, skip this part
  10253.          iny                       ;set to face left
  10254.          ldax EnemyIntervalTimer,x  ;check walking timer
  10255.          checka
  10256.          bne SetShim               ;if not yet expired, skip to set moving direction
  10257.          ldan ++$f8
  10258.          stax Enemy_X_Speed,x       ;otherwise, make the hammer bro walk left towards player
  10259. SetShim: styx Enemy_MovingDir,x     ;set moving direction
  10260.  
  10261. MoveNormalEnemy:
  10262.        ldyn ++$00                   ;init Y to leave horizontal movement as-is
  10263.        ldax Enemy_State,x
  10264.        andn ++%01000000             ;check enemy state for d6 set, if set skip
  10265.        bne FallE                  ;to move enemy vertically, then horizontally if necessary
  10266.        ldax Enemy_State,x
  10267.        asl                        ;check enemy state for d7 set
  10268.        bcs SteadM                 ;if set, branch to move enemy horizontally
  10269.        ldax Enemy_State,x
  10270.        andn ++%00100000             ;check enemy state for d5 set
  10271.        bne MoveDefeatedEnemy      ;if set, branch to move defeated enemy object
  10272.        ldax Enemy_State,x
  10273.        andn ++%00000111             ;check d2-d0 of enemy state for any set bits
  10274.        beq SteadM                 ;if enemy in normal state, branch to move enemy horizontally
  10275.        cmpn ++$05
  10276.        beq FallE                  ;if enemy in state used by spiny's egg, go ahead here
  10277.        cmpn ++$03
  10278.               cmpcy
  10279.        bcs ReviveStunned          ;if enemy in states $03 or $04, skip ahead to yet another part
  10280. FallE: jsr MoveD_EnemyVertically  ;do a sub here to move enemy downwards
  10281.        ldyn ++$00
  10282.        ldax Enemy_State,x          ;check for enemy state $02
  10283.        cmpn ++$02
  10284.        beq MEHor                  ;if found, branch to move enemy horizontally
  10285.        andn ++%01000000             ;check for d6 set
  10286.        beq SteadM                 ;if not set, branch to something else
  10287.        ldax Enemy_ID,x
  10288.        cmpn ++PowerUpObject         ;check for power-up object
  10289.        beq SteadM
  10290.        bne SlowM                  ;if any other object where d6 set, jump to set Y
  10291. MEHor: jmp MoveEnemyHorizontally  ;jump here to move enemy horizontally for LOW HIGH  $2e and d6 set
  10292.  
  10293. SlowM:  ldyn ++$01                  ;if branched here, increment Y to slow horizontal movement
  10294. SteadM: ldax Enemy_X_Speed,x       ;get current horizontal speed
  10295.       pha                       ;save to stack
  10296.          checka
  10297.         bpl AddHS                 ;if not moving or moving right, skip, leave Y alone
  10298.         iny
  10299.         iny                       ;otherwise increment Y to next data
  10300. AddHS:  clc
  10301.         adcy XSpeedAdderData,y     ;add value here to slow enemy down if necessary
  10302.         stax Enemy_X_Speed,x       ;save as horizontal speed temporarily
  10303.         jsr MoveEnemyHorizontally ;then do a sub to move horizontally
  10304.       pla
  10305.         stax Enemy_X_Speed,x       ;get old horizontal speed from stack and return to
  10306.         rts                       ;original memory location, then leave
  10307.  
  10308. ReviveStunned:
  10309.          ldax EnemyIntervalTimer,x  ;if enemy timer not expired yet,
  10310.          checka
  10311.          bne ChkKillGoomba         ;skip ahead to something else
  10312.          stax Enemy_State,x         ;otherwise initialize enemy state to normal
  10313.          lda FrameCounter
  10314.          andn ++$01                  ;get d0 of frame counter
  10315.          tay                       ;use as Y and increment for movement direction
  10316.          iny
  10317.          styx Enemy_MovingDir,x     ;store as pseudorandom movement direction
  10318.          dey                       ;decrement for use as pointer
  10319.          lda PrimaryHardMode       ;check primary hard mode flag
  10320.          checka
  10321.          beq SetRSpd               ;if not set, use pointer as-is
  10322.          iny
  10323.          iny                       ;otherwise increment 2 bytes to next data
  10324. SetRSpd: lday RevivedXSpeed,y       ;load and store new horizontal speed
  10325.          stax Enemy_X_Speed,x       ;and leave
  10326.          rts
  10327.  
  10328. MoveDefeatedEnemy:
  10329.       jsr MoveD_EnemyVertically      ;execute sub to move defeated enemy downwards
  10330.       jmp MoveEnemyHorizontally      ;now move defeated enemy horizontally
  10331.  
  10332. ChkKillGoomba:
  10333.         cmpn ++$0e              ;check to see if enemy timer has reached
  10334.         bne NKGmba            ;a certain point, and branch to leave if not
  10335.         ldax Enemy_ID,x
  10336.         cmpn ++Goomba           ;check for goomba object
  10337.         bne NKGmba            ;branch if not found
  10338.         jsr EraseEnemyObject  ;otherwise, kill this goomba object
  10339. NKGmba: rts                   ;leave!
  10340.  
  10341. ;--------------------------------
  10342.  
  10343. MoveJumpingEnemy:
  10344.       jsr MoveJ_EnemyVertically  ;do a sub to impose gravity on green paratroopa
  10345.       jmp MoveEnemyHorizontally  ;jump to move enemy horizontally
  10346.  
  10347. ;--------------------------------
  10348.  
  10349. ProcMoveRedPTroopa:
  10350.           ldax Enemy_Y_Speed,x
  10351.           orax Enemy_Y_MoveForce,x     ;check for any vertical force or speed
  10352.           bne MoveRedPTUpOrDown       ;branch if any found
  10353.           stax Enemy_YMF_Dummy,x       ;initialize something here
  10354.           ldax Enemy_Y_Position,x      ;check current vs. original vertical coordinate
  10355.           cmpx RedPTroopaOrigXPos,x
  10356.               cmpcy
  10357.           bcs MoveRedPTUpOrDown       ;if current =HIGH  original, skip ahead to more code
  10358.           lda FrameCounter            ;get frame counter
  10359.           andn ++%00000111              ;mask out all but 3 LSB
  10360.           bne NoIncPT                 ;if any bits set, branch to leave
  10361.           incx Enemy_Y_Position,x      ;otherwise increment red paratroopa's vertical position
  10362. NoIncPT:  rts                         ;leave
  10363.  
  10364. MoveRedPTUpOrDown:
  10365.           ldax Enemy_Y_Position,x      ;check current vs. central vertical coordinate
  10366.           cmpx RedPTroopaCenterYPos,x
  10367.               cmpcy
  10368.           bcc MovPTDwn                ;if current LOW  central, jump to move downwards
  10369.           jmp MoveRedPTroopaUp        ;otherwise jump to move upwards
  10370. MovPTDwn: jmp MoveRedPTroopaDown      ;move downwards
  10371.  
  10372. ;--------------------------------
  10373. ;$00 - used to store adder for movement, also used as adder for platform
  10374. ;$01 - used to store maximum value for secondary counter
  10375.  
  10376. MoveFlyGreenPTroopa:
  10377.         jsr XMoveCntr_GreenPTroopa ;do sub to increment primary and secondary counters
  10378.         jsr MoveWithXMCntrs        ;do sub to move green paratroopa accordingly, and horizontally
  10379.         ldyn ++$01                   ;set Y to move green paratroopa down
  10380.         lda FrameCounter
  10381.         andn ++%00000011             ;check frame counter 2 LSB for any bits set
  10382.         bne NoMGPT                 ;branch to leave if set to move up/down every fourth frame
  10383.         lda FrameCounter
  10384.         andn ++%01000000             ;check frame counter for d6 set
  10385.         bne YSway                  ;branch to move green paratroopa down if set
  10386.         ldyn ++$ff                   ;otherwise set Y to move green paratroopa up
  10387. YSway:  sty SCRATCHPAD+$00                    ;store adder here
  10388.         ldax Enemy_Y_Position,x
  10389.         clc                        ;add or subtract from vertical position
  10390.         adci SCRATCHPAD+$00                    ;to give green paratroopa a wavy flight
  10391.         stax Enemy_Y_Position,x
  10392. NoMGPT: rts                        ;leave!
  10393.  
  10394. XMoveCntr_GreenPTroopa:
  10395.          ldan ++$13                    ;load preset maximum value for secondary counter
  10396.  
  10397. XMoveCntr_Platform:
  10398.          sta SCRATCHPAD+$01                     ;store value here
  10399.          lda FrameCounter
  10400.          andn ++%00000011              ;branch to leave if not on
  10401.          bne NoIncXM                 ;every fourth frame
  10402.          ldyx XMoveSecondaryCounter,x ;get secondary counter
  10403.          ldax XMovePrimaryCounter,x   ;get primary counter
  10404.          lsr
  10405.          bcs DecSeXM                 ;if d0 of primary counter set, branch elsewhere
  10406.          cpyi SCRATCHPAD+$01                     ;compare secondary counter to preset maximum value
  10407.          beq IncPXM                  ;if equal, branch ahead of this part
  10408.          incx XMoveSecondaryCounter,x ;increment secondary counter and leave
  10409. NoIncXM: rts
  10410. IncPXM:  incx XMovePrimaryCounter,x   ;increment primary counter and leave
  10411.          rts
  10412. DecSeXM: tya                         ;put secondary counter in A
  10413.          checka
  10414.          beq IncPXM                  ;if secondary counter at zero, branch back
  10415.          decx XMoveSecondaryCounter,x ;otherwise decrement secondary counter and leave
  10416.          rts
  10417.  
  10418. MoveWithXMCntrs:
  10419.          ldax XMoveSecondaryCounter,x  ;save secondary counter to stack
  10420.          pha
  10421.          ldyn ++$01                     ;set value here by default
  10422.          ldax XMovePrimaryCounter,x
  10423.          andn ++%00000010               ;if d1 of primary counter is
  10424.          bne XMRight                  ;set, branch ahead of this part here
  10425.          ldax XMoveSecondaryCounter,x
  10426.          eorn ++$ff                     ;otherwise change secondary
  10427.          clc                          ;counter to two's compliment
  10428.          adcn ++$01
  10429.          stax XMoveSecondaryCounter,x
  10430.          ldyn ++$02                     ;load alternate value here
  10431. XMRight: styx Enemy_MovingDir,x        ;store as moving direction
  10432.          jsr MoveEnemyHorizontally
  10433.          sta SCRATCHPAD+$00                      ;save value obtained from sub here (ёюїЁрэ хь ёьх∙хэшх X-ъююЁфшэрЄ√ яю ёЁртэхэш■ ё яЁю°ы√ь яюыюцхэшхь)
  10434.          pla                          ;get secondary counter from stack
  10435.          stax XMoveSecondaryCounter,x  ;and return to original place
  10436.          rts
  10437.  
  10438. ;--------------------------------
  10439.  
  10440. BlooberBitmasks:
  10441.       .db %00111111, %00000011
  10442.  
  10443. MoveBloober:
  10444.         ldax Enemy_State,x
  10445.         andn ++%00100000             ;check enemy state for d5 set
  10446.         bne MoveDefeatedBloober    ;branch if set to move defeated bloober
  10447.         ldy SecondaryHardMode      ;use secondary hard mode flag as offset
  10448.         ldax PseudoRandomBitReg+1,x ;get LSFR
  10449.         andy BlooberBitmasks,y      ;mask out bits in LSFR using bitmask loaded with offset
  10450.         bne BlooberSwim            ;if any bits set, skip ahead to make swim
  10451.         txa
  10452.         lsr                        ;check to see if on second or fourth slot (1 or 3)
  10453.         bcc FBLeft                 ;if not, branch to figure out moving direction
  10454.         ldy Player_MovingDir       ;otherwise, load player's moving direction and
  10455.         bcs SBMDir                 ;do an unconditional branch to set
  10456. FBLeft: ldyn ++$02                   ;set left moving direction by default
  10457.         jsr PlayerEnemyDiff        ;get horizontal difference between player and bloober
  10458.         bpl SBMDir                 ;if enemy to the right of player, keep left
  10459.         dey                        ;otherwise decrement to set right moving direction
  10460. SBMDir: styx Enemy_MovingDir,x      ;set moving direction of bloober, then continue on here
  10461.  
  10462. BlooberSwim:
  10463.        jsr ProcSwimmingB        ;execute sub to make bloober swim characteristically
  10464.        ldax Enemy_Y_Position,x   ;get vertical coordinate
  10465.        secsub
  10466.        sbcx Enemy_Y_MoveForce,x  ;subtract movement force
  10467.        cmpn ++$20                 ;check to see if position is above edge of status bar
  10468.               cmpcy
  10469.        bcc SwimX                ;if so, don't do it
  10470.        stax Enemy_Y_Position,x   ;otherwise, set new vertical position, make bloober swim
  10471. SwimX: ldyx Enemy_MovingDir,x    ;check moving direction
  10472.        dey
  10473.        bne LeftSwim             ;if moving to the left, branch to second part
  10474.        ldax Enemy_X_Position,x
  10475.        clc                      ;add movement speed to horizontal coordinate
  10476.        adcx BlooperMoveSpeed,x
  10477.           push af
  10478.        stax Enemy_X_Position,x   ;store result as new horizontal coordinate
  10479.        ldax Enemy_PageLoc,x
  10480.           ld h,a
  10481.           pop af
  10482.           ld a,h
  10483.        adcn ++$00                 ;add carry to page location
  10484.        stax Enemy_PageLoc,x      ;store as new page location and leave
  10485.        rts
  10486.  
  10487. LeftSwim:
  10488.       ldax Enemy_X_Position,x
  10489.       secsub                      ;subtract movement speed from horizontal coordinate
  10490.       sbcx BlooperMoveSpeed,x
  10491.           push af
  10492.       stax Enemy_X_Position,x   ;store result as new horizontal coordinate
  10493.       ldax Enemy_PageLoc,x
  10494.           ld h,a
  10495.           pop af
  10496.           ld a,h
  10497.       sbcn ++$00                 ;subtract borrow from page location
  10498.       stax Enemy_PageLoc,x      ;store as new page location and leave
  10499.       rts
  10500.  
  10501. MoveDefeatedBloober:
  10502.       jmp MoveEnemySlowVert    ;jump to move defeated bloober downwards
  10503.  
  10504. ProcSwimmingB:
  10505.         ldax BlooperMoveCounter,x  ;get enemy's movement counter
  10506.         andn ++%00000010            ;check for d1 set
  10507.         bne ChkForFloatdown       ;branch if set
  10508.         lda FrameCounter
  10509.         andn ++%00000111            ;get 3 LSB of frame counter
  10510.         pha                       ;and save it to the stack
  10511.         ldax BlooperMoveCounter,x  ;get enemy's movement counter
  10512.         lsr                       ;check for d0 set
  10513.         bcs SlowSwim              ;branch if set
  10514.         pla                       ;pull 3 LSB of frame counter from the stack
  10515.          checka
  10516.         bne BSwimE                ;branch to leave, execute code only every eighth frame
  10517.         ldax Enemy_Y_MoveForce,x
  10518.         clc                       ;add to movement force to speed up swim
  10519.         adcn ++$01
  10520.         stax Enemy_Y_MoveForce,x   ;set movement force
  10521.         stax BlooperMoveSpeed,x    ;set as movement speed
  10522.         cmpn ++$02
  10523.         bne BSwimE                ;if certain horizontal speed, branch to leave
  10524.         incx BlooperMoveCounter,x  ;otherwise increment movement counter
  10525. BSwimE: rts
  10526.  
  10527. SlowSwim:
  10528.        pla                      ;pull 3 LSB of frame counter from the stack
  10529.          checka
  10530.        bne NoSSw                ;branch to leave, execute code only every eighth frame
  10531.        ldax Enemy_Y_MoveForce,x
  10532.        secsub                      ;subtract from movement force to slow swim
  10533.        sbcn ++$01
  10534.        stax Enemy_Y_MoveForce,x  ;set movement force
  10535.        stax BlooperMoveSpeed,x   ;set as movement speed
  10536.          checka
  10537.        bne NoSSw                ;if any speed, branch to leave
  10538.        incx BlooperMoveCounter,x ;otherwise increment movement counter
  10539.        ldan ++$02
  10540.        stax EnemyIntervalTimer,x ;set enemy's timer
  10541. NoSSw: rts                      ;leave
  10542.  
  10543. ChkForFloatdown:
  10544.       ldax EnemyIntervalTimer,x ;get enemy timer
  10545.          checka
  10546.       beq ChkNearPlayer        ;branch if expired
  10547.  
  10548. Floatdown:
  10549.       lda FrameCounter        ;get frame counter
  10550.       lsr                     ;check for d0 set
  10551.       bcs NoFD                ;branch to leave on every other frame
  10552.       incx Enemy_Y_Position,x  ;otherwise increment vertical coordinate
  10553. NoFD: rts                     ;leave
  10554.  
  10555. ChkNearPlayer:
  10556. ;CY=0??? after JumpEngine
  10557.       ldax Enemy_Y_Position,x    ;get vertical coordinate
  10558.      or a ;???
  10559.       adcn ++$10                  ;add sixteen pixels
  10560.       cmpi Player_Y_Position     ;compare result with player's vertical coordinate
  10561.               cmpcy
  10562.       bcc Floatdown             ;if modified vertical less than player's, branch
  10563.       ldan ++$00
  10564.       stax BlooperMoveCounter,x  ;otherwise nullify movement counter
  10565.       rts
  10566.  
  10567. ;--------------------------------
  10568.  
  10569. MoveBulletBill:
  10570.          ldax Enemy_State,x          ;check bullet bill's enemy object state for d5 set
  10571.          andn ++%00100000
  10572.          beq NotDefB                ;if not set, continue with movement code
  10573.          jmp MoveJ_EnemyVertically  ;otherwise jump to move defeated bullet bill downwards
  10574. NotDefB: ldan ++$e8                   ;set bullet bill's horizontal speed
  10575.          stax Enemy_X_Speed,x        ;and move it accordingly (note: this bullet bill
  10576.          jmp MoveEnemyHorizontally  ;object occurs in frenzy object $17, not from cannons)
  10577.  
  10578. ;--------------------------------
  10579. ;$02 - used to hold preset values
  10580. ;$03 - used to hold enemy state
  10581.  
  10582. SwimCCXMoveData:
  10583.       .db $40, $80
  10584.       .db $04, $04 ;residual data, not used
  10585.  
  10586. MoveSwimmingCheepCheep:
  10587.         ldax Enemy_State,x         ;check cheep-cheep's enemy object state
  10588.         andn ++%00100000            ;for d5 set
  10589.         beq CCSwim                ;if not set, continue with movement code
  10590.         jmp MoveEnemySlowVert     ;otherwise jump to move defeated cheep-cheep downwards
  10591. CCSwim: sta SCRATCHPAD+$03                   ;save enemy state in $03
  10592.         ldax Enemy_ID,x            ;get enemy identifier
  10593.         secsub
  10594.         sbcn ++$0a                  ;subtract ten for cheep-cheep identifiers
  10595.         tay                       ;use as offset
  10596.         lday SwimCCXMoveData,y     ;load value here
  10597.         sta SCRATCHPAD+$02
  10598.         ldax Enemy_X_MoveForce,x   ;load horizontal force (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  10599.         secsub
  10600.         sbci SCRATCHPAD+$02                   ;subtract preset value from horizontal force
  10601.           push af
  10602.         stax Enemy_X_MoveForce,x   ;store as new horizontal force (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  10603.         ldax Enemy_X_Position,x    ;get horizontal coordinate
  10604.           ld h,a
  10605.           pop af
  10606.           ld a,h
  10607.         sbcn ++$00                  ;subtract borrow (thus moving it slowly)
  10608.           push af
  10609.         stax Enemy_X_Position,x    ;and save as new horizontal coordinate
  10610.         ldax Enemy_PageLoc,x
  10611.           ld h,a
  10612.           pop af
  10613.           ld a,h
  10614.         sbcn ++$00                  ;subtract borrow again, this time from the
  10615.         stax Enemy_PageLoc,x       ;page location, then save
  10616.         ldan ++$20
  10617.         sta SCRATCHPAD+$02                   ;save new value here
  10618.         cpxn ++$02                  ;check enemy object offset
  10619.               cmpcy
  10620.         bcc ExSwCC                ;if in first or second slot, branch to leave
  10621.         ldax CheepCheepMoveMFlag,x ;check movement flag
  10622.         cmpn ++$10                  ;if movement speed set to $00,
  10623.               cmpcy
  10624.         bcc CCSwimUpwards         ;branch to move upwards
  10625.         ldax Enemy_YMF_Dummy,x
  10626.         clc
  10627.         adci SCRATCHPAD+$02                   ;add preset value to dummy variable to get carry
  10628.           push af
  10629.         stax Enemy_YMF_Dummy,x     ;and save dummy
  10630.         ldax Enemy_Y_Position,x    ;get vertical coordinate
  10631.           ld h,a
  10632.           pop af
  10633.           ld a,h
  10634.         adci SCRATCHPAD+$03                   ;add carry to it plus enemy state to slowly move it downwards
  10635.           push af
  10636.         stax Enemy_Y_Position,x    ;save as new vertical coordinate
  10637.         ldax Enemy_Y_HighPos,x
  10638.           ld h,a
  10639.           pop af
  10640.           ld a,h
  10641.         adcn ++$00                  ;add carry to page location and
  10642.         jmp ChkSwimYPos           ;jump to end of movement code
  10643.  
  10644. CCSwimUpwards:
  10645.         ldax Enemy_YMF_Dummy,x
  10646.         secsub
  10647.         sbci SCRATCHPAD+$02                   ;subtract preset value to dummy variable to get borrow
  10648.           push af
  10649.         stax Enemy_YMF_Dummy,x     ;and save dummy
  10650.         ldax Enemy_Y_Position,x    ;get vertical coordinate
  10651.           ld h,a
  10652.           pop af
  10653.           ld a,h
  10654.         sbci SCRATCHPAD+$03                   ;subtract borrow to it plus enemy state to slowly move it upwards
  10655.           push af
  10656.         stax Enemy_Y_Position,x    ;save as new vertical coordinate
  10657.         ldax Enemy_Y_HighPos,x
  10658.           ld h,a
  10659.           pop af
  10660.           ld a,h
  10661.         sbcn ++$00                  ;subtract borrow from page location
  10662.  
  10663. ChkSwimYPos:
  10664.         stax Enemy_Y_HighPos,x     ;save new page location here
  10665.         ldyn ++$00                  ;load movement speed to upwards by default
  10666.         ldax Enemy_Y_Position,x    ;get vertical coordinate
  10667.         secsub
  10668.         sbcx CheepCheepOrigYPos,x  ;subtract original coordinate from current
  10669.         bpl YPDiff                ;if result positive, skip to next part
  10670.         ldyn ++$10                  ;otherwise load movement speed to downwards
  10671.         eorn ++$ff
  10672.         clc                       ;get two's compliment of result
  10673.         adcn ++$01                  ;to obtain total difference of original vs. current
  10674. YPDiff: cmpn ++$0f                  ;if difference between original vs. current vertical
  10675.               cmpcy
  10676.         bcc ExSwCC                ;coordinates LOW  15 pixels, leave movement speed alone
  10677.         tya
  10678.         stax CheepCheepMoveMFlag,x ;otherwise change movement speed
  10679. ExSwCC: rts                       ;leave
  10680.  
  10681. ;--------------------------------
  10682. ;$00 - used as counter for firebar parts
  10683. ;$01 - used for oscillated high byte of spin state or to hold horizontal adder
  10684. ;$02 - used for oscillated high byte of spin state or to hold vertical adder
  10685. ;$03 - used for mirror data
  10686. ;$04 - used to store player's sprite 1 X coordinate
  10687. ;$05 - used to evaluate mirror data
  10688. ;$06 - used to store either screen X coordinate or sprite data offset
  10689. ;$07 - used to store screen Y coordinate
  10690. ;$ed - used to hold maximum length of firebar
  10691. ;$ef - used to hold high byte of spinstate
  10692.  
  10693. ;horizontal adder is at first byte + high byte of spinstate,
  10694. ;vertical adder is same + 8 bytes, two's compliment
  10695. ;if greater than $08 for proper oscillation
  10696. FirebarPosLookupTbl:
  10697.       .db $00, $01, $03, $04, $05, $06, $07, $07, $08
  10698.       .db $00, $03, $06, $09, $0b, $0d, $0e, $0f, $10
  10699.       .db $00, $04, $09, $0d, $10, $13, $16, $17, $18
  10700.       .db $00, $06, $0c, $12, $16, $1a, $1d, $1f, $20
  10701.       .db $00, $07, $0f, $16, $1c, $21, $25, $27, $28
  10702.       .db $00, $09, $12, $1b, $21, $27, $2c, $2f, $30
  10703.       .db $00, $0b, $15, $1f, $27, $2e, $33, $37, $38
  10704.       .db $00, $0c, $18, $24, $2d, $35, $3b, $3e, $40
  10705.       .db $00, $0e, $1b, $28, $32, $3b, $42, $46, $48
  10706.       .db $00, $0f, $1f, $2d, $38, $42, $4a, $4e, $50
  10707.       .db $00, $11, $22, $31, $3e, $49, $51, $56, $58
  10708.  
  10709. FirebarMirrorData:
  10710.       .db $01, $03, $02, $00
  10711.  
  10712. FirebarTblOffsets:
  10713.       .db $00, $09, $12, $1b, $24, $2d
  10714.       .db $36, $3f, $48, $51, $5a, $63
  10715.  
  10716. FirebarYPos:
  10717.       .db $0c, $18
  10718.  
  10719. ProcFirebar:
  10720.           jsr GetEnemyOffscreenBits   ;get offscreen information
  10721.           lda Enemy_OffscreenBits     ;check for d3 set
  10722.           andn ++%00001000              ;if so, branch to leave
  10723.           bne SkipFBar
  10724.           lda TimerControl            ;if master timer control set, branch
  10725.          checka
  10726.           bne SusFbar                 ;ahead of this part
  10727.           ldax FirebarSpinSpeed,x      ;load spinning speed of firebar
  10728.           jsr FirebarSpin             ;modify current spinstate
  10729.           andn ++%00011111              ;mask out all but 5 LSB
  10730.           stax FirebarSpinState_High,x ;and store as new high byte of spinstate
  10731. SusFbar:  ldax FirebarSpinState_High,x ;get high byte of spinstate
  10732.           ldyx Enemy_ID,x              ;check enemy identifier
  10733.           cpyn ++$1f
  10734.               cmpcy
  10735.           bcc SetupGFB                ;if LOW  $1f (long firebar), branch
  10736.           cmpn ++$08                    ;check high byte of spinstate
  10737.           beq SkpFSte                 ;if eight, branch to change
  10738.           cmpn ++$18
  10739.           bne SetupGFB                ;if not at twenty-four branch to not change
  10740. SkpFSte:  clc
  10741.           adcn ++$01                    ;add one to spinning thing to avoid horizontal state
  10742.           stax FirebarSpinState_High,x
  10743. SetupGFB: sta SCRATCHPAD+$ef                     ;save high byte of spinning thing, modified or otherwise
  10744.           jsr RelativeEnemyPosition   ;get relative coordinates to screen
  10745.           jsr GetFirebarPosition      ;do a sub here (residual, too early to be used now)
  10746.           ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  10747.           lda Enemy_Rel_YPos          ;get relative vertical coordinate
  10748.           stay Sprite_Y_Position,y     ;store as Y in OAM data
  10749.           sta SCRATCHPAD+$07                     ;also save here
  10750.           lda Enemy_Rel_XPos          ;get relative horizontal coordinate
  10751.           stay Sprite_X_Position,y     ;store as X in OAM data
  10752.           sta SCRATCHPAD+$06                     ;also save here
  10753.           ldan ++$01
  10754.           sta SCRATCHPAD+$00                     ;set $01 value here (not necessary)
  10755.           jsr FirebarCollision        ;draw fireball part and do collision detection
  10756.           ldyn ++$05                    ;load value for short firebars by default
  10757.           ldax Enemy_ID,x
  10758.           cmpn ++$1f                    ;are we doing a long firebar?
  10759.               cmpcy
  10760.           bcc SetMFbar                ;no, branch then
  10761.           ldyn ++$0b                    ;otherwise load value for long firebars
  10762. SetMFbar: sty SCRATCHPAD+$ed                     ;store maximum value for length of firebars
  10763.           ldan ++$00
  10764.           sta SCRATCHPAD+$00                     ;initialize counter here
  10765. DrawFbar: lda SCRATCHPAD+$ef                     ;load high byte of spinstate
  10766.           jsr GetFirebarPosition      ;get fireball position data depending on firebar part
  10767.           jsr DrawFirebar_Collision   ;position it properly, draw it and do collision detection
  10768.           lda SCRATCHPAD+$00                     ;check which firebar part
  10769.           cmpn ++$04
  10770.           bne NextFbar
  10771.           ldy DuplicateObj_Offset     ;if we arrive at fifth firebar part,
  10772.           lday Enemy_SprDataOffset,y   ;get offset from long firebar and load OAM data offset
  10773.           sta SCRATCHPAD+$06                     ;using long firebar offset, then store as new one here
  10774. NextFbar: inci SCRATCHPAD+$00                     ;move onto the next firebar part
  10775.           lda SCRATCHPAD+$00
  10776.           cmpi SCRATCHPAD+$ed                     ;if we end up at the maximum part, go on and leave
  10777.               cmpcy
  10778.           bcc DrawFbar                ;otherwise go back and do another
  10779. SkipFBar: rts
  10780.  
  10781. DrawFirebar_Collision:
  10782.          lda SCRATCHPAD+$03                  ;store mirror data elsewhere
  10783.          sta SCRATCHPAD+$05          
  10784.          ldy SCRATCHPAD+$06                  ;load OAM data offset for firebar
  10785.          lda SCRATCHPAD+$01                  ;load horizontal adder we got from position loader
  10786.          lsri SCRATCHPAD+$05                  ;shift LSB of mirror data
  10787.          bcs AddHA                ;if carry was set, skip this part
  10788.          eorn ++$ff
  10789.          adcn ++$01                 ;otherwise get two's compliment of horizontal adder
  10790. AddHA:   clc                      ;add horizontal coordinate relative to screen to
  10791.          adci Enemy_Rel_XPos       ;horizontal adder, modified or otherwise
  10792.          stay Sprite_X_Position,y  ;store as X coordinate here
  10793.          sta SCRATCHPAD+$06                  ;store here for now, note offset is saved in Y still
  10794.          cmpi Enemy_Rel_XPos       ;compare X coordinate of sprite to original X of firebar
  10795.               cmpcy
  10796.          bcs SubtR1               ;if sprite coordinate =HIGH  original coordinate, branch
  10797.          lda Enemy_Rel_XPos
  10798.          secsub                      ;otherwise subtract sprite X from the
  10799.          sbci SCRATCHPAD+$06                  ;original one and skip this part
  10800.          jmp ChkFOfs
  10801. SubtR1:  secsub                      ;subtract original X from the
  10802.          sbci Enemy_Rel_XPos       ;current sprite X
  10803. ChkFOfs: cmpn ++$59                 ;if difference of coordinates within a certain range,
  10804.               cmpcy
  10805.          bcc VAHandl              ;continue by handling vertical adder
  10806.          ldan ++$f8                 ;otherwise, load offscreen Y coordinate
  10807.          checka
  10808.          bne SetVFbr              ;and unconditionally branch to move sprite offscreen
  10809. VAHandl: lda Enemy_Rel_YPos       ;if vertical relative coordinate offscreen,
  10810.          cmpn ++$f8                 ;skip ahead of this part and write into sprite Y coordinate
  10811.          beq SetVFbr
  10812.          lda SCRATCHPAD+$02                  ;load vertical adder we got from position loader
  10813.          lsri SCRATCHPAD+$05                  ;shift LSB of mirror data one more time
  10814.          bcs AddVA                ;if carry was set, skip this part
  10815.          eorn ++$ff
  10816.          adcn ++$01                 ;otherwise get two's compliment of second part
  10817. AddVA:   clc                      ;add vertical coordinate relative to screen to
  10818.          adci Enemy_Rel_YPos       ;the second data, modified or otherwise
  10819. SetVFbr: stay Sprite_Y_Position,y  ;store as Y coordinate here
  10820.          sta SCRATCHPAD+$07                  ;also store here for now
  10821.  
  10822. FirebarCollision:
  10823.          jsr DrawFirebar          ;run sub here to draw current tile of firebar
  10824.          tya                      ;return OAM data offset and save
  10825.          pha                      ;to the stack for now
  10826.          lda StarInvincibleTimer  ;if star mario invincibility timer
  10827.          orai TimerControl         ;or master timer controls set
  10828.          bne NoColFB              ;then skip all of this
  10829.          sta SCRATCHPAD+$05                  ;otherwise initialize counter
  10830.          ldy Player_Y_HighPos
  10831.          dey                      ;if player's vertical high byte offscreen,
  10832.          bne NoColFB              ;skip all of this
  10833.          ldy Player_Y_Position    ;get player's vertical position
  10834.          lda PlayerSize           ;get player's size
  10835.          checka
  10836.          bne AdjSm                ;if player small, branch to alter variables
  10837.          lda CrouchingFlag
  10838.          checka
  10839.          beq BigJp                ;if player big and not crouching, jump ahead
  10840. AdjSm:   inci SCRATCHPAD+$05                  ;if small or big but crouching, execute this part
  10841.          inci SCRATCHPAD+$05                  ;first increment our counter twice (setting $02 as flag)
  10842.          tya
  10843.          clc                      ;then add 24 pixels to the player's
  10844.          adcn ++$18                 ;vertical coordinate
  10845.          tay
  10846. BigJp:   tya                      ;get vertical coordinate, altered or otherwise, from Y
  10847. FBCLoop: secsub                      ;subtract vertical position of firebar
  10848.          sbci SCRATCHPAD+$07                  ;from the vertical coordinate of the player
  10849.          bpl ChkVFBD              ;if player lower on the screen than firebar,
  10850.          eorn ++$ff                 ;skip two's compliment part
  10851.          clc                      ;otherwise get two's compliment
  10852.          adcn ++$01
  10853. ChkVFBD: cmpn ++$08                 ;if difference =HIGH  8 pixels, skip ahead of this part
  10854.               cmpcy
  10855.          bcs Chk2Ofs
  10856.          lda SCRATCHPAD+$06                  ;if firebar on far right on the screen, skip this,
  10857.          cmpn ++$f0                 ;because, really, what's the point?
  10858.               cmpcy
  10859.          bcs Chk2Ofs
  10860.          lda Sprite_X_Position+4  ;get OAM X coordinate for sprite ++1
  10861.          clc
  10862.          adcn ++$04                 ;add four pixels
  10863.          sta SCRATCHPAD+$04                  ;store here
  10864.          secsub                      ;subtract horizontal coordinate of firebar
  10865.          sbci SCRATCHPAD+$06                  ;from the X coordinate of player's sprite 1
  10866.          bpl ChkFBCl              ;if modded X coordinate to the right of firebar
  10867.          eorn ++$ff                 ;skip two's compliment part
  10868.          clc                      ;otherwise get two's compliment
  10869.          adcn ++$01
  10870. ChkFBCl: cmpn ++$08                 ;if difference LOW  8 pixels, collision, thus branch
  10871.               cmpcy
  10872.          bcc ChgSDir              ;to process
  10873. Chk2Ofs: lda SCRATCHPAD+$05                  ;if value of $02 was set earlier for whatever reason,
  10874.          cmpn ++$02                 ;branch to increment OAM offset and leave, no collision
  10875.          beq NoColFB
  10876.          ldy SCRATCHPAD+$05                  ;otherwise get temp here and use as offset
  10877.          lda Player_Y_Position
  10878.          clc
  10879.          adcy FirebarYPos,y        ;add value loaded with offset to player's vertical coordinate
  10880.          inci SCRATCHPAD+$05                  ;then increment temp and jump back
  10881.          jmp FBCLoop
  10882. ChgSDir: ldxn ++$01                 ;set movement direction by default
  10883.          lda SCRATCHPAD+$04                  ;if OAM X coordinate of player's sprite 1
  10884.          cmpi SCRATCHPAD+$06                  ;is greater than horizontal coordinate of firebar
  10885.               cmpcy
  10886.          bcs SetSDir              ;then do not alter movement direction
  10887.          inx                      ;otherwise increment it
  10888. SetSDir: stx Enemy_MovingDir      ;store movement direction here
  10889.          ldxn ++$00
  10890.          lda SCRATCHPAD+$00                  ;save value written to $00 to stack
  10891.          pha
  10892.          jsr InjurePlayer         ;perform sub to hurt or kill player
  10893.          pla
  10894.          sta SCRATCHPAD+$00                  ;get value of $00 from stack
  10895. NoColFB: pla                      ;get OAM data offset
  10896.          clc                      ;add four to it and save
  10897.          adcn ++$04
  10898.          sta SCRATCHPAD+$06
  10899.          ldx ObjectOffset         ;get enemy object buffer offset and leave
  10900.          rts
  10901.  
  10902. GetFirebarPosition:
  10903.            pha                        ;save high byte of spinstate to the stack
  10904.            andn ++%00001111             ;mask out low nybble
  10905.            cmpn ++$09
  10906.               cmpcy
  10907.            bcc GetHAdder              ;if lower than $09, branch ahead
  10908.            eorn ++%00001111             ;otherwise get two's compliment to oscillate
  10909.            clc
  10910.            adcn ++$01
  10911. GetHAdder: sta SCRATCHPAD+$01                    ;store result, modified or not, here
  10912.            ldy SCRATCHPAD+$00                    ;load number of firebar ball where we're at
  10913.            lday FirebarTblOffsets,y    ;load offset to firebar position data
  10914.            clc
  10915.            adci SCRATCHPAD+$01                    ;add oscillated high byte of spinstate
  10916.            tay                        ;to offset here and use as new offset
  10917.            lday FirebarPosLookupTbl,y  ;get data here and store as horizontal adder
  10918.            sta SCRATCHPAD+$01
  10919.            pla                        ;pull whatever was in A from the stack
  10920.            pha                        ;save it again because we still need it
  10921.            clc
  10922.            adcn ++$08                   ;add eight this time, to get vertical adder
  10923.            andn ++%00001111             ;mask out high nybble
  10924.            cmpn ++$09                   ;if lower than $09, branch ahead
  10925.               cmpcy
  10926.            bcc GetVAdder
  10927.            eorn ++%00001111             ;otherwise get two's compliment
  10928.            clc
  10929.            adcn ++$01
  10930. GetVAdder: sta SCRATCHPAD+$02                    ;store result here
  10931.            ldy SCRATCHPAD+$00
  10932.            lday FirebarTblOffsets,y    ;load offset to firebar position data again
  10933.            clc
  10934.            adci SCRATCHPAD+$02                    ;this time add value in $02 to offset here and use as offset
  10935.            tay
  10936.            lday FirebarPosLookupTbl,y  ;get data here and store as vertica adder
  10937.            sta SCRATCHPAD+$02
  10938.            pla                        ;pull out whatever was in A one last time
  10939.            lsr                        ;divide by eight or shift three to the right
  10940.            lsr
  10941.            lsr
  10942.            tay                        ;use as offset
  10943.            lday FirebarMirrorData,y    ;load mirroring data here
  10944.            sta SCRATCHPAD+$03                    ;store
  10945.            rts
  10946.  
  10947. ;--------------------------------
  10948.  
  10949. PRandomSubtracter:
  10950.       .db $f8, $a0, $70, $bd, $00
  10951.  
  10952. FlyCCBPriority:
  10953.       .db $20, $20, $20, $00, $00
  10954.  
  10955. MoveFlyingCheepCheep:
  10956.         ldax Enemy_State,x          ;check cheep-cheep's enemy state
  10957.         andn ++%00100000             ;for d5 set
  10958.         beq FlyCC                  ;branch to continue code if not set
  10959.         ldan ++$00
  10960.         stax Enemy_SprAttrib,x      ;otherwise clear sprite attributes
  10961.         jmp MoveJ_EnemyVertically  ;and jump to move defeated cheep-cheep downwards
  10962. FlyCC:  jsr MoveEnemyHorizontally  ;move cheep-cheep horizontally based on speed and force
  10963.         ldyn ++$0d                   ;set vertical movement amount
  10964.         ldan ++$05                   ;set maximum speed
  10965.         jsr SetXMoveAmt            ;branch to impose gravity on flying cheep-cheep
  10966.         ldax Enemy_Y_MoveForce,x
  10967.         lsr                        ;get vertical movement force and
  10968.         lsr                        ;move high nybble to low
  10969.         lsr
  10970.         lsr
  10971.         tay                        ;save as offset (note this tends to go into reach of code)
  10972.         ldax Enemy_Y_Position,x     ;get vertical position
  10973.         secsub                        ;subtract pseudorandom value based on offset from position
  10974.         sbcy PRandomSubtracter,y
  10975.         bpl AddCCF                  ;if result within top half of screen, skip this part
  10976.         eorn ++$ff
  10977.         clc                        ;otherwise get two's compliment
  10978.         adcn ++$01
  10979. AddCCF: cmpn ++$08                   ;if result or two's compliment greater than eight,
  10980.               cmpcy
  10981.         bcs BPGet                  ;skip to the end without changing movement force
  10982.         ldax Enemy_Y_MoveForce,x
  10983.         clc
  10984.         adcn ++$10                   ;otherwise add to it
  10985.         stax Enemy_Y_MoveForce,x
  10986.         lsr                        ;move high nybble to low again
  10987.         lsr
  10988.         lsr
  10989.         lsr
  10990.         tay
  10991. BPGet:  lday FlyCCBPriority,y       ;load bg priority data and store (this is very likely
  10992.         stax Enemy_SprAttrib,x      ;broken or residual code, value is overwritten before
  10993.         rts                        ;drawing it next frame), then leave
  10994.  
  10995. ;--------------------------------
  10996. ;$00 - used to hold horizontal difference
  10997. ;$01-$03 - used to hold difference adjusters
  10998.  
  10999. LakituDiffAdj:
  11000.       .db $15, $30, $40
  11001.  
  11002. MoveLakitu:
  11003.          ldax Enemy_State,x          ;check lakitu's enemy state
  11004.          andn ++%00100000             ;for d5 set
  11005.          beq ChkLS                  ;if not set, continue with code
  11006.          jmp MoveD_EnemyVertically  ;otherwise jump to move defeated lakitu downwards
  11007. ChkLS:   ldax Enemy_State,x          ;if lakitu's enemy state not set at all,
  11008.          checka
  11009.          beq Fr12S                  ;go ahead and continue with code
  11010.          ldan ++$00
  11011.          stax LakituMoveDirection,x  ;otherwise initialize moving direction to move to left
  11012.          sta EnemyFrenzyBuffer      ;initialize frenzy buffer
  11013.          ldan ++$10
  11014.          checka
  11015.          bne SetLSpd                ;load horizontal speed and do unconditional branch
  11016. Fr12S:   ldan ++Spiny
  11017.          sta EnemyFrenzyBuffer      ;set spiny identifier in frenzy buffer
  11018.          ldyn ++$02
  11019. LdLDa:   lday LakituDiffAdj,y        ;load values
  11020.          stay SCRATCHPAD+$0001,y                ;store in zero page
  11021.          dey
  11022.          bpl LdLDa                  ;do this until all values are stired
  11023.          jsr PlayerLakituDiff       ;execute sub to set speed and create spinys
  11024. SetLSpd: stax LakituMoveSpeed,x      ;set movement speed returned from sub
  11025.          ldyn ++$01                   ;set moving direction to right by default
  11026.          ldax LakituMoveDirection,x
  11027.          andn ++$01                   ;get LSB of moving direction
  11028.          bne SetLMov                ;if set, branch to the end to use moving direction
  11029.          ldax LakituMoveSpeed,x
  11030.          eorn ++$ff                   ;get two's compliment of moving speed
  11031.          clc
  11032.          adcn ++$01
  11033.          stax LakituMoveSpeed,x      ;store as new moving speed
  11034.          iny                        ;increment moving direction to left
  11035. SetLMov: styx Enemy_MovingDir,x      ;store moving direction
  11036.          jmp MoveEnemyHorizontally  ;move lakitu horizontally
  11037.  
  11038. PlayerLakituDiff:
  11039.            ldyn ++$00                   ;set Y for default value
  11040.            jsr PlayerEnemyDiff        ;get horizontal difference between enemy and player
  11041.            bpl ChkLakDif              ;branch if enemy is to the right of the player
  11042.            iny                        ;increment Y for left of player
  11043.            lda SCRATCHPAD+$00
  11044.            eorn ++$ff                   ;get two's compliment of low byte of horizontal difference
  11045.            clc
  11046.            adcn ++$01                   ;store two's compliment as horizontal difference
  11047.            sta SCRATCHPAD+$00
  11048. ChkLakDif: lda SCRATCHPAD+$00                    ;get low byte of horizontal difference
  11049.            cmpn ++$3c                   ;if within a certain distance of player, branch
  11050.               cmpcy
  11051.            bcc ChkPSpeed
  11052.            ldan ++$3c                   ;otherwise set maximum distance
  11053.            sta SCRATCHPAD+$00
  11054.            ldax Enemy_ID,x             ;check if lakitu is in our current enemy slot
  11055.            cmpn ++Lakitu
  11056.            bne ChkPSpeed              ;if not, branch elsewhere
  11057.            tya                        ;compare contents of Y, now in A
  11058.            cmpx LakituMoveDirection,x  ;to what is being used as horizontal movement direction
  11059.            beq ChkPSpeed              ;if moving toward the player, branch, do not alter
  11060.            ldax LakituMoveDirection,x  ;if moving to the left beyond maximum distance,
  11061.          checka
  11062.            beq SetLMovD               ;branch and alter without delay
  11063.            decx LakituMoveSpeed,x      ;decrement horizontal speed
  11064.            ldax LakituMoveSpeed,x      ;if horizontal speed not yet at zero, branch to leave
  11065.          checka
  11066.            bne ExMoveLak
  11067. SetLMovD:  tya                        ;set horizontal direction depending on horizontal
  11068.            stax LakituMoveDirection,x  ;difference between enemy and player if necessary
  11069. ChkPSpeed: lda SCRATCHPAD+$00
  11070.            andn ++%00111100             ;mask out all but four bits in the middle
  11071.            lsr                        ;divide masked difference by four
  11072.            lsr
  11073.            sta SCRATCHPAD+$00                    ;store as new value
  11074.            ldyn ++$00                   ;init offset
  11075.            lda Player_X_Speed
  11076.          checka
  11077.            beq SubDifAdj              ;if player not moving horizontally, branch
  11078.            lda ScrollAmount
  11079.          checka
  11080.            beq SubDifAdj              ;if scroll speed not set, branch to same place
  11081.            iny                        ;otherwise increment offset
  11082.            lda Player_X_Speed
  11083.            cmpn ++$19                   ;if player not running, branch
  11084.               cmpcy
  11085.            bcc ChkSpinyO
  11086.            lda ScrollAmount
  11087.            cmpn ++$02                   ;if scroll speed below a certain amount, branch
  11088.               cmpcy
  11089.            bcc ChkSpinyO              ;to same place
  11090.            iny                        ;otherwise increment once more
  11091. ChkSpinyO: ldax Enemy_ID,x             ;check for spiny object
  11092.            cmpn ++Spiny
  11093.            bne ChkEmySpd              ;branch if not found
  11094.            lda Player_X_Speed         ;if player not moving, skip this part
  11095.          checka
  11096.            bne SubDifAdj
  11097. ChkEmySpd: ldax Enemy_Y_Speed,x        ;check vertical speed
  11098.          checka
  11099.            bne SubDifAdj              ;branch if nonzero
  11100.            ldyn ++$00                   ;otherwise reinit offset
  11101. SubDifAdj: lday SCRATCHPAD+$0001,y                ;get one of three saved values from earlier
  11102.            ldy SCRATCHPAD+$00                    ;get saved horizontal difference
  11103. SPixelLak: secsub                        ;subtract one for each pixel of horizontal difference
  11104.            sbcn ++$01                   ;from one of three saved values
  11105.            dey
  11106.            bpl SPixelLak              ;branch until all pixels are subtracted, to adjust difference
  11107. ExMoveLak: rts                        ;leave!!!
  11108.  
  11109. ;-------------------------------------------------------------------------------------
  11110. ;$04-$05 - used to store name table address in little endian order
  11111.  
  11112. BridgeCollapseData:
  11113.       .db $1a ;axe
  11114.       .db $58 ;chain
  11115.       .db $98, $96, $94, $92, $90, $8e, $8c ;bridge
  11116.       .db $8a, $88, $86, $84, $82, $80
  11117.  
  11118. BridgeCollapse:
  11119.        ldx BowserFront_Offset    ;get enemy offset for bowser
  11120.        ldax Enemy_ID,x            ;check enemy object identifier for bowser
  11121.        cmpn ++Bowser               ;if not found, branch ahead,
  11122.        bne SetM2                 ;metatile removal not necessary
  11123.        stx ObjectOffset          ;store as enemy offset here
  11124.        ldax Enemy_State,x         ;if bowser in normal state, skip all of this
  11125.          checka
  11126.        beq RemoveBridge
  11127.        andn ++%01000000            ;if bowser's state has d6 clear, skip to silence music
  11128.        beq SetM2
  11129.        ldax Enemy_Y_Position,x    ;check bowser's vertical coordinate
  11130.        cmpn ++$e0                  ;if bowser not yet low enough, skip this part ahead
  11131.               cmpcy
  11132.        bcc MoveD_Bowser
  11133. SetM2: ldan ++Silence              ;silence music
  11134.        sta EventMusicQueue
  11135.        inci OperMode_Task         ;move onto next secondary mode in autoctrl mode
  11136.        jmp KillAllEnemies        ;jump to empty all enemy slots and then leave  
  11137.  
  11138. MoveD_Bowser:
  11139.        jsr MoveEnemySlowVert     ;do a sub to move bowser downwards
  11140.        jmp BowserGfxHandler      ;jump to draw bowser's front and rear, then leave
  11141.  
  11142. RemoveBridge:
  11143.          deci BowserFeetCounter     ;decrement timer to control bowser's feet
  11144.          bne NoBFall               ;if not expired, skip all of this
  11145.          ldan ++$04
  11146.          sta BowserFeetCounter     ;otherwise, set timer now
  11147.          lda BowserBodyControls
  11148.          eorn ++$01                  ;invert bit to control bowser's feet
  11149.          sta BowserBodyControls
  11150.          ldan ++$22                  ;put high byte of name table address here for now
  11151.          sta SCRATCHPAD+$05
  11152.          ldy BridgeCollapseOffset  ;get bridge collapse offset here
  11153.          lday BridgeCollapseData,y  ;load low byte of name table address and store here
  11154.          sta SCRATCHPAD+$04
  11155.          ldy VRAM_Buffer1_Offset   ;increment vram buffer offset
  11156.          iny
  11157.          ldxn ++$0c                  ;set offset for tile data for sub to draw blank metatile
  11158.          jsr RemBridge             ;do sub here to remove bowser's bridge metatiles
  11159.          ldx ObjectOffset          ;get enemy offset
  11160.          jsr MoveVOffset           ;set new vram buffer offset
  11161.          ldan ++Sfx_Blast            ;load the fireworks/gunfire sound into the square 2 sfx
  11162.          sta Square2SoundQueue     ;queue while at the same time loading the brick
  11163.          ldan ++Sfx_BrickShatter     ;shatter sound into the noise sfx queue thus
  11164.          sta NoiseSoundQueue       ;producing the unique sound of the bridge collapsing
  11165.          inci BridgeCollapseOffset  ;increment bridge collapse offset
  11166.          lda BridgeCollapseOffset
  11167.          cmpn ++$0f                  ;if bridge collapse offset has not yet reached
  11168.          bne NoBFall               ;the end, go ahead and skip this part
  11169.          jsr InitVStf              ;initialize whatever vertical speed bowser has
  11170.          ldan ++%01000000
  11171.          stax Enemy_State,x         ;set bowser's state to one of defeated states (d6 set)
  11172.          ldan ++Sfx_BowserFall
  11173.          sta Square2SoundQueue     ;play bowser defeat sound
  11174. NoBFall: jmp BowserGfxHandler      ;jump to code that draws bowser
  11175.  
  11176. ;--------------------------------
  11177.  
  11178. PRandomRange:
  11179.       .db $21, $41, $11, $31
  11180.  
  11181. RunBowser:
  11182.       ldax Enemy_State,x       ;if d5 in enemy state is not set
  11183.       andn ++%00100000          ;then branch elsewhere to run bowser
  11184.       beq BowserControl
  11185.       ldax Enemy_Y_Position,x  ;otherwise check vertical position
  11186.       cmpn ++$e0                ;if above a certain point, branch to move defeated bowser
  11187.               cmpcy
  11188.       bcc MoveD_Bowser        ;otherwise proceed to KillAllEnemies
  11189.  
  11190. KillAllEnemies:
  11191.           ldxn ++$04              ;start with last enemy slot
  11192. KillLoop: jsr EraseEnemyObject  ;branch to kill enemy objects
  11193.           dex                   ;move onto next enemy slot
  11194.           bpl KillLoop          ;do this until all slots are emptied
  11195.           sta EnemyFrenzyBuffer ;empty frenzy buffer
  11196.           ldx ObjectOffset      ;get enemy object offset and leave
  11197.           rts
  11198.  
  11199. BowserControl:
  11200.            ldan ++$00
  11201.            sta EnemyFrenzyBuffer      ;empty frenzy buffer
  11202.            lda TimerControl           ;if master timer control not set,
  11203.          checka
  11204.            beq ChkMouth               ;skip jump and execute code here
  11205.            jmp SkipToFB               ;otherwise, jump over a bunch of code
  11206. ChkMouth:  lda BowserBodyControls     ;check bowser's mouth
  11207.          checka
  11208.            bpl FeetTmr                ;if bit clear, go ahead with code here
  11209.            jmp HammerChk              ;otherwise skip a whole section starting here
  11210. FeetTmr:   deci BowserFeetCounter      ;decrement timer to control bowser's feet
  11211.            bne ResetMDr               ;if not expired, skip this part
  11212.            ldan ++$20                   ;otherwise, reset timer
  11213.            sta BowserFeetCounter        
  11214.            lda BowserBodyControls     ;and invert bit used
  11215.            eorn ++%00000001             ;to control bowser's feet
  11216.            sta BowserBodyControls
  11217. ResetMDr:  lda FrameCounter           ;check frame counter
  11218.            andn ++%00001111             ;if not on every sixteenth frame, skip
  11219.            bne B_FaceP                ;ahead to continue code
  11220.            ldan ++$02                   ;otherwise reset moving/facing direction every
  11221.            stax Enemy_MovingDir,x      ;sixteen frames
  11222. B_FaceP:   ldax EnemyFrameTimer,x      ;if timer set here expired,
  11223.          checka
  11224.            beq GetPRCmp               ;branch to next section
  11225.            jsr PlayerEnemyDiff        ;get horizontal difference between player and bowser,
  11226.            bpl GetPRCmp               ;and branch if bowser to the right of the player
  11227.            ldan ++$01
  11228.            stax Enemy_MovingDir,x      ;set bowser to move and face to the right
  11229.            ldan ++$02
  11230.            sta BowserMovementSpeed    ;set movement speed
  11231.            ldan ++$20
  11232.            stax EnemyFrameTimer,x      ;set timer here
  11233.            sta BowserFireBreathTimer  ;set timer used for bowser's flame
  11234.            ldax Enemy_X_Position,x        
  11235.            cmpn ++$c8                   ;if bowser to the right past a certain point,
  11236.               cmpcy
  11237.            bcs HammerChk              ;skip ahead to some other section
  11238. GetPRCmp:  lda FrameCounter           ;get frame counter
  11239.            andn ++%00000011
  11240.            bne HammerChk              ;execute this code every fourth frame, otherwise branch
  11241.            ldax Enemy_X_Position,x
  11242.            cmpi BowserOrigXPos         ;if bowser not at original horizontal position,
  11243.            bne GetDToO                ;branch to skip this part
  11244.            ldax PseudoRandomBitReg,x
  11245.            andn ++%00000011             ;get pseudorandom offset
  11246.            tay
  11247.            lday PRandomRange,y         ;load value using pseudorandom offset
  11248.            sta MaxRangeFromOrigin     ;and store here
  11249. GetDToO:   ldax Enemy_X_Position,x
  11250.            clc                        ;add movement speed to bowser's horizontal
  11251.            adci BowserMovementSpeed    ;coordinate and save as new horizontal position
  11252.            stax Enemy_X_Position,x
  11253.            ldyx Enemy_MovingDir,x
  11254.            cpyn ++$01                   ;if bowser moving and facing to the right, skip ahead
  11255.            beq HammerChk
  11256.            ldyn ++$ff                   ;set default movement speed here (move left)
  11257.            secsub                        ;get difference of current vs. original
  11258.            sbci BowserOrigXPos         ;horizontal position
  11259.            bpl CompDToO               ;if current position to the right of original, skip ahead
  11260.            eorn ++$ff
  11261.            clc                        ;get two's compliment
  11262.            adcn ++$01
  11263.            ldyn ++$01                   ;set alternate movement speed here (move right)
  11264. CompDToO:  cmpi MaxRangeFromOrigin     ;compare difference with pseudorandom value
  11265.               cmpcy
  11266.            bcc HammerChk              ;if difference LOW  pseudorandom value, leave speed alone
  11267.            sty BowserMovementSpeed    ;otherwise change bowser's movement speed
  11268. HammerChk: ldax EnemyFrameTimer,x      ;if timer set here not expired yet, skip ahead to
  11269.          checka
  11270.            bne MakeBJump              ;some other section of code
  11271.            jsr MoveEnemySlowVert      ;otherwise start by moving bowser downwards
  11272.            lda WorldNumber            ;check world number
  11273.            cmpn ++World6
  11274.               cmpcy
  11275.            bcc SetHmrTmr              ;if world 1-5, skip this part (not time to throw hammers yet)
  11276.            lda FrameCounter
  11277.            andn ++%00000011             ;check to see if it's time to execute sub
  11278.            bne SetHmrTmr              ;if not, skip sub, otherwise
  11279.            jsr SpawnHammerObj         ;execute sub on every fourth frame to spawn misc object (hammer)
  11280. SetHmrTmr: ldax Enemy_Y_Position,x     ;get current vertical position
  11281.            cmpn ++$80                   ;if still above a certain point
  11282.               cmpcy
  11283.            bcc ChkFireB               ;then skip to world number check for flames
  11284.            ldax PseudoRandomBitReg,x
  11285.            andn ++%00000011             ;get pseudorandom offset
  11286.            tay
  11287.            lday PRandomRange,y         ;get value using pseudorandom offset
  11288.            stax EnemyFrameTimer,x      ;set for timer here
  11289. SkipToFB:  jmp ChkFireB               ;jump to execute flames code
  11290. MakeBJump: cmpn ++$01                   ;if timer not yet about to expire,
  11291.            bne ChkFireB               ;skip ahead to next part
  11292.            decx Enemy_Y_Position,x     ;otherwise decrement vertical coordinate
  11293.            jsr InitVStf               ;initialize movement amount
  11294.            ldan ++$fe
  11295.            stax Enemy_Y_Speed,x        ;set vertical speed to move bowser upwards
  11296. ChkFireB:  lda WorldNumber            ;check world number here
  11297.            cmpn ++World8                ;world 8?
  11298.            beq SpawnFBr               ;if so, execute this part here
  11299.            cmpn ++World6                ;world 6-7?
  11300.               cmpcy
  11301.            bcs BowserGfxHandler       ;if so, skip this part here
  11302. SpawnFBr:  lda BowserFireBreathTimer  ;check timer here
  11303.          checka
  11304.            bne BowserGfxHandler       ;if not expired yet, skip all of this
  11305.            ldan ++$20
  11306.            sta BowserFireBreathTimer  ;set timer here
  11307.            lda BowserBodyControls
  11308.            eorn ++%10000000             ;invert bowser's mouth bit to open
  11309.            sta BowserBodyControls     ;and close bowser's mouth
  11310.            bmi ChkFireB               ;if bowser's mouth open, loop back
  11311.            jsr SetFlameTimer          ;get timing for bowser's flame
  11312.            ldy SecondaryHardMode
  11313.          checky
  11314.            beq SetFBTmr               ;if secondary hard mode flag not set, skip this
  11315.            secsub
  11316.            sbcn ++$10                   ;otherwise subtract from value in A
  11317. SetFBTmr:  sta BowserFireBreathTimer  ;set value as timer here
  11318.            ldan ++BowserFlame           ;put bowser's flame identifier
  11319.            sta EnemyFrenzyBuffer      ;in enemy frenzy buffer
  11320.  
  11321. ;--------------------------------
  11322.  
  11323. BowserGfxHandler:
  11324.           jsr ProcessBowserHalf    ;do a sub here to process bowser's front
  11325.           ldyn ++$10                 ;load default value here to position bowser's rear
  11326.           ldax Enemy_MovingDir,x    ;check moving direction
  11327.           lsr
  11328.           bcc CopyFToR             ;if moving left, use default
  11329.           ldyn ++$f0                 ;otherwise load alternate positioning value here
  11330. CopyFToR: tya                      ;move bowser's rear object position value to A
  11331.           clc
  11332.           adcx Enemy_X_Position,x   ;add to bowser's front object horizontal coordinate
  11333.           ldy DuplicateObj_Offset  ;get bowser's rear object offset
  11334.           stay Enemy_X_Position,y   ;store A as bowser's rear horizontal coordinate
  11335.           ldax Enemy_Y_Position,x
  11336.           clc                      ;add eight pixels to bowser's front object
  11337.           adcn ++$08                 ;vertical coordinate and store as vertical coordinate
  11338.           stay Enemy_Y_Position,y   ;for bowser's rear
  11339.           ldax Enemy_State,x
  11340.           stay Enemy_State,y        ;copy enemy state directly from front to rear
  11341.           ldax Enemy_MovingDir,x
  11342.           stay Enemy_MovingDir,y    ;copy moving direction also
  11343.           lda ObjectOffset         ;save enemy object offset of front to stack
  11344.           pha
  11345.           ldx DuplicateObj_Offset  ;put enemy object offset of rear as current
  11346.           stx ObjectOffset
  11347.           ldan ++Bowser              ;set bowser's enemy identifier
  11348.           stax Enemy_ID,x           ;store in bowser's rear object
  11349.           jsr ProcessBowserHalf    ;do a sub here to process bowser's rear
  11350.           pla
  11351.           sta ObjectOffset         ;get original enemy object offset
  11352.           tax
  11353.           ldan ++$00                 ;nullify bowser's front/rear graphics flag
  11354.           sta BowserGfxFlag
  11355. ExBGfxH:  rts                      ;leave!
  11356.  
  11357. ProcessBowserHalf:
  11358.       inci BowserGfxFlag         ;increment bowser's graphics flag, then run subroutines
  11359.       jsr RunRetainerObj        ;to get offscreen bits, relative position and draw bowser (finally!)
  11360.       ldax Enemy_State,x
  11361.          checka
  11362.       bne ExBGfxH               ;if either enemy object not in normal state, branch to leave
  11363.       ldan ++$0a
  11364.       stax Enemy_BoundBoxCtrl,x  ;set bounding box size control
  11365.       jsr GetEnemyBoundBox      ;get bounding box coordinates
  11366.       jmp PlayerEnemyCollision  ;do player-to-enemy collision detection
  11367.  
  11368. ;-------------------------------------------------------------------------------------
  11369. ;$00 - used to hold movement force and tile number
  11370. ;$01 - used to hold sprite attribute data
  11371.  
  11372. FlameTimerData:
  11373.       .db $bf, $40, $bf, $bf, $bf, $40, $40, $bf
  11374.  
  11375. SetFlameTimer:
  11376.       ldy BowserFlameTimerCtrl  ;load counter as offset
  11377.       inci BowserFlameTimerCtrl  ;increment
  11378.       lda BowserFlameTimerCtrl  ;mask out all but 3 LSB
  11379.       andn ++%00000111            ;to keep in range of 0-7
  11380.       sta BowserFlameTimerCtrl
  11381.       lday FlameTimerData,y      ;load value to be used then leave
  11382. ExFl: rts
  11383.  
  11384. ProcBowserFlame:
  11385.          lda TimerControl            ;if master timer control flag set,
  11386.          checka
  11387.          bne SetGfxF                 ;skip all of this
  11388.          ldan ++$40                    ;load default movement force
  11389.          ldy SecondaryHardMode
  11390.          checky
  11391.          beq SFlmX                   ;if secondary hard mode flag not set, use default
  11392.          ldan ++$60                    ;otherwise load alternate movement force to go faster
  11393. SFlmX:   sta SCRATCHPAD+$00                     ;store value here
  11394.          ldax Enemy_X_MoveForce,x
  11395.          secsub                         ;subtract value from movement force (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  11396.          sbci SCRATCHPAD+$00
  11397.           push af
  11398.          stax Enemy_X_MoveForce,x     ;save new value (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  11399.          ldax Enemy_X_Position,x
  11400.           ld h,a
  11401.           pop af
  11402.           ld a,h
  11403.          sbcn ++$01                    ;subtract one from horizontal position to move
  11404.           push af
  11405.          stax Enemy_X_Position,x      ;to the left
  11406.          ldax Enemy_PageLoc,x
  11407.           ld h,a
  11408.           pop af
  11409.           ld a,h
  11410.          sbcn ++$00                    ;subtract borrow from page location
  11411.          stax Enemy_PageLoc,x
  11412.          ldyx BowserFlamePRandomOfs,x ;get some value here and use as offset
  11413.          ldax Enemy_Y_Position,x      ;load vertical coordinate
  11414.          cmpy FlameYPosData,y         ;compare against coordinate data using $0417,x (???) as offset
  11415.          beq SetGfxF                 ;if equal, branch and do not modify coordinate
  11416.          clc
  11417.          adcx Enemy_Y_MoveForce,x     ;otherwise add value here to coordinate and store
  11418.          stax Enemy_Y_Position,x      ;as new vertical coordinate
  11419. SetGfxF: jsr RelativeEnemyPosition   ;get new relative coordinates
  11420.          ldax Enemy_State,x           ;if bowser's flame not in normal state,
  11421.          checka
  11422.          bne ExFl                    ;branch to leave
  11423.          ldan ++$51                    ;otherwise, continue
  11424.          sta SCRATCHPAD+$00                     ;write first tile number
  11425.          ldyn ++$02                    ;load attributes without vertical flip by default
  11426.          lda FrameCounter
  11427.          andn ++%00000010              ;invert vertical flip bit every 2 frames
  11428.          beq FlmeAt                  ;if d1 not set, write default value
  11429.          ldyn ++$82                    ;otherwise write value with vertical flip bit set
  11430. FlmeAt:  sty SCRATCHPAD+$01                     ;set bowser's flame sprite attributes here
  11431.          ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  11432.          ldxn ++$00
  11433.  
  11434. DrawFlameLoop:
  11435.          lda Enemy_Rel_YPos         ;get Y relative coordinate of current enemy object
  11436.          stay Sprite_Y_Position,y    ;write into Y coordinate of OAM data
  11437.          lda SCRATCHPAD+$00
  11438.          stay Sprite_Tilenumber,y    ;write current tile number into OAM data
  11439.          inci SCRATCHPAD+$00                    ;increment tile number to draw more bowser's flame
  11440.          lda SCRATCHPAD+$01
  11441.          stay Sprite_Attributes,y    ;write saved attributes into OAM data
  11442.          lda Enemy_Rel_XPos
  11443.          stay Sprite_X_Position,y    ;write X relative coordinate of current enemy object
  11444.          clc
  11445.          adcn ++$08
  11446.          sta Enemy_Rel_XPos         ;then add eight to it and store
  11447.          iny
  11448.          iny
  11449.          iny
  11450.          iny                        ;increment Y four times to move onto the next OAM
  11451.          inx                        ;move onto the next OAM, and branch if three
  11452.          cpxn ++$03                   ;have not yet been done
  11453.               cmpcy
  11454.          bcc DrawFlameLoop
  11455.          ldx ObjectOffset           ;reload original enemy offset
  11456.          jsr GetEnemyOffscreenBits  ;get offscreen information
  11457.          ldyx Enemy_SprDataOffset,x  ;get OAM data offset
  11458.          lda Enemy_OffscreenBits    ;get enemy object offscreen bits
  11459.          lsr                        ;move d0 to carry and result to stack
  11460.          pha
  11461.          bcc M3FOfs                 ;branch if carry not set
  11462.          ldan ++$f8                   ;otherwise move sprite offscreen, this part likely
  11463.          stay Sprite_Y_Position+12,y ;residual since flame is only made of three sprites
  11464. M3FOfs:  pla                        ;get bits from stack
  11465.          lsr                        ;move d1 to carry and move bits back to stack
  11466.          pha
  11467.          bcc M2FOfs                 ;branch if carry not set again
  11468.          ldan ++$f8                   ;otherwise move third sprite offscreen
  11469.          stay Sprite_Y_Position+8,y
  11470. M2FOfs:  pla                        ;get bits from stack again
  11471.          lsr                        ;move d2 to carry and move bits back to stack again
  11472.          pha
  11473.          bcc M1FOfs                 ;branch if carry not set yet again
  11474.          ldan ++$f8                   ;otherwise move second sprite offscreen
  11475.          stay Sprite_Y_Position+4,y
  11476. M1FOfs:  pla                        ;get bits from stack one last time
  11477.          lsr                        ;move d3 to carry
  11478.          bcc ExFlmeD                ;branch if carry not set one last time
  11479.          ldan ++$f8
  11480.          stay Sprite_Y_Position,y    ;otherwise move first sprite offscreen
  11481. ExFlmeD: rts                        ;leave
  11482.  
  11483. ;--------------------------------
  11484.  
  11485. RunFireworks:
  11486.            decx ExplosionTimerCounter,x ;decrement explosion timing counter here
  11487.            bne SetupExpl               ;if not expired, skip this part
  11488.            ldan ++$08
  11489.            stax ExplosionTimerCounter,x ;reset counter
  11490.            incx ExplosionGfxCounter,x   ;increment explosion graphics counter
  11491.            ldax ExplosionGfxCounter,x
  11492.            cmpn ++$03                    ;check explosion graphics counter
  11493.               cmpcy
  11494.            bcs FireworksSoundScore     ;if at a certain point, branch to kill this object
  11495. SetupExpl: jsr RelativeEnemyPosition   ;get relative coordinates of explosion
  11496.            lda Enemy_Rel_YPos          ;copy relative coordinates
  11497.            sta Fireball_Rel_YPos       ;from the enemy object to the fireball object
  11498.            lda Enemy_Rel_XPos          ;first vertical, then horizontal
  11499.            sta Fireball_Rel_XPos
  11500.            ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  11501.            ldax ExplosionGfxCounter,x   ;get explosion graphics counter
  11502.            jsr DrawExplosion_Fireworks ;do a sub to draw the explosion then leave
  11503.            rts
  11504.  
  11505. FireworksSoundScore:
  11506.       ldan ++$00               ;disable enemy buffer flag
  11507.       stax Enemy_Flag,x
  11508.       ldan ++Sfx_Blast         ;play fireworks/gunfire sound
  11509.       sta Square2SoundQueue
  11510.       ldan ++$05               ;set part of score modifier for 500 points
  11511.       sta DigitModifier+4
  11512.       jmp EndAreaPoints     ;jump to award points accordingly then leave
  11513.  
  11514. ;--------------------------------
  11515.  
  11516. StarFlagYPosAdder:
  11517.       .db $00, $00, $08, $08
  11518.  
  11519. StarFlagXPosAdder:
  11520.       .db $00, $08, $00, $08
  11521.  
  11522. StarFlagTileData:
  11523.       .db $54, $55, $56, $57
  11524.  
  11525. RunStarFlagObj:
  11526.       ldan ++$00                 ;initialize enemy frenzy buffer
  11527.       sta EnemyFrenzyBuffer
  11528.       lda StarFlagTaskControl  ;check star flag object task number here
  11529.       cmpn ++$05                 ;if greater than 5, branch to exit
  11530.               cmpcy
  11531.       bcs StarFlagExit
  11532.       jsr JumpEngine           ;otherwise jump to appropriate sub
  11533.      
  11534.       .dw StarFlagExit
  11535.       .dw GameTimerFireworks
  11536.       .dw AwardGameTimerPoints
  11537.       .dw RaiseFlagSetoffFWorks
  11538.       .dw DelayToAreaEnd
  11539.  
  11540. GameTimerFireworks:
  11541.         ldyn ++$05               ;set default state for star flag object
  11542.         lda GameTimerDisplay+2 ;get game timer's last digit
  11543.         cmpn ++$01
  11544.         beq SetFWC             ;if last digit of game timer set to 1, skip ahead
  11545.         ldyn ++$03               ;otherwise load new value for state
  11546.         cmpn ++$03
  11547.         beq SetFWC             ;if last digit of game timer set to 3, skip ahead
  11548.         ldyn ++$00               ;otherwise load one more potential value for state
  11549.         cmpn ++$06
  11550.         beq SetFWC             ;if last digit of game timer set to 6, skip ahead
  11551.         ldan ++$ff               ;otherwise set value for no fireworks
  11552. SetFWC: sta FireworksCounter   ;set fireworks counter here
  11553.         styx Enemy_State,x      ;set whatever state we have in star flag object
  11554.  
  11555. IncrementSFTask1:
  11556.       inci StarFlagTaskControl  ;increment star flag object task number
  11557.  
  11558. StarFlagExit:
  11559.       rts                      ;leave
  11560.  
  11561. AwardGameTimerPoints:
  11562.          lda GameTimerDisplay   ;check all game timer digits for any intervals left
  11563.          orai GameTimerDisplay+1
  11564.          orai GameTimerDisplay+2
  11565.          beq IncrementSFTask1   ;if no time left on game timer at all, branch to next task
  11566.          lda FrameCounter
  11567.          andn ++%00000100         ;check frame counter for d2 set (skip ahead
  11568.          beq NoTTick            ;for four frames every four frames) branch if not set
  11569.          ldan ++Sfx_TimerTick
  11570.          sta Square2SoundQueue  ;load timer tick sound
  11571. NoTTick: ldyn ++GameTimerDisplay-DisplayDigits+2;++$23               ;set offset here to subtract from game timer's last digit
  11572.          ldan ++$ff               ;set adder here to $ff, or -1, to subtract one
  11573.          sta DigitModifier+5    ;from the last digit of the game timer
  11574.          jsr DigitsMathRoutine  ;subtract digit
  11575.          ldan ++$05               ;set now to add 50 points
  11576.          sta DigitModifier+5    ;per game timer interval subtracted
  11577.  
  11578. EndAreaPoints:
  11579.          ldyn ++$0b               ;load offset for mario's score by default
  11580.          lda CurrentPlayer      ;check player on the screen
  11581.          checka
  11582.          beq ELPGive            ;if mario, do not change
  11583.          ldyn ++$11               ;otherwise load offset for luigi's score
  11584. ELPGive: jsr DigitsMathRoutine  ;award 50 points per game timer interval
  11585.          lda CurrentPlayer      ;get player on the screen (or 500 points per
  11586.          asl                    ;fireworks explosion if branched here from there)
  11587.          asl                    ;shift to high nybble
  11588.          asl
  11589.          asl
  11590.          oran ++%00000100         ;add four to set nybble for game timer
  11591.          jmp UpdateNumber       ;jump to print the new score and game timer
  11592.  
  11593. RaiseFlagSetoffFWorks:
  11594.          ldax Enemy_Y_Position,x  ;check star flag's vertical position
  11595.          cmpn ++$72                ;against preset value
  11596.               cmpcy
  11597.          bcc SetoffF             ;if star flag higher vertically, branch to other code
  11598.          decx Enemy_Y_Position,x  ;otherwise, raise star flag by one pixel
  11599.          jmp DrawStarFlag        ;and skip this part here
  11600. SetoffF: lda FireworksCounter    ;check fireworks counter
  11601.          checka
  11602.          beq DrawFlagSetTimer    ;if no fireworks left to go off, skip this part
  11603.          bmi DrawFlagSetTimer    ;if no fireworks set to go off, skip this part
  11604.          ldan ++Fireworks
  11605.          sta EnemyFrenzyBuffer   ;otherwise set fireworks object in frenzy queue
  11606.  
  11607. DrawStarFlag:
  11608.          jsr RelativeEnemyPosition  ;get relative coordinates of star flag
  11609.          ldyx Enemy_SprDataOffset,x  ;get OAM data offset
  11610.          ldxn ++$03                   ;do four sprites
  11611. DSFLoop: lda Enemy_Rel_YPos         ;get relative vertical coordinate
  11612.          clc
  11613.          adcx StarFlagYPosAdder,x    ;add Y coordinate adder data
  11614.          stay Sprite_Y_Position,y    ;store as Y coordinate
  11615.          ldax StarFlagTileData,x     ;get tile number
  11616.          stay Sprite_Tilenumber,y    ;store as tile number
  11617.          ldan ++$22                   ;set palette and background priority bits
  11618.          stay Sprite_Attributes,y    ;store as attributes
  11619.          lda Enemy_Rel_XPos         ;get relative horizontal coordinate
  11620.          clc
  11621.          adcx StarFlagXPosAdder,x    ;add X coordinate adder data
  11622.          stay Sprite_X_Position,y    ;store as X coordinate
  11623.          iny
  11624.          iny                        ;increment OAM data offset four bytes
  11625.          iny                        ;for next sprite
  11626.          iny
  11627.          dex                        ;move onto next sprite
  11628.          bpl DSFLoop                ;do this until all sprites are done
  11629.          ldx ObjectOffset           ;get enemy object offset and leave
  11630.          rts
  11631.  
  11632. DrawFlagSetTimer:
  11633.       jsr DrawStarFlag          ;do sub to draw star flag
  11634.       ldan ++$06
  11635.       stax EnemyIntervalTimer,x  ;set interval timer here
  11636.  
  11637. IncrementSFTask2:
  11638.       inci StarFlagTaskControl   ;move onto next task
  11639.       rts
  11640.  
  11641. DelayToAreaEnd:
  11642.       jsr DrawStarFlag          ;do sub to draw star flag
  11643.       ldax EnemyIntervalTimer,x  ;if interval timer set in previous task
  11644.          checka
  11645.       bne StarFlagExit2         ;not yet expired, branch to leave
  11646.      
  11647. ;ъюёЄ√ы№: ¤Єю ьхёЄю ьх°рхЄ яЁхфёърчєхьюёЄш яЁш MUSICONINT=1
  11648.         if MUSICONINT
  11649.       lda EventMusicBuffer      ;if event music buffer empty,
  11650.          checka
  11651.      ret nz
  11652.     ;ld hl,(EventMusicQueue_noint)      ;if event music buffer empty,
  11653.     ;jr $ ;hl=fdcb/fdd0/fe2b/ (fdc9/fdce/fe29/fde0)
  11654.                ;ld a,(WorldNumber)           ;check world number
  11655.                ;cp ++World4;8
  11656.                ;jr nc,IncrementSFTask2 ;юс√ўэ√щ ъюёЄ√ы№ эх яюьюурхЄ эр 8-2... ¤ЄюЄ Єюцх!
  11657.      ld hl,SoundEngine_noint
  11658.      ld (soundenginepatch),hl ;тючтЁр∙рхь MUSICONINT=1
  11659.      ld a,0xcd
  11660.      ld (soundenginecall),a ;тючтЁр∙рхь MUSICONINT=1
  11661.      jr IncrementSFTask2      ;branch to increment task
  11662.         else
  11663.       lda EventMusicBuffer      ;if event music buffer empty,
  11664.          checka
  11665.       beq IncrementSFTask2      ;branch to increment task
  11666.         endif
  11667.  
  11668. StarFlagExit2:
  11669.       rts                       ;otherwise leave
  11670.  
  11671. ;--------------------------------
  11672. ;$00 - used to store horizontal difference between player and piranha plant
  11673.  
  11674. MovePiranhaPlant:
  11675.       ldax Enemy_State,x           ;check enemy state
  11676.          checka
  11677.       bne PutinPipe               ;if set at all, branch to leave
  11678.       ldax EnemyFrameTimer,x       ;check enemy's timer here
  11679.          checka
  11680.       bne PutinPipe               ;branch to end if not yet expired
  11681.       ldax PiranhaPlant_MoveFlag,x ;check movement flag
  11682.          checka
  11683.       bne SetupToMovePPlant       ;if moving, skip to part ahead
  11684.       ldax PiranhaPlant_Y_Speed,x  ;if currently rising, branch
  11685.          checka
  11686.       bmi ReversePlantSpeed       ;to move enemy upwards out of pipe
  11687.       jsr PlayerEnemyDiff         ;get horizontal difference between player and
  11688.       bpl ChkPlayerNearPipe       ;piranha plant, and branch if enemy to right of player
  11689.       lda SCRATCHPAD+$00                     ;otherwise get saved horizontal difference
  11690.       eorn ++$ff
  11691.       clc                         ;and change to two's compliment
  11692.       adcn ++$01
  11693.       sta SCRATCHPAD+$00                     ;save as new horizontal difference
  11694.  
  11695. ChkPlayerNearPipe:
  11696.       lda SCRATCHPAD+$00                     ;get saved horizontal difference
  11697.       cmpn ++$21
  11698.               cmpcy
  11699.       bcc PutinPipe               ;if player within a certain distance, branch to leave
  11700.  
  11701. ReversePlantSpeed:
  11702.       ldax PiranhaPlant_Y_Speed,x  ;get vertical speed
  11703.       eorn ++$ff
  11704.       clc                         ;change to two's compliment
  11705.       adcn ++$01
  11706.       stax PiranhaPlant_Y_Speed,x  ;save as new vertical speed
  11707.       incx PiranhaPlant_MoveFlag,x ;increment to set movement flag
  11708.  
  11709. SetupToMovePPlant:
  11710.       ldax PiranhaPlantDownYPos,x  ;get original vertical coordinate (lowest point)
  11711.       ldyx PiranhaPlant_Y_Speed,x  ;get vertical speed
  11712.          checky
  11713.       bpl RiseFallPiranhaPlant    ;branch if moving downwards
  11714.       ldax PiranhaPlantUpYPos,x    ;otherwise get other vertical coordinate (highest point)
  11715.  
  11716. RiseFallPiranhaPlant:
  11717.       sta SCRATCHPAD+$00                     ;save vertical coordinate here
  11718.       lda FrameCounter            ;get frame counter
  11719.       lsr
  11720.       bcc PutinPipe               ;branch to leave if d0 set (execute code every other frame)
  11721.       lda TimerControl            ;get master timer control
  11722.          checka
  11723.       bne PutinPipe               ;branch to leave if set (likely not necessary)
  11724.       ldax Enemy_Y_Position,x      ;get current vertical coordinate
  11725.       clc
  11726.       adcx PiranhaPlant_Y_Speed,x  ;add vertical speed to move up or down
  11727.       stax Enemy_Y_Position,x      ;save as new vertical coordinate
  11728.       cmpi SCRATCHPAD+$00                     ;compare against low or high coordinate
  11729.       bne PutinPipe               ;branch to leave if not yet reached
  11730.       ldan ++$00
  11731.       stax PiranhaPlant_MoveFlag,x ;otherwise clear movement flag
  11732.       ldan ++$40
  11733.       stax EnemyFrameTimer,x       ;set timer to delay piranha plant movement
  11734.  
  11735. PutinPipe:
  11736.       ldan ++%00100000              ;set background priority bit in sprite
  11737.       stax Enemy_SprAttrib,x       ;attributes to give illusion of being inside pipe
  11738.       rts                         ;then leave
  11739.  
  11740. ;-------------------------------------------------------------------------------------
  11741. ;$07 - spinning speed
  11742.  
  11743. FirebarSpin:
  11744.       sta SCRATCHPAD+$07                     ;save spinning speed here
  11745.       ldax FirebarSpinDirection,x  ;check spinning direction
  11746.          checka
  11747.       bne SpinCounterClockwise    ;if moving counter-clockwise, branch to other part
  11748.       ldyn ++$18                    ;possibly residual ldy
  11749.       ldax FirebarSpinState_Low,x
  11750.       clc                         ;add spinning speed to what would normally be
  11751.       adci SCRATCHPAD+$07                     ;the horizontal speed
  11752.           push af
  11753.       stax FirebarSpinState_Low,x
  11754.       ldax FirebarSpinState_High,x ;add carry to what would normally be the vertical speed
  11755.           ld h,a
  11756.           pop af
  11757.           ld a,h
  11758.       adcn ++$00
  11759.       rts
  11760.  
  11761. SpinCounterClockwise:
  11762.       ldyn ++$08                    ;possibly residual ldy
  11763.       ldax FirebarSpinState_Low,x
  11764.       secsub                         ;subtract spinning speed to what would normally be
  11765.       sbci SCRATCHPAD+$07                     ;the horizontal speed
  11766.           push af
  11767.       stax FirebarSpinState_Low,x
  11768.       ldax FirebarSpinState_High,x ;add carry to what would normally be the vertical speed
  11769.           ld h,a
  11770.           pop af
  11771.           ld a,h
  11772.       sbcn ++$00
  11773.       rts
  11774.  
  11775. ;-------------------------------------------------------------------------------------
  11776. ;$00 - used to hold collision flag, Y movement force + 5 or low byte of name table for rope
  11777. ;$01 - used to hold high byte of name table for rope
  11778. ;$02 - used to hold page location of rope
  11779.  
  11780. BalancePlatform:
  11781.        ldax Enemy_Y_HighPos,x       ;check high byte of vertical position
  11782.        cmpn ++$03
  11783.        bne DoBPl
  11784.        jmp EraseEnemyObject        ;if far below screen, kill the object
  11785. DoBPl: ldax Enemy_State,x           ;get object's state (set to $ff or other platform offset)
  11786.          checka
  11787.        bpl CheckBalPlatform        ;if doing other balance platform, branch to leave
  11788.        rts
  11789.  
  11790. CheckBalPlatform:
  11791.        tay                         ;save offset from state as Y
  11792.        ldax PlatformCollisionFlag,x ;get collision flag of platform
  11793.        sta SCRATCHPAD+$00                     ;store here
  11794.        ldax Enemy_MovingDir,x       ;get moving direction
  11795.          checka
  11796.        beq ChkForFall
  11797.        jmp PlatformFall            ;if set, jump here
  11798.  
  11799. ChkForFall:
  11800.        ldan ++$2d                    ;check if platform is above a certain point
  11801.        cmpx Enemy_Y_Position,x
  11802.               cmpcy
  11803.        bcc ChkOtherForFall         ;if not, branch elsewhere
  11804.        cpyi SCRATCHPAD+$00                     ;if collision flag is set to same value as
  11805.        beq MakePlatformFall        ;enemy state, branch to make platforms fall
  11806.        clc
  11807.        adcn ++$02                    ;otherwise add 2 pixels to vertical position
  11808.        stax Enemy_Y_Position,x      ;of current platform and branch elsewhere
  11809.        jmp StopPlatforms           ;to make platforms stop
  11810.  
  11811. MakePlatformFall:
  11812.        jmp InitPlatformFall        ;make platforms fall
  11813.  
  11814. ChkOtherForFall:
  11815.        cmpy Enemy_Y_Position,y      ;check if other platform is above a certain point
  11816.               cmpcy
  11817.        bcc ChkToMoveBalPlat        ;if not, branch elsewhere
  11818.        cpxi SCRATCHPAD+$00                     ;if collision flag is set to same value as
  11819.        beq MakePlatformFall        ;enemy state, branch to make platforms fall
  11820.        clc
  11821.        adcn ++$02                    ;otherwise add 2 pixels to vertical position
  11822.        stay Enemy_Y_Position,y      ;of other platform and branch elsewhere
  11823.        jmp StopPlatforms           ;jump to stop movement and do not return
  11824.  
  11825. ChkToMoveBalPlat:
  11826.         ldax Enemy_Y_Position,x      ;save vertical position to stack
  11827.         pha
  11828.         ldax PlatformCollisionFlag,x ;get collision flag
  11829.          checka
  11830.         bpl ColFlg                  ;branch if collision
  11831.         ldax Enemy_Y_MoveForce,x
  11832.         clc                         ;add $05 to contents of moveforce, whatever they be
  11833.         adcn ++$05
  11834.         sta SCRATCHPAD+$00                     ;store here
  11835.         ldaxkeepcy Enemy_Y_Speed,x
  11836.         adcn ++$00                    ;add carry to vertical speed
  11837.         bmi PlatDn                  ;branch if moving downwards
  11838.         bne PlatUp                  ;branch elsewhere if moving upwards
  11839.         lda SCRATCHPAD+$00
  11840.         cmpn ++$0b                    ;check if there's still a little force left
  11841.               cmpcy
  11842.         bcc PlatSt                  ;if not enough, branch to stop movement
  11843.         bcs PlatUp                  ;otherwise keep branch to move upwards
  11844. ColFlg: cmpi ObjectOffset            ;if collision flag matches
  11845.         beq PlatDn                  ;current enemy object offset, branch
  11846. PlatUp: jsr MovePlatformUp          ;do a sub to move upwards
  11847.         jmp DoOtherPlatform         ;jump ahead to remaining code
  11848. PlatSt: jsr StopPlatforms           ;do a sub to stop movement
  11849.         jmp DoOtherPlatform         ;jump ahead to remaining code
  11850. PlatDn: jsr MovePlatformDown        ;do a sub to move downwards
  11851.  
  11852. DoOtherPlatform:
  11853.        ldyx Enemy_State,x           ;get offset of other platform
  11854.        pla                         ;get old vertical coordinate from stack
  11855.        secsub
  11856.        sbcx Enemy_Y_Position,x      ;get difference of old vs. new coordinate
  11857.        clc
  11858.        adcy Enemy_Y_Position,y      ;add difference to vertical coordinate of other
  11859.        stay Enemy_Y_Position,y      ;platform to move it in the opposite direction
  11860.        ldax PlatformCollisionFlag,x ;if no collision, skip this part here
  11861.          checka
  11862.        bmi DrawEraseRope
  11863.        tax                         ;put offset which collision occurred here
  11864.        jsr PositionPlayerOnVPlat   ;and use it to position player accordingly
  11865.  
  11866. DrawEraseRope:
  11867.          ldy ObjectOffset            ;get enemy object offset
  11868.          lday Enemy_Y_Speed,y         ;check to see if current platform is
  11869.          oray Enemy_Y_MoveForce,y     ;moving at all
  11870.          beq ExitRp                  ;if not, skip all of this and branch to leave
  11871.          ldx VRAM_Buffer1_Offset     ;get vram buffer offset
  11872.          cpxn ++$20                    ;if offset beyond a certain point, go ahead
  11873.               cmpcy
  11874.          bcs ExitRp                  ;and skip this, branch to leave
  11875.          lday Enemy_Y_Speed,y
  11876.          pha                         ;save two copies of vertical speed to stack
  11877.          pha
  11878.          jsr SetupPlatformRope       ;do a sub to figure out where to put new bg tiles
  11879.          lda SCRATCHPAD+$01                     ;write name table address to vram buffer
  11880.          stax VRAM_Buffer1,x          ;first the high byte, then the low
  11881.          lda SCRATCHPAD+$00
  11882.          stax VRAM_Buffer1+1,x
  11883.          ldan ++$02                    ;set length for 2 bytes
  11884.          stax VRAM_Buffer1+2,x
  11885.          lday Enemy_Y_Speed,y         ;if platform moving upwards, branch
  11886.          checka
  11887.          bmi EraseR1                 ;to do something else
  11888.          ldan ++xa2
  11889.          stax VRAM_Buffer1+3,x        ;otherwise put tile numbers for left
  11890.          ldan ++xa3                    ;and right sides of rope in vram buffer
  11891.          stax VRAM_Buffer1+4,x
  11892.          jmp OtherRope               ;jump to skip this part
  11893. EraseR1: ldan ++$24                    ;put blank tiles in vram buffer
  11894.          stax VRAM_Buffer1+3,x        ;to erase rope
  11895.          stax VRAM_Buffer1+4,x
  11896.  
  11897. OtherRope:
  11898.          lday Enemy_State,y           ;get offset of other platform from state
  11899.          tay                         ;use as Y here
  11900.          pla                         ;pull second copy of vertical speed from stack
  11901.          eorn ++$ff                    ;invert bits to reverse speed
  11902.          jsr SetupPlatformRope       ;do sub again to figure out where to put bg tiles  
  11903.          lda SCRATCHPAD+$01                     ;write name table address to vram buffer
  11904.          stax VRAM_Buffer1+5,x        ;this time we're doing putting tiles for
  11905.          lda SCRATCHPAD+$00                     ;the other platform
  11906.          stax VRAM_Buffer1+6,x
  11907.          ldan ++$02
  11908.          stax VRAM_Buffer1+7,x        ;set length again for 2 bytes
  11909.          pla                         ;pull first copy of vertical speed from stack
  11910.          checka
  11911.          bpl EraseR2                 ;if moving upwards (note inversion earlier), skip this
  11912.          ldan ++xa2
  11913.          stax VRAM_Buffer1+8,x        ;otherwise put tile numbers for left
  11914.          ldan ++xa3                    ;and right sides of rope in vram
  11915.          stax VRAM_Buffer1+9,x        ;transfer buffer
  11916.          jmp EndRp                   ;jump to skip this part
  11917. EraseR2: ldan ++$24                    ;put blank tiles in vram buffer
  11918.          stax VRAM_Buffer1+8,x        ;to erase rope
  11919.          stax VRAM_Buffer1+9,x
  11920. EndRp:   ldan ++$00                    ;put null terminator at the end
  11921.          stax VRAM_Buffer1+10,x
  11922.          lda VRAM_Buffer1_Offset     ;add ten bytes to the vram buffer offset
  11923.          clc                         ;and store
  11924.          adcn ++10
  11925.          sta VRAM_Buffer1_Offset
  11926. ExitRp:  ldx ObjectOffset            ;get enemy object buffer offset and leave
  11927.          rts
  11928.  
  11929. SetupPlatformRope:
  11930.         pha                     ;save second/third copy to stack
  11931.         lday Enemy_X_Position,y  ;get horizontal coordinate
  11932.         clc
  11933.         adcn ++$08                ;add eight pixels
  11934.         ldx SecondaryHardMode   ;if secondary hard mode flag set,
  11935.          checkx
  11936.         bne GetLRp              ;use coordinate as-is
  11937.         clc
  11938.         adcn ++$10                ;otherwise add sixteen more pixels
  11939. GetLRp: pha                     ;save modified horizontal coordinate to stack
  11940.         ldaykeepcy Enemy_PageLoc,y
  11941.         adcn ++$00                ;add carry to page location
  11942.         sta SCRATCHPAD+$02                 ;and save here
  11943.         pla                     ;pull modified horizontal coordinate
  11944.         andn ++%11110000          ;from the stack, mask out low nybble
  11945.         lsr                     ;and shift three bits to the right
  11946.         lsr
  11947.         lsr
  11948.         sta SCRATCHPAD+$00                 ;store result here as part of name table low byte
  11949.         ldxy Enemy_Y_Position,y  ;get vertical coordinate
  11950.         pla                     ;get second/third copy of vertical speed from stack
  11951.          checka
  11952.         bpl GetHRp              ;skip this part if moving downwards or not at all
  11953.         txa
  11954.         clc
  11955.         adcn ++$08                ;add eight to vertical coordinate and
  11956.         tax                     ;save as X
  11957. GetHRp: txa                     ;move vertical coordinate to A
  11958.         ldx VRAM_Buffer1_Offset ;get vram buffer offset
  11959.         asl
  11960.         rol                     ;rotate d7 to d0 and d6 into carry
  11961.         pha                     ;save modified vertical coordinate to stack
  11962.         rol                     ;rotate carry to d0, thus d7 and d6 are at 2 LSB
  11963.         andn ++%00000011          ;mask out all bits but d7 and d6, then set
  11964.         oran ++%00100000          ;d5 to get appropriate high byte of name table
  11965.         sta SCRATCHPAD+$01                 ;address, then store
  11966.         lda SCRATCHPAD+$02                 ;get saved page location from earlier
  11967.         andn ++$01                ;mask out all but LSB
  11968.         asl
  11969.         asl                     ;shift twice to the left and save with the
  11970.         orai SCRATCHPAD+$01                 ;rest of the bits of the high byte, to get
  11971.         sta SCRATCHPAD+$01                 ;the proper name table and the right place on it
  11972.         pla                     ;get modified vertical coordinate from stack
  11973.         andn ++%11100000          ;mask out low nybble and LSB of high nybble
  11974.         clc
  11975.         adci SCRATCHPAD+$00                 ;add to horizontal part saved here
  11976.         sta SCRATCHPAD+$00                 ;save as name table low byte
  11977.         lday Enemy_Y_Position,y
  11978.         cmpn ++$e8                ;if vertical position not below the
  11979.               cmpcy
  11980.         bcc ExPRp               ;bottom of the screen, we're done, branch to leave
  11981.         lda SCRATCHPAD+$00
  11982.         andn ++%10111111          ;mask out d6 of low byte of name table address
  11983.         sta SCRATCHPAD+$00
  11984. ExPRp:  rts                     ;leave!
  11985.  
  11986. InitPlatformFall:
  11987.       tya                        ;move offset of other platform from Y to X
  11988.       tax
  11989.       jsr GetEnemyOffscreenBits  ;get offscreen bits
  11990.       ldan ++$06
  11991.       jsr SetupFloateyNumber     ;award 1000 points to player
  11992.       lda Player_Rel_XPos
  11993.       stax FloateyNum_X_Pos,x     ;put floatey number coordinates where player is
  11994.       lda Player_Y_Position
  11995.       stax FloateyNum_Y_Pos,x
  11996.       ldan ++$01                   ;set moving direction as flag for
  11997.       stax Enemy_MovingDir,x      ;falling platforms
  11998.  
  11999. StopPlatforms:
  12000.       jsr InitVStf             ;initialize vertical speed and low byte
  12001.       stay Enemy_Y_Speed,y      ;for both platforms and leave
  12002.       stay Enemy_Y_MoveForce,y
  12003.       rts
  12004.  
  12005. PlatformFall:
  12006.       tya                         ;save offset for other platform to stack
  12007.       pha
  12008.       jsr MoveFallingPlatform     ;make current platform fall
  12009.       pla
  12010.       tax                         ;pull offset from stack and save to X
  12011.       jsr MoveFallingPlatform     ;make other platform fall
  12012.       ldx ObjectOffset
  12013.       ldax PlatformCollisionFlag,x ;if player not standing on either platform,
  12014.          checka
  12015.       bmi ExPF                    ;skip this part
  12016.       tax                         ;transfer collision flag offset as offset to X
  12017.       jsr PositionPlayerOnVPlat   ;and position player appropriately
  12018. ExPF: ldx ObjectOffset            ;get enemy object buffer offset and leave
  12019.       rts
  12020.  
  12021. ;--------------------------------
  12022.  
  12023. YMovingPlatform:
  12024.         ldax Enemy_Y_Speed,x          ;if platform moving up or down, skip ahead to
  12025.         orax Enemy_Y_MoveForce,x      ;check on other position
  12026.         bne ChkYCenterPos
  12027.         stax Enemy_YMF_Dummy,x        ;initialize dummy variable
  12028.         ldax Enemy_Y_Position,x
  12029.         cmpx YPlatformTopYPos,x       ;if current vertical position =HIGH  top position, branch
  12030.               cmpcy
  12031.         bcs ChkYCenterPos            ;ahead of all this
  12032.         lda FrameCounter
  12033.         andn ++%00000111               ;check for every eighth frame
  12034.         bne SkipIY
  12035.         incx Enemy_Y_Position,x       ;increase vertical position every eighth frame
  12036. SkipIY: jmp ChkYPCollision           ;skip ahead to last part
  12037.  
  12038. ChkYCenterPos:
  12039.         ldax Enemy_Y_Position,x       ;if current vertical position LOW  central position, branch
  12040.         cmpx YPlatformCenterYPos,x    ;to slow ascent/move downwards
  12041.               cmpcy
  12042.         bcc YMDown
  12043.         jsr MovePlatformUp           ;otherwise start slowing descent/moving upwards
  12044.         jmp ChkYPCollision
  12045. YMDown: jsr MovePlatformDown         ;start slowing ascent/moving downwards
  12046.  
  12047. ChkYPCollision:
  12048.        ldax PlatformCollisionFlag,x  ;if collision flag not set here, branch
  12049.          checka
  12050.        bmi ExYPl                    ;to leave
  12051.        jsr PositionPlayerOnVPlat    ;otherwise position player appropriately
  12052. ExYPl: rts                          ;leave
  12053.  
  12054. ;--------------------------------
  12055. ;$00 - used as adder to position player hotizontally
  12056.  
  12057. XMovingPlatform:
  12058.       ldan ++$0e                     ;load preset maximum value for secondary counter
  12059.       jsr XMoveCntr_Platform       ;do a sub to increment counters for movement
  12060.       jsr MoveWithXMCntrs          ;do a sub to move platform accordingly, and return value
  12061.       ldax PlatformCollisionFlag,x  ;if no collision with player,
  12062.          checka
  12063.       bmi ExXMP                    ;branch ahead to leave
  12064.  
  12065. PositionPlayerOnHPlat:
  12066.          lda Player_X_Position
  12067.          clc                       ;add saved value from second subroutine to
  12068.          adci SCRATCHPAD+$00                   ;current player's position to position (яЁшсрты хь ёьх∙хэшх шуЁюър яю X юЄэюёшЄхы№эю яЁю°ыюую Ёрчр)
  12069.          sta Player_X_Position     ;player accordingly in horizontal position
  12070.          lda Player_PageLoc        ;get player's page location
  12071.          ldy SCRATCHPAD+$00                   ;check to see if saved value here is positive or negative
  12072.          checky
  12073.          bmi PPHSubt               ;if negative, branch to subtract
  12074.          adcn ++$00                  ;otherwise add carry to page location
  12075.          jmp SetPVar               ;jump to skip subtraction
  12076. PPHSubt:
  12077.         cmpcy
  12078.          sbcn ++$00                  ;subtract borrow from page location
  12079. SetPVar: sta Player_PageLoc        ;save result to player's page location
  12080.          sty Platform_X_Scroll     ;put saved value from second sub here to be used later
  12081.          jsr PositionPlayerOnVPlat ;position player vertically and appropriately
  12082. ExXMP:   rts                       ;and we are done here
  12083.  
  12084. ;--------------------------------
  12085.  
  12086. DropPlatform:
  12087.        ldax PlatformCollisionFlag,x  ;if no collision between platform and player
  12088.          checka
  12089.        bmi ExDPl                    ;occurred, just leave without moving anything
  12090.        jsr MoveDropPlatform         ;otherwise do a sub to move platform down very quickly
  12091.        jsr PositionPlayerOnVPlat    ;do a sub to position player appropriately
  12092. ExDPl: rts                          ;leave
  12093.  
  12094. ;--------------------------------
  12095. ;$00 - residual value from sub
  12096.  
  12097. RightPlatform:
  12098.        jsr MoveEnemyHorizontally     ;move platform with current horizontal speed, if any
  12099.        sta SCRATCHPAD+$00                       ;store saved value here (residual code)
  12100.        ldax PlatformCollisionFlag,x   ;check collision flag, if no collision between player
  12101.          checka
  12102.        bmi ExRPl                     ;and platform, branch ahead, leave speed unaltered
  12103.        ldan ++$10
  12104.        stax Enemy_X_Speed,x           ;otherwise set new speed (gets moving if motionless)
  12105.        jsr PositionPlayerOnHPlat     ;use saved value from earlier sub to position player
  12106. ExRPl: rts                           ;then leave
  12107.  
  12108. ;--------------------------------
  12109.  
  12110. MoveLargeLiftPlat:
  12111.       jsr MoveLiftPlatforms  ;execute common to all large and small lift platforms
  12112.       jmp ChkYPCollision     ;branch to position player correctly
  12113.  
  12114. MoveSmallPlatform:
  12115.       jsr MoveLiftPlatforms      ;execute common to all large and small lift platforms
  12116.       jmp ChkSmallPlatCollision  ;branch to position player correctly
  12117.  
  12118. MoveLiftPlatforms:
  12119.       lda TimerControl         ;if master timer control set, skip all of this
  12120.          checka
  12121.       bne ExLiftP              ;and branch to leave
  12122.       ldax Enemy_YMF_Dummy,x
  12123.       clc                      ;add contents of movement amount to whatever's here
  12124.       adcx Enemy_Y_MoveForce,x
  12125.           push af
  12126.       stax Enemy_YMF_Dummy,x
  12127.       ldax Enemy_Y_Position,x   ;add whatever vertical speed is set to current
  12128.           ld h,a
  12129.           pop af
  12130.           ld a,h
  12131.       adcx Enemy_Y_Speed,x      ;vertical position plus carry to move up or down
  12132.       stax Enemy_Y_Position,x   ;and then leave
  12133.       rts
  12134.  
  12135. ChkSmallPlatCollision:
  12136.          ldax PlatformCollisionFlag,x ;get bounding box counter saved in collision flag
  12137.          checka
  12138.          beq ExLiftP                 ;if none found, leave player position alone
  12139.          jsr PositionPlayerOnS_Plat  ;use to position player correctly
  12140. ExLiftP: rts                         ;then leave
  12141.  
  12142. ;-------------------------------------------------------------------------------------
  12143. ;$00 - page location of extended left boundary
  12144. ;$01 - extended left boundary position
  12145. ;$02 - page location of extended right boundary
  12146. ;$03 - extended right boundary position
  12147.  
  12148. OffscreenBoundsCheck:
  12149.           ldax Enemy_ID,x          ;check for cheep-cheep object
  12150.           cmpn ++FlyingCheepCheep   ;branch to leave if found
  12151.           beq ExScrnBd
  12152.           lda ScreenLeft_X_Pos    ;get horizontal coordinate for left side of screen
  12153.           ldyx Enemy_ID,x
  12154.           cpyn ++HammerBro          ;check for hammer bro object
  12155.           beq LimitB
  12156.           cpyn ++PiranhaPlant       ;check for piranha plant object
  12157.           bne ExtendLB            ;these two will be erased sooner than others if too far left
  12158. LimitB:  
  12159.         cmpcy
  12160.           adcn ++$38                ;add 56 pixels to coordinate if hammer bro or piranha plant
  12161.         cmpcy
  12162. ExtendLB:
  12163.           sbcn ++$48                ;subtract 72 pixels regardless of enemy object
  12164.           sta SCRATCHPAD+$01                 ;store result here
  12165.           lda ScreenLeft_PageLoc
  12166.           sbcn ++$00                ;subtract borrow from page location of left side
  12167.         cmpcy
  12168.           sta SCRATCHPAD+$00                 ;store result here
  12169.           lda ScreenRight_X_Pos   ;add 72 pixels to the right side horizontal coordinate
  12170.           adcn ++$48
  12171.           sta SCRATCHPAD+$03                 ;store result here
  12172.           lda ScreenRight_PageLoc    
  12173.           adcn ++$00                ;then add the carry to the page location
  12174.           sta SCRATCHPAD+$02                 ;and store result here
  12175.           ldax Enemy_X_Position,x  ;compare horizontal coordinate of the enemy object
  12176.           cmpi SCRATCHPAD+$01                 ;to modified horizontal left edge coordinate to get carry
  12177.           ldaxkeepcy Enemy_PageLoc,x
  12178.           sbci SCRATCHPAD+$00                 ;then subtract it from the page coordinate of the enemy object
  12179.           bmi TooFar              ;if enemy object is too far left, branch to erase it
  12180.           ldax Enemy_X_Position,x  ;compare horizontal coordinate of the enemy object
  12181.           cmpi SCRATCHPAD+$03                 ;to modified horizontal right edge coordinate to get carry
  12182.           ldaxkeepcy Enemy_PageLoc,x
  12183.           sbci SCRATCHPAD+$02                 ;then subtract it from the page coordinate of the enemy object
  12184.           bmi ExScrnBd            ;if enemy object is on the screen, leave, do not erase enemy
  12185.           ldax Enemy_State,x       ;if at this point, enemy is offscreen to the right, so check
  12186.           cmpn ++HammerBro          ;if in state used by spiny's egg, do not erase
  12187.           beq ExScrnBd
  12188.           cpyn ++PiranhaPlant       ;if piranha plant, do not erase
  12189.           beq ExScrnBd
  12190.           cpyn ++FlagpoleFlagObject ;if flagpole flag, do not erase
  12191.           beq ExScrnBd
  12192.           cpyn ++StarFlagObject     ;if star flag, do not erase
  12193.           beq ExScrnBd
  12194.           cpyn ++JumpspringObject   ;if jumpspring, do not erase
  12195.           beq ExScrnBd            ;erase all others too far to the right
  12196. TooFar:   jsr EraseEnemyObject    ;erase object if necessary
  12197. ExScrnBd: rts                     ;leave
  12198.  
  12199. ;-------------------------------------------------------------------------------------
  12200.  
  12201. ;some unused space
  12202.       .db $ff, $ff, $ff
  12203.  
  12204. ;-------------------------------------------------------------------------------------
  12205. ;$01 - enemy buffer offset
  12206.  
  12207. FireballEnemyCollision:
  12208.       ldax Fireball_State,x  ;check to see if fireball state is set at all
  12209.          checka
  12210.       beq ExitFBallEnemy    ;branch to leave if not
  12211.       asl
  12212.       bcs ExitFBallEnemy    ;branch to leave also if d7 in state is set
  12213.       lda FrameCounter
  12214.       lsr                   ;get LSB of frame counter
  12215.       bcs ExitFBallEnemy    ;branch to leave if set (do routine every other frame)
  12216.       txa
  12217.       asl                   ;multiply fireball offset by four
  12218.       asl
  12219.       clc
  12220.       adcn ++$1c              ;then add $1c or 28 bytes to it
  12221.       tay                   ;to use fireball's bounding box coordinates
  12222.       ldxn ++$04
  12223.  
  12224. FireballEnemyCDLoop:
  12225.            stx SCRATCHPAD+$01                     ;store enemy object offset here
  12226.            tya
  12227.            pha                         ;push fireball offset to the stack
  12228.            ldax Enemy_State,x
  12229.            andn ++%00100000              ;check to see if d5 is set in enemy state
  12230.            bne NoFToECol               ;if so, skip to next enemy slot
  12231.            ldax Enemy_Flag,x            ;check to see if buffer flag is set
  12232.          checka
  12233.            beq NoFToECol               ;if not, skip to next enemy slot
  12234.            ldax Enemy_ID,x              ;check enemy identifier
  12235.            cmpn ++$24
  12236.               cmpcy
  12237.            bcc GoombaDie               ;if LOW  $24, branch to check further
  12238.            cmpn ++$2b
  12239.               cmpcy
  12240.            bcc NoFToECol               ;if in range $24-$2a, skip to next enemy slot
  12241. GoombaDie: cmpn ++Goomba                 ;check for goomba identifier
  12242.            bne NotGoomba               ;if not found, continue with code
  12243.            ldax Enemy_State,x           ;otherwise check for defeated state
  12244.            cmpn ++$02                    ;if stomped or otherwise defeated,
  12245.               cmpcy
  12246.            bcs NoFToECol               ;skip to next enemy slot
  12247. NotGoomba: ldax EnemyOffscrBitsMasked,x ;if any masked offscreen bits set,
  12248.          checka
  12249.            bne NoFToECol               ;skip to next enemy slot
  12250.            txa
  12251.            asl                         ;otherwise multiply enemy offset by four
  12252.            asl
  12253.            clc
  12254.            adcn ++$04                    ;add 4 bytes to it
  12255.            tax                         ;to use enemy's bounding box coordinates
  12256.            jsr SprObjectCollisionCore  ;do fireball-to-enemy collision detection
  12257.            ldx ObjectOffset            ;return fireball's original offset
  12258.            bcc NoFToECol               ;if carry clear, no collision, thus do next enemy slot
  12259.            ldan ++%10000000
  12260.            stax Fireball_State,x        ;set d7 in enemy state
  12261.            ldx SCRATCHPAD+$01                     ;get enemy offset
  12262.            jsr HandleEnemyFBallCol     ;jump to handle fireball to enemy collision
  12263. NoFToECol: pla                         ;pull fireball offset from stack
  12264.            tay                         ;put it in Y
  12265.            ldx SCRATCHPAD+$01                     ;get enemy object offset
  12266.            dex                         ;decrement it
  12267.            bpl FireballEnemyCDLoop     ;loop back until collision detection done on all enemies
  12268.  
  12269. ExitFBallEnemy:
  12270.       ldx ObjectOffset                 ;get original fireball offset and leave
  12271.       rts
  12272.  
  12273. BowserIdentities:
  12274.       .db Goomba, GreenKoopa, BuzzyBeetle, Spiny, Lakitu, Bloober, HammerBro, Bowser
  12275.  
  12276. HandleEnemyFBallCol:
  12277.       jsr RelativeEnemyPosition  ;get relative coordinate of enemy
  12278.       ldx SCRATCHPAD+$01                    ;get current enemy object offset
  12279.       ldax Enemy_Flag,x           ;check buffer flag for d7 set
  12280.          checka
  12281.       bpl ChkBuzzyBeetle         ;branch if not set to continue
  12282.       andn ++%00001111             ;otherwise mask out high nybble and
  12283.       tax                        ;use low nybble as enemy offset
  12284.       ldax Enemy_ID,x
  12285.       cmpn ++Bowser                ;check enemy identifier for bowser
  12286.       beq HurtBowser             ;branch if found
  12287.       ldx SCRATCHPAD+$01                    ;otherwise retrieve current enemy offset
  12288.  
  12289. ChkBuzzyBeetle:
  12290.       ldax Enemy_ID,x
  12291.       cmpn ++BuzzyBeetle           ;check for buzzy beetle
  12292.       beq ExHCF                  ;branch if found to leave (buzzy beetles fireproof)
  12293.       cmpn ++Bowser                ;check for bowser one more time (necessary if d7 of flag was clear)
  12294.       bne ChkOtherEnemies        ;if not found, branch to check other enemies
  12295.  
  12296. HurtBowser:
  12297.           deci BowserHitPoints        ;decrement bowser's hit points
  12298.           bne ExHCF                  ;if bowser still has hit points, branch to leave
  12299.           jsr InitVStf               ;otherwise do sub to init vertical speed and movement force
  12300.           stax Enemy_X_Speed,x        ;initialize horizontal speed
  12301.           sta EnemyFrenzyBuffer      ;init enemy frenzy buffer
  12302.           ldan ++$fe
  12303.           stax Enemy_Y_Speed,x        ;set vertical speed to make defeated bowser jump a little
  12304.           ldy WorldNumber            ;use world number as offset
  12305.           lday BowserIdentities,y     ;get enemy identifier to replace bowser with
  12306.           stax Enemy_ID,x             ;set as new enemy identifier
  12307.           ldan ++$20                   ;set A to use starting value for state
  12308.           cpyn ++$03                   ;check to see if using offset of 3 or more
  12309.               cmpcy
  12310.           bcs SetDBSte               ;branch if so
  12311.           oran ++$03                   ;otherwise add 3 to enemy state
  12312. SetDBSte: stax Enemy_State,x          ;set defeated enemy state
  12313.           ldan ++Sfx_BowserFall
  12314.           sta Square2SoundQueue      ;load bowser defeat sound
  12315.           ldx SCRATCHPAD+$01                    ;get enemy offset
  12316.           ldan ++$09                   ;award 5000 points to player for defeating bowser
  12317.          checka
  12318.           bne EnemySmackScore        ;unconditional branch to award points
  12319.  
  12320. ChkOtherEnemies:
  12321.       cmpn ++BulletBill_FrenzyVar
  12322.       beq ExHCF                 ;branch to leave if bullet bill (frenzy variant)
  12323.       cmpn ++Podoboo      
  12324.       beq ExHCF                 ;branch to leave if podoboo
  12325.       cmpn ++$15      
  12326.               cmpcy
  12327.       bcs ExHCF                 ;branch to leave if identifier =HIGH  $15
  12328.  
  12329. ShellOrBlockDefeat:
  12330.       ldax Enemy_ID,x            ;check for piranha plant
  12331.       cmpn ++PiranhaPlant
  12332.        cmpcy
  12333.       bne StnE                  ;branch if not found
  12334.       ldaxkeepcy Enemy_Y_Position,x
  12335.       adcn ++$18                  ;add 24 pixels to enemy object's vertical position
  12336.       stax Enemy_Y_Position,x
  12337. StnE: jsr ChkToStunEnemies      ;do yet another sub
  12338.       ldax Enemy_State,x
  12339.       andn ++%00011111            ;mask out 2 MSB of enemy object's state
  12340.       oran ++%00100000            ;set d5 to defeat enemy and save as new state
  12341.       stax Enemy_State,x
  12342.       ldan ++$02                  ;award 200 points by default
  12343.       ldyx Enemy_ID,x            ;check for hammer bro
  12344.       cpyn ++HammerBro
  12345.       bne GoombaPoints          ;branch if not found
  12346.       ldan ++$06                  ;award 1000 points for hammer bro
  12347.  
  12348. GoombaPoints:
  12349.       cpyn ++Goomba               ;check for goomba
  12350.       bne EnemySmackScore       ;branch if not found
  12351.       ldan ++$01                  ;award 100 points for goomba
  12352.  
  12353. EnemySmackScore:
  12354.        jsr SetupFloateyNumber   ;update necessary score variables
  12355.        ldan ++Sfx_EnemySmack      ;play smack enemy sound
  12356.        sta Square1SoundQueue
  12357. ExHCF: rts                      ;and now let's leave
  12358.  
  12359. ;-------------------------------------------------------------------------------------
  12360.  
  12361. PlayerHammerCollision:
  12362.         lda FrameCounter          ;get frame counter
  12363.         lsr                       ;shift d0 into carry
  12364.         bcc ExPHC                 ;branch to leave if d0 not set to execute every other frame
  12365.         lda TimerControl          ;if either master timer control
  12366.         orai Misc_OffscreenBits    ;or any offscreen bits for hammer are set,
  12367.         bne ExPHC                 ;branch to leave
  12368.         txa
  12369.         asl                       ;multiply misc object offset by four
  12370.         asl
  12371.         clc
  12372.         adcn ++$24                  ;add 36 or $24 bytes to get proper offset
  12373.         tay                       ;for misc object bounding box coordinates
  12374.         jsr PlayerCollisionCore   ;do player-to-hammer collision detection
  12375.         ldx ObjectOffset          ;get misc object offset
  12376.         bcc ClHCol                ;if no collision, then branch
  12377.         ldax Misc_Collision_Flag,x ;otherwise read collision flag
  12378.          checka
  12379.         bne ExPHC                 ;if collision flag already set, branch to leave
  12380.         ldan ++$01
  12381.         stax Misc_Collision_Flag,x ;otherwise set collision flag now
  12382.         ldax Misc_X_Speed,x
  12383.         eorn ++$ff                  ;get two's compliment of
  12384.         clc                       ;hammer's horizontal speed
  12385.         adcn ++$01
  12386.         stax Misc_X_Speed,x        ;set to send hammer flying the opposite direction
  12387.         lda StarInvincibleTimer   ;if star mario invincibility timer set,
  12388.          checka
  12389.         bne ExPHC                 ;branch to leave
  12390.         jmp InjurePlayer          ;otherwise jump to hurt player, do not return
  12391. ClHCol: ldan ++$00                  ;clear collision flag
  12392.         stax Misc_Collision_Flag,x
  12393. ExPHC:  rts
  12394.  
  12395. ;-------------------------------------------------------------------------------------
  12396.  
  12397. HandlePowerUpCollision:
  12398.       jsr EraseEnemyObject    ;erase the power-up object
  12399.       ldan ++$06
  12400.       jsr SetupFloateyNumber  ;award 1000 points to player by default
  12401.       ldan ++Sfx_PowerUpGrab
  12402.       sta Square2SoundQueue   ;play the power-up sound
  12403.       lda PowerUpType         ;check power-up type
  12404.       cmpn ++$02
  12405.               cmpcy
  12406.       bcc Shroom_Flower_PUp   ;if mushroom or fire flower, branch
  12407.       cmpn ++$03
  12408.       beq SetFor1Up           ;if 1-up mushroom, branch
  12409.       ldan ++$23                ;otherwise set star mario invincibility
  12410.       sta StarInvincibleTimer ;timer, and load the star mario music
  12411.       ldan ++StarPowerMusic     ;into the area music queue, then leave
  12412.       sta AreaMusicQueue
  12413.       rts
  12414.  
  12415. Shroom_Flower_PUp:
  12416.       lda PlayerStatus    ;if player status = small, branch
  12417.          checka
  12418.       beq UpToSuper
  12419.       cmpn ++$01            ;if player status not super, leave
  12420.       bne NoPUp
  12421.       ldx ObjectOffset    ;get enemy offset, not necessary
  12422.       ldan ++$02            ;set player status to fiery
  12423.       sta PlayerStatus
  12424.       jsr GetPlayerColors ;run sub to change colors of player
  12425.       ldx ObjectOffset    ;get enemy offset again, and again not necessary
  12426.       ldan ++$0c            ;set value to be used by subroutine tree (fiery)
  12427.       jmp UpToFiery       ;jump to set values accordingly
  12428.  
  12429. SetFor1Up:
  12430.       ldan ++$0b                 ;change 1000 points into 1-up instead
  12431.       stax FloateyNum_Control,x ;and then leave
  12432.       rts
  12433.  
  12434. UpToSuper:
  12435.        ldan ++$01         ;set player status to super
  12436.        sta PlayerStatus
  12437.        ldan ++$09         ;set value to be used by subroutine tree (super)
  12438.  
  12439. UpToFiery:
  12440.        ldyn ++$00         ;set value to be used as new player state
  12441.        jsr SetPRout     ;set values to stop certain things in motion
  12442. NoPUp: rts
  12443.  
  12444. ;--------------------------------
  12445.  
  12446. ResidualXSpdData:
  12447.       .db $18, $e8
  12448.  
  12449. KickedShellXSpdData:
  12450.       .db $30, $d0
  12451.  
  12452. DemotedKoopaXSpdData:
  12453.       .db $08, $f8
  12454.  
  12455. PlayerEnemyCollision:
  12456.          lda FrameCounter            ;check counter for d0 set
  12457.          lsr
  12458.         ;ccf ;эх яюьюурхЄ эр 1-2 (яЁш Їшъёрї CY Єюцх эх яюьюурхЄ)
  12459.         ;scf ;схч ъюыышчшщ ё ьюэёЄЁрьш
  12460.          bcs NoPUp                   ;if set, branch to leave
  12461.          jsr CheckPlayerVertical     ;if player object is completely offscreen or
  12462.          bcs NoPECol                 ;if down past 224th pixel row, branch to leave
  12463.          ldax EnemyOffscrBitsMasked,x ;if current enemy is offscreen by any amount,
  12464.          checka
  12465.          bne NoPECol                 ;go ahead and branch to leave
  12466.          lda GameEngineSubroutine
  12467.          cmpn ++$08                    ;if not set to run player control routine
  12468.          bne NoPECol                 ;on next frame, branch to leave
  12469.          ldax Enemy_State,x
  12470.          andn ++%00100000              ;if enemy state has d5 set, branch to leave
  12471.          bne NoPECol
  12472.          jsr GetEnemyBoundBoxOfs     ;get bounding box offset for current enemy object
  12473.          jsr PlayerCollisionCore     ;do collision detection on player vs. enemy
  12474.          ldx ObjectOffset            ;get enemy object buffer offset
  12475.          bcs CheckForPUpCollision    ;if collision, branch past this part here
  12476.          ldax Enemy_CollisionBits,x
  12477.          andn ++%11111110              ;otherwise, clear d0 of current enemy object's
  12478.          stax Enemy_CollisionBits,x   ;collision bit
  12479. NoPECol: rts
  12480.  
  12481. CheckForPUpCollision:
  12482.        ldyx Enemy_ID,x
  12483.        cpyn ++PowerUpObject            ;check for power-up object
  12484.        bne EColl                     ;if not found, branch to next part
  12485.        jmp HandlePowerUpCollision    ;otherwise, unconditional jump backwards
  12486. EColl: lda StarInvincibleTimer       ;if star mario invincibility timer expired,
  12487.          checka
  12488.        beq HandlePECollisions        ;perform task here, otherwise kill enemy like
  12489.        jmp ShellOrBlockDefeat        ;hit with a shell, or from beneath
  12490.  
  12491. KickedShellPtsData:
  12492.       .db $0a, $06, $04
  12493.  
  12494. HandlePECollisions:
  12495.        ldax Enemy_CollisionBits,x    ;check enemy collision bits for d0 set
  12496.        andn ++%00000001               ;or for being offscreen at all
  12497.        orax EnemyOffscrBitsMasked,x
  12498.        bne ExPEC                    ;branch to leave if either is true
  12499.        ldan ++$01
  12500.        orax Enemy_CollisionBits,x    ;otherwise set d0 now
  12501.        stax Enemy_CollisionBits,x
  12502.        cpyn ++Spiny                   ;branch if spiny
  12503.        beq ChkForPlayerInjury
  12504.        cpyn ++PiranhaPlant            ;branch if piranha plant
  12505.        beq InjurePlayer_PiranhaPlant
  12506.        cpyn ++Podoboo                 ;branch if podoboo
  12507.        beq InjurePlayer_PiranhaPlant
  12508.        cpyn ++BulletBill_CannonVar    ;branch if bullet bill
  12509.        beq ChkForPlayerInjury
  12510.        cpyn ++$15                     ;branch if object =>  $15
  12511.               cmpcy
  12512.        bcs InjurePlayer
  12513.        lda AreaType                 ;branch if water type level
  12514.          checka
  12515.        beq InjurePlayer
  12516.        ldax Enemy_State,x            ;branch if d7 of enemy state was set
  12517.        asl
  12518.        bcs ChkForPlayerInjury
  12519.        ldax Enemy_State,x            ;mask out all but 3 LSB of enemy state
  12520.        andn ++%00000111
  12521.        cmpn ++$02                     ;branch if enemy is in normal or falling state
  12522.               cmpcy
  12523.        bcc ChkForPlayerInjury
  12524.        ldax Enemy_ID,x               ;branch to leave if goomba in defeated state
  12525.        cmpn ++Goomba
  12526.        beq ExPEC
  12527.        ldan ++Sfx_EnemySmack          ;play smack enemy sound
  12528.        sta Square1SoundQueue
  12529.        ldax Enemy_State,x            ;set d7 in enemy state, thus become moving shell
  12530.        oran ++%10000000
  12531.        stax Enemy_State,x
  12532.        jsr EnemyFacePlayer          ;set moving direction and get offset
  12533.        lday KickedShellXSpdData,y    ;load and set horizontal speed data with offset
  12534.        stax Enemy_X_Speed,x
  12535.        ldan ++$03                     ;add three to whatever the stomp counter contains
  12536.        clc                          ;to give points for kicking the shell
  12537.        adci StompChainCounter
  12538.        ldyx EnemyIntervalTimer,x     ;check shell enemy's timer
  12539.        cpyn ++$03                     ;if above a certain point, branch using the points
  12540.               cmpcy
  12541.        bcs KSPts                    ;data obtained from the stomp counter + 3
  12542.        lday KickedShellPtsData,y     ;otherwise, set points based on proximity to timer expiration
  12543. KSPts: jsr SetupFloateyNumber       ;set values for floatey number now
  12544. ExPEC: rts                          ;leave!!!
  12545.  
  12546. ChkForPlayerInjury:
  12547.           lda Player_Y_Speed     ;check player's vertical speed
  12548.          checka
  12549.           bmi ChkInj             ;perform procedure below if player moving upwards
  12550.            ;jr $ ;хёыш чфхё№ яющьрЄ№ ёЄюыъэютхэшх ё уЁшсюь эр 1-2 (yspeed=0!!!) ш яхЁхэряЁртшЄ№ тЁєўэє■ эр EnemyStomped (їюЄ  яю шфхх ь√ эх фюыцэ√ хую фртшЄ№), Єю фры№°х єьшЁрхь эр ъръЄєёх
  12551.           bne EnemyStomped       ;or not at all, and branch elsewhere if moving downwards
  12552. ChkInj:   ldax Enemy_ID,x         ;branch if enemy object <  $07
  12553.       if GOODBULLET
  12554.        cp BulletBill_CannonVar
  12555.        ret z
  12556.       endif
  12557.           cmpn ++Bloober
  12558.               cmpcy
  12559.           bcc ChkETmrs
  12560.           lda Player_Y_Position  ;add 12 pixels to player's vertical position
  12561.           clc
  12562.           adcn ++$0c
  12563.           cmpx Enemy_Y_Position,x ;compare modified player's position to enemy's position
  12564.               cmpcy
  12565.           bcc EnemyStomped       ;branch if this player's position above (less than) enemy's
  12566. ChkETmrs: lda StompTimer         ;check stomp timer
  12567.          checka
  12568.           bne EnemyStomped       ;branch if set
  12569.           lda InjuryTimer        ;check to see if injured invincibility timer still
  12570.          checka
  12571.           bne ExInjColRoutines   ;counting down, and branch elsewhere to leave if so
  12572.           lda Player_Rel_XPos
  12573.           cmpi Enemy_Rel_XPos     ;if player's relative position to the left of enemy's
  12574.               cmpcy
  12575.           bcc TInjE              ;relative position, branch here
  12576.           jmp ChkEnemyFaceRight  ;otherwise do a jump here
  12577. TInjE:    ldax Enemy_MovingDir,x  ;if enemy moving towards the left,
  12578.           cmpn ++$01               ;branch, otherwise do a jump here
  12579.           bne InjurePlayer       ;to turn the enemy around
  12580.           jmp LInj
  12581.  
  12582. InjurePlayer_PiranhaPlant:
  12583.       if GOODPIRANHAPLANT
  12584.        ret
  12585.       endif
  12586. InjurePlayer:
  12587.       lda InjuryTimer          ;check again to see if injured invincibility timer is
  12588.          checka
  12589.       bne ExInjColRoutines     ;at zero, and branch to leave if so
  12590.  
  12591. ForceInjury:
  12592.           ldx PlayerStatus          ;check player's status
  12593.          checkx
  12594.           beq KillPlayer            ;branch if small
  12595.           sta PlayerStatus          ;otherwise set player's status to small
  12596.           ldan ++$08
  12597.           sta InjuryTimer           ;set injured invincibility timer
  12598.           asl
  12599.           sta Square1SoundQueue     ;play pipedown/injury sound
  12600.           jsr GetPlayerColors       ;change player's palette if necessary
  12601.           ldan ++$0a                  ;set subroutine to run on next frame
  12602. SetKRout: ldyn ++$01                  ;set new player state
  12603. SetPRout: sta GameEngineSubroutine  ;load new value to run subroutine on next frame
  12604.           sty Player_State          ;store new player state
  12605.           ldyn ++$ff
  12606.           sty TimerControl          ;set master timer control flag to halt timers
  12607.           iny
  12608.           sty ScrollAmount          ;initialize scroll speed
  12609.  
  12610. ExInjColRoutines:
  12611.       ldx ObjectOffset              ;get enemy offset and leave
  12612.       rts
  12613.  
  12614. KillPlayer:
  12615.       stx Player_X_Speed   ;halt player's horizontal movement by initializing speed
  12616.       inx
  12617.       stx EventMusicQueue  ;set event music queue to death music
  12618.       ldan ++$fc
  12619.       sta Player_Y_Speed   ;set new vertical speed
  12620.       ldan ++$0b             ;set subroutine to run on next frame
  12621.          checka
  12622.       bne SetKRout         ;branch to set player's state and other things
  12623.  
  12624. StompedEnemyPtsData:
  12625.       .db $02, $06, $05, $06
  12626.  
  12627. EnemyStomped:
  12628.       ldax Enemy_ID,x             ;check for spiny, branch to hurt player
  12629.       cmpn ++Spiny                 ;if found
  12630.       beq InjurePlayer
  12631.       ldan ++Sfx_EnemyStomp        ;otherwise play stomp/swim sound
  12632.       sta Square1SoundQueue
  12633.       ldax Enemy_ID,x
  12634.       ldyn ++$00                   ;initialize points data offset for stomped enemies
  12635.       cmpn ++FlyingCheepCheep      ;branch for cheep-cheep
  12636.       beq EnemyStompedPts
  12637.       cmpn ++BulletBill_FrenzyVar  ;branch for either bullet bill object
  12638.       beq EnemyStompedPts
  12639.       cmpn ++BulletBill_CannonVar
  12640.       beq EnemyStompedPts
  12641.       cmpn ++Podoboo               ;branch for podoboo (this branch is logically impossible
  12642.       beq EnemyStompedPts        ;for cpu to take due to earlier checking of podoboo)
  12643.       iny                        ;increment points data offset
  12644.       cmpn ++HammerBro             ;branch for hammer bro
  12645.       beq EnemyStompedPts
  12646.       iny                        ;increment points data offset
  12647.       cmpn ++Lakitu                ;branch for lakitu
  12648.       beq EnemyStompedPts
  12649.       iny                        ;increment points data offset
  12650.       cmpn ++Bloober               ;branch if NOT bloober
  12651.       bne ChkForDemoteKoopa
  12652.  
  12653. EnemyStompedPts:
  12654.       lday StompedEnemyPtsData,y  ;load points data using offset in Y
  12655.       jsr SetupFloateyNumber     ;run sub to set floatey number controls
  12656.       ldax Enemy_MovingDir,x
  12657.       pha                        ;save enemy movement direction to stack
  12658.       jsr SetStun                ;run sub to kill enemy
  12659.       pla
  12660.       stax Enemy_MovingDir,x      ;return enemy movement direction from stack
  12661.       ldan ++%00100000
  12662.       stax Enemy_State,x          ;set d5 in enemy state
  12663.       jsr InitVStf               ;nullify vertical speed, physics-related thing,
  12664.       stax Enemy_X_Speed,x        ;and horizontal speed
  12665.       ldan ++$fd                   ;set player's vertical speed, to give bounce
  12666.       sta Player_Y_Speed
  12667.       rts
  12668.  
  12669. ChkForDemoteKoopa:
  12670.       cmpn ++$09                   ;branch elsewhere if enemy object < $09 ;эрўшэр  ё юс·хъЄр #9 шфєЄ misc objects (ўЄю ¤Єю???)
  12671.               cmpcy
  12672.       bcc HandleStompedShellE
  12673.       andn ++%00000001             ;demote koopa paratroopas to ordinary troopas
  12674.       stax Enemy_ID,x
  12675.       ldyn ++$00                   ;return enemy to normal state
  12676.       styx Enemy_State,x
  12677.       ldan ++$03                   ;award 400 points to the player
  12678.       jsr SetupFloateyNumber
  12679.       jsr InitVStf               ;nullify physics-related thing and vertical speed
  12680.       jsr EnemyFacePlayer        ;turn enemy around if necessary
  12681.       lday DemotedKoopaXSpdData,y
  12682.       stax Enemy_X_Speed,x        ;set appropriate moving speed based on direction
  12683.       jmp SBnce                  ;then move onto something else
  12684.  
  12685. RevivalRateData:
  12686.       .db $10, $0b
  12687.  
  12688. HandleStompedShellE:
  12689.        ldan ++$04                   ;set defeated state for enemy
  12690.        stax Enemy_State,x
  12691.        inci StompChainCounter      ;increment the stomp counter
  12692.        lda StompChainCounter      ;add whatever is in the stomp counter
  12693.        clc                        ;to whatever is in the stomp timer
  12694.        adci StompTimer
  12695.        jsr SetupFloateyNumber     ;award points accordingly
  12696.        inci StompTimer             ;increment stomp timer of some sort
  12697.        ldy PrimaryHardMode        ;check primary hard mode flag
  12698.        lday RevivalRateData,y      ;load timer setting according to flag
  12699.        stax EnemyIntervalTimer,x   ;set as enemy timer to revive stomped enemy
  12700. SBnce: ldan ++$fc                   ;set player's vertical speed for bounce
  12701.        sta Player_Y_Speed         ;and then leave!!!
  12702.        rts
  12703.  
  12704. ChkEnemyFaceRight:
  12705.        ldax Enemy_MovingDir,x ;check to see if enemy is moving to the right
  12706.        cmpn ++$01
  12707.        bne LInj              ;if not, branch
  12708.        jmp InjurePlayer      ;otherwise go back to hurt player
  12709. LInj:  jsr EnemyTurnAround   ;turn the enemy around, if necessary
  12710.        jmp InjurePlayer      ;go back to hurt player
  12711.  
  12712.  
  12713. EnemyFacePlayer:
  12714.        ldyn ++$01               ;set to move right by default
  12715.        jsr PlayerEnemyDiff    ;get horizontal difference between player and enemy
  12716.        bpl SFcRt              ;if enemy is to the right of player, do not increment
  12717.        iny                    ;otherwise, increment to set to move to the left
  12718. SFcRt: styx Enemy_MovingDir,x  ;set moving direction here
  12719.        dey                    ;then decrement to use as a proper offset
  12720.        rts
  12721.  
  12722. SetupFloateyNumber:
  12723.        stax FloateyNum_Control,x ;set number of points control for floatey numbers
  12724.        ldan ++$30
  12725.        stax FloateyNum_Timer,x   ;set timer for floatey numbers
  12726.        ldax Enemy_Y_Position,x
  12727.        stax FloateyNum_Y_Pos,x   ;set vertical coordinate
  12728.        lda Enemy_Rel_XPos
  12729.        stax FloateyNum_X_Pos,x   ;set horizontal coordinate and leave
  12730. ExSFN: rts
  12731.  
  12732. ;-------------------------------------------------------------------------------------
  12733. ;$01 - used to hold enemy offset for second enemy
  12734.  
  12735. SetBitsMask:
  12736.       .db %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010
  12737.  
  12738. ClearBitsMask:
  12739.       .db %01111111, %10111111, %11011111, %11101111, %11110111, %11111011, %11111101
  12740.  
  12741. EnemiesCollision:
  12742. ;TODO єёъюЁшЄ№ ўхЁхч ix тьхёЄю c
  12743.        if Z80OPT2
  12744.         ld a,(FrameCounter)            ;check counter for d0 set
  12745.         rra
  12746.         ret nc;bcc ExSFN                   ;if d0 not set, leave
  12747.         ld a,(AreaType)
  12748.         or a
  12749.         ret z;beq ExSFN                   ;if water area type, leave
  12750.         ld hl,Enemy_ID
  12751.         add hl,bc
  12752.         ld a,(hl)
  12753.         cp ++$15                    ;if enemy object =>  $15, branch to leave
  12754.         jp nc,ExitECRoutine
  12755.         cp ++Lakitu                 ;if lakitu, branch to leave
  12756.         jp z,ExitECRoutine
  12757.         cp ++PiranhaPlant           ;if piranha plant, branch to leave
  12758.         jp z,ExitECRoutine
  12759.         ldax EnemyOffscrBitsMasked,x ;if masked offscreen bits nonzero, branch to leave
  12760.         or a
  12761.         jp nz,ExitECRoutine
  12762.         call GetEnemyBoundBoxOfs     ;otherwise, do sub, get appropriate bounding box offset for
  12763.         dec c                         ;first enemy we're going to compare, then decrement for second
  12764.         jp m,ExitECRoutine           ;branch to leave if there are no other enemies
  12765. ECLoop: ;ld ly,c;stx SCRATCHPAD+$01                     ;save enemy object buffer offset for second enemy here
  12766.        ;ld hy,e;tya                         ;save first enemy's bounding box offset to stack
  12767.        ;pha
  12768.         ldax Enemy_Flag,x            ;check enemy object enable flag
  12769.         or a
  12770.         jr z,ReadyNextEnemy_fast          ;branch if flag not set
  12771.         ldax Enemy_ID,x
  12772.         cp ++$15                    ;check for enemy object =>  $15
  12773.         jr nc,ReadyNextEnemy_fast          ;branch if true
  12774.         cp ++Lakitu
  12775.         jr z,ReadyNextEnemy_fast          ;branch if enemy object is lakitu
  12776.         cp ++PiranhaPlant
  12777.         jr z,ReadyNextEnemy_fast          ;branch if enemy object is piranha plant
  12778.         ldax EnemyOffscrBitsMasked,x
  12779.         or a
  12780.         jr nz,ReadyNextEnemy_fast          ;branch if masked offscreen bits set
  12781.       ld ly,c
  12782.       ;ld hy,e ;эх яюьюурхЄ
  12783.         ld a,c                         ;get second enemy object's bounding box offset
  12784.         inc a
  12785.         add a,a                         ;multiply by four, then add four
  12786.         add a,a
  12787.         ld c,a                         ;use as new contents of X
  12788.        push ix
  12789.        push iy
  12790.        call SprObjectCollisionCore  ;do collision detection using the two enemies here ;эх яюЁЄшЄ y
  12791.        pop iy
  12792.        pop ix
  12793.         ld hy,e
  12794.       ld hl,ObjectOffset
  12795.       ld e,(hl);ld c,(hl)      ;use first enemy offset for X
  12796.       ld c,ly;ld e,ly;ldy SCRATCHPAD+$01                     ;use second enemy offset for Y
  12797.         jr nc,NoEnemyCollision        ;if carry clear, no collision, branch ahead of this
  12798.         ld hl,Enemy_State
  12799.         add hl,de;bc
  12800.         ld a,(hl) ;ldax Enemy_State,x
  12801.         ld hl,Enemy_State
  12802.         add hl,bc;de
  12803.         or (hl) ;oray Enemy_State,y           ;check both enemy states for d7 set
  12804.         jp m,YesEC                   ;branch if at least one of them is set
  12805.         ld ix,Enemy_CollisionBits
  12806.         add ix,bc;de
  12807.         ld a,(ix);lday Enemy_CollisionBits,y   ;load first enemy's collision-related bits
  12808.         ld hl,SetBitsMask
  12809.         add hl,de;bc
  12810.         and (hl);andx SetBitsMask,x           ;check to see if bit connected to second enemy is
  12811.         jr nz,ReadyNextEnemy          ;already set, and move onto next enemy slot if set
  12812.         ld a,(ix);lday Enemy_CollisionBits,y
  12813.         or (hl);orax SetBitsMask,x           ;if the bit is not set, set it now
  12814.         ld (ix),a;stay Enemy_CollisionBits,y
  12815. YesEC:  ;push iy ;эх яюьюурхЄ
  12816.         ;ly чрьхэ хЄ SCRATCHPAD+$01!!!
  12817.        if Z80OPT2bug==0
  12818.         ld a,c
  12819.         ld c,e
  12820.         ld e,a ;яюўхьє-Єю яюЁ фюъ тыш хЄ! шэрўх ўхЁхярїш эх ёЄрыъштр■Єё  фЁєу юс фЁєур
  12821.        endif
  12822.         call ProcEnemyCollisions     ;react according to the nature of collision ;яюЁЄшЄ x,y
  12823.         ;pop iy
  12824.         jp ReadyNextEnemy          ;move onto next enemy slot
  12825.  
  12826. NoEnemyCollision:
  12827.         ld hl,ClearBitsMask
  12828.         add hl,de;bc
  12829.         ld a,(hl)
  12830.         ld hl,Enemy_CollisionBits
  12831.         add hl,bc;de
  12832.       ;lday Enemy_CollisionBits,y     ;load first enemy's collision-related bits
  12833.       and (hl) ;andx ClearBitsMask,x           ;clear bit connected to second enemy
  12834.       ld (hl),a ;stay Enemy_CollisionBits,y     ;then move onto next enemy slot
  12835.  
  12836. ReadyNextEnemy:
  12837.      ;pla              ;get first enemy's bounding box offset from the stack
  12838.      ld e,hy ;tay              ;use as Y again
  12839.       ld c,ly;ldx SCRATCHPAD+$01          ;get and decrement second enemy's object buffer offset
  12840. ReadyNextEnemy_fast:
  12841.       dec c
  12842.       jp p,ECLoop       ;loop until all enemy slots have been checked
  12843.  
  12844. ExitECRoutine:
  12845.       ld hl,ObjectOffset
  12846.       ld c,(hl) ;get enemy object buffer offset
  12847.       ret              ;leave
  12848.      
  12849.        else ;~Z80
  12850.  
  12851.         lda FrameCounter            ;check counter for d0 set
  12852.         lsr
  12853.         bcc ExSFN                   ;if d0 not set, leave
  12854.         lda AreaType
  12855.          checka
  12856.         beq ExSFN                   ;if water area type, leave
  12857.         ldax Enemy_ID,x
  12858.         cmpn ++$15                    ;if enemy object =>  $15, branch to leave
  12859.               cmpcy
  12860.         bcs ExitECRoutine
  12861.         cmpn ++Lakitu                 ;if lakitu, branch to leave
  12862.         beq ExitECRoutine
  12863.         cmpn ++PiranhaPlant           ;if piranha plant, branch to leave
  12864.         beq ExitECRoutine
  12865.         ldax EnemyOffscrBitsMasked,x ;if masked offscreen bits nonzero, branch to leave
  12866.          checka
  12867.         bne ExitECRoutine
  12868.         jsr GetEnemyBoundBoxOfs     ;otherwise, do sub, get appropriate bounding box offset for
  12869.         dex                         ;first enemy we're going to compare, then decrement for second
  12870.         bmi ExitECRoutine           ;branch to leave if there are no other enemies
  12871. ECLoop: stx SCRATCHPAD+$01                     ;save enemy object buffer offset for second enemy here
  12872.         tya                         ;save first enemy's bounding box offset to stack
  12873.         pha
  12874.         ldax Enemy_Flag,x            ;check enemy object enable flag
  12875.          checka
  12876.         beq ReadyNextEnemy          ;branch if flag not set
  12877.         ldax Enemy_ID,x
  12878.         cmpn ++$15                    ;check for enemy object =>  $15
  12879.               cmpcy
  12880.         bcs ReadyNextEnemy          ;branch if true
  12881.         cmpn ++Lakitu
  12882.         beq ReadyNextEnemy          ;branch if enemy object is lakitu
  12883.         cmpn ++PiranhaPlant
  12884.         beq ReadyNextEnemy          ;branch if enemy object is piranha plant
  12885.         ldax EnemyOffscrBitsMasked,x
  12886.          checka
  12887.         bne ReadyNextEnemy          ;branch if masked offscreen bits set
  12888.         txa                         ;get second enemy object's bounding box offset
  12889.         asl                         ;multiply by four, then add four
  12890.         asl
  12891.         clc
  12892.         adcn ++$04
  12893.         tax                         ;use as new contents of X
  12894.         jsr SprObjectCollisionCore  ;do collision detection using the two enemies here
  12895.         ldx ObjectOffset            ;use first enemy offset for X
  12896.         ldy SCRATCHPAD+$01                     ;use second enemy offset for Y
  12897.         bcc NoEnemyCollision        ;if carry clear, no collision, branch ahead of this
  12898.         ldax Enemy_State,x
  12899.         oray Enemy_State,y           ;check both enemy states for d7 set
  12900.         andn ++%10000000
  12901.         bne YesEC                   ;branch if at least one of them is set
  12902.         lday Enemy_CollisionBits,y   ;load first enemy's collision-related bits
  12903.         andx SetBitsMask,x           ;check to see if bit connected to second enemy is
  12904.         bne ReadyNextEnemy          ;already set, and move onto next enemy slot if set
  12905.         lday Enemy_CollisionBits,y
  12906.         orax SetBitsMask,x           ;if the bit is not set, set it now
  12907.         stay Enemy_CollisionBits,y
  12908. YesEC:  jsr ProcEnemyCollisions     ;react according to the nature of collision
  12909.         jmp ReadyNextEnemy          ;move onto next enemy slot
  12910.  
  12911. NoEnemyCollision:
  12912.       lday Enemy_CollisionBits,y     ;load first enemy's collision-related bits
  12913.       andx ClearBitsMask,x           ;clear bit connected to second enemy
  12914.       stay Enemy_CollisionBits,y     ;then move onto next enemy slot
  12915.  
  12916. ReadyNextEnemy:
  12917.       pla              ;get first enemy's bounding box offset from the stack
  12918.       tay              ;use as Y again
  12919.       ldx SCRATCHPAD+$01          ;get and decrement second enemy's object buffer offset
  12920.       dex
  12921.       bpl ECLoop       ;loop until all enemy slots have been checked
  12922.  
  12923. ExitECRoutine:
  12924.       ldx ObjectOffset ;get enemy object buffer offset
  12925.       rts              ;leave
  12926.         endif
  12927.      
  12928. ProcEnemyCollisions:
  12929. ;ly чрьхэ хЄ SCRATCHPAD+$01!!!
  12930.       lday Enemy_State,y        ;check both enemy states for d5 set
  12931.       orax Enemy_State,x
  12932.       andn ++%00100000           ;if d5 is set in either state, or both, branch
  12933.       bne ExitProcessEColl     ;to leave and do nothing else at this point
  12934.       ldax Enemy_State,x
  12935.       cmpn ++$06                 ;if second enemy state <  $06, branch elsewhere
  12936.               cmpcy
  12937.       bcc ProcSecondEnemyColl
  12938.       ldax Enemy_ID,x           ;check second enemy identifier for hammer bro
  12939.       cmpn ++HammerBro           ;if hammer bro found in alt state, branch to leave
  12940.       beq ExitProcessEColl
  12941.       lday Enemy_State,y        ;check first enemy state for d7 set
  12942.       asl
  12943.       bcc ShellCollisions      ;branch if d7 is clear
  12944.       ldan ++$06
  12945.       jsr SetupFloateyNumber   ;award 1000 points for killing enemy
  12946.       jsr ShellOrBlockDefeat   ;then kill enemy, then load
  12947.      if Z80OPT2
  12948.       ld e,ly;ldy SCRATCHPAD+$01                  ;original offset of second enemy
  12949.      else
  12950.       ldy SCRATCHPAD+$01                  ;original offset of second enemy
  12951.      endif
  12952.  
  12953. ShellCollisions:
  12954.       tya                      ;move Y to X
  12955.       tax
  12956.       jsr ShellOrBlockDefeat   ;kill second enemy
  12957.       ldx ObjectOffset
  12958.       ldax ShellChainCounter,x  ;get chain counter for shell
  12959.       clc
  12960.       adcn ++$04                 ;add four to get appropriate point offset
  12961.      if Z80OPT2
  12962.       ld c,ly;ldx SCRATCHPAD+$01
  12963.      else
  12964.       ldx SCRATCHPAD+$01
  12965.      endif
  12966.       jsr SetupFloateyNumber   ;award appropriate number of points for second enemy
  12967.       ldx ObjectOffset         ;load original offset of first enemy
  12968.       incx ShellChainCounter,x  ;increment chain counter for additional enemies
  12969.  
  12970. ExitProcessEColl:
  12971.       rts                      ;leave!!!
  12972.  
  12973. ProcSecondEnemyColl:
  12974.       lday Enemy_State,y        ;if first enemy state <  $06, branch elsewhere
  12975.       cmpn ++$06
  12976.               cmpcy
  12977.       bcc MoveEOfs
  12978.       lday Enemy_ID,y           ;check first enemy identifier for hammer bro
  12979.       cmpn ++HammerBro           ;if hammer bro found in alt state, branch to leave
  12980.       beq ExitProcessEColl
  12981.       jsr ShellOrBlockDefeat   ;otherwise, kill first enemy
  12982.      if Z80OPT2
  12983.       ld e,ly;ldy SCRATCHPAD+$01
  12984.      else
  12985.       ldy SCRATCHPAD+$01
  12986.      endif
  12987.       lday ShellChainCounter,y  ;get chain counter for shell
  12988.       clc
  12989.       adcn ++$04                 ;add four to get appropriate point offset
  12990.       ldx ObjectOffset
  12991.       jsr SetupFloateyNumber   ;award appropriate number of points for first enemy
  12992.      if Z80OPT2
  12993.       ld c,ly;ldx SCRATCHPAD+$01                  ;load original offset of second enemy
  12994.      else
  12995.       ldx SCRATCHPAD+$01                  ;load original offset of second enemy
  12996.      endif
  12997.       incx ShellChainCounter,x  ;increment chain counter for additional enemies
  12998.       rts                      ;leave!!!
  12999.  
  13000. MoveEOfs:
  13001.       tya                      ;move Y ($01) to X
  13002.       tax
  13003.       jsr EnemyTurnAround      ;do the sub here using value from $01
  13004.       ldx ObjectOffset         ;then do it again using value from $08
  13005.  
  13006. EnemyTurnAround:
  13007.        ldax Enemy_ID,x           ;check for specific enemies
  13008.        cmpn ++PiranhaPlant
  13009.        beq ExTA                 ;if piranha plant, leave
  13010.        cmpn ++Lakitu
  13011.        beq ExTA                 ;if lakitu, leave
  13012.        cmpn ++HammerBro
  13013.        beq ExTA                 ;if hammer bro, leave
  13014.        cmpn ++Spiny
  13015.        beq RXSpd                ;if spiny, turn it around
  13016.        cmpn ++GreenParatroopaJump
  13017.        beq RXSpd                ;if green paratroopa, turn it around
  13018.        cmpn ++$07
  13019.               cmpcy
  13020.        bcs ExTA                 ;if any OTHER enemy object =>  $07, leave
  13021. RXSpd: ldax Enemy_X_Speed,x      ;load horizontal speed
  13022.        eorn ++$ff                 ;get two's compliment for horizontal speed
  13023.        tay
  13024.        iny
  13025.        styx Enemy_X_Speed,x      ;store as new horizontal speed
  13026.        ldax Enemy_MovingDir,x
  13027.        eorn ++%00000011           ;invert moving direction and store, then leave
  13028.        stax Enemy_MovingDir,x    ;thus effectively turning the enemy around
  13029. ExTA:  rts                      ;leave!!!
  13030.  
  13031. ;-------------------------------------------------------------------------------------
  13032. ;$00 - vertical position of platform
  13033.  
  13034. LargePlatformCollision:
  13035.        ldan ++$ff                     ;save value here
  13036.        stax PlatformCollisionFlag,x
  13037.        lda TimerControl             ;check master timer control
  13038.          checka
  13039.        bne ExLPC                    ;if set, branch to leave
  13040.        ldax Enemy_State,x            ;if d7 set in object state,
  13041.          checka
  13042.        bmi ExLPC                    ;branch to leave
  13043.        ldax Enemy_ID,x
  13044.        cmpn ++$24                     ;check enemy object identifier for
  13045.        bne ChkForPlayerC_LargeP     ;balance platform, branch if not found
  13046.        ldax Enemy_State,x
  13047.        tax                          ;set state as enemy offset here
  13048.        jsr ChkForPlayerC_LargeP     ;perform code with state offset, then original offset, in X
  13049.  
  13050. ChkForPlayerC_LargeP:
  13051.        jsr CheckPlayerVertical      ;figure out if player is below a certain point
  13052.        bcs ExLPC                    ;or offscreen, branch to leave if true
  13053.        txa
  13054.        jsr GetEnemyBoundBoxOfsArg   ;get bounding box offset in Y
  13055.        ldax Enemy_Y_Position,x       ;store vertical coordinate in
  13056.        sta SCRATCHPAD+$00                      ;temp variable for now
  13057.        txa                          ;send offset we're on to the stack
  13058.        pha
  13059.        jsr PlayerCollisionCore      ;do player-to-platform collision detection
  13060.        plakeepcy                          ;retrieve offset from the stack
  13061.        tax
  13062.        bcc ExLPC                    ;if no collision, branch to leave
  13063.        jsr ProcLPlatCollisions      ;otherwise collision, perform sub
  13064. ExLPC: ldx ObjectOffset             ;get enemy object buffer offset and leave
  13065.        rts
  13066.  
  13067. ;--------------------------------
  13068. ;$00 - counter for bounding boxes
  13069.  
  13070. SmallPlatformCollision:
  13071.       lda TimerControl             ;if master timer control set,
  13072.          checka
  13073.       bne ExSPC                    ;branch to leave
  13074.       stax PlatformCollisionFlag,x  ;otherwise initialize collision flag
  13075.       jsr CheckPlayerVertical      ;do a sub to see if player is below a certain point
  13076.       bcs ExSPC                    ;or entirely offscreen, and branch to leave if true
  13077.       ldan ++$02
  13078.       sta SCRATCHPAD+$00                      ;load counter here for 2 bounding boxes
  13079.  
  13080. ChkSmallPlatLoop:
  13081.       ldx ObjectOffset           ;get enemy object offset
  13082.       jsr GetEnemyBoundBoxOfs    ;get bounding box offset in Y
  13083.       andn ++%00000010             ;if d1 of offscreen lower nybble bits was set
  13084.       bne ExSPC                  ;then branch to leave
  13085.       lday BoundingBox_UL_YPos,y  ;check top of platform's bounding box for being
  13086.       cmpn ++$20                   ;above a specific point
  13087.               cmpcy
  13088.       bcc MoveBoundBox           ;if so, branch, don't do collision detection
  13089.       jsr PlayerCollisionCore    ;otherwise, perform player-to-platform collision detection
  13090.       bcs ProcSPlatCollisions    ;skip ahead if collision
  13091.  
  13092. MoveBoundBox:
  13093.        lday BoundingBox_UL_YPos,y  ;move bounding box vertical coordinates
  13094.        clc                        ;128 pixels downwards
  13095.        adcn ++$80
  13096.        stay BoundingBox_UL_YPos,y
  13097.        lday BoundingBox_DR_YPos,y
  13098.        clc
  13099.        adcn ++$80
  13100.        stay BoundingBox_DR_YPos,y
  13101.        deci SCRATCHPAD+$00                    ;decrement counter we set earlier
  13102.        bne ChkSmallPlatLoop       ;loop back until both bounding boxes are checked
  13103. ExSPC: ldx ObjectOffset           ;get enemy object buffer offset, then leave
  13104.        rts
  13105.  
  13106. ;--------------------------------
  13107.  
  13108. ProcSPlatCollisions:
  13109.       ldx ObjectOffset             ;return enemy object buffer offset to X, then continue
  13110.  
  13111. ProcLPlatCollisions:
  13112.       lday BoundingBox_DR_YPos,y    ;get difference by subtracting the top
  13113.       secsub                          ;of the player's bounding box from the bottom
  13114.       sbci BoundingBox_UL_YPos      ;of the platform's bounding box
  13115.       cmpn ++$04                     ;if difference too large or negative,
  13116.               cmpcy
  13117.       bcs ChkForTopCollision       ;branch, do not alter vertical speed of player
  13118.       lda Player_Y_Speed           ;check to see if player's vertical speed is moving down
  13119.          checka
  13120.       bpl ChkForTopCollision       ;if so, don't mess with it
  13121.       ldan ++$01                     ;otherwise, set vertical
  13122.       sta Player_Y_Speed           ;speed of player to kill jump
  13123.  
  13124. ChkForTopCollision:
  13125.       lda BoundingBox_DR_YPos      ;get difference by subtracting the top
  13126.       secsub                          ;of the platform's bounding box from the bottom
  13127.       sbcy BoundingBox_UL_YPos,y    ;of the player's bounding box
  13128.       cmpn ++$06
  13129.               cmpcy
  13130.       bcs PlatformSideCollisions   ;if difference not close enough, skip all of this
  13131.       lda Player_Y_Speed
  13132.          checka
  13133.       bmi PlatformSideCollisions   ;if player's vertical speed moving upwards, skip this
  13134.       lda SCRATCHPAD+$00                      ;get saved bounding box counter from earlier
  13135.       ldyx Enemy_ID,x
  13136.       cpyn ++$2b                     ;if either of the two small platform objects are found,
  13137.       beq SetCollisionFlag         ;regardless of which one, branch to use bounding box counter
  13138.       cpyn ++$2c                     ;as contents of collision flag
  13139.       beq SetCollisionFlag
  13140.       txa                          ;otherwise use enemy object buffer offset
  13141.  
  13142. SetCollisionFlag: ;яюўхьє ё■фр эх яюярфрхь???
  13143.       ldx ObjectOffset             ;get enemy object buffer offset
  13144.       stax PlatformCollisionFlag,x  ;save either bounding box counter or enemy offset here
  13145.       ldan ++$00
  13146.       sta Player_State             ;set player state to normal then leave
  13147.       rts
  13148.  
  13149. PlatformSideCollisions:
  13150.          ldan ++$01                   ;set value here to indicate possible horizontal
  13151.          sta SCRATCHPAD+$00                    ;collision on left side of platform
  13152.          lda BoundingBox_DR_XPos    ;get difference by subtracting platform's left edge
  13153.          secsub                        ;from player's right edge
  13154.          sbcy BoundingBox_UL_XPos,y
  13155.          cmpn ++$08                   ;if difference close enough, skip all of this
  13156.               cmpcy
  13157.          bcc SideC
  13158.          inci SCRATCHPAD+$00                    ;otherwise increment value set here for right side collision
  13159.          lday BoundingBox_DR_XPos,y  ;get difference by subtracting player's left edge
  13160.          clc                        ;from platform's right edge
  13161.          sbci BoundingBox_UL_XPos
  13162.          cmpn ++$09                   ;if difference not close enough, skip subroutine
  13163.               cmpcy
  13164.          bcs NoSideC                ;and instead branch to leave (no collision)
  13165. SideC:   jsr ImpedePlayerMove       ;deal with horizontal collision
  13166. NoSideC: ldx ObjectOffset           ;return with enemy object buffer offset
  13167.          rts
  13168.  
  13169. ;-------------------------------------------------------------------------------------
  13170.  
  13171. PlayerPosSPlatData:
  13172.       .db $80, $00
  13173.  
  13174. PositionPlayerOnS_Plat:
  13175.       tay                        ;use bounding box counter saved in collision flag
  13176.       ldax Enemy_Y_Position,x     ;for offset
  13177.       clc                        ;add positioning data using offset to the vertical
  13178.       adcy PlayerPosSPlatData-1,y ;coordinate
  13179.       jr PositionPlayerOnVPlat_go;.db $2c                    ;BIT instruction opcode
  13180.  
  13181. PositionPlayerOnVPlat:
  13182.          ldax Enemy_Y_Position,x    ;get vertical coordinate
  13183. PositionPlayerOnVPlat_go
  13184.          ldy GameEngineSubroutine
  13185.          cpyn ++$0b                  ;if certain routine being executed on this frame,
  13186.          beq ExPlPos               ;skip all of this
  13187.          ldyx Enemy_Y_HighPos,x
  13188.          cpyn ++$01                  ;if vertical high byte offscreen, skip this
  13189.          bne ExPlPos
  13190.          secsub                       ;subtract 32 pixels from vertical coordinate
  13191.          sbcn ++$20                  ;for the player object's height
  13192.          sta Player_Y_Position     ;save as player's new vertical coordinate
  13193.          tya
  13194.          sbcn ++$00                  ;subtract borrow and store as player's
  13195.          sta Player_Y_HighPos      ;new vertical high byte
  13196.          ldan ++$00
  13197.          sta Player_Y_Speed        ;initialize vertical speed and low byte of force
  13198.          sta Player_Y_MoveForce    ;and then leave
  13199. ExPlPos: rts
  13200.  
  13201. ;-------------------------------------------------------------------------------------
  13202.  
  13203. CheckPlayerVertical:
  13204.        lda Player_OffscreenBits  ;if player object is completely offscreen
  13205.        cmpn ++$f0                  ;vertically, leave this routine
  13206.               cmpcy
  13207.        bcs ExCPV
  13208.        ldy Player_Y_HighPos      ;if player high vertical byte is not
  13209.        dey                       ;within the screen, leave this routine
  13210.        bne ExCPV
  13211.        lda Player_Y_Position     ;if on the screen, check to see how far down
  13212.        cmpn ++$d0                  ;the player is vertically
  13213.               cmpcy
  13214. ExCPV: rts
  13215.  
  13216. ;-------------------------------------------------------------------------------------
  13217.  
  13218. GetEnemyBoundBoxOfs:
  13219.       lda ObjectOffset         ;get enemy object buffer offset
  13220.  
  13221. GetEnemyBoundBoxOfsArg:
  13222.       asl                      ;multiply A by four, then add four
  13223.       asl                      ;to skip player's bounding box
  13224.       clc
  13225.       adcn ++$04
  13226.       tay                      ;send to Y
  13227.       lda Enemy_OffscreenBits  ;get offscreen bits for enemy object
  13228.       andn ++%00001111           ;save low nybble
  13229.       cmpn ++%00001111           ;check for all bits set
  13230.               cmpcy
  13231.       rts
  13232.  
  13233. ;-------------------------------------------------------------------------------------
  13234. ;$00-$01 - used to hold many values, essentially temp variables
  13235. ;$04 - holds lower nybble of vertical coordinate from block buffer routine
  13236. ;$eb - used to hold block buffer adder
  13237.  
  13238. PlayerBGUpperExtent:
  13239.       .db $20, $10
  13240.  
  13241. PlayerBGCollision:
  13242.           lda DisableCollisionDet   ;if collision detection disabled flag set,
  13243.          checka
  13244.           bne ExPBGCol              ;branch to leave
  13245.           lda GameEngineSubroutine
  13246.           cmpn ++$0b                  ;if running routine ++11 or $0b
  13247.           beq ExPBGCol              ;branch to leave
  13248.           cmpn ++$04
  13249.               cmpcy
  13250.           bcc ExPBGCol              ;if running routines $00-$03 branch to leave
  13251.           ldan ++$01                  ;load default player state for swimming
  13252.           ldy SwimmingFlag          ;if swimming flag set,
  13253.          checky
  13254.           bne SetPSte               ;branch ahead to set default state
  13255.           lda Player_State          ;if player in normal state,
  13256.          checka
  13257.           beq SetFallS              ;branch to set default state for falling
  13258.           cmpn ++$03
  13259.           bne ChkOnScr              ;if in any other state besides climbing, skip to next part
  13260. SetFallS: ldan ++$02                  ;load default player state for falling
  13261. SetPSte:  sta Player_State          ;set whatever player state is appropriate
  13262. ChkOnScr: lda Player_Y_HighPos
  13263.           cmpn ++$01                  ;check player's vertical high byte for still on the screen
  13264.           bne ExPBGCol              ;branch to leave if not
  13265.           ldan ++$ff
  13266.           sta Player_CollisionBits  ;initialize player's collision flag
  13267.           lda Player_Y_Position
  13268.           cmpn ++$cf                  ;check player's vertical coordinate
  13269.               cmpcy
  13270.           bcc ChkCollSize           ;if not too close to the bottom of screen, continue
  13271. ExPBGCol: rts                       ;otherwise leave
  13272.  
  13273. ChkCollSize:
  13274.          ldyn ++$02                    ;load default offset
  13275.          lda CrouchingFlag
  13276.          checka
  13277.          bne GBBAdr                  ;if player crouching, skip ahead
  13278.          lda PlayerSize
  13279.          checka
  13280.          bne GBBAdr                  ;if player small, skip ahead
  13281.          dey                         ;otherwise decrement offset for big player not crouching
  13282.          lda SwimmingFlag
  13283.          checka
  13284.          bne GBBAdr                  ;if swimming flag set, skip ahead
  13285.          dey                         ;otherwise decrement offset
  13286. GBBAdr:  lday BlockBufferAdderData,y  ;get value using offset ;0,7,14
  13287.          sta SCRATCHPAD+$eb                     ;store value here
  13288.          tay                         ;put value into Y, as offset for block buffer routine
  13289.          ldx PlayerSize              ;get player's size as offset
  13290.          lda CrouchingFlag
  13291.          checka
  13292.          beq HeadChk                 ;if player not crouching, branch ahead
  13293.          inx                         ;otherwise increment size as offset
  13294. HeadChk: lda Player_Y_Position       ;get player's vertical coordinate ;є эрё ёэрўрыр $b0???
  13295.          cmpx PlayerBGUpperExtent,x   ;compare with upper extent value based on offset ;$20 шыш $10
  13296.               cmpcy
  13297.          bcc DoFootCheck             ;if player is too high, skip this part
  13298.          jsr BlockBufferColli_Head   ;do player-to-bg collision detection on top of
  13299.          beq DoFootCheck             ;player, and branch if nothing above player's head
  13300.          jsr CheckForCoinMTiles      ;check to see if player touched coin with their head
  13301.          bcs AwardTouchedCoin        ;if so, branch to some other part of code
  13302.          ldy Player_Y_Speed          ;check player's vertical speed
  13303.          checky
  13304.          bpl DoFootCheck             ;if player not moving upwards, branch elsewhere
  13305.          ldy SCRATCHPAD+$04                     ;check lower nybble of vertical coordinate returned
  13306.          cpyn ++$04                    ;from collision detection routine
  13307.               cmpcy
  13308.          bcc DoFootCheck             ;if low nybble <  4, branch
  13309.          jsr CheckForSolidMTiles     ;check to see what player's head bumped on
  13310.          bcs SolidOrClimb            ;if player collided with solid metatile, branch
  13311.          ldy AreaType                ;otherwise check area type
  13312.          checky
  13313.          beq NYSpd                   ;if water level, branch ahead
  13314.          ldy BlockBounceTimer        ;if block bounce timer not expired,
  13315.          checky
  13316.          bne NYSpd                   ;branch ahead, do not process collision
  13317.          jsr PlayerHeadCollision     ;otherwise do a sub to process collision
  13318.          jmp DoFootCheck             ;jump ahead to skip these other parts here
  13319.  
  13320. SolidOrClimb:
  13321.        cmpn ++$26               ;if climbing metatile,
  13322.        beq NYSpd              ;branch ahead and do not play sound
  13323.        ldan ++Sfx_Bump
  13324.        sta Square1SoundQueue  ;otherwise load bump sound
  13325. NYSpd: ldan ++$01               ;set player's vertical speed to nullify
  13326.        sta Player_Y_Speed     ;jump or swim
  13327.  
  13328. DoFootCheck:
  13329.       ldy SCRATCHPAD+$eb                    ;get block buffer adder offset ;0,7,14?
  13330.       lda Player_Y_Position
  13331.       cmpn ++$cf                   ;check to see how low player is
  13332.               cmpcy
  13333.       bcs DoPlayerSideCheck      ;if player is too far down on screen, skip all of this
  13334.       jsr BlockBufferColli_Feet  ;do player-to-bg collision detection on bottom left of player
  13335.       jsr CheckForCoinMTiles     ;check to see if player touched coin with their left foot
  13336.       bcs AwardTouchedCoin       ;if so, branch to some other part of code
  13337.       pha                        ;save bottom left metatile to stack
  13338.       jsr BlockBufferColli_Feet  ;do player-to-bg collision detection on bottom right of player
  13339.       sta SCRATCHPAD+$00                    ;save bottom right metatile here
  13340.       pla
  13341.       sta SCRATCHPAD+$01                    ;pull bottom left metatile and save here
  13342.          checka
  13343.       bne ChkFootMTile           ;if anything here, skip this part
  13344.       lda SCRATCHPAD+$00                    ;otherwise check for anything in bottom right metatile
  13345.          checka
  13346.       beq DoPlayerSideCheck      ;and skip ahead if not
  13347.       jsr CheckForCoinMTiles     ;check to see if player touched coin with their right foot
  13348.       bcc ChkFootMTile           ;if not, skip unconditional jump and continue code
  13349.  
  13350. AwardTouchedCoin:
  13351.       jmp HandleCoinMetatile     ;follow the code to erase coin and award to player 1 coin
  13352.  
  13353. ChkFootMTile:
  13354.           jsr CheckForClimbMTiles    ;check to see if player landed on climbable metatiles
  13355.           bcs DoPlayerSideCheck      ;if so, branch
  13356.           ldy Player_Y_Speed         ;check player's vertical speed
  13357.          checky
  13358.           bmi DoPlayerSideCheck      ;if player moving upwards, branch
  13359.           cmpn ++$c5
  13360.           bne ContChk                ;if player did not touch axe, skip ahead
  13361.           jmp HandleAxeMetatile      ;otherwise jump to set modes of operation
  13362. ContChk:  jsr ChkInvisibleMTiles     ;do sub to check for hidden coin or 1-up blocks
  13363.           beq DoPlayerSideCheck      ;if either found, branch
  13364.           ldy JumpspringAnimCtrl     ;if jumpspring animating right now,
  13365.          checky
  13366.           bne InitSteP               ;branch ahead
  13367.           ldy SCRATCHPAD+$04                    ;check lower nybble of vertical coordinate returned
  13368.           cpyn ++$05                   ;from collision detection routine
  13369.               cmpcy
  13370.           bcc LandPlyr               ;if lower nybble <  5, branch
  13371.           lda Player_MovingDir
  13372.           sta SCRATCHPAD+$00                    ;use player's moving direction as temp variable
  13373.           jmp ImpedePlayerMove       ;jump to impede player's movement in that direction
  13374. LandPlyr: jsr ChkForLandJumpSpring   ;do sub to check for jumpspring metatiles and deal with it
  13375.           ldan ++$f0
  13376.           andi Player_Y_Position      ;mask out lower nybble of player's vertical position
  13377.           sta Player_Y_Position      ;and store as new vertical position to land player properly
  13378.           jsr HandlePipeEntry        ;do sub to process potential pipe entry
  13379.           ldan ++$00
  13380.           sta Player_Y_Speed         ;initialize vertical speed and fractional
  13381.           sta Player_Y_MoveForce     ;movement force to stop player's vertical movement
  13382.           sta StompChainCounter      ;initialize enemy stomp counter
  13383. InitSteP: ldan ++$00
  13384.           sta Player_State           ;set player's state to normal
  13385.  
  13386. DoPlayerSideCheck:
  13387.       ldy SCRATCHPAD+$eb       ;get block buffer adder offset ;ъръюх шёїюфэюх ёюёЄю эшх???0,7,14?
  13388.       iny
  13389.       iny           ;increment offset 2 bytes to use adders for side collisions ;ёэрўрыр яЁютхЁ хь ёяЁртр??? (р т ЄрсышЎрї ссюъёют т√уы фшЄ ъръ ыхтр  ёЄюЁюэр???)
  13390.       ldan ++$02      ;set value here to be used as counter
  13391.       sta SCRATCHPAD+$00
  13392.  
  13393. SideCheckLoop:
  13394.        iny                       ;move onto the next one ;эрўшэрхь ёю ёьх∙хэш  3 т ЄрсышЎрї ссюъёют, яюЄюь 4,5,6???
  13395.        sty SCRATCHPAD+$eb                   ;store it
  13396.        lda Player_Y_Position
  13397.        cmpn ++$20                  ;check player's vertical position
  13398.               cmpcy
  13399.        bcc BHalf                 ;if player is in status bar area, branch ahead to skip this part
  13400.        cmpn ++$e4
  13401.               cmpcy
  13402.        bcs ExSCH                 ;branch to leave if player is too far down
  13403.        jsr BlockBufferColli_Side ;do player-to-bg collision detection on one half of player
  13404.        beq BHalf                 ;branch ahead if nothing found
  13405.        cmpn ++$1c                  ;otherwise check for pipe metatiles
  13406.        beq BHalf                 ;if collided with sideways pipe (top), branch ahead
  13407.        cmpn ++$6b
  13408.        beq BHalf                 ;if collided with water pipe (top), branch ahead
  13409.        jsr CheckForClimbMTiles   ;do sub to see if player bumped into anything climbable
  13410.        bcc CheckSideMTiles       ;if not, branch to alternate section of code
  13411. BHalf: ldy SCRATCHPAD+$eb                   ;load block adder offset
  13412.        iny                       ;increment it ;???
  13413.        lda Player_Y_Position     ;get player's vertical position
  13414.        cmpn ++$08
  13415.               cmpcy
  13416.        bcc ExSCH                 ;if too high, branch to leave
  13417.        cmpn ++$d0
  13418.               cmpcy
  13419.        bcs ExSCH                 ;if too low, branch to leave
  13420.        jsr BlockBufferColli_Side ;do player-to-bg collision detection on other half of player
  13421.        bne CheckSideMTiles       ;if something found, branch
  13422.        deci SCRATCHPAD+$00                   ;otherwise decrement counter ;єўшЄ√трхЄё  т ImpedePlayerMove (ыхтр  ёЄюЁюэр=1??? шыш эрюсюЁюЄ???)
  13423.        bne SideCheckLoop         ;run code until both sides of player are checked ;хёыш чръюььхэЄшЁютрЄ№, Єю эх яюьюурхЄ тющЄш т ЄЁєсє ёЁрчє, эю ЄхяхЁ№ яЁюїюфшЄ ъшЁяшўш тяЁртю эрёътюч№
  13424. ExSCH: rts                       ;leave
  13425.  
  13426. CheckSideMTiles:
  13427.           jsr ChkInvisibleMTiles     ;check for hidden or coin 1-up blocks
  13428.           beq ExCSM                  ;branch to leave if either found
  13429.           jsr CheckForClimbMTiles    ;check for climbable metatiles
  13430.           bcc ContSChk               ;if not found, skip and continue with code
  13431.           jmp HandleClimbing         ;otherwise jump to handle climbing
  13432. ContSChk: jsr CheckForCoinMTiles     ;check to see if player touched coin
  13433.           bcs HandleCoinMetatile     ;if so, execute code to erase coin and award to player 1 coin
  13434.           jsr ChkJumpspringMetatiles ;check for jumpspring metatiles
  13435.           bcc ChkPBtm                ;if not found, branch ahead to continue cude
  13436.           lda JumpspringAnimCtrl     ;otherwise check jumpspring animation control
  13437.          checka
  13438.           bne ExCSM                  ;branch to leave if set
  13439.           jmp StopPlayerMove         ;otherwise jump to impede player's movement
  13440. ChkPBtm:  ldy Player_State           ;get player's state
  13441.         ;jr $ ;ёЄюыъэєышё№ ёяЁртр ё тхЁїюь ЄЁєс√, шфє∙хщ тяЁртю ($1c)
  13442.           cpyn ++$00                   ;check for player's state set to normal
  13443.           bne StopPlayerMove         ;if not, branch to impede player's movement ;эх яюьюурхЄ тющЄш т ЄЁєсє ёЁрчє ;ўхьє Ёртхэ (SCRATCHPAD+$00)? (ыхтр  ёЄюЁюэр=1???)
  13444.           ldy PlayerFacingDir        ;get player's facing direction
  13445.           dey
  13446.           bne StopPlayerMove         ;if facing left, branch to impede movement
  13447.           cmpn ++$6c                   ;otherwise check for pipe metatiles
  13448.           beq PipeDwnS               ;if collided with sideways pipe (bottom), branch
  13449.           cmpn ++$1f                   ;if collided with water pipe (bottom), continue
  13450.           bne StopPlayerMove         ;otherwise branch to impede player's movement
  13451. PipeDwnS: lda Player_SprAttrib       ;check player's attributes
  13452.         ;jr $ ;ё■фр яюярфрхь эх ёЁрчє, ъръ Єюы№ъю тёЄрыш ёэшчє є ЄЁєс√, р яюёых эрцрЄш  тяЁртю Єрь - ¤Єю яюЁЄшЄ фхьє
  13453.          checka
  13454.           bne PlyrPipe               ;if already set, branch, do not play sound again
  13455.           ldyn ++Sfx_PipeDown_Injury
  13456.           sty Square1SoundQueue      ;otherwise load pipedown/injury sound
  13457. PlyrPipe: oran ++%00100000
  13458.           sta Player_SprAttrib       ;set background priority bit in player attributes
  13459.           lda Player_X_Position
  13460.           andn ++%00001111             ;get lower nybble of player's horizontal coordinate
  13461.           beq ChkGERtn               ;if at zero, branch ahead to skip this part
  13462.           ldyn ++$00                   ;set default offset for timer setting data
  13463.           lda ScreenLeft_PageLoc     ;load page location for left side of screen
  13464.          checka
  13465.           beq SetCATmr               ;if at page zero, use default offset
  13466.           iny                        ;otherwise increment offset
  13467. SetCATmr: lday AreaChangeTimerData,y  ;set timer for change of area as appropriate
  13468.           sta ChangeAreaTimer
  13469. ChkGERtn: lda GameEngineSubroutine   ;get number of game engine routine running
  13470.           cmpn ++$07
  13471.           beq ExCSM                  ;if running player entrance routine or
  13472.           cmpn ++$08                   ;player control routine, go ahead and branch to leave
  13473.           bne ExCSM
  13474.           ldan ++$02
  13475.           sta GameEngineSubroutine   ;otherwise set sideways pipe entry routine to run
  13476.           rts                        ;and leave
  13477.  
  13478. ;--------------------------------
  13479. ;$02 - high nybble of vertical coordinate from block buffer
  13480. ;$04 - low nybble of horizontal coordinate from block buffer
  13481. ;$06-$07 - block buffer address
  13482.  
  13483. StopPlayerMove:
  13484. ;хёыш яЁютхЁ хь ъюыышчш■ ёяЁртр, Єю (SCRATCHPAD+$00) != 1!!! шыш эрюсюЁюЄ?
  13485.        jsr ImpedePlayerMove      ;stop player's movement
  13486. ExCSM: rts                       ;leave
  13487.      
  13488. AreaChangeTimerData:
  13489.       .db $a0, $34
  13490.  
  13491. HandleCoinMetatile:
  13492.         ;jr $
  13493.       jsr ErACM             ;do sub to erase coin metatile from block buffer
  13494.       inci CoinTallyFor1Ups  ;increment coin tally used for 1-up blocks
  13495.       jmp GiveOneCoin       ;update coin amount and tally on the screen
  13496.  
  13497. HandleAxeMetatile:
  13498.        ldan ++$00
  13499.        sta OperMode_Task   ;reset secondary mode
  13500.        ldan ++$02
  13501.        sta OperMode        ;set primary mode to autoctrl mode
  13502.        ldan ++$18
  13503.        sta Player_X_Speed  ;set horizontal speed and continue to erase axe metatile
  13504. ErACM: ldy SCRATCHPAD+$02             ;load vertical high nybble offset for block buffer
  13505.        ldan ++$00            ;load blank metatile
  13506.        stayindirect (SCRATCHPAD+$06),y         ;store to remove old contents from block buffer
  13507.        jmp RemoveCoin_Axe  ;update the screen accordingly
  13508.  
  13509. ;--------------------------------
  13510. ;$02 - high nybble of vertical coordinate from block buffer
  13511. ;$04 - low nybble of horizontal coordinate from block buffer
  13512. ;$06-$07 - block buffer address
  13513.  
  13514. ClimbXPosAdder:
  13515.       .db $f9, $07
  13516.  
  13517. ClimbPLocAdder:
  13518.       .db $ff, $00
  13519.  
  13520. FlagpoleYPosData:
  13521.       .db $18, $22, $50, $68, $90
  13522.  
  13523. HandleClimbing:
  13524.       ldy SCRATCHPAD+$04            ;check low nybble of horizontal coordinate returned from
  13525.       cpyn ++$06           ;collision detection routine against certain values, this
  13526.               cmpcy
  13527.       bcc ExHC           ;makes actual physical part of vine or flagpole thinner
  13528.       cpyn ++$0a           ;than 16 pixels
  13529.               cmpcy
  13530.       bcc ChkForFlagpole
  13531. ExHC: rts                ;leave if too far left or too far right
  13532.  
  13533. ChkForFlagpole:
  13534.       cmpn ++$24               ;check climbing metatiles
  13535.       beq FlagpoleCollision  ;branch if flagpole ball found
  13536.       cmpn ++$25
  13537.       bne VineCollision      ;branch to alternate code if flagpole shaft not found
  13538.  
  13539. FlagpoleCollision:
  13540.       lda GameEngineSubroutine
  13541.       cmpn ++$05                  ;check for end-of-level routine running
  13542.       beq PutPlayerOnVine       ;if running, branch to end of climbing code
  13543.       ldan ++$01
  13544.       sta PlayerFacingDir       ;set player's facing direction to right
  13545.       inci ScrollLock            ;set scroll lock flag
  13546.       lda GameEngineSubroutine
  13547.       cmpn ++$04                  ;check for flagpole slide routine running
  13548.       beq RunFR                 ;if running, branch to end of flagpole code here
  13549.       ldan ++BulletBill_CannonVar ;load identifier for bullet bills (cannon variant)
  13550.       jsr KillEnemies           ;get rid of them
  13551.       ldan ++Silence
  13552.       sta EventMusicQueue       ;silence music
  13553.       lsr
  13554.       sta FlagpoleSoundQueue    ;load flagpole sound into flagpole sound queue
  13555.       ldxn ++$04                  ;start at end of vertical coordinate data
  13556.       lda Player_Y_Position
  13557.       sta FlagpoleCollisionYPos ;store player's vertical coordinate here to be used later
  13558.  
  13559. ChkFlagpoleYPosLoop:
  13560.        cmpx FlagpoleYPosData,x    ;compare with current vertical coordinate data
  13561.               cmpcy
  13562.        bcs MtchF                 ;if player's =>  current, branch to use current offset
  13563.        dex                       ;otherwise decrement offset to use
  13564.        bne ChkFlagpoleYPosLoop   ;do this until all data is checked (use last one if all checked)
  13565. MtchF: stx FlagpoleScore         ;store offset here to be used later
  13566. RunFR: ldan ++$04
  13567.        sta GameEngineSubroutine  ;set value to run flagpole slide routine
  13568.        jmp PutPlayerOnVine       ;jump to end of climbing code
  13569.  
  13570. VineCollision:
  13571.       cmpn ++$26                  ;check for climbing metatile used on vines
  13572.       bne PutPlayerOnVine
  13573.       lda Player_Y_Position     ;check player's vertical coordinate
  13574.       cmpn ++$20                  ;for being in status bar area
  13575.               cmpcy
  13576.       bcs PutPlayerOnVine       ;branch if not that far up
  13577.       ldan ++$01
  13578.       sta GameEngineSubroutine  ;otherwise set to run autoclimb routine next frame
  13579.  
  13580. PutPlayerOnVine:
  13581.          ldan ++$03                ;set player state to climbing
  13582.          sta Player_State
  13583.          ldan ++$00                ;nullify player's horizontal speed
  13584.          sta Player_X_Speed      ;and fractional horizontal movement force
  13585.          sta Player_X_MoveForce ; (ьырф°р  ўрёЄ№ X-ъююЁфшэрЄ√)
  13586.          lda Player_X_Position   ;get player's horizontal coordinate
  13587.          secsub
  13588.          sbci ScreenLeft_X_Pos    ;subtract from left side horizontal coordinate
  13589.          cmpn ++$10
  13590.               cmpcy
  13591.          bcs SetVXPl             ;if 16 or more pixels difference, do not alter facing direction
  13592.          ldan ++$02
  13593.          sta PlayerFacingDir     ;otherwise force player to face left
  13594. SetVXPl: ldy PlayerFacingDir     ;get current facing direction, use as offset
  13595.          lda SCRATCHPAD+$06                 ;get low byte of block buffer address
  13596.          asl
  13597.          asl                     ;move low nybble to high
  13598.          asl
  13599.          asl
  13600.          clc
  13601.          adcy ClimbXPosAdder-1,y  ;add pixels depending on facing direction
  13602.          sta Player_X_Position   ;store as player's horizontal coordinate
  13603.          lda SCRATCHPAD+$06                 ;get low byte of block buffer address again
  13604.          checka
  13605.          bne ExPVne              ;if not zero, branch
  13606.          lda ScreenRight_PageLoc ;load page location of right side of screen
  13607.          clc
  13608.          adcy ClimbPLocAdder-1,y  ;add depending on facing location
  13609.          sta Player_PageLoc      ;store as player's page location
  13610. ExPVne:  rts                     ;finally, we're done!
  13611.  
  13612. ;--------------------------------
  13613.  
  13614. ChkInvisibleMTiles:
  13615.          cmpn ++$5f       ;check for hidden coin block
  13616.          beq ExCInvT    ;branch to leave if found
  13617.          cmpn ++$60       ;check for hidden 1-up block
  13618. ExCInvT:
  13619.               cmpcy ;???
  13620.          rts            ;leave with zero flag set if either found
  13621.  
  13622. ;--------------------------------
  13623. ;$00-$01 - used to hold bottom right and bottom left metatiles (in that order)
  13624. ;$00 - used as flag by ImpedePlayerMove to restrict specific movement
  13625.  
  13626. ChkForLandJumpSpring:
  13627.         jsr ChkJumpspringMetatiles  ;do sub to check if player landed on jumpspring
  13628.         bcc ExCJSp                  ;if carry not set, jumpspring not found, therefore leave
  13629.         ldan ++$70
  13630.         sta VerticalForce           ;otherwise set vertical movement force for player
  13631.         ldan ++$f9
  13632.         sta JumpspringForce         ;set default jumpspring force
  13633.         ldan ++$03
  13634.         sta JumpspringTimer         ;set jumpspring timer to be used later
  13635.         lsr
  13636.         sta JumpspringAnimCtrl      ;set jumpspring animation control to start animating
  13637. ExCJSp: rts                         ;and leave
  13638.  
  13639. ChkJumpspringMetatiles:
  13640.          cmpn ++$67      ;check for top jumpspring metatile
  13641.          beq JSFnd     ;branch to set carry if found
  13642.          cmpn ++$68      ;check for bottom jumpspring metatile
  13643.          clc           ;clear carry flag
  13644.          bne NoJSFnd   ;branch to use cleared carry if not found
  13645. JSFnd:   sec           ;set carry if found
  13646. NoJSFnd: rts           ;leave
  13647.  
  13648. HandlePipeEntry:
  13649.          lda Up_Down_Buttons       ;check saved controller bits from earlier
  13650.          andn ++%00000100            ;for pressing down
  13651.          beq ExPipeE               ;if not pressing down, branch to leave
  13652.          lda SCRATCHPAD+$00
  13653.          cmpn ++$11                  ;check right foot metatile for warp pipe right metatile
  13654.          bne ExPipeE               ;branch to leave if not found
  13655.          lda SCRATCHPAD+$01
  13656.          cmpn ++$10                  ;check left foot metatile for warp pipe left metatile
  13657.          bne ExPipeE               ;branch to leave if not found
  13658.          ldan ++$30
  13659.          sta ChangeAreaTimer       ;set timer for change of area
  13660.          ldan ++$03
  13661.          sta GameEngineSubroutine  ;set to run vertical pipe entry routine on next frame
  13662.          ldan ++Sfx_PipeDown_Injury
  13663.          sta Square1SoundQueue     ;load pipedown/injury sound
  13664.          ldan ++%00100000
  13665.          sta Player_SprAttrib      ;set background priority bit in player's attributes
  13666.          lda WarpZoneControl       ;check warp zone control
  13667.          checka
  13668.          beq ExPipeE               ;branch to leave if none found
  13669.          andn ++%00000011            ;mask out all but 2 LSB
  13670.          asl
  13671.          asl                       ;multiply by four
  13672.          tax                       ;save as offset to warp zone numbers (starts at left pipe)
  13673.          lda Player_X_Position     ;get player's horizontal position
  13674.          cmpn ++$60      
  13675.               cmpcy
  13676.          bcc GetWNum               ;if player at left, not near middle, use offset and skip ahead
  13677.          inx                       ;otherwise increment for middle pipe
  13678.          cmpn ++$a0      
  13679.               cmpcy
  13680.          bcc GetWNum               ;if player at middle, but not too far right, use offset and skip
  13681.          inx                       ;otherwise increment for last pipe
  13682. GetWNum: ldyx WarpZoneNumbers,x     ;get warp zone numbers
  13683.          dey                       ;decrement for use as world number
  13684.          sty WorldNumber           ;store as world number and offset
  13685.          ldxy WorldAddrOffsets,y    ;get offset to where this world's area offsets are
  13686.          ldax AreaAddrOffsets,x     ;get area offset based on world offset
  13687.          sta AreaPointer           ;store area offset here to be used to change areas
  13688.          ldan ++Silence
  13689.          sta EventMusicQueue       ;silence music
  13690.          ldan ++$00
  13691.          sta EntrancePage          ;initialize starting page number
  13692.          sta AreaNumber            ;initialize area number used for area address offset
  13693.          sta LevelNumber           ;initialize level number used for world display
  13694.          sta AltEntranceControl    ;initialize mode of entry
  13695.          inci Hidden1UpFlag         ;set flag for hidden 1-up blocks
  13696.          inci FetchNewGameTimerFlag ;set flag to load new game timer
  13697. ExPipeE: rts                       ;leave!!!
  13698.  
  13699. ImpedePlayerMove:
  13700. ;хёыш яЁютхЁ хь ъюыышчш■ ёяЁртр, Єю (SCRATCHPAD+$00) != 1!!! шыш эрюсюЁюЄ??? яюЁЄшЄ (SCRATCHPAD+$00)
  13701. ;єёЄрэртыштрхЄ Player_CollisionBits, SideCollisionTimer, фтшурхЄ X ш XSpeed
  13702.        ldan ++$00                  ;initialize value here
  13703.        ldy Player_X_Speed        ;get player's horizontal speed
  13704.        ldx SCRATCHPAD+$00                   ;check value set earlier for
  13705.        dex                       ;left side collision
  13706.       ;jr RImpd
  13707.       bne RImpd                 ;if right side collision, skip this part ;хёыш jr RImpd, Єю т 53672 яЁюїюфшЄ т яЁртє■ ЄЁєсє яЁртшы№эю, эю тїюфшЄ тыхтю т ёЄхэ√ ш эх юёЄрэртыштрхЄё  эр чрьъх!!!???
  13708. ;яЁютхЁ ыш ёяЁртр???
  13709.        inx                       ;return value to X
  13710.        cpyn ++$00                  ;if player moving to the left,
  13711.        bmi ExIPM                 ;branch to invert bit and leave ;шуЁюъ ёЄюыъэєыё  ёяЁртр, эю шф╕Є тыхтю - эшўхую эх фхырхь
  13712.        ldan ++$ff                  ;otherwise load A with value to be used later (¤Єю ёфтшэхЄ шуЁюър тыхтю эр 1 яшъё)
  13713.        jmp NXSpd                 ;and jump to affect movement
  13714. RImpd: ldxn ++$02                  ;return $02 to X
  13715.        cpyn ++$01                  ;if player moving to the right,
  13716.        bpl ExIPM                 ;branch to invert bit and leave
  13717.        ldan ++$01                  ;otherwise load A with value to be used here
  13718. NXSpd: ldyn ++$10
  13719.        sty SideCollisionTimer    ;set timer of some sort
  13720.        ldyn ++$00
  13721.        sty Player_X_Speed        ;nullify player's horizontal speed
  13722.        cmpn ++$00                  ;if value set in A not set to $ff,
  13723.        bpl PlatF                 ;branch ahead, do not decrement Y
  13724.        dey                       ;otherwise decrement Y now
  13725. PlatF: sty SCRATCHPAD+$00                   ;store Y as high bits of horizontal adder
  13726.        clc
  13727.        adci Player_X_Position     ;add contents of A to player's horizontal
  13728.        sta Player_X_Position     ;position to move player left or right
  13729.        lda Player_PageLoc
  13730.        adci SCRATCHPAD+$00                   ;add high bits and carry to
  13731.        sta Player_PageLoc        ;page location if necessary
  13732. ExIPM: txa                       ;invert contents of X
  13733.        eorn ++$ff ;1->fe, 2->fd
  13734.        andi Player_CollisionBits  ;mask out bit that was set here
  13735.        sta Player_CollisionBits  ;store to clear bit
  13736.        rts
  13737.  
  13738. ;--------------------------------
  13739.  
  13740. SolidMTileUpperExt:
  13741.       .db $10, $61, $88, $c4
  13742.  
  13743. CheckForSolidMTiles:
  13744. ;a=metatile
  13745. ;out: CY=???
  13746.       jsr GetMTileAttrib        ;find appropriate offset based on metatile's 2 MSB
  13747.       cmpx SolidMTileUpperExt,x  ;compare current metatile with solid metatiles
  13748.        cmpcy
  13749.       rts
  13750.  
  13751. ClimbMTileUpperExt:
  13752.       .db $24, $6d, $8a, $c6
  13753.  
  13754. CheckForClimbMTiles:
  13755. ;a=metatile
  13756. ;out: CY=???
  13757.       jsr GetMTileAttrib        ;find appropriate offset based on metatile's 2 MSB
  13758.       cmpx ClimbMTileUpperExt,x  ;compare current metatile with climbable metatiles
  13759.        cmpcy
  13760.       rts
  13761.  
  13762. CheckForCoinMTiles:
  13763. ;out: CY=1:touched coin
  13764.          cmpn ++$c2              ;check for regular coin
  13765.          beq CoinSd            ;branch if found
  13766.          cmpn ++$c3              ;check for underwater coin
  13767.          beq CoinSd            ;branch if found
  13768.          clc                   ;otherwise clear carry and leave
  13769.          rts
  13770. CoinSd:  ldan ++Sfx_CoinGrab
  13771.          sta Square2SoundQueue ;load coin grab sound and leave
  13772.         scf
  13773.          rts
  13774.  
  13775. GetMTileAttrib:
  13776.        tay            ;save metatile value into Y
  13777.        andn ++%11000000 ;mask out all but 2 MSB
  13778.        asl
  13779.        rol            ;shift and rotate d7-d6 to d1-d0
  13780.        rol
  13781.        tax            ;use as offset for metatile data
  13782.        tya            ;get original metatile value back
  13783. ExEBG: rts            ;leave
  13784.  
  13785. ;-------------------------------------------------------------------------------------
  13786. ;$06-$07 - address from block buffer routine
  13787.  
  13788. EnemyBGCStateData:
  13789.       .db $01, $01, $02, $02, $02, $05
  13790.  
  13791. EnemyBGCXSpdData:
  13792.       .db $10, $f0
  13793.  
  13794. EnemyToBGCollisionDet:
  13795.       ldax Enemy_State,x        ;check enemy state for d6 set
  13796.       andn ++%00100000
  13797.       bne ExEBG                ;if set, branch to leave
  13798.       jsr SubtEnemyYPos        ;otherwise, do a subroutine here
  13799.       bcc ExEBG                ;if enemy vertical coord + 62 <  68, branch to leave
  13800.       ldyx Enemy_ID,x
  13801.       cpyn ++Spiny               ;if enemy object is not spiny, branch elsewhere
  13802.       bne DoIDCheckBGColl
  13803.       ldax Enemy_Y_Position,x
  13804.       cmpn ++$25                 ;if enemy vertical coordinate <  36 branch to leave
  13805.               cmpcy
  13806.       bcc ExEBG
  13807.  
  13808. DoIDCheckBGColl:
  13809.        cpyn ++GreenParatroopaJump ;check for some other enemy object
  13810.        bne HBChk                ;branch if not found
  13811.        jmp EnemyJump            ;otherwise jump elsewhere
  13812. HBChk: cpyn ++HammerBro           ;check for hammer bro
  13813.        bne CInvu                ;branch if not found
  13814.        jmp HammerBroBGColl      ;otherwise jump elsewhere
  13815. CInvu: cpyn ++Spiny               ;if enemy object is spiny, branch
  13816.        beq YesIn
  13817.        cpyn ++PowerUpObject       ;if special power-up object, branch
  13818.        beq YesIn
  13819.        cpyn ++$07                 ;if enemy object => $07, branch to leave
  13820.               cmpcy
  13821.        bcs ExEBGChk
  13822. YesIn: jsr ChkUnderEnemy        ;if enemy object <  $07, or = $12 or $2e, do this sub
  13823.        bne HandleEToBGCollision ;if block underneath enemy, branch
  13824.  
  13825. NoEToBGCollision:
  13826.        jmp ChkForRedKoopa       ;otherwise skip and do something else
  13827.  
  13828. ;--------------------------------
  13829. ;$02 - vertical coordinate from block buffer routine
  13830.  
  13831. HandleEToBGCollision:
  13832.       jsr ChkForNonSolids       ;if something is underneath enemy, find out what
  13833.       beq NoEToBGCollision      ;if blank $26, coins, or hidden blocks, jump, enemy falls through
  13834.       cmpn ++$23
  13835.       bne LandEnemyProperly     ;check for blank metatile $23 and branch if not found
  13836.       ldy SCRATCHPAD+$02                   ;get vertical coordinate used to find block
  13837.       ldan ++$00                  ;store default blank metatile in that spot so we won't
  13838.       stayindirect (SCRATCHPAD+$06),y               ;trigger this routine accidentally again
  13839.       ldax Enemy_ID,x
  13840.       cmpn ++$15                  ;if enemy object =HIGH  $15, branch ahead
  13841.               cmpcy
  13842.       bcs ChkToStunEnemies
  13843.       cmpn ++Goomba               ;if enemy object not goomba, branch ahead of this routine
  13844.       bne GiveOEPoints
  13845.       jsr KillEnemyAboveBlock   ;if enemy object IS goomba, do this sub
  13846.  
  13847. GiveOEPoints:
  13848.       ldan ++$01                  ;award 100 points for hitting block beneath enemy
  13849.       jsr SetupFloateyNumber
  13850.  
  13851. ChkToStunEnemies:
  13852.           cmpn ++$09                   ;perform many comparisons on enemy object identifier
  13853.               cmpcy
  13854.           bcc SetStun      
  13855.           cmpn ++$11                   ;if the enemy object identifier is equal to the values
  13856.               cmpcy
  13857.           bcs SetStun                ;$09, $0e, $0f or $10, it will be modified, and not
  13858.           cmpn ++$0a                   ;modified if not any of those values, note that piranha plant will
  13859.               cmpcy
  13860.           bcc Demote                 ;always fail this test because A will still have vertical
  13861.           cmpn ++PiranhaPlant          ;coordinate from previous addition, also these comparisons
  13862.               cmpcy
  13863.           bcc SetStun                ;are only necessary if branching from $d7a1
  13864. Demote:   andn ++%00000001             ;erase all but LSB, essentially turning enemy object
  13865.           stax Enemy_ID,x             ;into green or red koopa troopa to demote them
  13866. SetStun:  ldax Enemy_State,x          ;load enemy state
  13867.           andn ++%11110000             ;save high nybble
  13868.           oran ++%00000010
  13869.           stax Enemy_State,x          ;set d1 of enemy state
  13870.           decx Enemy_Y_Position,x
  13871.           decx Enemy_Y_Position,x     ;subtract two pixels from enemy's vertical position
  13872.           ldax Enemy_ID,x
  13873.           cmpn ++Bloober               ;check for bloober object
  13874.           beq SetWYSpd
  13875.           ldan ++$fd                   ;set default vertical speed
  13876.           ldy AreaType
  13877.          checky
  13878.           bne SetNotW                ;if area type not water, set as speed, otherwise
  13879. SetWYSpd: ldan ++$ff                   ;change the vertical speed
  13880. SetNotW:  stax Enemy_Y_Speed,x        ;set vertical speed now
  13881.           ldyn ++$01
  13882.           jsr PlayerEnemyDiff        ;get horizontal difference between player and enemy object
  13883.           bpl ChkBBill               ;branch if enemy is to the right of player
  13884.           iny                        ;increment Y if not
  13885. ChkBBill: ldax Enemy_ID,x      
  13886.           cmpn ++BulletBill_CannonVar  ;check for bullet bill (cannon variant)
  13887.           beq NoCDirF
  13888.           cmpn ++BulletBill_FrenzyVar  ;check for bullet bill (frenzy variant)
  13889.           beq NoCDirF                ;branch if either found, direction does not change
  13890.           styx Enemy_MovingDir,x      ;store as moving direction
  13891. NoCDirF:  dey                        ;decrement and use as offset
  13892.           lday EnemyBGCXSpdData,y     ;get proper horizontal speed
  13893.           stax Enemy_X_Speed,x        ;and store, then leave
  13894. ExEBGChk: rts
  13895.  
  13896. ;--------------------------------
  13897. ;$04 - low nybble of vertical coordinate from block buffer routine
  13898.  
  13899. LandEnemyProperly:
  13900.        lda SCRATCHPAD+$04                 ;check lower nybble of vertical coordinate saved earlier
  13901.        secsub
  13902.        sbcn ++$08                ;subtract eight pixels
  13903.        cmpn ++$05                ;used to determine whether enemy landed from falling
  13904.               cmpcy
  13905.        bcs ChkForRedKoopa      ;branch if lower nybble in range of $0d-$0f before subtract
  13906.        ldax Enemy_State,x      
  13907.        andn ++%01000000          ;branch if d6 in enemy state is set
  13908.        bne LandEnemyInitState
  13909.        ldax Enemy_State,x
  13910.        asl                     ;branch if d7 in enemy state is not set
  13911.        bcc ChkLandedEnemyState
  13912. SChkA: jmp DoEnemySideCheck    ;if lower nybble LOW  $0d, d7 set but d6 not set, jump here
  13913.  
  13914. ChkLandedEnemyState:
  13915.            ldax Enemy_State,x         ;if enemy in normal state, branch back to jump here
  13916.          checka
  13917.            beq SChkA
  13918.            cmpn ++$05                  ;if in state used by spiny's egg
  13919.            beq ProcEnemyDirection    ;then branch elsewhere
  13920.            cmpn ++$03                  ;if already in state used by koopas and buzzy beetles
  13921.               cmpcy
  13922.            bcs ExSteChk              ;or in higher numbered state, branch to leave
  13923.            ldax Enemy_State,x         ;load enemy state again (why?)
  13924.            cmpn ++$02                  ;if not in $02 state (used by koopas and buzzy beetles)
  13925.            bne ProcEnemyDirection    ;then branch elsewhere
  13926.            ldan ++$10                  ;load default timer here
  13927.            ldyx Enemy_ID,x            ;check enemy identifier for spiny
  13928.            cpyn ++Spiny
  13929.            bne SetForStn             ;branch if not found
  13930.            ldan ++$00                  ;set timer for $00 if spiny
  13931. SetForStn: stax EnemyIntervalTimer,x  ;set timer here
  13932.            ldan ++$03                  ;set state here, apparently used to render
  13933.            stax Enemy_State,x         ;upside-down koopas and buzzy beetles
  13934.            jsr EnemyLanding          ;then land it properly
  13935. ExSteChk:  rts                       ;then leave
  13936.  
  13937. ProcEnemyDirection:
  13938.          ldax Enemy_ID,x            ;check enemy identifier for goomba
  13939.          cmpn ++Goomba               ;branch if found
  13940.          beq LandEnemyInitState
  13941.          cmpn ++Spiny                ;check for spiny
  13942.          bne InvtD                 ;branch if not found
  13943.          ldan ++$01
  13944.          stax Enemy_MovingDir,x     ;send enemy moving to the right by default
  13945.          ldan ++$08
  13946.          stax Enemy_X_Speed,x       ;set horizontal speed accordingly
  13947.          lda FrameCounter
  13948.          andn ++%00000111            ;if timed appropriately, spiny will skip over
  13949.          beq LandEnemyInitState    ;trying to face the player
  13950. InvtD:   ldyn ++$01                  ;load 1 for enemy to face the left (inverted here)
  13951.          jsr PlayerEnemyDiff       ;get horizontal difference between player and enemy
  13952.          bpl CNwCDir               ;if enemy to the right of player, branch
  13953.          iny                       ;if to the left, increment by one for enemy to face right (inverted)
  13954. CNwCDir: tya
  13955.          cmpx Enemy_MovingDir,x     ;compare direction in A with current direction in memory
  13956.          bne LandEnemyInitState
  13957.          jsr ChkForBump_HammerBroJ ;if equal, not facing in correct dir, do sub to turn around
  13958.  
  13959. LandEnemyInitState:
  13960.       jsr EnemyLanding       ;land enemy properly
  13961.       ldax Enemy_State,x
  13962.       andn ++%10000000         ;if d7 of enemy state is set, branch
  13963.       bne NMovShellFallBit
  13964.       ldan ++$00               ;otherwise initialize enemy state and leave
  13965.       stax Enemy_State,x      ;note this will also turn spiny's egg into spiny
  13966.       rts
  13967.  
  13968. NMovShellFallBit:
  13969.       ldax Enemy_State,x   ;nullify d6 of enemy state, save other bits
  13970.       andn ++%10111111      ;and store, then leave
  13971.       stax Enemy_State,x
  13972.       rts
  13973.  
  13974. ;--------------------------------
  13975.  
  13976. ChkForRedKoopa:
  13977.              ldax Enemy_ID,x            ;check for red koopa troopa $03
  13978.              cmpn ++RedKoopa
  13979.              bne Chk2MSBSt             ;branch if not found
  13980.              ldax Enemy_State,x
  13981.          checka
  13982.              beq ChkForBump_HammerBroJ ;if enemy found and in normal state, branch
  13983. Chk2MSBSt:   ldax Enemy_State,x         ;save enemy state into Y
  13984.              tay
  13985.              asl                       ;check for d7 set
  13986.              bcc GetSteFromD           ;branch if not set
  13987.              ldax Enemy_State,x
  13988.              oran ++%01000000            ;set d6
  13989.              jmp SetD6Ste              ;jump ahead of this part
  13990. GetSteFromD: lday EnemyBGCStateData,y   ;load new enemy state with old as offset
  13991. SetD6Ste:    stax Enemy_State,x         ;set as new state
  13992.  
  13993. ;--------------------------------
  13994. ;$00 - used to store bitmask (not used but initialized here)
  13995. ;$eb - used in DoEnemySideCheck as counter and to compare moving directions
  13996.  
  13997. DoEnemySideCheck:
  13998.           ldax Enemy_Y_Position,x     ;if enemy within status bar, branch to leave
  13999.           cmpn ++$20                   ;because there's nothing there that impedes movement
  14000.               cmpcy
  14001.           bcc ExESdeC
  14002.           ldyn ++$16                   ;start by finding block to the left of enemy ($00,$14)
  14003.           ldan ++$02                   ;set value here in what is also used as
  14004.           sta SCRATCHPAD+$eb                    ;OAM data offset
  14005. SdeCLoop: lda SCRATCHPAD+$eb                    ;check value
  14006.           cmpx Enemy_MovingDir,x      ;compare value against moving direction
  14007.           bne NextSdeC               ;branch if different and do not seek block there
  14008.           ldan ++$01                   ;set flag in A for save horizontal coordinate
  14009.           jsr BlockBufferChk_Enemy   ;find block to left or right of enemy object
  14010.           beq NextSdeC               ;if nothing found, branch
  14011.           jsr ChkForNonSolids        ;check for non-solid blocks
  14012.           bne ChkForBump_HammerBroJ  ;branch if not found
  14013. NextSdeC: deci SCRATCHPAD+$eb                    ;move to the next direction
  14014.           iny
  14015.           cpyn ++$18                   ;increment Y, loop only if Y <  $18, thus we check
  14016.               cmpcy
  14017.           bcc SdeCLoop               ;enemy ($00, $14) and ($10, $14) pixel coordinates
  14018. ExESdeC:  rts
  14019.  
  14020. ChkForBump_HammerBroJ:
  14021.         cpxn ++$05               ;check if we're on the special use slot
  14022.         beq NoBump             ;and if so, branch ahead and do not play sound
  14023.         ldax Enemy_State,x      ;if enemy state d7 not set, branch
  14024.         asl                    ;ahead and do not play sound
  14025.         bcc NoBump
  14026.         ldan ++Sfx_Bump          ;otherwise, play bump sound
  14027.         sta Square1SoundQueue  ;sound will never be played if branching from ChkForRedKoopa
  14028. NoBump: ldax Enemy_ID,x         ;check for hammer bro
  14029.         cmpn ++$05
  14030.         bne InvEnemyDir        ;branch if not found
  14031.         ldan ++$00
  14032.         sta SCRATCHPAD+$00                ;initialize value here for bitmask  
  14033.         ldyn ++$fa               ;load default vertical speed for jumping
  14034.         jmp SetHJ              ;jump to code that makes hammer bro jump
  14035.  
  14036. InvEnemyDir:
  14037.       jmp RXSpd     ;jump to turn the enemy around
  14038.  
  14039. ;--------------------------------
  14040. ;$00 - used to hold horizontal difference between player and enemy
  14041.  
  14042. PlayerEnemyDiff:
  14043.       ldax Enemy_X_Position,x  ;get distance between enemy object's
  14044.       secsub                     ;horizontal coordinate and the player's
  14045.       sbci Player_X_Position   ;horizontal coordinate
  14046.       sta SCRATCHPAD+$00                 ;and store here
  14047.       ldaxkeepcy Enemy_PageLoc,x
  14048.       sbci Player_PageLoc      ;subtract borrow, then leave
  14049.        cmpcy ;шёяюы№чєхЄё  юфшэ Ёрч
  14050.       rts
  14051.  
  14052. ;--------------------------------
  14053.  
  14054. EnemyLanding:
  14055.       jsr InitVStf            ;do something here to vertical speed and something else
  14056.       ldax Enemy_Y_Position,x
  14057.       andn ++%11110000          ;save high nybble of vertical coordinate, and
  14058.       oran ++%00001000          ;set d3, then store, probably used to set enemy object
  14059.       stax Enemy_Y_Position,x  ;neatly on whatever it's landing on
  14060.       rts
  14061.  
  14062. SubtEnemyYPos:
  14063.       ldax Enemy_Y_Position,x  ;add 62 pixels to enemy object's
  14064.       clc                     ;vertical coordinate
  14065.       adcn ++$3e
  14066.       cmpn ++$44                ;compare against a certain range
  14067.               cmpcy
  14068.       rts                     ;and leave with flags set for conditional branch
  14069.  
  14070. EnemyJump:
  14071.         jsr SubtEnemyYPos     ;do a sub here
  14072.         bcc DoSide            ;if enemy vertical coord + 62 LOW  68, branch to leave
  14073.         ldax Enemy_Y_Speed,x
  14074.         clc                   ;add two to vertical speed
  14075.         adcn ++$02
  14076.         cmpn ++$03              ;if green paratroopa not falling, branch ahead
  14077.               cmpcy
  14078.         bcc DoSide
  14079.         jsr ChkUnderEnemy     ;otherwise, check to see if green paratroopa is
  14080.         beq DoSide            ;standing on anything, then branch to same place if not
  14081.         jsr ChkForNonSolids   ;check for non-solid blocks
  14082.         beq DoSide            ;branch if found
  14083.         jsr EnemyLanding      ;change vertical coordinate and speed
  14084.         ldan ++$fd
  14085.         stax Enemy_Y_Speed,x   ;make the paratroopa jump again
  14086. DoSide: jmp DoEnemySideCheck  ;check for horizontal blockage, then leave
  14087.  
  14088. ;--------------------------------
  14089.  
  14090. HammerBroBGColl:
  14091.       jsr ChkUnderEnemy    ;check to see if hammer bro is standing on anything
  14092.       beq NoUnderHammerBro      
  14093.       cmpn ++$23             ;check for blank metatile $23 and branch if not found
  14094.       bne UnderHammerBro
  14095.  
  14096. KillEnemyAboveBlock:
  14097.       jsr ShellOrBlockDefeat  ;do this sub to kill enemy
  14098.       ldan ++$fc                ;alter vertical speed of enemy and leave
  14099.       stax Enemy_Y_Speed,x
  14100.       rts
  14101.  
  14102. UnderHammerBro:
  14103.       ldax EnemyFrameTimer,x ;check timer used by hammer bro
  14104.          checka
  14105.       bne NoUnderHammerBro  ;branch if not expired
  14106.       ldax Enemy_State,x
  14107.       andn ++%10001000        ;save d7 and d3 from enemy state, nullify other bits
  14108.       stax Enemy_State,x     ;and store
  14109.       jsr EnemyLanding      ;modify vertical coordinate, speed and something else
  14110.       jmp DoEnemySideCheck  ;then check for horizontal blockage and leave
  14111.  
  14112. NoUnderHammerBro:
  14113.       ldax Enemy_State,x  ;if hammer bro is not standing on anything, set d0
  14114.       oran ++$01           ;in the enemy state to indicate jumping or falling, then leave
  14115.       stax Enemy_State,x
  14116.       rts
  14117.  
  14118. ChkUnderEnemy:
  14119.       ldan ++$00                  ;set flag in A for save vertical coordinate
  14120.       ldyn ++$15                  ;set Y to check the bottom middle (8,18) of enemy object
  14121.       jmp BlockBufferChk_Enemy  ;hop to it!
  14122.  
  14123. ChkForNonSolids:
  14124.        cmpn ++$26       ;blank metatile used for vines?
  14125.        beq NSFnd
  14126.        cmpn ++$c2       ;regular coin?
  14127.        beq NSFnd
  14128.        cmpn ++$c3       ;underwater coin?
  14129.        beq NSFnd
  14130.        cmpn ++$5f       ;hidden coin block?
  14131.        beq NSFnd
  14132.        cmpn ++$60       ;hidden 1-up block?
  14133. NSFnd:
  14134.               cmpcy ;???
  14135.         rts
  14136.  
  14137. ;-------------------------------------------------------------------------------------
  14138.  
  14139. FireballBGCollision:
  14140.       ldax Fireball_Y_Position,x   ;check fireball's vertical coordinate
  14141.       cmpn ++$18
  14142.               cmpcy
  14143.       bcc ClearBounceFlag         ;if within the status bar area of the screen, branch ahead
  14144.       jsr BlockBufferChk_FBall    ;do fireball to background collision detection on bottom of it
  14145.       beq ClearBounceFlag         ;if nothing underneath fireball, branch
  14146.       jsr ChkForNonSolids         ;check for non-solid metatiles
  14147.       beq ClearBounceFlag         ;branch if any found
  14148.       ldax Fireball_Y_Speed,x      ;if fireball's vertical speed set to move upwards,
  14149.          checka
  14150.       bmi InitFireballExplode     ;branch to set exploding bit in fireball's state
  14151.       ldax FireballBouncingFlag,x  ;if bouncing flag already set,
  14152.          checka
  14153.       bne InitFireballExplode     ;branch to set exploding bit in fireball's state
  14154.       ldan ++$fd
  14155.       stax Fireball_Y_Speed,x      ;otherwise set vertical speed to move upwards (give it bounce)
  14156.       ldan ++$01
  14157.       stax FireballBouncingFlag,x  ;set bouncing flag
  14158.       ldax Fireball_Y_Position,x
  14159.       andn ++$f8                    ;modify vertical coordinate to land it properly
  14160.       stax Fireball_Y_Position,x   ;store as new vertical coordinate
  14161.       rts                         ;leave
  14162.  
  14163. ClearBounceFlag:
  14164.       ldan ++$00
  14165.       stax FireballBouncingFlag,x  ;clear bouncing flag by default
  14166.       rts                         ;leave
  14167.  
  14168. InitFireballExplode:
  14169.       ldan ++$80
  14170.       stax Fireball_State,x        ;set exploding flag in fireball's state
  14171.       ldan ++Sfx_Bump
  14172.       sta Square1SoundQueue       ;load bump sound
  14173.       rts                         ;leave
  14174.  
  14175. ;-------------------------------------------------------------------------------------
  14176. ;$00 - used to hold one of bitmasks, or offset
  14177. ;$01 - used for relative X coordinate, also used to store middle screen page location
  14178. ;$02 - used for relative Y coordinate, also used to store middle screen coordinate
  14179.  
  14180. ;this data added to relative coordinates of sprite objects
  14181. ;stored in order: left edge, top edge, right edge, bottom edge
  14182. BoundBoxCtrlData:
  14183.       .db $02, $08, $0e, $20
  14184.       .db $03, $14, $0d, $20
  14185.       .db $02, $14, $0e, $20
  14186.       .db $02, $09, $0e, $15
  14187.       .db $00, $00, $18, $06
  14188.       .db $00, $00, $20, $0d
  14189.       .db $00, $00, $30, $0d
  14190.       .db $00, $00, $08, $08
  14191.       .db $06, $04, $0a, $08
  14192.       .db $03, $0e, $0d, $14
  14193.       .db $00, $02, $10, $15
  14194.       .db $04, $04, $0c, $1c
  14195.  
  14196. GetFireballBoundBox:
  14197.       txa         ;add seven bytes to offset
  14198.       clc         ;to use in routines as offset for fireball
  14199.       adcn ++$07
  14200.       tax
  14201.       ldyn ++$02    ;set offset for relative coordinates
  14202.          checky
  14203.       bne FBallB  ;unconditional branch
  14204.  
  14205. GetMiscBoundBox:
  14206.         txa                       ;add nine bytes to offset
  14207.         clc                       ;to use in routines as offset for misc object
  14208.         adcn ++$09 ;эрўшэр  ё юс·хъЄр #9 шфєЄ misc objects (ўЄю ¤Єю???)
  14209.         tax
  14210.         ldyn ++$06                  ;set offset for relative coordinates
  14211. FBallB: jsr BoundingBoxCore       ;get bounding box coordinates
  14212.         jmp CheckRightScreenBBox  ;jump to handle any offscreen coordinates
  14213.  
  14214. GetEnemyBoundBox:
  14215.       ldyn ++$48                 ;store bitmask here for now
  14216.       sty SCRATCHPAD+$00
  14217.       ldyn ++$44                 ;store another bitmask here for now and jump
  14218.       jmp GetMaskedOffScrBits
  14219.  
  14220. SmallPlatformBoundBox:
  14221.       ldyn ++$08                 ;store bitmask here for now
  14222.       sty SCRATCHPAD+$00
  14223.       ldyn ++$04                 ;store another bitmask here for now
  14224.  
  14225. GetMaskedOffScrBits:
  14226.         ldax Enemy_X_Position,x      ;get enemy object position relative
  14227.         secsub                         ;to the left side of the screen
  14228.         sbci ScreenLeft_X_Pos
  14229.         sta SCRATCHPAD+$01                     ;store here
  14230.         ldaxkeepcy Enemy_PageLoc,x         ;subtract borrow from current page location
  14231.         sbci ScreenLeft_PageLoc      ;of left side
  14232.         bmi CMBits                  ;if enemy object is beyond left edge, branch
  14233.         orai SCRATCHPAD+$01 ;ёЄртшЄ Z???
  14234.         beq CMBits                  ;if precisely at the left edge, branch
  14235.         ldy SCRATCHPAD+$00                     ;if to the right of left edge, use value in $00 for A
  14236. CMBits: tya                         ;otherwise use contents of Y
  14237.         andi Enemy_OffscreenBits     ;preserve bitwise whatever's in here
  14238.         stax EnemyOffscrBitsMasked,x ;save masked offscreen bits here
  14239.          checka
  14240.         bne MoveBoundBoxOffscreen   ;if anything set here, branch
  14241.         jmp SetupEOffsetFBBox       ;otherwise, do something else
  14242.  
  14243. LargePlatformBoundBox:
  14244.         if Z80OPT
  14245.         push bc
  14246.       inc c                        ;increment X to get the proper offset
  14247.       call GetXOffscreenBits      ;then jump directly to the sub for horizontal offscreen bits
  14248.         pop bc                   ;decrement to return to original offset
  14249.         else
  14250.       inx                        ;increment X to get the proper offset
  14251.       jsr GetXOffscreenBits      ;then jump directly to the sub for horizontal offscreen bits
  14252.       dex                        ;decrement to return to original offset
  14253.         endif
  14254.       cmpn ++$fe                   ;if completely offscreen, branch to put entire bounding ;TODO >>4 т GetXOffscreenBits
  14255.               cmpcy
  14256.       bcs MoveBoundBoxOffscreen  ;box offscreen, otherwise start getting coordinates
  14257.  
  14258. SetupEOffsetFBBox:
  14259.       txa                        ;add 1 to offset to properly address
  14260.       clc                        ;the enemy object memory locations
  14261.       adcn ++$01
  14262.       tax
  14263.       ldyn ++$01                   ;load 1 as offset here, same reason
  14264.       jsr BoundingBoxCore        ;do a sub to get the coordinates of the bounding box
  14265.       jmp CheckRightScreenBBox   ;jump to handle offscreen coordinates of bounding box
  14266.  
  14267. MoveBoundBoxOffscreen:
  14268.       txa                            ;multiply offset by 4
  14269.       asl
  14270.       asl
  14271.       tay                            ;use as offset here
  14272.       ldan ++$ff
  14273.       stay EnemyBoundingBoxCoord,y    ;load value into four locations here and leave
  14274.       stay EnemyBoundingBoxCoord+1,y
  14275.       stay EnemyBoundingBoxCoord+2,y
  14276.       stay EnemyBoundingBoxCoord+3,y
  14277.       rts
  14278.  
  14279. BoundingBoxCore:
  14280. ;x=obj?
  14281. ;y=obj2?
  14282. ;keep x
  14283. ;out: y=x*4 (фы  яюёыхфє■∙хую CheckRightScreenBBox, т юёЄры№э√ї ёыєўр ї эх эєцэю)
  14284.         if Z80OPT ;???эхЄ ЁрчэшЎ√ т 1-2
  14285.         ld iy,SprObject_Rel_YPos
  14286.         add iy,de
  14287.         ld hl,SprObj_BoundBoxCtrl
  14288.         add hl,bc
  14289.       ld a,(hl)
  14290.       add a,a
  14291.       add a,a ;*4
  14292.      ld hl,BoundBoxCtrlData ;left edge, top edge, right edge, bottom edge (12 Єръшї ¤ыхьхэЄют)
  14293.      add a,l
  14294.      ld l,a
  14295.      adc a,h
  14296.      sub l
  14297.      ld h,a
  14298.       ld a,c ;txa                         ;multiply offset by four and save to stack
  14299.       add a,a
  14300.       add a,a ;*4
  14301.      ld e,a                        ;use as offset
  14302.      ;push de
  14303.         ld ix,BoundingBox_UL_Corner
  14304.         add ix,de
  14305.       ld a,(iy+SprObject_Rel_XPos-SprObject_Rel_YPos) ;object X coordinate relative to screen
  14306.       add a,(hl) ;adcx BoundBoxCtrlData,x     ;add the first number in the bounding box data to the
  14307.       ld (ix+BoundingBox_UL_Corner-BoundingBox_UL_Corner),a ;stay BoundingBox_UL_Corner,y ;store here
  14308.      sub (hl)
  14309.      inc hl
  14310.      inc hl
  14311.       add a,(hl) ;adcx BoundBoxCtrlData+2,x    ;add the third number in the bounding box data to the
  14312.       ld (ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner),a ;stay BoundingBox_LR_Corner,y ;relative horizontal coordinate and store
  14313.      dec hl
  14314.       ld a,(iy+SprObject_Rel_YPos-SprObject_Rel_YPos) ;object Y coordinate relative to screen
  14315.       add a,(hl);adcx BoundBoxCtrlData,x      ;add the second number to the relative vertical coordinate
  14316.       ld (ix+BoundingBox_UL_Corner-BoundingBox_UL_Corner+1),a ;stay BoundingBox_UL_Corner,y
  14317.      sub (hl)
  14318.      inc hl
  14319.      inc hl
  14320.       add a,(hl) ;adcx BoundBoxCtrlData+2,x    ;add the fourth number to the relative vertical coordinate
  14321.       ld (ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner+1),a ;stay BoundingBox_LR_Corner,y ;and store
  14322.      ;pop de
  14323.       ret
  14324.  
  14325. CheckRightScreenBBox:
  14326. ;y = x*4
  14327. ;ix = BoundingBox_UL_Corner + (x*4)
  14328.         ld iy,SprObject_X_Position
  14329.         add iy,bc
  14330.        lda ScreenLeft_X_Pos       ;add 128 pixels to left side of screen
  14331.        add a,0x80
  14332.        ld h,a;sta SCRATCHPAD+$02 ;and store as horizontal coordinate of middle
  14333.        lda ScreenLeft_PageLoc     ;add carry to page location of left side of screen
  14334.        adcn ++$00                   ;and store as page location of middle
  14335.        ld l,a;sta SCRATCHPAD+$01
  14336.        ld a,(iy+SprObject_X_Position-SprObject_X_Position) ;ldax SprObject_X_Position,x ;get horizontal coordinate
  14337.        sub h;cmpi SCRATCHPAD+$02                    ;compare against middle horizontal coordinate
  14338.        ld a,(iy+SprObject_PageLoc-SprObject_X_Position) ;ldaxkeepcy SprObject_PageLoc,x    ;get page location
  14339.        sbc a,l;sbci SCRATCHPAD+$01                    ;subtract from middle page location
  14340.        jr c,CheckLeftScreenBBox    ;if object is on the left side of the screen, branch
  14341.        ld a,(ix+BoundingBox_DR_XPos-BoundingBox_UL_Corner) ;lday BoundingBox_DR_XPos,y  ;check right-side edge of bounding box for offscreen
  14342.         or a
  14343.        bmi NoOfs                  ;coordinates, branch if still on the screen
  14344.        ld a,(ix+BoundingBox_UL_XPos-BoundingBox_UL_Corner) ;ldxy BoundingBox_UL_XPos,y  ;check left-side edge of bounding box for offscreen
  14345.         or a
  14346.        ldan ++$ff                   ;load offscreen value here to use on one or both horizontal sides
  14347.        bmi SORte                  ;coordinates, and branch if still on the screen
  14348.        ld (ix+BoundingBox_UL_XPos-BoundingBox_UL_Corner),a ;stay BoundingBox_UL_XPos,y  ;store offscreen value for left side
  14349. SORte: ld (ix+BoundingBox_DR_XPos-BoundingBox_UL_Corner),a ;stay BoundingBox_DR_XPos,y  ;store offscreen value for right side
  14350. NoOfs: ldx ObjectOffset           ;get object offset and leave
  14351.        ret
  14352.  
  14353. CheckLeftScreenBBox:
  14354.         ld a,(ix+BoundingBox_UL_XPos-BoundingBox_UL_Corner) ;lday BoundingBox_UL_XPos,y  ;check left-side edge of bounding box for offscreen
  14355.          or a
  14356.         bpl NoOfs2                 ;coordinates, and branch if still on the screen
  14357.         cmpn ++$a0                   ;check to see if left-side edge is in the middle of the
  14358.         jr c,NoOfs2                 ;screen or really offscreen, and branch if still on
  14359.         ld a,(ix+BoundingBox_DR_XPos-BoundingBox_UL_Corner) ;ldxy BoundingBox_DR_XPos,y  ;check right-side edge of bounding box for offscreen
  14360.          or a
  14361.         ldan ++$00
  14362.         bpl SOLft                  ;coordinates, branch if still onscreen
  14363.         ld (ix+BoundingBox_DR_XPos-BoundingBox_UL_Corner),a ;stay BoundingBox_DR_XPos,y  ;store offscreen value for right side
  14364. SOLft:  ld (ix+BoundingBox_UL_XPos-BoundingBox_UL_Corner),a ;stay BoundingBox_UL_XPos,y  ;store offscreen value for left side
  14365. NoOfs2: ldx ObjectOffset           ;get object offset and leave
  14366.         rts
  14367.      
  14368.         else ;~Z80
  14369. ;ЄєЄ ыюьрыюё№ юЄюсЁрцхэшх ыхтющ эюуш уЁшср
  14370. ;фхыю эх т яюЁўх SCRATCHPAD (яЁютхЁхэю ўхЁхч юЄфхы№э√щ сєЇхЁ)
  14371. ;фхыю эх т CY эр т√їюфх (яЁютхЁхэю ўхЁхч plakeepcy)
  14372. ;фхыю с√ыю т эхёючфрэшш ix фы  Z80-тхЁёшш CheckRightScreenBBox
  14373.       stx zSCRATCHPAD+$00                     ;save offset here
  14374.       lday SprObject_Rel_YPos,y    ;store object coordinates relative to screen
  14375.       sta zSCRATCHPAD+$02                     ;vertically and horizontally, respectively
  14376.       lday SprObject_Rel_XPos,y
  14377.       sta zSCRATCHPAD+$01
  14378.       txa                         ;multiply offset by four and save to stack
  14379.       asl
  14380.       asl
  14381.       pha
  14382.       tay                         ;use as offset for Y, X is left alone
  14383.       ldax SprObj_BoundBoxCtrl,x   ;load value here to be used as offset for X
  14384.       asl                         ;multiply that by four and use as X
  14385.       asl
  14386.       tax
  14387.       lda zSCRATCHPAD+$01                     ;add the first number in the bounding box data to the
  14388.       clc                         ;relative horizontal coordinate using enemy object offset
  14389.       adcx BoundBoxCtrlData,x      ;and store somewhere using same offset * 4
  14390.       stay BoundingBox_UL_Corner,y ;store here
  14391.       lda zSCRATCHPAD+$01
  14392.       clc
  14393.       adcx BoundBoxCtrlData+2,x    ;add the third number in the bounding box data to the
  14394.       stay BoundingBox_LR_Corner,y ;relative horizontal coordinate and store
  14395.       inx                         ;increment both offsets
  14396.       iny
  14397.       lda zSCRATCHPAD+$02                     ;add the second number to the relative vertical coordinate
  14398.       clc                         ;using incremented offset and store using the other
  14399.       adcx BoundBoxCtrlData,x      ;incremented offset
  14400.       stay BoundingBox_UL_Corner,y
  14401.       lda zSCRATCHPAD+$02
  14402.       clc
  14403.       adcx BoundBoxCtrlData+2,x    ;add the fourth number to the relative vertical coordinate
  14404.       stay BoundingBox_LR_Corner,y ;and store
  14405.       plakeepcy;pla                         ;get original offset loaded into $00 * y from stack
  14406.       tay                         ;use as Y
  14407.       ldx zSCRATCHPAD+$00                     ;get original offset and use as X again
  14408.       rts
  14409. zSCRATCHPAD=SCRATCHPAD
  14410.         ;ds 3
  14411.  
  14412. CheckRightScreenBBox:
  14413. ;y = x*4
  14414.        lda ScreenLeft_X_Pos       ;add 128 pixels to left side of screen
  14415.        clc                        ;and store as horizontal coordinate of middle
  14416.        adcn ++$80
  14417.        sta SCRATCHPAD+$02
  14418.        lda ScreenLeft_PageLoc     ;add carry to page location of left side of screen
  14419.        adcn ++$00                   ;and store as page location of middle
  14420.        sta SCRATCHPAD+$01
  14421.        ldax SprObject_X_Position,x ;get horizontal coordinate
  14422.        cmpi SCRATCHPAD+$02                    ;compare against middle horizontal coordinate
  14423.        ldaxkeepcy SprObject_PageLoc,x    ;get page location
  14424.        sbci SCRATCHPAD+$01                    ;subtract from middle page location
  14425.               cmpcy
  14426.        bcc CheckLeftScreenBBox    ;if object is on the left side of the screen, branch
  14427.        lday BoundingBox_DR_XPos,y  ;check right-side edge of bounding box for offscreen
  14428.          checka
  14429.        bmi NoOfs                  ;coordinates, branch if still on the screen
  14430.        ldan ++$ff                   ;load offscreen value here to use on one or both horizontal sides
  14431.        ldxy BoundingBox_UL_XPos,y  ;check left-side edge of bounding box for offscreen
  14432.          checkx
  14433.        bmi SORte                  ;coordinates, and branch if still on the screen
  14434.        stay BoundingBox_UL_XPos,y  ;store offscreen value for left side
  14435. SORte: stay BoundingBox_DR_XPos,y  ;store offscreen value for right side
  14436. NoOfs: ldx ObjectOffset           ;get object offset and leave
  14437.        rts
  14438.  
  14439. CheckLeftScreenBBox:
  14440.         lday BoundingBox_UL_XPos,y  ;check left-side edge of bounding box for offscreen
  14441.          checka
  14442.         bpl NoOfs2                 ;coordinates, and branch if still on the screen
  14443.         cmpn ++$a0                   ;check to see if left-side edge is in the middle of the
  14444.               cmpcy
  14445.         bcc NoOfs2                 ;screen or really offscreen, and branch if still on
  14446.         ldan ++$00
  14447.         ldxy BoundingBox_DR_XPos,y  ;check right-side edge of bounding box for offscreen
  14448.          checkx
  14449.         bpl SOLft                  ;coordinates, branch if still onscreen
  14450.         stay BoundingBox_DR_XPos,y  ;store offscreen value for right side
  14451. SOLft:  stay BoundingBox_UL_XPos,y  ;store offscreen value for left side
  14452. NoOfs2: ldx ObjectOffset           ;get object offset and leave
  14453.         rts
  14454.         endif
  14455.  
  14456. ;-------------------------------------------------------------------------------------
  14457. ;$06 - second object's offset
  14458. ;$07 - counter
  14459. ;y=second object's offset
  14460. ;эх яюЁЄшЄ y
  14461.  
  14462. ;TODO ЁрёъЁ√Є№ Ўшъы
  14463.  
  14464. PlayerCollisionCore:
  14465.       ldxn ++$00     ;initialize X to use player's bounding box for comparison
  14466.  
  14467. SprObjectCollisionCore:
  14468.  
  14469.         if Z80OPT2a
  14470.        
  14471.       push de;sty SCRATCHPAD+$06      ;save contents of Y here
  14472.       ld iy,BoundingBox_UL_Corner
  14473.       add iy,de
  14474.       ld ix,BoundingBox_UL_Corner
  14475.       add ix,bc
  14476.       ;ldan ++$01
  14477.       ld d,1 ;sta SCRATCHPAD+$07      ;save value 1 here as counter, compare horizontal coordinates first
  14478.      
  14479. CollisionCoreLoop:
  14480.       ld e,(ix)
  14481.       ld c,(ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner)
  14482.       ld a,(iy);lday BoundingBox_UL_Corner,y  ;compare left/top coordinates
  14483.       cp e;(ix);icmpx BoundingBox_UL_Corner,x  ;of first and second objects' bounding boxes
  14484.       jr nc,FirstBoxGreater          ;if first left/top =>  second, branch
  14485.       cp c;(ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner);cmpx BoundingBox_LR_Corner,x  ;otherwise compare to right/bottom of second
  14486.       jr c,SecondBoxVerticalChk     ;if first left/top <  second right/bottom, branch elsewhere
  14487.       jr z,CollisionFound           ;if somehow equal, collision, thus branch
  14488.        ld c,a
  14489.       ld a,(iy+BoundingBox_LR_Corner-BoundingBox_UL_Corner);lday BoundingBox_LR_Corner,y  ;if somehow greater, check to see if bottom of
  14490.       cp c;(iy);cmpy BoundingBox_UL_Corner,y  ;first object's bounding box is greater than its top
  14491.       jr c,CollisionFound           ;if somehow less, vertical wrap collision, thus branch
  14492.       cp e;(ix);cmpx BoundingBox_UL_Corner,x  ;otherwise compare bottom of first bounding box to the top
  14493.       jr nc,CollisionFound           ;of second box, and if equal or greater, collision, thus branch
  14494.       or a
  14495.       pop de;ldy SCRATCHPAD+$06                      ;otherwise return with carry clear and Y = $0006
  14496.       ret                       ;note horizontal wrapping never occurs
  14497.  
  14498. SecondBoxVerticalChk:
  14499.       ld a,(ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner);ldax BoundingBox_LR_Corner,x  ;check to see if the vertical bottom of the box
  14500.       cp e;(ix);cmpx BoundingBox_UL_Corner,x  ;is greater than the vertical top
  14501.       jr c,CollisionFound           ;if somehow less, vertical wrap collision, thus branch
  14502.       ld a,(iy+BoundingBox_LR_Corner-BoundingBox_UL_Corner);lday BoundingBox_LR_Corner,y  ;otherwise compare horizontal right or vertical bottom
  14503.       cp e;(ix);cmpx BoundingBox_UL_Corner,x  ;of first box with horizontal left or vertical top of second box
  14504.       jr nc,CollisionFound           ;if equal or greater, collision, thus branch
  14505.       or a
  14506.       pop de;ldy SCRATCHPAD+$06                      ;otherwise return with carry clear and Y = $0006
  14507.       ret
  14508.  
  14509. FirstBoxGreater:
  14510.       cp e;(ix);cmpx BoundingBox_UL_Corner,x  ;compare first and second box horizontal left/vertical top again
  14511.       jr z,CollisionFound           ;if first coordinate = second, collision, thus branch
  14512.       cp c;(ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner);cmpx BoundingBox_LR_Corner,x  ;if not, compare with second object right or bottom edge
  14513.       jr c,CollisionFound           ;if left/top of first less than or equal to right/bottom of second
  14514.       jr z,CollisionFound           ;then collision, thus branch
  14515.       cp (iy+BoundingBox_LR_Corner-BoundingBox_UL_Corner);cmpy BoundingBox_LR_Corner,y  ;otherwise check to see if top of first box is greater than bottom
  14516.       jr c,NoCollisionFound         ;if less than or equal, no collision, branch to end
  14517.       jr z,NoCollisionFound
  14518.       ld a,(iy+BoundingBox_LR_Corner-BoundingBox_UL_Corner);lday BoundingBox_LR_Corner,y  ;otherwise compare bottom of first to top of second
  14519.       cp c;(ix+BoundingBox_LR_Corner-BoundingBox_UL_Corner);cmpx BoundingBox_UL_Corner,x  ;if bottom of first is greater than top of second, vertical wrap
  14520.       jr nc,CollisionFound           ;collision, and branch, otherwise, proceed onwards here
  14521. NoCollisionFound:
  14522.       or a          ;clear carry, then load value set earlier, then leave
  14523.       pop de;ldy SCRATCHPAD+$06      ;like previous ones, if horizontal coordinates do not collide, we do
  14524.       ret          ;not bother checking vertical ones, because what's the point?
  14525.  
  14526. CollisionFound:
  14527.       inc ix ;inx                    ;increment offsets on both objects to check
  14528.       inc iy ;iny                    ;the vertical coordinates
  14529.       dec d ;deci SCRATCHPAD+$07                ;decrement counter to reflect this
  14530.       jp p,CollisionCoreLoop  ;if counter not expired, branch to loop
  14531.       scf                    ;otherwise we already did both sets, therefore collision, so set carry
  14532.       pop de;ldy SCRATCHPAD+$06                ;load original value set here earlier, then leave
  14533.       ret
  14534.        
  14535.         else ;~Z80
  14536.  
  14537.       sty SCRATCHPAD+$06      ;save contents of Y here
  14538.       ldan ++$01
  14539.       sta SCRATCHPAD+$07      ;save value 1 here as counter, compare horizontal coordinates first
  14540.  
  14541. CollisionCoreLoop:
  14542.       lday BoundingBox_UL_Corner,y  ;compare left/top coordinates
  14543.       cmpx BoundingBox_UL_Corner,x  ;of first and second objects' bounding boxes
  14544.               cmpcy
  14545.       bcs FirstBoxGreater          ;if first left/top =>  second, branch
  14546.       cmpx BoundingBox_LR_Corner,x  ;otherwise compare to right/bottom of second
  14547.               cmpcy
  14548.       bcc SecondBoxVerticalChk     ;if first left/top <  second right/bottom, branch elsewhere
  14549.       beq CollisionFound           ;if somehow equal, collision, thus branch
  14550.       lday BoundingBox_LR_Corner,y  ;if somehow greater, check to see if bottom of
  14551.       cmpy BoundingBox_UL_Corner,y  ;first object's bounding box is greater than its top
  14552.               cmpcy
  14553.       bcc CollisionFound           ;if somehow less, vertical wrap collision, thus branch
  14554.       cmpx BoundingBox_UL_Corner,x  ;otherwise compare bottom of first bounding box to the top
  14555.               cmpcy
  14556.       bcs CollisionFound           ;of second box, and if equal or greater, collision, thus branch
  14557.       ldy SCRATCHPAD+$06                      ;otherwise return with carry clear and Y = $0006
  14558.       rts                          ;note horizontal wrapping never occurs
  14559.  
  14560. SecondBoxVerticalChk:
  14561.       ldax BoundingBox_LR_Corner,x  ;check to see if the vertical bottom of the box
  14562.       cmpx BoundingBox_UL_Corner,x  ;is greater than the vertical top
  14563.               cmpcy
  14564.       bcc CollisionFound           ;if somehow less, vertical wrap collision, thus branch
  14565.       lday BoundingBox_LR_Corner,y  ;otherwise compare horizontal right or vertical bottom
  14566.       cmpx BoundingBox_UL_Corner,x  ;of first box with horizontal left or vertical top of second box
  14567.               cmpcy
  14568.       bcs CollisionFound           ;if equal or greater, collision, thus branch
  14569.       ldy SCRATCHPAD+$06                      ;otherwise return with carry clear and Y = $0006
  14570.       rts
  14571.  
  14572. FirstBoxGreater:
  14573.       cmpx BoundingBox_UL_Corner,x  ;compare first and second box horizontal left/vertical top again
  14574.       beq CollisionFound           ;if first coordinate = second, collision, thus branch
  14575.       cmpx BoundingBox_LR_Corner,x  ;if not, compare with second object right or bottom edge
  14576.               cmpcy
  14577.       bcc CollisionFound           ;if left/top of first less than or equal to right/bottom of second
  14578.       beq CollisionFound           ;then collision, thus branch
  14579.       cmpy BoundingBox_LR_Corner,y  ;otherwise check to see if top of first box is greater than bottom
  14580.               cmpcy
  14581.       bcc NoCollisionFound         ;if less than or equal, no collision, branch to end
  14582.       beq NoCollisionFound
  14583.       lday BoundingBox_LR_Corner,y  ;otherwise compare bottom of first to top of second
  14584.       cmpx BoundingBox_UL_Corner,x  ;if bottom of first is greater than top of second, vertical wrap
  14585.               cmpcy
  14586.       bcs CollisionFound           ;collision, and branch, otherwise, proceed onwards here
  14587.  
  14588. NoCollisionFound:
  14589.       clc          ;clear carry, then load value set earlier, then leave
  14590.       ldy SCRATCHPAD+$06      ;like previous ones, if horizontal coordinates do not collide, we do
  14591.       rts          ;not bother checking vertical ones, because what's the point?
  14592.  
  14593. CollisionFound:
  14594.       inx                    ;increment offsets on both objects to check
  14595.       iny                    ;the vertical coordinates
  14596.       deci SCRATCHPAD+$07                ;decrement counter to reflect this
  14597.       bpl CollisionCoreLoop  ;if counter not expired, branch to loop
  14598.       sec                    ;otherwise we already did both sets, therefore collision, so set carry
  14599.       ldy SCRATCHPAD+$06                ;load original value set here earlier, then leave
  14600.       rts
  14601.  
  14602.         endif
  14603.      
  14604. ;-------------------------------------------------------------------------------------
  14605. ;$02 - modified y coordinate
  14606. ;$03 - stores metatile involved in block buffer collisions
  14607. ;$04 - comes in with offset to block buffer adder data, goes out with low nybble x/y coordinate
  14608. ;$05 - modified x coordinate
  14609. ;$06-$07 - block buffer address
  14610.  
  14611. BlockBufferChk_Enemy:
  14612.       pha        ;save contents of A to stack
  14613.       txa
  14614.       clc        ;add 1 to X to run sub with enemy offset in mind
  14615.       adcn ++$01
  14616.       tax
  14617.       pla        ;pull A from stack and jump elsewhere
  14618.       jmp BBChk_E
  14619.  
  14620. ResidualMiscObjectCode:
  14621.       txa
  14622.       clc           ;supposedly used once to set offset for
  14623.       adcn ++$0d      ;miscellaneous objects
  14624.       tax
  14625.       ldyn ++$1b      ;supposedly used once to set offset for block buffer data
  14626.       jmp ResJmpM   ;probably used in early stages to do misc to bg collision detection
  14627.  
  14628. BlockBufferChk_FBall:
  14629.          ldyn ++$1a                  ;set offset for block buffer adder data
  14630.          txa
  14631.          clc
  14632.          adcn ++$07                  ;add seven bytes to use
  14633.          tax
  14634. ResJmpM: ldan ++$00                  ;set A to return vertical coordinate
  14635. BBChk_E: jsr BlockBufferCollision  ;do collision detection subroutine for sprite object
  14636.          ldx ObjectOffset          ;get object offset
  14637.          cmpn ++$00                  ;check to see if object bumped into anything
  14638.               cmpcy ;???
  14639.          rts
  14640.  
  14641. BlockBufferAdderData:
  14642.       .db $00, $07, $0e
  14643.  
  14644. ;юяшёрэшх срєэфшэу сюъёют фы  ёЄюыъэютхэш  ё ърЁЄющ???
  14645. BlockBuffer_X_Adder:
  14646. ;яхЁшюф 7 (т ърцфющ уЁєяях яхЁт√х 3 ўшёыр шёяюы№чє■Єё  Єюы№ъю фы  ьюэёЄЁют, юёЄры№э√х 4 фы  шуЁюър)
  14647.       .db $08, $03, $0c, $02, $02, $0d, $0d
  14648.       .db $08, $03, $0c, $02, $02, $0d, $0d
  14649.       .db $08, $03, $0c, $02, $02, $0d, $0d
  14650.       .db $08, $00, $10, $04, $14, $04, $04 ;ъръ ё■фр яюярёЄ№???
  14651.  
  14652. BlockBuffer_Y_Adder:
  14653. ;яхЁшюф 7 (т ърцфющ уЁєяях яхЁт√х 3 ўшёыр шёяюы№чє■Єё  Єюы№ъю фы  ьюэёЄЁют, юёЄры№э√х 4 фы  шуЁюър)
  14654.       .db $04, $20, $20, $08, $18, $08, $18
  14655.       .db $02, $20, $20, $08, $18, $08, $18
  14656.       .db $12, $20, $20, $18, $18, $18, $18
  14657.       .db $18, $14, $14, $06, $06, $08, $10 ;ъръ ё■фр яюярёЄ№???
  14658.  
  14659. BlockBufferColli_Feet:
  14660.        iny            ;if branched here, increment to next set of adders
  14661.  
  14662. BlockBufferColli_Head:
  14663. ;out: NZ=collision
  14664.        ldan ++$00       ;set flag to return vertical coordinate
  14665.        jr BlockBufferColli_Side_go;.db $2c        ;BIT instruction opcode
  14666.  
  14667. BlockBufferColli_Side:
  14668.        ldan ++$01       ;set flag to return horizontal coordinate
  14669. BlockBufferColli_Side_go
  14670.        ldxn ++$00       ;set offset for player object
  14671.  
  14672. BlockBufferCollision:
  14673. ;x=obj
  14674. ;y=??? (эхы№ч  яюЁЄшЄ№!) эхъшщ шэфхъё фы  BlockBuffer_X_Adder, BlockBuffer_Y_Adder
  14675. ;a=1: return X to ($04)
  14676. ;a=0: return Y to ($04)
  14677. ;х∙╕ єёЄрэртыштрхЄ ($02) = (y+yadder)&0xf0 - 32
  14678. ;х∙╕ єёЄрэртыштрхЄ ($06..07) = blockbuffer+x
  14679.         if Z80OPT
  14680.        ld hl,BlockBuffer_X_Adder
  14681.        add hl,de
  14682.        ld ix,SprObject_X_Position
  14683.        add ix,bc
  14684.          or a
  14685.        jr nz,RetXC                   ;if A = 1, branch
  14686.        ld a,(ix+SprObject_Y_Position-SprObject_X_Position) ;ldax SprObject_Y_Position,x  ;if A = 0, load vertical coordinate
  14687.        jp RetYC                   ;and jump
  14688. RetXC: ld a,(ix+SprObject_X_Position-SprObject_X_Position) ;ldax SprObject_X_Position,x  ;otherwise load horizontal coordinate
  14689. RetYC: and ++%00001111              ;and mask out high nybble
  14690.        ld (SCRATCHPAD+$04),a                     ;store masked out result here
  14691.  
  14692.        ld a,(hl) ;lday BlockBuffer_X_Adder,y   ;add horizontal coordinate
  14693.        add a,(ix+SprObject_X_Position-SprObject_X_Position) ;adcx SprObject_X_Position,x ;of object to value obtained using Y as offset
  14694.        ld l,a ;sta SCRATCHPAD+$05                     ;store here ;є эрё яюър 3???
  14695.        adc a,(ix+SprObject_PageLoc-SprObject_X_Position) ;adcn ++$00                    ;add carry to page location
  14696.        sub l
  14697.        rra                         ;move to carry ;xHSB
  14698.        ld a,l ;orai SCRATCHPAD+$05                     ;get stored value ;xLSB
  14699.         ld hl,Block_Buffer_1
  14700.         jr nc,$+5
  14701.          ld hl,Block_Buffer_2
  14702.        rra
  14703.        rra
  14704.        rra
  14705.        rra
  14706.         and 0x0f
  14707.         add a,l
  14708.         ld l,a
  14709.         ;adc a,h
  14710.         ;sub l
  14711.         ;ld h,a
  14712.         ld (SCRATCHPAD+$06),hl ;???
  14713.        ld hl,BlockBuffer_Y_Adder
  14714.        add hl,de
  14715.        ld a,(ix+SprObject_Y_Position-SprObject_X_Position) ;ldax SprObject_Y_Position,x  ;get vertical coordinate of object
  14716.        add a,(hl);adcy BlockBuffer_Y_Adder,y   ;add it to value obtained using Y as offset      
  14717.        and ++%11110000              ;mask out low nybble
  14718.        sub 32               ;subtract 32 pixels for the status bar
  14719.        ld (SCRATCHPAD+$02),a                     ;store result here ;???
  14720.        ;use as offset for block buffer
  14721.         ld hl,(SCRATCHPAD+$06)
  14722.         add a,l
  14723.         ld l,a
  14724.         adc a,h
  14725.         sub l
  14726.         ld h,a
  14727.        ;ld a,(hl) ;ldayindirect (SCRATCHPAD+$06),y                 ;check current content of block buffer
  14728.        ;sta SCRATCHPAD+$03                     ;and store here
  14729.        ld a,(hl) ;lda SCRATCHPAD+$03                     ;get saved content of block buffer
  14730.        ;lda SCRATCHPAD+$03                     ;get saved content of block buffer
  14731.         or a
  14732.        ret                         ;and leave
  14733.        
  14734.         else ;~Z80
  14735.        
  14736.        pha                         ;save contents of A to stack
  14737.        sty SCRATCHPAD+$04                     ;save contents of Y here
  14738.        lday BlockBuffer_X_Adder,y   ;add horizontal coordinate
  14739.        clc                         ;of object to value obtained using Y as offset
  14740.        adcx SprObject_X_Position,x
  14741.        sta SCRATCHPAD+$05                     ;store here ;є эрё яюър 3???
  14742.        ldaxkeepcy SprObject_PageLoc,x
  14743.        adcn ++$00                    ;add carry to page location
  14744.        andn ++$01                    ;get LSB, mask out all other bits
  14745.        lsr                         ;move to carry
  14746.       push af
  14747.        orai SCRATCHPAD+$05                     ;get stored value
  14748.       ld h,a
  14749.       pop af
  14750.       ld a,h
  14751.        ror                         ;rotate carry to MSB of A
  14752.        lsr                         ;and effectively move high nybble to
  14753.        lsr                         ;lower, LSB which became MSB will be
  14754.        lsr                         ;d4 at this point
  14755.        jsr GetBlockBufferAddr      ;get address of block buffer into $06, $07
  14756.        ldy SCRATCHPAD+$04                     ;get old contents of Y
  14757.        ldax SprObject_Y_Position,x  ;get vertical coordinate of object
  14758.        clc
  14759.        adcy BlockBuffer_Y_Adder,y   ;add it to value obtained using Y as offset
  14760.        andn ++%11110000              ;mask out low nybble
  14761.        secsub
  14762.        sbcn ++$20                    ;subtract 32 pixels for the status bar
  14763.        sta SCRATCHPAD+$02                     ;store result here
  14764.        tay                         ;use as offset for block buffer
  14765.        ldayindirect (SCRATCHPAD+$06),y                 ;check current content of block buffer
  14766.        sta SCRATCHPAD+$03                     ;and store here
  14767.        ldy SCRATCHPAD+$04                     ;get old contents of Y again
  14768.        pla                         ;pull A from stack
  14769.          checka
  14770.        bne RetXC                   ;if A = 1, branch
  14771.        ldax SprObject_Y_Position,x  ;if A = 0, load vertical coordinate
  14772.        jmp RetYC                   ;and jump
  14773. RetXC: ldax SprObject_X_Position,x  ;otherwise load horizontal coordinate
  14774. RetYC: andn ++%00001111              ;and mask out high nybble
  14775.        sta SCRATCHPAD+$04                     ;store masked out result here
  14776.        lda SCRATCHPAD+$03                     ;get saved content of block buffer
  14777.         checka
  14778.        rts                         ;and leave
  14779.         endif
  14780.  
  14781. ;-------------------------------------------------------------------------------------
  14782.  
  14783.         if Z80==0
  14784. ;unused byte
  14785.       .db $ff
  14786.         endif
  14787.  
  14788. ;-------------------------------------------------------------------------------------
  14789. ;$00 - offset to vine Y coordinate adder
  14790. ;$02 - offset to sprite data
  14791.  
  14792. VineYPosAdder:
  14793.       .db $00, $30
  14794.  
  14795. DrawVine:
  14796.          sty SCRATCHPAD+$00                    ;save offset here
  14797.          lda Enemy_Rel_YPos         ;get relative vertical coordinate
  14798.          clc
  14799.          adcy VineYPosAdder,y        ;add value using offset in Y to get value
  14800.          ldxy VineObjOffset,y        ;get offset to vine
  14801.          ldyx Enemy_SprDataOffset,x  ;get sprite data offset
  14802.          sty SCRATCHPAD+$02                    ;store sprite data offset here
  14803.          jsr SixSpriteStacker       ;stack six sprites on top of each other vertically
  14804.          lda Enemy_Rel_XPos         ;get relative horizontal coordinate
  14805.          stay Sprite_X_Position,y    ;store in first, third and fifth sprites
  14806.          stay Sprite_X_Position+8,y
  14807.          stay Sprite_X_Position+16,y
  14808.          clc
  14809.          adcn ++$06                   ;add six pixels to second, fourth and sixth sprites
  14810.          stay Sprite_X_Position+4,y  ;to give characteristic staggered vine shape to
  14811.          stay Sprite_X_Position+12,y ;our vertical stack of sprites
  14812.          stay Sprite_X_Position+20,y
  14813.          ldan ++%00100001             ;set bg priority and palette attribute bits
  14814.          stay Sprite_Attributes,y    ;set in first, third and fifth sprites
  14815.          stay Sprite_Attributes+8,y
  14816.          stay Sprite_Attributes+16,y
  14817.          oran ++%01000000             ;additionally, set horizontal flip bit
  14818.          stay Sprite_Attributes+4,y  ;for second, fourth and sixth sprites
  14819.          stay Sprite_Attributes+12,y
  14820.          stay Sprite_Attributes+20,y
  14821.          ldxn ++$05                   ;set tiles for six sprites
  14822. VineTL:  ldan ++$e1                   ;set tile number for sprite
  14823.          stay Sprite_Tilenumber,y
  14824.          iny                        ;move offset to next sprite data
  14825.          iny
  14826.          iny
  14827.          iny
  14828.          dex                        ;move onto next sprite
  14829.          bpl VineTL                 ;loop until all sprites are done
  14830.          ldy SCRATCHPAD+$02                    ;get original offset
  14831.          lda SCRATCHPAD+$00                    ;get offset to vine adding data
  14832.          checka
  14833.          bne SkpVTop                ;if offset not zero, skip this part
  14834.          ldan ++$e0
  14835.          stay Sprite_Tilenumber,y    ;set other tile number for top of vine
  14836. SkpVTop: ldxn ++$00                   ;start with the first sprite again
  14837. ChkFTop: lda VineStart_Y_Position   ;get original starting vertical coordinate
  14838.          secsub
  14839.          sbcy Sprite_Y_Position,y    ;subtract top-most sprite's Y coordinate
  14840.          cmpn ++$64                   ;if two coordinates are less than 100/$64 pixels
  14841.               cmpcy
  14842.          bcc NextVSp                ;apart, skip this to leave sprite alone
  14843.          ldan ++$f8
  14844.          stay Sprite_Y_Position,y    ;otherwise move sprite offscreen
  14845. NextVSp: iny                        ;move offset to next OAM data
  14846.          iny
  14847.          iny
  14848.          iny
  14849.          inx                        ;move onto next sprite
  14850.          cpxn ++$06                   ;do this until all sprites are checked
  14851.          bne ChkFTop
  14852.          ldy SCRATCHPAD+$00                    ;return offset set earlier
  14853.          rts
  14854.  
  14855. SixSpriteStacker:
  14856.        ldxn ++$06           ;do six sprites
  14857. StkLp: stay Sprite_Data,y  ;store X or Y coordinate into OAM data
  14858.        clc
  14859.        adcn ++$08           ;add eight pixels
  14860.        iny
  14861.        iny                ;move offset four bytes forward
  14862.        iny
  14863.        iny
  14864.        dex                ;do another sprite
  14865.        bne StkLp          ;do this until all sprites are done
  14866.        ldy SCRATCHPAD+$02            ;get saved OAM data offset and leave
  14867.        rts
  14868.  
  14869. ;-------------------------------------------------------------------------------------
  14870.  
  14871. FirstSprXPos:
  14872.       .db $04, $00, $04, $00
  14873.  
  14874. FirstSprYPos:
  14875.       .db $00, $04, $00, $04
  14876.  
  14877. SecondSprXPos:
  14878.       .db $00, $08, $00, $08
  14879.  
  14880. SecondSprYPos:
  14881.       .db $08, $00, $08, $00
  14882.  
  14883. FirstSprTilenum:
  14884.       .db $80, $82, $81, $83
  14885.  
  14886. SecondSprTilenum:
  14887.       .db $81, $83, $80, $82
  14888.  
  14889. HammerSprAttrib:
  14890.       .db $03, $03, $c3, $c3
  14891.  
  14892. DrawHammer:
  14893.             ldyx Misc_SprDataOffset,x    ;get misc object OAM data offset
  14894.             lda TimerControl
  14895.          checka
  14896.             bne ForceHPose              ;if master timer control set, skip this part
  14897.             ldax Misc_State,x            ;otherwise get hammer's state
  14898.             andn ++%01111111              ;mask out d7
  14899.             cmpn ++$01                    ;check to see if set to 1 yet
  14900.             beq GetHPose                ;if so, branch
  14901. ForceHPose: ldxn ++$00                    ;reset offset here
  14902.          checkx
  14903.             beq RenderH                 ;do unconditional branch to rendering part
  14904. GetHPose:   lda FrameCounter            ;get frame counter
  14905.             lsr                         ;move d3-d2 to d1-d0
  14906.             lsr
  14907.             andn ++%00000011              ;mask out all but d1-d0 (changes every four frames)
  14908.             tax                         ;use as timing offset
  14909. RenderH:    lda Misc_Rel_YPos           ;get relative vertical coordinate
  14910.             clc
  14911.             adcx FirstSprYPos,x          ;add first sprite vertical adder based on offset
  14912.             stay Sprite_Y_Position,y     ;store as sprite Y coordinate for first sprite
  14913.             clc
  14914.             adcx SecondSprYPos,x         ;add second sprite vertical adder based on offset
  14915.             stay Sprite_Y_Position+4,y   ;store as sprite Y coordinate for second sprite
  14916.             lda Misc_Rel_XPos           ;get relative horizontal coordinate
  14917.             clc
  14918.             adcx FirstSprXPos,x          ;add first sprite horizontal adder based on offset
  14919.             stay Sprite_X_Position,y     ;store as sprite X coordinate for first sprite
  14920.             clc
  14921.             adcx SecondSprXPos,x         ;add second sprite horizontal adder based on offset
  14922.             stay Sprite_X_Position+4,y   ;store as sprite X coordinate for second sprite
  14923.             ldax FirstSprTilenum,x
  14924.             stay Sprite_Tilenumber,y     ;get and store tile number of first sprite
  14925.             ldax SecondSprTilenum,x
  14926.             stay Sprite_Tilenumber+4,y   ;get and store tile number of second sprite
  14927.             ldax HammerSprAttrib,x
  14928.             stay Sprite_Attributes,y     ;get and store attribute bytes for both
  14929.             stay Sprite_Attributes+4,y   ;note in this case they use the same data
  14930.             ldx ObjectOffset            ;get misc object offset
  14931.             lda Misc_OffscreenBits
  14932.             andn ++%11111100              ;check offscreen bits
  14933.             beq NoHOffscr               ;if all bits clear, leave object alone
  14934.             ldan ++$00
  14935.             stax Misc_State,x            ;otherwise nullify misc object state
  14936.             ldan ++$f8
  14937.             jsr DumpTwoSpr              ;do sub to move hammer sprites offscreen
  14938. NoHOffscr:  rts                         ;leave
  14939.  
  14940. ;-------------------------------------------------------------------------------------
  14941. ;$00-$01 - used to hold tile numbers ($01 addressed in draw floatey number part)
  14942. ;$02 - used to hold Y coordinate for floatey number
  14943. ;$03 - residual byte used for flip (but value set here affects nothing)
  14944. ;$04 - attribute byte for floatey number
  14945. ;$05 - used as X coordinate for floatey number
  14946.  
  14947. FlagpoleScoreNumTiles:
  14948.       .db $f9, $50
  14949.       .db $f7, $50
  14950.       .db $fa, $fb
  14951.       .db $f8, $fb
  14952.       .db $f6, $fb
  14953.  
  14954. FlagpoleGfxHandler:
  14955.       ldyx Enemy_SprDataOffset,x      ;get sprite data offset for flagpole flag
  14956.       lda Enemy_Rel_XPos             ;get relative horizontal coordinate
  14957.       stay Sprite_X_Position,y        ;store as X coordinate for first sprite
  14958.       clc
  14959.       adcn ++$08                       ;add eight pixels and store
  14960.       stay Sprite_X_Position+4,y      ;as X coordinate for second and third sprites
  14961.       stay Sprite_X_Position+8,y
  14962.       clc
  14963.       adcn ++$0c                       ;add twelve more pixels and
  14964.           push af
  14965.       sta SCRATCHPAD+$05                        ;store here to be used later by floatey number
  14966.       ldax Enemy_Y_Position,x         ;get vertical coordinate
  14967.       jsr DumpTwoSpr                 ;and do sub to dump into first and second sprites
  14968.           ld h,a
  14969.           pop af
  14970.           ld a,h
  14971.       adcn ++$08                       ;add eight pixels
  14972.       stay Sprite_Y_Position+8,y      ;and store into third sprite
  14973.       lda FlagpoleFNum_Y_Pos         ;get vertical coordinate for floatey number
  14974.       sta SCRATCHPAD+$02                        ;store it here
  14975.       ldan ++$01
  14976.       sta SCRATCHPAD+$03                        ;set value for flip which will not be used, and
  14977.       sta SCRATCHPAD+$04                        ;attribute byte for floatey number
  14978.       stay Sprite_Attributes,y        ;set attribute bytes for all three sprites
  14979.       stay Sprite_Attributes+4,y
  14980.       stay Sprite_Attributes+8,y
  14981.       ldan ++$7e
  14982.       stay Sprite_Tilenumber,y        ;put triangle shaped tile
  14983.       stay Sprite_Tilenumber+8,y      ;into first and third sprites
  14984.       ldan ++$7f
  14985.       stay Sprite_Tilenumber+4,y      ;put skull tile into second sprite
  14986.       lda FlagpoleCollisionYPos      ;get vertical coordinate at time of collision
  14987.          checka
  14988.       beq ChkFlagOffscreen           ;if zero, branch ahead
  14989.       tya
  14990.       clc                            ;add 12 bytes to sprite data offset
  14991.       adcn ++$0c
  14992.       tay                            ;put back in Y
  14993.       lda FlagpoleScore              ;get offset used to award points for touching flagpole
  14994.       asl                            ;multiply by 2 to get proper offset here
  14995.       tax
  14996.         if Z80OPT
  14997.       ld hl,FlagpoleScoreNumTiles
  14998.       add hl,bc
  14999.       call DrawSpriteObject
  15000.         else
  15001.       ldax FlagpoleScoreNumTiles,x    ;get appropriate tile data
  15002.       sta SCRATCHPAD+$00
  15003.       ldax FlagpoleScoreNumTiles+1,x
  15004.       jsr DrawOneSpriteRow           ;use it to render floatey number
  15005.         endif
  15006.  
  15007. ChkFlagOffscreen:
  15008.       ldx ObjectOffset               ;get object offset for flag
  15009.       ldyx Enemy_SprDataOffset,x      ;get OAM data offset
  15010.       lda Enemy_OffscreenBits        ;get offscreen bits
  15011.       andn ++%00001110                 ;mask out all but d3-d1
  15012.       beq ExitDumpSpr                ;if none of these bits set, branch to leave
  15013.  
  15014. ;-------------------------------------------------------------------------------------
  15015.  
  15016. MoveSixSpritesOffscreen:
  15017.       ldan ++$f8                  ;set offscreen coordinate if jumping here
  15018.  
  15019. DumpSixSpr:
  15020.       stay Sprite_Data+20,y      ;dump A contents
  15021.       stay Sprite_Data+16,y      ;into third row sprites
  15022.  
  15023. DumpFourSpr:
  15024.       stay Sprite_Data+12,y      ;into second row sprites
  15025.  
  15026. DumpThreeSpr:
  15027.       stay Sprite_Data+8,y
  15028.  
  15029. DumpTwoSpr:
  15030.       stay Sprite_Data+4,y       ;and into first row sprites
  15031.       stay Sprite_Data,y
  15032.  
  15033. ExitDumpSpr:
  15034.       rts
  15035.  
  15036. ;-------------------------------------------------------------------------------------
  15037.  
  15038. DrawLargePlatform:
  15039.       ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  15040.       sty SCRATCHPAD+$02                     ;store here
  15041.       iny                         ;add 3 to it for offset
  15042.       iny                         ;to X coordinate
  15043.       iny
  15044.       lda Enemy_Rel_XPos          ;get horizontal relative coordinate
  15045.       jsr SixSpriteStacker        ;store X coordinates using A as base, stack horizontally
  15046.       ldx ObjectOffset
  15047.       ldax Enemy_Y_Position,x      ;get vertical coordinate
  15048.       jsr DumpFourSpr             ;dump into first four sprites as Y coordinate
  15049.       ldy AreaType
  15050.       cpyn ++$03                    ;check for castle-type level
  15051.       beq ShrinkPlatform
  15052.       ldy SecondaryHardMode       ;check for secondary hard mode flag set
  15053.          checky
  15054.       beq SetLast2Platform        ;branch if not set elsewhere
  15055.  
  15056. ShrinkPlatform:
  15057.       ldan ++$f8                    ;load offscreen coordinate if flag set or castle-type level
  15058.  
  15059. SetLast2Platform:
  15060.       ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  15061.       stay Sprite_Y_Position+16,y  ;store vertical coordinate or offscreen
  15062.       stay Sprite_Y_Position+20,y  ;coordinate into last two sprites as Y coordinate
  15063.       ldan ++$5b                    ;load default tile for platform (girder)
  15064.       ldx CloudTypeOverride
  15065.          checkx
  15066.       beq SetPlatformTilenum      ;if cloud level override flag not set, use
  15067.       ldan ++$75                    ;otherwise load other tile for platform (puff)
  15068.  
  15069. SetPlatformTilenum:
  15070. ;TODO ўхЁхч rla:jr nc,$+5;ld (ix),L
  15071.         ldx ObjectOffset            ;get enemy object buffer offset
  15072.         iny                         ;increment Y for tile offset
  15073.         jsr DumpSixSpr              ;dump tile number into all six sprites
  15074.         ldan ++$02                    ;set palette controls
  15075.         iny                         ;increment Y for sprite attributes
  15076.         jsr DumpSixSpr              ;dump attributes into all six sprites
  15077.         if Z80OPT
  15078.         push bc
  15079.       inc c                        ;increment X to get the proper offset
  15080.       call GetXOffscreenBits      ;then jump directly to the sub for horizontal offscreen bits
  15081.         pop bc                   ;decrement to return to original offset
  15082.         else
  15083.         inx                         ;increment X for enemy objects
  15084.         jsr GetXOffscreenBits       ;get offscreen bits again
  15085.         dex
  15086.         endif
  15087.         ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  15088.         asl                         ;rotate d7 into carry, save remaining ;TODO >>4 т GetXOffscreenBits
  15089.         pha                         ;bits to the stack
  15090.         bcc SChk2
  15091.         ldan ++$f8                    ;if d7 was set, move first sprite offscreen
  15092.         stay Sprite_Y_Position,y
  15093. SChk2:  pla                         ;get bits from stack
  15094.         asl                         ;rotate d6 into carry ;TODO >>4 т GetXOffscreenBits
  15095.         pha                         ;save to stack
  15096.         bcc SChk3
  15097.         ldan ++$f8                    ;if d6 was set, move second sprite offscreen
  15098.         stay Sprite_Y_Position+4,y
  15099. SChk3:  pla                         ;get bits from stack
  15100.         asl                         ;rotate d5 into carry ;TODO >>4 т GetXOffscreenBits
  15101.         pha                         ;save to stack
  15102.         bcc SChk4
  15103.         ldan ++$f8                    ;if d5 was set, move third sprite offscreen
  15104.         stay Sprite_Y_Position+8,y
  15105. SChk4:  pla                         ;get bits from stack
  15106.         asl                         ;rotate d4 into carry ;TODO >>4 т GetXOffscreenBits
  15107.         pha                         ;save to stack
  15108.         bcc SChk5
  15109.         ldan ++$f8                    ;if d4 was set, move fourth sprite offscreen
  15110.         stay Sprite_Y_Position+12,y
  15111. SChk5:  pla                         ;get bits from stack
  15112.         asl                         ;rotate d3 into carry ;???
  15113.         pha                         ;save to stack
  15114.         bcc SChk6
  15115.         ldan ++$f8                    ;if d3 was set, move fifth sprite offscreen
  15116.         stay Sprite_Y_Position+16,y
  15117. SChk6:  pla                         ;get bits from stack
  15118.         asl                         ;rotate d2 into carry ;???
  15119.         bcc SLChk                   ;save to stack
  15120.         ldan ++$f8
  15121.         stay Sprite_Y_Position+20,y  ;if d2 was set, move sixth sprite offscreen
  15122. SLChk:  lda Enemy_OffscreenBits     ;check d7 of offscreen bits
  15123.         asl                         ;and if d7 is not set, skip sub
  15124.         bcc ExDLPl
  15125.         jsr MoveSixSpritesOffscreen ;otherwise branch to move all sprites offscreen
  15126. ExDLPl: rts
  15127.  
  15128. ;-------------------------------------------------------------------------------------
  15129.  
  15130. DrawFloateyNumber_Coin:
  15131.           lda FrameCounter          ;get frame counter
  15132.           lsr                       ;divide by 2
  15133.           bcs NotRsNum              ;branch if d0 not set to raise number every other frame
  15134.           decx Misc_Y_Position,x     ;otherwise, decrement vertical coordinate
  15135. NotRsNum: ldax Misc_Y_Position,x     ;get vertical coordinate
  15136.           jsr DumpTwoSpr            ;dump into both sprites
  15137.           lda Misc_Rel_XPos         ;get relative horizontal coordinate
  15138.           stay Sprite_X_Position,y   ;store as X coordinate for first sprite
  15139.           clc
  15140.           adcn ++$08                  ;add eight pixels
  15141.           stay Sprite_X_Position+4,y ;store as X coordinate for second sprite
  15142.           ldan ++$02
  15143.           stay Sprite_Attributes,y   ;store attribute byte in both sprites
  15144.           stay Sprite_Attributes+4,y
  15145.           ldan ++$f7
  15146.           stay Sprite_Tilenumber,y   ;put tile numbers into both sprites
  15147.           ldan ++$fb                  ;that resemble "200"
  15148.           stay Sprite_Tilenumber+4,y
  15149.           jmp ExJCGfx               ;then jump to leave (why not an rts here instead?)
  15150.  
  15151. JumpingCoinTiles:
  15152.       .db $60, $61, $62, $63
  15153.  
  15154. JCoinGfxHandler:
  15155.          ldyx Misc_SprDataOffset,x    ;get coin/floatey number's OAM data offset
  15156.          ldax Misc_State,x            ;get state of misc object
  15157.          cmpn ++$02                    ;if 2 or greater,
  15158.               cmpcy
  15159.          bcs DrawFloateyNumber_Coin  ;branch to draw floatey number
  15160.          ldax Misc_Y_Position,x       ;store vertical coordinate as
  15161.          stay Sprite_Y_Position,y     ;Y coordinate for first sprite
  15162.          clc
  15163.          adcn ++$08                    ;add eight pixels
  15164.          stay Sprite_Y_Position+4,y   ;store as Y coordinate for second sprite
  15165.          lda Misc_Rel_XPos           ;get relative horizontal coordinate
  15166.          stay Sprite_X_Position,y
  15167.          stay Sprite_X_Position+4,y   ;store as X coordinate for first and second sprites
  15168.          lda FrameCounter            ;get frame counter
  15169.          lsr                         ;divide by 2 to alter every other frame
  15170.          andn ++%00000011              ;mask out d2-d1
  15171.          tax                         ;use as graphical offset
  15172.          ldax JumpingCoinTiles,x      ;load tile number
  15173.          iny                         ;increment OAM data offset to write tile numbers
  15174.          jsr DumpTwoSpr              ;do sub to dump tile number into both sprites
  15175.          dey                         ;decrement to get old offset
  15176.          ldan ++$02
  15177.          stay Sprite_Attributes,y     ;set attribute byte in first sprite
  15178.          ldan ++$82
  15179.          stay Sprite_Attributes+4,y   ;set attribute byte with vertical flip in second sprite
  15180.          ldx ObjectOffset            ;get misc object offset
  15181. ExJCGfx: rts                         ;leave
  15182.  
  15183. ;-------------------------------------------------------------------------------------
  15184. ;$00-$01 - used to hold tiles for drawing the power-up, $00 also used to hold power-up type
  15185. ;$02 - used to hold bottom row Y position
  15186. ;$03 - used to hold flip control (not used here)
  15187. ;$04 - used to hold sprite attributes
  15188. ;$05 - used to hold X position
  15189. ;$07 - counter
  15190.  
  15191. ;tiles arranged in top left, right, bottom left, right order
  15192. PowerUpGfxTable:
  15193.       .db $76, $77, $78, $79 ;regular mushroom
  15194.       .db $d6, $d6, $d9, $d9 ;fire flower
  15195.       .db $8d, $8d, $e4, $e4 ;star
  15196.       .db $76, $77, $78, $79 ;1-up mushroom
  15197.  
  15198. PowerUpAttributes:
  15199.       .db $02, $01, $02, $01
  15200.  
  15201. DrawPowerUp:
  15202.       ldy Enemy_SprDataOffset+5  ;get power-up's sprite data offset
  15203.       lda Enemy_Rel_YPos         ;get relative vertical coordinate
  15204.       clc
  15205.       adcn ++$08                   ;add eight pixels
  15206.       sta SCRATCHPAD+$02                    ;store result here
  15207.       lda Enemy_Rel_XPos         ;get relative horizontal coordinate
  15208.       sta SCRATCHPAD+$05                    ;store here
  15209.       ldx PowerUpType            ;get power-up type
  15210.       ldax PowerUpAttributes,x    ;get attribute data for power-up type
  15211.       orai Enemy_SprAttrib+5      ;add background priority bit if set
  15212.       sta SCRATCHPAD+$04                    ;store attributes here
  15213.       txa
  15214.       pha                        ;save power-up type to the stack
  15215.       asl
  15216.       asl                        ;multiply by four to get proper offset
  15217.       tax                        ;use as X
  15218.       ldan ++$01
  15219.         if Z80OPT
  15220.       ;ld (SCRATCHPAD+$07),a                    ;set counter here to draw two rows of sprite object
  15221.       ld (SCRATCHPAD+$03),a                    ;init d1 of flip control
  15222.       ld hl,PowerUpGfxTable
  15223.       add hl,bc
  15224.       call DrawSpriteObject
  15225.       call DrawSpriteObject
  15226.         else
  15227.       sta SCRATCHPAD+$07                    ;set counter here to draw two rows of sprite object
  15228.       sta SCRATCHPAD+$03                    ;init d1 of flip control
  15229. PUpDrawLoop0
  15230.         ldax PowerUpGfxTable,x      ;load left tile of power-up object
  15231.         sta SCRATCHPAD+$00
  15232.         ldax PowerUpGfxTable+1,x    ;load right tile
  15233.         jsr DrawOneSpriteRow       ;branch to draw one row of our power-up object
  15234.         deci SCRATCHPAD+$07                    ;decrement counter
  15235.         bpl PUpDrawLoop0            ;branch until two rows are drawn
  15236.         endif
  15237.         ldy Enemy_SprDataOffset+5  ;get sprite data offset again
  15238.         pla                        ;pull saved power-up type from the stack
  15239.          checka
  15240.         beq PUpOfs                 ;if regular mushroom, branch, do not change colors or flip
  15241.         cmpn ++$03
  15242.         beq PUpOfs                 ;if 1-up mushroom, branch, do not change colors or flip
  15243.         sta SCRATCHPAD+$00                    ;store power-up type here now
  15244.         lda FrameCounter           ;get frame counter
  15245.         lsr                        ;divide by 2 to change colors every two frames
  15246.         andn ++%00000011             ;mask out all but d1 and d0 (previously d2 and d1)
  15247.         orai Enemy_SprAttrib+5      ;add background priority bit if any set
  15248.         stay Sprite_Attributes,y    ;set as new palette bits for top left and
  15249.         stay Sprite_Attributes+4,y  ;top right sprites for fire flower and star
  15250.         ldx SCRATCHPAD+$00
  15251.         dex                        ;check power-up type for fire flower
  15252.         beq FlipPUpRightSide       ;if found, skip this part
  15253.         stay Sprite_Attributes+8,y  ;otherwise set new palette bits  for bottom left
  15254.         stay Sprite_Attributes+12,y ;and bottom right sprites as well for star only
  15255.  
  15256. FlipPUpRightSide:
  15257.         lday Sprite_Attributes+4,y
  15258.         oran ++%01000000             ;set horizontal flip bit for top right sprite
  15259.         stay Sprite_Attributes+4,y
  15260.         lday Sprite_Attributes+12,y
  15261.         oran ++%01000000             ;set horizontal flip bit for bottom right sprite
  15262.         stay Sprite_Attributes+12,y ;note these are only done for fire flower and star power-ups
  15263. PUpOfs: jmp SprObjectOffscrChk     ;jump to check to see if power-up is offscreen at all, then leave
  15264.  
  15265. ;-------------------------------------------------------------------------------------
  15266. ;$00-$01 - used in DrawEnemyObjRow to hold sprite tile numbers
  15267. ;$02 - used to store Y position
  15268. ;$03 - used to store moving direction, used to flip enemies horizontally
  15269. ;$04 - used to store enemy's sprite attributes
  15270. ;$05 - used to store X position
  15271. ;$eb - used to hold sprite data offset
  15272. ;$ec - used to hold either altered enemy state or special value used in gfx handler as condition
  15273. ;$ed - used to hold enemy state from buffer
  15274. ;$ef - used to hold enemy code used in gfx handler (may or may not resemble Enemy_ID values)
  15275.  
  15276. ;tiles arranged in top left, right, middle left, right, bottom left, right order
  15277. EnemyGraphicsTable:
  15278.       .db $fc, $fc, $aa, $ab, $ac, $ad  ;buzzy beetle frame 1
  15279.       .db $fc, $fc, $ae, $af, $b0, $b1  ;             frame 2
  15280.       .db $fc, $a5, $a6, $a7, $a8, $a9  ;koopa troopa frame 1
  15281.       .db $fc, $a0, $a1, $a2, $a3, $a4  ;             frame 2
  15282.       .db $69, $a5, $6a, $a7, $a8, $a9  ;koopa paratroopa frame 1
  15283.       .db $6b, $a0, $6c, $a2, $a3, $a4  ;                 frame 2
  15284.       .db $fc, $fc, $96, $97, $98, $99  ;spiny frame 1
  15285.       .db $fc, $fc, $9a, $9b, $9c, $9d  ;      frame 2
  15286.       .db $fc, $fc, $8f, $8e, $8e, $8f  ;spiny's egg frame 1
  15287.       .db $fc, $fc, $95, $94, $94, $95  ;            frame 2
  15288.       .db $fc, $fc, $dc, $dc, $df, $df  ;bloober frame 1
  15289.       .db $dc, $dc, $dd, $dd, $de, $de  ;        frame 2
  15290.       .db $fc, $fc, $b2, $b3, $b4, $b5  ;cheep-cheep frame 1
  15291.       .db $fc, $fc, $b6, $b3, $b7, $b5  ;            frame 2
  15292.       .db $fc, $fc, $70, $71, $72, $73  ;goomba
  15293.       .db $fc, $fc, $6e, $6e, $6f, $6f  ;koopa shell frame 1 (upside-down)
  15294.       .db $fc, $fc, $6d, $6d, $6f, $6f  ;            frame 2
  15295.       .db $fc, $fc, $6f, $6f, $6e, $6e  ;koopa shell frame 1 (rightsideup)
  15296.       .db $fc, $fc, $6f, $6f, $6d, $6d  ;            frame 2
  15297.       .db $fc, $fc, $f4, $f4, $f5, $f5  ;buzzy beetle shell frame 1 (rightsideup)
  15298.       .db $fc, $fc, $f4, $f4, $f5, $f5  ;                   frame 2
  15299.       .db $fc, $fc, $f5, $f5, $f4, $f4  ;buzzy beetle shell frame 1 (upside-down)
  15300.       .db $fc, $fc, $f5, $f5, $f4, $f4  ;                   frame 2
  15301.       .db $fc, $fc, $fc, $fc, $ef, $ef  ;defeated goomba
  15302.       .db $b9, $b8, $bb, $ba, $bc, $bc  ;lakitu frame 1
  15303.       .db $fc, $fc, $bd, $bd, $bc, $bc  ;       frame 2
  15304.       .db $7a, $7b, $da, $db, $d8, $d8  ;princess
  15305.       .db $cd, $cd, $ce, $ce, $cf, $cf  ;mushroom retainer
  15306.       .db $7d, $7c, $d1, $8c, $d3, $d2  ;hammer bro frame 1
  15307.       .db $7d, $7c, $89, $88, $8b, $8a  ;           frame 2
  15308.       .db $d5, $d4, $e3, $e2, $d3, $d2  ;           frame 3
  15309.       .db $d5, $d4, $e3, $e2, $8b, $8a  ;           frame 4
  15310.       .db $e5, $e5, $e6, $e6, $eb, $eb  ;piranha plant frame 1
  15311.       .db $ec, $ec, $ed, $ed, $ee, $ee  ;              frame 2
  15312.       .db $fc, $fc, $d0, $d0, $d7, $d7  ;podoboo
  15313.       .db $bf, $be, $c1, $c0, $c2, $fc  ;bowser front frame 1
  15314.       .db $c4, $c3, $c6, $c5, $c8, $c7  ;bowser rear frame 1
  15315.       .db $bf, $be, $ca, $c9, $c2, $fc  ;       front frame 2
  15316.       .db $c4, $c3, $c6, $c5, $cc, $cb  ;       rear frame 2
  15317.       .db $fc, $fc, $e8, $e7, $ea, $e9  ;bullet bill
  15318.       .db $f2, $f2, $f3, $f3, $f2, $f2  ;jumpspring frame 1
  15319.       .db $f1, $f1, $f1, $f1, $fc, $fc  ;           frame 2
  15320.       .db $f0, $f0, $fc, $fc, $fc, $fc  ;           frame 3
  15321.  
  15322. EnemyGfxTableOffsets:
  15323.       .db $0c, $0c, $00, $0c, $0c, $a8, $54, $3c
  15324.       .db $ea, $18, $48, $48, $cc, $c0, $18, $18
  15325.       .db $18, $90, $24, $ff, $48, $9c, $d2, $d8
  15326.       .db $f0, $f6, $fc
  15327.  
  15328. EnemyAttributeData:
  15329.       .db $01, $02, $03, $02, $01, $01, $03, $03
  15330.       .db $03, $01, $01, $02, $02, $21, $01, $02
  15331.       .db $01, $01, $02, $ff, $02, $02, $01, $01
  15332.       .db $02, $02, $02
  15333.  
  15334. EnemyAnimTimingBMask:
  15335.       .db $08, $18
  15336.  
  15337. JumpspringFrameOffsets:
  15338.       .db $18, $19, $1a, $19, $18
  15339.  
  15340. EnemyGfxHandler:
  15341. ;TODO тьхёЄю ¤Єюую фхЁхтр тхЄтыхэшщ ёфхырЄ№ яхЁхїюф яю Єшяє юс·хъЄр яю ЄрсышЎх, фры№°х тхЄтшЄ№
  15342.       ldax Enemy_Y_Position,x      ;get enemy object vertical position
  15343.       sta SCRATCHPAD+$02
  15344.       lda Enemy_Rel_XPos          ;get enemy object horizontal position
  15345.       sta SCRATCHPAD+$05                     ;relative to screen
  15346.       ldyx Enemy_SprDataOffset,x
  15347.       sty SCRATCHPAD+$eb                     ;get sprite data offset
  15348.       ldan ++$00
  15349.       sta VerticalFlipFlag        ;initialize vertical flip flag by default
  15350.       ldax Enemy_MovingDir,x
  15351.       sta SCRATCHPAD+$03                     ;get enemy object moving direction
  15352.       ldax Enemy_SprAttrib,x
  15353.       sta SCRATCHPAD+$04                     ;get enemy object sprite attributes
  15354.       ldax Enemy_ID,x
  15355.      
  15356.       cmpn ++PiranhaPlant           ;is enemy object piranha plant?
  15357.      bne CheckForRetainerObj     ;if not, branch
  15358.       ldyx PiranhaPlant_Y_Speed,x
  15359.          checky
  15360.      bmi CheckForRetainerObj     ;if piranha plant moving upwards, branch
  15361.       ldyx EnemyFrameTimer,x
  15362.          checky
  15363.      beq CheckForRetainerObj     ;if timer for movement expired, branch
  15364.       rts                         ;if all conditions fail, leave
  15365.  
  15366. CheckForRetainerObj:
  15367.       ldax Enemy_State,x           ;store enemy state
  15368.       sta SCRATCHPAD+$ed
  15369.       andn ++%00011111              ;nullify all but 5 LSB and use as Y
  15370.       tay
  15371.       ldax Enemy_ID,x              ;check for mushroom retainer/princess object
  15372.       cmpn ++RetainerObject
  15373.      bne CheckForBulletBillCV    ;if not found, branch
  15374.       ldyn ++$00                    ;if found, nullify saved state in Y
  15375.       ldan ++$01                    ;set value that will not be used
  15376.       sta SCRATCHPAD+$03
  15377.       ldan ++$15                    ;set value $15 as code for mushroom retainer/princess object
  15378.  
  15379. CheckForBulletBillCV:
  15380.        cmpn ++BulletBill_CannonVar   ;otherwise check for bullet bill object
  15381.       bne CheckForJumpspring      ;if not found, branch again
  15382.        deci SCRATCHPAD+$02                     ;decrement saved vertical position
  15383.        ldan ++$03
  15384.        ldyx EnemyFrameTimer,x       ;get timer for enemy object
  15385.          checky
  15386.        beq SBBAt                   ;if expired, do not set priority bit
  15387.        oran ++%00100000              ;otherwise do so
  15388. SBBAt: sta SCRATCHPAD+$04                     ;set new sprite attributes
  15389.        ldyn ++$00                    ;nullify saved enemy state both in Y and in
  15390.        sty SCRATCHPAD+$ed                     ;memory location here
  15391.        ldan ++$08                    ;set specific value to unconditionally branch once
  15392.  
  15393. CheckForJumpspring:
  15394.       cmpn ++JumpspringObject        ;check for jumpspring object
  15395.      bne CheckForPodoboo
  15396.       ldyn ++$03                     ;set enemy state -2 MSB here for jumpspring object
  15397.       ldx JumpspringAnimCtrl       ;get current frame number for jumpspring object
  15398.       ldax JumpspringFrameOffsets,x ;load data using frame number as offset
  15399.  
  15400. CheckForPodoboo:
  15401.       sta SCRATCHPAD+$ef                 ;store saved enemy object value here
  15402.       sty SCRATCHPAD+$ec                 ;and Y here (enemy state -2 MSB if not changed)
  15403.       ldx ObjectOffset        ;get enemy object offset
  15404.       cmpn ++$0c                ;check for podoboo object
  15405.      bne CheckBowserGfxFlag  ;branch if not found
  15406.       ldax Enemy_Y_Speed,x     ;if moving upwards, branch
  15407.          checka
  15408.      bmi CheckBowserGfxFlag
  15409.       inci VerticalFlipFlag    ;otherwise, set flag for vertical flip
  15410.  
  15411. CheckBowserGfxFlag:
  15412.              lda BowserGfxFlag   ;if not drawing bowser at all, skip to something else
  15413.          checka
  15414.       beq CheckForGoomba
  15415.              ldyn ++$16            ;if set to 1, draw bowser's front
  15416.              cmpn ++$01
  15417.              beq SBwsrGfxOfs
  15418.              iny                 ;otherwise draw bowser's rear
  15419. SBwsrGfxOfs: sty SCRATCHPAD+$ef
  15420.  
  15421. CheckForGoomba:
  15422. ;фюё■фр 485t
  15423.           ldy SCRATCHPAD+$ef               ;check value for goomba object
  15424.           cpyn ++Goomba
  15425.        bne CheckBowserFront  ;branch if not found
  15426.           ldax Enemy_State,x
  15427.           cmpn ++$02              ;check for defeated state
  15428.               cmpcy
  15429.           bcc GmbaAnim          ;if not defeated, go ahead and animate
  15430.           ldxn ++$04              ;if defeated, write new value here
  15431.           stx SCRATCHPAD+$ec
  15432. GmbaAnim: andn ++%00100000        ;check for d5 set in enemy object state
  15433.           orai TimerControl      ;or timer disable flag set
  15434.         bne CheckBowserFront  ;if either condition true, do not animate goomba
  15435.           lda FrameCounter
  15436.           andn ++%00001000        ;check for every eighth frame
  15437.         bne CheckBowserFront
  15438.           lda SCRATCHPAD+$03
  15439.           eorn ++%00000011        ;invert bits to flip horizontally every eight frames
  15440.           sta SCRATCHPAD+$03               ;leave alone otherwise
  15441.  
  15442. CheckBowserFront:
  15443.              lday EnemyAttributeData,y    ;load sprite attribute using enemy object
  15444.              orai SCRATCHPAD+$04                     ;as offset, and add to bits already loaded
  15445.              sta SCRATCHPAD+$04
  15446.              lday EnemyGfxTableOffsets,y  ;load value based on enemy object as offset
  15447.              tax                         ;save as X
  15448.              ldy SCRATCHPAD+$ec                     ;get previously saved value
  15449.              lda BowserGfxFlag
  15450.          checka
  15451.        beq CheckForSpiny           ;if not drawing bowser object at all, skip all of this
  15452.              cmpn ++$01
  15453.              bne CheckBowserRear         ;if not drawing front part, branch to draw the rear part
  15454.              lda BowserBodyControls      ;check bowser's body control bits
  15455.          checka
  15456.              bpl ChkFrontSte             ;branch if d7 not set (control's bowser's mouth)      
  15457.              ldxn ++$de                    ;otherwise load offset for second frame
  15458. ChkFrontSte: lda SCRATCHPAD+$ed                     ;check saved enemy state
  15459.              andn ++%00100000              ;if bowser not defeated, do not set flag
  15460.              beq DrawBowser
  15461.  
  15462. FlipBowserOver:
  15463.       stx VerticalFlipFlag  ;set vertical flip flag to nonzero
  15464.  
  15465. DrawBowser:
  15466.       jmp DrawEnemyObject   ;draw bowser's graphics now
  15467.  
  15468. CheckBowserRear:
  15469.             lda BowserBodyControls  ;check bowser's body control bits
  15470.             andn ++$01
  15471.             beq ChkRearSte          ;branch if d0 not set (control's bowser's feet)
  15472.             ldxn ++$e4                ;otherwise load offset for second frame
  15473. ChkRearSte: lda SCRATCHPAD+$ed                 ;check saved enemy state
  15474.             andn ++%00100000          ;if bowser not defeated, do not set flag
  15475.             beq DrawBowser
  15476.             lda SCRATCHPAD+$02                 ;subtract 16 pixels from
  15477.             secsub                     ;saved vertical coordinate
  15478.             sbcn ++$10
  15479.             sta SCRATCHPAD+$02
  15480.             jmp FlipBowserOver      ;jump to set vertical flip flag
  15481.  
  15482. CheckForSpiny:
  15483.         cpxn ++$24               ;check if value loaded is for spiny
  15484.        bne CheckForLakitu     ;if not found, branch
  15485.         cpyn ++$05               ;if enemy state set to $05, do this,
  15486.         bne NotEgg             ;otherwise branch
  15487.         ldxn ++$30               ;set to spiny egg offset
  15488.         ldan ++$02
  15489.         sta SCRATCHPAD+$03                ;set enemy direction to reverse sprites horizontally
  15490.         ldan ++$05
  15491.         sta SCRATCHPAD+$ec                ;set enemy state
  15492. NotEgg: jmp CheckForHammerBro  ;skip a big chunk of this if we found spiny but not in egg
  15493.  
  15494. CheckForLakitu:
  15495.         cpxn ++$90                  ;check value for lakitu's offset loaded
  15496.        bne CheckUpsideDownShell  ;branch if not loaded
  15497.         lda SCRATCHPAD+$ed
  15498.         andn ++%00100000            ;check for d5 set in enemy state
  15499.         bne NoLAFr                ;branch if set
  15500.         lda FrenzyEnemyTimer
  15501.         cmpn ++$10                  ;check timer to see if we've reached a certain range
  15502.               cmpcy
  15503.         bcs NoLAFr                ;branch if not
  15504.         ldxn ++$96                  ;if d6 not set and timer in range, load alt frame for lakitu
  15505. NoLAFr: jmp CheckDefeatedState    ;skip this next part if we found lakitu but alt frame not needed
  15506.  
  15507. CheckUpsideDownShell:
  15508.       lda SCRATCHPAD+$ef                    ;check for enemy object => $04
  15509.       cmpn ++$04
  15510.               cmpcy
  15511.      bcs CheckRightSideUpShell  ;branch if true
  15512.       cpyn ++$02
  15513.               cmpcy
  15514.      bcc CheckRightSideUpShell  ;branch if enemy state < $02
  15515.       ldxn ++$5a                   ;set for upside-down koopa shell by default
  15516.       ldy SCRATCHPAD+$ef
  15517.       cpyn ++BuzzyBeetle           ;check for buzzy beetle object
  15518.      bne CheckRightSideUpShell
  15519.       ldxn ++$7e                   ;set for upside-down buzzy beetle shell if found
  15520.       inci SCRATCHPAD+$02                    ;increment vertical position by one pixel
  15521.  
  15522. CheckRightSideUpShell:
  15523.       lda SCRATCHPAD+$ec                ;check for value set here
  15524.       cmpn ++$04               ;if enemy state < $02, do not change to shell, if
  15525.      bne CheckForHammerBro  ;enemy state => $02 but not = $04, leave shell upside-down
  15526.       ldxn ++$72               ;set right-side up buzzy beetle shell by default
  15527.       inci SCRATCHPAD+$02                ;increment saved vertical position by one pixel
  15528.       ldy SCRATCHPAD+$ef
  15529.       cpyn ++BuzzyBeetle       ;check for buzzy beetle object
  15530.      beq CheckForDefdGoomba ;branch if found
  15531.       ldxn ++$66               ;change to right-side up koopa shell if not found
  15532.       inci SCRATCHPAD+$02                ;and increment saved vertical position again
  15533.  
  15534. CheckForDefdGoomba:
  15535.       cpyn ++Goomba            ;check for goomba object (necessary if previously
  15536.      bne CheckForHammerBro  ;failed buzzy beetle object test)
  15537.       ldxn ++$54               ;load for regular goomba
  15538.       lda SCRATCHPAD+$ed                ;note that this only gets performed if enemy state => $02
  15539.       andn ++%00100000         ;check saved enemy state for d5 set
  15540.      bne CheckForHammerBro  ;branch if set
  15541.       ldxn ++$8a               ;load offset for defeated goomba
  15542.       deci SCRATCHPAD+$02                ;set different value and decrement saved vertical position
  15543.  
  15544. CheckForHammerBro:
  15545.       ldy ObjectOffset
  15546.       lda SCRATCHPAD+$ef                  ;check for hammer bro object
  15547.       cmpn ++HammerBro
  15548.      bne CheckForBloober      ;branch if not found
  15549.       lda SCRATCHPAD+$ed
  15550.          checka
  15551.      beq CheckToAnimateEnemy  ;branch if not in normal enemy state
  15552.       andn ++%00001000
  15553.      beq CheckDefeatedState   ;if d3 not set, branch further away
  15554.       ldxn ++$b4                 ;otherwise load offset for different frame
  15555.          checkx
  15556.      bne CheckToAnimateEnemy  ;unconditional branch
  15557.  
  15558. CheckForBloober:
  15559.       cpxn ++$48                 ;check for cheep-cheep offset loaded
  15560.      beq CheckToAnimateEnemy  ;branch if found
  15561.       lday EnemyIntervalTimer,y
  15562.       cmpn ++$05
  15563.               cmpcy
  15564.      bcs CheckDefeatedState   ;branch if some timer is above a certain point
  15565.       cpxn ++$3c                 ;check for bloober offset loaded
  15566.      bne CheckToAnimateEnemy  ;branch if not found this time
  15567.       cmpn ++$01
  15568.      beq CheckDefeatedState   ;branch if timer is set to certain point
  15569.       inci SCRATCHPAD+$02                  ;increment saved vertical coordinate three pixels
  15570.       inci SCRATCHPAD+$02
  15571.       inci SCRATCHPAD+$02
  15572.       jmp CheckAnimationStop   ;and do something else
  15573.  
  15574. CheckToAnimateEnemy:
  15575.       lda SCRATCHPAD+$ef                  ;check for specific enemy objects
  15576.       cmpn ++Goomba
  15577.      beq CheckDefeatedState   ;branch if goomba
  15578.       cmpn ++$08
  15579.      beq CheckDefeatedState   ;branch if bullet bill (note both variants use $08 here)
  15580.       cmpn ++Podoboo
  15581.      beq CheckDefeatedState   ;branch if podoboo
  15582.       cmpn ++$18                 ;branch if => $18
  15583.               cmpcy
  15584.       bcs CheckDefeatedState
  15585.       ldyn ++$00    
  15586.       cmpn ++$15                 ;check for mushroom retainer/princess object
  15587.        ;jr $
  15588.       bne CheckForSecondFrame  ;which uses different code here, branch if not found
  15589.       iny                      ;residual instruction
  15590.       lda WorldNumber          ;are we on world 8?
  15591.       cmpn ++World8
  15592.               cmpcy
  15593.         if ALWAYSPRINCESS
  15594.         scf
  15595.         endif
  15596.       bcs CheckDefeatedState   ;if so, leave the offset alone (use princess)
  15597.       ldxn ++$a2                 ;otherwise, set for mushroom retainer object instead
  15598.       ldan ++$03                 ;set alternate state here
  15599.       sta SCRATCHPAD+$ec
  15600.          checka
  15601.       bne CheckDefeatedState   ;unconditional branch
  15602.  
  15603. CheckForSecondFrame:
  15604.       lda FrameCounter            ;load frame counter
  15605.       andy EnemyAnimTimingBMask,y  ;mask it (partly residual, one byte not ever used)
  15606.       bne CheckDefeatedState      ;branch if timing is off
  15607.  
  15608. CheckAnimationStop:
  15609.       lda SCRATCHPAD+$ed                 ;check saved enemy state
  15610.       andn ++%10100000          ;for d7 or d5, or check for timers stopped
  15611.       orai TimerControl
  15612.       bne CheckDefeatedState  ;if either condition true, branch
  15613.       txa
  15614.       clc
  15615.       adcn ++$06                ;add $06 to current enemy offset
  15616.       tax                     ;to animate various enemy objects
  15617.  
  15618. CheckDefeatedState:
  15619.       lda SCRATCHPAD+$ed               ;check saved enemy state
  15620.       andn ++%00100000        ;for d5 set
  15621.      beq DrawEnemyObject   ;branch if not set
  15622.       lda SCRATCHPAD+$ef
  15623.       cmpn ++$04              ;check for saved enemy object => $04
  15624.               cmpcy
  15625.      bcc DrawEnemyObject   ;branch if less
  15626.       ldyn ++$01
  15627.       sty VerticalFlipFlag  ;set vertical flip flag
  15628.       dey
  15629.       sty SCRATCHPAD+$ec               ;init saved value here
  15630.  
  15631. DrawEnemyObject:
  15632. ;фюё■фр 1118t (юЄ эрўрыр яЁюЎхфєЁ√)
  15633.       ldy SCRATCHPAD+$eb                    ;load sprite data offset
  15634.         if Z80OPT
  15635.         ld hl,EnemyGraphicsTable
  15636.         add hl,bc
  15637.         call DrawSpriteObject ;360t
  15638.         call DrawSpriteObject ;360t
  15639.         call DrawSpriteObject ;360t
  15640.         else
  15641.       jsr DrawEnemyObjRow        ;draw six tiles of data
  15642.       jsr DrawEnemyObjRow        ;into sprite data
  15643.       jsr DrawEnemyObjRow
  15644.         endif
  15645. ;фю т√їюфр х∙╕ 1030t (эхтшфшь√щ Goomba)/604t (тшфшь√щ)
  15646.       ldx ObjectOffset           ;get enemy object offset
  15647.       ldyx Enemy_SprDataOffset,x  ;get sprite data offset
  15648.       lda SCRATCHPAD+$ef
  15649.       cmpn ++$08                   ;get saved enemy object and check
  15650.       bne CheckForVerticalFlip   ;for bullet bill, branch if not found
  15651.  
  15652. SkipToOffScrChk:
  15653.       jmp SprObjectOffscrChk     ;jump if found
  15654.  
  15655. CheckForVerticalFlip:
  15656.       lda VerticalFlipFlag       ;check if vertical flip flag is set here
  15657.          checka
  15658.       beq CheckForESymmetry      ;branch if not
  15659.       lday Sprite_Attributes,y    ;get attributes of first sprite we dealt with
  15660.       oran ++%10000000             ;set bit for vertical flip
  15661.       iny
  15662.       iny                        ;increment two bytes so that we store the vertical flip
  15663.       jsr DumpSixSpr             ;in attribute bytes of enemy obj sprite data
  15664.       dey
  15665.       dey                        ;now go back to the Y coordinate offset
  15666.       tya
  15667.       tax                        ;give offset to X
  15668.       lda SCRATCHPAD+$ef
  15669.       cmpn ++HammerBro             ;check saved enemy object for hammer bro
  15670.       beq FlipEnemyVertically
  15671.       cmpn ++Lakitu                ;check saved enemy object for lakitu
  15672.       beq FlipEnemyVertically    ;branch for hammer bro or lakitu
  15673.       cmpn ++$15
  15674.               cmpcy
  15675.       bcs FlipEnemyVertically    ;also branch if enemy object => $15
  15676.       txa
  15677.       clc
  15678.       adcn ++$08                   ;if not selected objects or => $15, set
  15679.       tax                        ;offset in X for next row
  15680.  
  15681. FlipEnemyVertically:
  15682.       ldax Sprite_Tilenumber,x     ;load first or second row tiles
  15683.       pha                         ;and save tiles to the stack
  15684.       ldax Sprite_Tilenumber+4,x
  15685.       pha
  15686.       lday Sprite_Tilenumber+16,y  ;exchange third row tiles
  15687.       stax Sprite_Tilenumber,x     ;with first or second row tiles
  15688.       lday Sprite_Tilenumber+20,y
  15689.       stax Sprite_Tilenumber+4,x
  15690.       pla                         ;pull first or second row tiles from stack
  15691.       stay Sprite_Tilenumber+20,y  ;and save in third row
  15692.       pla
  15693.       stay Sprite_Tilenumber+16,y
  15694.  
  15695. CheckForESymmetry:
  15696.         lda BowserGfxFlag           ;are we drawing bowser at all?
  15697.          checka
  15698.         bne SkipToOffScrChk         ;branch if so
  15699.         lda SCRATCHPAD+$ef      
  15700.         ldx SCRATCHPAD+$ec                     ;get alternate enemy state
  15701.         cmpn ++$05                    ;check for hammer bro object
  15702.         bne ContES
  15703.         jmp SprObjectOffscrChk      ;jump if found
  15704. ContES: cmpn ++Bloober                ;check for bloober object
  15705.         beq MirrorEnemyGfx
  15706.         cmpn ++PiranhaPlant           ;check for piranha plant object
  15707.         beq MirrorEnemyGfx
  15708.         cmpn ++Podoboo                ;check for podoboo object
  15709.         beq MirrorEnemyGfx          ;branch if either of three are found
  15710.         cmpn ++Spiny                  ;check for spiny object
  15711.         bne ESRtnr                  ;branch closer if not found
  15712.         cpxn ++$05                    ;check spiny's state
  15713.         bne CheckToMirrorLakitu     ;branch if not an egg, otherwise
  15714. ESRtnr: cmpn ++$15                    ;check for princess/mushroom retainer object
  15715.         bne SpnySC
  15716.         ldan ++$42                    ;set horizontal flip on bottom right sprite
  15717.         stay Sprite_Attributes+20,y  ;note that palette bits were already set earlier
  15718. SpnySC: cpxn ++$02                    ;if alternate enemy state set to 1 or 0, branch
  15719.               cmpcy
  15720.         bcc CheckToMirrorLakitu
  15721.  
  15722. MirrorEnemyGfx:
  15723.         lda BowserGfxFlag           ;if enemy object is bowser, skip all of this
  15724.          checka
  15725.         bne CheckToMirrorLakitu
  15726.         lday Sprite_Attributes,y     ;load attribute bits of first sprite
  15727.         andn ++%10100011
  15728.         stay Sprite_Attributes,y     ;save vertical flip, priority, and palette bits
  15729.         stay Sprite_Attributes+8,y   ;in left sprite column of enemy object OAM data
  15730.         stay Sprite_Attributes+16,y
  15731.         oran ++%01000000              ;set horizontal flip
  15732.         cpxn ++$05                    ;check for state used by spiny's egg
  15733.         bne EggExc                  ;if alternate state not set to $05, branch
  15734.         oran ++%10000000              ;otherwise set vertical flip
  15735. EggExc: stay Sprite_Attributes+4,y   ;set bits of right sprite column
  15736.         stay Sprite_Attributes+12,y  ;of enemy object sprite data
  15737.         stay Sprite_Attributes+20,y
  15738.         cpxn ++$04                    ;check alternate enemy state
  15739.         bne CheckToMirrorLakitu     ;branch if not $04
  15740.         lday Sprite_Attributes+8,y   ;get second row left sprite attributes
  15741.         oran ++%10000000
  15742.         stay Sprite_Attributes+8,y   ;store bits with vertical flip in
  15743.         stay Sprite_Attributes+16,y  ;second and third row left sprites
  15744.         oran ++%01000000
  15745.         stay Sprite_Attributes+12,y  ;store with horizontal and vertical flip in
  15746.         stay Sprite_Attributes+20,y  ;second and third row right sprites
  15747.  
  15748. CheckToMirrorLakitu:
  15749.         lda SCRATCHPAD+$ef                     ;check for lakitu enemy object
  15750.         cmpn ++Lakitu
  15751.         bne CheckToMirrorJSpring    ;branch if not found
  15752.         lda VerticalFlipFlag
  15753.          checka
  15754.         bne NVFLak                  ;branch if vertical flip flag not set
  15755.         lday Sprite_Attributes+16,y  ;save vertical flip and palette bits
  15756.         andn ++%10000001              ;in third row left sprite
  15757.         stay Sprite_Attributes+16,y
  15758.         lday Sprite_Attributes+20,y  ;set horizontal flip and palette bits
  15759.         oran ++%01000001              ;in third row right sprite
  15760.         stay Sprite_Attributes+20,y
  15761.         ldx FrenzyEnemyTimer        ;check timer
  15762.         cpxn ++$10
  15763.               cmpcy
  15764.         bcs SprObjectOffscrChk      ;branch if timer has not reached a certain range
  15765.         stay Sprite_Attributes+12,y  ;otherwise set same for second row right sprite
  15766.         andn ++%10000001
  15767.         stay Sprite_Attributes+8,y   ;preserve vertical flip and palette bits for left sprite
  15768.        if Z80
  15769.        or a
  15770.        endif
  15771.         bcc SprObjectOffscrChk      ;unconditional branch
  15772. NVFLak: lday Sprite_Attributes,y     ;get first row left sprite attributes
  15773.         andn ++%10000001
  15774.         stay Sprite_Attributes,y     ;save vertical flip and palette bits
  15775.         lday Sprite_Attributes+4,y   ;get first row right sprite attributes
  15776.         oran ++%01000001              ;set horizontal flip and palette bits
  15777.         stay Sprite_Attributes+4,y   ;note that vertical flip is left as-is
  15778.  
  15779. CheckToMirrorJSpring:
  15780.       lda SCRATCHPAD+$ef                     ;check for jumpspring object (any frame)
  15781.       cmpn ++$18
  15782.               cmpcy
  15783.       bcc SprObjectOffscrChk      ;branch if not jumpspring object at all
  15784.       ldan ++$82
  15785.       stay Sprite_Attributes+8,y   ;set vertical flip and palette bits of
  15786.       stay Sprite_Attributes+16,y  ;second and third row left sprites
  15787.       oran ++%01000000
  15788.       stay Sprite_Attributes+12,y  ;set, in addition to those, horizontal flip
  15789.       stay Sprite_Attributes+20,y  ;for second and third row right sprites
  15790.  
  15791. SprObjectOffscrChk:
  15792. ;юЄё■фр фю т√їюфр х∙╕ 238t (тшфшь√щ Goomba)
  15793.          ldx ObjectOffset          ;get enemy buffer offset
  15794.          lda Enemy_OffscreenBits   ;check offscreen information
  15795.          lsr
  15796.          lsr                       ;shift three times to the right
  15797.          lsr                       ;which puts d2 into carry
  15798.          pha                       ;save to stack
  15799.          bcc LcChk                 ;branch if not set
  15800.          ldan ++$04                  ;set for right column sprites
  15801.          jsr MoveESprColOffscreen  ;and move them offscreen
  15802. LcChk:   pla                       ;get from stack
  15803.          lsr                       ;move d3 to carry
  15804.          pha                       ;save to stack
  15805.          bcc Row3C                 ;branch if not set
  15806.          ldan ++$00                  ;set for left column sprites,
  15807.          jsr MoveESprColOffscreen  ;move them offscreen
  15808. Row3C:   pla                       ;get from stack again
  15809.          lsr                       ;move d5 to carry this time
  15810.          lsr
  15811.          pha                       ;save to stack again
  15812.          bcc Row23C                ;branch if carry not set
  15813.          ldan ++$10                  ;set for third row of sprites
  15814.          jsr MoveESprRowOffscreen  ;and move them offscreen
  15815. Row23C:  pla                       ;get from stack
  15816.          lsr                       ;move d6 into carry
  15817.          pha                       ;save to stack
  15818.          bcc AllRowC
  15819.          ldan ++$08                  ;set for second and third rows
  15820.          jsr MoveESprRowOffscreen  ;move them offscreen
  15821. AllRowC: pla                       ;get from stack once more
  15822.          lsr                       ;move d7 into carry
  15823.          bcc ExEGHandler
  15824.          jsr MoveESprRowOffscreen  ;move all sprites offscreen (A should be 0 by now)
  15825.          ldax Enemy_ID,x
  15826.          cmpn ++Podoboo              ;check enemy identifier for podoboo
  15827.          beq ExEGHandler           ;skip this part if found, we do not want to erase podoboo!
  15828.          ldax Enemy_Y_HighPos,x     ;check high byte of vertical position
  15829.          cmpn ++$02                  ;if not yet past the bottom of the screen, branch
  15830.          bne ExEGHandler
  15831.          jsr EraseEnemyObject      ;what it says
  15832.  
  15833. ExEGHandler:
  15834.       rts
  15835.  
  15836.         if Z80OPT
  15837.         else
  15838. DrawEnemyObjRow:
  15839.       ldax EnemyGraphicsTable,x    ;load two tiles of enemy graphics
  15840.       sta SCRATCHPAD+$00
  15841.       ldax EnemyGraphicsTable+1,x
  15842. DrawOneSpriteRow:
  15843.       sta SCRATCHPAD+$01
  15844.       jmp DrawSpriteObject        ;draw them
  15845.         endif
  15846.  
  15847. MoveESprRowOffscreen:
  15848.       clc                         ;add A to enemy object OAM data offset
  15849.       adcx Enemy_SprDataOffset,x
  15850.       tay                         ;use as offset
  15851.       ldan ++$f8
  15852.       jmp DumpTwoSpr              ;move first row of sprites offscreen
  15853.  
  15854. MoveESprColOffscreen:
  15855.       clc                         ;add A to enemy object OAM data offset
  15856.       adcx Enemy_SprDataOffset,x
  15857.       tay                         ;use as offset
  15858.       jsr MoveColOffscreen        ;move first and second row sprites in column offscreen
  15859.       stay Sprite_Data+16,y        ;move third row sprite in column offscreen
  15860.       rts
  15861.  
  15862. ;-------------------------------------------------------------------------------------
  15863. ;$00-$01 - tile numbers
  15864. ;$02 - relative Y position
  15865. ;$03 - horizontal flip flag (not used here)
  15866. ;$04 - attributes
  15867. ;$05 - relative X position
  15868.  
  15869. DefaultBlockObjTiles:
  15870.       .db $85, $85, $86, $86             ;brick w/ line (these are sprite tiles, not BG!)
  15871.  
  15872. DrawBlock:
  15873.            lda Block_Rel_YPos            ;get relative vertical coordinate of block object
  15874.            sta SCRATCHPAD+$02                       ;store here
  15875.            lda Block_Rel_XPos            ;get relative horizontal coordinate of block object
  15876.            sta SCRATCHPAD+$05                       ;store here
  15877.            ldan ++$03
  15878.            sta SCRATCHPAD+$04                       ;set attribute byte here
  15879.            lsr
  15880.            sta SCRATCHPAD+$03                       ;set horizontal flip bit here (will not be used) ???
  15881.            ldyx Block_SprDataOffset,x     ;get sprite data offset
  15882.         if Z80OPT
  15883.       ld hl,DefaultBlockObjTiles
  15884.       ;add hl,bc
  15885.       call DrawSpriteObject
  15886.       call DrawSpriteObject
  15887.         else
  15888.            ldxn ++$00                      ;reset X for use as offset to tile data
  15889. DBlkLoop:  
  15890.            ldax DefaultBlockObjTiles,x    ;get left tile number
  15891.            sta SCRATCHPAD+$00                       ;set here
  15892.            ldax DefaultBlockObjTiles+1,x  ;get right tile number
  15893.            jsr DrawOneSpriteRow          ;do sub to write tile numbers to first row of sprites
  15894.            cpxn ++$04                      ;check incremented offset
  15895.            bne DBlkLoop                  ;and loop back until all four sprites are done
  15896.         endif
  15897.            ldx ObjectOffset              ;get block object offset
  15898.            ldyx Block_SprDataOffset,x     ;get sprite data offset
  15899.            lda AreaType
  15900.            cmpn ++$01                      ;check for ground level type area
  15901.            beq ChkRep                    ;if found, branch to next part
  15902.            ldan ++$86
  15903.            stay Sprite_Tilenumber,y       ;otherwise remove brick tiles with lines
  15904.            stay Sprite_Tilenumber+4,y     ;and replace then with lineless brick tiles
  15905. ChkRep:    ldax Block_Metatile,x          ;check replacement metatile
  15906.            cmpn ++$c4                      ;if not used block metatile, then
  15907.            bne BlkOffscr                 ;branch ahead to use current graphics
  15908.            ldan ++$87                      ;set A for used block tile
  15909.            iny                           ;increment Y to write to tile bytes
  15910.            jsr DumpFourSpr               ;do sub to dump into all four sprites
  15911.            dey                           ;return Y to original offset
  15912.            ldan ++$03                      ;set palette bits
  15913.            ldx AreaType
  15914.            dex                           ;check for ground level type area again
  15915.            beq SetBFlip                  ;if found, use current palette bits
  15916.            lsr                           ;otherwise set to $01
  15917. SetBFlip:  ldx ObjectOffset              ;put block object offset back in X
  15918.            stay Sprite_Attributes,y       ;store attribute byte as-is in first sprite
  15919.            oran ++%01000000
  15920.            stay Sprite_Attributes+4,y     ;set horizontal flip bit for second sprite
  15921.            oran ++%10000000
  15922.            stay Sprite_Attributes+12,y    ;set both flip bits for fourth sprite
  15923.            andn ++%10000011
  15924.            stay Sprite_Attributes+8,y     ;set vertical flip bit for third sprite
  15925. BlkOffscr: lda Block_OffscreenBits       ;get offscreen bits for block object
  15926.            pha                           ;save to stack
  15927.            andn ++%00000100                ;check to see if d2 in offscreen bits are set
  15928.            beq PullOfsB                  ;if not set, branch, otherwise move sprites offscreen
  15929.            ldan ++$f8                      ;move offscreen two OAMs
  15930.            stay Sprite_Y_Position+4,y     ;on the right side
  15931.            stay Sprite_Y_Position+12,y
  15932. PullOfsB:  pla                           ;pull offscreen bits from stack
  15933. ChkLeftCo: andn ++%00001000                ;check to see if d3 in offscreen bits are set
  15934.            beq ExDBlk                    ;if not set, branch, otherwise move sprites offscreen
  15935.  
  15936. MoveColOffscreen:
  15937.         ldan ++$f8                   ;move offscreen two OAMs
  15938.         stay Sprite_Y_Position,y    ;on the left side (or two rows of enemy on either side
  15939.         stay Sprite_Y_Position+8,y  ;if branched here from enemy graphics handler)
  15940. ExDBlk: rts
  15941.  
  15942. ;-------------------------------------------------------------------------------------
  15943. ;$00 - used to hold palette bits for attribute byte or relative X position
  15944.  
  15945. DrawBrickChunks:
  15946.          ldan ++$02                   ;set palette bits here
  15947.          sta SCRATCHPAD+$00
  15948.          ldan ++$75                   ;set tile number for ball (something residual, likely)
  15949.          ldy GameEngineSubroutine
  15950.          cpyn ++$05                   ;if end-of-level routine running,
  15951.          beq DChunks                ;use palette and tile number assigned
  15952.          ldan ++$03                   ;otherwise set different palette bits
  15953.          sta SCRATCHPAD+$00
  15954.          ldan ++$84                   ;and set tile number for brick chunks
  15955. DChunks: ldyx Block_SprDataOffset,x  ;get OAM data offset
  15956.          iny                        ;increment to start with tile bytes in OAM
  15957.          jsr DumpFourSpr            ;do sub to dump tile number into all four sprites
  15958.          lda FrameCounter           ;get frame counter
  15959.          asl
  15960.          asl
  15961.          asl                        ;move low nybble to high
  15962.          asl
  15963.          andn ++$c0                   ;get what was originally d3-d2 of low nybble
  15964.          orai SCRATCHPAD+$00                    ;add palette bits
  15965.          iny                        ;increment offset for attribute bytes
  15966.          jsr DumpFourSpr            ;do sub to dump attribute data into all four sprites
  15967.          dey
  15968.          dey                        ;decrement offset to Y coordinate
  15969.          lda Block_Rel_YPos         ;get first block object's relative vertical coordinate
  15970.          jsr DumpTwoSpr             ;do sub to dump current Y coordinate into two sprites
  15971.          lda Block_Rel_XPos         ;get first block object's relative horizontal coordinate
  15972.          stay Sprite_X_Position,y    ;save into X coordinate of first sprite
  15973.          ldax Block_Orig_XPos,x      ;get original horizontal coordinate
  15974.          secsub
  15975.          sbci ScreenLeft_X_Pos       ;subtract coordinate of left side from original coordinate
  15976.          sta SCRATCHPAD+$00                    ;store result as relative horizontal coordinate of original
  15977.          secsub
  15978.          sbci Block_Rel_XPos         ;get difference of relative positions of original - current
  15979.         cmpcy
  15980.          adci SCRATCHPAD+$00                    ;add original relative position to result
  15981.          adcn ++$06                   ;plus 6 pixels to position second brick chunk correctly
  15982.          stay Sprite_X_Position+4,y  ;save into X coordinate of second sprite
  15983.          lda Block_Rel_YPos+1       ;get second block object's relative vertical coordinate
  15984.          stay Sprite_Y_Position+8,y
  15985.          stay Sprite_Y_Position+12,y ;dump into Y coordinates of third and fourth sprites
  15986.          lda Block_Rel_XPos+1       ;get second block object's relative horizontal coordinate
  15987.          stay Sprite_X_Position+8,y  ;save into X coordinate of third sprite
  15988.          lda SCRATCHPAD+$00                    ;use original relative horizontal position
  15989.          secsub
  15990.          sbci Block_Rel_XPos+1       ;get difference of relative positions of original - current
  15991.         cmpcy
  15992.          adci SCRATCHPAD+$00                    ;add original relative position to result
  15993.          adcn ++$06                   ;plus 6 pixels to position fourth brick chunk correctly
  15994.          stay Sprite_X_Position+12,y ;save into X coordinate of fourth sprite
  15995.          lda Block_OffscreenBits    ;get offscreen bits for block object
  15996.          jsr ChkLeftCo              ;do sub to move left half of sprites offscreen if necessary
  15997.          lda Block_OffscreenBits    ;get offscreen bits again
  15998.          asl                        ;shift d7 into carry
  15999.          bcc ChnkOfs                ;if d7 not set, branch to last part
  16000.          ldan ++$f8
  16001.          jsr DumpTwoSpr             ;otherwise move top sprites offscreen
  16002. ChnkOfs: lda SCRATCHPAD+$00                    ;if relative position on left side of screen,
  16003.          checka
  16004.          bpl ExBCDr                 ;go ahead and leave
  16005.          lday Sprite_X_Position,y    ;otherwise compare left-side X coordinate
  16006.          cmpy Sprite_X_Position+4,y  ;to right-side X coordinate
  16007.               cmpcy
  16008.          bcc ExBCDr                 ;branch to leave if less
  16009.          ldan ++$f8                   ;otherwise move right half of sprites offscreen
  16010.          stay Sprite_Y_Position+4,y
  16011.          stay Sprite_Y_Position+12,y
  16012. ExBCDr:  rts                        ;leave
  16013.  
  16014. ;-------------------------------------------------------------------------------------
  16015.  
  16016. DrawFireball:
  16017.       ldyx FBall_SprDataOffset,x  ;get fireball's sprite data offset
  16018.       lda Fireball_Rel_YPos      ;get relative vertical coordinate
  16019.       stay Sprite_Y_Position,y    ;store as sprite Y coordinate
  16020.       lda Fireball_Rel_XPos      ;get relative horizontal coordinate
  16021.       stay Sprite_X_Position,y    ;store as sprite X coordinate, then do shared code
  16022.  
  16023. DrawFirebar:
  16024.        lda FrameCounter         ;get frame counter
  16025.        lsr                      ;divide by four
  16026.        lsr
  16027.        pha                      ;save result to stack
  16028.        andn ++$01                 ;mask out all but last bit
  16029.        eorn ++$64                 ;set either tile $64 or $65 as fireball tile
  16030.        stay Sprite_Tilenumber,y  ;thus tile changes every four frames
  16031.        pla                      ;get from stack
  16032.        lsr                      ;divide by four again
  16033.        lsr
  16034.        ldan ++$02                 ;load value $02 to set palette in attrib byte
  16035.        bcc FireA                ;if last bit shifted out was not set, skip this
  16036.        oran ++%11000000           ;otherwise flip both ways every eight frames
  16037. FireA: stay Sprite_Attributes,y  ;store attribute byte and leave
  16038.        rts
  16039.  
  16040. ;-------------------------------------------------------------------------------------
  16041.  
  16042. ExplosionTiles:
  16043.       .db $68, $67, $66
  16044.  
  16045. DrawExplosion_Fireball:
  16046.       ldyx Alt_SprDataOffset,x  ;get OAM data offset of alternate sort for fireball's explosion
  16047.       ldax Fireball_State,x     ;load fireball state
  16048.       incx Fireball_State,x     ;increment state for next frame
  16049.       lsr                      ;divide by 2
  16050.       andn ++%00000111           ;mask out all but d3-d1
  16051.       cmpn ++$03                 ;check to see if time to kill fireball
  16052.               cmpcy
  16053.       bcs KillFireBall         ;branch if so, otherwise continue to draw explosion
  16054.  
  16055. DrawExplosion_Fireworks:
  16056.       tax                         ;use whatever's in A for offset
  16057.       ldax ExplosionTiles,x        ;get tile number using offset
  16058.       iny                         ;increment Y (contains sprite data offset)
  16059.       jsr DumpFourSpr             ;and dump into tile number part of sprite data
  16060.       dey                         ;decrement Y so we have the proper offset again
  16061.       ldx ObjectOffset            ;return enemy object buffer offset to X
  16062.       lda Fireball_Rel_YPos       ;get relative vertical coordinate
  16063.       secsub                         ;subtract four pixels vertically
  16064.       sbcn ++$04                    ;for first and third sprites
  16065.       stay Sprite_Y_Position,y
  16066.       stay Sprite_Y_Position+8,y
  16067.       clc                         ;add eight pixels vertically
  16068.       adcn ++$08                    ;for second and fourth sprites
  16069.       stay Sprite_Y_Position+4,y
  16070.       stay Sprite_Y_Position+12,y
  16071.       lda Fireball_Rel_XPos       ;get relative horizontal coordinate
  16072.       secsub                         ;subtract four pixels horizontally
  16073.       sbcn ++$04                    ;for first and second sprites
  16074.       stay Sprite_X_Position,y
  16075.       stay Sprite_X_Position+4,y
  16076.       clc                         ;add eight pixels horizontally
  16077.       adcn ++$08                    ;for third and fourth sprites
  16078.       stay Sprite_X_Position+8,y
  16079.       stay Sprite_X_Position+12,y
  16080.       ldan ++$02                    ;set palette attributes for all sprites, but
  16081.       stay Sprite_Attributes,y     ;set no flip at all for first sprite
  16082.       ldan ++$82
  16083.       stay Sprite_Attributes+4,y   ;set vertical flip for second sprite
  16084.       ldan ++$42
  16085.       stay Sprite_Attributes+8,y   ;set horizontal flip for third sprite
  16086.       ldan ++$c2
  16087.       stay Sprite_Attributes+12,y  ;set both flips for fourth sprite
  16088.       rts                         ;we are done
  16089.  
  16090. KillFireBall:
  16091.       ldan ++$00                    ;clear fireball state to kill it
  16092.       stax Fireball_State,x
  16093.       rts
  16094.  
  16095. ;-------------------------------------------------------------------------------------
  16096.  
  16097. DrawSmallPlatform:
  16098.        ldyx Enemy_SprDataOffset,x   ;get OAM data offset
  16099.        ldan ++$5b                    ;load tile number for small platforms
  16100.        iny                         ;increment offset for tile numbers
  16101.        jsr DumpSixSpr              ;dump tile number into all six sprites
  16102.        iny                         ;increment offset for attributes
  16103.        ldan ++$02                    ;load palette controls
  16104.        jsr DumpSixSpr              ;dump attributes into all six sprites
  16105.        dey                         ;decrement for original offset
  16106.        dey
  16107.        lda Enemy_Rel_XPos          ;get relative horizontal coordinate
  16108.        stay Sprite_X_Position,y
  16109.        stay Sprite_X_Position+12,y  ;dump as X coordinate into first and fourth sprites
  16110.        clc
  16111.        adcn ++$08                    ;add eight pixels
  16112.        stay Sprite_X_Position+4,y   ;dump into second and fifth sprites
  16113.        stay Sprite_X_Position+16,y
  16114.        clc
  16115.        adcn ++$08                    ;add eight more pixels
  16116.        stay Sprite_X_Position+8,y   ;dump into third and sixth sprites
  16117.        stay Sprite_X_Position+20,y
  16118.        ldax Enemy_Y_Position,x      ;get vertical coordinate
  16119.        tax
  16120.        pha                         ;save to stack
  16121.        cpxn ++$20                    ;if vertical coordinate below status bar,
  16122.               cmpcy
  16123.        bcs TopSP                   ;do not mess with it
  16124.        ldan ++$f8                    ;otherwise move first three sprites offscreen
  16125. TopSP: jsr DumpThreeSpr            ;dump vertical coordinate into Y coordinates
  16126.        pla                         ;pull from stack
  16127.        clc
  16128.        adcn ++$80                    ;add 128 pixels
  16129.        tax
  16130.        cpxn ++$20                    ;if below status bar (taking wrap into account)
  16131.               cmpcy
  16132.        bcs BotSP                   ;then do not change altered coordinate
  16133.        ldan ++$f8                    ;otherwise move last three sprites offscreen
  16134. BotSP: stay Sprite_Y_Position+12,y  ;dump vertical coordinate + 128 pixels
  16135.        stay Sprite_Y_Position+16,y  ;into Y coordinates
  16136.        stay Sprite_Y_Position+20,y
  16137.        lda Enemy_OffscreenBits     ;get offscreen bits
  16138.        pha                         ;save to stack
  16139.        andn ++%00001000              ;check d3
  16140.        beq SOfs
  16141.        ldan ++$f8                    ;if d3 was set, move first and
  16142.        stay Sprite_Y_Position,y     ;fourth sprites offscreen
  16143.        stay Sprite_Y_Position+12,y
  16144. SOfs:  pla                         ;move out and back into stack
  16145.        pha
  16146.        andn ++%00000100              ;check d2
  16147.        beq SOfs2
  16148.        ldan ++$f8                    ;if d2 was set, move second and
  16149.        stay Sprite_Y_Position+4,y   ;fifth sprites offscreen
  16150.        stay Sprite_Y_Position+16,y
  16151. SOfs2: pla                         ;get from stack
  16152.        andn ++%00000010              ;check d1
  16153.        beq ExSPl
  16154.        ldan ++$f8                    ;if d1 was set, move third and
  16155.        stay Sprite_Y_Position+8,y   ;sixth sprites offscreen
  16156.        stay Sprite_Y_Position+20,y
  16157. ExSPl: ldx ObjectOffset            ;get enemy object offset and leave
  16158.        rts
  16159.  
  16160. ;-------------------------------------------------------------------------------------
  16161.  
  16162. DrawBubble:
  16163.         ldy Player_Y_HighPos        ;if player's vertical high position
  16164.         dey                         ;not within screen, skip all of this
  16165.         bne ExDBub
  16166.         lda Bubble_OffscreenBits    ;check air bubble's offscreen bits
  16167.         andn ++%00001000
  16168.         bne ExDBub                  ;if bit set, branch to leave
  16169.         ldyx Bubble_SprDataOffset,x  ;get air bubble's OAM data offset
  16170.         lda Bubble_Rel_XPos         ;get relative horizontal coordinate
  16171.         stay Sprite_X_Position,y     ;store as X coordinate here
  16172.         lda Bubble_Rel_YPos         ;get relative vertical coordinate
  16173.         stay Sprite_Y_Position,y     ;store as Y coordinate here
  16174.         ldan ++$74
  16175.         stay Sprite_Tilenumber,y     ;put air bubble tile into OAM data
  16176.         ldan ++$02
  16177.         stay Sprite_Attributes,y     ;set attribute byte
  16178. ExDBub: rts                         ;leave
  16179.  
  16180. ;-------------------------------------------------------------------------------------
  16181. ;$00 - used to store player's vertical offscreen bits
  16182.  
  16183. PlayerGfxTblOffsets:
  16184.       .db $20, $28, $c8, $18, $00, $40, $50, $58
  16185.       .db $80, $88, $b8, $78, $60, $a0, $b0, $b8
  16186.  
  16187. ;tiles arranged in order, 2 tiles per row, top to bottom
  16188.  
  16189. PlayerGraphicsTable:
  16190. ;big player table
  16191.       .db $00, $01, $02, $03, $04, $05, $06, $07 ;walking frame 1
  16192.       .db $08, $09, $0a, $0b, $0c, $0d, $0e, $0f ;        frame 2
  16193.       .db $10, $11, $12, $13, $14, $15, $16, $17 ;        frame 3
  16194.       .db $18, $19, $1a, $1b, $1c, $1d, $1e, $1f ;skidding
  16195.       .db $20, $21, $22, $23, $24, $25, $26, $27 ;jumping
  16196.       .db $08, $09, $28, $29, $2a, $2b, $2c, $2d ;swimming frame 1
  16197.       .db $08, $09, $0a, $0b, $0c, $30, $2c, $2d ;         frame 2
  16198.       .db $08, $09, $0a, $0b, $2e, $2f, $2c, $2d ;         frame 3
  16199.       .db $08, $09, $28, $29, $2a, $2b, $5c, $5d ;climbing frame 1
  16200.       .db $08, $09, $0a, $0b, $0c, $0d, $5e, $5f ;         frame 2
  16201.       .db $fc, $fc, $08, $09, $58, $59, $5a, $5a ;crouching
  16202.       .db $08, $09, $28, $29, $2a, $2b, $0e, $0f ;fireball throwing
  16203.  
  16204. ;small player table
  16205.       .db $fc, $fc, $fc, $fc, $32, $33, $34, $35 ;walking frame 1
  16206.       .db $fc, $fc, $fc, $fc, $36, $37, $38, $39 ;        frame 2
  16207.       .db $fc, $fc, $fc, $fc, $3a, $37, $3b, $3c ;        frame 3
  16208.       .db $fc, $fc, $fc, $fc, $3d, $3e, $3f, $40 ;skidding
  16209.       .db $fc, $fc, $fc, $fc, $32, $41, $42, $43 ;jumping
  16210.       .db $fc, $fc, $fc, $fc, $32, $33, $44, $45 ;swimming frame 1
  16211.       .db $fc, $fc, $fc, $fc, $32, $33, $44, $47 ;         frame 2
  16212.       .db $fc, $fc, $fc, $fc, $32, $33, $48, $49 ;         frame 3
  16213.       .db $fc, $fc, $fc, $fc, $32, $33, $90, $91 ;climbing frame 1
  16214.       .db $fc, $fc, $fc, $fc, $3a, $37, $92, $93 ;         frame 2
  16215.       .db $fc, $fc, $fc, $fc, $9e, $9e, $9f, $9f ;killed
  16216.  
  16217. ;used by both player sizes
  16218.       .db $fc, $fc, $fc, $fc, $3a, $37, $4f, $4f ;small player standing
  16219.       .db $fc, $fc, $00, $01, $4c, $4d, $4e, $4e ;intermediate grow frame
  16220.       .db $00, $01, $4c, $4d, $4a, $4a, $4b, $4b ;big player standing
  16221.  
  16222. SwimKickTileNum:
  16223.       .db $31, $46
  16224.  
  16225. PlayerGfxHandler:
  16226.         lda InjuryTimer             ;if player's injured invincibility timer
  16227.          checka
  16228.         beq CntPl                   ;not set, skip checkpoint and continue code
  16229.         lda FrameCounter
  16230.         lsr                         ;otherwise check frame counter and branch
  16231.         bcs ExPGH                   ;to leave on every other frame (when d0 is set)
  16232. CntPl:  lda GameEngineSubroutine    ;if executing specific game engine routine,
  16233.         cmpn ++$0b                    ;branch ahead to some other part
  16234.         beq PlayerKilled
  16235.         lda PlayerChangeSizeFlag    ;if grow/shrink flag set
  16236.          checka
  16237.         bne DoChangeSize            ;then branch to some other code
  16238.         ldy SwimmingFlag            ;if swimming flag set, branch to
  16239.          checky
  16240.         beq FindPlayerAction        ;different part, do not return
  16241.         lda Player_State
  16242.         cmpn ++$00                    ;if player status normal,
  16243.         beq FindPlayerAction        ;branch and do not return
  16244.         jsr FindPlayerAction        ;otherwise jump and return
  16245.         lda FrameCounter
  16246.         andn ++%00000100              ;check frame counter for d2 set (8 frames every
  16247.         bne ExPGH                   ;eighth frame), and branch if set to leave
  16248.         tax                         ;initialize X to zero
  16249.         ldy Player_SprDataOffset    ;get player sprite data offset
  16250.         lda PlayerFacingDir         ;get player's facing direction
  16251.         lsr
  16252.         bcs SwimKT                  ;if player facing to the right, use current offset
  16253.         iny
  16254.         iny                         ;otherwise move to next OAM data
  16255.         iny
  16256.         iny
  16257. SwimKT: lda PlayerSize              ;check player's size
  16258.          checka
  16259.         beq BigKTS                  ;if big, use first tile
  16260.         lday Sprite_Tilenumber+24,y  ;check tile number of seventh/eighth sprite
  16261.         cmpi SwimTileRepOffset       ;against tile number in player graphics table
  16262.         beq ExPGH                   ;if spr7/spr8 tile number = value, branch to leave
  16263.         inx                         ;otherwise increment X for second tile
  16264. BigKTS: ldax SwimKickTileNum,x       ;overwrite tile number in sprite 7/8
  16265.         stay Sprite_Tilenumber+24,y  ;to animate player's feet when swimming
  16266. ExPGH:  rts                         ;then leave
  16267.  
  16268. FindPlayerAction:
  16269.       jsr ProcessPlayerAction       ;find proper offset to graphics table by player's actions
  16270.       jmp PlayerGfxProcessing       ;draw player, then process for fireball throwing
  16271.  
  16272. DoChangeSize:
  16273.       jsr HandleChangeSize          ;find proper offset to graphics table for grow/shrink
  16274.       jmp PlayerGfxProcessing       ;draw player, then process for fireball throwing
  16275.  
  16276. PlayerKilled:
  16277.       ldyn ++$0e                      ;load offset for player killed
  16278.       lday PlayerGfxTblOffsets,y     ;get offset to graphics table
  16279.  
  16280. PlayerGfxProcessing:
  16281.        sta PlayerGfxOffset           ;store offset to graphics table here
  16282.        ldan ++$04
  16283.        jsr RenderPlayerSub           ;draw player based on offset loaded
  16284.        jsr ChkForPlayerAttrib        ;set horizontal flip bits as necessary
  16285.        lda FireballThrowingTimer
  16286.          checka
  16287.        beq PlayerOffscreenChk        ;if fireball throw timer not set, skip to the end
  16288.        ldyn ++$00                      ;set value to initialize by default
  16289.        lda PlayerAnimTimer           ;get animation frame timer
  16290.        cmpi FireballThrowingTimer     ;compare to fireball throw timer
  16291.        sty FireballThrowingTimer     ;initialize fireball throw timer
  16292.               cmpcy
  16293.        bcs PlayerOffscreenChk        ;if animation frame timer =>  fireball throw timer skip to end
  16294.        sta FireballThrowingTimer     ;otherwise store animation timer into fireball throw timer
  16295.        ldyn ++$07                      ;load offset for throwing
  16296.        lday PlayerGfxTblOffsets,y     ;get offset to graphics table
  16297.        sta PlayerGfxOffset           ;store it for use later
  16298.        ldyn ++$04                      ;set to update four sprite rows by default
  16299.        lda Player_X_Speed
  16300.        orai Left_Right_Buttons        ;check for horizontal speed or left/right button press
  16301.        beq SUpdR                     ;if no speed or button press, branch using set value in Y
  16302.        dey                           ;otherwise set to update only three sprite rows
  16303. SUpdR: tya                           ;save in A for use
  16304.        jsr RenderPlayerSub           ;in sub, draw player object again
  16305.  
  16306. PlayerOffscreenChk:
  16307.            lda Player_OffscreenBits      ;get player's offscreen bits
  16308.            lsr
  16309.            lsr                           ;move vertical bits to low nybble
  16310.            lsr
  16311.            lsr
  16312.            sta SCRATCHPAD+$00                       ;store here
  16313.            ldxn ++$03                      ;check all four rows of player sprites
  16314.            lda Player_SprDataOffset      ;get player's sprite data offset
  16315.            clc
  16316.            adcn ++$18                      ;add 24 bytes to start at bottom row
  16317.            tay                           ;set as offset here
  16318. PROfsLoop: ldan ++$f8                      ;load offscreen Y coordinate just in case
  16319.            lsri SCRATCHPAD+$00                       ;shift bit into carry
  16320.            bcc NPROffscr                 ;if bit not set, skip, do not move sprites
  16321.            jsr DumpTwoSpr                ;otherwise dump offscreen Y coordinate into sprite data
  16322. NPROffscr: tya
  16323.            secsub                           ;subtract eight bytes to do
  16324.            sbcn ++$08                      ;next row up
  16325.            tay
  16326.            dex                           ;decrement row counter
  16327.            bpl PROfsLoop                 ;do this until all sprite rows are checked
  16328.            rts                           ;then we are done!
  16329.  
  16330. ;-------------------------------------------------------------------------------------
  16331.  
  16332. IntermediatePlayerData:
  16333.         .db $58, $01, $00, $60, $ff, $04
  16334.  
  16335. DrawPlayer_Intermediate:
  16336.         if Z80OPT
  16337.         ld hl,IntermediatePlayerData
  16338.         ld de,SCRATCHPAD+$02
  16339.         ld c,6
  16340.         ldir
  16341.         ld d,b;0
  16342.           ld e,++$04                       ;load sprite data offset
  16343.       ld hl,PlayerGraphicsTable+$b8                       ;load offset for small standing
  16344.       ;add hl,bc
  16345.           call DrawPlayerLoop             ;draw player accordingly
  16346.         else
  16347.           ldxn ++$05                       ;store data into zero page memory
  16348. PIntLoop: ldax IntermediatePlayerData,x   ;load data to display player as he always
  16349.           stax SCRATCHPAD+$02,x                      ;appears on world/lives display
  16350.           dex
  16351.           bpl PIntLoop                   ;do this until all data is loaded
  16352.           ldxn ++$b8                       ;load offset for small standing
  16353.           ldyn ++$04                       ;load sprite data offset
  16354.           jsr DrawPlayerLoop             ;draw player accordingly
  16355.         endif
  16356.           lda Sprite_Attributes+36       ;get empty sprite attributes
  16357.           oran ++%01000000                 ;set horizontal flip bit for bottom-right sprite
  16358.           sta Sprite_Attributes+32       ;store and leave
  16359.           rts
  16360.  
  16361. ;-------------------------------------------------------------------------------------
  16362. ;$00-$01 - used to hold tile numbers, $00 also used to hold upper extent of animation frames
  16363. ;$02 - vertical position
  16364. ;$03 - facing direction, used as horizontal flip control
  16365. ;$04 - attributes
  16366. ;$05 - horizontal position
  16367. ;$07 - number of rows to draw
  16368. ;these also used in IntermediatePlayerData
  16369.  
  16370. RenderPlayerSub:
  16371.         sta SCRATCHPAD+$07                      ;store number of rows of sprites to draw
  16372.         lda Player_Rel_XPos
  16373.         sta Player_Pos_ForScroll     ;store player's relative horizontal position
  16374.         sta SCRATCHPAD+$05                      ;store it here also
  16375.         lda Player_Rel_YPos
  16376.         sta SCRATCHPAD+$02                      ;store player's vertical position
  16377.         lda PlayerFacingDir
  16378.         sta SCRATCHPAD+$03                      ;store player's facing direction
  16379.         lda Player_SprAttrib
  16380.         sta SCRATCHPAD+$04                      ;store player's sprite attributes
  16381.         ldx PlayerGfxOffset          ;load graphics table offset
  16382.         ldy Player_SprDataOffset     ;get player's sprite data offset
  16383.  
  16384.         if Z80OPT
  16385.       ld hl,PlayerGraphicsTable
  16386.       add hl,bc
  16387. DrawPlayerLoop:
  16388.       ld a,(SCRATCHPAD+$07)
  16389.       ld b,a
  16390. DrawPlayerLoop0
  16391.       call DrawSpriteObject
  16392.       djnz DrawPlayerLoop0           ;do this until all rows are drawn
  16393.         else
  16394. DrawPlayerLoop:
  16395. DrawPlayerLoop0
  16396.         ldax PlayerGraphicsTable,x    ;load player's left side
  16397.         sta SCRATCHPAD+$00
  16398.         ldax PlayerGraphicsTable+1,x  ;now load right side
  16399.         jsr DrawOneSpriteRow
  16400.         deci SCRATCHPAD+$07                      ;decrement rows of sprites to draw
  16401.         bne DrawPlayerLoop0           ;do this until all rows are drawn
  16402.         endif
  16403.         rts
  16404.  
  16405. ProcessPlayerAction:
  16406.         lda Player_State      ;get player's state
  16407.         cmpn ++$03
  16408.         beq ActionClimbing    ;if climbing, branch here
  16409.         cmpn ++$02
  16410.         beq ActionFalling     ;if falling, branch here
  16411.         cmpn ++$01
  16412.         bne ProcOnGroundActs  ;if not jumping, branch here
  16413.         lda SwimmingFlag
  16414.          checka
  16415.         bne ActionSwimming    ;if swimming flag set, branch elsewhere
  16416.         ldyn ++$06              ;load offset for crouching
  16417.         lda CrouchingFlag     ;get crouching flag
  16418.          checka
  16419.         bne NonAnimatedActs   ;if set, branch to get offset for graphics table
  16420.         ldyn ++$00              ;otherwise load offset for jumping
  16421.         jmp NonAnimatedActs   ;go to get offset to graphics table
  16422.  
  16423. ProcOnGroundActs:
  16424.         ldyn ++$06                   ;load offset for crouching
  16425.         lda CrouchingFlag          ;get crouching flag
  16426.          checka
  16427.         bne NonAnimatedActs        ;if set, branch to get offset for graphics table
  16428.         ldyn ++$02                   ;load offset for standing
  16429.         lda Player_X_Speed         ;check player's horizontal speed
  16430.         orai Left_Right_Buttons     ;and left/right controller bits
  16431.         beq NonAnimatedActs        ;if no speed or buttons pressed, use standing offset
  16432.         lda Player_XSpeedAbsolute  ;load walking/running speed
  16433.         cmpn ++$09
  16434.               cmpcy
  16435.         bcc ActionWalkRun          ;if less than a certain amount, branch, too slow to skid
  16436.         lda Player_MovingDir       ;otherwise check to see if moving direction
  16437.         andi PlayerFacingDir        ;and facing direction are the same
  16438.         bne ActionWalkRun          ;if moving direction = facing direction, branch, don't skid
  16439.         iny                        ;otherwise increment to skid offset ($03)
  16440.  
  16441. NonAnimatedActs:
  16442.         jsr GetGfxOffsetAdder      ;do a sub here to get offset adder for graphics table
  16443.         ldan ++$00
  16444.         sta PlayerAnimCtrl         ;initialize animation frame control
  16445.         lday PlayerGfxTblOffsets,y  ;load offset to graphics table using size as offset
  16446.         rts
  16447.  
  16448. ActionFalling:
  16449.         ldyn ++$04                  ;load offset for walking/running
  16450.         jsr GetGfxOffsetAdder     ;get offset to graphics table
  16451.         jmp GetCurrentAnimOffset  ;execute instructions for falling state
  16452.  
  16453. ActionWalkRun:
  16454.         ldyn ++$04               ;load offset for walking/running
  16455.         jsr GetGfxOffsetAdder  ;get offset to graphics table
  16456.         jmp FourFrameExtent    ;execute instructions for normal state
  16457.  
  16458. ActionClimbing:
  16459.         ldyn ++$05               ;load offset for climbing
  16460.         lda Player_Y_Speed     ;check player's vertical speed
  16461.          checka
  16462.         beq NonAnimatedActs    ;if no speed, branch, use offset as-is
  16463.         jsr GetGfxOffsetAdder  ;otherwise get offset for graphics table
  16464.         jmp ThreeFrameExtent   ;then skip ahead to more code
  16465.  
  16466. ActionSwimming:
  16467.         ldyn ++$01               ;load offset for swimming
  16468.         jsr GetGfxOffsetAdder
  16469.         lda JumpSwimTimer      ;check jump/swim timer
  16470.         orai PlayerAnimCtrl     ;and animation frame control
  16471.         bne FourFrameExtent    ;if any one of these set, branch ahead
  16472.         lda A_B_Buttons
  16473.         asl                    ;check for A button pressed
  16474.         bcs FourFrameExtent    ;branch to same place if A button pressed
  16475.  
  16476. GetCurrentAnimOffset:
  16477.         lda PlayerAnimCtrl         ;get animation frame control
  16478.         jmp GetOffsetFromAnimCtrl  ;jump to get proper offset to graphics table
  16479.  
  16480. FourFrameExtent:
  16481.         ldan ++$03              ;load upper extent for frame control
  16482.         jmp AnimationControl  ;jump to get offset and animate player object
  16483.  
  16484. ThreeFrameExtent:
  16485.         ldan ++$02              ;load upper extent for frame control for climbing
  16486.  
  16487. AnimationControl:
  16488.           sta SCRATCHPAD+$00                   ;store upper extent here
  16489.           jsr GetCurrentAnimOffset  ;get proper offset to graphics table
  16490.           pha                       ;save offset to stack
  16491.           lda PlayerAnimTimer       ;load animation frame timer
  16492.          checka
  16493.           bne ExAnimC               ;branch if not expired
  16494.           lda PlayerAnimTimerSet    ;get animation frame timer amount
  16495.           sta PlayerAnimTimer       ;and set timer accordingly
  16496.           lda PlayerAnimCtrl
  16497.           clc                       ;add one to animation frame control
  16498.           adcn ++$01
  16499.           cmpi SCRATCHPAD+$00                   ;compare to upper extent
  16500.               cmpcy
  16501.           bcc SetAnimC              ;if frame control + 1 < upper extent, use as next
  16502.           ldan ++$00                  ;otherwise initialize frame control
  16503. SetAnimC: sta PlayerAnimCtrl        ;store as new animation frame control
  16504. ExAnimC:  pla                       ;get offset to graphics table from stack and leave
  16505.           rts
  16506.  
  16507. GetGfxOffsetAdder:
  16508.         lda PlayerSize  ;get player's size
  16509.          checka
  16510.         beq SzOfs       ;if player big, use current offset as-is
  16511.         tya             ;for big player
  16512.         clc             ;otherwise add eight bytes to offset
  16513.         adcn ++$08        ;for small player
  16514.         tay
  16515. SzOfs:  rts             ;go back
  16516.  
  16517. ChangeSizeOffsetAdder:
  16518.         .db $00, $01, $00, $01, $00, $01, $02, $00, $01, $02
  16519.         .db $02, $00, $02, $00, $02, $00, $02, $00, $02, $00
  16520.  
  16521. HandleChangeSize:
  16522.          ldy PlayerAnimCtrl           ;get animation frame control
  16523.          lda FrameCounter
  16524.          andn ++%00000011               ;get frame counter and execute this code every
  16525.          bne GorSLog                  ;fourth frame, otherwise branch ahead
  16526.          iny                          ;increment frame control
  16527.          cpyn ++$0a                     ;check for preset upper extent
  16528.               cmpcy
  16529.          bcc CSzNext                  ;if not there yet, skip ahead to use
  16530.          ldyn ++$00                     ;otherwise initialize both grow/shrink flag
  16531.          sty PlayerChangeSizeFlag     ;and animation frame control
  16532. CSzNext: sty PlayerAnimCtrl           ;store proper frame control
  16533. GorSLog: lda PlayerSize               ;get player's size
  16534.          checka
  16535.          bne ShrinkPlayer             ;if player small, skip ahead to next part
  16536.          lday ChangeSizeOffsetAdder,y  ;get offset adder based on frame control as offset
  16537.          ldyn ++$0f                     ;load offset for player growing
  16538.  
  16539. GetOffsetFromAnimCtrl:
  16540.         asl                        ;multiply animation frame control
  16541.         asl                        ;by eight to get proper amount
  16542.         asl                        ;to add to our offset
  16543.         adcy PlayerGfxTblOffsets,y  ;add to offset to graphics table
  16544.         rts                        ;and return with result in A
  16545.  
  16546. ShrinkPlayer:
  16547.         tya                          ;add ten bytes to frame control as offset
  16548.         clc
  16549.         adcn ++$0a                     ;this thing apparently uses two of the swimming frames
  16550.         tax                          ;to draw the player shrinking
  16551.         ldyn ++$09                     ;load offset for small player swimming
  16552.         ldax ChangeSizeOffsetAdder,x  ;get what would normally be offset adder
  16553.          checka
  16554.         bne ShrPlF                   ;and branch to use offset if nonzero
  16555.         ldyn ++$01                     ;otherwise load offset for big player swimming
  16556. ShrPlF: lday PlayerGfxTblOffsets,y    ;get offset to graphics table based on offset loaded
  16557.         rts                          ;and leave
  16558.  
  16559. ChkForPlayerAttrib:
  16560.            ldy Player_SprDataOffset    ;get sprite data offset
  16561.            lda GameEngineSubroutine
  16562.            cmpn ++$0b                    ;if executing specific game engine routine,
  16563.            beq KilledAtt               ;branch to change third and fourth row OAM attributes
  16564.            lda PlayerGfxOffset         ;get graphics table offset
  16565.            cmpn ++$50
  16566.            beq C_S_IGAtt               ;if crouch offset, either standing offset,
  16567.            cmpn ++$b8                    ;or intermediate growing offset,
  16568.            beq C_S_IGAtt               ;go ahead and execute code to change
  16569.            cmpn ++$c0                    ;fourth row OAM attributes only
  16570.            beq C_S_IGAtt
  16571.            cmpn ++$c8
  16572.            bne ExPlyrAt                ;if none of these, branch to leave
  16573. KilledAtt: lday Sprite_Attributes+16,y
  16574.            andn ++%00111111              ;mask out horizontal and vertical flip bits
  16575.            stay Sprite_Attributes+16,y  ;for third row sprites and save
  16576.            lday Sprite_Attributes+20,y
  16577.            andn ++%00111111  
  16578.            oran ++%01000000              ;set horizontal flip bit for second
  16579.            stay Sprite_Attributes+20,y  ;sprite in the third row
  16580. C_S_IGAtt: lday Sprite_Attributes+24,y
  16581.            andn ++%00111111              ;mask out horizontal and vertical flip bits
  16582.            stay Sprite_Attributes+24,y  ;for fourth row sprites and save
  16583.            lday Sprite_Attributes+28,y
  16584.            andn ++%00111111
  16585.            oran ++%01000000              ;set horizontal flip bit for second
  16586.            stay Sprite_Attributes+28,y  ;sprite in the fourth row
  16587. ExPlyrAt:  rts                         ;leave
  16588.  
  16589. ;-------------------------------------------------------------------------------------
  16590. ;$00 - used in adding to get proper offset
  16591.  
  16592. RelativePlayerPosition:
  16593.         ldxn ++$00      ;set offsets for relative cooordinates
  16594.         ldyn ++$00      ;routine to correspond to player object
  16595.         jmp RelWOfs   ;get the coordinates
  16596.  
  16597. RelativeBubblePosition:
  16598.         ldyn ++$01                ;set for air bubble offsets
  16599.         jsr GetProperObjOffset  ;modify X to get proper air bubble offset
  16600.         ldyn ++$03
  16601.         jmp RelWOfs             ;get the coordinates
  16602.  
  16603. RelativeFireballPosition:
  16604.          ldyn ++$00                    ;set for fireball offsets
  16605.          jsr GetProperObjOffset      ;modify X to get proper fireball offset
  16606.          ldyn ++$02
  16607. RelWOfs: jsr GetObjRelativePosition  ;get the coordinates
  16608.          ldx ObjectOffset            ;return original offset
  16609.          rts                         ;leave
  16610.  
  16611. RelativeMiscPosition:
  16612.         ldyn ++$02                ;set for misc object offsets
  16613.         jsr GetProperObjOffset  ;modify X to get proper misc object offset
  16614.         ldyn ++$06
  16615.         jmp RelWOfs             ;get the coordinates
  16616.  
  16617. RelativeEnemyPosition:
  16618.         ldan ++$01                     ;get coordinates of enemy object
  16619.         ldyn ++$01                     ;relative to the screen
  16620.         jmp VariableObjOfsRelPos
  16621.  
  16622. RelativeBlockPosition:
  16623.         ldan ++$09                     ;get coordinates of one block object
  16624.         ldyn ++$04                     ;relative to the screen
  16625.         jsr VariableObjOfsRelPos
  16626.         inx                          ;adjust offset for other block object if any
  16627.         inx
  16628.         ldan ++$09
  16629.         iny                          ;adjust other and get coordinates for other one
  16630.  
  16631. VariableObjOfsRelPos:
  16632.         stx SCRATCHPAD+$00                     ;store value to add to A here
  16633.         clc
  16634.         adci SCRATCHPAD+$00                     ;add A to value stored
  16635.         tax                         ;use as enemy offset
  16636.         jsr GetObjRelativePosition
  16637.         ldx ObjectOffset            ;reload old object offset and leave
  16638.         rts
  16639.  
  16640. GetObjRelativePosition:
  16641.         ldax SprObject_Y_Position,x  ;load vertical coordinate low
  16642.         stay SprObject_Rel_YPos,y    ;store here
  16643.         ldax SprObject_X_Position,x  ;load horizontal coordinate
  16644.         secsub                         ;subtract left edge coordinate
  16645.         sbci ScreenLeft_X_Pos
  16646.         stay SprObject_Rel_XPos,y    ;store result here
  16647.         rts
  16648.  
  16649. ;-------------------------------------------------------------------------------------
  16650. ;$00 - used as temp variable to hold offscreen bits
  16651.  
  16652. GetPlayerOffscreenBits:
  16653.         ldxn ++$00                 ;set offsets for player-specific variables
  16654.         ldyn ++$00                 ;and get offscreen information about player
  16655.         jmp GetOffScreenBitsSet
  16656.  
  16657. GetFireballOffscreenBits:
  16658.         ldyn ++$00                 ;set for fireball offsets
  16659.         jsr GetProperObjOffset   ;modify X to get proper fireball offset
  16660.         ldyn ++$02                 ;set other offset for fireball's offscreen bits
  16661.         jmp GetOffScreenBitsSet  ;and get offscreen information about fireball
  16662.  
  16663. GetBubbleOffscreenBits:
  16664.         ldyn ++$01                 ;set for air bubble offsets
  16665.         jsr GetProperObjOffset   ;modify X to get proper air bubble offset
  16666.         ldyn ++$03                 ;set other offset for airbubble's offscreen bits
  16667.         jmp GetOffScreenBitsSet  ;and get offscreen information about air bubble
  16668.  
  16669. GetMiscOffscreenBits:
  16670.         ldyn ++$02                 ;set for misc object offsets
  16671.         jsr GetProperObjOffset   ;modify X to get proper misc object offset
  16672.         ldyn ++$06                 ;set other offset for misc object's offscreen bits
  16673.         jmp GetOffScreenBitsSet  ;and get offscreen information about misc object
  16674.  
  16675. ObjOffsetData:
  16676.         .db $07, $16, $0d
  16677.  
  16678. GetProperObjOffset:
  16679.         txa                  ;move offset to A
  16680.         clc
  16681.         adcy ObjOffsetData,y  ;add amount of bytes to offset depending on setting in Y
  16682.         tax                  ;put back in X and leave
  16683.         rts
  16684.  
  16685. GetEnemyOffscreenBits:
  16686.         if Z80OPT ;???эх яюьюурхЄ т 1-2
  16687.         inc c
  16688.         call RunOffscrBitsSubs ;a=$00, $08, $0c, $0e, $0f, $07, $03, $01, $00
  16689.         add a,a                         ;move low nybble to high nybble
  16690.         add a,a
  16691.         add a,a
  16692.         add a,a
  16693.         ld hl,SCRATCHPAD+$00
  16694.         or (hl)                    ;mask together with previously saved low nybble
  16695.         ld (SprObject_OffscrBits+1),a
  16696.         ld hl,ObjectOffset
  16697.         ld c,(hl)
  16698.         ret
  16699.         else
  16700.         ldan ++$01                 ;set A to add 1 byte in order to get enemy offset
  16701.         ldyn ++$01                 ;set Y to put offscreen bits in Enemy_OffscreenBits
  16702.         jmp SetOffscrBitsOffset
  16703.         endif
  16704.  
  16705. GetBlockOffscreenBits:
  16706.         ldan ++$09       ;set A to add 9 bytes in order to get block obj offset
  16707.         ldyn ++$04       ;set Y to put offscreen bits in Block_OffscreenBits
  16708.  
  16709. SetOffscrBitsOffset:
  16710.         stx SCRATCHPAD+$00
  16711.         clc           ;add contents of X to A to get
  16712.         adci SCRATCHPAD+$00       ;appropriate offset, then give back to X
  16713.         tax
  16714.  
  16715. GetOffScreenBitsSet:
  16716.         tya                         ;save offscreen bits offset to stack for now
  16717.         pha
  16718.         jsr RunOffscrBitsSubs ;a=$00, $08, $0c, $0e, $0f, $07, $03, $01, $00
  16719.         asl                         ;move low nybble to high nybble
  16720.         asl
  16721.         asl
  16722.         asl
  16723.         orai SCRATCHPAD+$00                     ;mask together with previously saved low nybble
  16724.         sta SCRATCHPAD+$00                     ;store both here
  16725.         pla                         ;get offscreen bits offset from stack
  16726.         tay
  16727.         lda SCRATCHPAD+$00                     ;get value here and store elsewhere
  16728.         stay SprObject_OffscrBits,y
  16729.         ldx ObjectOffset
  16730.         rts
  16731.  
  16732. RunOffscrBitsSubs:
  16733. ;2 calls
  16734. ;x эр т√їюфх эх трцхэ, трцэю SCRATCHPAD+$00 [ш +$07(???)]
  16735.         if Z80OPT ;???
  16736.  
  16737.         call GetXOffscreenBits  ;do subroutine here
  16738.         rra                    ;move high nybble to low
  16739.         rra
  16740.         rra
  16741.         rra        ;TODO єсЁрЄ№ т GetXOffscreenBits
  16742.         and 0x0f
  16743.         ld (SCRATCHPAD+$00),a                ;store here
  16744. ;test top of screen
  16745.         ;ld c,0
  16746.         xor a ;load coordinate for edge of vertical unit ;.db $ff, $00
  16747.         sub (ix+SprObject_Y_Position-SprObject_X_Position)  ;subtract from vertical coordinate of object
  16748.           ld l,a;sta SCRATCHPAD+$07                      ;store here
  16749.           ld a,++$01                     ;subtract one from vertical high byte of object
  16750.         sbc a,(ix+SprObject_Y_HighPos-SprObject_X_Position)
  16751.         ;  jp m,YLdBData                 ;if under top of the screen or beyond bottom, branch
  16752.         jp m,YLdBbottom ;if under top of the screen or beyond bottom
  16753.         ld c,4  ;if not, load alternate offset value here (y+DefaultYOnscreenOfs+1) ;.db $04, $00, $04
  16754.           jp nz,YLdBData                 ;if one vertical unit or more above the screen, branch ;ЄєЄ Єюўэю т√їюф
  16755. ;с√ыю dyhigh==0
  16756.           ld a,l;lda SCRATCHPAD+$07       ;get pixel difference
  16757.           cp 32 ;cmpi SCRATCHPAD+$06       ;compare to preset value
  16758.           jr nc,YLdBData  ;if pixel difference HIGH = preset value, branch ;шёяюы№чєхЄ c=x=4 ;ЄєЄ Єюўэю т√їюф
  16759.           rra           ;divide by eight
  16760.           rra
  16761.           rra ;т ьырф°шї сшЄрї: 0..3
  16762.           and 3 ;andn ++$07      ;mask out all but 3 LSB ;с√ыю эх 2 сшЄр, яюЄюьє ўЄю ¤Єю с√ыр юс∙р  яЁюЎхфєЁр фы  X ш Y
  16763.           ld c,a;tax           ;use as offset
  16764. YLdBData:
  16765.         ld hl,YOffscreenBitsData ;.db $00, $08, $0c, $0e, $0f, $07, $03, $01, $00 ;чрўхь яюёыхфэшщ 0?
  16766.         add hl,bc
  16767.         ld a,(hl) ;get offscreen data bits using offset
  16768.           or a
  16769.           ret nz                     ;if bits not zero, branch to leave
  16770. ;test bottom of screen
  16771. YLdBbottom:
  16772.         ;ld c,4
  16773.         ld a,-1 ;load coordinate for edge of vertical unit ;.db $ff, $00
  16774.         sub (ix+SprObject_Y_Position-SprObject_X_Position)  ;subtract from vertical coordinate of object
  16775.           ld l,a;sta SCRATCHPAD+$07                      ;store here
  16776.           ld a,++$01                     ;subtract one from vertical high byte of object
  16777.         sbc a,(ix+SprObject_Y_HighPos-SprObject_X_Position)
  16778.         ;  jp m,YLdBDatabottom                 ;if under top of the screen or beyond bottom, branch
  16779.         ld a,15
  16780.         ret m ;if under top of the screen or beyond bottom
  16781.         ;ld c,0  ;if not, load alternate offset value here (y+DefaultYOnscreenOfs+1) ;.db $04, $00, $04
  16782.         ld c,8-4 ;фы  єёъюЁхэш  ўхЁхч ёфтшу ЄрсышЎ√
  16783.           jp nz,YLdBDatabottom                 ;if one vertical unit or more above the screen, branch
  16784. ;с√ыю dyHSB==0
  16785.           ld a,l;lda SCRATCHPAD+$07       ;get pixel difference
  16786.           cp 32 ;cmpi SCRATCHPAD+$06       ;compare to preset value
  16787.           jr nc,YLdBDatabottom  ;if pixel difference HIGH = preset value, branch ;шёяюы№чєхЄ c=x=0
  16788.           rra           ;divide by eight
  16789.           rra
  16790.           rra ;т ьырф°шї сшЄрї: 0..3
  16791.           and 3 ;andn ++$07      ;mask out all but 3 LSB ;с√ыю эх 2 сшЄр, яюЄюьє ўЄю ¤Єю с√ыр юс∙р  яЁюЎхфєЁр фы  X ш Y
  16792.           ;add a,4
  16793.           ld c,a;tax           ;use as offset
  16794. YLdBDatabottom:
  16795.         ld hl,YOffscreenBitsData +4 ;.db $00, $08, $0c, $0e, $0f, $07, $03, $01, $00 ;чрўхь яюёыхфэшщ 0? шёяюы№чєхь хую фы  єёъюЁхэш 
  16796.         add hl,bc
  16797.         ld a,(hl) ;get offscreen data bits using offset
  16798.           ret
  16799.  
  16800.         else ;~Z80
  16801.  
  16802.         jsr GetXOffscreenBits  ;do subroutine here
  16803.         lsr                    ;move high nybble to low
  16804.         lsr
  16805.         lsr
  16806.         lsr
  16807.         sta SCRATCHPAD+$00                ;store here
  16808.         jmp GetYOffscreenBits
  16809.  
  16810.         endif
  16811.  
  16812. ;--------------------------------
  16813. ;(these apply to these three subsections)
  16814. ;$04 - used to store proper offset
  16815. ;$05 - used as adder in DividePDiff
  16816. ;$06 - used to store preset value used to compare to pixel difference in $07
  16817. ;$07 - used to store difference between coordinates of object and screen edges
  16818.  
  16819. ;TODO ърцфюх чэрўхэшх 8 Ёрч, ўЄюс√ эх ёфтшурЄ№
  16820. XOffscreenBitsData:
  16821.         .db $7f, $3f, $1f, $0f, $07, $03, $01, $00
  16822.         .db $80, $c0, $e0, $f0, $f8, $fc, $fe, $ff
  16823.  
  16824. DefaultXOnscreenOfs:
  16825.         .db $07, $0f, $07
  16826.  
  16827. GetXOffscreenBits:
  16828. ;TODO >>4?
  16829.         if Z80OPT
  16830.           ld ix,SprObject_X_Position
  16831.           add ix,bc
  16832. ;right side of screen
  16833.           ld a,(ScreenEdge_X_Pos+1) ;get pixel coordinate of edge ;т яхЁхьхээ√ї!!!
  16834.         ;ld c,15
  16835.         sub (ix) ;get difference between pixel coordinate of edge and pixel coordinate of object position
  16836.          ld l,a ;sta SCRATCHPAD+$07                     ;store here
  16837.           ld a,(ScreenEdge_PageLoc+1)    ;get page location of edge ;т яхЁхьхээ√ї!!!
  16838.         sbc a,(ix+SprObject_PageLoc-SprObject_X_Position) ;subtract from page location of object position
  16839.           ;jp m,XLdBData                ;if beyond right edge or in front of left edge, branch ;ЄєЄ Єюўэю т√їюф
  16840.          ;ld a,0xff
  16841.          ; ret m                ;if beyond right edge or in front of left edge, branch
  16842.          jp m,XLdBDataleftq ;if beyond right edge or in front of left edge, branch
  16843.          ;ld c,7 ;ldxy DefaultXOnscreenOfs+1,y ;if not, load alternate offset value here ;.db $07, $0f, $07
  16844.           jp nz,XLdBleft;XLdBData                ;if one page or more to the left of either edge, branch
  16845. ;с√ыю dxHSB==0
  16846.          ld a,l ;lda SCRATCHPAD+$07       ;get pixel difference
  16847.           cp 56 ;cmpi SCRATCHPAD+$06       ;compare to preset value
  16848.           jr nc,XLdBleft;XLdBData  ;if pixel difference >= preset value, branch
  16849.           rra           ;divide by eight
  16850.           rra
  16851.           rra ;т ьырф°шї сшЄрї: 0..6
  16852.           and ++$07      ;mask out all but 3 LSB
  16853.           ld c,a;tax           ;use as offset
  16854. ;XLdBData:
  16855.         ld hl,XOffscreenBitsData
  16856.         add hl,bc
  16857.         ld a,(hl) ;.db $7f, $3f, $1f, $0f, $07, $03, $01, $00, $80, $c0, $e0, $f0, $f8, $fc, $fe, $ff
  16858.           or a                    ;if bits not zero, branch to leave
  16859.           ret nz
  16860. ;left side of screen
  16861. XLdBleft
  16862.         ld a,(ScreenEdge_X_Pos) ;get pixel coordinate of edge ;т яхЁхьхээ√ї!!!
  16863.         ld c,7
  16864.         sub (ix) ;get difference between pixel coordinate of edge and pixel coordinate of object position
  16865.          ld l,a ;sta SCRATCHPAD+$07                     ;store here
  16866.           ld a,(ScreenEdge_PageLoc)    ;get page location of edge ;т яхЁхьхээ√ї!!!
  16867.         sbc a,(ix+SprObject_PageLoc-SprObject_X_Position) ;subtract from page location of object position
  16868.           jp m,XLdBDataleft                ;if beyond right edge or in front of left edge, branch
  16869.          ;ld c,15 ;ldxy DefaultXOnscreenOfs+1,y ;if not, load alternate offset value here ;.db $07, $0f, $07
  16870.           jp nz,XLdBDataleftq;XLdBDataleft                ;if one page or more to the left of either edge, branch ;ЄєЄ Єюўэю т√їюф
  16871. ;с√ыю dxHSB==0
  16872.          ld a,l ;lda SCRATCHPAD+$07       ;get pixel difference
  16873.           cp 56 ;cmpi SCRATCHPAD+$06       ;compare to preset value
  16874.           jr nc,XLdBDataleftq;XLdBDataleft  ;if pixel difference >= preset value, branch ;шёяюы№чєхЄ x=c=15 ;ЄєЄ Єюўэю т√їюф
  16875.           rra           ;divide by eight
  16876.           rra
  16877.           rra ;т ьырф°шї сшЄрї: 0..6
  16878.           and ++$07      ;mask out all but 3 LSB
  16879.           add a,8
  16880.           ld c,a;tax           ;use as offset
  16881. XLdBDataleft:
  16882.         ld hl,XOffscreenBitsData
  16883.         add hl,bc
  16884.         ld a,(hl) ;.db $7f, $3f, $1f, $0f, $07, $03, $01, $00, $80, $c0, $e0, $f0, $f8, $fc, $fe, $ff
  16885.           ret
  16886. XLdBDataleftq
  16887.         ld a,0xff
  16888.         ret
  16889.          
  16890.         else ;~Z80
  16891.        
  16892. ;keep x!
  16893.           stx SCRATCHPAD+$04                     ;save position in buffer to here
  16894.           ldyn ++$01                    ;start with right side of screen
  16895. XOfsLoop: lday ScreenEdge_X_Pos,y      ;get pixel coordinate of edge
  16896.           secsub                         ;get difference between pixel coordinate of edge
  16897.           sbcx SprObject_X_Position,x  ;and pixel coordinate of object position
  16898.           sta SCRATCHPAD+$07                     ;store here
  16899.           ldaykeepcy ScreenEdge_PageLoc,y    ;get page location of edge
  16900.           sbcx SprObject_PageLoc,x     ;subtract from page location of object position
  16901.           ldxy DefaultXOnscreenOfs,y   ;load offset value here
  16902.           cmpn ++$00      
  16903.           bmi XLdBData                ;if beyond right edge or in front of left edge, branch
  16904.           ldxy DefaultXOnscreenOfs+1,y ;if not, load alternate offset value here
  16905.           cmpn ++$01      
  16906.           bpl XLdBData                ;if one page or more to the left of either edge, branch
  16907.           ldan ++$38                    ;if no branching, load value here and store
  16908.           sta SCRATCHPAD+$06
  16909.           ldan ++$08                    ;load some other value and execute subroutine
  16910.           jsr DividePDiff
  16911. XLdBData: ldax XOffscreenBitsData,x    ;get bits here
  16912.           ldx SCRATCHPAD+$04                     ;reobtain position in buffer
  16913.           cmpn ++$00                    ;if bits not zero, branch to leave
  16914.           bne ExXOfsBS
  16915.           dey                         ;otherwise, do left side of screen now
  16916.           bpl XOfsLoop                ;branch if not already done with left side ;2 яЁюїюфр
  16917. ExXOfsBS: rts
  16918.         endif
  16919.  
  16920. ;--------------------------------
  16921.  
  16922. ;TODO ърцфюх чэрўхэшх 8 Ёрч, ўЄюс√ эх ёфтшурЄ№
  16923. YOffscreenBitsData:
  16924.         .db $00, $08, $0c, $0e
  16925.         .db $0f, $07, $03, $01
  16926.         .db $00 ;чрўхь юэ с√ы эєцхэ? (т Z80 ЄхяхЁ№ эєцхэ)
  16927.  
  16928. DefaultYOnscreenOfs:
  16929.         .db $04, $00, $04
  16930.  
  16931. HighPosUnitData:
  16932.         .db $ff, $00
  16933.  
  16934.         if Z80OPT
  16935.         else
  16936. GetYOffscreenBits:
  16937.           stx SCRATCHPAD+$04                      ;save position in buffer to here
  16938.           ldyn ++$01                     ;start with top of screen
  16939. YOfsLoop0: lday HighPosUnitData,y        ;load coordinate for edge of vertical unit
  16940.           secsub
  16941.           sbcx SprObject_Y_Position,x   ;subtract from vertical coordinate of object
  16942.           sta SCRATCHPAD+$07                      ;store here
  16943.           ldan ++$01                     ;subtract one from vertical high byte of object
  16944.           sbcx SprObject_Y_HighPos,x
  16945.           ldxy DefaultYOnscreenOfs,y    ;load offset value here
  16946.           cmpn ++$00
  16947.           bmi YLdBData                 ;if under top of the screen or beyond bottom, branch
  16948.           ldxy DefaultYOnscreenOfs+1,y  ;if not, load alternate offset value here
  16949.           cmpn ++$01
  16950.           bpl YLdBData                 ;if one vertical unit or more above the screen, branch
  16951.           ldan ++$20                     ;if no branching, load value here and store
  16952.           sta SCRATCHPAD+$06
  16953.           ldan ++$04                     ;load some other value and execute subroutine
  16954.           jsr DividePDiff
  16955. YLdBData: ldax YOffscreenBitsData,x     ;get offscreen data bits using offset
  16956.           ldx SCRATCHPAD+$04                      ;reobtain position in buffer
  16957.           cmpn ++$00
  16958.           bne ExYOfsBS                 ;if bits not zero, branch to leave
  16959.           dey                          ;otherwise, do bottom of the screen now
  16960.           bpl YOfsLoop0
  16961. ExYOfsBS: rts
  16962.         endif
  16963.  
  16964. ;--------------------------------
  16965.  
  16966. DividePDiff:
  16967. ;a = 4 (Y) / 8 (X)
  16968. ;y = эюьхЁ яЁюїюфр т ъююЁфшэрЄх (0 = ыхтю/эшч, 1 = яЁртю/тхЁї)
  16969. ;out: x
  16970.         if Z80OPT
  16971.           ld ly,a;sta SCRATCHPAD+$05       ;store current value in A here
  16972.           ld hl,(SCRATCHPAD+$06)
  16973.           ld a,h ;lda SCRATCHPAD+$07       ;get pixel difference
  16974.           cp l ;cmpi SCRATCHPAD+$06       ;compare to preset value
  16975.           ret nc  ;if pixel difference >= preset value, branch
  16976.           rra           ;divide by eight
  16977.           rra
  16978.           rra
  16979.           and ++$07      ;mask out all but 3 LSB
  16980.         inc e ;right side of the screen or top?
  16981.         dec e
  16982.           jr nz,SetOscrO  ;if so, branch, use difference / 8 as offset
  16983.           add a,ly; SCRATCHPAD+$05       ;if not, add value to difference / 8
  16984. SetOscrO: ld c,a           ;use as offset
  16985.         ret
  16986.         else
  16987.           sta SCRATCHPAD+$05       ;store current value in A here
  16988.           lda SCRATCHPAD+$07       ;get pixel difference
  16989.           cmpi SCRATCHPAD+$06       ;compare to preset value
  16990.               cmpcy
  16991.           bcs ExDivPD   ;if pixel difference >= preset value, branch
  16992.           lsr           ;divide by eight
  16993.           lsr
  16994.           lsr
  16995.           andn ++$07      ;mask out all but 3 LSB
  16996.           cpyn ++$01      ;right side of the screen or top?
  16997.               cmpcy
  16998.           bcs SetOscrO  ;if so, branch, use difference / 8 as offset
  16999.           adci SCRATCHPAD+$05       ;if not, add value to difference / 8
  17000. SetOscrO: tax           ;use as offset
  17001. ExDivPD:  rts           ;leave
  17002.         endif
  17003.  
  17004. ;-------------------------------------------------------------------------------------
  17005. ;$00-$01 - tile numbers (hl, out: hl+=2)
  17006. ;$02 - Y coordinate
  17007. ;$03 - flip control
  17008. ;$04 - sprite attributes
  17009. ;$05 - X coordinate
  17010. ;y = Sprite_Data offset
  17011. ;out: [x+=2], y+=8
  17012.  
  17013. DrawSpriteObject:
  17014.         if Z80OPT
  17015.          ld ix,Sprite_Data
  17016.          add ix,de
  17017.          lda SCRATCHPAD+$03                    ;get saved flip control bits
  17018.          rra
  17019.          rra                        ;move d1 into carry
  17020.          ;ld hl,(SCRATCHPAD+$00)
  17021.          ld a,(hl)
  17022.          jr nc,NoHFlip                ;if d1 not set, branch
  17023.          ld (ix+Sprite_Tilenumber-Sprite_Data+4),a  ;store first tile into second sprite
  17024.          inc hl
  17025.          ld a,(hl)
  17026.          ld (ix+Sprite_Tilenumber-Sprite_Data),a ;and second into first sprite
  17027.          ld a,(SCRATCHPAD+$04)
  17028.          or 0x40                   ;activate horizontal flip OAM attribute
  17029.          jp SetHFAt                ;and unconditionally branch
  17030. NoHFlip: ld (ix+Sprite_Tilenumber-Sprite_Data),a    ;store first tile into first sprite
  17031.          inc hl
  17032.          ld a,(hl)
  17033.          ld (ix+Sprite_Tilenumber-Sprite_Data+4),a ;and second into second sprite
  17034.          ld a,(SCRATCHPAD+$04)                    ;схч +0x40 OAM attribute
  17035. SetHFAt:
  17036.          ld (ix+Sprite_Attributes-Sprite_Data),a    ;store sprite attributes
  17037.          ld (ix+Sprite_Attributes-Sprite_Data+4),a
  17038.          ld a,(SCRATCHPAD+$02)                    ;now the y coordinates
  17039.          ld (ix+Sprite_Y_Position-Sprite_Data),a   ;note because they are
  17040.          ld (ix+Sprite_Y_Position-Sprite_Data+4),a ;side by side, they are the same
  17041.          add a,8    ;add eight pixels to the next y coordinate
  17042.          ld (SCRATCHPAD+$02),a
  17043.          ld a,(SCRATCHPAD+$05)
  17044.          ld (ix+Sprite_X_Position-Sprite_Data),a    ;store x coordinate, then
  17045.          add a,8                        ;add 8 pixels and store another to
  17046.          ld (ix+Sprite_X_Position-Sprite_Data+4),a  ;put them side by side
  17047.          ld a,e                        ;add eight to the offset in Y to
  17048.          add a,8                      ;move to the next two sprites
  17049.          ld e,a
  17050.          inc hl
  17051.         else
  17052.          lda SCRATCHPAD+$03                    ;get saved flip control bits
  17053.          lsr
  17054.          lsr                        ;move d1 into carry
  17055.          lda SCRATCHPAD+$00
  17056.          bcc NoHFlip                ;if d1 not set, branch
  17057.          stay Sprite_Tilenumber+4,y  ;store first tile into second sprite
  17058.          lda SCRATCHPAD+$01                    ;and second into first sprite
  17059.          stay Sprite_Tilenumber,y
  17060.          ldan ++$40                   ;activate horizontal flip OAM attribute
  17061.          checka
  17062.          bne SetHFAt                ;and unconditionally branch
  17063. NoHFlip: stay Sprite_Tilenumber,y    ;store first tile into first sprite
  17064.          lda SCRATCHPAD+$01                    ;and second into second sprite
  17065.          stay Sprite_Tilenumber+4,y
  17066.          ldan ++$00                   ;clear bit for horizontal flip
  17067. SetHFAt: orai SCRATCHPAD+$04                    ;add other OAM attributes if necessary
  17068.          stay Sprite_Attributes,y    ;store sprite attributes
  17069.          stay Sprite_Attributes+4,y
  17070.          lda SCRATCHPAD+$02                    ;now the y coordinates
  17071.          stay Sprite_Y_Position,y    ;note because they are
  17072.          stay Sprite_Y_Position+4,y  ;side by side, they are the same
  17073.          lda SCRATCHPAD+$05      
  17074.          stay Sprite_X_Position,y    ;store x coordinate, then
  17075.          clc                        ;add 8 pixels and store another to
  17076.          adcn ++$08                   ;put them side by side
  17077.          stay Sprite_X_Position+4,y
  17078.          lda SCRATCHPAD+$02                    ;add eight pixels to the next y
  17079.          clc                        ;coordinate
  17080.          adcn ++$08
  17081.          sta SCRATCHPAD+$02
  17082.          tya                        ;add eight to the offset in Y to
  17083.          clc                        ;move to the next two sprites
  17084.          adcn ++$08
  17085.          tay
  17086.          inx                        ;increment offset to return it to the
  17087.          inx                        ;routine that called this subroutine
  17088.         endif
  17089.          rts
  17090.  
  17091. ;-------------------------------------------------------------------------------------
  17092.  
  17093.         if Z80==0
  17094. ;unused space (т тхЁёшш Super Mario Bros..nes)
  17095. ;р т тхЁёшш Super Mario Bros (JU) (PRG 1).nes ЄєЄ 78, ee, cb, f2, ff, ff - чрўхь??? фЁєушї Ёрчышўшщ ьхцфє ¤Єшьш тхЁёш ьш эхЄ!!!
  17096.         .db $ff, $ff, $ff, $ff, $ff, $ff
  17097.         endif
  17098.  
  17099. ;-------------------------------------------------------------------------------------
  17100.         if MUSICONINT==0
  17101.         include "smbsound.asm"
  17102.         include "smbmusic.asm"
  17103.         endif
  17104. ;-------------------------------------------------------------------------------------
  17105. ;INTERRUPT VECTORS
  17106.  
  17107.        if Z80==0
  17108. ;т ъюэЎх ярь Єш яЁюуЁрьь√: 82 80 00 80 f0 ff
  17109.       .dw NonMaskableInterrupt
  17110.       .dw Start
  17111.       .dw $fff0  ;unused (т Xevious Єюцх т ъюэЎх ff, юёЄры№э√х чэрўхэш  фЁєушх, т Bomberman1 т ъюэЎх 7 фЁєушї срщЄ)
  17112.        endif
  17113.      
  17114. SwimTileRepOffset     = PlayerGraphicsTable + $9e
  17115. MusicHeaderOffsetData = MusicHeaderData - 1
  17116. MHD                   = MusicHeaderData
  17117.