back to project page

SuperMarioBros Disassembly

                   ********************************************************************************
                   * Super Mario Bros for the NES                                                 *
                   * Copyright 1985 Nintendo, Inc.                                                *
                   ********************************************************************************
                   * Disassembly by doppelganger (doppelheathen@gmail.com).  Obtained from        *
                   * https://gist.github.com/1wErt3r/4048722 (SMBDIS.ASM, posted 9-Nov-2012).     *
                   *                                                                              *
                   * The binary for this project is the iNES image for the "Japan, USA" version   *
                   * of the ROM.  It has three distinct parts:                                    *
                   *  (1) 16 byte iNES header                                                     *
                   *  (2) 32KB PRG ROM                                                            *
                   *  (3) 8KB CHR ROM                                                             *
                   *                                                                              *
                   * Only the PRG section is directly addressable by the 6502.  The iNES header   *
                   * and CHR section are given addresses here because you have to give the        *
                   * assembler something to go on.                                                *
                   ********************************************************************************
                   * Project created by Andy McFadden, using 6502bench SourceGen v1.7.  This is a *
                   * straight conversion from the original text listing to SourceGen format.      *
                   * Very little has been changed other than formatting (and, most likely, the    *
                   * introduction of some errors).  I have left spelling errors (e.g. LSFR vs.    *
                   * LFSR) in place.                                                              *
                   *                                                                              *
                   * I converted the player and enemy graphics with the "tile grid" visualizer,   *
                   * which mostly worked but some things need to be flipped horizontally partway  *
                   * through (e.g. the top half is A-B, but the bottom half is A-flipA).  On the  *
                   * bright side, the CHR ROM rendering looks pretty good.                        *
                   *                                                                              *
                   * Last updated 2020/05/14                                                      *
                   ********************************************************************************
                   GreenKoopa      .eq     $00    {const}
                   DeathMusic      .eq     %00000001 {const}
                   GameModeValue   .eq     1      {const}
                   GroundMusic     .eq     %00000001 {const}
                   Sfx_BigJump     .eq     %00000001 {const}
                   Sfx_BrickShatter .eq    %00000001 {const}
                   Sfx_CoinGrab    .eq     %00000001 {const}
                   World2          .eq     1      {const}
                   BuzzyBeetle     .eq     $02    {const}
                   GameOverMusic   .eq     %00000010 {const}
                   Level3          .eq     2      {const}
                   Sfx_BowserFlame .eq     %00000010 {const}
                   Sfx_Bump        .eq     %00000010 {const}
                   Sfx_GrowPowerUp .eq     %00000010 {const}
                   VictoryModeValue .eq    2      {const}
                   WaterMusic      .eq     %00000010 {const}
                   GameOverModeValue .eq   3      {const}
                   RedKoopa        .eq     $03    {const}
                   Sfx_EnemyStomp  .eq     %00000100 {const}
                   Sfx_GrowVine    .eq     %00000100 {const}
                   UndergroundMusic .eq    %00000100 {const}
                   VictoryMusic    .eq     %00000100 {const}
                   World5          .eq     4      {const}
                   HammerBro       .eq     $05    {const}
                   World6          .eq     5      {const}
                   Goomba          .eq     $06    {const}
                   World7          .eq     6      {const}
                   Bloober         .eq     $07    {const}
                   World8          .eq     7      {const}
                   BulletBill_FrenzyVar .eq $08    {const}
                   CastleMusic     .eq     %00001000 {const}
                   EndOfCastleMusic .eq    %00001000 {const}
                   Sfx_Blast       .eq     %00001000 {const}
                   Sfx_EnemySmack  .eq     %00001000 {const}
                   TallEnemy       .eq     $09    {const}
                   GreyCheepCheep  .eq     $0a    {const}
                   RedCheepCheep   .eq     $0b    {const}
                   Podoboo         .eq     $0c    {const}
                   PiranhaPlant    .eq     $0d    {const}
                   GreenParatroopaJump .eq $0e    {const}
                   CloudMusic      .eq     %00010000 {const}
                   Sfx_PipeDown_Injury .eq %00010000 {const}
                   Sfx_TimerTick   .eq     %00010000 {const}
                   Start_Button    .eq     %00010000 {const}
                   Lakitu          .eq     $11    {const}
                   Spiny           .eq     $12    {const}
                   FlyCheepCheepFrenzy .eq $14    {const}
                   FlyingCheepCheep .eq    $14    {const}
                   Fireworks       .eq     $16    {const}
                   BBill_CCheep_Frenzy .eq $17    {const}
                   Stop_Frenzy     .eq     $18    {const}
                   EndOfLevelMusic .eq     %00100000 {const}
                   PipeIntroMusic  .eq     %00100000 {const}
                   Select_Button   .eq     %00100000 {const}
                   Sfx_Fireball    .eq     %00100000 {const}
                   Sfx_PowerUpGrab .eq     %00100000 {const}
                   Bowser          .eq     $2d    {const}
                   PowerUpObject   .eq     $2e    {const}
                   VineObject      .eq     $2f    {const}
                   FlagpoleFlagObject .eq  $30    {const}
                   StarFlagObject  .eq     $31    {const}
                   JumpspringObject .eq    $32    {const}
                   BulletBill_CannonVar .eq $33    {const}
                   B_Button        .eq     %01000000 {const}
                   Sfx_ExtraLife   .eq     %01000000 {const}
                   StarPowerMusic  .eq     %01000000 {const}
                   TimeRunningOutMusic .eq %01000000 {const}
                   A_Button        .eq     %10000000 {const}
                   Sfx_BowserFall  .eq     %10000000 {const}
                   Sfx_SmallJump   .eq     %10000000 {const}
                   Silence         .eq     %10000000 {const}
                   TitleScreenDataOffset .eq $1ec0  {const}
                   ObjectOffset    .eq     $08
                   FrameCounter    .eq     $09
                   A_B_Buttons     .eq     $0a
                   Up_Down_Buttons .eq     $0b
                   Left_Right_Buttons .eq  $0c
                   PreviousA_B_Buttons .eq $0d
                   GameEngineSubroutine .eq $0e
                   Enemy_Flag      .eq     $0f    {addr/6}
                   Enemy_ID        .eq     $16    {addr/6}
                   Player_State    .eq     $1d
                   Enemy_State     .eq     $1e    {addr/6}
                   Fireball_State  .eq     $24
                   Block_State     .eq     $26
                   Misc_State      .eq     $2a
                   PlayerFacingDir .eq     $33
                   DestinationPageLoc .eq  $34                     ;2 defs for $34
                   FirebarSpinDirection .eq $34
                   VictoryWalkControl .eq  $35
                   PowerUpType     .eq     $39
                   FireballBouncingFlag .eq $3a
                   HammerBroJumpTimer .eq  $3c
                   Player_MovingDir .eq    $45
                   Enemy_MovingDir .eq     $46
                   Player_X_Speed  .eq     $57
                   SprObject_X_Speed .eq   $57
                   BlooperMoveSpeed .eq    $58                     ;11 defs for $58
                   CheepCheepMoveMFlag .eq $58
                   Enemy_X_Speed   .eq     $58
                   ExplosionGfxCounter .eq $58
                   FirebarSpinState_Low .eq $58
                   Jumpspring_FixedYPos .eq $58
                   LakituMoveSpeed .eq     $58
                   PiranhaPlant_Y_Speed .eq $58
                   RedPTroopaCenterYPos .eq $58
                   XMoveSecondaryCounter .eq $58
                   YPlatformCenterYPos .eq $58
                   Fireball_X_Speed .eq    $5e
                   Block_X_Speed   .eq     $60    {addr/3}
                   Misc_X_Speed    .eq     $64
                   Player_PageLoc  .eq     $6d                     ;2 defs for $6d
                   SprObject_PageLoc .eq   $6d
                   Enemy_PageLoc   .eq     $6e    {addr/6}
                   Fireball_PageLoc .eq    $74
                   Block_PageLoc   .eq     $76    {addr/3}
                   Misc_PageLoc    .eq     $7a
                   Bubble_PageLoc  .eq     $83
                   Player_X_Position .eq   $86                     ;2 defs for $86
                   SprObject_X_Position .eq $86
                   Enemy_X_Position .eq    $87    {addr/6}
                   Fireball_X_Position .eq $8d
                   Block_X_Position .eq    $8f    {addr/3}
                   Misc_X_Position .eq     $93
                   Bubble_X_Position .eq   $9c
                   Player_Y_Speed  .eq     $9f
                   SprObject_Y_Speed .eq   $9f
                   BlooperMoveCounter .eq  $a0                     ;7 defs for $a0
                   Enemy_Y_Speed   .eq     $a0
                   ExplosionTimerCounter .eq $a0
                   FirebarSpinState_High .eq $a0
                   LakituMoveDirection .eq $a0
                   PiranhaPlant_MoveFlag .eq $a0
                   XMovePrimaryCounter .eq $a0
                   Fireball_Y_Speed .eq    $a6
                   Block_Y_Speed   .eq     $a8    {addr/3}
                   Misc_Y_Speed    .eq     $ac
                   Player_Y_HighPos .eq    $b5                     ;2 defs for $b5
                   SprObject_Y_HighPos .eq $b5
                   Enemy_Y_HighPos .eq     $b6    {addr/6}
                   Fireball_Y_HighPos .eq  $bc
                   Block_Y_HighPos .eq     $be
                   Misc_Y_HighPos  .eq     $c2
                   Bubble_Y_HighPos .eq    $cb
                   Player_Y_Position .eq   $ce                     ;2 defs for $ce
                   SprObject_Y_Position .eq $ce
                   Enemy_Y_Position .eq    $cf    {addr/6}
                   Fireball_Y_Position .eq $d5
                   Block_Y_Position .eq    $d7    {addr/3}
                   Misc_Y_Position .eq     $db
                   Bubble_Y_Position .eq   $e4
                   AreaData        .eq     $e7    {addr/2}
                   EnemyData       .eq     $e9    {addr/2}
                   NoteLenLookupTblOfs .eq $f0
                   Square1SoundBuffer .eq  $f1
                   Square2SoundBuffer .eq  $f2
                   NoiseSoundBuffer .eq    $f3
                   AreaMusicBuffer .eq     $f4
                   MusicData       .eq     $f5    {addr/2}
                   MusicOffset_Square2 .eq $f7
                   MusicOffset_Square1 .eq $f8
                   MusicOffset_Triangle .eq $f9
                   PauseSoundQueue .eq     $fa
                   AreaMusicQueue  .eq     $fb
                   EventMusicQueue .eq     $fc
                   NoiseSoundQueue .eq     $fd
                   Square2SoundQueue .eq   $fe
                   Square1SoundQueue .eq   $ff
                   VerticalFlipFlag .eq    $0109
                   FlagpoleFNum_Y_Pos .eq  $010d
                   FlagpoleFNum_YMFDummy .eq $010e
                   FlagpoleScore   .eq     $010f
                   FloateyNum_Control .eq  $0110
                   FloateyNum_X_Pos .eq    $0117
                   FloateyNum_Y_Pos .eq    $011e
                   ShellChainCounter .eq   $0125
                   FloateyNum_Timer .eq    $012c
                   DigitModifier   .eq     $0134  {addr/6}
                   Sprite_Data     .eq     $0200  {addr/32}
                   Sprite_Y_Position .eq   $0200
                   Sprite_Tilenumber .eq   $0201
                   Sprite_Attributes .eq   $0202
                   Sprite_X_Position .eq   $0203  {addr/5}
                   VRAM_Buffer1_Offset .eq $0300
                   VRAM_Buffer1    .eq     $0301  {addr/63}
                   VRAM_Buffer2_Offset .eq $0340
                   VRAM_Buffer2    .eq     $0341  {addr/63}
                   BowserBodyControls .eq  $0363
                   BowserFeetCounter .eq   $0364
                   BowserMovementSpeed .eq $0365
                   BowserOrigXPos  .eq     $0366
                   BowserFlameTimerCtrl .eq $0367
                   BowserFront_Offset .eq  $0368
                   BridgeCollapseOffset .eq $0369
                   BowserGfxFlag   .eq     $036a
                   FirebarSpinSpeed .eq    $0388
                   VineFlagOffset  .eq     $0398
                   VineHeight      .eq     $0399
                   VineObjOffset   .eq     $039a
                   VineStart_Y_Position .eq $039d
                   BalPlatformAlignment .eq $03a0
                   Platform_X_Scroll .eq   $03a1
                   HammerThrowingTimer .eq $03a2                   ;2 defs for $03a2
                   PlatformCollisionFlag .eq $03a2
                   Player_Rel_XPos .eq     $03ad                   ;2 defs for $03ad
                   SprObject_Rel_XPos .eq  $03ad
                   Enemy_Rel_XPos  .eq     $03ae
                   Fireball_Rel_XPos .eq   $03af
                   Bubble_Rel_XPos .eq     $03b0
                   Block_Rel_XPos  .eq     $03b1
                   Misc_Rel_XPos   .eq     $03b3
                   Player_Rel_YPos .eq     $03b8                   ;2 defs for $03b8
                   SprObject_Rel_YPos .eq  $03b8
                   Enemy_Rel_YPos  .eq     $03b9
                   Fireball_Rel_YPos .eq   $03ba
                   Bubble_Rel_YPos .eq     $03bb
                   Block_Rel_YPos  .eq     $03bc
                   Misc_Rel_YPos   .eq     $03be
                   Player_SprAttrib .eq    $03c4
                   Enemy_SprAttrib .eq     $03c5  {addr/6}
                   Player_OffscreenBits .eq $03d0                  ;2 defs for $03d0
                   SprObject_OffscrBits .eq $03d0
                   Enemy_OffscreenBits .eq $03d1
                   FBall_OffscreenBits .eq $03d2
                   Bubble_OffscreenBits .eq $03d3
                   Block_OffscreenBits .eq $03d4
                   Misc_OffscreenBits .eq  $03d6
                   EnemyOffscrBitsMasked .eq $03d8
                   Block_Orig_YPos .eq     $03e4
                   Block_BBuf_Low  .eq     $03e6
                   Block_Metatile  .eq     $03e8
                   Block_PageLoc2  .eq     $03ea
                   Block_RepFlag   .eq     $03ec
                   SprDataOffset_Ctrl .eq  $03ee
                   Block_ResidualCounter .eq $03f0
                   Block_Orig_XPos .eq     $03f1
                   AttributeBuffer .eq     $03f9
                   SprObject_X_MoveForce .eq $0400
                   Enemy_X_MoveForce .eq   $0401                   ;3 defs for $0401
                   RedPTroopaOrigXPos .eq  $0401
                   YPlatformTopYPos .eq    $0401
                   Player_YMF_Dummy .eq    $0416
                   SprObject_YMF_Dummy .eq $0416
                   BowserFlamePRandomOfs .eq $0417                 ;3 defs for $0417
                   Enemy_YMF_Dummy .eq     $0417
                   PiranhaPlantUpYPos .eq  $0417
                   Bubble_YMF_Dummy .eq    $042c
                   Player_Y_MoveForce .eq  $0433
                   SprObject_Y_MoveForce .eq $0433
                   CheepCheepOrigYPos .eq  $0434                   ;3 defs for $434
                   Enemy_Y_MoveForce .eq   $0434
                   PiranhaPlantDownYPos .eq $0434
                   Block_Y_MoveForce .eq   $043c  {addr/3}
                   MaximumLeftSpeed .eq    $0450
                   MaximumRightSpeed .eq   $0456
                   Cannon_Offset   .eq     $046a
                   Whirlpool_Offset .eq    $046a
                   Cannon_PageLoc  .eq     $046b                   ;2 defs for $046b
                   Whirlpool_PageLoc .eq   $046b
                   Cannon_X_Position .eq   $0471                   ;2 defs for $0471
                   Whirlpool_LeftExtent .eq $0471
                   Cannon_Y_Position .eq   $0477                   ;2 defs for $0477
                   Whirlpool_Length .eq    $0477
                   Cannon_Timer    .eq     $047d                   ;2 defs for $047d
                   Whirlpool_Flag  .eq     $047d
                   BowserHitPoints .eq     $0483
                   StompChainCounter .eq   $0484
                   Player_CollisionBits .eq $0490
                   Enemy_CollisionBits .eq $0491
                   Player_BoundBoxCtrl .eq $0499                   ;2 defs for $0499
                   SprObj_BoundBoxCtrl .eq $0499
                   Enemy_BoundBoxCtrl .eq  $049a  {addr/6}
                   Fireball_BoundBoxCtrl .eq $04a0
                   Misc_BoundBoxCtrl .eq   $04a2
                   BoundingBox_UL_XPos .eq $04ac
                   BoundingBox_UL_YPos .eq $04ad
                   BoundingBox_DR_XPos .eq $04ae
                   BoundingBox_DR_YPos .eq $04af
                   EnemyBoundingBoxCoord .eq $04b0  {addr/4}
                   Block_Buffer_1  .eq     $0500
                   Block_Buffer_2  .eq     $05d0
                   BlockBufferColumnPos .eq $06a0
                   MetatileBuffer  .eq     $06a1  {addr/11}
                   HammerEnemyOffset .eq   $06ae
                   JumpCoinMiscOffset .eq  $06b7
                   BrickCoinTimerFlag .eq  $06bc
                   Misc_Collision_Flag .eq $06be
                   unused_06c9     .eq     $06c9
                   EnemyFrenzyBuffer .eq   $06cb
                   SecondaryHardMode .eq   $06cc
                   EnemyFrenzyQueue .eq    $06cd
                   FireballCounter .eq     $06ce
                   DuplicateObj_Offset .eq $06cf
                   LakituReappearTimer .eq $06d1
                   NumberofGroupEnemies .eq $06d3
                   ColorRotateOffset .eq   $06d4
                   PlayerGfxOffset .eq     $06d5
                   WarpZoneControl .eq     $06d6
                   FireworksCounter .eq    $06d7
                   MultiLoopCorrectCntr .eq $06d9
                   MultiLoopPassCntr .eq   $06da
                   JumpspringForce .eq     $06db
                   MaxRangeFromOrigin .eq  $06dc
                   BitMFilter      .eq     $06dd
                   ChangeAreaTimer .eq     $06de
                   SprShuffleAmtOffset .eq $06e0
                   SprShuffleAmt   .eq     $06e1  {addr/3}
                   SprDataOffset   .eq     $06e4  {addr/15}
                   Enemy_SprDataOffset .eq $06e5
                   Alt_SprDataOffset .eq   $06ec                   ;2 defs for $06ec
                   Block_SprDataOffset .eq $06ec
                   Bubble_SprDataOffset .eq $06ee
                   FBall_SprDataOffset .eq $06f1
                   Misc_SprDataOffset .eq  $06f3
                   SavedJoypad1Bits .eq    $06fc
                   SavedJoypad2Bits .eq    $06fd
                   Player_X_Scroll .eq     $06ff
                   Player_XSpeedAbsolute .eq $0700
                   FrictionAdderHigh .eq   $0701
                   FrictionAdderLow .eq    $0702
                   RunningSpeed    .eq     $0703
                   SwimmingFlag    .eq     $0704
                   Player_X_MoveForce .eq  $0705
                   DiffToHaltJump  .eq     $0706
                   JumpOrigin_Y_HighPos .eq $0707
                   JumpOrigin_Y_Position .eq $0708
                   VerticalForce   .eq     $0709
                   VerticalForceDown .eq   $070a
                   PlayerChangeSizeFlag .eq $070b
                   PlayerAnimTimerSet .eq  $070c
                   PlayerAnimCtrl  .eq     $070d
                   JumpspringAnimCtrl .eq  $070e
                   FlagpoleCollisionYPos .eq $070f
                   PlayerEntranceCtrl .eq  $0710
                   FireballThrowingTimer .eq $0711
                   DeathMusicLoaded .eq    $0712
                   FlagpoleSoundQueue .eq  $0713
                   CrouchingFlag   .eq     $0714
                   GameTimerSetting .eq    $0715
                   DisableCollisionDet .eq $0716
                   DemoAction      .eq     $0717
                   DemoActionTimer .eq     $0718
                   PrimaryMsgCounter .eq   $0719
                   ScreenLeft_PageLoc .eq  $071a
                   ScreenRight_PageLoc .eq $071b
                   ScreenLeft_X_Pos .eq    $071c
                   ScreenRight_X_Pos .eq   $071d
                   ColumnSets      .eq     $071e
                   AreaParserTaskNum .eq   $071f
                   CurrentNTAddr_High .eq  $0720
                   CurrentNTAddr_Low .eq   $0721
                   Sprite0HitDetectFlag .eq $0722
                   ScrollLock      .eq     $0723
                   CurrentPageLoc  .eq     $0725
                   CurrentColumnPos .eq    $0726
                   TerrainControl  .eq     $0727
                   BackloadingFlag .eq     $0728
                   BehindAreaParserFlag .eq $0729
                   AreaObjectPageLoc .eq   $072a
                   AreaObjectPageSel .eq   $072b
                   AreaDataOffset  .eq     $072c
                   AreaObjOffsetBuffer .eq $072d
                   AreaObjectLength .eq    $0730  {addr/3}
                   AreaStyle       .eq     $0733
                   StaircaseControl .eq    $0734
                   AreaObjectHeight .eq    $0735
                   MushroomLedgeHalfLen .eq $0736
                   EnemyDataOffset .eq     $0739
                   EnemyObjectPageLoc .eq  $073a
                   EnemyObjectPageSel .eq  $073b
                   ScreenRoutineTask .eq   $073c
                   ScrollThirtyTwo .eq     $073d
                   HorizontalScroll .eq    $073f
                   VerticalScroll  .eq     $0740
                   ForegroundScenery .eq   $0741
                   BackgroundScenery .eq   $0742
                   CloudTypeOverride .eq   $0743
                   BackgroundColorCtrl .eq $0744
                   LoopCommand     .eq     $0745
                   StarFlagTaskControl .eq $0746
                   TimerControl    .eq     $0747
                   CoinTallyFor1Ups .eq    $0748
                   SecondaryMsgCounter .eq $0749
                   JoypadBitMask   .eq     $074a
                   AreaType        .eq     $074e
                   AreaAddrsLOffset .eq    $074f
                   AreaPointer     .eq     $0750
                   EntrancePage    .eq     $0751
                   AltEntranceControl .eq  $0752
                   CurrentPlayer   .eq     $0753
                   PlayerSize      .eq     $0754
                   Player_Pos_ForScroll .eq $0755
                   PlayerStatus    .eq     $0756
                   FetchNewGameTimerFlag .eq $0757
                   JoypadOverride  .eq     $0758
                   GameTimerExpiredFlag .eq $0759
                   OnscreenPlayerInfo .eq  $075a  {addr/7}
                   NumberOfLives   .eq     $075a                   ;used by current player
                   HalfwayPage     .eq     $075b
                   LevelNumber     .eq     $075c                   ;the actual dash number
                   Hidden1UpFlag   .eq     $075d
                   CoinTally       .eq     $075e
                   WorldNumber     .eq     $075f
                   AreaNumber      .eq     $0760                   ;internal number used to find areas
                   OffscreenPlayerInfo .eq $0761  {addr/7}
                   OffScr_NumberofLives .eq $0761                  ;used by offscreen player
                   OffScr_Hidden1UpFlag .eq $0764
                   OffScr_WorldNumber .eq  $0766
                   OffScr_AreaNumber .eq   $0767
                   ScrollFractional .eq    $0768
                   DisableIntermediate .eq $0769
                   PrimaryHardMode .eq     $076a
                   WorldSelectNumber .eq   $076b
                   OperMode        .eq     $0770
                   OperMode_Task   .eq     $0772
                   VRAM_Buffer_AddrCtrl .eq $0773
                   DisableScreenFlag .eq   $0774
                   ScrollAmount    .eq     $0775
                   GamePauseStatus .eq     $0776
                   GamePauseTimer  .eq     $0777
                   Mirror_PPU_CTRL_REG1 .eq $0778
                   Mirror_PPU_CTRL_REG2 .eq $0779
                   NumberOfPlayers .eq     $077a
                   IntervalTimerControl .eq $077f
                   Timers          .eq     $0780  {addr/36}
                   SelectTimer     .eq     $0780
                   PlayerAnimTimer .eq     $0781
                   JumpSwimTimer   .eq     $0782
                   RunningTimer    .eq     $0783
                   BlockBounceTimer .eq    $0784
                   SideCollisionTimer .eq  $0785
                   JumpspringTimer .eq     $0786
                   GameTimerCtrlTimer .eq  $0787
                   ClimbSlideTimer .eq     $0789
                   EnemyFrameTimer .eq     $078a
                   FrenzyEnemyTimer .eq    $078f
                   BowserFireBreathTimer .eq $0790
                   StompTimer      .eq     $0791
                   AirBubbleTimer  .eq     $0792
                   ScrollIntervalTimer .eq $0795
                   EnemyIntervalTimer .eq  $0796
                   BrickCoinTimer  .eq     $079d
                   InjuryTimer     .eq     $079e
                   StarInvincibleTimer .eq $079f
                   ScreenTimer     .eq     $07a0
                   WorldEndTimer   .eq     $07a1
                   DemoTimer       .eq     $07a2
                   PseudoRandomBitReg .eq  $07a7  {addr/3}
                   SoundMemory     .eq     $07b0  {addr/32}
                   MusicOffset_Noise .eq   $07b0
                   EventMusicBuffer .eq    $07b1
                   PauseSoundBuffer .eq    $07b2
                   Squ2_NoteLenBuffer .eq  $07b3
                   Squ2_NoteLenCounter .eq $07b4
                   Squ2_EnvelopeDataCtrl .eq $07b5
                   Squ1_NoteLenCounter .eq $07b6
                   Squ1_EnvelopeDataCtrl .eq $07b7
                   Tri_NoteLenBuffer .eq   $07b8
                   Tri_NoteLenCounter .eq  $07b9
                   Noise_BeatLenCounter .eq $07ba
                   Squ1_SfxLenCounter .eq  $07bb
                   Squ2_SfxLenCounter .eq  $07bd
                   Sfx_SecondaryCounter .eq $07be
                   Noise_SfxLenCounter .eq $07bf
                   DAC_Counter     .eq     $07c0
                   NoiseDataLoopbackOfs .eq $07c1
                   NoteLengthTblAdder .eq  $07c4
                   AreaMusicBuffer_Alt .eq $07c5
                   PauseModeFlag   .eq     $07c6
                   GroundMusicHeaderOfs .eq $07c7
                   AltRegContentFlag .eq   $07ca
                   WarmBootOffset  .eq     $07d6
                   TopScoreDisplay .eq     $07d7  {addr/6}
                   ScoreAndCoinDisplay .eq $07dd
                   GameTimerDisplay .eq    $07f8  {addr/3}
                   WorldSelectEnableFlag .eq $07fc
                   ContinueWorld   .eq     $07fd
                   ColdBootOffset  .eq     $07fe
                   WarmBootValidation .eq  $07ff
                   PPUCTRL         .eq     $2000                   ;W VPHB SINN  various
                   PPUMASK         .eq     $2001                   ;W BGRs bMmG  various
                   PPUSTATUS       .eq     $2002                   ;R VSO- ----  various; read resets $2005/2006
                   OAMADDR         .eq     $2003                   ;W OAM read/write address
                   PPUSCROLL       .eq     $2005                   ;WW fine scroll position (two writes: X,Y)
                   PPUADDR         .eq     $2006                   ;WW PPU read/write address (two writes: MSB, LSB)
                   PPUDATA         .eq     $2007                   ;RW PPU data read/write
                   SQ1_VOL         .eq     $4000                   ;DDLC VVVV
                   SQ1_SWEEP       .eq     $4001                   ;EPPP NSSS
                   SQ1_LO          .eq     $4002                   ;TTTT TTTT
                   SQ1_HI          .eq     $4003                   ;LLLL LTTT
                   SQ2_VOL         .eq     $4004                   ;DDLC VVVV
                   SQ2_SWEEP       .eq     $4005                   ;EPPP NSSS
                   SQ2_LO          .eq     $4006                   ;TTTT TTTT
                   TRI_LINEAR      .eq     $4008                   ;CRRR RRRR
                   NOISE_VOL       .eq     $400c                   ;--LC VVVV
                   NOISE_LO        .eq     $400e                   ;L--- PPPP
                   NOISE_HI        .eq     $400f                   ;LLLL L---
                   DMC_RAW         .eq     $4011                   ;-DDD DDDD
                   OAMDMA          .eq     $4014                   ;AAAA AAAA  OAM DMA high address
                   SND_CHN         .eq     $4015                   ;W:---D NT21 R:IF-D NT21
                   JOY1            .eq     $4016                   ;joystick 1 data (R) and joystick strobe (W)
                   JOY2            .eq     $4017                   ;joystick 2 data (R) and frame counter (W)

                                   .org    $8000
                   ; 
                   ; iNES file header, for use by emulators.
                   ; (See https://wiki.nesdev.com/w/index.php/INES )
                   ; 
8000: 4e 45 53                     .str    ‘NES’
8003: 1a                           .dd1    $1a                     ;Ctrl+Z
8004: 02                           .dd1    $02                     ;PRG ROM is 2 x 8KB
8005: 01                           .dd1    $01                     ;CHR ROM is 1 x 8KB
8006: 01                           .dd1    %00000001               ;flags 6
8007: 00                           .dd1    %00000000               ;flags 7
8008: 00                           .dd1    %00000000               ;flags 8
8009: 00                           .dd1    %00000000               ;flags 9
800a: 00                           .dd1    %00000000               ;flags 10
800b: 00 00 00 00+                 .bulk   $00,$00,$00,$00,$00     ;padding

                                   .org    $8000
                   ; 
                   ; Start of main program.
                   ; 
                   ; The RESET vector points here.
                   ; 
8000: 78           Start           sei                             ;pretty standard 6502 type init here
8001: d8                           cld
8002: a9 10                        lda     #%00010000              ;init PPU control register 1
8004: 8d 00 20                     sta     PPUCTRL
8007: a2 ff                        ldx     #$ff                    ;reset stack pointer
8009: 9a                           txs
800a: ad 02 20     VBlank1         lda     PPUSTATUS               ;wait two frames
800d: 10 fb                        bpl     VBlank1
800f: ad 02 20     VBlank2         lda     PPUSTATUS
8012: 10 fb                        bpl     VBlank2
8014: a0 fe                        ldy     #<ColdBootOffset        ;load default cold boot pointer
8016: a2 05                        ldx     #$05                    ;this is where we check for a warm boot
8018: bd d7 07     WBootCheck      lda     TopScoreDisplay,x       ;check each score digit in the top score
801b: c9 0a                        cmp     #10                     ;to see if we have a valid digit
801d: b0 0c                        bcs     ColdBoot                ;if not, give up and proceed with cold boot
801f: ca                           dex
8020: 10 f6                        bpl     WBootCheck
8022: ad ff 07                     lda     WarmBootValidation      ;second checkpoint, check to see if
8025: c9 a5                        cmp     #$a5                    ; another location has a specific value
8027: d0 02                        bne     ColdBoot
8029: a0 d6                        ldy     #<WarmBootOffset        ;if passed both, load warm boot pointer
802b: 20 cc 90     ColdBoot        jsr     InitializeMemory        ;clear memory using pointer in Y
802e: 8d 11 40                     sta     DMC_RAW                 ;reset delta counter load register
8031: 8d 70 07                     sta     OperMode                ;reset primary mode of operation
8034: a9 a5                        lda     #$a5                    ;set warm boot flag
8036: 8d ff 07                     sta     WarmBootValidation
8039: 8d a7 07                     sta     PseudoRandomBitReg      ;set seed for pseudorandom register
803c: a9 0f                        lda     #%00001111
803e: 8d 15 40                     sta     SND_CHN                 ;enable all sound channels except dmc
8041: a9 06                        lda     #%00000110
8043: 8d 01 20                     sta     PPUMASK                 ;turn off clipping for OAM and background
8046: 20 20 82                     jsr     MoveAllSpritesOffscreen
8049: 20 19 8e                     jsr     InitializeNameTables    ;initialize both name tables
804c: ee 74 07                     inc     DisableScreenFlag       ;set flag to disable screen output
804f: ad 78 07                     lda     Mirror_PPU_CTRL_REG1
8052: 09 80                        ora     #%10000000              ;enable NMIs
8054: 20 ed 8e                     jsr     WritePPUReg1
8057: 4c 57 80     EndlessLoop     jmp     EndlessLoop             ;endless loop, need I say more?

                   ; -----------------------------------------------------------------------------
                   ; $00 - vram buffer address table low, also used for pseudorandom bit
                   ; $01 - vram buffer address table high
                   VRAM_AddrTable_Low
805a: 01                           .dd1    <VRAM_Buffer1
805b: a4                           .dd1    <WaterPaletteData
805c: c8                           .dd1    <GroundPaletteData
805d: ec                           .dd1    <UndergroundPaletteData
805e: 10                           .dd1    <CastlePaletteData
805f: 00                           .dd1    <VRAM_Buffer1_Offset
8060: 41                           .dd1    <VRAM_Buffer2
8061: 41                           .dd1    <VRAM_Buffer2
8062: 4c                           .dd1    <BowserPaletteData
8063: 34                           .dd1    <DaySnowPaletteData
8064: 3c                           .dd1    <NightSnowPaletteData
8065: 44                           .dd1    <MushroomPaletteData
8066: 54                           .dd1    <MarioThanksMessage
8067: 68                           .dd1    <LuigiThanksMessage
8068: 7c                           .dd1    <MushroomRetainerSaved
8069: a8                           .dd1    <PrincessSaved1
806a: bf                           .dd1    <PrincessSaved2
806b: de                           .dd1    <WorldSelectMessage1
806c: ef                           .dd1    <WorldSelectMessage2
                   VRAM_AddrTable_High
806d: 03                           .dd1    >VRAM_Buffer1
806e: 8c                           .dd1    >WaterPaletteData
806f: 8c                           .dd1    >GroundPaletteData
8070: 8c                           .dd1    >UndergroundPaletteData
8071: 8d                           .dd1    >CastlePaletteData
8072: 03                           .dd1    >VRAM_Buffer1_Offset
8073: 03                           .dd1    >VRAM_Buffer2
8074: 03                           .dd1    >VRAM_Buffer2
8075: 8d                           .dd1    >BowserPaletteData
8076: 8d                           .dd1    >DaySnowPaletteData
8077: 8d                           .dd1    >NightSnowPaletteData
8078: 8d                           .dd1    >MushroomPaletteData
8079: 8d                           .dd1    >MarioThanksMessage
807a: 8d                           .dd1    >LuigiThanksMessage
807b: 8d                           .dd1    >MushroomRetainerSaved
807c: 8d                           .dd1    >PrincessSaved1
807d: 8d                           .dd1    >PrincessSaved2
807e: 8d                           .dd1    >WorldSelectMessage1
807f: 8d                           .dd1    >WorldSelectMessage2
                   VRAM_Buffer_Offset
8080: 00                           .dd1    <VRAM_Buffer1_Offset
8081: 40                           .dd1    <VRAM_Buffer2_Offset

                   NonMaskableInterrupt
8082: ad 78 07                     lda     Mirror_PPU_CTRL_REG1    ;disable NMIs in mirror reg
8085: 29 7f                        and     #%01111111              ;save all other bits
8087: 8d 78 07                     sta     Mirror_PPU_CTRL_REG1
808a: 29 7e                        and     #%01111110              ;alter name table address to be $2800
808c: 8d 00 20                     sta     PPUCTRL                 ;(essentially $2000) but save other bits
808f: ad 79 07                     lda     Mirror_PPU_CTRL_REG2    ;disable OAM and background display by default
8092: 29 e6                        and     #%11100110
8094: ac 74 07                     ldy     DisableScreenFlag       ;get screen disable flag
8097: d0 05                        bne     ScreenOff               ;if set, used bits as-is
8099: ad 79 07                     lda     Mirror_PPU_CTRL_REG2    ;otherwise reenable bits and save them
809c: 09 1e                        ora     #%00011110
809e: 8d 79 07     ScreenOff       sta     Mirror_PPU_CTRL_REG2    ;save bits for later but not in register at the moment
80a1: 29 e7                        and     #%11100111              ;disable screen for now
80a3: 8d 01 20                     sta     PPUMASK
80a6: ae 02 20                     ldx     PPUSTATUS               ;reset flip-flop and reset scroll registers to zero
80a9: a9 00                        lda     #$00
80ab: 20 e6 8e                     jsr     InitScroll
80ae: 8d 03 20                     sta     OAMADDR                 ;reset spr-ram address register
80b1: a9 02                        lda     #$02                    ;perform spr-ram DMA access on $0200-$02ff
80b3: 8d 14 40                     sta     OAMDMA
80b6: ae 73 07                     ldx     VRAM_Buffer_AddrCtrl    ;load control for pointer to buffer contents
80b9: bd 5a 80                     lda     VRAM_AddrTable_Low,x    ;set indirect at $00 to pointer
80bc: 85 00                        sta     $00
80be: bd 6d 80                     lda     VRAM_AddrTable_High,x
80c1: 85 01                        sta     $01
80c3: 20 dd 8e                     jsr     UpdateScreen            ;update screen with buffer contents
80c6: a0 00                        ldy     #$00
80c8: ae 73 07                     ldx     VRAM_Buffer_AddrCtrl    ;check for usage of $0341
80cb: e0 06                        cpx     #$06
80cd: d0 01                        bne     InitBuffer
80cf: c8                           iny                             ;get offset based on usage
80d0: be 80 80     InitBuffer      ldx     VRAM_Buffer_Offset,y
80d3: a9 00                        lda     #$00                    ;clear buffer header at last location
80d5: 9d 00 03                     sta     VRAM_Buffer1_Offset,x
80d8: 9d 01 03                     sta     VRAM_Buffer1,x
80db: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ;reinit address control to $0301
80de: ad 79 07                     lda     Mirror_PPU_CTRL_REG2    ;copy mirror of $2001 to register
80e1: 8d 01 20                     sta     PPUMASK
80e4: 20 d0 f2                     jsr     SoundEngine             ;play sound
80e7: 20 5c 8e                     jsr     ReadJoypads             ;read joypads
80ea: 20 82 81                     jsr     PauseRoutine            ;handle pause
80ed: 20 97 8f                     jsr     UpdateTopScore
80f0: ad 76 07                     lda     GamePauseStatus         ;check for pause status
80f3: 4a                           lsr     A
80f4: b0 25                        bcs     PauseSkip
80f6: ad 47 07                     lda     TimerControl            ;if master timer control not set, decrement
80f9: f0 05                        beq     DecTimers               ;all frame and interval timers
80fb: ce 47 07                     dec     TimerControl
80fe: d0 19                        bne     NoDecTimers
8100: a2 14        DecTimers       ldx     #$14                    ;load end offset for end of frame timers
8102: ce 7f 07                     dec     IntervalTimerControl    ;decrement interval timer control,
8105: 10 07                        bpl     DecTimersLoop           ; if not expired, only frame timers will decrement
8107: a9 14                        lda     #$14
8109: 8d 7f 07                     sta     IntervalTimerControl    ;if control for interval timers expired,
810c: a2 23                        ldx     #$23                    ; interval timers will decrement along with frame timers
810e: bd 80 07     DecTimersLoop   lda     SelectTimer,x           ;check current timer
8111: f0 03                        beq     SkipExpTimer            ;if current timer expired, branch to skip,
8113: de 80 07                     dec     SelectTimer,x           ; otherwise decrement the current timer
8116: ca           SkipExpTimer    dex                             ;move onto next timer
8117: 10 f5                        bpl     DecTimersLoop           ;do this until all timers are dealt with
8119: e6 09        NoDecTimers     inc     FrameCounter            ;increment frame counter
811b: a2 00        PauseSkip       ldx     #$00
811d: a0 07                        ldy     #$07
811f: ad a7 07                     lda     PseudoRandomBitReg      ;get first memory locaion of LSFR bytes
8122: 29 02                        and     #%00000010              ;mask out all but d1
8124: 85 00                        sta     $00                     ;save here
8126: ad a8 07                     lda     PseudoRandomBitReg+1    ;get second memory location
8129: 29 02                        and     #%00000010              ;mask out all but d1
812b: 45 00                        eor     $00                     ;perform exclusive-OR on d1 from first and second bytes
812d: 18                           clc                             ;if neither or both are set, carry will be clear
812e: f0 01                        beq     RotPRandomBit
8130: 38                           sec                             ;if one or the other is set, carry will be set
8131: 7e a7 07     RotPRandomBit   ror     PseudoRandomBitReg,x    ;rotate carry into d7, and rotate last bit into carry
8134: e8                           inx                             ;increment to next byte
8135: 88                           dey                             ;decrement for loop
8136: d0 f9                        bne     RotPRandomBit
8138: ad 22 07                     lda     Sprite0HitDetectFlag    ;check for flag here
813b: f0 1f                        beq     SkipSprite0
813d: ad 02 20     Sprite0Clr      lda     PPUSTATUS               ;wait for sprite 0 flag to clear, which will
8140: 29 40                        and     #%01000000              ; not happen until vblank has ended
8142: d0 f9                        bne     Sprite0Clr
8144: ad 76 07                     lda     GamePauseStatus         ;if in pause mode, do not bother with sprites at all
8147: 4a                           lsr     A
8148: b0 06                        bcs     Sprite0Hit
814a: 20 23 82                     jsr     MoveSpritesOffscreen
814d: 20 c6 81                     jsr     SpriteShuffler
8150: ad 02 20     Sprite0Hit      lda     PPUSTATUS               ;do sprite #0 hit detection
8153: 29 40                        and     #%01000000
8155: f0 f9                        beq     Sprite0Hit
8157: a0 14                        ldy     #$14                    ;small delay, to wait until we hit orizontal blank time
8159: 88           HBlankDelay     dey
815a: d0 fd                        bne     HBlankDelay
815c: ad 3f 07     SkipSprite0     lda     HorizontalScroll        ;set scroll registers from variables
815f: 8d 05 20                     sta     PPUSCROLL
8162: ad 40 07                     lda     VerticalScroll
8165: 8d 05 20                     sta     PPUSCROLL
8168: ad 78 07                     lda     Mirror_PPU_CTRL_REG1    ;load saved mirror of $2000
816b: 48                           pha
816c: 8d 00 20                     sta     PPUCTRL
816f: ad 76 07                     lda     GamePauseStatus         ;if in pause mode, do not perform operation mode stuff
8172: 4a                           lsr     A
8173: b0 03                        bcs     SkipMainOper
8175: 20 12 82                     jsr     OperModeExecutionTree   ;otherwise do one of many, many possible subroutines
8178: ad 02 20     SkipMainOper    lda     PPUSTATUS               ;reset flip-flip
817b: 68                           pla
817c: 09 80                        ora     #%10000000              ;reactivate NMIs
817e: 8d 00 20                     sta     PPUCTRL
8181: 40                           rti                             ;we are done until the next frame!

                   ; -----------------------------------------------------------------------------
8182: ad 70 07     PauseRoutine    lda     OperMode                ;are we in victory mode?
8185: c9 02                        cmp     #VictoryModeValue       ;if so, go ahead
8187: f0 0b                        beq     ChkPauseTimer
8189: c9 01                        cmp     #GameModeValue          ;are we in game mode?
818b: d0 38                        bne     ExitPause               ;if not, leave
818d: ad 72 07                     lda     OperMode_Task           ;if we are in game mode, are we running game engine?
8190: c9 03                        cmp     #$03
8192: d0 31                        bne     ExitPause               ;if not, leave
8194: ad 77 07     ChkPauseTimer   lda     GamePauseTimer          ;check if pause timer is still counting down
8197: f0 04                        beq     ChkStart
8199: ce 77 07                     dec     GamePauseTimer          ;if so, decrement and leave
819c: 60                           rts

819d: ad fc 06     ChkStart        lda     SavedJoypad1Bits        ;check to see if start is pressed
81a0: 29 10                        and     #Start_Button           ;on controller 1
81a2: f0 19                        beq     ClrPauseTimer
81a4: ad 76 07                     lda     GamePauseStatus         ;check to see if timer flag is set
81a7: 29 80                        and     #%10000000              ;and if so, do not reset timer (residual,
81a9: d0 1a                        bne     ExitPause               ; joypad reading routine makes this unnecessary)
81ab: a9 2b                        lda     #$2b                    ;set pause timer
81ad: 8d 77 07                     sta     GamePauseTimer
81b0: ad 76 07                     lda     GamePauseStatus
81b3: a8                           tay
81b4: c8                           iny                             ;set pause sfx queue for next pause mode
81b5: 84 fa                        sty     PauseSoundQueue
81b7: 49 01                        eor     #%00000001              ;invert d0 and set d7
81b9: 09 80                        ora     #%10000000
81bb: d0 05                        bne     SetPause                ;unconditional branch

81bd: ad 76 07     ClrPauseTimer   lda     GamePauseStatus         ;clear timer flag if timer is at zero and start button
81c0: 29 7f                        and     #%01111111              ; is not pressed
81c2: 8d 76 07     SetPause        sta     GamePauseStatus
81c5: 60           ExitPause       rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used for preset value
81c6: ac 4e 07     SpriteShuffler  ldy     AreaType                ;load level type, likely residual code
81c9: a9 28                        lda     #$28                    ;load preset value which will put it at
81cb: 85 00                        sta     $00                     ; sprite #10
81cd: a2 0e                        ldx     #$0e                    ;start at the end of OAM data offsets
81cf: bd e4 06     ShuffleLoop     lda     SprDataOffset,x         ;check for offset value against
81d2: c5 00                        cmp     $00                     ; the preset value
81d4: 90 0f                        bcc     NextSprOffset           ;if less, skip this part
81d6: ac e0 06                     ldy     SprShuffleAmtOffset     ;get current offset to preset value we want to add
81d9: 18                           clc
81da: 79 e1 06                     adc     SprShuffleAmt,y         ;get shuffle amount, add to current sprite offset
81dd: 90 03                        bcc     StrSprOffset            ;if not exceeded $ff, skip second add
81df: 18                           clc
81e0: 65 00                        adc     $00                     ;otherwise add preset value $28 to offset
81e2: 9d e4 06     StrSprOffset    sta     SprDataOffset,x         ;store new offset here or old one if branched to here
81e5: ca           NextSprOffset   dex                             ;move backwards to next one
81e6: 10 e7                        bpl     ShuffleLoop
81e8: ae e0 06                     ldx     SprShuffleAmtOffset     ;load offset
81eb: e8                           inx
81ec: e0 03                        cpx     #$03                    ;check if offset + 1 goes to 3
81ee: d0 02                        bne     SetAmtOffset            ;if offset + 1 not 3, store
81f0: a2 00                        ldx     #$00                    ;otherwise, init to 0
81f2: 8e e0 06     SetAmtOffset    stx     SprShuffleAmtOffset
81f5: a2 08                        ldx     #$08                    ;load offsets for values and storage
81f7: a0 02                        ldy     #$02
81f9: b9 e9 06     SetMiscOffset   lda     SprDataOffset+5,y       ;load one of three OAM data offsets
81fc: 9d f1 06                     sta     Misc_SprDataOffset-2,x  ;store first one unmodified, but
81ff: 18                           clc                             ; add eight to the second and eight
8200: 69 08                        adc     #$08                    ; more to the third one
8202: 9d f2 06                     sta     Misc_SprDataOffset-1,x  ;note that due to the way X is set up,
8205: 18                           clc                             ; this code loads into the misc sprite offsets
8206: 69 08                        adc     #$08
8208: 9d f3 06                     sta     Misc_SprDataOffset,x
820b: ca                           dex
820c: ca                           dex
820d: ca                           dex
820e: 88                           dey
820f: 10 e8                        bpl     SetMiscOffset           ;do this until all misc spr offsets are loaded
8211: 60                           rts

                   ; -----------------------------------------------------------------------------
                   OperModeExecutionTree
8212: ad 70 07                     lda     OperMode
8215: 20 04 8e                     jsr     JumpEngine

8218: 31 82                        .dd2    TitleScreenMode
821a: dc ae                        .dd2    GameMode
821c: 8b 83                        .dd2    VictoryMode
821e: 18 92                        .dd2    GameOverMode

                   ; -----------------------------------------------------------------------------
                   MoveAllSpritesOffscreen
8220: a0 00                        ldy     #$00                    ;this routine moves all sprites off the screen
8222: 2c                           bit ▼   Fireball_BoundBoxCtrl   ;BIT instruction opcode
                   MoveSpritesOffscreen
8223: a0 04                        ldy     #$04                    ;this routine moves all but sprite 0
8225: a9 f8                        lda     #$f8                    ;off the screen
8227: 99 00 02     SprInitLoop     sta     Sprite_Y_Position,y     ;write 248 into OAM data's Y coordinate
822a: c8                           iny                             ;which will move it off the screen
822b: c8                           iny
822c: c8                           iny
822d: c8                           iny
822e: d0 f7                        bne     SprInitLoop
8230: 60                           rts

                   ; -----------------------------------------------------------------------------
8231: ad 72 07     TitleScreenMode lda     OperMode_Task
8234: 20 04 8e                     jsr     JumpEngine

8237: cf 8f                        .dd2    InitializeGame
8239: 67 85                        .dd2    ScreenRoutines
823b: 61 90                        .dd2    PrimaryGameSetup
823d: 45 82                        .dd2    GameMenuRoutine
                   ; -----------------------------------------------------------------------------
                   WSelectBufferTemplate
823f: 04 20 73 01+                 .bulk   $04,$20,$73,$01,$00,$00

8245: a0 00        GameMenuRoutine ldy     #$00
8247: ad fc 06                     lda     SavedJoypad1Bits        ;check to see if either player pressed
824a: 0d fd 06                     ora     SavedJoypad2Bits        ; only the start button (either joypad)
824d: c9 10                        cmp     #Start_Button
824f: f0 04                        beq     StartGame
8251: c9 90                        cmp     #$90                    ;||check to see if A + start was pressed
8253: d0 03                        bne     ChkSelect               ;if not, branch to check select button
8255: 4c d8 82     StartGame       jmp     ChkContinue             ;if either start or A + start, execute here

8258: c9 20        ChkSelect       cmp     #Select_Button          ;check to see if the select button was pressed
825a: f0 1a                        beq     SelectBLogic            ;if so, branch reset demo timer
825c: ae a2 07                     ldx     DemoTimer               ;otherwise check demo timer
825f: d0 0b                        bne     ChkWorldSel             ;if demo timer not expired, branch to check world selection
8261: 8d 80 07                     sta     SelectTimer             ;set controller bits here if running demo
8264: 20 6b 83                     jsr     DemoEngine              ;run through the demo actions
8267: b0 60                        bcs     ResetTitle              ;if carry flag set, demo over, thus branch
8269: 4c c0 82                     jmp     RunDemo                 ;otherwise, run game engine for demo

826c: ae fc 07     ChkWorldSel     ldx     WorldSelectEnableFlag   ;check to see if world selection has been enabled
826f: f0 4a                        beq     NullJoypad
8271: c9 40                        cmp     #B_Button               ;if so, check to see if the B button was pressed
8273: d0 46                        bne     NullJoypad
8275: c8                           iny                             ;if so, increment Y and execute same code as select
8276: ad a2 07     SelectBLogic    lda     DemoTimer               ;if select or B pressed, check demo timer one last time
8279: f0 4e                        beq     ResetTitle              ;if demo timer expired, branch to reset title screen mode
827b: a9 18                        lda     #$18                    ;otherwise reset demo timer
827d: 8d a2 07                     sta     DemoTimer
8280: ad 80 07                     lda     SelectTimer             ;check select/B button timer
8283: d0 36                        bne     NullJoypad              ;if not expired, branch
8285: a9 10                        lda     #$10                    ;otherwise reset select button timer
8287: 8d 80 07                     sta     SelectTimer
828a: c0 01                        cpy     #$01                    ;was the B button pressed earlier?  if so, branch
828c: f0 0e                        beq     IncWorldSel             ;note this will not be run if world selection is disabled
828e: ad 7a 07                     lda     NumberOfPlayers         ;if no, must have been the select button, therefore
8291: 49 01                        eor     #%00000001              ; change number of players and draw icon accordingly
8293: 8d 7a 07                     sta     NumberOfPlayers
8296: 20 25 83                     jsr     DrawMushroomIcon
8299: 4c bb 82                     jmp     NullJoypad

829c: ae 6b 07     IncWorldSel     ldx     WorldSelectNumber       ;increment world select number
829f: e8                           inx
82a0: 8a                           txa
82a1: 29 07                        and     #%00000111              ;mask out higher bits
82a3: 8d 6b 07                     sta     WorldSelectNumber       ;store as current world select number
82a6: 20 0e 83                     jsr     GoContinue
82a9: bd 3f 82     UpdateShroom    lda     WSelectBufferTemplate,x ;write template for world select in vram buffer
82ac: 9d 00 03                     sta     VRAM_Buffer1-1,x        ;do this until all bytes are written
82af: e8                           inx
82b0: e0 06                        cpx     #$06
82b2: 30 f5                        bmi     UpdateShroom
82b4: ac 5f 07                     ldy     WorldNumber             ;get world number from variable and increment for
82b7: c8                           iny                             ; proper display, and put in blank byte before
82b8: 8c 04 03                     sty     VRAM_Buffer1+3          ; null terminator
82bb: a9 00        NullJoypad      lda     #$00                    ;clear joypad bits for player 1
82bd: 8d fc 06                     sta     SavedJoypad1Bits
82c0: 20 ea ae     RunDemo         jsr     GameCoreRoutine         ;run game engine
82c3: a5 0e                        lda     GameEngineSubroutine    ;check to see if we're running lose life routine
82c5: c9 06                        cmp     #$06
82c7: d0 44                        bne     ExitMenu                ;if not, do not do all the resetting below
82c9: a9 00        ResetTitle      lda     #$00                    ;reset game modes, disable
82cb: 8d 70 07                     sta     OperMode                ;sprite 0 check and disable
82ce: 8d 72 07                     sta     OperMode_Task           ;screen output
82d1: 8d 22 07                     sta     Sprite0HitDetectFlag
82d4: ee 74 07                     inc     DisableScreenFlag
82d7: 60                           rts

82d8: ac a2 07     ChkContinue     ldy     DemoTimer               ;if timer for demo has expired, reset modes
82db: f0 ec                        beq     ResetTitle
82dd: 0a                           asl     A                       ;check to see if A button was also pushed
82de: 90 06                        bcc     StartWorld1             ;if not, don't load continue function's world number
82e0: ad fd 07                     lda     ContinueWorld           ;load previously saved world number for secret
82e3: 20 0e 83                     jsr     GoContinue              ;continue function when pressing A + start
82e6: 20 03 9c     StartWorld1     jsr     LoadAreaPointer
82e9: ee 5d 07                     inc     Hidden1UpFlag           ;set 1-up box flag for both players
82ec: ee 64 07                     inc     OffScr_Hidden1UpFlag
82ef: ee 57 07                     inc     FetchNewGameTimerFlag   ;set fetch new game timer flag
82f2: ee 70 07                     inc     OperMode                ;set next game mode
82f5: ad fc 07                     lda     WorldSelectEnableFlag   ;if world select flag is on, then primary
82f8: 8d 6a 07                     sta     PrimaryHardMode         ; hard mode must be on as well
82fb: a9 00                        lda     #$00
82fd: 8d 72 07                     sta     OperMode_Task           ;set game mode here, and clear demo timer
8300: 8d a2 07                     sta     DemoTimer
8303: a2 17                        ldx     #$17
8305: a9 00                        lda     #$00
8307: 9d dd 07     InitScores      sta     ScoreAndCoinDisplay,x   ;clear player scores and coin displays
830a: ca                           dex
830b: 10 fa                        bpl     InitScores
830d: 60           ExitMenu        rts

830e: 8d 5f 07     GoContinue      sta     WorldNumber             ;start both players at the first area
8311: 8d 66 07                     sta     OffScr_WorldNumber      ; of the previously saved world number
8314: a2 00                        ldx     #$00                    ;note that on power-up using this function
8316: 8e 60 07                     stx     AreaNumber              ; will make no difference
8319: 8e 67 07                     stx     OffScr_AreaNumber
831c: 60                           rts

                   ; -----------------------------------------------------------------------------
                   MushroomIconData
831d: 07 22 49 83+                 .bulk   $07,$22,$49,$83,$ce,$24,$24,$00

                   DrawMushroomIcon
8325: a0 07                        ldy     #$07                    ;read eight bytes to be read by transfer routine
8327: b9 1d 83     IconDataRead    lda     MushroomIconData,y      ;note that the default position is set for a
832a: 99 00 03                     sta     VRAM_Buffer1-1,y        ; 1-player game
832d: 88                           dey
832e: 10 f7                        bpl     IconDataRead
8330: ad 7a 07                     lda     NumberOfPlayers         ;check number of players
8333: f0 0a                        beq     ExitIcon                ;if set to 1-player game, we're done
8335: a9 24                        lda     #$24                    ;otherwise, load blank tile in 1-player position
8337: 8d 04 03                     sta     VRAM_Buffer1+3
833a: a9 ce                        lda     #$ce                    ;then load shroom icon tile in 2-player position
833c: 8d 06 03                     sta     VRAM_Buffer1+5
833f: 60           ExitIcon        rts

                   ; -----------------------------------------------------------------------------
8340: 01 80 02 81+ DemoActionData  .bulk   $01,$80,$02,$81,$41,$80,$01,$42,$c2,$02,$80,$41,$c1,$41,$c1,$01
                                    +      $c1,$01,$02,$80,$00
8355: 9b 10 18 05+ DemoTimingData  .bulk   $9b,$10,$18,$05,$2c,$20,$24,$15,$5a,$10,$20,$28,$30,$20,$10,$80
                                    +      $20,$30,$30,$01,$ff,$00

836b: ae 17 07     DemoEngine      ldx     DemoAction              ;load current demo action
836e: ad 18 07                     lda     DemoActionTimer         ;load current action timer
8371: d0 0d                        bne     DoAction                ;if timer still counting down, skip
8373: e8                           inx
8374: ee 17 07                     inc     DemoAction              ;if expired, increment action, X, and
8377: 38                           sec                             ; set carry by default for demo over
8378: bd 54 83                     lda     DemoTimingData-1,x      ;get next timer
837b: 8d 18 07                     sta     DemoActionTimer         ;store as current timer
837e: f0 0a                        beq     DemoOver                ;if timer already at zero, skip
8380: bd 3f 83     DoAction        lda     DemoActionData-1,x      ;get and perform action (current or next)
8383: 8d fc 06                     sta     SavedJoypad1Bits
8386: ce 18 07                     dec     DemoActionTimer         ;decrement action timer
8389: 18                           clc                             ;clear carry if demo still going
838a: 60           DemoOver        rts

                   ; -----------------------------------------------------------------------------
838b: 20 a0 83     VictoryMode     jsr     VictoryModeSubroutines  ;run victory mode subroutines
838e: ad 72 07                     lda     OperMode_Task           ;get current task of victory mode
8391: f0 07                        beq     AutoPlayer              ;if on bridge collapse, skip enemy processing
8393: a2 00                        ldx     #$00
8395: 86 08                        stx     ObjectOffset            ;otherwise reset enemy object offset
8397: 20 47 c0                     jsr     EnemiesAndLoopsCore     ; and run enemy code
839a: 20 2a f1     AutoPlayer      jsr     RelativePlayerPosition  ;get player's relative coordinates
839d: 4c e9 ee                     jmp     PlayerGfxHandler        ;draw the player, then leave

                   VictoryModeSubroutines
83a0: ad 72 07                     lda     OperMode_Task
83a3: 20 04 8e                     jsr     JumpEngine

83a6: ec cf                        .dd2    BridgeCollapse
83a8: b0 83                        .dd2    SetupVictoryMode
83aa: bd 83                        .dd2    PlayerVictoryWalk
83ac: f6 83                        .dd2    PrintVictoryMessages
83ae: 61 84                        .dd2    PlayerEndWorld

                   ; -----------------------------------------------------------------------------
                   SetupVictoryMode
83b0: ae 1b 07                     ldx     ScreenRight_PageLoc     ;get page location of right side of screen
83b3: e8                           inx                             ;increment to next page
83b4: 86 34                        stx     DestinationPageLoc      ;store here
83b6: a9 08                        lda     #EndOfCastleMusic
83b8: 85 fc                        sta     EventMusicQueue         ;play win castle music
83ba: 4c 4e 87                     jmp     IncModeTask_B           ;jump to set next major task in victory mode

                   ; -----------------------------------------------------------------------------
                   PlayerVictoryWalk
83bd: a0 00                        ldy     #$00                    ;set value here to not walk player by default
83bf: 84 35                        sty     VictoryWalkControl
83c1: a5 6d                        lda     Player_PageLoc          ;get player's page location
83c3: c5 34                        cmp     DestinationPageLoc      ;compare with destination page location
83c5: d0 06                        bne     PerformWalk             ;if page locations don't match, branch
83c7: a5 86                        lda     Player_X_Position       ;otherwise get player's horizontal position
83c9: c9 60                        cmp     #$60                    ;compare with preset horizontal position
83cb: b0 03                        bcs     DontWalk                ;if still on other page, branch ahead
83cd: e6 35        PerformWalk     inc     VictoryWalkControl      ;otherwise increment value and Y
83cf: c8                           iny                             ;note Y will be used to walk the player
83d0: 98           DontWalk        tya                             ;put contents of Y in A and
83d1: 20 e6 b0                     jsr     AutoControlPlayer       ; use A to mvoe player to the right or not
83d4: ad 1a 07                     lda     ScreenLeft_PageLoc      ;check page location of left side of screen
83d7: c5 34                        cmp     DestinationPageLoc      ;against set value here
83d9: f0 16                        beq     ExitVWalk               ;branch if equal to change modes if necessary
83db: ad 68 07                     lda     ScrollFractional
83de: 18                           clc                             ;do fixed point math on fractional part of scroll
83df: 69 80                        adc     #$80
83e1: 8d 68 07                     sta     ScrollFractional        ;save fractional movement amount
83e4: a9 01                        lda     #$01                    ;set 1 pixel per frame
83e6: 69 00                        adc     #$00                    ;add carry from previous addition
83e8: a8                           tay                             ;use as scroll amount
83e9: 20 c4 af                     jsr     ScrollScreen            ;do sub to scroll the screen
83ec: 20 6f af                     jsr     UpdScrollVar            ;do another sub to update screen and scroll variables
83ef: e6 35                        inc     VictoryWalkControl      ;increment value to stay in this routine
83f1: a5 35        ExitVWalk       lda     VictoryWalkControl      ;load value set here
83f3: f0 68                        beq     IncModeTask_A           ;if zero, branch to change modes
83f5: 60                           rts                             ;otherwise leave

                   ; -----------------------------------------------------------------------------
                   PrintVictoryMessages
83f6: ad 49 07                     lda     SecondaryMsgCounter     ;load secondary message counter
83f9: d0 48                        bne     IncMsgCounter           ;if set, branch to increment message counters
83fb: ad 19 07                     lda     PrimaryMsgCounter       ;otherwise load primary message counter
83fe: f0 18                        beq     ThankPlayer             ;if set to zero, branch to print first message
8400: c9 09                        cmp     #$09                    ;if at 9 or above, branch elsewhere (this comparison
8402: b0 3f                        bcs     IncMsgCounter           ; is residual code, counter never reaches 9)
8404: ac 5f 07                     ldy     WorldNumber             ;check world number
8407: c0 07                        cpy     #World8
8409: d0 09                        bne     MRetainerMsg            ;if not at world 8, skip to next part
840b: c9 03                        cmp     #$03                    ;check primary message counter again
840d: 90 34                        bcc     IncMsgCounter           ;if not at 3 yet (world 8 only), branch to increment
840f: e9 01                        sbc     #$01                    ;otherwise subtract one
8411: 4c 18 84                     jmp     ThankPlayer             ;and skip to next part

8414: c9 02        MRetainerMsg    cmp     #$02                    ;check primary message counter
8416: 90 2b                        bcc     IncMsgCounter           ;if not at 2 yet (world 1-7 only), branch
8418: a8           ThankPlayer     tay                             ;put primary message counter into Y
8419: d0 08                        bne     SecondPartMsg           ;if counter nonzero, skip this part, do not print first message
841b: ad 53 07                     lda     CurrentPlayer           ;otherwise get player currently on the screen
841e: f0 14                        beq     EvalForMusic            ;if mario, branch
8420: c8                           iny                             ;otherwise increment Y once for luigi and
8421: d0 11                        bne     EvalForMusic            ;do an unconditional branch to the same place
8423: c8           SecondPartMsg   iny                             ;increment Y to do world 8's message
8424: ad 5f 07                     lda     WorldNumber
8427: c9 07                        cmp     #World8                 ;check world number
8429: f0 09                        beq     EvalForMusic            ;if at world 8, branch to next part
842b: 88                           dey                             ;otherwise decrement Y for world 1-7's message
842c: c0 04                        cpy     #$04                    ;if counter at 4 (world 1-7) only
842e: b0 26                        bcs     SetEndTimer             ; branch to set victory end timer
8430: c0 03                        cpy     #$03                    ;if counter at 3 (world 1-7 only)
8432: b0 0f                        bcs     IncMsgCounter           ; branch to keep counting
8434: c0 03        EvalForMusic    cpy     #$03                    ;if counter not yet at 3 (world 8 only), branch
8436: d0 04                        bne     PrintMsg                ; to print message only (note world 1-7 will only
8438: a9 04                        lda     #VictoryMusic           ; reach this code if counter = 0, and will always branch)
843a: 85 fc                        sta     EventMusicQueue         ;otherwise load victory music first (world 8 only)
843c: 98           PrintMsg        tya                             ;put primary message counter in A
843d: 18                           clc                             ;add $0c or 12 to counter thus giving an appropriate value,
843e: 69 0c                        adc     #$0c                    ; ($0c-$0d = first), ($0e = world 1-7's), ($0f-$12 = world 8's)
8440: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ;write message counter to vram address controller
8443: ad 49 07     IncMsgCounter   lda     SecondaryMsgCounter
8446: 18                           clc
8447: 69 04                        adc     #$04                    ;add four to secondary message counter
8449: 8d 49 07                     sta     SecondaryMsgCounter
844c: ad 19 07                     lda     PrimaryMsgCounter
844f: 69 00                        adc     #$00                    ;add carry to primary message counter
8451: 8d 19 07                     sta     PrimaryMsgCounter
8454: c9 07                        cmp     #$07                    ;check primary counter one more time
8456: 90 08        SetEndTimer     bcc     ExitMsgs                ;if not reached value yet, branch to leave
8458: a9 06                        lda     #$06
845a: 8d a1 07                     sta     WorldEndTimer           ;otherwise set world end timer
845d: ee 72 07     IncModeTask_A   inc     OperMode_Task           ;move onto next task in mode
8460: 60           ExitMsgs        rts                             ;leave

                   ; -----------------------------------------------------------------------------
8461: ad a1 07     PlayerEndWorld  lda     WorldEndTimer           ;check to see if world end timer expired
8464: d0 20                        bne     EndExitOne              ;branch to leave if not
8466: ac 5f 07                     ldy     WorldNumber             ;check world number
8469: c0 07                        cpy     #World8                 ;if on world 8, player is done with game,
846b: b0 1a                        bcs     EndChkBButton           ; thus branch to read controller
846d: a9 00                        lda     #$00
846f: 8d 60 07                     sta     AreaNumber              ;otherwise initialize area number used as offset
8472: 8d 5c 07                     sta     LevelNumber             ; and level number control to start at area 1
8475: 8d 72 07                     sta     OperMode_Task           ;initialize secondary mode of operation
8478: ee 5f 07                     inc     WorldNumber             ;increment world number to move onto the next world
847b: 20 03 9c                     jsr     LoadAreaPointer         ;get area address offset for the next area
847e: ee 57 07                     inc     FetchNewGameTimerFlag   ;set flag to load game timer from header
8481: a9 01                        lda     #GameModeValue
8483: 8d 70 07                     sta     OperMode                ;set mode of operation to game mode
8486: 60           EndExitOne      rts                             ;and leave

8487: ad fc 06     EndChkBButton   lda     SavedJoypad1Bits
848a: 0d fd 06                     ora     SavedJoypad2Bits        ;check to see if B button was pressed on
848d: 29 40                        and     #B_Button               ; either controller
848f: f0 0d                        beq     EndExitTwo              ;branch to leave if not
8491: a9 01                        lda     #$01                    ;otherwise set world selection flag
8493: 8d fc 07                     sta     WorldSelectEnableFlag
8496: a9 ff                        lda     #$ff                    ;remove onscreen player's lives
8498: 8d 5a 07                     sta     NumberOfLives
849b: 20 48 92                     jsr     TerminateGame           ;do sub to continue other player or end game
849e: 60           EndExitTwo      rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; 
                   ; Data is used as tiles for numbers that appear when you defeat enemies.
                   FloateyNumTileData
849f: ff ff                        .bulk   $ff,$ff                 ;dummy
84a1: f6 fb                        .bulk   $f6,$fb                 ;"100"
84a3: f7 fb                        .bulk   $f7,$fb                 ;"200"
84a5: f8 fb                        .bulk   $f8,$fb                 ;"400"
84a7: f9 fb                        .bulk   $f9,$fb                 ;"500"
84a9: fa fb                        .bulk   $fa,$fb                 ;"800"
84ab: f6 50                        .bulk   $f6,$50                 ;"1000"
84ad: f7 50                        .bulk   $f7,$50                 ;"2000"
84af: f8 50                        .bulk   $f8,$50                 ;"4000"
84b1: f9 50                        .bulk   $f9,$50                 ;"5000"
84b3: fa 50                        .bulk   $fa,$50                 ;"8000"
84b5: fd fe                        .bulk   $fd,$fe                 ;"1-UP"
                   ; 
                   ; High nybble is digit number, low nybble is number to add to the digit of the
                   ; player's score.
84b7: ff           ScoreUpdateData .dd1    $ff                     ;dummy
84b8: 41 42 44 45+                 .bulk   $41,$42,$44,$45,$48,$31,$32,$34,$35,$38,$00

                   FloateyNumbersRoutine
84c3: bd 10 01                     lda     FloateyNum_Control,x    ;load control for floatey number
84c6: f0 be                        beq     EndExitOne              ;if zero, branch to leave
84c8: c9 0b                        cmp     #$0b                    ;if less than $0b, branch
84ca: 90 05                        bcc     ChkNumTimer
84cc: a9 0b                        lda     #$0b                    ;otherwise set to $0b, thus keeping
84ce: 9d 10 01                     sta     FloateyNum_Control,x    ; it in range
84d1: a8           ChkNumTimer     tay                             ;use as Y
84d2: bd 2c 01                     lda     FloateyNum_Timer,x      ;check value here
84d5: d0 04                        bne     DecNumTimer             ;if nonzero, branch ahead
84d7: 9d 10 01                     sta     FloateyNum_Control,x    ;initialize floatey number control and leave
84da: 60                           rts

84db: de 2c 01     DecNumTimer     dec     FloateyNum_Timer,x      ;decrement value here
84de: c9 2b                        cmp     #$2b                    ;if not reached a certain point, branch
84e0: d0 1e                        bne     ChkTallEnemy
84e2: c0 0b                        cpy     #$0b                    ;check offset for $0b
84e4: d0 07                        bne     LoadNumTiles            ;branch ahead if not found
84e6: ee 5a 07                     inc     NumberOfLives           ;give player one extra life (1-up)
84e9: a9 40                        lda     #Sfx_ExtraLife
84eb: 85 fe                        sta     Square2SoundQueue       ;and play the 1-up sound
84ed: b9 b7 84     LoadNumTiles    lda     ScoreUpdateData,y       ;load point value here
84f0: 4a                           lsr     A                       ;move high nybble to low
84f1: 4a                           lsr     A
84f2: 4a                           lsr     A
84f3: 4a                           lsr     A
84f4: aa                           tax                             ;use as X offset, essentially the digit
84f5: b9 b7 84                     lda     ScoreUpdateData,y       ;load again and this time
84f8: 29 0f                        and     #%00001111              ;mask out the high nybble
84fa: 9d 34 01                     sta     DigitModifier,x         ;store as amount to add to the digit
84fd: 20 27 bc                     jsr     AddToScore              ;update the score accordingly
8500: bc e5 06     ChkTallEnemy    ldy     Enemy_SprDataOffset,x   ;get OAM data offset for enemy object
8503: b5 16                        lda     Enemy_ID,x              ;get enemy object identifier
8505: c9 12                        cmp     #Spiny
8507: f0 22                        beq     FloateyPart             ;branch if spiny
8509: c9 0d                        cmp     #PiranhaPlant
850b: f0 1e                        beq     FloateyPart             ;branch if piranha plant
850d: c9 05                        cmp     #HammerBro
850f: f0 12                        beq     GetAltOffset            ;branch elsewhere if hammer bro
8511: c9 0a                        cmp     #GreyCheepCheep
8513: f0 16                        beq     FloateyPart             ;branch if cheep-cheep of either color
8515: c9 0b                        cmp     #RedCheepCheep
8517: f0 12                        beq     FloateyPart
8519: c9 09                        cmp     #TallEnemy
851b: b0 06                        bcs     GetAltOffset            ;branch elsewhere if enemy object => $09
851d: b5 1e                        lda     Enemy_State,x
851f: c9 02                        cmp     #$02                    ;if enemy state defeated or otherwise
8521: b0 08                        bcs     FloateyPart             ;$02 or greater, branch beyond this part
8523: ae ee 03     GetAltOffset    ldx     SprDataOffset_Ctrl      ;load some kind of control bit
8526: bc ec 06                     ldy     Alt_SprDataOffset,x     ;get alternate OAM data offset
8529: a6 08                        ldx     ObjectOffset            ;get enemy object offset again
852b: bd 1e 01     FloateyPart     lda     FloateyNum_Y_Pos,x      ;get vertical coordinate for
852e: c9 18                        cmp     #$18                    ; floatey number, if coordinate in the
8530: 90 05                        bcc     SetupNumSpr             ; status bar, branch
8532: e9 01                        sbc     #$01
8534: 9d 1e 01                     sta     FloateyNum_Y_Pos,x      ;otherwise subtract one and store as new
8537: bd 1e 01     SetupNumSpr     lda     FloateyNum_Y_Pos,x      ;get vertical coordinate
853a: e9 08                        sbc     #$08                    ;subtract eight and dump into the
853c: 20 c1 e5                     jsr     DumpTwoSpr              ; left and right sprite's Y coordinates
853f: bd 17 01                     lda     FloateyNum_X_Pos,x      ;get horizontal coordinate
8542: 99 03 02                     sta     Sprite_X_Position,y     ;store into X coordinate of left sprite
8545: 18                           clc
8546: 69 08                        adc     #$08                    ;add eight pixels and store into X
8548: 99 07 02                     sta     Sprite_X_Position+4,y   ; coordinate of right sprite
854b: a9 02                        lda     #$02
854d: 99 02 02                     sta     Sprite_Attributes,y     ;set palette control in attribute bytes
8550: 99 06 02                     sta     Sprite_Attributes+4,y   ; of left and right sprites
8553: bd 10 01                     lda     FloateyNum_Control,x
8556: 0a                           asl     A                       ;multiply our floatey number control by 2
8557: aa                           tax                             ; and use as offset for look-up table
8558: bd 9f 84                     lda     FloateyNumTileData,x
855b: 99 01 02                     sta     Sprite_Tilenumber,y     ;display first half of number of points
855e: bd a0 84                     lda     FloateyNumTileData+1,x
8561: 99 05 02                     sta     Sprite_Tilenumber+4,y   ;display the second half
8564: a6 08                        ldx     ObjectOffset            ;get enemy object offset and leave
8566: 60                           rts

                   ; -----------------------------------------------------------------------------
8567: ad 3c 07     ScreenRoutines  lda     ScreenRoutineTask       ;run one of the following subroutines
856a: 20 04 8e                     jsr     JumpEngine

856d: 8b 85                        .dd2    InitScreen
856f: 9b 85                        .dd2    SetupIntermediate
8571: 52 86                        .dd2    WriteTopStatusLine
8573: 5a 86                        .dd2    WriteBottomStatusLine
8575: 93 86                        .dd2    DisplayTimeUp
8577: 9d 88                        .dd2    ResetSpritesAndScreenTimer
8579: a8 86                        .dd2    DisplayIntermediate
857b: 9d 88                        .dd2    ResetSpritesAndScreenTimer
857d: e6 86                        .dd2    AreaParserTaskControl
857f: bf 85                        .dd2    GetAreaPalette
8581: e3 85                        .dd2    GetBackgroundColor
8583: 43 86                        .dd2    GetAlternatePalette1
8585: ff 86                        .dd2    DrawTitleScreen
8587: 32 87                        .dd2    ClearBuffersDrawIcon
8589: 49 87                        .dd2    WriteTopScore

                   ; -----------------------------------------------------------------------------
858b: 20 20 82     InitScreen      jsr     MoveAllSpritesOffscreen ;initialize all sprites including sprite #0
858e: 20 19 8e                     jsr     InitializeNameTables    ; and erase both name and attribute tables
8591: ad 70 07                     lda     OperMode
8594: f0 32                        beq     NextSubtask             ;if mode still 0, do not load
8596: a2 03                        ldx     #$03                    ;into buffer pointer
8598: 4c c5 85                     jmp     SetVRAMAddr_A

                   ; -----------------------------------------------------------------------------
                   SetupIntermediate
859b: ad 44 07                     lda     BackgroundColorCtrl     ;save current background color control
859e: 48                           pha                             ; and player status to stack
859f: ad 56 07                     lda     PlayerStatus
85a2: 48                           pha
85a3: a9 00                        lda     #$00                    ;set background color to black
85a5: 8d 56 07                     sta     PlayerStatus            ; and player status to not fiery
85a8: a9 02                        lda     #$02                    ;this is the ONLY time background color control
85aa: 8d 44 07                     sta     BackgroundColorCtrl     ; is set to less than 4
85ad: 20 f1 85                     jsr     GetPlayerColors
85b0: 68                           pla                             ;we only execute this routine for
85b1: 8d 56 07                     sta     PlayerStatus            ; the intermediate lives display
85b4: 68                           pla                             ; and once we're done, we return bg
85b5: 8d 44 07                     sta     BackgroundColorCtrl     ; color ctrl and player status from stack
85b8: 4c 45 87                     jmp     IncSubtask              ; then move into the next task

                   ; -----------------------------------------------------------------------------
85bb: 01 02 03 04  AreaPalette     .bulk   $01,$02,$03,$04

85bf: ac 4e 07     GetAreaPalette  ldy     AreaType                ;select appropriate palette to load
85c2: be bb 85                     ldx     AreaPalette,y           ; based on area type
85c5: 8e 73 07     SetVRAMAddr_A   stx     VRAM_Buffer_AddrCtrl    ;store offset into buffer control
85c8: 4c 45 87     NextSubtask     jmp     IncSubtask              ;move onto next task

                   ; -----------------------------------------------------------------------------
                   ; $00 - used as temp counter in GetPlayerColors
                   BGColorCtrl_Addr
85cb: 00 09 0a 04                  .bulk   $00,$09,$0a,$04
                   BackgroundColors
85cf: 22 22 0f 0f                  .bulk   $22,$22,$0f,$0f         ;used by area type if bg color ctrl not set
85d3: 0f 22 0f 0f                  .bulk   $0f,$22,$0f,$0f         ;used by background color control if set
85d7: 22 16 27 18  PlayerColors    .bulk   $22,$16,$27,$18         ;mario's colors
85db: 22 30 27 19                  .bulk   $22,$30,$27,$19         ;luigi's colors
85df: 22 37 27 16                  .bulk   $22,$37,$27,$16         ;fiery (used by both)

                   GetBackgroundColor
85e3: ac 44 07                     ldy     BackgroundColorCtrl     ;check background color control
85e6: f0 06                        beq     NoBGColor               ;if not set, increment task and fetch palette
85e8: b9 c7 85                     lda     BGColorCtrl_Addr-4,y    ;put appropriate palette into vram
85eb: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ;note that if set to 5-7, $0301 will not be read
85ee: ee 3c 07     NoBGColor       inc     ScreenRoutineTask       ;increment to next subtask and plod on through
                   ; 
85f1: ae 00 03     GetPlayerColors ldx     VRAM_Buffer1_Offset     ;get current buffer offset
85f4: a0 00                        ldy     #$00
85f6: ad 53 07                     lda     CurrentPlayer           ;check which player is on the screen
85f9: f0 02                        beq     ChkFiery
85fb: a0 04                        ldy     #$04                    ;load offset for luigi
85fd: ad 56 07     ChkFiery        lda     PlayerStatus            ;check player status
8600: c9 02                        cmp     #$02
8602: d0 02                        bne     StartClrGet             ;if fiery, load alternate offset for fiery player
8604: a0 08                        ldy     #$08
8606: a9 03        StartClrGet     lda     #$03                    ;do four colors
8608: 85 00                        sta     $00
860a: b9 d7 85     ClrGetLoop      lda     PlayerColors,y          ;fetch player colors and store them
860d: 9d 04 03                     sta     VRAM_Buffer1+3,x        ; in the buffer
8610: c8                           iny
8611: e8                           inx
8612: c6 00                        dec     $00
8614: 10 f4                        bpl     ClrGetLoop
8616: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;load original offset from before
8619: ac 44 07                     ldy     BackgroundColorCtrl     ;if this value is four or greater, it will be set
861c: d0 03                        bne     SetBGColor              ;therefore use it as offset to background color
861e: ac 4e 07                     ldy     AreaType                ;otherwise use area type bits from area offset as offset
8621: b9 cf 85     SetBGColor      lda     BackgroundColors,y      ; to background color instead
8624: 9d 04 03                     sta     VRAM_Buffer1+3,x
8627: a9 3f                        lda     #$3f                    ;set for sprite palette address
8629: 9d 01 03                     sta     VRAM_Buffer1,x          ;save to buffer
862c: a9 10                        lda     #$10
862e: 9d 02 03                     sta     VRAM_Buffer1+1,x
8631: a9 04                        lda     #$04                    ;write length byte to buffer
8633: 9d 03 03                     sta     VRAM_Buffer1+2,x
8636: a9 00                        lda     #$00                    ;now the null terminator
8638: 9d 08 03                     sta     VRAM_Buffer1+7,x
863b: 8a                           txa                             ;move the buffer pointer ahead 7 bytes
863c: 18                           clc                             ;in case we want to write anything else later
863d: 69 07                        adc     #$07
863f: 8d 00 03     SetVRAMOffset   sta     VRAM_Buffer1_Offset     ;store as new vram buffer offset
8642: 60                           rts

                   ; -----------------------------------------------------------------------------
                   GetAlternatePalette1
8643: ad 33 07                     lda     AreaStyle               ;check for mushroom level style
8646: c9 01                        cmp     #$01
8648: d0 05                        bne     NoAltPal
864a: a9 0b                        lda     #$0b                    ;if found, load appropriate palette
864c: 8d 73 07     SetVRAMAddr_B   sta     VRAM_Buffer_AddrCtrl
864f: 4c 45 87     NoAltPal        jmp     IncSubtask              ;now onto the next task

                   ; -----------------------------------------------------------------------------
                   WriteTopStatusLine
8652: a9 00                        lda     #$00                    ;select main status bar
8654: 20 08 88                     jsr     WriteGameText           ;output it
8657: 4c 45 87                     jmp     IncSubtask              ;onto the next task

                   ; -----------------------------------------------------------------------------
                   WriteBottomStatusLine
865a: 20 30 bc                     jsr     GetSBNybbles            ;write player's score and coin tally to screen
865d: ae 00 03                     ldx     VRAM_Buffer1_Offset
8660: a9 20                        lda     #$20                    ;write address for world-area number on screen
8662: 9d 01 03                     sta     VRAM_Buffer1,x
8665: a9 73                        lda     #$73
8667: 9d 02 03                     sta     VRAM_Buffer1+1,x
866a: a9 03                        lda     #$03                    ;write length for it
866c: 9d 03 03                     sta     VRAM_Buffer1+2,x
866f: ac 5f 07                     ldy     WorldNumber             ;first the world number
8672: c8                           iny
8673: 98                           tya
8674: 9d 04 03                     sta     VRAM_Buffer1+3,x
8677: a9 28                        lda     #$28                    ;next the dash
8679: 9d 05 03                     sta     VRAM_Buffer1+4,x
867c: ac 5c 07                     ldy     LevelNumber             ;next the level number
867f: c8                           iny                             ;increment for proper number display
8680: 98                           tya
8681: 9d 06 03                     sta     VRAM_Buffer1+5,x
8684: a9 00                        lda     #$00                    ;put null terminator on
8686: 9d 07 03                     sta     VRAM_Buffer1+6,x
8689: 8a                           txa                             ;move the buffer offset up by 6 bytes
868a: 18                           clc
868b: 69 06                        adc     #$06
868d: 8d 00 03                     sta     VRAM_Buffer1_Offset
8690: 4c 45 87                     jmp     IncSubtask

                   ; -----------------------------------------------------------------------------
8693: ad 59 07     DisplayTimeUp   lda     GameTimerExpiredFlag    ;if game timer not expired, increment task
8696: f0 0a                        beq     NoTimeUp                ;control 2 tasks forward, otherwise, stay here
8698: a9 00                        lda     #$00
869a: 8d 59 07                     sta     GameTimerExpiredFlag    ;reset timer expiration flag
869d: a9 02                        lda     #$02                    ;output time-up screen to buffer
869f: 4c c7 86                     jmp     OutputInter

86a2: ee 3c 07     NoTimeUp        inc     ScreenRoutineTask       ;increment control task 2 tasks forward
86a5: 4c 45 87                     jmp     IncSubtask

                   ; -----------------------------------------------------------------------------
                   DisplayIntermediate
86a8: ad 70 07                     lda     OperMode                ;check primary mode of operation
86ab: f0 33                        beq     NoInter                 ;if in title screen mode, skip this
86ad: c9 03                        cmp     #GameOverModeValue      ;are we in game over mode?
86af: f0 22                        beq     GameOverInter           ;if so, proceed to display game over screen
86b1: ad 52 07                     lda     AltEntranceControl      ;otherwise check for mode of alternate entry
86b4: d0 2a                        bne     NoInter                 ; and branch if found
86b6: ac 4e 07                     ldy     AreaType                ;check if we are on castle level
86b9: c0 03                        cpy     #$03                    ;and if so, branch (possibly residual)
86bb: f0 05                        beq     PlayerInter
86bd: ad 69 07                     lda     DisableIntermediate     ;if this flag is set, skip intermediate lives display
86c0: d0 1e                        bne     NoInter                 ; and jump to specific task, otherwise
86c2: 20 a4 ef     PlayerInter     jsr     DrawPlayer_Intermediate ;put player in appropriate place for
86c5: a9 01                        lda     #$01                    ; lives display, then output lives display to buffer
86c7: 20 08 88     OutputInter     jsr     WriteGameText
86ca: 20 a5 88                     jsr     ResetScreenTimer
86cd: a9 00                        lda     #$00
86cf: 8d 74 07                     sta     DisableScreenFlag       ;reenable screen output
86d2: 60                           rts

86d3: a9 12        GameOverInter   lda     #$12                    ;set screen timer
86d5: 8d a0 07                     sta     ScreenTimer
86d8: a9 03                        lda     #$03                    ;output game over screen to buffer
86da: 20 08 88                     jsr     WriteGameText
86dd: 4c 4e 87                     jmp     IncModeTask_B

86e0: a9 08        NoInter         lda     #$08                    ;set for specific task and leave
86e2: 8d 3c 07                     sta     ScreenRoutineTask
86e5: 60                           rts

                   ; -----------------------------------------------------------------------------
                   AreaParserTaskControl
86e6: ee 74 07                     inc     DisableScreenFlag       ;turn off screen
86e9: 20 b0 92     TaskLoop        jsr     AreaParserTaskHandler   ;render column set of current area
86ec: ad 1f 07                     lda     AreaParserTaskNum       ;check number of tasks
86ef: d0 f8                        bne     TaskLoop                ;if tasks still not all done, do another one
86f1: ce 1e 07                     dec     ColumnSets              ;do we need to render more column sets?
86f4: 10 03                        bpl     OutputCol
86f6: ee 3c 07                     inc     ScreenRoutineTask       ;if not, move on to the next task
86f9: a9 06        OutputCol       lda     #$06                    ;set vram buffer to output rendered column set
86fb: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ; on next NMI
86fe: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - vram buffer address table low
                   ; $01 - vram buffer address table high
86ff: ad 70 07     DrawTitleScreen lda     OperMode                ;are we in title screen mode?
8702: d0 4a                        bne     IncModeTask_B           ;if not, exit
8704: a9 1e                        lda     #>TitleScreenDataOffset ;load address $1ec0 into
8706: 8d 06 20                     sta     PPUADDR                 ; the vram address register
8709: a9 c0                        lda     #<TitleScreenDataOffset
870b: 8d 06 20                     sta     PPUADDR
870e: a9 03                        lda     #$03                    ;put address $0300 into
8710: 85 01                        sta     $01                     ; the indirect at $00
8712: a0 00                        ldy     #$00
8714: 84 00                        sty     $00
8716: ad 07 20                     lda     PPUDATA                 ;do one garbage read
8719: ad 07 20     OutputTScr      lda     PPUDATA                 ;get title screen from chr-rom
871c: 91 00                        sta     ($00),y                 ;store 256 bytes into buffer
871e: c8                           iny
871f: d0 02                        bne     ChkHiByte               ;if not past 256 bytesw, do not increment
8721: e6 01                        inc     $01                     ;otherwise increment high byte of indirect
8723: a5 01        ChkHiByte       lda     $01                     ;heck high byte?
8725: c9 04                        cmp     #$04                    ;at $0400?
8727: d0 f0                        bne     OutputTScr              ;if not, loop back and do another
8729: c0 3a                        cpy     #$3a                    ;check if offset points past end of data
872b: 90 ec                        bcc     OutputTScr              ;if not, loop back and do another
872d: a9 05                        lda     #$05                    ;set buffer transfer control to $0300,
872f: 4c 4c 86                     jmp     SetVRAMAddr_B           ; increment task and exit

                   ; -----------------------------------------------------------------------------
                   ClearBuffersDrawIcon
8732: ad 70 07                     lda     OperMode                ;check game mode
8735: d0 17                        bne     IncModeTask_B           ;if not title screen mnode, leave
8737: a2 00                        ldx     #$00                    ;otherwise, clear buffer space
8739: 9d 00 03     TScrClear       sta     VRAM_Buffer1-1,x
873c: 9d 00 04                     sta     VRAM_Buffer1+255,x
873f: ca                           dex
8740: d0 f7                        bne     TScrClear
8742: 20 25 83                     jsr     DrawMushroomIcon        ;draw player select icon
8745: ee 3c 07     IncSubtask      inc     ScreenRoutineTask       ;move onto next task
8748: 60                           rts

                   ; -----------------------------------------------------------------------------
8749: a9 fa        WriteTopScore   lda     #$fa                    ;run display routine to display top score on title
874b: 20 36 bc                     jsr     UpdateNumber
874e: ee 72 07     IncModeTask_B   inc     OperMode_Task           ;move onto next mode
8751: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; ||TopStatusBarLine
8752: 20 43 05 16+ GameText        .bulk   $20,$43,$05,$16,$0a,$1b,$12,$18 ;"MARIO"
875a: 20 52 0b 20+                 .bulk   $20,$52,$0b,$20,$18,$1b,$15,$0d ;"WORLD  TIME"
8762: 24 24 1d 12+                 .bulk   $24,$24,$1d,$12,$16,$0e
8768: 20 68 05 00+                 .bulk   $20,$68,$05,$00,$24,$24,$2e,$29 ;score trailing digit and coin display
8770: 23 c0 7f aa                  .bulk   $23,$c0,$7f,$aa         ;attribute table data, clears name table 0 to palette 2
8774: 23 c2 01 ea                  .bulk   $23,$c2,$01,$ea         ;attribute table data, used for coin icon in status bar
8778: ff                           .dd1    $ff                     ;end of data block
                   WorldLivesDisplay
8779: 21 cd 07 24+                 .bulk   $21,$cd,$07,$24,$24     ;cross with spaces used on
877e: 29 24 24 24+                 .bulk   $29,$24,$24,$24,$24     ; lives display
8783: 21 4b 09 20+                 .bulk   $21,$4b,$09,$20,$18     ;"WORLD  - " used on lives display
8788: 1b 15 0d 24+                 .bulk   $1b,$15,$0d,$24,$24,$28,$24
878f: 22 0c 47 24                  .bulk   $22,$0c,$47,$24         ;possibly used to clear time up
8793: 23 dc 01 ba                  .bulk   $23,$dc,$01,$ba         ;attribute table data for crown if more than 9 lives
8797: ff                           .dd1    $ff
8798: 21 cd 05 16+ TwoPlayerTimeUp .bulk   $21,$cd,$05,$16,$0a,$1b,$12,$18 ;"MARIO"
87a0: 22 0c 07 1d+                 .bulk   $22,$0c,$07,$1d,$12,$16,$0e,$24,$1e,$19 ;"TIME UP"
87aa: ff                           .dd1    $ff
                   TwoPlayerGameOver
87ab: 21 cd 05 16+                 .bulk   $21,$cd,$05,$16,$0a,$1b,$12,$18 ;"MARIO"
                   OnePlayerGameOver
87b3: 22 0b 09 10+                 .bulk   $22,$0b,$09,$10,$0a,$16,$0e,$24 ;"GAME OVER"
87bb: 18 1f 0e 1b                  .bulk   $18,$1f,$0e,$1b
87bf: ff                           .dd1    $ff
87c0: 25 84 15 20+ WarpZoneWelcome .bulk   $25,$84,$15,$20,$0e,$15,$0c,$18,$16 ;"WELCOME TO WARP ZONE!"
87c9: 0e 24 1d 18+                 .bulk   $0e,$24,$1d,$18,$24,$20,$0a,$1b,$19
87d2: 24 23 18 17+                 .bulk   $24,$23,$18,$17,$0e,$2b
87d8: 26 25 01 24                  .bulk   $26,$25,$01,$24         ;placeholder for left pipe
87dc: 26 2d 01 24                  .bulk   $26,$2d,$01,$24         ;placeholder for middle pipe
87e0: 26 35 01 24                  .bulk   $26,$35,$01,$24         ;placeholder for right pipe
87e4: 27 d9 46 aa                  .bulk   $27,$d9,$46,$aa         ;attribute data
87e8: 27 e1 45 aa                  .bulk   $27,$e1,$45,$aa
87ec: ff                           .dd1    $ff
87ed: 15 1e 12 10+ LuigiName       .bulk   $15,$1e,$12,$10,$12     ;"LUIGI", no address or length
87f2: 04 03 02 00  WarpZoneNumbers .bulk   $04,$03,$02,$00         ;warp zone numbers, note spaces on middle
87f6: 24 05 24 00                  .bulk   $24,$05,$24,$00         ; zone, partly responsible for
87fa: 08 07 06 00                  .bulk   $08,$07,$06,$00         ; the minus world
                   ; || (should be table of single-byte offsets, e.g. TopStatusBarLine-GameText and
                   ; WorldLivesDisplay-GameText)
87fe: 00 00 27 27+ GameTextOffsets .bulk   $00,$00,$27,$27,$46,$4e,$59,$61,$6e,$6e

8808: 48           WriteGameText   pha                             ;save text number to stack
8809: 0a                           asl     A
880a: a8                           tay                             ;multiply by 2 and use as offset
880b: c0 04                        cpy     #$04                    ;if set to do top status bar on world/lives display,
880d: 90 0c                        bcc     LdGameText              ; branch to use current offset as-is
880f: c0 08                        cpy     #$08                    ;if set to do time-up or game over,
8811: 90 02                        bcc     Chk2Players             ;branch to check players
8813: a0 08                        ldy     #$08                    ;otherwise warp zone, therefore set offset
8815: ad 7a 07     Chk2Players     lda     NumberOfPlayers         ;check for number of players
8818: d0 01                        bne     LdGameText              ;if there are two, use current offset to also print name
881a: c8                           iny                             ;otherwise increment offset by one to not print name
881b: be fe 87     LdGameText      ldx     GameTextOffsets,y       ;get offset to message we want to print
881e: a0 00                        ldy     #$00
8820: bd 52 87     GameTextLoop    lda     GameText,x              ;load message data
8823: c9 ff                        cmp     #$ff                    ;check for terminator
8825: f0 07                        beq     EndGameText             ;branch to end text if found
8827: 99 01 03                     sta     VRAM_Buffer1,y          ;otherwise write data to buffer
882a: e8                           inx                             ;and increment increment
882b: c8                           iny
882c: d0 f2                        bne     GameTextLoop            ;do this for 256 bytes if no terminator found
882e: a9 00        EndGameText     lda     #$00                    ;put null terminator at end
8830: 99 01 03                     sta     VRAM_Buffer1,y
8833: 68                           pla                             ;pull original text number from stack
8834: aa                           tax
8835: c9 04                        cmp     #$04                    ;are we printing warp zone?
8837: b0 49                        bcs     PrintWarpZoneNumbers
8839: ca                           dex                             ;are we printing the world/lives display?
883a: d0 23                        bne     CheckPlayerName         ;if not, branch to check player's name
883c: ad 5a 07                     lda     NumberOfLives           ;otherwise, check number of lives
883f: 18                           clc                             ; and increment by one for display
8840: 69 01                        adc     #$01
8842: c9 0a                        cmp     #10                     ;more than 9 lives?
8844: 90 07                        bcc     PutLives
8846: e9 0a                        sbc     #10                     ;if so, subtract 10 and put a crown tile
8848: a0 9f                        ldy     #$9f                    ; next to the difference...strange things happen if
884a: 8c 08 03                     sty     VRAM_Buffer1+7          ; the number of lives exceeds 19
884d: 8d 09 03     PutLives        sta     VRAM_Buffer1+8
8850: ac 5f 07                     ldy     WorldNumber             ;write world and level numbers (incremented for display)
8853: c8                           iny                             ; to the buffer in the spaces surrounding the dash
8854: 8c 14 03                     sty     VRAM_Buffer1+19
8857: ac 5c 07                     ldy     LevelNumber
885a: c8                           iny
885b: 8c 16 03                     sty     VRAM_Buffer1+21         ;we're done here
885e: 60                           rts

885f: ad 7a 07     CheckPlayerName lda     NumberOfPlayers         ;check number of players
8862: f0 1d                        beq     ExitChkName             ;if only 1 player, leave
8864: ad 53 07                     lda     CurrentPlayer           ;load current player
8867: ca                           dex                             ;check to see if current message number is for time up
8868: d0 09                        bne     ChkLuigi
886a: ac 70 07                     ldy     OperMode                ;check for game over mode
886d: c0 03                        cpy     #GameOverModeValue
886f: f0 02                        beq     ChkLuigi
8871: 49 01                        eor     #%00000001              ;if not, must be time up, invert d0 to do other player
8873: 4a           ChkLuigi        lsr     A
8874: 90 0b                        bcc     ExitChkName             ;if mario is current player, do not change the name
8876: a0 04                        ldy     #$04
8878: b9 ed 87     NameLoop        lda     LuigiName,y             ;otherwise, replace "MARIO" with "LUIGI"
887b: 99 04 03                     sta     VRAM_Buffer1+3,y
887e: 88                           dey
887f: 10 f7                        bpl     NameLoop                ;do this until each letter is replaced
8881: 60           ExitChkName     rts

                   PrintWarpZoneNumbers
8882: e9 04                        sbc     #$04                    ;subtract 4 and then shift to the left
8884: 0a                           asl     A                       ; twice to get proper warp zone number
8885: 0a                           asl     A                       ;offset
8886: aa                           tax
8887: a0 00                        ldy     #$00
8889: bd f2 87     WarpNumLoop     lda     WarpZoneNumbers,x       ;print warp zone numbers into the
888c: 99 1c 03                     sta     VRAM_Buffer1+27,y       ; placeholders from earlier
888f: e8                           inx
8890: c8                           iny                             ;put a number in every fourth space
8891: c8                           iny
8892: c8                           iny
8893: c8                           iny
8894: c0 0c                        cpy     #$0c
8896: 90 f1                        bcc     WarpNumLoop
8898: a9 2c                        lda     #$2c                    ;load new buffer pointer at end of message
889a: 4c 3f 86                     jmp     SetVRAMOffset

                   ; -----------------------------------------------------------------------------
                   ResetSpritesAndScreenTimer
889d: ad a0 07                     lda     ScreenTimer             ;check if screen timer has expired
88a0: d0 0b                        bne     NoReset                 ;if not, branch to leave
88a2: 20 20 82                     jsr     MoveAllSpritesOffscreen ;otherwise reset sprites now
                   ResetScreenTimer
88a5: a9 07                        lda     #$07                    ;reset timer again
88a7: 8d a0 07                     sta     ScreenTimer
88aa: ee 3c 07                     inc     ScreenRoutineTask       ;move onto next task
88ad: 60           NoReset         rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - temp vram buffer offset
                   ; $01 - temp metatile buffer offset
                   ; $02 - temp metatile graphics table offset
                   ; $03 - used to store attribute bits
                   ; $04 - used to determine attribute table row
                   ; $05 - used to determine attribute table column
                   ; $06 - metatile graphics table address low
                   ; $07 - metatile graphics table address high
                   RenderAreaGraphics
88ae: ad 26 07                     lda     CurrentColumnPos        ;store LSB of where we're at
88b1: 29 01                        and     #$01
88b3: 85 05                        sta     $05
88b5: ac 40 03                     ldy     VRAM_Buffer2_Offset     ;store vram buffer offset
88b8: 84 00                        sty     $00
88ba: ad 21 07                     lda     CurrentNTAddr_Low       ;get current name table address we're supposed to render
88bd: 99 42 03                     sta     VRAM_Buffer2+1,y
88c0: ad 20 07                     lda     CurrentNTAddr_High
88c3: 99 41 03                     sta     VRAM_Buffer2,y
88c6: a9 9a                        lda     #$9a                    ;store length byte of 26 here with d7 set
88c8: 99 43 03                     sta     VRAM_Buffer2+2,y        ; to increment by 32 (in columns)
88cb: a9 00                        lda     #$00                    ;init attribute row
88cd: 85 04                        sta     $04
88cf: aa                           tax
88d0: 86 01        DrawMTLoop      stx     $01                     ;tore init value of 0 or incremented offset for buffer
88d2: bd a1 06                     lda     MetatileBuffer,x        ;get first metatile number, and mask out all but 2 MSB
88d5: 29 c0                        and     #%11000000
88d7: 85 03                        sta     $03                     ;store attribute table bits here
88d9: 0a                           asl     A                       ;note that metatile format is:
88da: 2a                           rol     A                       ;%xx000000 - attribute table bits
88db: 2a                           rol     A                       ;%00xxxxxx - metatile number
88dc: a8                           tay                             ;rotate bits to d1-d0 and use as offset here
88dd: b9 08 8b                     lda     MetatileGraphics_Low,y  ;get address to graphics table from here
88e0: 85 06                        sta     $06
88e2: b9 0c 8b                     lda     MetatileGraphics_High,y
88e5: 85 07                        sta     $07
88e7: bd a1 06                     lda     MetatileBuffer,x        ;get metatile number again
88ea: 0a                           asl     A                       ;multiply by 4 and use as tile offset
88eb: 0a                           asl     A
88ec: 85 02                        sta     $02
88ee: ad 1f 07                     lda     AreaParserTaskNum       ;get current task number for level processing and
88f1: 29 01                        and     #%00000001              ; mask out all but LSB, then invert LSB, multiply by 2
88f3: 49 01                        eor     #%00000001              ; to get the correct column position in the metatile,
88f5: 0a                           asl     A                       ; then add to the tile offset so we can draw either side
88f6: 65 02                        adc     $02                     ; of the metatiles
88f8: a8                           tay
88f9: a6 00                        ldx     $00                     ;use vram buffer offset from before as X
88fb: b1 06                        lda     ($06),y
88fd: 9d 44 03                     sta     VRAM_Buffer2+3,x        ;get first tile number (top left or top right) and store
8900: c8                           iny
8901: b1 06                        lda     ($06),y                 ;now get the second (bottom left or bottom right) and store
8903: 9d 45 03                     sta     VRAM_Buffer2+4,x
8906: a4 04                        ldy     $04                     ;get current attribute row
8908: a5 05                        lda     $05                     ;get LSB of current column where we're at, and
890a: d0 0e                        bne     RightCheck              ; branch if set (clear = left attrib, set = right)
890c: a5 01                        lda     $01                     ;get current row we're rendering
890e: 4a                           lsr     A                       ;branch if LSB set (clear = top left, set = bottom left)
890f: b0 19                        bcs     LLeft
8911: 26 03                        rol     $03                     ;rotate attribute bits 3 to the left
8913: 26 03                        rol     $03                     ;this in d1-d0, for upper left square
8915: 26 03                        rol     $03
8917: 4c 30 89                     jmp     SetAttrib

891a: a5 01        RightCheck      lda     $01                     ;get LSB of current row we're rendering
891c: 4a                           lsr     A                       ;branch if set (clear = top right, set = bottom right)
891d: b0 0f                        bcs     NextMTRow
891f: 46 03                        lsr     $03                     ;shift attribute bits 4 to the right
8921: 46 03                        lsr     $03
8923: 46 03                        lsr     $03
8925: 46 03                        lsr     $03
8927: 4c 30 89                     jmp     SetAttrib

892a: 46 03        LLeft           lsr     $03                     ;shift attribute bits 2 to the right
892c: 46 03                        lsr     $03                     ;this in d5-d4 for lower left square
892e: e6 04        NextMTRow       inc     $04                     ;move onto next attribute row
8930: b9 f9 03     SetAttrib       lda     AttributeBuffer,y       ;get previously saved bits from before
8933: 05 03                        ora     $03                     ; if any, and put new bits, if any
8935: 99 f9 03                     sta     AttributeBuffer,y       ; onto the old, and store
8938: e6 00                        inc     $00                     ;increment vram buffer offset by 2
893a: e6 00                        inc     $00
893c: a6 01                        ldx     $01                     ;get current gfx buffer row, and check for
893e: e8                           inx                             ; the bottom of the screen
893f: e0 0d                        cpx     #$0d
8941: 90 8d                        bcc     DrawMTLoop              ;if not there yet, loop back
8943: a4 00                        ldy     $00                     ;get current vram buffer offset, increment by 3
8945: c8                           iny                             ;(for name table address and length bytes)
8946: c8                           iny
8947: c8                           iny
8948: a9 00                        lda     #$00
894a: 99 41 03                     sta     VRAM_Buffer2,y          ;put null terminator at end of data for name table
894d: 8c 40 03                     sty     VRAM_Buffer2_Offset     ;store new buffer offset
8950: ee 21 07                     inc     CurrentNTAddr_Low       ;increment name table address low
8953: ad 21 07                     lda     CurrentNTAddr_Low       ;check current low byte
8956: 29 1f                        and     #%00011111              ;if no wraparound, just skip this part
8958: d0 0d                        bne     ExitDrawM
895a: a9 80                        lda     #$80                    ;if wraparound occurs, make sure low byte stays
895c: 8d 21 07                     sta     CurrentNTAddr_Low       ; just under the status bar
895f: ad 20 07                     lda     CurrentNTAddr_High      ; and then invert d2 of the name table address high
8962: 49 04                        eor     #%00000100              ; to move onto the next appropriate name table
8964: 8d 20 07                     sta     CurrentNTAddr_High
8967: 4c bd 89     ExitDrawM       jmp     SetVRAMCtrl             ;jump to set buffer to $0341 and leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - temp attribute table address high (big endian order this time!)
                   ; $01 - temp attribute table address low
                   RenderAttributeTables
896a: ad 21 07                     lda     CurrentNTAddr_Low       ;get low byte of next name table address
896d: 29 1f                        and     #%00011111              ; to be written to, mask out all but 5 LSB,
896f: 38                           sec                             ; subtract four 
8970: e9 04                        sbc     #$04
8972: 29 1f                        and     #%00011111              ;mask out bits again and store
8974: 85 01                        sta     $01
8976: ad 20 07                     lda     CurrentNTAddr_High      ;get high byte and branch if borrow not set
8979: b0 02                        bcs     SetATHigh
897b: 49 04                        eor     #%00000100              ;otherwise invert d2
897d: 29 04        SetATHigh       and     #%00000100              ;mask out all other bits
897f: 09 23                        ora     #$23                    ;add $2300 to the high byte and store
8981: 85 00                        sta     $00
8983: a5 01                        lda     $01                     ;get low byte - 4, divide by 4, add offset for
8985: 4a                           lsr     A                       ; attribute table and store
8986: 4a                           lsr     A
8987: 69 c0                        adc     #$c0                    ;we should now have the appropriate block of
8989: 85 01                        sta     $01                     ; attribute table in our temp address
898b: a2 00                        ldx     #$00
898d: ac 40 03                     ldy     VRAM_Buffer2_Offset     ;get buffer offset
8990: a5 00        AttribLoop      lda     $00
8992: 99 41 03                     sta     VRAM_Buffer2,y          ;store high byte of attribute table address
8995: a5 01                        lda     $01
8997: 18                           clc                             ;get low byte, add 8 because we want to start
8998: 69 08                        adc     #$08                    ; below the status bar, and store
899a: 99 42 03                     sta     VRAM_Buffer2+1,y
899d: 85 01                        sta     $01                     ;also store in temp again
899f: bd f9 03                     lda     AttributeBuffer,x       ;fetch current attribute table byte and store
89a2: 99 44 03                     sta     VRAM_Buffer2+3,y        ; in the buffer
89a5: a9 01                        lda     #$01
89a7: 99 43 03                     sta     VRAM_Buffer2+2,y        ;store length of 1 in buffer
89aa: 4a                           lsr     A
89ab: 9d f9 03                     sta     AttributeBuffer,x       ;clear current byte in attribute buffer
89ae: c8                           iny                             ;increment buffer offset by 4 bytes
89af: c8                           iny
89b0: c8                           iny
89b1: c8                           iny
89b2: e8                           inx                             ;increment attribute offset and check to see
89b3: e0 07                        cpx     #$07                    ; if we're at the end yet
89b5: 90 d9                        bcc     AttribLoop
89b7: 99 41 03                     sta     VRAM_Buffer2,y          ;put null terminator at the end
89ba: 8c 40 03                     sty     VRAM_Buffer2_Offset     ;store offset in case we want to do any more
89bd: a9 06        SetVRAMCtrl     lda     #$06
89bf: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ;set buffer to $0341 and leave
89c2: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used as temporary counter in ColorRotation
                   ColorRotatePalette
89c3: 27 27 27 17+                 .bulk   $27,$27,$27,$17,$07,$17
89c9: 3f 0c 04 ff+ BlankPalette    .bulk   $3f,$0c,$04,$ff,$ff,$ff,$ff,$00
                   ; used based on area type
89d1: 0f 07 12 0f  Palette3Data    .bulk   $0f,$07,$12,$0f
89d5: 0f 07 17 0f                  .bulk   $0f,$07,$17,$0f
89d9: 0f 07 17 1c                  .bulk   $0f,$07,$17,$1c
89dd: 0f 07 17 00                  .bulk   $0f,$07,$17,$00

89e1: a5 09        ColorRotation   lda     FrameCounter            ;get frame counter
89e3: 29 07                        and     #$07                    ;mask out all but three LSB
89e5: d0 51                        bne     ExitColorRot            ;branch if not set to zero to do this every eighth frame
89e7: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;check vram buffer offset
89ea: e0 31                        cpx     #$31
89ec: b0 4a                        bcs     ExitColorRot            ;if offset over 48 bytes, branch to leave
89ee: a8                           tay                             ;otherwise use frame counter's 3 LSB as offset here
89ef: b9 c9 89     GetBlankPal     lda     BlankPalette,y          ;get blank palette for palette 3
89f2: 9d 01 03                     sta     VRAM_Buffer1,x          ;store it in the vram buffer
89f5: e8                           inx                             ;increment offsets
89f6: c8                           iny
89f7: c0 08                        cpy     #$08
89f9: 90 f4                        bcc     GetBlankPal             ;do this until all bytes are copied
89fb: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;get current vram buffer offset
89fe: a9 03                        lda     #$03
8a00: 85 00                        sta     $00                     ;set counter here
8a02: ad 4e 07                     lda     AreaType                ;get area type
8a05: 0a                           asl     A                       ;multiply by 4 to get proper offset
8a06: 0a                           asl     A
8a07: a8                           tay                             ;save as offset here
8a08: b9 d1 89     GetAreaPal      lda     Palette3Data,y          ;fetch palette to be written based on area type
8a0b: 9d 04 03                     sta     VRAM_Buffer1+3,x        ;store it to overwrite blank palette in vram buffer
8a0e: c8                           iny
8a0f: e8                           inx
8a10: c6 00                        dec     $00                     ;decrement counter
8a12: 10 f4                        bpl     GetAreaPal              ;do this until the palette is all copied
8a14: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;get current vram buffer offset
8a17: ac d4 06                     ldy     ColorRotateOffset       ;get color cycling offset
8a1a: b9 c3 89                     lda     ColorRotatePalette,y
8a1d: 9d 05 03                     sta     VRAM_Buffer1+4,x        ;get and store current color in second slot of palette
8a20: ad 00 03                     lda     VRAM_Buffer1_Offset
8a23: 18                           clc                             ;add seven bytes to vram buffer offset
8a24: 69 07                        adc     #$07
8a26: 8d 00 03                     sta     VRAM_Buffer1_Offset
8a29: ee d4 06                     inc     ColorRotateOffset       ;increment color cycling offset
8a2c: ad d4 06                     lda     ColorRotateOffset
8a2f: c9 06                        cmp     #$06                    ;check to see if it's still in range
8a31: 90 05                        bcc     ExitColorRot            ;if so, branch to leave
8a33: a9 00                        lda     #$00
8a35: 8d d4 06                     sta     ColorRotateOffset       ;otherwise, init to keep it in range
8a38: 60           ExitColorRot    rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - temp store for offset control bit
                   ; $01 - temp vram buffer offset
                   ; $02 - temp store for vertical high nybble in block buffer routine
                   ; $03 - temp adder for high byte of name table address
                   ; $04, $05 - name table address low/high
                   ; $06, $07 - block buffer address low/high
8a39: 45 45 47 47  BlockGfxData    .bulk   $45,$45,$47,$47
8a3d: 47 47 47 47                  .bulk   $47,$47,$47,$47
8a41: 57 58 59 5a                  .bulk   $57,$58,$59,$5a
8a45: 24 24 24 24                  .bulk   $24,$24,$24,$24
8a49: 26 26 26 26                  .bulk   $26,$26,$26,$26

8a4d: a0 41        RemoveCoin_Axe  ldy     #$41                    ;set low byte so offset points to $0341
8a4f: a9 03                        lda     #$03                    ;load offset for default blank metatile
8a51: ae 4e 07                     ldx     AreaType                ;check area type
8a54: d0 02                        bne     WriteBlankMT            ;if not water type, use offset
8a56: a9 04                        lda     #$04                    ;otherwise load offset for blank metatile used in water
8a58: 20 97 8a     WriteBlankMT    jsr     PutBlockMetatile        ;do a sub to write blank metatile to vram buffer
8a5b: a9 06                        lda     #$06
8a5d: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl    ;set vram address controller to $0341 and leave
8a60: 60                           rts

                   ReplaceBlockMetatile
8a61: 20 6d 8a                     jsr     WriteBlockMetatile      ;write metatile to vram buffer to replace block object
8a64: ee f0 03                     inc     Block_ResidualCounter   ;increment unused counter (residual code)
8a67: de ec 03                     dec     Block_RepFlag,x         ;decrement flag (residual code)
8a6a: 60                           rts                             ;leave

                   DestroyBlockMetatile
8a6b: a9 00                        lda     #$00                    ;force blank metatile if branched/jumped to this point
                   WriteBlockMetatile
8a6d: a0 03                        ldy     #$03                    ;load offset for blank metatile
8a6f: c9 00                        cmp     #$00                    ;check contents of A for blank metatile
8a71: f0 14                        beq     UseBOffset              ;branch if found (unconditional if branched from 8a6b)
8a73: a0 00                        ldy     #$00                    ;load offset for brick metatile w/ line
8a75: c9 58                        cmp     #$58
8a77: f0 0e                        beq     UseBOffset              ;use offset if metatile is brick with coins (w/ line)
8a79: c9 51                        cmp     #$51
8a7b: f0 0a                        beq     UseBOffset              ;use offset if metatile is breakable brick w/ line
8a7d: c8                           iny                             ;increment offset for brick metatile w/o line
8a7e: c9 5d                        cmp     #$5d
8a80: f0 05                        beq     UseBOffset              ;use offset if metatile is brick with coins (w/o line)
8a82: c9 52                        cmp     #$52
8a84: f0 01                        beq     UseBOffset              ;use offset if metatile is breakable brick w/o line
8a86: c8                           iny                             ;if any other metatile, increment offset for empty block
8a87: 98           UseBOffset      tya                             ;put Y in A
8a88: ac 00 03                     ldy     VRAM_Buffer1_Offset     ;get vram buffer offset
8a8b: c8                           iny                             ;move onto next byte
8a8c: 20 97 8a                     jsr     PutBlockMetatile        ;get appropriate block data and write to vram buffer
8a8f: 88           MoveVOffset     dey                             ;decrement vram buffer offset
8a90: 98                           tya                             ;add 10 bytes to it
8a91: 18                           clc
8a92: 69 0a                        adc     #10
8a94: 4c 3f 86                     jmp     SetVRAMOffset           ;branch to store as new vram buffer offset

                   PutBlockMetatile
8a97: 86 00                        stx     $00                     ;store control bit from SprDataOffset_Ctrl
8a99: 84 01                        sty     $01                     ;store vram buffer offset for next byte
8a9b: 0a                           asl     A
8a9c: 0a                           asl     A                       ;multiply A by four and use as X
8a9d: aa                           tax
8a9e: a0 20                        ldy     #$20                    ;load high byte for name table 0
8aa0: a5 06                        lda     $06                     ;get low byte of block buffer pointer
8aa2: c9 d0                        cmp     #$d0                    ;check to see if we're on odd-page block buffer
8aa4: 90 02                        bcc     SaveHAddr               ;if not, use current high byte
8aa6: a0 24                        ldy     #$24                    ;otherwise load high byte for name table 1
8aa8: 84 03        SaveHAddr       sty     $03                     ;save high byte here
8aaa: 29 0f                        and     #$0f                    ;mask out high nybble of block buffer pointer
8aac: 0a                           asl     A                       ;multiply by 2 to get appropriate name table low byte
8aad: 85 04                        sta     $04                     ;and then store it here
8aaf: a9 00                        lda     #$00
8ab1: 85 05                        sta     $05                     ;initialize temp high byte
8ab3: a5 02                        lda     $02                     ;get vertical high nybble offset used in block buffer routine
8ab5: 18                           clc
8ab6: 69 20                        adc     #$20                    ;add 32 pixels for the status bar
8ab8: 0a                           asl     A
8ab9: 26 05                        rol     $05                     ;shift and rotate d7 onto d0 and d6 into carry
8abb: 0a                           asl     A
8abc: 26 05                        rol     $05                     ;shift and rotate d6 onto d0 and d5 into carry
8abe: 65 04                        adc     $04                     ;add low byte of name table and carry to vertical high nybble
8ac0: 85 04                        sta     $04                     ;and store here
8ac2: a5 05                        lda     $05                     ;get whatever was in d7 and d6 of vertical high nybble
8ac4: 69 00                        adc     #$00                    ;add carry
8ac6: 18                           clc
8ac7: 65 03                        adc     $03                     ;then add high byte of name table
8ac9: 85 05                        sta     $05                     ;store here
8acb: a4 01                        ldy     $01                     ;get vram buffer offset to be used
8acd: bd 39 8a     RemBridge       lda     BlockGfxData,x          ;write top left and top right
8ad0: 99 03 03                     sta     VRAM_Buffer1+2,y        ; tile numbers into first spot
8ad3: bd 3a 8a                     lda     BlockGfxData+1,x
8ad6: 99 04 03                     sta     VRAM_Buffer1+3,y
8ad9: bd 3b 8a                     lda     BlockGfxData+2,x        ;write bottom left and bottom
8adc: 99 08 03                     sta     VRAM_Buffer1+7,y        ; right tiles numbers into
8adf: bd 3c 8a                     lda     BlockGfxData+3,x        ; second spot
8ae2: 99 09 03                     sta     VRAM_Buffer1+8,y
8ae5: a5 04                        lda     $04
8ae7: 99 01 03                     sta     VRAM_Buffer1,y          ;write low byte of name table
8aea: 18                           clc                             ; into first slot as read
8aeb: 69 20                        adc     #$20                    ;add 32 bytes to value
8aed: 99 06 03                     sta     VRAM_Buffer1+5,y        ;write low byte of name table
8af0: a5 05                        lda     $05                     ; plus 32 bytes into second slot
8af2: 99 00 03                     sta     VRAM_Buffer1-1,y        ;write high byte of name
8af5: 99 05 03                     sta     VRAM_Buffer1+4,y        ; table address to both slots
8af8: a9 02                        lda     #$02
8afa: 99 02 03                     sta     VRAM_Buffer1+1,y        ;put length of 2 in
8afd: 99 07 03                     sta     VRAM_Buffer1+6,y        ; both slots
8b00: a9 00                        lda     #$00
8b02: 99 0a 03                     sta     VRAM_Buffer1+9,y        ;put null terminator at end
8b05: a6 00                        ldx     $00                     ;get offset control bit here
8b07: 60                           rts                             ;and leave

                   ; -----------------------------------------------------------------------------
                   ; METATILE GRAPHICS TABLE
                   MetatileGraphics_Low
8b08: 10                           .dd1    <Palette0_MTiles
8b09: ac                           .dd1    <Palette1_MTiles
8b0a: 64                           .dd1    <Palette2_MTiles
8b0b: 8c                           .dd1    <Palette3_MTiles
                   MetatileGraphics_High
8b0c: 8b                           .dd1    >Palette0_MTiles
8b0d: 8b                           .dd1    >Palette1_MTiles
8b0e: 8c                           .dd1    >Palette2_MTiles
8b0f: 8c                           .dd1    >Palette3_MTiles
8b10: 24 24 24 24  Palette0_MTiles .bulk   $24,$24,$24,$24         ;blank
8b14: 27 27 27 27                  .bulk   $27,$27,$27,$27         ;black metatile
8b18: 24 24 24 35                  .bulk   $24,$24,$24,$35         ;bush left
8b1c: 36 25 37 25                  .bulk   $36,$25,$37,$25         ;bush middle
8b20: 24 38 24 24                  .bulk   $24,$38,$24,$24         ;bush right
8b24: 24 30 30 26                  .bulk   $24,$30,$30,$26         ;mountain left
8b28: 26 26 34 26                  .bulk   $26,$26,$34,$26         ;mountain left bottom/middle center
8b2c: 24 31 24 32                  .bulk   $24,$31,$24,$32         ;mountain middle top
8b30: 33 26 24 33                  .bulk   $33,$26,$24,$33         ;mountain right
8b34: 34 26 26 26                  .bulk   $34,$26,$26,$26         ;mountain right bottom
8b38: 26 26 26 26                  .bulk   $26,$26,$26,$26         ;mountain middle bottom
8b3c: 24 c0 24 c0                  .bulk   $24,$c0,$24,$c0         ;bridge guardrail
8b40: 24 7f 7f 24                  .bulk   $24,$7f,$7f,$24         ;chain
8b44: b8 ba b9 bb                  .bulk   $b8,$ba,$b9,$bb         ;tall tree, top half
8b48: b8 bc b9 bd                  .bulk   $b8,$bc,$b9,$bd         ;short tree top
8b4c: ba bc bb bd                  .bulk   $ba,$bc,$bb,$bd         ;tall tree top, bottom half
8b50: 60 64 61 65                  .bulk   $60,$64,$61,$65         ;warp pipe end left, points up
8b54: 62 66 63 67                  .bulk   $62,$66,$63,$67         ;warp pipe end right, points up
8b58: 60 64 61 65                  .bulk   $60,$64,$61,$65         ;decoration pipe end left, points up
8b5c: 62 66 63 67                  .bulk   $62,$66,$63,$67         ;decoration pipe end right, points up
8b60: 68 68 69 69                  .bulk   $68,$68,$69,$69         ;pipe shaft left
8b64: 26 26 6a 6a                  .bulk   $26,$26,$6a,$6a         ;pipe shaft right
8b68: 4b 4c 4d 4e                  .bulk   $4b,$4c,$4d,$4e         ;tree ledge left edge
8b6c: 4d 4f 4d 4f                  .bulk   $4d,$4f,$4d,$4f         ;tree ledge middle
8b70: 4d 4e 50 51                  .bulk   $4d,$4e,$50,$51         ;tree ledge right edge
8b74: 6b 70 2c 2d                  .bulk   $6b,$70,$2c,$2d         ;mushroom left edge
8b78: 6c 71 6d 72                  .bulk   $6c,$71,$6d,$72         ;mushroom middle
8b7c: 6e 73 6f 74                  .bulk   $6e,$73,$6f,$74         ;mushroom right edge
8b80: 86 8a 87 8b                  .bulk   $86,$8a,$87,$8b         ;sideways pipe end top
8b84: 88 8c 88 8c                  .bulk   $88,$8c,$88,$8c         ;sideways pipe shaft top
8b88: 89 8d 69 69                  .bulk   $89,$8d,$69,$69         ;sideways pipe joint top
8b8c: 8e 91 8f 92                  .bulk   $8e,$91,$8f,$92         ;sideways pipe end bottom
8b90: 26 93 26 93                  .bulk   $26,$93,$26,$93         ;sideways pipe shaft bottom
8b94: 90 94 69 69                  .bulk   $90,$94,$69,$69         ;sideways pipe joint bottom
8b98: a4 e9 ea eb                  .bulk   $a4,$e9,$ea,$eb         ;seaplant
8b9c: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;blank, used on bricks or blocks that are hit
8ba0: 24 2f 24 3d                  .bulk   $24,$2f,$24,$3d         ;flagpole ball
8ba4: a2 a2 a3 a3                  .bulk   $a2,$a2,$a3,$a3         ;flagpole shaft
8ba8: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;blank, used in conjunction with vines
8bac: a2 a2 a3 a3  Palette1_MTiles .bulk   $a2,$a2,$a3,$a3         ;vertical rope
8bb0: 99 24 99 24                  .bulk   $99,$24,$99,$24         ;horizontal rope
8bb4: 24 a2 3e 3f                  .bulk   $24,$a2,$3e,$3f         ;left pulley
8bb8: 5b 5c 24 a3                  .bulk   $5b,$5c,$24,$a3         ;right pulley
8bbc: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;blank used for balance rope
8bc0: 9d 47 9e 47                  .bulk   $9d,$47,$9e,$47         ;castle top
8bc4: 47 47 27 27                  .bulk   $47,$47,$27,$27         ;castle window left
8bc8: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;castle brick wall
8bcc: 27 27 47 47                  .bulk   $27,$27,$47,$47         ;castle window right
8bd0: a9 47 aa 47                  .bulk   $a9,$47,$aa,$47         ;castle top w/ brick
8bd4: 9b 27 9c 27                  .bulk   $9b,$27,$9c,$27         ;entrance top
8bd8: 27 27 27 27                  .bulk   $27,$27,$27,$27         ;entrance bottom
8bdc: 52 52 52 52                  .bulk   $52,$52,$52,$52         ;green ledge stump
8be0: 80 a0 81 a1                  .bulk   $80,$a0,$81,$a1         ;fence
8be4: be be bf bf                  .bulk   $be,$be,$bf,$bf         ;tree trunk
8be8: 75 ba 76 bb                  .bulk   $75,$ba,$76,$bb         ;mushroom stump top
8bec: ba ba bb bb                  .bulk   $ba,$ba,$bb,$bb         ;mushroom stump bottom
8bf0: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;breakable brick w/ line 
8bf4: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;breakable brick 
8bf8: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;breakable brick (not used)
8bfc: b4 b6 b5 b7                  .bulk   $b4,$b6,$b5,$b7         ;cracked rock terrain
8c00: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;brick with line (power-up)
8c04: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;brick with line (vine)
8c08: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;brick with line (star)
8c0c: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;brick with line (coins)
8c10: 45 47 45 47                  .bulk   $45,$47,$45,$47         ;brick with line (1-up)
8c14: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;brick (power-up)
8c18: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;brick (vine)
8c1c: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;brick (star)
8c20: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;brick (coins)
8c24: 47 47 47 47                  .bulk   $47,$47,$47,$47         ;brick (1-up)
8c28: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;hidden block (1 coin)
8c2c: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;hidden block (1-up)
8c30: ab ac ad ae                  .bulk   $ab,$ac,$ad,$ae         ;solid block (3-d block)
8c34: 5d 5e 5d 5e                  .bulk   $5d,$5e,$5d,$5e         ;solid block (white wall)
8c38: c1 24 c1 24                  .bulk   $c1,$24,$c1,$24         ;bridge
8c3c: c6 c8 c7 c9                  .bulk   $c6,$c8,$c7,$c9         ;bullet bill cannon barrel
8c40: ca cc cb cd                  .bulk   $ca,$cc,$cb,$cd         ;bullet bill cannon top
8c44: 2a 2a 40 40                  .bulk   $2a,$2a,$40,$40         ;bullet bill cannon bottom
8c48: 24 24 24 24                  .bulk   $24,$24,$24,$24         ;blank used for jumpspring
8c4c: 24 47 24 47                  .bulk   $24,$47,$24,$47         ;half brick used for jumpspring
8c50: 82 83 84 85                  .bulk   $82,$83,$84,$85         ;solid block (water level, green rock)
8c54: 24 47 24 47                  .bulk   $24,$47,$24,$47         ;half brick (???)
8c58: 86 8a 87 8b                  .bulk   $86,$8a,$87,$8b         ;water pipe top
8c5c: 8e 91 8f 92                  .bulk   $8e,$91,$8f,$92         ;water pipe bottom
8c60: 24 2f 24 3d                  .bulk   $24,$2f,$24,$3d         ;flag ball (residual object)
8c64: 24 24 24 35  Palette2_MTiles .bulk   $24,$24,$24,$35         ;cloud left
8c68: 36 25 37 25                  .bulk   $36,$25,$37,$25         ;cloud middle
8c6c: 24 38 24 24                  .bulk   $24,$38,$24,$24         ;cloud right
8c70: 24 24 39 24                  .bulk   $24,$24,$39,$24         ;cloud bottom left
8c74: 3a 24 3b 24                  .bulk   $3a,$24,$3b,$24         ;cloud bottom middle
8c78: 3c 24 24 24                  .bulk   $3c,$24,$24,$24         ;cloud bottom right
8c7c: 41 26 41 26                  .bulk   $41,$26,$41,$26         ;water/lava top
8c80: 26 26 26 26                  .bulk   $26,$26,$26,$26         ;water/lava
8c84: b0 b1 b2 b3                  .bulk   $b0,$b1,$b2,$b3         ;cloud level terrain
8c88: 77 79 77 79                  .bulk   $77,$79,$77,$79         ;bowser's bridge
8c8c: 53 55 54 56  Palette3_MTiles .bulk   $53,$55,$54,$56         ;question block (coin)
8c90: 53 55 54 56                  .bulk   $53,$55,$54,$56         ;question block (power-up)
8c94: a5 a7 a6 a8                  .bulk   $a5,$a7,$a6,$a8         ;coin
8c98: c2 c4 c3 c5                  .bulk   $c2,$c4,$c3,$c5         ;underwater coin
8c9c: 57 59 58 5a                  .bulk   $57,$59,$58,$5a         ;empty block
8ca0: 7b 7d 7c 7e                  .bulk   $7b,$7d,$7c,$7e         ;axe
                   ; -----------------------------------------------------------------------------
                   ; VRAM BUFFER DATA FOR LOCATIONS IN PRG-ROM
                   WaterPaletteData
8ca4: 3f 00 20                     .bulk   $3f,$00,$20
8ca7: 0f 15 12 25                  .bulk   $0f,$15,$12,$25
8cab: 0f 3a 1a 0f                  .bulk   $0f,$3a,$1a,$0f
8caf: 0f 30 12 0f                  .bulk   $0f,$30,$12,$0f
8cb3: 0f 27 12 0f                  .bulk   $0f,$27,$12,$0f
8cb7: 22 16 27 18                  .bulk   $22,$16,$27,$18
8cbb: 0f 10 30 27                  .bulk   $0f,$10,$30,$27
8cbf: 0f 16 30 27                  .bulk   $0f,$16,$30,$27
8cc3: 0f 0f 30 10                  .bulk   $0f,$0f,$30,$10
8cc7: 00                           .bulk   $00
                   GroundPaletteData
8cc8: 3f 00 20                     .bulk   $3f,$00,$20
8ccb: 0f 29 1a 0f                  .bulk   $0f,$29,$1a,$0f
8ccf: 0f 36 17 0f                  .bulk   $0f,$36,$17,$0f
8cd3: 0f 30 21 0f                  .bulk   $0f,$30,$21,$0f
8cd7: 0f 27 17 0f                  .bulk   $0f,$27,$17,$0f
8cdb: 0f 16 27 18                  .bulk   $0f,$16,$27,$18
8cdf: 0f 1a 30 27                  .bulk   $0f,$1a,$30,$27
8ce3: 0f 16 30 27                  .bulk   $0f,$16,$30,$27
8ce7: 0f 0f 36 17                  .bulk   $0f,$0f,$36,$17
8ceb: 00                           .bulk   $00
                   UndergroundPaletteData
8cec: 3f 00 20                     .bulk   $3f,$00,$20
8cef: 0f 29 1a 09                  .bulk   $0f,$29,$1a,$09
8cf3: 0f 3c 1c 0f                  .bulk   $0f,$3c,$1c,$0f
8cf7: 0f 30 21 1c                  .bulk   $0f,$30,$21,$1c
8cfb: 0f 27 17 1c                  .bulk   $0f,$27,$17,$1c
8cff: 0f 16 27 18                  .bulk   $0f,$16,$27,$18
8d03: 0f 1c 36 17                  .bulk   $0f,$1c,$36,$17
8d07: 0f 16 30 27                  .bulk   $0f,$16,$30,$27
8d0b: 0f 0c 3c 1c                  .bulk   $0f,$0c,$3c,$1c
8d0f: 00                           .bulk   $00
                   CastlePaletteData
8d10: 3f 00 20                     .bulk   $3f,$00,$20
8d13: 0f 30 10 00                  .bulk   $0f,$30,$10,$00
8d17: 0f 30 10 00                  .bulk   $0f,$30,$10,$00
8d1b: 0f 30 16 00                  .bulk   $0f,$30,$16,$00
8d1f: 0f 27 17 00                  .bulk   $0f,$27,$17,$00
8d23: 0f 16 27 18                  .bulk   $0f,$16,$27,$18
8d27: 0f 1c 36 17                  .bulk   $0f,$1c,$36,$17
8d2b: 0f 16 30 27                  .bulk   $0f,$16,$30,$27
8d2f: 0f 00 30 10                  .bulk   $0f,$00,$30,$10
8d33: 00                           .bulk   $00
                   DaySnowPaletteData
8d34: 3f 00 04                     .bulk   $3f,$00,$04
8d37: 22 30 00 10                  .bulk   $22,$30,$00,$10
8d3b: 00                           .bulk   $00
                   NightSnowPaletteData
8d3c: 3f 00 04                     .bulk   $3f,$00,$04
8d3f: 0f 30 00 10                  .bulk   $0f,$30,$00,$10
8d43: 00                           .bulk   $00
                   MushroomPaletteData
8d44: 3f 00 04                     .bulk   $3f,$00,$04
8d47: 22 27 16 0f                  .bulk   $22,$27,$16,$0f
8d4b: 00                           .bulk   $00
                   BowserPaletteData
8d4c: 3f 14 04                     .bulk   $3f,$14,$04
8d4f: 0f 1a 30 27+                 .bulk   $0f,$1a,$30,$27,$00
                   ; "THANK YOU MARIO"
                   MarioThanksMessage
8d54: 25 48 10                     .bulk   $25,$48,$10
8d57: 1d 11 0a 17+                 .bulk   $1d,$11,$0a,$17,$14,$24
8d5d: 22 18 1e 24                  .bulk   $22,$18,$1e,$24
8d61: 16 0a 1b 12+                 .bulk   $16,$0a,$1b,$12,$18,$2b
8d67: 00                           .dd1    $00
                   ; THANK YOU LUIGI
                   LuigiThanksMessage
8d68: 25 48 10                     .bulk   $25,$48,$10
8d6b: 1d 11 0a 17+                 .bulk   $1d,$11,$0a,$17,$14,$24
8d71: 22 18 1e 24                  .bulk   $22,$18,$1e,$24
8d75: 15 1e 12 10+                 .bulk   $15,$1e,$12,$10,$12,$2b
8d7b: 00                           .dd1    $00
                   ; "BUT OUR PRINCESS IS IN"
                   MushroomRetainerSaved
8d7c: 25 c5 16                     .bulk   $25,$c5,$16
8d7f: 0b 1e 1d 24+                 .bulk   $0b,$1e,$1d,$24,$18,$1e,$1b,$24
8d87: 19 1b 12 17+                 .bulk   $19,$1b,$12,$17,$0c,$0e,$1c,$1c,$24
8d90: 12 1c 24 12+                 .bulk   $12,$1c,$24,$12,$17
                   ; "ANOTHER CASTLE!"
8d95: 26 05 0f                     .bulk   $26,$05,$0f
8d98: 0a 17 18 1d+                 .bulk   $0a,$17,$18,$1d,$11,$0e,$1b,$24
8da0: 0c 0a 1c 1d+                 .bulk   $0c,$0a,$1c,$1d,$15,$0e,$2b,$00
                   ; "YOUR QUEST IS OVER."
8da8: 25 a7 13     PrincessSaved1  .bulk   $25,$a7,$13
8dab: 22 18 1e 1b+                 .bulk   $22,$18,$1e,$1b,$24
8db0: 1a                           .dd1    $1a
8db1: 1e 0e 1c 1d+                 .bulk   $1e,$0e,$1c,$1d,$24
8db6: 12 1c 24 18+                 .bulk   $12,$1c,$24,$18,$1f,$0e,$1b,$af
8dbe: 00                           .dd1    $00
                   ; "WE PRESENT YOU A NEW QUEST."
8dbf: 25 e3 1b     PrincessSaved2  .bulk   $25,$e3,$1b
8dc2: 20 0e 24                     .bulk   $20,$0e,$24
8dc5: 19 1b 0e 1c+                 .bulk   $19,$1b,$0e,$1c,$0e,$17,$1d,$24
8dcd: 22 18 1e 24+                 .bulk   $22,$18,$1e,$24,$0a,$24,$17,$0e,$20,$24
8dd7: 1a 1e 0e 1c+                 .bulk   $1a,$1e,$0e,$1c,$1d,$af
8ddd: 00                           .dd1    $00
                   ; "PUSH BUTTON B"
                   WorldSelectMessage1
8dde: 26 4a 0d                     .bulk   $26,$4a,$0d
8de1: 19 1e 1c 11+                 .bulk   $19,$1e,$1c,$11,$24
8de6: 0b 1e 1d 1d+                 .bulk   $0b,$1e,$1d,$1d,$18,$17,$24,$0b
8dee: 00                           .dd1    $00
                   ; "TO SELECT A WORLD"
                   WorldSelectMessage2
8def: 26 88 11                     .bulk   $26,$88,$11
8df2: 1d 18 24 1c+                 .bulk   $1d,$18,$24,$1c,$0e,$15,$0e,$0c,$1d,$24
8dfc: 0a 24 20 18+                 .bulk   $0a,$24,$20,$18,$1b,$15,$0d
8e03: 00                           .dd1    $00

                   ; -----------------------------------------------------------------------------
                   ; $04 - address low to jump address
                   ; $05 - address high to jump address
                   ; $06 - jump address low
                   ; $07 - jump address high
8e04: 0a           JumpEngine      asl     A                       ;shift bit from contents of A
8e05: a8                           tay
8e06: 68                           pla                             ;pull saved return address from stack
8e07: 85 04                        sta     $04                     ;save to indirect
8e09: 68                           pla
8e0a: 85 05                        sta     $05
8e0c: c8                           iny
8e0d: b1 04                        lda     ($04),y                 ;load pointer from indirect
8e0f: 85 06                        sta     $06                     ;note that if an RTS is performed in next routine
8e11: c8                           iny                             ;it will return to the execution before the sub
8e12: b1 04                        lda     ($04),y                 ; that called this routine
8e14: 85 07                        sta     $07
8e16: 6c 06 00                     jmp     ($0006)                 ;jump to the address we loaded

                   ; -----------------------------------------------------------------------------
                   InitializeNameTables
8e19: ad 02 20                     lda     PPUSTATUS               ;reset flip-flop
8e1c: ad 78 07                     lda     Mirror_PPU_CTRL_REG1    ;load mirror of ppu reg $2000
8e1f: 09 10                        ora     #%00010000              ;set sprites for first 4k and background for second 4k
8e21: 29 f0                        and     #%11110000              ;clear rest of lower nybble, leave higher alone
8e23: 20 ed 8e                     jsr     WritePPUReg1
8e26: a9 24                        lda     #$24                    ;set vram address to start of name table 1
8e28: 20 2d 8e                     jsr     WriteNTAddr
8e2b: a9 20                        lda     #$20                    ;and then set it to name table 0
8e2d: 8d 06 20     WriteNTAddr     sta     PPUADDR
8e30: a9 00                        lda     #$00
8e32: 8d 06 20                     sta     PPUADDR
8e35: a2 04                        ldx     #$04                    ;clear name table with blank tile #24
8e37: a0 c0                        ldy     #$c0
8e39: a9 24                        lda     #$24
8e3b: 8d 07 20     InitNTLoop      sta     PPUDATA                 ;count out exactly 768 tiles
8e3e: 88                           dey
8e3f: d0 fa                        bne     InitNTLoop
8e41: ca                           dex
8e42: d0 f7                        bne     InitNTLoop
8e44: a0 40                        ldy     #64                     ;now to clear the attribute table (with zero this time)
8e46: 8a                           txa
8e47: 8d 00 03                     sta     VRAM_Buffer1_Offset     ;init vram buffer 1 offset
8e4a: 8d 01 03                     sta     VRAM_Buffer1            ;init vram buffer 1
8e4d: 8d 07 20     InitATLoop      sta     PPUDATA
8e50: 88                           dey
8e51: d0 fa                        bne     InitATLoop
8e53: 8d 3f 07                     sta     HorizontalScroll        ;reset scroll variables
8e56: 8d 40 07                     sta     VerticalScroll
8e59: 4c e6 8e                     jmp     InitScroll              ;initialize scroll registers to zero

                   ; -----------------------------------------------------------------------------
                   ; $00 - temp joypad bit
8e5c: a9 01        ReadJoypads     lda     #$01                    ;reset and clear strobe of joypad ports
8e5e: 8d 16 40                     sta     JOY1
8e61: 4a                           lsr     A
8e62: aa                           tax                             ;start with joypad 1's port
8e63: 8d 16 40                     sta     JOY1
8e66: 20 6a 8e                     jsr     ReadPortBits
8e69: e8                           inx                             ;increment for joypad 2's port
8e6a: a0 08        ReadPortBits    ldy     #$08
8e6c: 48           PortLoop        pha                             ;push previous bit onto stack
8e6d: bd 16 40                     lda     JOY1,x                  ;read current bit on joypad port
8e70: 85 00                        sta     $00                     ;check d1 and d0 of port output
8e72: 4a                           lsr     A                       ;this is necessary on the old
8e73: 05 00                        ora     $00                     ; famicom systems in japan
8e75: 4a                           lsr     A
8e76: 68                           pla                             ;read bits from stack
8e77: 2a                           rol     A                       ;rotate bit from carry flag
8e78: 88                           dey
8e79: d0 f1                        bne     PortLoop                ;count down bits left
8e7b: 9d fc 06                     sta     SavedJoypad1Bits,x      ;save controller status here always
8e7e: 48                           pha
8e7f: 29 30                        and     #%00110000              ;check for select or start
8e81: 3d 4a 07                     and     JoypadBitMask,x         ;if neither saved state nor current state
8e84: f0 07                        beq     Save8Bits               ; have any of these two set, branch
8e86: 68                           pla
8e87: 29 cf                        and     #%11001111              ;otherwise store without select
8e89: 9d fc 06                     sta     SavedJoypad1Bits,x      ; or start bits and leave
8e8c: 60                           rts

8e8d: 68           Save8Bits       pla
8e8e: 9d 4a 07                     sta     JoypadBitMask,x         ;save with all bits in another place and leave
8e91: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - vram buffer address table low
                   ; $01 - vram buffer address table high
                   WriteBufferToScreen
8e92: 8d 06 20                     sta     PPUADDR                 ;store high byte of vram address
8e95: c8                           iny
8e96: b1 00                        lda     ($00),y                 ;load next byte (second)
8e98: 8d 06 20                     sta     PPUADDR                 ;store low byte of vram address
8e9b: c8                           iny
8e9c: b1 00                        lda     ($00),y                 ;load next byte (third)
8e9e: 0a                           asl     A                       ;shift to left and save in stack
8e9f: 48                           pha
8ea0: ad 78 07                     lda     Mirror_PPU_CTRL_REG1    ;load mirror of $2000,
8ea3: 09 04                        ora     #%00000100              ;set ppu to increment by 32 by default
8ea5: b0 02                        bcs     SetupWrites             ;if d7 of third byte was clear, ppu will
8ea7: 29 fb                        and     #%11111011              ;only increment by 1
8ea9: 20 ed 8e     SetupWrites     jsr     WritePPUReg1            ;write to register
8eac: 68                           pla                             ;pull from stack and shift to left again
8ead: 0a                           asl     A
8eae: 90 03                        bcc     GetLength               ;if d6 of third byte was clear, do not repeat byte
8eb0: 09 02                        ora     #%00000010              ;otherwise set d1 and increment Y
8eb2: c8                           iny
8eb3: 4a           GetLength       lsr     A                       ;shift back to the right to get proper length
8eb4: 4a                           lsr     A                       ;note that d1 will now be in carry
8eb5: aa                           tax
8eb6: b0 01        OutputToVRAM    bcs     RepeatByte              ;if carry set, repeat loading the same byte
8eb8: c8                           iny                             ;otherwise increment Y to load next byte
8eb9: b1 00        RepeatByte      lda     ($00),y                 ;load more data from buffer and write to vram
8ebb: 8d 07 20                     sta     PPUDATA
8ebe: ca                           dex                             ;done writing?
8ebf: d0 f5                        bne     OutputToVRAM
8ec1: 38                           sec
8ec2: 98                           tya
8ec3: 65 00                        adc     $00                     ;add end length plus one to the indirect at $00
8ec5: 85 00                        sta     $00                     ; to allow this routine to read another set of updates
8ec7: a9 00                        lda     #$00
8ec9: 65 01                        adc     $01
8ecb: 85 01                        sta     $01
8ecd: a9 3f                        lda     #$3f                    ;sets vram address to $3f00
8ecf: 8d 06 20                     sta     PPUADDR
8ed2: a9 00                        lda     #$00
8ed4: 8d 06 20                     sta     PPUADDR
8ed7: 8d 06 20                     sta     PPUADDR                 ;then reinitializes it for some reason
8eda: 8d 06 20                     sta     PPUADDR
8edd: ae 02 20     UpdateScreen    ldx     PPUSTATUS               ;reset flip-flop
8ee0: a0 00                        ldy     #$00                    ;load first byte from indirect as a pointer
8ee2: b1 00                        lda     ($00),y
8ee4: d0 ac                        bne     WriteBufferToScreen     ;if byte is zero we have no further updates to make here
8ee6: 8d 05 20     InitScroll      sta     PPUSCROLL               ;store contents of A into scroll registers
8ee9: 8d 05 20                     sta     PPUSCROLL               ;and end whatever subroutine led us here
8eec: 60                           rts

                   ; -----------------------------------------------------------------------------
8eed: 8d 00 20     WritePPUReg1    sta     PPUCTRL                 ;write contents of A to PPU register 1
8ef0: 8d 78 07                     sta     Mirror_PPU_CTRL_REG1    ;and its mirror
8ef3: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store status bar nybbles
                   ; $02 - used as temp vram offset
                   ; $03 - used to store length of status bar number
                   ; 
                   ; status bar name table offset and length data
8ef4: f0 06        StatusBarData   .bulk   $f0,$06                 ;top score display on title screen
8ef6: 62 06                        .bulk   $62,$06                 ;player score
8ef8: 62 06                        .bulk   $62,$06
8efa: 6d 02                        .bulk   $6d,$02                 ;coin tally
8efc: 6d 02                        .bulk   $6d,$02
8efe: 7a 03                        .bulk   $7a,$03                 ;game timer
8f00: 06 0c 12 18+ StatusBarOffset .bulk   $06,$0c,$12,$18,$1e,$24

                   PrintStatusBarNumbers
8f06: 85 00                        sta     $00                     ;store player-specific offset
8f08: 20 11 8f                     jsr     OutputNumbers           ;use first nybble to print the coin display
8f0b: a5 00                        lda     $00                     ;move high nybble to low
8f0d: 4a                           lsr     A                       ;and print to score display
8f0e: 4a                           lsr     A
8f0f: 4a                           lsr     A
8f10: 4a                           lsr     A
8f11: 18           OutputNumbers   clc                             ;add 1 to low nybble
8f12: 69 01                        adc     #$01
8f14: 29 0f                        and     #%00001111              ;mask out high nybble
8f16: c9 06                        cmp     #$06
8f18: b0 44                        bcs     ExitOutputN
8f1a: 48                           pha                             ;save incremented value to stack for now and
8f1b: 0a                           asl     A                       ;shift to left and use as offset
8f1c: a8                           tay
8f1d: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;get current buffer pointer
8f20: a9 20                        lda     #$20                    ;put at top of screen by default
8f22: c0 00                        cpy     #$00                    ;are we writing top score on title screen?
8f24: d0 02                        bne     SetupNums
8f26: a9 22                        lda     #$22                    ;if so, put further down on the screen
8f28: 9d 01 03     SetupNums       sta     VRAM_Buffer1,x
8f2b: b9 f4 8e                     lda     StatusBarData,y         ;write low vram address and length of thing
8f2e: 9d 02 03                     sta     VRAM_Buffer1+1,x        ;we're printing to the buffer
8f31: b9 f5 8e                     lda     StatusBarData+1,y
8f34: 9d 03 03                     sta     VRAM_Buffer1+2,x
8f37: 85 03                        sta     $03                     ;save length byte in counter
8f39: 86 02                        stx     $02                     ;and buffer pointer elsewhere for now
8f3b: 68                           pla                             ;pull original incremented value from stack
8f3c: aa                           tax
8f3d: bd 00 8f                     lda     StatusBarOffset,x       ;load offset to value we want to write
8f40: 38                           sec
8f41: f9 f5 8e                     sbc     StatusBarData+1,y       ;subtract from length byte we read before
8f44: a8                           tay                             ;use value as offset to display digits
8f45: a6 02                        ldx     $02
8f47: b9 d7 07     DigitPLoop      lda     TopScoreDisplay,y       ;write digits to the buffer
8f4a: 9d 04 03                     sta     VRAM_Buffer1+3,x
8f4d: e8                           inx
8f4e: c8                           iny
8f4f: c6 03                        dec     $03                     ;do this until all the digits are written
8f51: d0 f4                        bne     DigitPLoop
8f53: a9 00                        lda     #$00                    ;put null terminator at end
8f55: 9d 04 03                     sta     VRAM_Buffer1+3,x
8f58: e8                           inx                             ;increment buffer pointer by 3
8f59: e8                           inx
8f5a: e8                           inx
8f5b: 8e 00 03                     stx     VRAM_Buffer1_Offset     ;store it in case we want to use it again
8f5e: 60           ExitOutputN     rts

                   ; -----------------------------------------------------------------------------
                   DigitsMathRoutine
8f5f: ad 70 07                     lda     OperMode                ;check mode of operation
8f62: c9 00                        cmp     #$00
8f64: f0 16                        beq     EraseDMods              ;if in title screen mode, branch to lock score
8f66: a2 05                        ldx     #$05
8f68: bd 34 01     AddModLoop      lda     DigitModifier,x         ;load digit amount to increment
8f6b: 18                           clc
8f6c: 79 d7 07                     adc     TopScoreDisplay,y       ;add to current digit
8f6f: 30 16                        bmi     BorrowOne               ;if result is a negative number, branch to subtract
8f71: c9 0a                        cmp     #$0a
8f73: b0 19                        bcs     CarryOne                ;if digit greater than $09, branch to add
8f75: 99 d7 07     StoreNewD       sta     TopScoreDisplay,y       ;store as new score or game timer digit
8f78: 88                           dey                             ;move onto next digits in score or game timer
8f79: ca                           dex                             ;and digit amounts to increment
8f7a: 10 ec                        bpl     AddModLoop              ;loop back if we're not done yet
8f7c: a9 00        EraseDMods      lda     #$00                    ;store zero here
8f7e: a2 06                        ldx     #$06                    ;start with the last digit
8f80: 9d 33 01     EraseMLoop      sta     DigitModifier-1,x       ;initialize the digit amounts to increment
8f83: ca                           dex
8f84: 10 fa                        bpl     EraseMLoop              ;do this until they're all reset, then leave
8f86: 60                           rts

8f87: de 33 01     BorrowOne       dec     DigitModifier-1,x       ;decrement the previous digit, then put $09 in
8f8a: a9 09                        lda     #$09                    ; the game timer digit we're currently on to "borrow
8f8c: d0 e7                        bne     StoreNewD               ; the one", then do an unconditional branch back

8f8e: 38           CarryOne        sec                             ;subtract ten from our digit to make it a
8f8f: e9 0a                        sbc     #$0a                    ; proper BCD number, then increment the digit
8f91: fe 33 01                     inc     DigitModifier-1,x       ; preceding current digit to "carry the one" properly
8f94: 4c 75 8f                     jmp     StoreNewD               ;go back to just after we branched here

                   ; -----------------------------------------------------------------------------
8f97: a2 05        UpdateTopScore  ldx     #$05                    ;start with mario's score
8f99: 20 9e 8f                     jsr     TopScoreCheck
8f9c: a2 0b                        ldx     #$0b                    ;now do luigi's score
8f9e: a0 05        TopScoreCheck   ldy     #$05                    ;start with the lowest digit
8fa0: 38                           sec
8fa1: bd dd 07     GetScoreDiff    lda     ScoreAndCoinDisplay,x   ;subtract each player digit from each high score digit
8fa4: f9 d7 07                     sbc     TopScoreDisplay,y       ; from lowest to highest, if any top score digit exceeds
8fa7: ca                           dex                             ; any player digit, borrow will be set until a subsequent
8fa8: 88                           dey                             ; subtraction clears it (player digit is higher than top)
8fa9: 10 f6                        bpl     GetScoreDiff
8fab: 90 0e                        bcc     NoTopSc                 ;check to see if borrow is still set, if so, no new high score
8fad: e8                           inx                             ;increment X and Y once to the start of the score
8fae: c8                           iny
8faf: bd dd 07     CopyScore       lda     ScoreAndCoinDisplay,x   ;store player's score digits into high score memory area
8fb2: 99 d7 07                     sta     TopScoreDisplay,y
8fb5: e8                           inx
8fb6: c8                           iny
8fb7: c0 06                        cpy     #$06                    ;do this until we have stored them all
8fb9: 90 f4                        bcc     CopyScore
8fbb: 60           NoTopSc         rts

                   ; -----------------------------------------------------------------------------
                   DefaultSprOffsets
8fbc: 04 30 48 60+                 .bulk   $04,$30,$48,$60,$78,$90,$a8,$c0,$d8,$e8,$24,$f8,$fc,$28,$2c
8fcb: 18 ff 23 58  Sprite0Data     .bulk   $18,$ff,$23,$58

                   ; -----------------------------------------------------------------------------
8fcf: a0 6f        InitializeGame  ldy     #$6f                    ;clear all memory as in initialization procedure,
8fd1: 20 cc 90                     jsr     InitializeMemory        ; but this time, clear only as far as $076f
8fd4: a0 1f                        ldy     #$1f
8fd6: 99 b0 07     ClrSndLoop      sta     SoundMemory,y           ;clear out memory used
8fd9: 88                           dey                             ; by the sound engines
8fda: 10 fa                        bpl     ClrSndLoop
8fdc: a9 18                        lda     #$18                    ;set demo timer
8fde: 8d a2 07                     sta     DemoTimer
8fe1: 20 03 9c                     jsr     LoadAreaPointer
                   ; 
8fe4: a0 4b        InitializeArea  ldy     #$4b                    ;clear all memory again, only as far as $074b
8fe6: 20 cc 90                     jsr     InitializeMemory        ;this is only necessary if branching from
8fe9: a2 21                        ldx     #$21
8feb: a9 00                        lda     #$00
8fed: 9d 80 07     ClrTimersLoop   sta     Timers,x                ;clear out memory between
8ff0: ca                           dex                             ; $0780 and $07a1
8ff1: 10 fa                        bpl     ClrTimersLoop
8ff3: ad 5b 07                     lda     HalfwayPage
8ff6: ac 52 07                     ldy     AltEntranceControl      ;if AltEntranceControl not set, use halfway page, if any found
8ff9: f0 03                        beq     StartPage
8ffb: ad 51 07                     lda     EntrancePage            ;otherwise use saved entry page number here
8ffe: 8d 1a 07     StartPage       sta     ScreenLeft_PageLoc      ;set as value here
9001: 8d 25 07                     sta     CurrentPageLoc          ;also set as current page
9004: 8d 28 07                     sta     BackloadingFlag         ;set flag here if halfway page or saved entry page number found
9007: 20 38 b0                     jsr     GetScreenPosition       ;get pixel coordinates for screen borders
900a: a0 20                        ldy     #$20                    ;if on odd numbered page, use $2480 as start of rendering
900c: 29 01                        and     #%00000001              ;otherwise use $2080, this address used later as name table
900e: f0 02                        beq     SetInitNTHigh           ; address for rendering of game area
9010: a0 24                        ldy     #$24
9012: 8c 20 07     SetInitNTHigh   sty     CurrentNTAddr_High      ;store name table address
9015: a0 80                        ldy     #$80
9017: 8c 21 07                     sty     CurrentNTAddr_Low
901a: 0a                           asl     A                       ;store LSB of page number in high nybble
901b: 0a                           asl     A                       ; of block buffer column position
901c: 0a                           asl     A
901d: 0a                           asl     A
901e: 8d a0 06                     sta     BlockBufferColumnPos
9021: ce 30 07                     dec     AreaObjectLength        ;set area object lengths for all empty
9024: ce 31 07                     dec     AreaObjectLength+1
9027: ce 32 07                     dec     AreaObjectLength+2
902a: a9 0b                        lda     #$0b                    ;set value for renderer to update 12 column sets
902c: 8d 1e 07                     sta     ColumnSets              ;12 column sets = 24 metatile columns = 1 1/2 screens
902f: 20 22 9c                     jsr     GetAreaDataAddrs        ;get enemy and level addresses and load header
9032: ad 6a 07                     lda     PrimaryHardMode         ;check to see if primary hard mode has been activated
9035: d0 10                        bne     SetSecHard              ;if so, activate the secondary no matter where we're at
9037: ad 5f 07                     lda     WorldNumber             ;otherwise check world number
903a: c9 04                        cmp     #World5                 ;if less than 5, do not activate secondary
903c: 90 0c                        bcc     CheckHalfway
903e: d0 07                        bne     SetSecHard              ;if not equal to, then world > 5, thus activate
9040: ad 5c 07                     lda     LevelNumber             ;otherwise, world 5, so check level number
9043: c9 02                        cmp     #Level3                 ;if 1 or 2, do not set secondary hard mode flag
9045: 90 03                        bcc     CheckHalfway
9047: ee cc 06     SetSecHard      inc     SecondaryHardMode       ;set secondary hard mode flag for areas 5-3 and beyond
904a: ad 5b 07     CheckHalfway    lda     HalfwayPage
904d: f0 05                        beq     DoneInitArea
904f: a9 02                        lda     #$02                    ;if halfway page set, overwrite start position from header
9051: 8d 10 07                     sta     PlayerEntranceCtrl
9054: a9 80        DoneInitArea    lda     #Silence                ;silence music
9056: 85 fb                        sta     AreaMusicQueue
9058: a9 01                        lda     #$01                    ;disable screen output
905a: 8d 74 07                     sta     DisableScreenFlag
905d: ee 72 07                     inc     OperMode_Task           ;increment one of the modes
9060: 60                           rts

                   ; -----------------------------------------------------------------------------
                   PrimaryGameSetup
9061: a9 01                        lda     #$01
9063: 8d 57 07                     sta     FetchNewGameTimerFlag   ;set flag to load game timer from header
9066: 8d 54 07                     sta     PlayerSize              ;set player's size to small
9069: a9 02                        lda     #$02
906b: 8d 5a 07                     sta     NumberOfLives           ;give each player three lives
906e: 8d 61 07                     sta     OffScr_NumberofLives
                   ; 
                   SecondaryGameSetup
9071: a9 00                        lda     #$00
9073: 8d 74 07                     sta     DisableScreenFlag       ;enable screen output
9076: a8                           tay
9077: 99 00 03     ClearVRLoop     sta     VRAM_Buffer1-1,y        ;clear buffer at $0300-$03ff
907a: c8                           iny
907b: d0 fa                        bne     ClearVRLoop
907d: 8d 59 07                     sta     GameTimerExpiredFlag    ;clear game timer exp flag
9080: 8d 69 07                     sta     DisableIntermediate     ;clear skip lives display flag
9083: 8d 28 07                     sta     BackloadingFlag         ;clear value here
9086: a9 ff                        lda     #$ff
9088: 8d a0 03                     sta     BalPlatformAlignment    ;initialize balance platform assignment flag
908b: ad 1a 07                     lda     ScreenLeft_PageLoc      ;get left side page location
908e: 4e 78 07                     lsr     Mirror_PPU_CTRL_REG1    ;shift LSB of ppu register #1 mirror out
9091: 29 01                        and     #$01                    ;mask out all but LSB of page location
9093: 6a                           ror     A                       ;rotate LSB of page location into carry then onto mirror
9094: 2e 78 07                     rol     Mirror_PPU_CTRL_REG1    ;this is to set the proper PPU name table
9097: 20 ed 90                     jsr     GetAreaMusic            ;load proper music into queue
909a: a9 38                        lda     #$38                    ;load sprite shuffle amounts to be used later
909c: 8d e3 06                     sta     SprShuffleAmt+2
909f: a9 48                        lda     #$48
90a1: 8d e2 06                     sta     SprShuffleAmt+1
90a4: a9 58                        lda     #$58
90a6: 8d e1 06                     sta     SprShuffleAmt
90a9: a2 0e                        ldx     #$0e                    ;load default OAM offsets into $06e4-$06f2
90ab: bd bc 8f     ShufAmtLoop     lda     DefaultSprOffsets,x
90ae: 9d e4 06                     sta     SprDataOffset,x
90b1: ca                           dex                             ;do this until they're all set
90b2: 10 f7                        bpl     ShufAmtLoop
90b4: a0 03                        ldy     #$03                    ;set up sprite #0
90b6: b9 cb 8f     ISpr0Loop       lda     Sprite0Data,y
90b9: 99 00 02                     sta     Sprite_Data,y
90bc: 88                           dey
90bd: 10 f7                        bpl     ISpr0Loop
90bf: 20 af 92                     jsr     DoNothing2              ;these jsrs doesn't do anything useful
90c2: 20 aa 92                     jsr     DoNothing1
90c5: ee 22 07                     inc     Sprite0HitDetectFlag    ;set sprite #0 check flag
90c8: ee 72 07                     inc     OperMode_Task           ;increment to next task
90cb: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $06 - RAM address low
                   ; $07 - RAM address high
                   InitializeMemory
90cc: a2 07                        ldx     #$07                    ;set initial high byte to $0700-$07ff
90ce: a9 00                        lda     #$00                    ;set initial low byte to start of page (at $00 of page)
90d0: 85 06                        sta     $06
90d2: 86 07        InitPageLoop    stx     $07
90d4: e0 01        InitByteLoop    cpx     #$01                    ;check to see if we're on the stack ($0100-$01ff)
90d6: d0 04                        bne     InitByte                ;if not, go ahead anyway
90d8: c0 60                        cpy     #$60                    ;otherwise, check to see if we're at $0160-$01ff
90da: b0 02                        bcs     SkipByte                ;if so, skip write
90dc: 91 06        InitByte        sta     ($06),y                 ;otherwise, initialize byte with current low byte in Y
90de: 88           SkipByte        dey
90df: c0 ff                        cpy     #$ff                    ;do this until all bytes in page have been erased
90e1: d0 f1                        bne     InitByteLoop
90e3: ca                           dex                             ;go onto the next page
90e4: 10 ec                        bpl     InitPageLoop            ;do this until all pages of memory have been erased
90e6: 60                           rts

                   ; -----------------------------------------------------------------------------
90e7: 02           MusicSelectData .dd1    WaterMusic
90e8: 01                           .dd1    GroundMusic
90e9: 04                           .dd1    UndergroundMusic
90ea: 08                           .dd1    CastleMusic
90eb: 10                           .dd1    CloudMusic
90ec: 20                           .dd1    PipeIntroMusic

90ed: ad 70 07     GetAreaMusic    lda     OperMode                ;if in title screen mode, leave
90f0: f0 23                        beq     ExitGetM
90f2: ad 52 07                     lda     AltEntranceControl      ;check for specific alternate mode of entry
90f5: c9 02                        cmp     #$02                    ;if found, branch without checking starting position
90f7: f0 0d                        beq     ChkAreaType             ; from area object data header
90f9: a0 05                        ldy     #$05                    ;select music for pipe intro scene by default
90fb: ad 10 07                     lda     PlayerEntranceCtrl      ;check value from level header for certain values
90fe: c9 06                        cmp     #$06
9100: f0 0e                        beq     StoreMusic              ;load music for pipe intro scene if header
9102: c9 07                        cmp     #$07                    ;start position either value $06 or $07
9104: f0 0a                        beq     StoreMusic
9106: ac 4e 07     ChkAreaType     ldy     AreaType                ;load area type as offset for music bit
9109: ad 43 07                     lda     CloudTypeOverride
910c: f0 02                        beq     StoreMusic              ;check for cloud type override
910e: a0 04                        ldy     #$04                    ;select music for cloud type level if found
9110: b9 e7 90     StoreMusic      lda     MusicSelectData,y       ;otherwise select appropriate music for level type
9113: 85 fb                        sta     AreaMusicQueue          ;store in queue and leave
9115: 60           ExitGetM        rts

                   ; -----------------------------------------------------------------------------
                   PlayerStarting_X_Pos
9116: 28 18 38 28                  .bulk   $28,$18,$38,$28
911a: 08 00        AltYPosOffset   .bulk   $08,$00
                   PlayerStarting_Y_Pos
911c: 00 20 b0 50+                 .bulk   $00,$20,$b0,$50,$00,$00,$b0,$b0,$f0
                   PlayerBGPriorityData
9125: 00 20 00 00+                 .bulk   $00,$20,$00,$00,$00,$00,$00,$00
912d: 20           GameTimerData   .dd1    $20                     ;dummy byte, used as part of bg priority data
912e: 04 03 02                     .bulk   $04,$03,$02

                   Entrance_GameTimerSetup
9131: ad 1a 07                     lda     ScreenLeft_PageLoc      ;set current page for area objects
9134: 85 6d                        sta     Player_PageLoc          ; as page location for player
9136: a9 28                        lda     #$28                    ;store value here
9138: 8d 0a 07                     sta     VerticalForceDown       ;for fractional movement downwards if necessary
913b: a9 01                        lda     #$01                    ;set high byte of player position and
913d: 85 33                        sta     PlayerFacingDir         ;set facing direction so that player faces right
913f: 85 b5                        sta     Player_Y_HighPos
9141: a9 00                        lda     #$00                    ;set player state to on the ground by default
9143: 85 1d                        sta     Player_State
9145: ce 90 04                     dec     Player_CollisionBits    ;initialize player's collision bits
9148: a0 00                        ldy     #$00                    ;initialize halfway page
914a: 8c 5b 07                     sty     HalfwayPage
914d: ad 4e 07                     lda     AreaType                ;check area type
9150: d0 01                        bne     ChkStPos                ;if water type, set swimming flag, otherwise do not set
9152: c8                           iny
9153: 8c 04 07     ChkStPos        sty     SwimmingFlag
9156: ae 10 07                     ldx     PlayerEntranceCtrl      ;get starting position loaded from header
9159: ac 52 07                     ldy     AltEntranceControl      ;check alternate mode of entry flag for 0 or 1
915c: f0 07                        beq     SetStPos
915e: c0 01                        cpy     #$01
9160: f0 03                        beq     SetStPos
9162: be 18 91                     ldx     AltYPosOffset-2,y       ;if not 0 or 1, override $0710 with new offset in X
9165: b9 16 91     SetStPos        lda     PlayerStarting_X_Pos,y  ;load appropriate horizontal position
9168: 85 86                        sta     Player_X_Position       ; and vertical positions for the player, using
916a: bd 1c 91                     lda     PlayerStarting_Y_Pos,x  ; AltEntranceControl as offset for horizontal and either $0710
916d: 85 ce                        sta     Player_Y_Position       ; or value that overwrote $0710 as offset for vertical
916f: bd 25 91                     lda     PlayerBGPriorityData,x
9172: 8d c4 03                     sta     Player_SprAttrib        ;set player sprite attributes using offset in X
9175: 20 f1 85                     jsr     GetPlayerColors         ;get appropriate player palette
9178: ac 15 07                     ldy     GameTimerSetting        ;get timer control value from header
917b: f0 1a                        beq     ChkOverR                ;if set to zero, branch (do not use dummy byte for this)
917d: ad 57 07                     lda     FetchNewGameTimerFlag   ;do we need to set the game timer? if not, use 
9180: f0 15                        beq     ChkOverR                ; old game timer setting
9182: b9 2d 91                     lda     GameTimerData,y         ;if game timer is set and game timer flag is also set,
9185: 8d f8 07                     sta     GameTimerDisplay        ; use value of game timer control for first digit of game timer
9188: a9 01                        lda     #$01
918a: 8d fa 07                     sta     GameTimerDisplay+2      ;set last digit of game timer to 1
918d: 4a                           lsr     A
918e: 8d f9 07                     sta     GameTimerDisplay+1      ;set second digit of game timer
9191: 8d 57 07                     sta     FetchNewGameTimerFlag   ;clear flag for game timer reset
9194: 8d 9f 07                     sta     StarInvincibleTimer     ;clear star mario timer
9197: ac 58 07     ChkOverR        ldy     JoypadOverride          ;if controller bits not set, branch to skip this part
919a: f0 14                        beq     ChkSwimE
919c: a9 03                        lda     #$03                    ;set player state to climbing
919e: 85 1d                        sta     Player_State
91a0: a2 00                        ldx     #$00                    ;set offset for first slot, for block object
91a2: 20 84 bd                     jsr     InitBlock_XY_Pos
91a5: a9 f0                        lda     #$f0                    ;set vertical coordinate for block object
91a7: 85 d7                        sta     Block_Y_Position
91a9: a2 05                        ldx     #$05                    ;set offset in X for last enemy object buffer slot
91ab: a0 00                        ldy     #$00                    ;set offset in Y for object coordinates used earlier
91ad: 20 1e b9                     jsr     Setup_Vine              ;do a sub to grow vine
91b0: ac 4e 07     ChkSwimE        ldy     AreaType                ;if level not water-type,
91b3: d0 03                        bne     SetPESub                ; skip this subroutine
91b5: 20 0b b7                     jsr     SetupBubble             ;otherwise, execute sub to set up air bubbles
91b8: a9 07        SetPESub        lda     #$07                    ;set to run player entrance subroutine
91ba: 85 0e                        sta     GameEngineSubroutine    ; on the next frame of game engine
91bc: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; 
                   ; page numbers are in order from -1 to -4
                   HalfwayPageNybbles
91bd: 56 40                        .bulk   $56,$40
91bf: 65 70                        .bulk   $65,$70
91c1: 66 40                        .bulk   $66,$40
91c3: 66 40                        .bulk   $66,$40
91c5: 66 40                        .bulk   $66,$40
91c7: 66 60                        .bulk   $66,$60
91c9: 65 70                        .bulk   $65,$70
91cb: 00 00                        .bulk   $00,$00

91cd: ee 74 07     PlayerLoseLife  inc     DisableScreenFlag       ;disable screen and sprite 0 check
91d0: a9 00                        lda     #$00
91d2: 8d 22 07                     sta     Sprite0HitDetectFlag
91d5: a9 80                        lda     #Silence                ;silence music
91d7: 85 fc                        sta     EventMusicQueue
91d9: ce 5a 07                     dec     NumberOfLives           ;take one life from player
91dc: 10 0b                        bpl     StillInGame             ;if player still has lives, branch
91de: a9 00                        lda     #$00
91e0: 8d 72 07                     sta     OperMode_Task           ;initialize mode task,
91e3: a9 03                        lda     #GameOverModeValue      ;switch to game over mode
91e5: 8d 70 07                     sta     OperMode                ;and leave
91e8: 60                           rts

91e9: ad 5f 07     StillInGame     lda     WorldNumber             ;multiply world number by 2 and use
91ec: 0a                           asl     A                       ; as offset
91ed: aa                           tax
91ee: ad 5c 07                     lda     LevelNumber             ;if in area -3 or -4, increment
91f1: 29 02                        and     #$02                    ; offset by one byte, otherwise
91f3: f0 01                        beq     GetHalfway              ; leave offset alone
91f5: e8                           inx
91f6: bc bd 91     GetHalfway      ldy     HalfwayPageNybbles,x    ;get halfway page number with offset
91f9: ad 5c 07                     lda     LevelNumber             ;check area number's LSB
91fc: 4a                           lsr     A
91fd: 98                           tya                             ;if in area -2 or -4, use lower nybble
91fe: b0 04                        bcs     MaskHPNyb
9200: 4a                           lsr     A                       ;move higher nybble to lower if area
9201: 4a                           lsr     A                       ; number is -1 or -3
9202: 4a                           lsr     A
9203: 4a                           lsr     A
9204: 29 0f        MaskHPNyb       and     #%00001111              ;mask out all but lower nybble
9206: cd 1a 07                     cmp     ScreenLeft_PageLoc
9209: f0 04                        beq     SetHalfway              ;left side of screen must be at the halfway page,
920b: 90 02                        bcc     SetHalfway              ; otherwise player must start at the
920d: a9 00                        lda     #$00                    ;beginning of the level
920f: 8d 5b 07     SetHalfway      sta     HalfwayPage             ;store as halfway page for player
9212: 20 82 92                     jsr     TransposePlayers        ;switch players around if 2-player game
9215: 4c 64 92                     jmp     ContinueGame            ;continue the game

                   ; -----------------------------------------------------------------------------
9218: ad 72 07     GameOverMode    lda     OperMode_Task
921b: 20 04 8e                     jsr     JumpEngine

921e: 24 92                        .dd2    SetupGameOver
9220: 67 85                        .dd2    ScreenRoutines
9222: 37 92                        .dd2    RunGameOver

                   ; -----------------------------------------------------------------------------
9224: a9 00        SetupGameOver   lda     #$00                    ;reset screen routine task control for title screen, game,
9226: 8d 3c 07                     sta     ScreenRoutineTask       ; and game over modes
9229: 8d 22 07                     sta     Sprite0HitDetectFlag    ;disable sprite 0 check
922c: a9 02                        lda     #GameOverMusic
922e: 85 fc                        sta     EventMusicQueue         ;put game over music in secondary queue
9230: ee 74 07                     inc     DisableScreenFlag       ;disable screen output
9233: ee 72 07                     inc     OperMode_Task           ;set secondary mode to 1
9236: 60                           rts

                   ; -----------------------------------------------------------------------------
9237: a9 00        RunGameOver     lda     #$00                    ;reenable screen
9239: 8d 74 07                     sta     DisableScreenFlag
923c: ad fc 06                     lda     SavedJoypad1Bits        ;check controller for start pressed
923f: 29 10                        and     #Start_Button
9241: d0 05                        bne     TerminateGame
9243: ad a0 07                     lda     ScreenTimer             ;if not pressed, wait for
9246: d0 39                        bne     GameIsOn                ; screen timer to expire
9248: a9 80        TerminateGame   lda     #Silence                ;silence music
924a: 85 fc                        sta     EventMusicQueue
924c: 20 82 92                     jsr     TransposePlayers        ;check if other player can keep
924f: 90 13                        bcc     ContinueGame            ; going, and do so if possible
9251: ad 5f 07                     lda     WorldNumber             ;otherwise put world number of current
9254: 8d fd 07                     sta     ContinueWorld           ; player into secret continue function variable
9257: a9 00                        lda     #$00
9259: 0a                           asl     A                       ;residual ASL instruction
925a: 8d 72 07                     sta     OperMode_Task           ;reset all modes to title screen and
925d: 8d a0 07                     sta     ScreenTimer             ; leave
9260: 8d 70 07                     sta     OperMode
9263: 60                           rts

9264: 20 03 9c     ContinueGame    jsr     LoadAreaPointer         ;update level pointer with
9267: a9 01                        lda     #$01                    ; actual world and area numbers, then
9269: 8d 54 07                     sta     PlayerSize              ; reset player's size, status, and
926c: ee 57 07                     inc     FetchNewGameTimerFlag   ; set game timer flag to reload
926f: a9 00                        lda     #$00                    ; game timer from header
9271: 8d 47 07                     sta     TimerControl            ;also set flag for timers to count again
9274: 8d 56 07                     sta     PlayerStatus
9277: 85 0e                        sta     GameEngineSubroutine    ;reset task for game core
9279: 8d 72 07                     sta     OperMode_Task           ;set modes and leave
927c: a9 01                        lda     #$01                    ;if in game over mode, switch back to
927e: 8d 70 07                     sta     OperMode                ; game mode, because game is still on
9281: 60           GameIsOn        rts

                   TransposePlayers
9282: 38                           sec                             ;set carry flag by default to end game
9283: ad 7a 07                     lda     NumberOfPlayers         ;if only a 1 player game, leave
9286: f0 21                        beq     ExTrans
9288: ad 61 07                     lda     OffScr_NumberofLives    ;does offscreen player have any lives left?
928b: 30 1c                        bmi     ExTrans                 ;branch if not
928d: ad 53 07                     lda     CurrentPlayer           ;invert bit to update
9290: 49 01                        eor     #%00000001              ; which player is on the screen
9292: 8d 53 07                     sta     CurrentPlayer
9295: a2 06                        ldx     #$06
9297: bd 5a 07     TransLoop       lda     OnscreenPlayerInfo,x    ;transpose the information
929a: 48                           pha                             ; of the onscreen player
929b: bd 61 07                     lda     OffscreenPlayerInfo,x   ; with that of the offscreen player
929e: 9d 5a 07                     sta     OnscreenPlayerInfo,x
92a1: 68                           pla
92a2: 9d 61 07                     sta     OffscreenPlayerInfo,x
92a5: ca                           dex
92a6: 10 ef                        bpl     TransLoop
92a8: 18                           clc
92a9: 60           ExTrans         rts

                   ; -----------------------------------------------------------------------------
92aa: a9 ff        DoNothing1      lda     #$ff                    ;this is residual code, this value is
92ac: 8d c9 06                     sta     unused_06c9             ; not used anywhere in the program
92af: 60           DoNothing2      rts

                   ; -----------------------------------------------------------------------------
                   AreaParserTaskHandler
92b0: ac 1f 07                     ldy     AreaParserTaskNum       ;check number of tasks here
92b3: d0 05                        bne     DoAPTasks               ;if already set, go ahead
92b5: a0 08                        ldy     #$08
92b7: 8c 1f 07                     sty     AreaParserTaskNum       ;otherwise, set eight by default
92ba: 88           DoAPTasks       dey
92bb: 98                           tya
92bc: 20 c8 92                     jsr     AreaParserTasks
92bf: ce 1f 07                     dec     AreaParserTaskNum       ;if all tasks not complete do not
92c2: d0 03                        bne     SkipATRender            ; render attribute table yet
92c4: 20 6a 89                     jsr     RenderAttributeTables
92c7: 60           SkipATRender    rts

92c8: 20 04 8e     AreaParserTasks jsr     JumpEngine

92cb: db 92                        .dd2    IncrementColumnPos
92cd: ae 88                        .dd2    RenderAreaGraphics
92cf: ae 88                        .dd2    RenderAreaGraphics
92d1: fc 93                        .dd2    AreaParserCore
92d3: db 92                        .dd2    IncrementColumnPos
92d5: ae 88                        .dd2    RenderAreaGraphics
92d7: ae 88                        .dd2    RenderAreaGraphics
92d9: fc 93                        .dd2    AreaParserCore

                   ; -----------------------------------------------------------------------------
                   IncrementColumnPos
92db: ee 26 07                     inc     CurrentColumnPos        ;increment column where we're at
92de: ad 26 07                     lda     CurrentColumnPos
92e1: 29 0f                        and     #%00001111              ;mask out higher nybble
92e3: d0 06                        bne     NoColWrap
92e5: 8d 26 07                     sta     CurrentColumnPos        ;if no bits left set, wrap back to zero (0-f)
92e8: ee 25 07                     inc     CurrentPageLoc          ; and increment page number where we're at
92eb: ee a0 06     NoColWrap       inc     BlockBufferColumnPos    ;increment column offset where we're at
92ee: ad a0 06                     lda     BlockBufferColumnPos
92f1: 29 1f                        and     #%00011111              ;mask out all but 5 LSB (0-1f)
92f3: 8d a0 06                     sta     BlockBufferColumnPos    ;and save
92f6: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used as counter, store for low nybble for background, ceiling byte for
                   ; terrain
                   ; $01 - used to store floor byte for terrain
                   ; $07 - used to store terrain metatile
                   ; $06-$07 - used to store block buffer address
                   BSceneDataOffsets
92f7: 00 30 60                     .bulk   $00,$30,$60
92fa: 93 00 00 11+ BackSceneryData .bulk   $93,$00,$00,$11,$12,$12,$13,$00,$00,$51,$52,$53,$00,$00,$00,$00 ;clouds
                                    +      $00,$00,$01,$02,$02,$03,$00,$00,$00,$00,$00,$00,$91,$92,$93,$00
                                    +      $00,$00,$00,$51,$52,$53,$41,$42,$43,$00,$00,$00,$00,$00,$91,$92
932a: 97 87 88 89+                 .bulk   $97,$87,$88,$89,$99,$00,$00,$00,$11,$12,$13,$a4,$a5,$a5,$a5,$a6 ;mountains and bushes
                                    +      $97,$98,$99,$01,$02,$03,$00,$a4,$a5,$a6,$00,$11,$12,$12,$12,$13
                                    +      $00,$00,$00,$00,$01,$02,$02,$03,$00,$a4,$a5,$a5,$a6,$00,$00,$00
935a: 11 12 12 13+                 .bulk   $11,$12,$12,$13,$00,$00,$00,$00,$00,$00,$00,$9c,$00,$8b,$aa,$aa ;trees and fences
                                    +      $aa,$aa,$11,$12,$13,$8b,$00,$9c,$9c,$00,$00,$01,$02,$03,$11,$12
                                    +      $12,$13,$00,$00,$00,$00,$aa,$aa,$9c,$aa,$00,$8b,$00,$01,$02,$03
                   BackSceneryMetatiles
938a: 80 83 00                     .bulk   $80,$83,$00             ;cloud left
938d: 81 84 00                     .bulk   $81,$84,$00             ;cloud middle
9390: 82 85 00                     .bulk   $82,$85,$00             ;cloud right
9393: 02 00 00                     .bulk   $02,$00,$00             ;bush left
9396: 03 00 00                     .bulk   $03,$00,$00             ;bush middle
9399: 04 00 00                     .bulk   $04,$00,$00             ;bush right
939c: 00 05 06                     .bulk   $00,$05,$06             ;mountain left
939f: 07 06 0a                     .bulk   $07,$06,$0a             ;mountain middle
93a2: 00 08 09                     .bulk   $00,$08,$09             ;mountain right
93a5: 4d 00 00                     .bulk   $4d,$00,$00             ;fence
93a8: 0d 0f 4e                     .bulk   $0d,$0f,$4e             ;tall tree
93ab: 0e 4e 4e                     .bulk   $0e,$4e,$4e             ;short tree
                   FSceneDataOffsets
93ae: 00 0d 1a                     .bulk   $00,$0d,$1a
93b1: 86 87 87 87+ ForeSceneryData .bulk   $86,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87,$69,$69 ;in water
93be: 00 00 00 00+                 .bulk   $00,$00,$00,$00,$00,$45,$47,$47,$47,$47,$47,$00,$00 ;wall
93cb: 00 00 00 00+                 .bulk   $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$86,$87 ;over water
                   TerrainMetatiles
93d8: 69 54 52 62                  .bulk   $69,$54,$52,$62
                   TerrainRenderBits
93dc: 00 00                        .dbd2   %0000000000000000       ;no ceiling or floor
93de: 00 18                        .dbd2   %0000000000011000       ;no ceiling, floor 2
93e0: 01 18                        .dbd2   %0000000100011000       ;ceiling 1, floor 2
93e2: 07 18                        .dbd2   %0000011100011000       ;ceiling 3, floor 2
93e4: 0f 18                        .dbd2   %0000111100011000       ;ceiling 4, floor 2
93e6: ff 18                        .dbd2   %1111111100011000       ;ceiling 8, floor 2
93e8: 01 1f                        .dbd2   %0000000100011111       ;ceiling 1, floor 5
93ea: 07 1f                        .dbd2   %0000011100011111       ;ceiling 3, floor 5
93ec: 0f 1f                        .dbd2   %0000111100011111       ;ceiling 4, floor 5
93ee: 81 1f                        .dbd2   %1000000100011111       ;ceiling 1, floor 6
93f0: 01 00                        .dbd2   %0000000100000000       ;ceiling 1, no floor
93f2: 8f 1f                        .dbd2   %1000111100011111       ;ceiling 4, floor 6
93f4: f1 1f                        .dbd2   %1111000100011111       ;ceiling 1, floor 9
93f6: f9 18                        .dbd2   %1111100100011000       ;ceiling 1, middle 5, floor 2
93f8: f1 18                        .dbd2   %1111000100011000       ;ceiling 1, middle 4, floor 2
93fa: ff 1f                        .dbd2   %1111111100011111       ;completely solid top to bottom

93fc: ad 28 07     AreaParserCore  lda     BackloadingFlag         ;check to see if we are starting right of start
93ff: f0 03                        beq     RenderSceneryTerrain    ;if not, go ahead and render background, foreground and terrain
9401: 20 08 95                     jsr     ProcessAreaData         ;otherwise skip ahead and load level data
                   ; 
                   RenderSceneryTerrain
9404: a2 0c                        ldx     #$0c
9406: a9 00                        lda     #$00
9408: 9d a1 06     ClrMTBuf        sta     MetatileBuffer,x        ;clear out metatile buffer
940b: ca                           dex
940c: 10 fa                        bpl     ClrMTBuf
940e: ac 42 07                     ldy     BackgroundScenery       ;do we need to render the background scenery?
9411: f0 42                        beq     RendFore                ;if not, skip to check the foreground
9413: ad 25 07                     lda     CurrentPageLoc          ;otherwise check for every third page
9416: c9 03        ThirdP          cmp     #$03
9418: 30 05                        bmi     RendBack                ;if less than three we're there
941a: 38                           sec
941b: e9 03                        sbc     #$03                    ;if 3 or more, subtract 3 and 
941d: 10 f7                        bpl     ThirdP                  ;do an unconditional branch
941f: 0a           RendBack        asl     A                       ;move results to higher nybble
9420: 0a                           asl     A
9421: 0a                           asl     A
9422: 0a                           asl     A
9423: 79 f6 92                     adc     BSceneDataOffsets-1,y   ;add to it offset loaded from here
9426: 6d 26 07                     adc     CurrentColumnPos        ;add to the result our current column position
9429: aa                           tax
942a: bd fa 92                     lda     BackSceneryData,x       ;load data from sum of offsets
942d: f0 26                        beq     RendFore                ;if zero, no scenery for that part
942f: 48                           pha
9430: 29 0f                        and     #$0f                    ;save to stack and clear high nybble
9432: 38                           sec
9433: e9 01                        sbc     #$01                    ;subtract one (because low nybble is $01-$0c)
9435: 85 00                        sta     $00                     ;save low nybble
9437: 0a                           asl     A                       ;multiply by three (shift to left and add result to old one)
9438: 65 00                        adc     $00                     ;note that since d7 was nulled, the carry flag is always clear
943a: aa                           tax                             ;save as offset for background scenery metatile data
943b: 68                           pla                             ;get high nybble from stack, move low
943c: 4a                           lsr     A
943d: 4a                           lsr     A
943e: 4a                           lsr     A
943f: 4a                           lsr     A
9440: a8                           tay                             ;use as second offset (used to determine height)
9441: a9 03                        lda     #$03                    ;use previously saved memory location for counter
9443: 85 00                        sta     $00
9445: bd 8a 93     SceLoop1        lda     BackSceneryMetatiles,x  ;load metatile data from offset of (lsb - 1) * 3
9448: 99 a1 06                     sta     MetatileBuffer,y        ;store into buffer from offset of (msb / 16)
944b: e8                           inx
944c: c8                           iny
944d: c0 0b                        cpy     #$0b                    ;if at this location, leave loop
944f: f0 04                        beq     RendFore
9451: c6 00                        dec     $00                     ;decrement until counter expires, barring exception
9453: d0 f0                        bne     SceLoop1
9455: ae 41 07     RendFore        ldx     ForegroundScenery       ;check for foreground data needed or not
9458: f0 13                        beq     RendTerr                ;if not, skip this part
945a: bc ad 93                     ldy     FSceneDataOffsets-1,x   ;load offset from location offset by header value, then
945d: a2 00                        ldx     #$00                    ; reinit X
945f: b9 b1 93     SceLoop2        lda     ForeSceneryData,y       ;load data until counter expires
9462: f0 03                        beq     NoFore                  ;do not store if zero found
9464: 9d a1 06                     sta     MetatileBuffer,x
9467: c8           NoFore          iny
9468: e8                           inx
9469: e0 0d                        cpx     #$0d                    ;store up to end of metatile buffer
946b: d0 f2                        bne     SceLoop2
946d: ac 4e 07     RendTerr        ldy     AreaType                ;check world type for water level
9470: d0 0c                        bne     TerMTile                ;if not water level, skip this part
9472: ad 5f 07                     lda     WorldNumber             ;check world number, if not world number eight
9475: c9 07                        cmp     #World8                 ; then skip this part
9477: d0 05                        bne     TerMTile
9479: a9 62                        lda     #$62                    ;if set as water level and world number eight,
947b: 4c 88 94                     jmp     StoreMT                 ; use castle wall metatile as terrain type

947e: b9 d8 93     TerMTile        lda     TerrainMetatiles,y      ;otherwise get appropriate metatile for area type
9481: ac 43 07                     ldy     CloudTypeOverride       ;check for cloud type override
9484: f0 02                        beq     StoreMT                 ;if not set, keep value otherwise
9486: a9 88                        lda     #$88                    ;use cloud block terrain
9488: 85 07        StoreMT         sta     $07                     ;store value here
948a: a2 00                        ldx     #$00                    ;initialize X, use as metatile buffer offset
948c: ad 27 07                     lda     TerrainControl          ;use yet another value from the header
948f: 0a                           asl     A                       ;multiply by 2 and use as yet another offset
9490: a8                           tay
9491: b9 dc 93     TerrLoop        lda     TerrainRenderBits,y     ;get one of the terrain rendering bit data
9494: 85 00                        sta     $00
9496: c8                           iny                             ;increment Y and use as offset next time around
9497: 84 01                        sty     $01
9499: ad 43 07                     lda     CloudTypeOverride       ;skip if value here is zero
949c: f0 0a                        beq     NoCloud2
949e: e0 00                        cpx     #$00                    ;otherwise, check if we're doing the ceiling byte
94a0: f0 06                        beq     NoCloud2
94a2: a5 00                        lda     $00                     ;if not, mask out all but d3
94a4: 29 08                        and     #%00001000
94a6: 85 00                        sta     $00
94a8: a0 00        NoCloud2        ldy     #$00                    ;start at beginning of bitmasks
94aa: b9 8a c6     TerrBChk        lda     Bitmasks,y              ;load bitmask, then perform AND on contents of first byte
94ad: 24 00                        bit     $00
94af: f0 05                        beq     NextTBit                ;if not set, skip this part (do not write terrain to buffer)
94b1: a5 07                        lda     $07
94b3: 9d a1 06                     sta     MetatileBuffer,x        ;load terrain type metatile number and store into buffer here
94b6: e8           NextTBit        inx                             ;continue until end of buffer
94b7: e0 0d                        cpx     #$0d
94b9: f0 18                        beq     RendBBuf                ;if we're at the end, break out of this loop
94bb: ad 4e 07                     lda     AreaType                ;check world type for underground area
94be: c9 02                        cmp     #$02
94c0: d0 08                        bne     EndUChk                 ;if not underground, skip this part
94c2: e0 0b                        cpx     #$0b
94c4: d0 04                        bne     EndUChk                 ;if we're at the bottom of the screen, override
94c6: a9 54                        lda     #$54                    ; old terrain type with ground level terrain type
94c8: 85 07                        sta     $07
94ca: c8           EndUChk         iny                             ;increment bitmasks offset in Y
94cb: c0 08                        cpy     #$08
94cd: d0 db                        bne     TerrBChk                ;if not all bits checked, loop back  
94cf: a4 01                        ldy     $01
94d1: d0 be                        bne     TerrLoop                ;unconditional branch, use Y to load next byte
94d3: 20 08 95     RendBBuf        jsr     ProcessAreaData         ;do the area data loading routine now
94d6: ad a0 06                     lda     BlockBufferColumnPos
94d9: 20 e1 9b                     jsr     GetBlockBufferAddr      ;get block buffer address from where we're at
94dc: a2 00                        ldx     #$00
94de: a0 00                        ldy     #$00                    ;init index regs and start at beginning of smaller buffer
94e0: 84 00        ChkMTLow        sty     $00
94e2: bd a1 06                     lda     MetatileBuffer,x        ;load stored metatile number
94e5: 29 c0                        and     #%11000000              ;mask out all but 2 MSB
94e7: 0a                           asl     A
94e8: 2a                           rol     A                       ;make %xx000000 into %000000xx
94e9: 2a                           rol     A
94ea: a8                           tay                             ;use as offset in Y
94eb: bd a1 06                     lda     MetatileBuffer,x        ;reload original unmasked value here
94ee: d9 04 95                     cmp     BlockBuffLowBounds,y    ;check for certain values depending on bits set
94f1: b0 02                        bcs     StrBlock                ;if equal or greater, branch
94f3: a9 00                        lda     #$00                    ;if less, init value before storing
94f5: a4 00        StrBlock        ldy     $00                     ;get offset for block buffer
94f7: 91 06                        sta     ($06),y                 ;store value into block buffer
94f9: 98                           tya
94fa: 18                           clc                             ;add 16 (move down one row) to offset
94fb: 69 10                        adc     #$10
94fd: a8                           tay
94fe: e8                           inx                             ;increment column value
94ff: e0 0d                        cpx     #$0d
9501: 90 dd                        bcc     ChkMTLow                ;continue until we pass last row, then leave
9503: 60                           rts

                   ; numbers lower than these with the same attribute bits will not be stored in
                   ; the block buffer
                   BlockBuffLowBounds
9504: 10 51 88 c0                  .bulk   $10,$51,$88,$c0

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store area object identifier
                   ; $07 - used as adder to find proper area object code
9508: a2 02        ProcessAreaData ldx     #$02                    ;start at the end of area object buffer
950a: 86 08        ProcADLoop      stx     ObjectOffset
950c: a9 00                        lda     #$00                    ;reset flag
950e: 8d 29 07                     sta     BehindAreaParserFlag
9511: ac 2c 07                     ldy     AreaDataOffset          ;get offset of area data pointer
9514: b1 e7                        lda     (AreaData),y            ;get first byte of area object
9516: c9 fd                        cmp     #$fd                    ;if end-of-area, skip all this crap
9518: f0 4b                        beq     RdyDecode
951a: bd 30 07                     lda     AreaObjectLength,x      ;check area object buffer flag
951d: 10 46                        bpl     RdyDecode               ;if buffer not negative, branch, otherwise
951f: c8                           iny
9520: b1 e7                        lda     (AreaData),y            ;get second byte of area object
9522: 0a                           asl     A                       ;check for page select bit (d7), branch if not set
9523: 90 0b                        bcc     Chk1Row13
9525: ad 2b 07                     lda     AreaObjectPageSel       ;check page select
9528: d0 06                        bne     Chk1Row13
952a: ee 2b 07                     inc     AreaObjectPageSel       ;if not already set, set it now
952d: ee 2a 07                     inc     AreaObjectPageLoc       ;and increment page location
9530: 88           Chk1Row13       dey
9531: b1 e7                        lda     (AreaData),y            ;reread first byte of level object
9533: 29 0f                        and     #$0f                    ;mask out high nybble
9535: c9 0d                        cmp     #$0d                    ;row 13?
9537: d0 1b                        bne     Chk1Row14
9539: c8                           iny                             ;if so, reread second byte of level object
953a: b1 e7                        lda     (AreaData),y
953c: 88                           dey                             ;decrement to get ready to read first byte
953d: 29 40                        and     #%01000000              ;check for d6 set (if not, object is page control)
953f: d0 1c                        bne     CheckRear
9541: ad 2b 07                     lda     AreaObjectPageSel       ;if page select is set, do not reread
9544: d0 17                        bne     CheckRear
9546: c8                           iny                             ;if d6 not set, reread second byte
9547: b1 e7                        lda     (AreaData),y
9549: 29 1f                        and     #%00011111              ;mask out all but 5 LSB and store in page control
954b: 8d 2a 07                     sta     AreaObjectPageLoc
954e: ee 2b 07                     inc     AreaObjectPageSel       ;increment page select
9551: 4c 6e 95                     jmp     NextAObj

9554: c9 0e        Chk1Row14       cmp     #$0e                    ;row 14?
9556: d0 05                        bne     CheckRear
9558: ad 28 07                     lda     BackloadingFlag         ;check flag for saved page number and branch if set
955b: d0 08                        bne     RdyDecode               ; to render the object (otherwise bg might not look right)
955d: ad 2a 07     CheckRear       lda     AreaObjectPageLoc       ;check to see if current page of level object is
9560: cd 25 07                     cmp     CurrentPageLoc          ;behind current page of renderer
9563: 90 06                        bcc     SetBehind               ;if so branch
9565: 20 95 95     RdyDecode       jsr     DecodeAreaData          ;do sub and do not turn on flag
9568: 4c 71 95                     jmp     ChkLength

956b: ee 29 07     SetBehind       inc     BehindAreaParserFlag    ;turn on flag if object is behind renderer
956e: 20 89 95     NextAObj        jsr     IncAreaObjOffset        ;increment buffer offset and move on
9571: a6 08        ChkLength       ldx     ObjectOffset            ;get buffer offset
9573: bd 30 07                     lda     AreaObjectLength,x      ;check object length for anything stored here
9576: 30 03                        bmi     ProcLoopb               ;if not, branch to handle loopback
9578: de 30 07                     dec     AreaObjectLength,x      ;otherwise decrement length or get rid of it
957b: ca           ProcLoopb       dex                             ;decrement buffer offset
957c: 10 8c                        bpl     ProcADLoop              ; and loopback unless exceeded buffer
957e: ad 29 07                     lda     BehindAreaParserFlag    ;check for flag set if objects were behind renderer
9581: d0 85                        bne     ProcessAreaData         ;branch if true to load more level data, otherwise
9583: ad 28 07                     lda     BackloadingFlag         ;check for flag set if starting right of page $00
9586: d0 80                        bne     ProcessAreaData         ;branch if true to load more level data, otherwise leave
9588: 60           EndAParse       rts

                   IncAreaObjOffset
9589: ee 2c 07                     inc     AreaDataOffset          ;increment offset of level pointer
958c: ee 2c 07                     inc     AreaDataOffset
958f: a9 00                        lda     #$00                    ;reset page select
9591: 8d 2b 07                     sta     AreaObjectPageSel
9594: 60                           rts

9595: bd 30 07     DecodeAreaData  lda     AreaObjectLength,x      ;check current buffer flag
9598: 30 03                        bmi     Chk1stB
959a: bc 2d 07                     ldy     AreaObjOffsetBuffer,x   ;if not, get offset from buffer
959d: a2 10        Chk1stB         ldx     #$10                    ;load offset of 16 for special row 15
959f: b1 e7                        lda     (AreaData),y            ;get first byte of level object again
95a1: c9 fd                        cmp     #$fd
95a3: f0 e3                        beq     EndAParse               ;if end of level, leave this routine
95a5: 29 0f                        and     #$0f                    ;otherwise, mask out low nybble
95a7: c9 0f                        cmp     #$0f                    ;row 15?
95a9: f0 08                        beq     ChkRow14                ;if so, keep the offset of 16
95ab: a2 08                        ldx     #$08                    ;otherwise load offset of 8 for special row 12
95ad: c9 0c                        cmp     #$0c                    ;row 12?
95af: f0 02                        beq     ChkRow14                ;if so, keep the offset value of 8
95b1: a2 00                        ldx     #$00                    ;otherwise nullify value by default
95b3: 86 07        ChkRow14        stx     $07                     ;store whatever value we just loaded here
95b5: a6 08                        ldx     ObjectOffset            ;get object offset again
95b7: c9 0e                        cmp     #$0e                    ;row 14?
95b9: d0 08                        bne     ChkRow13
95bb: a9 00                        lda     #$00                    ;if so, load offset with $00
95bd: 85 07                        sta     $07
95bf: a9 2e                        lda     #$2e                    ;and load A with another value
95c1: d0 53                        bne     NormObj                 ;unconditional branch

95c3: c9 0d        ChkRow13        cmp     #$0d                    ;row 13?
95c5: d0 1b                        bne     ChkSRows
95c7: a9 22                        lda     #$22                    ;if so, load offset with 34
95c9: 85 07                        sta     $07
95cb: c8                           iny                             ;get next byte
95cc: b1 e7                        lda     (AreaData),y
95ce: 29 40                        and     #%01000000              ;mask out all but d6 (page control obj bit)
95d0: f0 63                        beq     LeavePar                ;if d6 clear, branch to leave (we handled this earlier)
95d2: b1 e7                        lda     (AreaData),y            ;otherwise, get byte again
95d4: 29 7f                        and     #%01111111              ;mask out d7
95d6: c9 4b                        cmp     #$4b                    ;check for loop command in low nybble
95d8: d0 03                        bne     Mask2MSB                ;(plus d6 set for object other than page control)
95da: ee 45 07                     inc     LoopCommand             ;if loop command, set loop command flag
95dd: 29 3f        Mask2MSB        and     #%00111111              ;mask out d7 and d6
95df: 4c 16 96                     jmp     NormObj                 ;and jump

95e2: c9 0c        ChkSRows        cmp     #$0c                    ;row 12-15?
95e4: b0 27                        bcs     SpecObj
95e6: c8                           iny                             ;if not, get second byte of level object
95e7: b1 e7                        lda     (AreaData),y
95e9: 29 70                        and     #%01110000              ;mask out all but d6-d4
95eb: d0 0b                        bne     LrgObj                  ;if any bits set, branch to handle large object
95ed: a9 16                        lda     #$16
95ef: 85 07                        sta     $07                     ;otherwise set offset of 24 for small object
95f1: b1 e7                        lda     (AreaData),y            ;reload second byte of level object
95f3: 29 0f                        and     #%00001111              ;mask out higher nybble and jump
95f5: 4c 16 96                     jmp     NormObj

95f8: 85 00        LrgObj          sta     $00                     ;store value here (branch for large objects)
95fa: c9 70                        cmp     #$70                    ;check for vertical pipe object
95fc: d0 0a                        bne     NotWPipe
95fe: b1 e7                        lda     (AreaData),y            ;if not, reload second byte
9600: 29 08                        and     #%00001000              ;mask out all but d3 (usage control bit)
9602: f0 04                        beq     NotWPipe                ;if d3 clear, branch to get original value
9604: a9 00                        lda     #$00                    ;otherwise, nullify value for warp pipe
9606: 85 00                        sta     $00
9608: a5 00        NotWPipe        lda     $00                     ;get value and jump ahead
960a: 4c 12 96                     jmp     MoveAOId

960d: c8           SpecObj         iny                             ;branch here for rows 12-15
960e: b1 e7                        lda     (AreaData),y
9610: 29 70                        and     #%01110000              ;get next byte and mask out all but d6-d4
9612: 4a           MoveAOId        lsr     A                       ;move d6-d4 to lower nybble
9613: 4a                           lsr     A
9614: 4a                           lsr     A
9615: 4a                           lsr     A
9616: 85 00        NormObj         sta     $00                     ;store value here (branch for small objects and rows 13 and 14)
9618: bd 30 07                     lda     AreaObjectLength,x      ;is there something stored here already?
961b: 10 42                        bpl     RunAObj                 ;if so, branch to do its particular sub
961d: ad 2a 07                     lda     AreaObjectPageLoc       ;otherwise check to see if the object we've loaded is on the
9620: cd 25 07                     cmp     CurrentPageLoc          ;same page as the renderer, and if so, branch
9623: f0 11                        beq     InitRear
9625: ac 2c 07                     ldy     AreaDataOffset          ;if not, get old offset of level pointer
9628: b1 e7                        lda     (AreaData),y            ;and reload first byte
962a: 29 0f                        and     #%00001111
962c: c9 0e                        cmp     #$0e                    ;row 14?
962e: d0 05                        bne     LeavePar
9630: ad 28 07                     lda     BackloadingFlag         ;if so, check backloading flag
9633: d0 21                        bne     StarAObj                ;if set, branch to render object, else leave
9635: 60           LeavePar        rts

9636: ad 28 07     InitRear        lda     BackloadingFlag         ;check backloading flag to see if it's been initialized
9639: f0 0b                        beq     BackColC                ;branch to column-wise check
963b: a9 00                        lda     #$00                    ;if not, initialize both backloading and 
963d: 8d 28 07                     sta     BackloadingFlag         ;behind-renderer flags and leave
9640: 8d 29 07                     sta     BehindAreaParserFlag
9643: 85 08                        sta     ObjectOffset
9645: 60           LoopCmdE        rts

9646: ac 2c 07     BackColC        ldy     AreaDataOffset          ;get first byte again
9649: b1 e7                        lda     (AreaData),y
964b: 29 f0                        and     #%11110000              ;mask out low nybble and move high to low
964d: 4a                           lsr     A
964e: 4a                           lsr     A
964f: 4a                           lsr     A
9650: 4a                           lsr     A
9651: cd 26 07                     cmp     CurrentColumnPos        ;is this where we're at?
9654: d0 df                        bne     LeavePar                ;if not, branch to leave
9656: ad 2c 07     StarAObj        lda     AreaDataOffset          ;if so, load area obj offset and store in buffer
9659: 9d 2d 07                     sta     AreaObjOffsetBuffer,x
965c: 20 89 95                     jsr     IncAreaObjOffset        ;do sub to increment to next object data
965f: a5 00        RunAObj         lda     $00                     ;get stored value and add offset to it
9661: 18                           clc                             ;then use the jump engine with current contents of A
9662: 65 07                        adc     $07
9664: 20 04 8e                     jsr     JumpEngine

                   ; large objects (rows $00-$0b or 00-11, d6-d4 set)
9667: e5 98                        .dd2    VerticalPipe
9669: 40 97                        .dd2    AreaStyleObject         ;used by warp pipes
966b: 2e 9a                        .dd2    RowOfBricks
966d: 3e 9a                        .dd2    RowOfSolidBlocks
966f: f2 99                        .dd2    RowOfCoins
9671: 50 9a                        .dd2    ColumnOfBricks
9673: 59 9a                        .dd2    ColumnOfSolidBlocks
9675: e5 98                        .dd2    VerticalPipe            ;used by decoration pipes
                   ; objects for special row $0c or 12
9677: 41 9b                        .dd2    Hole_Empty
9679: ba 97                        .dd2    PulleyRopeObject
967b: 79 99                        .dd2    Bridge_High
967d: 7c 99                        .dd2    Bridge_Middle
967f: 7f 99                        .dd2    Bridge_Low
9681: 57 99                        .dd2    Hole_Water
9683: 68 99                        .dd2    QuestionBlockRow_High
9685: 6b 99                        .dd2    QuestionBlockRow_Low
                   ; objects for special row $0f or 15
9687: d0 99                        .dd2    EndlessRope
9689: d7 99                        .dd2    BalancePlatRope
968b: 06 98                        .dd2    CastleObject
968d: b7 9a                        .dd2    StaircaseObject
968f: ab 98                        .dd2    ExitPipe
9691: 94 99                        .dd2    FlagBalls_Residual
                   ; small objects (rows $00-$0b or 00-11, d6-d4 all clear)
9693: 0e 9b                        .dd2    QuestionBlock           ;power-up
9695: 0e 9b                        .dd2    QuestionBlock           ;coin
9697: 0e 9b                        .dd2    QuestionBlock           ;hidden, coin
9699: 01 9b                        .dd2    Hidden1UpBlock          ;hidden, 1-up
969b: 19 9b                        .dd2    BrickWithItem           ;brick, power-up
969d: 19 9b                        .dd2    BrickWithItem           ;brick, vine
969f: 19 9b                        .dd2    BrickWithItem           ;brick, star
96a1: 14 9b                        .dd2    BrickWithCoins          ;brick, coins
96a3: 19 9b                        .dd2    BrickWithItem           ;brick, 1-up
96a5: 6f 98                        .dd2    WaterPipe
96a7: 19 9a                        .dd2    EmptyBlock
96a9: d3 9a                        .dd2    JumpSpring
                   ; objects for special row $0d or 13 (d6 set)
96ab: 82 98                        .dd2    IntroPipe
96ad: 9e 99                        .dd2    FlagpoleObject
96af: 09 9a                        .dd2    AxeObj
96b1: 0e 9a                        .dd2    ChainObj
96b3: 01 9a                        .dd2    CastleBridgeObj
96b5: f2 96                        .dd2    ScrollLockObject_Warp
96b7: 0d 97                        .dd2    ScrollLockObject
96b9: 0d 97                        .dd2    ScrollLockObject
96bb: 2b 97                        .dd2    AreaFrenzy              ;flying cheep-cheeps 
96bd: 2b 97                        .dd2    AreaFrenzy              ;bullet bills or swimming cheep-cheeps
96bf: 2b 97                        .dd2    AreaFrenzy              ;stop frenzy
96c1: 45 96                        .dd2    LoopCmdE
                   ; object for special row $0e or 14
96c3: c5 96                        .dd2    AlterAreaAttributes

                   ; -----------------------------------------------------------------------------
                   ; (these apply to all area object subroutines in this section unless otherwise
                   ; stated)
                   ; $00 - used to store offset used to find object code
                   ; $07 - starts with adder from area parser, used to store row offset
                   AlterAreaAttributes
96c5: bc 2d 07                     ldy     AreaObjOffsetBuffer,x   ;load offset for level object data saved in buffer
96c8: c8                           iny                             ;load second byte
96c9: b1 e7                        lda     (AreaData),y
96cb: 48                           pha                             ;save in stack for now
96cc: 29 40                        and     #%01000000
96ce: d0 12                        bne     Alter2                  ;branch if d6 is set
96d0: 68                           pla
96d1: 48                           pha                             ;pull and push offset to copy to A
96d2: 29 0f                        and     #%00001111              ;mask out high nybble and store as
96d4: 8d 27 07                     sta     TerrainControl          ; new terrain height type bits
96d7: 68                           pla
96d8: 29 30                        and     #%00110000              ;pull and mask out all but d5 and d4
96da: 4a                           lsr     A                       ;move bits to lower nybble and store
96db: 4a                           lsr     A                       ; as new background scenery bits
96dc: 4a                           lsr     A
96dd: 4a                           lsr     A
96de: 8d 42 07                     sta     BackgroundScenery       ;then leave
96e1: 60                           rts

96e2: 68           Alter2          pla
96e3: 29 07                        and     #%00000111              ;mask out all but 3 LSB
96e5: c9 04                        cmp     #$04                    ;if four or greater, set color control bits
96e7: 90 05                        bcc     SetFore                 ; and nullify foreground scenery bits
96e9: 8d 44 07                     sta     BackgroundColorCtrl
96ec: a9 00                        lda     #$00
96ee: 8d 41 07     SetFore         sta     ForegroundScenery       ;otherwise set new foreground scenery bits
96f1: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ScrollLockObject_Warp
96f2: a2 04                        ldx     #$04                    ;load value of 4 for game text routine as default
96f4: ad 5f 07                     lda     WorldNumber             ; warp zone (4-3-2), then check world number
96f7: f0 08                        beq     WarpNum
96f9: e8                           inx                             ;if world number > 1, increment for next warp zone (5)
96fa: ac 4e 07                     ldy     AreaType                ;check area type
96fd: 88                           dey
96fe: d0 01                        bne     WarpNum                 ;if ground area type, increment for last warp zone
9700: e8                           inx                             ; (8-7-6) and move on
9701: 8a           WarpNum         txa
9702: 8d d6 06                     sta     WarpZoneControl         ;store number here to be used by warp zone routine
9705: 20 08 88                     jsr     WriteGameText           ;print text and warp zone numbers
9708: a9 0d                        lda     #PiranhaPlant
970a: 20 16 97                     jsr     KillEnemies             ;load identifier for piranha plants and do sub
                   ScrollLockObject
970d: ad 23 07                     lda     ScrollLock              ;invert scroll lock to turn it on
9710: 49 01                        eor     #%00000001
9712: 8d 23 07                     sta     ScrollLock
9715: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store enemy identifier in KillEnemies
9716: 85 00        KillEnemies     sta     $00                     ;store identifier here
9718: a9 00                        lda     #$00
971a: a2 04                        ldx     #$04                    ;check for identifier in enemy object buffer
971c: b4 16        KillELoop       ldy     Enemy_ID,x
971e: c4 00                        cpy     $00                     ;if not found, branch
9720: d0 02                        bne     NoKillE
9722: 95 0f                        sta     Enemy_Flag,x
9724: ca           NoKillE         dex                             ;do this until all slots are checked
9725: 10 f5                        bpl     KillELoop
9727: 60                           rts

                   ; -----------------------------------------------------------------------------
9728: 14           FrenzyIDData    .dd1    FlyCheepCheepFrenzy
9729: 17                           .dd1    BBill_CCheep_Frenzy
972a: 18                           .dd1    Stop_Frenzy

972b: a6 00        AreaFrenzy      ldx     $00                     ;use area object identifier bit as offset
972d: bd 20 97                     lda     FrenzyIDData-8,x        ;note that it starts at 8, thus weird address here
9730: a0 05                        ldy     #$05
9732: 88           FreCompLoop     dey                             ;check regular slots of enemy object buffer
9733: 30 07                        bmi     ExitAFrenzy             ;if all slots checked and enemy object not found, branch to store
9735: d9 16 00                     cmp     Enemy_ID,y              ;check for enemy object in buffer versus frenzy object
9738: d0 f8                        bne     FreCompLoop
973a: a9 00                        lda     #$00                    ;if enemy object already present, nullify queue and leave
973c: 8d cd 06     ExitAFrenzy     sta     EnemyFrenzyQueue        ;store enemy into frenzy queue
973f: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $06 - used by MushroomLedge to store length
9740: ad 33 07     AreaStyleObject lda     AreaStyle               ;load level object style and jump to the right sub
9743: 20 04 8e                     jsr     JumpEngine

9746: 4c 97                        .dd2    TreeLedge               ;also used for cloud type levels
9748: 78 97                        .dd2    MushroomLedge
974a: 69 9a                        .dd2    BulletBillCannon

974c: 20 bb 9b     TreeLedge       jsr     GetLrgObjAttrib         ;get row and length of green ledge
974f: bd 30 07                     lda     AreaObjectLength,x      ;check length counter for expiration
9752: f0 1f                        beq     EndTreeL
9754: 10 11                        bpl     MidTreeL
9756: 98                           tya
9757: 9d 30 07                     sta     AreaObjectLength,x      ;store lower nybble into buffer flag as length of ledge
975a: ad 25 07                     lda     CurrentPageLoc
975d: 0d 26 07                     ora     CurrentColumnPos        ;are we at the start of the level?
9760: f0 05                        beq     MidTreeL
9762: a9 16                        lda     #$16                    ;render start of tree ledge
9764: 4c b0 97                     jmp     NoUnder

9767: a6 07        MidTreeL        ldx     $07
9769: a9 17                        lda     #$17                    ;render middle of tree ledge
976b: 9d a1 06                     sta     MetatileBuffer,x        ;note that this is also used if ledge position is
976e: a9 4c                        lda     #$4c                    ; at the start of level for continuous effect
9770: 4c aa 97                     jmp     AllUnder                ;now render the part underneath

9773: a9 18        EndTreeL        lda     #$18                    ;render end of tree ledge
9775: 4c b0 97                     jmp     NoUnder

9778: 20 ac 9b     MushroomLedge   jsr     ChkLrgObjLength         ;get shroom dimensions
977b: 84 06                        sty     $06                     ;store length here for now
977d: 90 0c                        bcc     EndMushL
977f: bd 30 07                     lda     AreaObjectLength,x      ;divide length by 2 and store elsewhere
9782: 4a                           lsr     A
9783: 9d 36 07                     sta     MushroomLedgeHalfLen,x
9786: a9 19                        lda     #$19                    ;render start of mushroom
9788: 4c b0 97                     jmp     NoUnder

978b: a9 1b        EndMushL        lda     #$1b                    ;if at the end, render end of mushroom
978d: bc 30 07                     ldy     AreaObjectLength,x
9790: f0 1e                        beq     NoUnder
9792: bd 36 07                     lda     MushroomLedgeHalfLen,x  ;get divided length and store where length
9795: 85 06                        sta     $06                     ; was stored originally
9797: a6 07                        ldx     $07
9799: a9 1a                        lda     #$1a
979b: 9d a1 06                     sta     MetatileBuffer,x        ;render middle of mushroom
979e: c4 06                        cpy     $06                     ;are we smack dab in the center?
97a0: d0 2c                        bne     MushLExit               ;if not, branch to leave
97a2: e8                           inx
97a3: a9 4f                        lda     #$4f
97a5: 9d a1 06                     sta     MetatileBuffer,x        ;render stem top of mushroom underneath the middle
97a8: a9 50                        lda     #$50
97aa: e8           AllUnder        inx
97ab: a0 0f                        ldy     #$0f                    ;set $0f to render all way down
97ad: 4c 7d 9b                     jmp     RenderUnderPart         ;now render the stem of mushroom

97b0: a6 07        NoUnder         ldx     $07                     ;load row of ledge
97b2: a0 00                        ldy     #$00                    ;set 0 for no bottom on this part
97b4: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
                   ; tiles used by pulleys and rope object
                   PulleyRopeMetatiles
97b7: 42 41 43                     .bulk   $42,$41,$43

                   PulleyRopeObject
97ba: 20 ac 9b                     jsr     ChkLrgObjLength         ;get length of pulley/rope object
97bd: a0 00                        ldy     #$00                    ;initialize metatile offset
97bf: b0 07                        bcs     RenderPul               ;if starting, render left pulley
97c1: c8                           iny
97c2: bd 30 07                     lda     AreaObjectLength,x      ;if not at the end, render rope
97c5: d0 01                        bne     RenderPul
97c7: c8                           iny                             ;otherwise render right pulley
97c8: b9 b7 97     RenderPul       lda     PulleyRopeMetatiles,y
97cb: 8d a1 06                     sta     MetatileBuffer          ;render at the top of the screen
97ce: 60           MushLExit       rts                             ;and leave

                   ; -----------------------------------------------------------------------------
                   ; $06 - used to store upper limit of rows for CastleObject
97cf: 00 45 45 45+ CastleMetatiles .bulk   $00,$45,$45,$45,$00
97d4: 00 48 47 46+                 .bulk   $00,$48,$47,$46,$00
97d9: 45 49 49 49+                 .bulk   $45,$49,$49,$49,$45
97de: 47 47 4a 47+                 .bulk   $47,$47,$4a,$47,$47
97e3: 47 47 4b 47+                 .bulk   $47,$47,$4b,$47,$47
97e8: 49 49 49 49+                 .bulk   $49,$49,$49,$49,$49
97ed: 47 4a 47 4a+                 .bulk   $47,$4a,$47,$4a,$47
97f2: 47 4b 47 4b+                 .bulk   $47,$4b,$47,$4b,$47
97f7: 47 47 47 47+                 .bulk   $47,$47,$47,$47,$47
97fc: 4a 47 4a 47+                 .bulk   $4a,$47,$4a,$47,$4a
9801: 4b 47 4b 47+                 .bulk   $4b,$47,$4b,$47,$4b

9806: 20 bb 9b     CastleObject    jsr     GetLrgObjAttrib         ;save lower nybble as starting row
9809: 84 07                        sty     $07                     ;if starting row is above $0a, game will crash!!!
980b: a0 04                        ldy     #$04
980d: 20 af 9b                     jsr     ChkLrgObjFixedLength    ;load length of castle if not already loaded
9810: 8a                           txa
9811: 48                           pha                             ;save obj buffer offset to stack
9812: bc 30 07                     ldy     AreaObjectLength,x      ;use current length as offset for castle data
9815: a6 07                        ldx     $07                     ;begin at starting row
9817: a9 0b                        lda     #$0b
9819: 85 06                        sta     $06                     ;load upper limit of number of rows to print
981b: b9 cf 97     CRendLoop       lda     CastleMetatiles,y       ;load current byte using offset
981e: 9d a1 06                     sta     MetatileBuffer,x
9821: e8                           inx                             ;store in buffer and increment buffer offset
9822: a5 06                        lda     $06
9824: f0 07                        beq     ChkCFloor               ;have we reached upper limit yet?
9826: c8                           iny                             ;if not, increment column-wise
9827: c8                           iny                             ; to byte in next row
9828: c8                           iny
9829: c8                           iny
982a: c8                           iny
982b: c6 06                        dec     $06                     ;move closer to upper limit
982d: e0 0b        ChkCFloor       cpx     #$0b                    ;have we reached the row just before floor?
982f: d0 ea                        bne     CRendLoop               ;if not, go back and do another row
9831: 68                           pla
9832: aa                           tax                             ;get obj buffer offset from before
9833: ad 25 07                     lda     CurrentPageLoc
9836: f0 36                        beq     ExitCastle              ;if we're at page 0, we do not need to do anything else
9838: bd 30 07                     lda     AreaObjectLength,x      ;check length
983b: c9 01                        cmp     #$01                    ;if length almost about to expire, put brick at floor
983d: f0 2a                        beq     PlayerStop
983f: a4 07                        ldy     $07                     ;check starting row for tall castle ($00)
9841: d0 04                        bne     NotTall
9843: c9 03                        cmp     #$03                    ;if found, then check to see if we're at the second column
9845: f0 22                        beq     PlayerStop
9847: c9 02        NotTall         cmp     #$02                    ;if not tall castle, check to see if we're at the third column
9849: d0 23                        bne     ExitCastle              ;if we aren't and the castle is tall, don't create flag yet
984b: 20 cb 9b                     jsr     GetAreaObjXPosition     ;otherwise, obtain and save horizontal pixel coordinate
984e: 48                           pha
984f: 20 4a 99                     jsr     FindEmptyEnemySlot      ;find an empty place on the enemy object buffer
9852: 68                           pla
9853: 95 87                        sta     Enemy_X_Position,x      ;then write horizontal coordinate for star flag
9855: ad 25 07                     lda     CurrentPageLoc
9858: 95 6e                        sta     Enemy_PageLoc,x         ;set page location for star flag
985a: a9 01                        lda     #$01
985c: 95 b6                        sta     Enemy_Y_HighPos,x       ;set vertical high byte
985e: 95 0f                        sta     Enemy_Flag,x            ;set flag for buffer
9860: a9 90                        lda     #$90
9862: 95 cf                        sta     Enemy_Y_Position,x      ;set vertical coordinate
9864: a9 31                        lda     #StarFlagObject         ;set star flag value in buffer itself
9866: 95 16                        sta     Enemy_ID,x
9868: 60                           rts

9869: a0 52        PlayerStop      ldy     #$52                    ;put brick at floor to stop player at end of level
986b: 8c ab 06                     sty     MetatileBuffer+10       ;this is only done if we're on the second column
986e: 60           ExitCastle      rts

                   ; -----------------------------------------------------------------------------
986f: 20 bb 9b     WaterPipe       jsr     GetLrgObjAttrib         ;get row and lower nybble
9872: bc 30 07                     ldy     AreaObjectLength,x      ;get length (residual code, water pipe is 1 col thick)
9875: a6 07                        ldx     $07                     ;get row
9877: a9 6b                        lda     #$6b
9879: 9d a1 06                     sta     MetatileBuffer,x        ;draw something here and below it
987c: a9 6c                        lda     #$6c
987e: 9d a2 06                     sta     MetatileBuffer+1,x
9881: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $05 - used to store length of vertical shaft in RenderSidewaysPipe
                   ; $06 - used to store leftover horizontal length in RenderSidewaysPipe and
                   ; vertical length in VerticalPipe and GetPipeHeight
9882: a0 03        IntroPipe       ldy     #$03                    ;check if length set, if not set, set it
9884: 20 af 9b                     jsr     ChkLrgObjFixedLength
9887: a0 0a                        ldy     #$0a                    ;set fixed value and render the sideways part
9889: 20 b3 98                     jsr     RenderSidewaysPipe
988c: b0 10                        bcs     NoBlankP                ;if carry flag set, not time to draw vertical pipe part
988e: a2 06                        ldx     #$06                    ;blank everything above the vertical pipe part
9890: a9 00        VPipeSectLoop   lda     #$00                    ; all the way to the top of the screen
9892: 9d a1 06                     sta     MetatileBuffer,x        ; because otherwise it will look like exit pipe
9895: ca                           dex
9896: 10 f8                        bpl     VPipeSectLoop
9898: b9 dd 98                     lda     VerticalPipeData,y      ;draw the end of the vertical pipe part
989b: 8d a8 06                     sta     MetatileBuffer+7
989e: 60           NoBlankP        rts

                   SidePipeShaftData
989f: 15 14                        .bulk   $15,$14                 ;used to control whether or not vertical pipe shaft
98a1: 00 00                        .bulk   $00,$00                 ; is drawn, and if so, controls the metatile number
98a3: 15 1e        SidePipeTopPart .bulk   $15,$1e                 ;top part of sideways part of pipe
98a5: 1d 1c                        .bulk   $1d,$1c
                   SidePipeBottomPart
98a7: 15 21                        .bulk   $15,$21                 ;bottom part of sideways part of pipe
98a9: 20 1f                        .bulk   $20,$1f

98ab: a0 03        ExitPipe        ldy     #$03                    ;check if length set, if not set, set it
98ad: 20 af 9b                     jsr     ChkLrgObjFixedLength
98b0: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get vertical length, then plow on through RenderSidewaysPipe
                   RenderSidewaysPipe
98b3: 88                           dey                             ;decrement twice to make room for shaft at bottom
98b4: 88                           dey                             ; and store here for now as vertical length
98b5: 84 05                        sty     $05
98b7: bc 30 07                     ldy     AreaObjectLength,x      ;get length left over and store here
98ba: 84 06                        sty     $06
98bc: a6 05                        ldx     $05                     ;get vertical length plus one, use as buffer offset
98be: e8                           inx
98bf: b9 9f 98                     lda     SidePipeShaftData,y     ;check for value $00 based on horizontal offset
98c2: c9 00                        cmp     #$00
98c4: f0 08                        beq     DrawSidePart            ;if found, do not draw the vertical pipe shaft
98c6: a2 00                        ldx     #$00
98c8: a4 05                        ldy     $05                     ;init buffer offset and get vertical length
98ca: 20 7d 9b                     jsr     RenderUnderPart         ; and render vertical shaft using tile number in A
98cd: 18                           clc                             ;clear carry flag to be used by IntroPipe
98ce: a4 06        DrawSidePart    ldy     $06                     ;render side pipe part at the bottom
98d0: b9 a3 98                     lda     SidePipeTopPart,y
98d3: 9d a1 06                     sta     MetatileBuffer,x        ;note that the pipe parts are stored
98d6: b9 a7 98                     lda     SidePipeBottomPart,y    ; backwards horizontally
98d9: 9d a2 06                     sta     MetatileBuffer+1,x
98dc: 60                           rts

                   VerticalPipeData
98dd: 11 10                        .bulk   $11,$10                 ;used by pipes that lead somewhere
98df: 15 14                        .bulk   $15,$14
98e1: 13 12                        .bulk   $13,$12                 ;used by decoration pipes
98e3: 15 14                        .bulk   $15,$14

98e5: 20 39 99     VerticalPipe    jsr     GetPipeHeight
98e8: a5 00                        lda     $00                     ;check to see if value was nullified earlier
98ea: f0 04                        beq     WarpPipe                ;(if d3, the usage control bit of second byte, was set)
98ec: c8                           iny
98ed: c8                           iny
98ee: c8                           iny
98ef: c8                           iny                             ;add four if usage control bit was not set
98f0: 98           WarpPipe        tya                             ;save value in stack
98f1: 48                           pha
98f2: ad 60 07                     lda     AreaNumber
98f5: 0d 5f 07                     ora     WorldNumber             ;if at world 1-1, do not add piranha plant ever
98f8: f0 2b                        beq     DrawPipe
98fa: bc 30 07                     ldy     AreaObjectLength,x      ;if on second column of pipe, branch
98fd: f0 26                        beq     DrawPipe                ;(because we only need to do this once)
98ff: 20 4a 99                     jsr     FindEmptyEnemySlot      ;check for an empty moving data buffer space
9902: b0 21                        bcs     DrawPipe                ;if not found, too many enemies, thus skip
9904: 20 cb 9b                     jsr     GetAreaObjXPosition     ;get horizontal pixel coordinate
9907: 18                           clc
9908: 69 08                        adc     #$08                    ;add eight to put the piranha plant in the center
990a: 95 87                        sta     Enemy_X_Position,x      ;store as enemy's horizontal coordinate
990c: ad 25 07                     lda     CurrentPageLoc          ;add carry to current page number
990f: 69 00                        adc     #$00
9911: 95 6e                        sta     Enemy_PageLoc,x         ;store as enemy's page coordinate
9913: a9 01                        lda     #$01
9915: 95 b6                        sta     Enemy_Y_HighPos,x
9917: 95 0f                        sta     Enemy_Flag,x            ;activate enemy flag
9919: 20 d3 9b                     jsr     GetAreaObjYPosition     ;get piranha plant's vertical coordinate and store here
991c: 95 cf                        sta     Enemy_Y_Position,x
991e: a9 0d                        lda     #PiranhaPlant           ;write piranha plant's value into buffer
9920: 95 16                        sta     Enemy_ID,x
9922: 20 87 c7                     jsr     InitPiranhaPlant
9925: 68           DrawPipe        pla                             ;get value saved earlier and use as Y
9926: a8                           tay
9927: a6 07                        ldx     $07                     ;get buffer offset
9929: b9 dd 98                     lda     VerticalPipeData,y      ;draw the appropriate pipe with the Y we loaded earlier
992c: 9d a1 06                     sta     MetatileBuffer,x        ;render the top of the pipe
992f: e8                           inx
9930: b9 df 98                     lda     VerticalPipeData+2,y    ;render the rest of the pipe
9933: a4 06                        ldy     $06                     ;subtract one from length and render the part underneath
9935: 88                           dey
9936: 4c 7d 9b                     jmp     RenderUnderPart

9939: a0 01        GetPipeHeight   ldy     #$01                    ;check for length loaded, if not, load
993b: 20 af 9b                     jsr     ChkLrgObjFixedLength    ;pipe length of 2 (horizontal)
993e: 20 bb 9b                     jsr     GetLrgObjAttrib
9941: 98                           tya                             ;get saved lower nybble as height
9942: 29 07                        and     #$07                    ;save only the three lower bits as
9944: 85 06                        sta     $06                     ; vertical length, then load Y with
9946: bc 30 07                     ldy     AreaObjectLength,x      ; length left over
9949: 60                           rts

                   FindEmptyEnemySlot
994a: a2 00                        ldx     #$00                    ;start at first enemy slot
994c: 18           EmptyChkLoop    clc                             ;clear carry flag by default
994d: b5 0f                        lda     Enemy_Flag,x            ;check enemy buffer for nonzero
994f: f0 05                        beq     ExitEmptyChk            ;if zero, leave
9951: e8                           inx
9952: e0 05                        cpx     #$05                    ;if nonzero, check next value
9954: d0 f6                        bne     EmptyChkLoop
9956: 60           ExitEmptyChk    rts                             ;if all values nonzero, carry flag is set

                   ; -----------------------------------------------------------------------------
9957: 20 ac 9b     Hole_Water      jsr     ChkLrgObjLength         ;get low nybble and save as length
995a: a9 86                        lda     #$86                    ;render waves
995c: 8d ab 06                     sta     MetatileBuffer+10
995f: a2 0b                        ldx     #$0b
9961: a0 01                        ldy     #$01                    ;now render the water underneath
9963: a9 87                        lda     #$87
9965: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
                   QuestionBlockRow_High
9968: a9 03                        lda     #$03                    ;start on the fourth row
996a: 2c                           bit ▼   PseudoRandomBitReg+2    ;BIT instruction opcode
                   QuestionBlockRow_Low
996b: a9 07                        lda     #$07                    ;start on the eighth row
996d: 48                           pha                             ;save whatever row to the stack for now
996e: 20 ac 9b                     jsr     ChkLrgObjLength         ;get low nybble and save as length
9971: 68                           pla
9972: aa                           tax                             ;render question boxes with coins
9973: a9 c0                        lda     #$c0
9975: 9d a1 06                     sta     MetatileBuffer,x
9978: 60                           rts

                   ; -----------------------------------------------------------------------------
9979: a9 06        Bridge_High     lda     #$06                    ;start on the seventh row from top of screen
997b: 2c                           bit ▼   PseudoRandomBitReg+2    ;BIT instruction opcode
997c: a9 07        Bridge_Middle   lda     #$07                    ;start on the eighth row
997e: 2c                           bit ▼   $09a9                   ;BIT instruction opcode
997f: a9 09        Bridge_Low      lda     #$09                    ;start on the tenth row
9981: 48                           pha                             ;save whatever row to the stack for now
9982: 20 ac 9b                     jsr     ChkLrgObjLength         ;get low nybble and save as length
9985: 68                           pla
9986: aa                           tax                             ;render bridge railing
9987: a9 0b                        lda     #$0b
9989: 9d a1 06                     sta     MetatileBuffer,x
998c: e8                           inx
998d: a0 00                        ldy     #$00                    ;now render the bridge itself
998f: a9 63                        lda     #$63
9991: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
                   FlagBalls_Residual
9994: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get low nybble from object byte
9997: a2 02                        ldx     #$02                    ;render flag balls on third row from top
9999: a9 6d                        lda     #$6d                    ; of screen downwards based on low nybble
999b: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
999e: a9 24        FlagpoleObject  lda     #$24                    ;render flagpole ball on top
99a0: 8d a1 06                     sta     MetatileBuffer
99a3: a2 01                        ldx     #$01                    ;now render the flagpole shaft
99a5: a0 08                        ldy     #$08
99a7: a9 25                        lda     #$25
99a9: 20 7d 9b                     jsr     RenderUnderPart
99ac: a9 61                        lda     #$61                    ;render solid block at the bottom
99ae: 8d ab 06                     sta     MetatileBuffer+10
99b1: 20 cb 9b                     jsr     GetAreaObjXPosition
99b4: 38                           sec                             ;get pixel coordinate of where the flagpole is,
99b5: e9 08                        sbc     #$08                    ; subtract eight pixels and use as horizontal
99b7: 85 8c                        sta     Enemy_X_Position+5      ; coordinate for the flag
99b9: ad 25 07                     lda     CurrentPageLoc
99bc: e9 00                        sbc     #$00                    ;subtract borrow from page location and use as
99be: 85 73                        sta     Enemy_PageLoc+5         ; page location for the flag
99c0: a9 30                        lda     #$30
99c2: 85 d4                        sta     Enemy_Y_Position+5      ;set vertical coordinate for flag
99c4: a9 b0                        lda     #$b0
99c6: 8d 0d 01                     sta     FlagpoleFNum_Y_Pos      ;set initial vertical coordinate for flagpole's floatey number
99c9: a9 30                        lda     #FlagpoleFlagObject
99cb: 85 1b                        sta     Enemy_ID+5              ;set flag identifier, note that identifier and coordinates
99cd: e6 14                        inc     Enemy_Flag+5            ;use last space in enemy object buffer
99cf: 60                           rts

                   ; -----------------------------------------------------------------------------
99d0: a2 00        EndlessRope     ldx     #$00                    ;render rope from the top to the bottom of screen
99d2: a0 0f                        ldy     #$0f
99d4: 4c e9 99                     jmp     DrawRope

99d7: 8a           BalancePlatRope txa                             ;save object buffer offset for now
99d8: 48                           pha
99d9: a2 01                        ldx     #$01                    ;blank out all from second row to the bottom
99db: a0 0f                        ldy     #$0f                    ; with blank used for balance platform rope
99dd: a9 44                        lda     #$44
99df: 20 7d 9b                     jsr     RenderUnderPart
99e2: 68                           pla                             ;get back object buffer offset
99e3: aa                           tax
99e4: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get vertical length from lower nybble
99e7: a2 01                        ldx     #$01
99e9: a9 40        DrawRope        lda     #$40                    ;render the actual rope
99eb: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
                   CoinMetatileData
99ee: c3 c2 c2 c2                  .bulk   $c3,$c2,$c2,$c2

99f2: ac 4e 07     RowOfCoins      ldy     AreaType                ;get area type
99f5: b9 ee 99                     lda     CoinMetatileData,y      ;load appropriate coin metatile
99f8: 4c 44 9a                     jmp     GetRow

                   ; -----------------------------------------------------------------------------
99fb: 06 07 08     C_ObjectRow     .bulk   $06,$07,$08
                   C_ObjectMetatile
99fe: c5 0c 89                     .bulk   $c5,$0c,$89

9a01: a0 0c        CastleBridgeObj ldy     #$0c                    ;load length of 13 columns
9a03: 20 af 9b                     jsr     ChkLrgObjFixedLength
9a06: 4c 0e 9a                     jmp     ChainObj

9a09: a9 08        AxeObj          lda     #$08                    ;load bowser's palette into sprite portion of palette
9a0b: 8d 73 07                     sta     VRAM_Buffer_AddrCtrl
9a0e: a4 00        ChainObj        ldy     $00                     ;get value loaded earlier from decoder
9a10: be f9 99                     ldx     C_ObjectRow-2,y         ;get appropriate row and metatile for object
9a13: b9 fc 99                     lda     C_ObjectMetatile-2,y
9a16: 4c 20 9a                     jmp     ColObj

9a19: 20 bb 9b     EmptyBlock      jsr     GetLrgObjAttrib         ;get row location
9a1c: a6 07                        ldx     $07
9a1e: a9 c4                        lda     #$c4
9a20: a0 00        ColObj          ldy     #$00                    ;column length of 1
9a22: 4c 7d 9b                     jmp     RenderUnderPart

                   SolidBlockMetatiles
9a25: 69 61 61 62                  .bulk   $69,$61,$61,$62
9a29: 22 51 52 52  BrickMetatiles  .bulk   $22,$51,$52,$52
9a2d: 88                           .dd1    $88                     ;used only by row of bricks object

9a2e: ac 4e 07     RowOfBricks     ldy     AreaType                ;load area type obtained from area offset pointer
9a31: ad 43 07                     lda     CloudTypeOverride       ;check for cloud type override
9a34: f0 02                        beq     DrawBricks
9a36: a0 04                        ldy     #$04                    ;if cloud type, override area type
9a38: b9 29 9a     DrawBricks      lda     BrickMetatiles,y        ;get appropriate metatile
9a3b: 4c 44 9a                     jmp     GetRow                  ;and go render it

                   RowOfSolidBlocks
9a3e: ac 4e 07                     ldy     AreaType                ;load area type obtained from area offset pointer
9a41: b9 25 9a                     lda     SolidBlockMetatiles,y   ;get metatile
9a44: 48           GetRow          pha                             ;store metatile here
9a45: 20 ac 9b                     jsr     ChkLrgObjLength         ;get row number, load length
9a48: a6 07        DrawRow         ldx     $07
9a4a: a0 00                        ldy     #$00                    ;set vertical height of 1
9a4c: 68                           pla
9a4d: 4c 7d 9b                     jmp     RenderUnderPart         ;render object

9a50: ac 4e 07     ColumnOfBricks  ldy     AreaType                ;load area type obtained from area offset
9a53: b9 29 9a                     lda     BrickMetatiles,y        ;get metatile (no cloud override as for row)
9a56: 4c 5f 9a                     jmp     GetRow2

                   ColumnOfSolidBlocks
9a59: ac 4e 07                     ldy     AreaType                ;load area type obtained from area offset
9a5c: b9 25 9a                     lda     SolidBlockMetatiles,y   ;get metatile
9a5f: 48           GetRow2         pha                             ;save metatile to stack for now
9a60: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get length and row
9a63: 68                           pla                             ;restore metatile
9a64: a6 07                        ldx     $07                     ;get starting row
9a66: 4c 7d 9b                     jmp     RenderUnderPart         ;now render the column

                   ; -----------------------------------------------------------------------------
                   BulletBillCannon
9a69: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get row and length of bullet bill cannon
9a6c: a6 07                        ldx     $07                     ;start at first row
9a6e: a9 64                        lda     #$64                    ;render bullet bill cannon
9a70: 9d a1 06                     sta     MetatileBuffer,x
9a73: e8                           inx
9a74: 88                           dey                             ;done yet?
9a75: 30 0e                        bmi     SetupCannon
9a77: a9 65                        lda     #$65                    ;if not, render middle part
9a79: 9d a1 06                     sta     MetatileBuffer,x
9a7c: e8                           inx
9a7d: 88                           dey                             ;done yet?
9a7e: 30 05                        bmi     SetupCannon
9a80: a9 66                        lda     #$66                    ;if not, render bottom until length expires
9a82: 20 7d 9b                     jsr     RenderUnderPart
9a85: ae 6a 04     SetupCannon     ldx     Cannon_Offset           ;get offset for data used by cannons and whirlpools
9a88: 20 d3 9b                     jsr     GetAreaObjYPosition     ;get proper vertical coordinate for cannon
9a8b: 9d 77 04                     sta     Cannon_Y_Position,x     ;and store it here
9a8e: ad 25 07                     lda     CurrentPageLoc
9a91: 9d 6b 04                     sta     Cannon_PageLoc,x        ;store page number for cannon here
9a94: 20 cb 9b                     jsr     GetAreaObjXPosition     ;get proper horizontal coordinate for cannon
9a97: 9d 71 04                     sta     Cannon_X_Position,x     ; and store it here
9a9a: e8                           inx
9a9b: e0 06                        cpx     #$06                    ;increment and check offset
9a9d: 90 02                        bcc     StrCOffset              ;if not yet reached sixth cannon, branch to save offset
9a9f: a2 00                        ldx     #$00                    ;otherwise initialize it
9aa1: 8e 6a 04     StrCOffset      stx     Cannon_Offset           ;save new offset and leave
9aa4: 60                           rts

                   ; -----------------------------------------------------------------------------
                   StaircaseHeightData
9aa5: 07 07 06 05+                 .bulk   $07,$07,$06,$05,$04,$03,$02,$01,$00
                   StaircaseRowData
9aae: 03 03 04 05+                 .bulk   $03,$03,$04,$05,$06,$07,$08,$09,$0a

9ab7: 20 ac 9b     StaircaseObject jsr     ChkLrgObjLength         ;check and load length
9aba: 90 05                        bcc     NextStair               ;if length already loaded, skip init part
9abc: a9 09                        lda     #$09                    ;start past the end for the bottom
9abe: 8d 34 07                     sta     StaircaseControl        ; of the staircase
9ac1: ce 34 07     NextStair       dec     StaircaseControl        ;move onto next step (or first if starting)
9ac4: ac 34 07                     ldy     StaircaseControl
9ac7: be ae 9a                     ldx     StaircaseRowData,y      ;get starting row and height to render
9aca: b9 a5 9a                     lda     StaircaseHeightData,y
9acd: a8                           tay
9ace: a9 61                        lda     #$61                    ;now render solid block staircase
9ad0: 4c 7d 9b                     jmp     RenderUnderPart

                   ; -----------------------------------------------------------------------------
9ad3: 20 bb 9b     JumpSpring      jsr     GetLrgObjAttrib
9ad6: 20 4a 99                     jsr     FindEmptyEnemySlot      ;find empty space in enemy object buffer
9ad9: 20 cb 9b                     jsr     GetAreaObjXPosition     ;get horizontal coordinate for jumpspring
9adc: 95 87                        sta     Enemy_X_Position,x      ;and store
9ade: ad 25 07                     lda     CurrentPageLoc          ;store page location of jumpspring
9ae1: 95 6e                        sta     Enemy_PageLoc,x
9ae3: 20 d3 9b                     jsr     GetAreaObjYPosition     ;get vertical coordinate for jumpspring
9ae6: 95 cf                        sta     Enemy_Y_Position,x      ;and store
9ae8: 95 58                        sta     Jumpspring_FixedYPos,x  ;store as permanent coordinate here
9aea: a9 32                        lda     #JumpspringObject
9aec: 95 16                        sta     Enemy_ID,x              ;write jumpspring object to enemy object buffer
9aee: a0 01                        ldy     #$01
9af0: 94 b6                        sty     Enemy_Y_HighPos,x       ;store vertical high byte
9af2: f6 0f                        inc     Enemy_Flag,x            ;set flag for enemy object buffer
9af4: a6 07                        ldx     $07
9af6: a9 67                        lda     #$67                    ;draw metatiles in two rows where jumpspring is
9af8: 9d a1 06                     sta     MetatileBuffer,x
9afb: a9 68                        lda     #$68
9afd: 9d a2 06                     sta     MetatileBuffer+1,x
9b00: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $07 - used to save ID of brick object
9b01: ad 5d 07     Hidden1UpBlock  lda     Hidden1UpFlag           ;if flag not set, do not render object
9b04: f0 36                        beq     ExitDecBlock
9b06: a9 00                        lda     #$00                    ;if set, init for the next one
9b08: 8d 5d 07                     sta     Hidden1UpFlag
9b0b: 4c 19 9b                     jmp     BrickWithItem           ;jump to code shared with unbreakable bricks

9b0e: 20 36 9b     QuestionBlock   jsr     GetAreaObjectID         ;get value from level decoder routine
9b11: 4c 2c 9b                     jmp     DrawQBlk                ;go to render it

9b14: a9 00        BrickWithCoins  lda     #$00                    ;initialize multi-coin timer flag
9b16: 8d bc 06                     sta     BrickCoinTimerFlag
9b19: 20 36 9b     BrickWithItem   jsr     GetAreaObjectID         ;save area object ID
9b1c: 84 07                        sty     $07
9b1e: a9 00                        lda     #$00                    ;load default adder for bricks with lines
9b20: ac 4e 07                     ldy     AreaType                ;check level type for ground level
9b23: 88                           dey
9b24: f0 02                        beq     BWithL                  ;if ground type, do not start with 5
9b26: a9 05                        lda     #$05                    ;otherwise use adder for bricks without lines
9b28: 18           BWithL          clc                             ;add object ID to adder
9b29: 65 07                        adc     $07
9b2b: a8                           tay                             ;use as offset for metatile
9b2c: b9 e8 bd     DrawQBlk        lda     BrickQBlockMetatiles,y  ;get appropriate metatile for brick (question block
9b2f: 48                           pha                             ; if branched to here from question block routine)
9b30: 20 bb 9b                     jsr     GetLrgObjAttrib         ;get row from location byte
9b33: 4c 48 9a                     jmp     DrawRow                 ;now render the object

9b36: a5 00        GetAreaObjectID lda     $00                     ;get value saved from area parser routine
9b38: 38                           sec
9b39: e9 00                        sbc     #$00                    ;possibly residual code
9b3b: a8                           tay                             ;save to Y
9b3c: 60           ExitDecBlock    rts

                   ; -----------------------------------------------------------------------------
9b3d: 87 00 00 00  HoleMetatiles   .bulk   $87,$00,$00,$00

9b41: 20 ac 9b     Hole_Empty      jsr     ChkLrgObjLength         ;get lower nybble and save as length
9b44: 90 2d                        bcc     NoWhirlP                ;skip this part if length already loaded
9b46: ad 4e 07                     lda     AreaType                ;check for water type level
9b49: d0 28                        bne     NoWhirlP                ;if not water type, skip this part
9b4b: ae 6a 04                     ldx     Whirlpool_Offset        ;get offset for data used by cannons and whirlpools
9b4e: 20 cb 9b                     jsr     GetAreaObjXPosition     ;get proper vertical coordinate of where we're at
9b51: 38                           sec
9b52: e9 10                        sbc     #$10                    ;subtract 16 pixels
9b54: 9d 71 04                     sta     Whirlpool_LeftExtent,x  ;store as left extent of whirlpool
9b57: ad 25 07                     lda     CurrentPageLoc          ;get page location of where we're at
9b5a: e9 00                        sbc     #$00                    ;subtract borrow
9b5c: 9d 6b 04                     sta     Whirlpool_PageLoc,x     ;save as page location of whirlpool
9b5f: c8                           iny
9b60: c8                           iny                             ;increment length by 2
9b61: 98                           tya
9b62: 0a                           asl     A                       ;multiply by 16 to get size of whirlpool
9b63: 0a                           asl     A                       ;note that whirlpool will always be
9b64: 0a                           asl     A                       ; two blocks bigger than actual size of hole
9b65: 0a                           asl     A                       ; and extend one block beyond each edge
9b66: 9d 77 04                     sta     Whirlpool_Length,x      ; save size of whirlpool here
9b69: e8                           inx
9b6a: e0 05                        cpx     #$05                    ;increment and check offset
9b6c: 90 02                        bcc     StrWOffset              ;if not yet reached fifth whirlpool, branch to save offset
9b6e: a2 00                        ldx     #$00                    ;otherwise initialize it
9b70: 8e 6a 04     StrWOffset      stx     Whirlpool_Offset        ;save new offset here
9b73: ae 4e 07     NoWhirlP        ldx     AreaType                ;get appropriate metatile, then
9b76: bd 3d 9b                     lda     HoleMetatiles,x         ; render the hole proper
9b79: a2 08                        ldx     #$08
9b7b: a0 0f                        ldy     #$0f                    ;start at ninth row and go to bottom, run RenderUnderPart
                   ; 
9b7d: 8c 35 07     RenderUnderPart sty     AreaObjectHeight        ;store vertical length to render
9b80: bc a1 06                     ldy     MetatileBuffer,x        ;check current spot to see if there's something
9b83: f0 18                        beq     DrawThisRow             ;we need to keep, if nothing, go ahead
9b85: c0 17                        cpy     #$17
9b87: f0 17                        beq     WaitOneRow              ;if middle part (tree ledge), wait until next row
9b89: c0 1a                        cpy     #$1a
9b8b: f0 13                        beq     WaitOneRow              ;if middle part (mushroom ledge), wait until next row
9b8d: c0 c0                        cpy     #$c0
9b8f: f0 0c                        beq     DrawThisRow             ;if question block w/ coin, overwrite
9b91: c0 c0                        cpy     #$c0
9b93: b0 0b                        bcs     WaitOneRow              ;if any other metatile with palette 3, wait until next row
9b95: c0 54                        cpy     #$54
9b97: d0 04                        bne     DrawThisRow             ;if cracked rock terrain, overwrite
9b99: c9 50                        cmp     #$50
9b9b: f0 03                        beq     WaitOneRow              ;if stem top of mushroom, wait until next row
9b9d: 9d a1 06     DrawThisRow     sta     MetatileBuffer,x        ;render contents of A from routine that called this
9ba0: e8           WaitOneRow      inx
9ba1: e0 0d                        cpx     #$0d                    ;stop rendering if we're at the bottom of the screen
9ba3: b0 06                        bcs     ExitUPartR
9ba5: ac 35 07                     ldy     AreaObjectHeight        ;decrement, and stop rendering if there is no more length
9ba8: 88                           dey
9ba9: 10 d2                        bpl     RenderUnderPart
9bab: 60           ExitUPartR      rts

                   ; -----------------------------------------------------------------------------
9bac: 20 bb 9b     ChkLrgObjLength jsr     GetLrgObjAttrib         ;get row location and size (length if branched to from here)
                   ChkLrgObjFixedLength
9baf: bd 30 07                     lda     AreaObjectLength,x      ;check for set length counter
9bb2: 18                           clc                             ;clear carry flag for not just starting
9bb3: 10 05                        bpl     LenSet                  ;if counter not set, load it, otherwise leave alone
9bb5: 98                           tya                             ;save length into length counter
9bb6: 9d 30 07                     sta     AreaObjectLength,x
9bb9: 38                           sec                             ;set carry flag if just starting
9bba: 60           LenSet          rts

9bbb: bc 2d 07     GetLrgObjAttrib ldy     AreaObjOffsetBuffer,x   ;get offset saved from area obj decoding routine
9bbe: b1 e7                        lda     (AreaData),y            ;get first byte of level object
9bc0: 29 0f                        and     #%00001111
9bc2: 85 07                        sta     $07                     ;save row location
9bc4: c8                           iny
9bc5: b1 e7                        lda     (AreaData),y            ;get next byte, save lower nybble (length or height)
9bc7: 29 0f                        and     #%00001111              ; as Y, then leave
9bc9: a8                           tay
9bca: 60                           rts

                   ; -----------------------------------------------------------------------------
                   GetAreaObjXPosition
9bcb: ad 26 07                     lda     CurrentColumnPos        ;multiply current offset where we're at by 16
9bce: 0a                           asl     A                       ; to obtain horizontal pixel coordinate
9bcf: 0a                           asl     A
9bd0: 0a                           asl     A
9bd1: 0a                           asl     A
9bd2: 60                           rts

                   ; -----------------------------------------------------------------------------
                   GetAreaObjYPosition
9bd3: a5 07                        lda     $07                     ;multiply value by 16
9bd5: 0a                           asl     A
9bd6: 0a                           asl     A                       ;this will give us the proper vertical pixel coordinate
9bd7: 0a                           asl     A
9bd8: 0a                           asl     A
9bd9: 18                           clc
9bda: 69 20                        adc     #32                     ;add 32 pixels for the status bar
9bdc: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $06-$07 - used to store block buffer address used as indirect
9bdd: 00           BlockBufferAddr .dd1    <Block_Buffer_1
9bde: d0                           .dd1    <Block_Buffer_2
9bdf: 05                           .dd1    >Block_Buffer_1
9be0: 05                           .dd1    >Block_Buffer_2

                   GetBlockBufferAddr
9be1: 48                           pha                             ;take value of A, save
9be2: 4a                           lsr     A                       ;move high nybble to low
9be3: 4a                           lsr     A
9be4: 4a                           lsr     A
9be5: 4a                           lsr     A
9be6: a8                           tay                             ;use nybble as pointer to high byte
9be7: b9 df 9b                     lda     BlockBufferAddr+2,y     ; of indirect here
9bea: 85 07                        sta     $07
9bec: 68                           pla
9bed: 29 0f                        and     #%00001111              ;pull from stack, mask out high nybble
9bef: 18                           clc
9bf0: 79 dd 9b                     adc     BlockBufferAddr,y       ;add to low byte
9bf3: 85 06                        sta     $06                     ;store here and leave
9bf5: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; unused space
9bf6: ff                           .dd1    $ff
9bf7: ff                           .dd1    $ff
                   ; -----------------------------------------------------------------------------
                   AreaDataOfsLoopback
9bf8: 12 36 0e 0e+                 .bulk   $12,$36,$0e,$0e,$0e,$32,$32,$32,$0a,$26,$40

                   ; -----------------------------------------------------------------------------
9c03: 20 13 9c     LoadAreaPointer jsr     FindAreaPointer         ;find it and store it here
9c06: 8d 50 07                     sta     AreaPointer
9c09: 29 60        GetAreaType     and     #%01100000              ;mask out all but d6 and d5
9c0b: 0a                           asl     A
9c0c: 2a                           rol     A
9c0d: 2a                           rol     A
9c0e: 2a                           rol     A                       ;make %0xx00000 into %000000xx
9c0f: 8d 4e 07                     sta     AreaType                ;save 2 MSB as area type
9c12: 60                           rts

9c13: ac 5f 07     FindAreaPointer ldy     WorldNumber             ;load offset from world variable
9c16: b9 b4 9c                     lda     WorldAddrOffsets,y
9c19: 18                           clc                             ;add area number used to find data
9c1a: 6d 60 07                     adc     AreaNumber
9c1d: a8                           tay
9c1e: b9 bc 9c                     lda     AreaAddrOffsets,y       ;from there we have our area pointer
9c21: 60                           rts

                   GetAreaDataAddrs
9c22: ad 50 07                     lda     AreaPointer             ;use 2 MSB for Y
9c25: 20 09 9c                     jsr     GetAreaType
9c28: a8                           tay
9c29: ad 50 07                     lda     AreaPointer             ;mask out all but 5 LSB
9c2c: 29 1f                        and     #%00011111
9c2e: 8d 4f 07                     sta     AreaAddrsLOffset        ;save as low offset
9c31: b9 e0 9c                     lda     EnemyAddrHOffsets,y     ;load base value with 2 altered MSB,
9c34: 18                           clc                             ; then add base value to 5 LSB, result
9c35: 6d 4f 07                     adc     AreaAddrsLOffset        ; becomes offset for level data
9c38: a8                           tay
9c39: b9 e4 9c                     lda     EnemyDataAddrLow,y      ;use offset to load pointer
9c3c: 85 e9                        sta     EnemyData
9c3e: b9 06 9d                     lda     EnemyDataAddrHigh,y
9c41: 85 ea                        sta     EnemyData+1
9c43: ac 4e 07                     ldy     AreaType                ;use area type as offset
9c46: b9 28 9d                     lda     AreaDataHOffsets,y      ;do the same thing but with different base value
9c49: 18                           clc
9c4a: 6d 4f 07                     adc     AreaAddrsLOffset
9c4d: a8                           tay
9c4e: b9 2c 9d                     lda     AreaDataAddrLow,y       ;use this offset to load another pointer
9c51: 85 e7                        sta     AreaData
9c53: b9 4e 9d                     lda     AreaDataAddrHigh,y
9c56: 85 e8                        sta     AreaData+1
9c58: a0 00                        ldy     #$00                    ;load first byte of header
9c5a: b1 e7                        lda     (AreaData),y
9c5c: 48                           pha                             ;save it to the stack for now
9c5d: 29 07                        and     #%00000111              ;save 3 LSB for foreground scenery or bg color control
9c5f: c9 04                        cmp     #$04
9c61: 90 05                        bcc     StoreFore
9c63: 8d 44 07                     sta     BackgroundColorCtrl     ;if 4 or greater, save value here as bg color control
9c66: a9 00                        lda     #$00
9c68: 8d 41 07     StoreFore       sta     ForegroundScenery       ;if less, save value here as foreground scenery
9c6b: 68                           pla                             ;pull byte from stack and push it back
9c6c: 48                           pha
9c6d: 29 38                        and     #%00111000              ;save player entrance control bits
9c6f: 4a                           lsr     A                       ;shift bits over to LSBs
9c70: 4a                           lsr     A
9c71: 4a                           lsr     A
9c72: 8d 10 07                     sta     PlayerEntranceCtrl      ;save value here as player entrance control
9c75: 68                           pla                             ;pull byte again but do not push it back
9c76: 29 c0                        and     #%11000000              ;save 2 MSB for game timer setting
9c78: 18                           clc
9c79: 2a                           rol     A                       ;rotate bits over to LSBs
9c7a: 2a                           rol     A
9c7b: 2a                           rol     A
9c7c: 8d 15 07                     sta     GameTimerSetting        ;save value here as game timer setting
9c7f: c8                           iny
9c80: b1 e7                        lda     (AreaData),y            ;load second byte of header
9c82: 48                           pha                             ;save to stack
9c83: 29 0f                        and     #%00001111              ;mask out all but lower nybble
9c85: 8d 27 07                     sta     TerrainControl
9c88: 68                           pla                             ;pull and push byte to copy it to A
9c89: 48                           pha
9c8a: 29 30                        and     #%00110000              ;save 2 MSB for background scenery type
9c8c: 4a                           lsr     A
9c8d: 4a                           lsr     A                       ;shift bits to LSBs
9c8e: 4a                           lsr     A
9c8f: 4a                           lsr     A
9c90: 8d 42 07                     sta     BackgroundScenery       ;save as background scenery
9c93: 68                           pla
9c94: 29 c0                        and     #%11000000
9c96: 18                           clc
9c97: 2a                           rol     A                       ;rotate bits over to LSBs
9c98: 2a                           rol     A
9c99: 2a                           rol     A
9c9a: c9 03                        cmp     #%00000011              ;if set to 3, store here
9c9c: d0 05                        bne     StoreStyle              ;and nullify other value
9c9e: 8d 43 07                     sta     CloudTypeOverride       ;otherwise store value in other place
9ca1: a9 00                        lda     #$00
9ca3: 8d 33 07     StoreStyle      sta     AreaStyle
9ca6: a5 e7                        lda     AreaData                ;increment area data address by 2 bytes
9ca8: 18                           clc
9ca9: 69 02                        adc     #$02
9cab: 85 e7                        sta     AreaData
9cad: a5 e8                        lda     AreaData+1
9caf: 69 00                        adc     #$00
9cb1: 85 e8                        sta     AreaData+1
9cb3: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; 
                   ; GAME LEVELS DATA
                   ; 
                   WorldAddrOffsets
9cb4: 00 05 0a 0e+                 .bulk   $00,$05,$0a,$0e,$13,$17,$1b,$20 ;||offsets from AreaAddrOffsets
9cbc: 25 29 c0 26+ AreaAddrOffsets .bulk   $25,$29,$c0,$26,$60     ;World1Areas
9cc1: 28 29 01 27+ World2Areas     .bulk   $28,$29,$01,$27,$62
9cc6: 24 35 20 63  World3Areas     .bulk   $24,$35,$20,$63
9cca: 22 29 41 2c+ World4Areas     .bulk   $22,$29,$41,$2c,$61
9ccf: 2a 31 26 62  World5Areas     .bulk   $2a,$31,$26,$62
9cd3: 2e 23 2d 60  World6Areas     .bulk   $2e,$23,$2d,$60
9cd7: 33 29 01 27+ World7Areas     .bulk   $33,$29,$01,$27,$64
9cdc: 30 32 21 65  World8Areas     .bulk   $30,$32,$21,$65
                   ; 
                   ; bonus area data offsets, included here for comparison purposes
                   ; 
                   ; underground bonus area  - c2
                   ; cloud area 1 (day)      - 2b
                   ; cloud area 2 (night)    - 34
                   ; water area (5-2/6-2)    - 00
                   ; water area (8-4)        - 02
                   ; warp zone area (4-2)    - 2f
                   EnemyAddrHOffsets
9ce0: 1f 06 1c 00                  .bulk   $1f,$06,$1c,$00
                   EnemyDataAddrLow
9ce4: 70                           .dd1    <E_CastleArea1
9ce5: 97                           .dd1    <E_CastleArea2
9ce6: b0                           .dd1    <E_CastleArea3
9ce7: df                           .dd1    <E_CastleArea4
9ce8: 0a                           .dd1    <E_CastleArea5
9ce9: 1f                           .dd1    <E_CastleArea6
9cea: 59                           .dd1    <E_GroundArea1
9ceb: 7e                           .dd1    <E_GroundArea2
9cec: 9b                           .dd1    <E_GroundArea3
9ced: a9                           .dd1    <E_GroundArea4
9cee: d0                           .dd1    <E_GroundArea5
9cef: 01                           .dd1    <E_GroundArea6
9cf0: 1f                           .dd1    <E_GroundArea7
9cf1: 3c                           .dd1    <E_GroundArea8
9cf2: 51                           .dd1    <E_GroundArea9
9cf3: 7b                           .dd1    <E_GroundArea10
9cf4: 7c                           .dd1    <E_GroundArea11
9cf5: a0                           .dd1    <E_GroundArea12
9cf6: a9                           .dd1    <E_GroundArea13
9cf7: ce                           .dd1    <E_GroundArea14
9cf8: f1                           .dd1    <E_GroundArea15
9cf9: fa                           .dd1    <E_GroundArea16
9cfa: fb                           .dd1    <E_GroundArea17
9cfb: 35                           .dd1    <E_GroundArea18
9cfc: 60                           .dd1    <E_GroundArea19
9cfd: 8e                           .dd1    <E_GroundArea20
9cfe: aa                           .dd1    <E_GroundArea21
9cff: b3                           .dd1    <E_GroundArea22
9d00: d8                           .dd1    <E_UndergroundArea1
9d01: 05                           .dd1    <E_UndergroundArea2
9d02: 33                           .dd1    <E_UndergroundArea3
9d03: 60                           .dd1    <E_WaterArea1
9d04: 71                           .dd1    <E_WaterArea2
9d05: 9b                           .dd1    <E_WaterArea3
                   EnemyDataAddrHigh
9d06: 9d                           .dd1    >E_CastleArea1
9d07: 9d                           .dd1    >E_CastleArea2
9d08: 9d                           .dd1    >E_CastleArea3
9d09: 9d                           .dd1    >E_CastleArea4
9d0a: 9e                           .dd1    >E_CastleArea5
9d0b: 9e                           .dd1    >E_CastleArea6
9d0c: 9e                           .dd1    >E_GroundArea1
9d0d: 9e                           .dd1    >E_GroundArea2
9d0e: 9e                           .dd1    >E_GroundArea3
9d0f: 9e                           .dd1    >E_GroundArea4
9d10: 9e                           .dd1    >E_GroundArea5
9d11: 9f                           .dd1    >E_GroundArea6
9d12: 9f                           .dd1    >E_GroundArea7
9d13: 9f                           .dd1    >E_GroundArea8
9d14: 9f                           .dd1    >E_GroundArea9
9d15: 9f                           .dd1    >E_GroundArea10
9d16: 9f                           .dd1    >E_GroundArea11
9d17: 9f                           .dd1    >E_GroundArea12
9d18: 9f                           .dd1    >E_GroundArea13
9d19: 9f                           .dd1    >E_GroundArea14
9d1a: 9f                           .dd1    >E_GroundArea15
9d1b: 9f                           .dd1    >E_GroundArea16
9d1c: 9f                           .dd1    >E_GroundArea17
9d1d: a0                           .dd1    >E_GroundArea18
9d1e: a0                           .dd1    >E_GroundArea19
9d1f: a0                           .dd1    >E_GroundArea20
9d20: a0                           .dd1    >E_GroundArea21
9d21: a0                           .dd1    >E_GroundArea22
9d22: a0                           .dd1    >E_UndergroundArea1
9d23: a1                           .dd1    >E_UndergroundArea2
9d24: a1                           .dd1    >E_UndergroundArea3
9d25: a1                           .dd1    >E_WaterArea1
9d26: a1                           .dd1    >E_WaterArea2
9d27: a1                           .dd1    >E_WaterArea3
                   AreaDataHOffsets
9d28: 00 03 19 1c                  .bulk   $00,$03,$19,$1c
9d2c: 06           AreaDataAddrLow .dd1    <L_WaterArea1
9d2d: 45                           .dd1    <L_WaterArea2
9d2e: c0                           .dd1    <L_WaterArea3
9d2f: 6b                           .dd1    <L_GroundArea1
9d30: ce                           .dd1    <L_GroundArea2
9d31: 37                           .dd1    <L_GroundArea3
9d32: 8a                           .dd1    <L_GroundArea4
9d33: 19                           .dd1    <L_GroundArea5
9d34: 8e                           .dd1    <L_GroundArea6
9d35: f3                           .dd1    <L_GroundArea7
9d36: 48                           .dd1    <L_GroundArea8
9d37: cd                           .dd1    <L_GroundArea9
9d38: 32                           .dd1    <L_GroundArea10
9d39: 3b                           .dd1    <L_GroundArea11
9d3a: 7a                           .dd1    <L_GroundArea12
9d3b: 8f                           .dd1    <L_GroundArea13
9d3c: f6                           .dd1    <L_GroundArea14
9d3d: 5b                           .dd1    <L_GroundArea15
9d3e: ce                           .dd1    <L_GroundArea16
9d3f: ff                           .dd1    <L_GroundArea17
9d40: 92                           .dd1    <L_GroundArea18
9d41: 05                           .dd1    <L_GroundArea19
9d42: 7e                           .dd1    <L_GroundArea20
9d43: d7                           .dd1    <L_GroundArea21
9d44: 02                           .dd1    <L_GroundArea22
9d45: 35                           .dd1    <L_UndergroundArea1
9d46: d8                           .dd1    <L_UndergroundArea2
9d47: 79                           .dd1    <L_UndergroundArea3
9d48: af                           .dd1    <L_CastleArea1
9d49: 10                           .dd1    <L_CastleArea2
9d4a: 8f                           .dd1    <L_CastleArea3
9d4b: 02                           .dd1    <L_CastleArea4
9d4c: 6f                           .dd1    <L_CastleArea5
9d4d: fa                           .dd1    <L_CastleArea6
                   AreaDataAddrHigh
9d4e: ae                           .dd1    >L_WaterArea1
9d4f: ae                           .dd1    >L_WaterArea2
9d50: ae                           .dd1    >L_WaterArea3
9d51: a4                           .dd1    >L_GroundArea1
9d52: a4                           .dd1    >L_GroundArea2
9d53: a5                           .dd1    >L_GroundArea3
9d54: a5                           .dd1    >L_GroundArea4
9d55: a6                           .dd1    >L_GroundArea5
9d56: a6                           .dd1    >L_GroundArea6
9d57: a6                           .dd1    >L_GroundArea7
9d58: a7                           .dd1    >L_GroundArea8
9d59: a7                           .dd1    >L_GroundArea9
9d5a: a8                           .dd1    >L_GroundArea10
9d5b: a8                           .dd1    >L_GroundArea11
9d5c: a8                           .dd1    >L_GroundArea12
9d5d: a8                           .dd1    >L_GroundArea13
9d5e: a8                           .dd1    >L_GroundArea14
9d5f: a9                           .dd1    >L_GroundArea15
9d60: a9                           .dd1    >L_GroundArea16
9d61: a9                           .dd1    >L_GroundArea17
9d62: aa                           .dd1    >L_GroundArea18
9d63: ab                           .dd1    >L_GroundArea19
9d64: ab                           .dd1    >L_GroundArea20
9d65: ab                           .dd1    >L_GroundArea21
9d66: ac                           .dd1    >L_GroundArea22
9d67: ac                           .dd1    >L_UndergroundArea1
9d68: ac                           .dd1    >L_UndergroundArea2
9d69: ad                           .dd1    >L_UndergroundArea3
9d6a: a1                           .dd1    >L_CastleArea1
9d6b: a2                           .dd1    >L_CastleArea2
9d6c: a2                           .dd1    >L_CastleArea3
9d6d: a3                           .dd1    >L_CastleArea4
9d6e: a3                           .dd1    >L_CastleArea5
9d6f: a3                           .dd1    >L_CastleArea6
                   ; 
                   ; ENEMY OBJECT DATA
                   ; 
                   ; level 1-4/6-4
9d70: 76 dd bb 4c+ E_CastleArea1   .bulk   $76,$dd,$bb,$4c,$ea,$1d,$1b,$cc,$56,$5d,$16,$9d,$c6,$1d,$36,$9d
                                    +      $c9,$1d,$04,$db,$49,$1d,$84,$1b,$c9,$5d,$88,$95,$0f,$08,$30,$4c
                                    +      $78,$2d,$a6,$28,$90,$b5
9d96: ff                           .dd1    $ff
                   ; level 4-4
9d97: 0f 03 56 1b+ E_CastleArea2   .bulk   $0f,$03,$56,$1b,$c9,$1b,$0f,$07,$36,$1b,$aa,$1b,$48,$95,$0f,$0a
                                    +      $2a,$1b,$5b,$0c,$78,$2d,$90,$b5
9daf: ff                           .dd1    $ff
                   ; level 2-4/5-4
9db0: 0b 8c 4b 4c+ E_CastleArea3   .bulk   $0b,$8c,$4b,$4c,$77,$5f,$eb,$0c,$bd,$db,$19,$9d,$75,$1d,$7d,$5b
                                    +      $d9,$1d,$3d,$dd,$99,$1d,$26,$9d,$5a,$2b,$8a,$2c,$ca,$1b,$20,$95
                                    +      $7b,$5c,$db,$4c,$1b,$cc,$3b,$cc,$78,$2d,$a6,$28,$90,$b5
9dde: ff                           .dd1    $ff
                   ; level 3-4
9ddf: 0b 8c 3b 1d+ E_CastleArea4   .bulk   $0b,$8c,$3b,$1d,$8b,$1d,$ab,$0c,$db,$1d,$0f,$03,$65,$1d,$6b,$1b
                                    +      $05,$9d,$0b,$1b,$05,$9b,$0b,$1d,$8b,$0c,$1b,$8c,$70,$15,$7b,$0c
                                    +      $db,$0c,$0f,$08,$78,$2d,$a6,$28,$90,$b5
9e09: ff                           .dd1    $ff
                   ; level 7-4
9e0a: 27 a9 4b 0c+ E_CastleArea5   .bulk   $27,$a9,$4b,$0c,$68,$29,$0f,$06,$77,$1b,$0f,$0b,$60,$15,$4b,$8c
                                    +      $78,$2d,$90,$b5
9e1e: ff                           .dd1    $ff
                   ; level 8-4
9e1f: 0f 03 8e 65+ E_CastleArea6   .bulk   $0f,$03,$8e,$65,$e1,$bb,$38,$6d,$a8,$3e,$e5,$e7,$0f,$08,$0b,$02
                                    +      $2b,$02,$5e,$65,$e1,$bb,$0e,$db,$0e,$bb,$8e,$db,$0e,$fe,$65,$ec
                                    +      $0f,$0d,$4e,$65,$e1,$0f,$0e,$4e,$02,$e0,$0f,$10,$fe,$e5,$e1,$1b
                                    +      $85,$7b,$0c,$5b,$95,$78,$2d,$90,$b5
9e58: ff                           .dd1    $ff
                   ; level 3-3
9e59: a5 86 e4 28+ E_GroundArea1   .bulk   $a5,$86,$e4,$28,$18,$a8,$45,$83,$69,$03,$c6,$29,$9b,$83,$16,$a4
                                    +      $88,$24,$e9,$28,$05,$a8,$7b,$28,$24,$8f,$c8,$03,$e8,$03,$46,$a8
                                    +      $85,$24,$c8,$24
9e7d: ff                           .dd1    $ff
                   ; level 8-3
9e7e: eb 8e 0f 03+ E_GroundArea2   .bulk   $eb,$8e,$0f,$03,$fb,$05,$17,$85,$db,$8e,$0f,$07,$57,$05,$7b,$05
                                    +      $9b,$80,$2b,$85,$fb,$05,$0f,$0b,$1b,$05,$9b,$05
9e9a: ff                           .dd1    $ff
                   ; level 4-1
9e9b: 2e c2 66 e2+ E_GroundArea3   .bulk   $2e,$c2,$66,$e2,$11,$0f,$07,$02,$11,$0f,$0c,$12,$11
9ea8: ff                           .dd1    $ff
                   ; level 6-2
9ea9: 0e c2 a8 ab+ E_GroundArea4   .bulk   $0e,$c2,$a8,$ab,$00,$bb,$8e,$6b,$82,$de,$00,$a0,$33,$86,$43,$06
                                    +      $3e,$b4,$a0,$cb,$02,$0f,$07,$7e,$42,$a6,$83,$02,$0f,$0a,$3b,$02
                                    +      $cb,$37,$0f,$0c,$e3,$0e
9ecf: ff                           .dd1    $ff
                   ; level 3-1
9ed0: 9b 8e ca 0e+ E_GroundArea5   .bulk   $9b,$8e,$ca,$0e,$ee,$42,$44,$5b,$86,$80,$b8,$1b,$80,$50,$ba,$10
                                    +      $b7,$5b,$00,$17,$85,$4b,$05,$fe,$34,$40,$b7,$86,$c6,$06,$5b,$80
                                    +      $83,$00,$d0,$38,$5b,$8e,$8a,$0e,$a6,$00,$bb,$0e,$c5,$80,$f3,$00
9f00: ff                           .dd1    $ff
                   ; level 1-1
9f01: 1e c2 00 6b+ E_GroundArea6   .bulk   $1e,$c2,$00,$6b,$06,$8b,$86,$63,$b7,$0f,$05,$03,$06,$23,$06,$4b
                                    +      $b7,$bb,$00,$5b,$b7,$fb,$37,$3b,$b7,$0f,$0b,$1b,$37
9f1e: ff                           .dd1    $ff
                   ; level 1-3/5-3
9f1f: 2b d7 e3 03+ E_GroundArea7   .bulk   $2b,$d7,$e3,$03,$c2,$86,$e2,$06,$76,$a5,$a3,$8f,$03,$86,$2b,$57
                                    +      $68,$28,$e9,$28,$e5,$83,$24,$8f,$36,$a8,$5b,$03
9f3b: ff                           .dd1    $ff
                   ; level 2-3/7-3
9f3c: 0f 02 78 40+ E_GroundArea8   .bulk   $0f,$02,$78,$40,$48,$ce,$f8,$c3,$f8,$c3,$0f,$07,$7b,$43,$c6,$d0
                                    +      $0f,$8a,$c8,$50
9f50: ff                           .dd1    $ff
                   ; level 2-1
9f51: 85 86 0b 80+ E_GroundArea9   .bulk   $85,$86,$0b,$80,$1b,$00,$db,$37,$77,$80,$eb,$37,$fe,$2b,$20,$2b
                                    +      $80,$7b,$38,$ab,$b8,$77,$86,$fe,$42,$20,$49,$86,$8b,$06,$9b,$80
                                    +      $7b,$8e,$5b,$b7,$9b,$0e,$bb,$0e,$9b,$80
                   ; end of data terminator here is also used by pipe intro area
9f7b: ff           E_GroundArea10  .dd1    $ff
                   ; level 5-1
9f7c: 0b 80 60 38+ E_GroundArea11  .bulk   $0b,$80,$60,$38,$10,$b8,$c0,$3b,$db,$8e,$40,$b8,$f0,$38,$7b,$8e
                                    +      $a0,$b8,$c0,$b8,$fb,$00,$a0,$b8,$30,$bb,$ee,$42,$88,$0f,$0b,$2b
                                    +      $0e,$67,$0e
9f9f: ff                           .dd1    $ff
                   ; cloud level used in levels 2-1 and 5-2
9fa0: 0a aa 0e 28+ E_GroundArea12  .bulk   $0a,$aa,$0e,$28,$2a,$0e,$31,$88
9fa8: ff                           .dd1    $ff
                   ; level 4-3
9fa9: c7 83 d7 03+ E_GroundArea13  .bulk   $c7,$83,$d7,$03,$42,$8f,$7a,$03,$05,$a4,$78,$24,$a6,$25,$e4,$25
                                    +      $4b,$83,$e3,$03,$05,$a4,$89,$24,$b5,$24,$09,$a4,$65,$24,$c9,$24
                                    +      $0f,$08,$85,$25
9fcd: ff                           .dd1    $ff
                   ; level 6-3
9fce: cd a5 b5 a8+ E_GroundArea14  .bulk   $cd,$a5,$b5,$a8,$07,$a8,$76,$28,$cc,$25,$65,$a4,$a9,$24,$e5,$24
                                    +      $19,$a4,$0f,$07,$95,$28,$e6,$24,$19,$a4,$d7,$29,$16,$a9,$58,$29
                                    +      $97,$29
9ff0: ff                           .dd1    $ff
                   ; level 6-1
9ff1: 0f 02 02 11+ E_GroundArea15  .bulk   $0f,$02,$02,$11,$0f,$07,$02,$11
9ff9: ff                           .dd1    $ff
                   ; warp zone area used in level 4-2
9ffa: ff           E_GroundArea16  .dd1    $ff
                   ; level 8-1
9ffb: 2b 82 ab 38+ E_GroundArea17  .bulk   $2b,$82,$ab,$38,$de,$42,$e2,$1b,$b8,$eb,$3b,$db,$80,$8b,$b8,$1b
                                    +      $82,$fb,$b8,$7b,$80,$fb,$3c,$5b,$bc,$7b,$b8,$1b,$8e,$cb,$0e,$1b
                                    +      $8e,$0f,$0d,$2b,$3b,$bb,$b8,$eb,$82,$4b,$b8,$bb,$38,$3b,$b7,$bb
                                    +      $02,$0f,$13,$1b,$00,$cb,$80,$6b,$bc
a034: ff                           .dd1    $ff
                   ; level 5-2
a035: 7b 80 ae 00+ E_GroundArea18  .bulk   $7b,$80,$ae,$00,$80,$8b,$8e,$e8,$05,$f9,$86,$17,$86,$16,$85,$4e
                                    +      $2b,$80,$ab,$8e,$87,$85,$c3,$05,$8b,$82,$9b,$02,$ab,$02,$bb,$86
                                    +      $cb,$06,$d3,$03,$3b,$8e,$6b,$0e,$a7,$8e
a05f: ff                           .dd1    $ff
                   ; level 8-2
a060: 29 8e 52 11+ E_GroundArea19  .bulk   $29,$8e,$52,$11,$83,$0e,$0f,$03,$9b,$0e,$2b,$8e,$5b,$0e,$cb,$8e
                                    +      $fb,$0e,$fb,$82,$9b,$82,$bb,$02,$fe,$42,$e8,$bb,$8e,$0f,$0a,$ab
                                    +      $0e,$cb,$0e,$f9,$0e,$88,$86,$a6,$06,$db,$02,$b6,$8e
a08d: ff                           .dd1    $ff
                   ; level 7-1
a08e: ab ce de 42+ E_GroundArea20  .bulk   $ab,$ce,$de,$42,$c0,$cb,$ce,$5b,$8e,$1b,$ce,$4b,$85,$67,$45,$0f
                                    +      $07,$2b,$00,$7b,$85,$97,$05,$0f,$0a,$92,$02
a0a9: ff                           .dd1    $ff
                   ; cloud level used in levels 3-1 and 6-2
a0aa: 0a aa 0e 24+ E_GroundArea21  .bulk   $0a,$aa,$0e,$24,$4a,$1e,$23,$aa
a0b2: ff                           .dd1    $ff
                   ; level 3-2
a0b3: 1b 80 bb 38+ E_GroundArea22  .bulk   $1b,$80,$bb,$38,$4b,$bc,$eb,$3b,$0f,$04,$2b,$00,$ab,$38,$eb,$00
                                    +      $cb,$8e,$fb,$80,$ab,$b8,$6b,$80,$fb,$3c,$9b,$bb,$5b,$bc,$fb,$00
                                    +      $6b,$b8,$fb,$38
a0d7: ff                           .dd1    $ff
                   ; level 1-2
                   E_UndergroundArea1
a0d8: 0b 86 1a 06+                 .bulk   $0b,$86,$1a,$06,$db,$06,$de,$c2,$02,$f0,$3b,$bb,$80,$eb,$06,$0b
                                    +      $86,$93,$06,$f0,$39,$0f,$06,$60,$b8,$1b,$86,$a0,$b9,$b7,$27,$bd
                                    +      $27,$2b,$83,$a1,$26,$a9,$26,$ee,$25,$0b,$27,$b4
a104: ff                           .dd1    $ff
                   ; level 4-2
                   E_UndergroundArea2
a105: 0f 02 1e 2f+                 .bulk   $0f,$02,$1e,$2f,$60,$e0,$3a,$a5,$a7,$db,$80,$3b,$82,$8b,$02,$fe
                                    +      $42,$68,$70,$bb,$25,$a7,$2c,$27,$b2,$26,$b9,$26,$9b,$80,$a8,$82
                                    +      $b5,$27,$bc,$27,$b0,$bb,$3b,$82,$87,$34,$ee,$25,$6b
a132: ff                           .dd1    $ff
                   ; underground bonus rooms area used in many levels
                   E_UndergroundArea3
a133: 1e a5 0a 2e+                 .bulk   $1e,$a5,$0a,$2e,$28,$27,$2e,$33,$c7,$0f,$03,$1e,$40,$07,$2e,$30
                                    +      $e7,$0f,$05,$1e,$24,$44,$0f,$07,$1e,$22,$6a,$2e,$23,$ab,$0f,$09
                                    +      $1e,$41,$68,$1e,$2a,$8a,$2e,$23,$a2,$2e,$32,$ea
a15f: ff                           .dd1    $ff
                   ; water area used in levels 5-2 and 6-2
a160: 3b 87 66 27+ E_WaterArea1    .bulk   $3b,$87,$66,$27,$cc,$27,$ee,$31,$87,$ee,$23,$a7,$3b,$87,$db,$07
a170: ff                           .dd1    $ff
                   ; level 2-2/7-2
a171: 0f 01 2e 25+ E_WaterArea2    .bulk   $0f,$01,$2e,$25,$2b,$2e,$25,$4b,$4e,$25,$cb,$6b,$07,$97,$47,$e9
                                    +      $87,$47,$c7,$7a,$07,$d6,$c7,$78,$07,$38,$87,$ab,$47,$e3,$07,$9b
                                    +      $87,$0f,$09,$68,$47,$db,$c7,$3b,$c7
a19a: ff                           .dd1    $ff
                   ; water area used in level 8-4
a19b: 47 9b cb 07+ E_WaterArea3    .bulk   $47,$9b,$cb,$07,$fa,$1d,$86,$9b,$3a,$87,$56,$07,$88,$1b,$07,$9d
                                    +      $2e,$65,$f0
a1ae: ff                           .dd1    $ff
                   ; 
                   ; AREA OBJECT DATA
                   ; 
                   ; level 1-4/6-4
a1af: 9b 07        L_CastleArea1   .bulk   $9b,$07
a1b1: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$ce,$03,$dc,$51,$ee,$07,$73,$e0,$74,$0a
                                    +      $7e,$06,$9e,$0a,$ce,$06,$e4,$00,$e8,$0a,$fe,$0a,$2e,$89,$4e,$0b
                                    +      $54,$0a,$14,$8a,$c4,$0a,$34,$8a,$7e,$06,$c7,$0a,$01,$e0,$02,$0a
                                    +      $47,$0a,$81,$60,$82,$0a,$c7,$0a,$0e,$87,$7e,$02,$a7,$02,$b3,$02
                                    +      $d7,$02,$e3,$02,$07,$82,$13,$02,$3e,$06,$7e,$02,$ae,$07,$fe,$0a
                                    +      $0d,$c4,$cd,$43,$ce,$09,$de,$0b,$dd,$42,$fe,$02,$5d,$c7
a20f: fd                           .dd1    $fd
                   ; level 4-4
a210: 5b 07        L_CastleArea2   .bulk   $5b,$07
a212: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$5e,$0a,$68,$64,$98,$64,$a8,$64,$ce,$06
                                    +      $fe,$02,$0d,$01,$1e,$0e,$7e,$02,$94,$63,$b4,$63,$d4,$63,$f4,$63
                                    +      $14,$e3,$2e,$0e,$5e,$02,$64,$35,$88,$72,$be,$0e,$0d,$04,$ae,$02
                                    +      $ce,$08,$cd,$4b,$fe,$02,$0d,$05,$68,$31,$7e,$0a,$96,$31,$a9,$63
                                    +      $a8,$33,$d5,$30,$ee,$02,$e6,$62,$f4,$61,$04,$b1,$08,$3f,$44,$33
                                    +      $94,$63,$a4,$31,$e4,$31,$04,$bf,$08,$3f,$04,$bf,$08,$3f,$cd,$4b
                                    +      $03,$e4,$0e,$03,$2e,$01,$7e,$06,$be,$02,$de,$06,$fe,$0a,$0d,$c4
                                    +      $cd,$43,$ce,$09,$de,$0b,$dd,$42,$fe,$02,$5d,$c7
a28e: fd                           .dd1    $fd
                   ; level 2-4/5-4
a28f: 9b 07        L_CastleArea3   .bulk   $9b,$07
a291: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$fe,$00,$27,$b1,$65,$32,$75,$0a,$71,$00
                                    +      $b7,$31,$08,$e4,$18,$64,$1e,$04,$57,$3b,$bb,$0a,$17,$8a,$27,$3a
                                    +      $73,$0a,$7b,$0a,$d7,$0a,$e7,$3a,$3b,$8a,$97,$0a,$fe,$08,$24,$8a
                                    +      $2e,$00,$3e,$40,$38,$64,$6f,$00,$9f,$00,$be,$43,$c8,$0a,$c9,$63
                                    +      $ce,$07,$fe,$07,$2e,$81,$66,$42,$6a,$42,$79,$0a,$be,$00,$c8,$64
                                    +      $f8,$64,$08,$e4,$2e,$07,$7e,$03,$9e,$07,$be,$03,$de,$07,$fe,$0a
                                    +      $03,$a5,$0d,$44,$cd,$43,$ce,$09,$dd,$42,$de,$0b,$fe,$02,$5d,$c7
a301: fd                           .dd1    $fd
                   ; level 3-4
a302: 9b 07        L_CastleArea4   .bulk   $9b,$07
a304: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$fe,$06,$0c,$81,$39,$0a,$5c,$01,$89,$0a
                                    +      $ac,$01,$d9,$0a,$fc,$01,$2e,$83,$a7,$01,$b7,$00,$c7,$01,$de,$0a
                                    +      $fe,$02,$4e,$83,$5a,$32,$63,$0a,$69,$0a,$7e,$02,$ee,$03,$fa,$32
                                    +      $03,$8a,$09,$0a,$1e,$02,$ee,$03,$fa,$32,$03,$8a,$09,$0a,$14,$42
                                    +      $1e,$02,$7e,$0a,$9e,$07,$fe,$0a,$2e,$86,$5e,$0a,$8e,$06,$be,$0a
                                    +      $ee,$07,$3e,$83,$5e,$07,$fe,$0a,$0d,$c4,$41,$52,$51,$52,$cd,$43
                                    +      $ce,$09,$de,$0b,$dd,$42,$fe,$02,$5d,$c7
a36e: fd                           .dd1    $fd
                   ; level 7-4
a36f: 5b 07        L_CastleArea5   .bulk   $5b,$07
a371: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$fe,$0a,$ae,$86,$be,$07,$fe,$02,$0d,$02
                                    +      $27,$32,$46,$61,$55,$62,$5e,$0e,$1e,$82,$68,$3c,$74,$3a,$7d,$4b
                                    +      $5e,$8e,$7d,$4b,$7e,$82,$84,$62,$94,$61,$a4,$31,$bd,$4b,$ce,$06
                                    +      $fe,$02,$0d,$06,$34,$31,$3e,$0a,$64,$32,$75,$0a,$7b,$61,$a4,$33
                                    +      $ae,$02,$de,$0e,$3e,$82,$64,$32,$78,$32,$b4,$36,$c8,$36,$dd,$4b
                                    +      $44,$b2,$58,$32,$94,$63,$a4,$3e,$ba,$30,$c9,$61,$ce,$06,$dd,$4b
                                    +      $ce,$86,$dd,$4b,$fe,$02,$2e,$86,$5e,$02,$7e,$06,$fe,$02,$1e,$86
                                    +      $3e,$02,$5e,$06,$7e,$02,$9e,$06,$fe,$0a,$0d,$c4,$cd,$43,$ce,$09
                                    +      $de,$0b,$dd,$42,$fe,$02,$5d,$c7
a3f9: fd                           .dd1    $fd
                   ; level 8-4
a3fa: 5b 06        L_CastleArea6   .bulk   $5b,$06
a3fc: 05 32 06 33+                 .bulk   $05,$32,$06,$33,$07,$34,$5e,$0a,$ae,$02,$0d,$01,$39,$73,$0d,$03
                                    +      $39,$7b,$4d,$4b,$de,$06,$1e,$8a,$ae,$06,$c4,$33,$16,$fe,$a5,$77
                                    +      $fe,$02,$fe,$82,$0d,$07,$39,$73,$a8,$74,$ed,$4b,$49,$fb,$e8,$74
                                    +      $fe,$0a,$2e,$82,$67,$02,$84,$7a,$87,$31,$0d,$0b,$fe,$02,$0d,$0c
                                    +      $39,$73,$5e,$06,$c6,$76,$45,$ff,$be,$0a,$dd,$48,$fe,$06,$3d,$cb
                                    +      $46,$7e,$ad,$4a,$fe,$82,$39,$f3,$a9,$7b,$4e,$8a,$9e,$07,$fe,$0a
                                    +      $0d,$c4,$cd,$43,$ce,$09,$de,$0b,$dd,$42,$fe,$02,$5d,$c7
a46a: fd                           .dd1    $fd
                   ; level 3-3
a46b: 94 11        L_GroundArea1   .bulk   $94,$11
a46d: 0f 26 fe 10+                 .bulk   $0f,$26,$fe,$10,$28,$94,$65,$15,$eb,$12,$fa,$41,$4a,$96,$54,$40
                                    +      $a4,$42,$b7,$13,$e9,$19,$f5,$15,$11,$80,$47,$42,$71,$13,$80,$41
                                    +      $15,$92,$1b,$1f,$24,$40,$55,$12,$64,$40,$95,$12,$a4,$40,$d2,$12
                                    +      $e1,$40,$13,$c0,$2c,$17,$2f,$12,$49,$13,$83,$40,$9f,$14,$a3,$40
                                    +      $17,$92,$83,$13,$92,$41,$b9,$14,$c5,$12,$c8,$40,$d4,$40,$4b,$92
                                    +      $78,$1b,$9c,$94,$9f,$11,$df,$14,$fe,$11,$7d,$c1,$9e,$42,$cf,$20
a4cd: fd                           .dd1    $fd
                   ; level 8-3
a4ce: 90 b1        L_GroundArea2   .bulk   $90,$b1
a4d0: 0f 26 29 91+                 .bulk   $0f,$26,$29,$91,$7e,$42,$fe,$40,$28,$92,$4e,$42,$2e,$c0,$57,$73
                                    +      $c3,$25,$c7,$27,$23,$84,$33,$20,$5c,$01,$77,$63,$88,$62,$99,$61
                                    +      $aa,$60,$bc,$01,$ee,$42,$4e,$c0,$69,$11,$7e,$42,$de,$40,$f8,$62
                                    +      $0e,$c2,$ae,$40,$d7,$63,$e7,$63,$33,$a7,$37,$27,$43,$04,$cc,$01
                                    +      $e7,$73,$0c,$81,$3e,$42,$0d,$0a,$5e,$40,$88,$72,$be,$42,$e7,$87
                                    +      $fe,$40,$39,$e1,$4e,$00,$69,$60,$87,$60,$a5,$60,$c3,$31,$fe,$31
                                    +      $6d,$c1,$be,$42,$ef,$20
a536: fd                           .dd1    $fd
                   ; level 4-1
a537: 52 21        L_GroundArea3   .bulk   $52,$21
a539: 0f 20 6e 40+                 .bulk   $0f,$20,$6e,$40,$58,$f2,$93,$01,$97,$00,$0c,$81,$97,$40,$a6,$41
                                    +      $c7,$40,$0d,$04,$03,$01,$07,$01,$23,$01,$27,$01,$ec,$03,$ac,$f3
                                    +      $c3,$03,$78,$e2,$94,$43,$47,$f3,$74,$43,$47,$fb,$74,$43,$2c,$f1
                                    +      $4c,$63,$47,$00,$57,$21,$5c,$01,$7c,$72,$39,$f1,$ec,$02,$4c,$81
                                    +      $d8,$62,$ec,$01,$0d,$0d,$0f,$38,$c7,$07,$ed,$4a,$1d,$c1,$5f,$26
a589: fd                           .dd1    $fd
                   ; level 6-2
a58a: 54 21        L_GroundArea4   .bulk   $54,$21
a58c: 0f 26 a7 22+                 .bulk   $0f,$26,$a7,$22,$37,$fb,$73,$20,$83,$07,$87,$02,$93,$20,$c7,$73
                                    +      $04,$f1,$06,$31,$39,$71,$59,$71,$e7,$73,$37,$a0,$47,$04,$86,$7c
                                    +      $e5,$71,$e7,$31,$33,$a4,$39,$71,$a9,$71,$d3,$23,$08,$f2,$13,$05
                                    +      $27,$02,$49,$71,$75,$75,$e8,$72,$67,$f3,$99,$71,$e7,$20,$f4,$72
                                    +      $f7,$31,$17,$a0,$33,$20,$39,$71,$73,$28,$bc,$05,$39,$f1,$79,$71
                                    +      $a6,$21,$c3,$06,$d3,$20,$dc,$00,$fc,$00,$07,$a2,$13,$21,$5f,$32
                                    +      $8c,$00,$98,$7a,$c7,$63,$d9,$61,$03,$a2,$07,$22,$74,$72,$77,$31
                                    +      $e7,$73,$39,$f1,$58,$72,$77,$73,$d8,$72,$7f,$b1,$97,$73,$b6,$64
                                    +      $c5,$65,$d4,$66,$e3,$67,$f3,$67,$8d,$c1,$cf,$26
a618: fd                           .dd1    $fd
                   ; level 3-1
a619: 52 31        L_GroundArea5   .bulk   $52,$31
a61b: 0f 20 6e 66+                 .bulk   $0f,$20,$6e,$66,$07,$81,$36,$01,$66,$00,$a7,$22,$08,$f2,$67,$7b
                                    +      $dc,$02,$98,$f2,$d7,$20,$39,$f1,$9f,$33,$dc,$27,$dc,$57,$23,$83
                                    +      $57,$63,$6c,$51,$87,$63,$99,$61,$a3,$06,$b3,$21,$77,$f3,$f3,$21
                                    +      $f7,$2a,$13,$81,$23,$22,$53,$00,$63,$22,$e9,$0b,$0c,$83,$13,$21
                                    +      $16,$22,$33,$05,$8f,$35,$ec,$01,$63,$a0,$67,$20,$73,$01,$77,$01
                                    +      $83,$20,$87,$20,$b3,$20,$b7,$20,$c3,$01,$c7,$00,$d3,$20,$d7,$20
                                    +      $67,$a0,$77,$07,$87,$22,$e8,$62,$f5,$65,$1c,$82,$7f,$38,$8d,$c1
                                    +      $cf,$26
a68d: fd                           .dd1    $fd
                   ; level 1-1
a68e: 50 21        L_GroundArea6   .bulk   $50,$21
a690: 07 81 47 24+                 .bulk   $07,$81,$47,$24,$57,$00,$63,$01,$77,$01,$c9,$71,$68,$f2,$e7,$73
                                    +      $97,$fb,$06,$83,$5c,$01,$d7,$22,$e7,$00,$03,$a7,$6c,$02,$b3,$22
                                    +      $e3,$01,$e7,$07,$47,$a0,$57,$06,$a7,$01,$d3,$00,$d7,$01,$07,$81
                                    +      $67,$20,$93,$22,$03,$a3,$1c,$61,$17,$21,$6f,$33,$c7,$63,$d8,$62
                                    +      $e9,$61,$fa,$60,$4f,$b3,$87,$63,$9c,$01,$b7,$63,$c8,$62,$d9,$61
                                    +      $ea,$60,$39,$f1,$87,$21,$a7,$01,$b7,$20,$39,$f1,$5f,$38,$6d,$c1
                                    +      $af,$26
a6f2: fd                           .dd1    $fd
                   ; level 1-3/5-3
a6f3: 90 11        L_GroundArea7   .bulk   $90,$11
a6f5: 0f 26 fe 10+                 .bulk   $0f,$26,$fe,$10,$2a,$93,$87,$17,$a3,$14,$b2,$42,$0a,$92,$19,$40
                                    +      $36,$14,$50,$41,$82,$16,$2b,$93,$24,$41,$bb,$14,$b8,$00,$c2,$43
                                    +      $c3,$13,$1b,$94,$67,$12,$c4,$15,$53,$c1,$d2,$41,$12,$c1,$29,$13
                                    +      $85,$17,$1b,$92,$1a,$42,$47,$13,$83,$41,$a7,$13,$0e,$91,$a7,$63
                                    +      $b7,$63,$c5,$65,$d5,$65,$dd,$4a,$e3,$67,$f3,$67,$8d,$c1,$ae,$42
                                    +      $df,$20
a747: fd                           .dd1    $fd
                   ; level 2-3/7-3
a748: 90 11        L_GroundArea8   .bulk   $90,$11
a74a: 0f 26 6e 10+                 .bulk   $0f,$26,$6e,$10,$8b,$17,$af,$32,$d8,$62,$e8,$62,$fc,$3f,$ad,$c8
                                    +      $f8,$64,$0c,$be,$43,$43,$f8,$64,$0c,$bf,$73,$40,$84,$40,$93,$40
                                    +      $a4,$40,$b3,$40,$f8,$64,$48,$e4,$5c,$39,$83,$40,$92,$41,$b3,$40
                                    +      $f8,$64,$48,$e4,$5c,$39,$f8,$64,$13,$c2,$37,$65,$4c,$24,$63,$00
                                    +      $97,$65,$c3,$42,$0b,$97,$ac,$32,$f8,$64,$0c,$be,$53,$45,$9d,$48
                                    +      $f8,$64,$2a,$e2,$3c,$47,$56,$43,$ba,$62,$f8,$64,$0c,$b7,$88,$64
                                    +      $bc,$31,$d4,$45,$fc,$31,$3c,$b1,$78,$64,$8c,$38,$0b,$9c,$1a,$33
                                    +      $18,$61,$28,$61,$39,$60,$5d,$4a,$ee,$11,$0f,$b8,$1d,$c1,$3e,$42
                                    +      $6f,$20
a7cc: fd                           .dd1    $fd
                   ; level 2-1
a7cd: 52 31        L_GroundArea9   .bulk   $52,$31
a7cf: 0f 20 6e 40+                 .bulk   $0f,$20,$6e,$40,$f7,$20,$07,$84,$17,$20,$4f,$34,$c3,$03,$c7,$02
                                    +      $d3,$22,$27,$e3,$39,$61,$e7,$73,$5c,$e4,$57,$00,$6c,$73,$47,$a0
                                    +      $53,$06,$63,$22,$a7,$73,$fc,$73,$13,$a1,$33,$05,$43,$21,$5c,$72
                                    +      $c3,$23,$cc,$03,$77,$fb,$ac,$02,$39,$f1,$a7,$73,$d3,$04,$e8,$72
                                    +      $e3,$22,$26,$f4,$bc,$02,$8c,$81,$a8,$62,$17,$87,$43,$24,$a7,$01
                                    +      $c3,$04,$08,$f2,$97,$21,$a3,$02,$c9,$0b,$e1,$69,$f1,$69,$8d,$c1
                                    +      $cf,$26
a831: fd                           .dd1    $fd
                   ; pipe intro area
a832: 38 11        L_GroundArea10  .bulk   $38,$11
a834: 0f 26 ad 40+                 .bulk   $0f,$26,$ad,$40,$3d,$c7
a83a: fd                           .dd1    $fd
                   ; level 5-1
a83b: 95 b1        L_GroundArea11  .bulk   $95,$b1
a83d: 0f 26 0d 02+                 .bulk   $0f,$26,$0d,$02,$c8,$72,$1c,$81,$38,$72,$0d,$05,$97,$34,$98,$62
                                    +      $a3,$20,$b3,$06,$c3,$20,$cc,$03,$f9,$91,$2c,$81,$48,$62,$0d,$09
                                    +      $37,$63,$47,$03,$57,$21,$8c,$02,$c5,$79,$c7,$31,$f9,$11,$39,$f1
                                    +      $a9,$11,$6f,$b4,$d3,$65,$e3,$65,$7d,$c1,$bf,$26
a879: fd                           .dd1    $fd
                   ; cloud level used in levels 2-1 and 5-2
a87a: 00 c1        L_GroundArea12  .bulk   $00,$c1
a87c: 4c 00 f4 4f+                 .bulk   $4c,$00,$f4,$4f,$0d,$02,$02,$42,$43,$4f,$52,$c2,$de,$00,$5a,$c2
                                    +      $4d,$c7
a88e: fd                           .dd1    $fd
                   ; level 4-3
a88f: 90 51        L_GroundArea13  .bulk   $90,$51
a891: 0f 26 ee 10+                 .bulk   $0f,$26,$ee,$10,$0b,$94,$33,$14,$42,$42,$77,$16,$86,$44,$02,$92
                                    +      $4a,$16,$69,$42,$73,$14,$b0,$00,$c7,$12,$05,$c0,$1c,$17,$1f,$11
                                    +      $36,$12,$8f,$14,$91,$40,$1b,$94,$35,$12,$34,$42,$60,$42,$61,$12
                                    +      $87,$12,$96,$40,$a3,$14,$1c,$98,$1f,$11,$47,$12,$9f,$15,$cc,$15
                                    +      $cf,$11,$05,$c0,$1f,$15,$39,$12,$7c,$16,$7f,$11,$82,$40,$98,$12
                                    +      $df,$15,$16,$c4,$17,$14,$54,$12,$9b,$16,$28,$94,$ce,$01,$3d,$c1
                                    +      $5e,$42,$8f,$20
a8f5: fd                           .dd1    $fd
                   ; level 6-3
a8f6: 97 11        L_GroundArea14  .bulk   $97,$11
a8f8: 0f 26 fe 10+                 .bulk   $0f,$26,$fe,$10,$2b,$92,$57,$12,$8b,$12,$c0,$41,$f7,$13,$5b,$92
                                    +      $69,$0b,$bb,$12,$b2,$46,$19,$93,$71,$00,$17,$94,$7c,$14,$7f,$11
                                    +      $93,$41,$bf,$15,$fc,$13,$ff,$11,$2f,$95,$50,$42,$51,$12,$58,$14
                                    +      $a6,$12,$db,$12,$1b,$93,$46,$43,$7b,$12,$8d,$49,$b7,$14,$1b,$94
                                    +      $49,$0b,$bb,$12,$fc,$13,$ff,$12,$03,$c1,$2f,$15,$43,$12,$4b,$13
                                    +      $77,$13,$9d,$4a,$15,$c1,$a1,$41,$c3,$12,$fe,$01,$7d,$c1,$9e,$42
                                    +      $cf,$20
a95a: fd                           .dd1    $fd
                   ; level 6-1
a95b: 52 21        L_GroundArea15  .bulk   $52,$21
a95d: 0f 20 6e 44+                 .bulk   $0f,$20,$6e,$44,$0c,$f1,$4c,$01,$aa,$35,$d9,$34,$ee,$20,$08,$b3
                                    +      $37,$32,$43,$04,$4e,$21,$53,$20,$7c,$01,$97,$21,$b7,$07,$9c,$81
                                    +      $e7,$42,$5f,$b3,$97,$63,$ac,$02,$c5,$41,$49,$e0,$58,$61,$76,$64
                                    +      $85,$65,$94,$66,$a4,$22,$a6,$03,$c8,$22,$dc,$02,$68,$f2,$96,$42
                                    +      $13,$82,$17,$02,$af,$34,$f6,$21,$fc,$06,$26,$80,$2a,$24,$36,$01
                                    +      $8c,$00,$ff,$35,$4e,$a0,$55,$21,$77,$20,$87,$07,$89,$22,$ae,$21
                                    +      $4c,$82,$9f,$34,$ec,$01,$03,$e7,$13,$67,$8d,$4a,$ad,$41,$0f,$a6
a9cd: fd                           .dd1    $fd
                   ; warp zone area used in level 4-2
a9ce: 10 51        L_GroundArea16  .bulk   $10,$51
a9d0: 4c 00 c7 12+                 .bulk   $4c,$00,$c7,$12,$c6,$42,$03,$92,$02,$42,$29,$12,$63,$12,$62,$42
                                    +      $69,$14,$a5,$12,$a4,$42,$e2,$14,$e1,$44,$f8,$16,$37,$c1,$8f,$38
                                    +      $02,$bb,$28,$7a,$68,$7a,$a8,$7a,$e0,$6a,$f0,$6a,$6d,$c5
a9fe: fd                           .dd1    $fd
                   ; level 8-1
a9ff: 92 31        L_GroundArea17  .bulk   $92,$31
aa01: 0f 20 6e 40+                 .bulk   $0f,$20,$6e,$40,$0d,$02,$37,$73,$ec,$00,$0c,$80,$3c,$00,$6c,$00
                                    +      $9c,$00,$06,$c0,$c7,$73,$06,$83,$28,$72,$96,$40,$e7,$73,$26,$c0
                                    +      $87,$7b,$d2,$41,$39,$f1,$c8,$f2,$97,$e3,$a3,$23,$e7,$02,$e3,$07
                                    +      $f3,$22,$37,$e3,$9c,$00,$bc,$00,$ec,$00,$0c,$80,$3c,$00,$86,$21
                                    +      $a6,$06,$b6,$24,$5c,$80,$7c,$00,$9c,$00,$29,$e1,$dc,$05,$f6,$41
                                    +      $dc,$80,$e8,$72,$0c,$81,$27,$73,$4c,$01,$66,$74,$0d,$11,$3f,$35
                                    +      $b6,$41,$2c,$82,$36,$40,$7c,$02,$86,$40,$f9,$61,$39,$e1,$ac,$04
                                    +      $c6,$41,$0c,$83,$16,$41,$88,$f2,$39,$f1,$7c,$00,$89,$61,$9c,$00
                                    +      $a7,$63,$bc,$00,$c5,$65,$dc,$00,$e3,$67,$f3,$67,$8d,$c1,$cf,$26
aa91: fd                           .dd1    $fd
                   ; level 5-2
aa92: 55 b1        L_GroundArea18  .bulk   $55,$b1
aa94: 0f 26 cf 33+                 .bulk   $0f,$26,$cf,$33,$07,$b2,$15,$11,$52,$42,$99,$0b,$ac,$02,$d3,$24
                                    +      $d6,$42,$d7,$25,$23,$84,$cf,$33,$07,$e3,$19,$61,$78,$7a,$ef,$33
                                    +      $2c,$81,$46,$64,$55,$65,$65,$65,$ec,$74,$47,$82,$53,$05,$63,$21
                                    +      $62,$41,$96,$22,$9a,$41,$cc,$03,$b9,$91,$39,$f1,$63,$26,$67,$27
                                    +      $d3,$06,$fc,$01,$18,$e2,$d9,$07,$e9,$04,$0c,$86,$37,$22,$93,$24
                                    +      $87,$84,$ac,$02,$c2,$41,$c3,$23,$d9,$71,$fc,$01,$7f,$b1,$9c,$00
                                    +      $a7,$63,$b6,$64,$cc,$00,$d4,$66,$e3,$67,$f3,$67,$8d,$c1,$cf,$26
ab04: fd                           .dd1    $fd
                   ; level 8-2
ab05: 50 b1        L_GroundArea19  .bulk   $50,$b1
ab07: 0f 26 fc 00+                 .bulk   $0f,$26,$fc,$00,$1f,$b3,$5c,$00,$65,$65,$74,$66,$83,$67,$93,$67
                                    +      $dc,$73,$4c,$80,$b3,$20,$c9,$0b,$c3,$08,$d3,$2f,$dc,$00,$2c,$80
                                    +      $4c,$00,$8c,$00,$d3,$2e,$ed,$4a,$fc,$00,$d7,$a1,$ec,$01,$4c,$80
                                    +      $59,$11,$d8,$11,$da,$10,$37,$a0,$47,$04,$99,$11,$e7,$21,$3a,$90
                                    +      $67,$20,$76,$10,$77,$60,$87,$07,$d8,$12,$39,$f1,$ac,$00,$e9,$71
                                    +      $0c,$80,$2c,$00,$4c,$05,$c7,$7b,$39,$f1,$ec,$00,$f9,$11,$0c,$82
                                    +      $6f,$34,$f8,$11,$fa,$10,$7f,$b2,$ac,$00,$b6,$64,$cc,$01,$e3,$67
                                    +      $f3,$67,$8d,$c1,$cf,$26
ab7d: fd                           .dd1    $fd
                   ; level 7-1
ab7e: 52 b1        L_GroundArea20  .bulk   $52,$b1
ab80: 0f 20 6e 45+                 .bulk   $0f,$20,$6e,$45,$39,$91,$b3,$04,$c3,$21,$c8,$11,$ca,$10,$49,$91
                                    +      $7c,$73,$e8,$12,$88,$91,$8a,$10,$e7,$21,$05,$91,$07,$30,$17,$07
                                    +      $27,$20,$49,$11,$9c,$01,$c8,$72,$23,$a6,$27,$26,$d3,$03,$d8,$7a
                                    +      $89,$91,$d8,$72,$39,$f1,$a9,$11,$09,$f1,$63,$24,$67,$24,$d8,$62
                                    +      $28,$91,$2a,$10,$56,$21,$70,$04,$79,$0b,$8c,$00,$94,$21,$9f,$35
                                    +      $2f,$b8,$3d,$c1,$7f,$26
abd6: fd                           .dd1    $fd
                   ; cloud level used in levels 3-1 and 6-2
abd7: 06 c1        L_GroundArea21  .bulk   $06,$c1
abd9: 4c 00 f4 4f+                 .bulk   $4c,$00,$f4,$4f,$0d,$02,$06,$20,$24,$4f,$35,$a0,$36,$20,$53,$46
                                    +      $d5,$20,$d6,$20,$34,$a1,$73,$49,$74,$20,$94,$20,$b4,$20,$d4,$20
                                    +      $f4,$20,$2e,$80,$59,$42,$4d,$c7
ac01: fd                           .dd1    $fd
                   ; level 3-2
ac02: 96 31        L_GroundArea22  .bulk   $96,$31
ac04: 0f 26 0d 03+                 .bulk   $0f,$26,$0d,$03,$1a,$60,$77,$42,$c4,$00,$c8,$62,$b9,$e1,$d3,$06
                                    +      $d7,$07,$f9,$61,$0c,$81,$4e,$b1,$8e,$b1,$bc,$01,$e4,$50,$e9,$61
                                    +      $0c,$81,$0d,$0a,$84,$43,$98,$72,$0d,$0c,$0f,$38,$1d,$c1,$5f,$26
ac34: fd                           .dd1    $fd
                   ; level 1-2
                   L_UndergroundArea1
ac35: 48 0f                        .bulk   $48,$0f
ac37: 0e 01 5e 02+                 .bulk   $0e,$01,$5e,$02,$a7,$00,$bc,$73,$1a,$e0,$39,$61,$58,$62,$77,$63
                                    +      $97,$63,$b8,$62,$d6,$07,$f8,$62,$19,$e1,$75,$52,$86,$40,$87,$50
                                    +      $95,$52,$93,$43,$a5,$21,$c5,$52,$d6,$40,$d7,$20,$e5,$06,$e6,$51
                                    +      $3e,$8d,$5e,$03,$67,$52,$77,$52,$7e,$02,$9e,$03,$a6,$43,$a7,$23
                                    +      $de,$05,$fe,$02,$1e,$83,$33,$54,$46,$40,$47,$21,$56,$04,$5e,$02
                                    +      $83,$54,$93,$52,$96,$07,$97,$50,$be,$03,$c7,$23,$fe,$02,$0c,$82
                                    +      $43,$45,$45,$24,$46,$24,$90,$08,$95,$51,$78,$fa,$d7,$73,$39,$f1
                                    +      $8c,$01,$a8,$52,$b8,$52,$cc,$01,$5f,$b3,$97,$63,$9e,$00,$0e,$81
                                    +      $16,$24,$66,$04,$8e,$00,$fe,$01,$08,$d2,$0e,$06,$6f,$47,$9e,$0f
                                    +      $0e,$82,$2d,$47,$28,$7a,$68,$7a,$a8,$7a,$ae,$01,$de,$0f,$6d,$c5
acd7: fd                           .dd1    $fd
                   ; level 4-2
                   L_UndergroundArea2
acd8: 48 0f                        .bulk   $48,$0f
acda: 0e 01 5e 02+                 .bulk   $0e,$01,$5e,$02,$bc,$01,$fc,$01,$2c,$82,$41,$52,$4e,$04,$67,$25
                                    +      $68,$24,$69,$24,$ba,$42,$c7,$04,$de,$0b,$b2,$87,$fe,$02,$2c,$e1
                                    +      $2c,$71,$67,$01,$77,$00,$87,$01,$8e,$00,$ee,$01,$f6,$02,$03,$85
                                    +      $05,$02,$13,$21,$16,$02,$27,$02,$2e,$02,$88,$72,$c7,$20,$d7,$07
                                    +      $e4,$76,$07,$a0,$17,$06,$48,$7a,$76,$20,$98,$72,$79,$e1,$88,$62
                                    +      $9c,$01,$b7,$73,$dc,$01,$f8,$62,$fe,$01,$08,$e2,$0e,$00,$6e,$02
                                    +      $73,$20,$77,$23,$83,$04,$93,$20,$ae,$00,$fe,$0a,$0e,$82,$39,$71
                                    +      $a8,$72,$e7,$73,$0c,$81,$8f,$32,$ae,$00,$fe,$04,$04,$d1,$17,$04
                                    +      $26,$49,$27,$29,$df,$33,$fe,$02,$44,$f6,$7c,$01,$8e,$06,$bf,$47
                                    +      $ee,$0f,$4d,$c7,$0e,$82,$68,$7a,$ae,$01,$de,$0f,$6d,$c5
ad78: fd                           .dd1    $fd
                   ; underground bonus rooms area used in many levels
                   L_UndergroundArea3
ad79: 48 01                        .bulk   $48,$01
ad7b: 0e 01 00 5a+                 .bulk   $0e,$01,$00,$5a,$3e,$06,$45,$46,$47,$46,$53,$44,$ae,$01,$df,$4a
                                    +      $4d,$c7,$0e,$81,$00,$5a,$2e,$04,$37,$28,$3a,$48,$46,$47,$c7,$07
                                    +      $ce,$0f,$df,$4a,$4d,$c7,$0e,$81,$00,$5a,$33,$53,$43,$51,$46,$40
                                    +      $47,$50,$53,$04,$55,$40,$56,$50,$62,$43,$64,$40,$65,$50,$71,$41
                                    +      $73,$51,$83,$51,$94,$40,$95,$50,$a3,$50,$a5,$40,$a6,$50,$b3,$51
                                    +      $b6,$40,$b7,$50,$c3,$53,$df,$4a,$4d,$c7,$0e,$81,$00,$5a,$2e,$02
                                    +      $36,$47,$37,$52,$3a,$49,$47,$25,$a7,$52,$d7,$04,$df,$4a,$4d,$c7
                                    +      $0e,$81,$00,$5a,$3e,$02,$44,$51,$53,$44,$54,$44,$55,$24,$a1,$54
                                    +      $ae,$01,$b4,$21,$df,$4a,$e5,$07,$4d,$c7
ae05: fd                           .dd1    $fd
                   ; water area used in levels 5-2 and 6-2
ae06: 41 01        L_WaterArea1    .bulk   $41,$01
ae08: b4 34 c8 52+                 .bulk   $b4,$34,$c8,$52,$f2,$51,$47,$d3,$6c,$03,$65,$49,$9e,$07,$be,$01
                                    +      $cc,$03,$fe,$07,$0d,$c9,$1e,$01,$6c,$01,$62,$35,$63,$53,$8a,$41
                                    +      $ac,$01,$b3,$53,$e9,$51,$26,$c3,$27,$33,$63,$43,$64,$33,$ba,$60
                                    +      $c9,$61,$ce,$0b,$e5,$09,$ee,$0f,$7d,$ca,$7d,$47
ae44: fd                           .dd1    $fd
                   ; level 2-2/7-2
ae45: 41 01        L_WaterArea2    .bulk   $41,$01
ae47: b8 52 ea 41+                 .bulk   $b8,$52,$ea,$41,$27,$b2,$b3,$42,$16,$d4,$4a,$42,$a5,$51,$a7,$31
                                    +      $27,$d3,$08,$e2,$16,$64,$2c,$04,$38,$42,$76,$64,$88,$62,$de,$07
                                    +      $fe,$01,$0d,$c9,$23,$32,$31,$51,$98,$52,$0d,$c9,$59,$42,$63,$53
                                    +      $67,$31,$14,$c2,$36,$31,$87,$53,$17,$e3,$29,$61,$30,$62,$3c,$08
                                    +      $42,$37,$59,$40,$6a,$42,$99,$40,$c9,$61,$d7,$63,$39,$d1,$58,$52
                                    +      $c3,$67,$d3,$31,$dc,$06,$f7,$42,$fa,$42,$23,$b1,$43,$67,$c3,$34
                                    +      $c7,$34,$d1,$51,$43,$b3,$47,$33,$9a,$30,$a9,$61,$b8,$62,$be,$0b
                                    +      $d5,$09,$de,$0f,$0d,$ca,$7d,$47
aebf: fd                           .dd1    $fd
                   ; water area used in level 8-4
aec0: 49 0f        L_WaterArea3    .bulk   $49,$0f
aec2: 1e 01 39 73+                 .bulk   $1e,$01,$39,$73,$5e,$07,$ae,$0b,$1e,$82,$6e,$88,$9e,$02,$0d,$04
                                    +      $2e,$0b,$45,$09,$4e,$0f,$ed,$47
aeda: fd                           .dd1    $fd
                   ; -----------------------------------------------------------------------------
                   ; unused space
aedb: ff                           .dd1    $ff

                   ; -----------------------------------------------------------------------------
                   ; indirect jump routine called when $0770 is set to 1
aedc: ad 72 07     GameMode        lda     OperMode_Task
aedf: 20 04 8e                     jsr     JumpEngine

aee2: e4 8f                        .dd2    InitializeArea
aee4: 67 85                        .dd2    ScreenRoutines
aee6: 71 90                        .dd2    SecondaryGameSetup
aee8: ea ae                        .dd2    GameCoreRoutine

                   ; -----------------------------------------------------------------------------
aeea: ae 53 07     GameCoreRoutine ldx     CurrentPlayer           ;get which player is on the screen
aeed: bd fc 06                     lda     SavedJoypad1Bits,x      ;use appropriate player's controller bits
aef0: 8d fc 06                     sta     SavedJoypad1Bits        ; as the master controller bits
aef3: 20 4a b0                     jsr     GameRoutines            ;execute one of many possible subs
aef6: ad 72 07                     lda     OperMode_Task           ;check major task of operating mode
aef9: c9 03                        cmp     #$03                    ;if we are supposed to be here,
aefb: b0 01                        bcs     GameEngine              ; branch to the game engine itself
aefd: 60                           rts

aefe: 20 24 b6     GameEngine      jsr     ProcFireball_Bubble     ;process fireballs and air bubbles
af01: a2 00                        ldx     #$00
af03: 86 08        ProcELoop       stx     ObjectOffset            ;put incremented offset in X as enemy object offset
af05: 20 47 c0                     jsr     EnemiesAndLoopsCore     ;process enemy objects
af08: 20 c3 84                     jsr     FloateyNumbersRoutine   ;process floatey numbers
af0b: e8                           inx
af0c: e0 06                        cpx     #$06                    ;do these two subroutines until the whole buffer is done
af0e: d0 f3                        bne     ProcELoop
af10: 20 80 f1                     jsr     GetPlayerOffscreenBits  ;get offscreen bits for player object
af13: 20 2a f1                     jsr     RelativePlayerPosition  ;get relative coordinates for player object
af16: 20 e9 ee                     jsr     PlayerGfxHandler        ;draw the player
af19: 20 d4 be                     jsr     BlockObjMT_Updater      ;replace block objects with metatiles if necessary
af1c: a2 01                        ldx     #$01
af1e: 86 08                        stx     ObjectOffset            ;set offset for second
af20: 20 70 be                     jsr     BlockObjectsCore        ;process second block object
af23: ca                           dex
af24: 86 08                        stx     ObjectOffset            ;set offset for first
af26: 20 70 be                     jsr     BlockObjectsCore        ;process first block object
af29: 20 96 bb                     jsr     MiscObjectsCore         ;process misc objects (hammer, jumping coins)
af2c: 20 bc b9                     jsr     ProcessCannons          ;process bullet bill cannons
af2f: 20 b8 b7                     jsr     ProcessWhirlpools       ;process whirlpools
af32: 20 55 b8                     jsr     FlagpoleRoutine         ;process the flagpole
af35: 20 4f b7                     jsr     RunGameTimer            ;count down the game timer
af38: 20 e1 89                     jsr     ColorRotation           ;cycle one of the background colors
af3b: a5 b5                        lda     Player_Y_HighPos
af3d: c9 02                        cmp     #$02                    ;if player is below the screen, don't bother with the music
af3f: 10 11                        bpl     NoChgMus
af41: ad 9f 07                     lda     StarInvincibleTimer     ;if star mario invincibility timer at zero,
af44: f0 1e                        beq     ClrPlrPal               ; skip this part
af46: c9 04                        cmp     #$04
af48: d0 08                        bne     NoChgMus                ;if not yet at a certain point, continue
af4a: ad 7f 07                     lda     IntervalTimerControl    ;if interval timer not yet expired,
af4d: d0 03                        bne     NoChgMus                ; branch ahead, don't bother with the music
af4f: 20 ed 90                     jsr     GetAreaMusic            ;to re-attain appropriate level music
af52: ac 9f 07     NoChgMus        ldy     StarInvincibleTimer     ;get invincibility timer
af55: a5 09                        lda     FrameCounter            ;get frame counter
af57: c0 08                        cpy     #$08                    ;if timer still above certain point,
af59: b0 02                        bcs     CycleTwo                ; branch to cycle player's palette quickly
af5b: 4a                           lsr     A                       ;otherwise, divide by 8 to cycle every eighth frame
af5c: 4a                           lsr     A
af5d: 4a           CycleTwo        lsr     A                       ;if branched here, divide by 2 to cycle every other frame
af5e: 20 88 b2                     jsr     CyclePlayerPalette      ;do sub to cycle the palette (note: shares fire flower code)
af61: 4c 67 af                     jmp     SaveAB                  ; then skip this sub to finish up the game engine

af64: 20 9a b2     ClrPlrPal       jsr     ResetPalStar            ;do sub to clear player's palette bits in attributes
af67: a5 0a        SaveAB          lda     A_B_Buttons             ;save current A and B button
af69: 85 0d                        sta     PreviousA_B_Buttons     ; into temp variable to be used on next frame
af6b: a9 00                        lda     #$00
af6d: 85 0c                        sta     Left_Right_Buttons      ;nullify left and right buttons temp variable
af6f: ad 73 07     UpdScrollVar    lda     VRAM_Buffer_AddrCtrl
af72: c9 06                        cmp     #$06                    ;if vram address controller set to 6 (one of two $0341s)
af74: f0 1c                        beq     ExitEng                 ; then branch to leave
af76: ad 1f 07                     lda     AreaParserTaskNum       ;otherwise check number of tasks
af79: d0 14                        bne     RunParser
af7b: ad 3d 07                     lda     ScrollThirtyTwo         ;get horizontal scroll in 0-31 or $00-$20 range
af7e: c9 20                        cmp     #$20                    ;check to see if exceeded $21
af80: 30 10                        bmi     ExitEng                 ;branch to leave if not
af82: ad 3d 07                     lda     ScrollThirtyTwo
af85: e9 20                        sbc     #$20                    ;otherwise subtract $20 to set appropriately
af87: 8d 3d 07                     sta     ScrollThirtyTwo         ;and store
af8a: a9 00                        lda     #$00                    ;reset vram buffer offset used in conjunction with
af8c: 8d 40 03                     sta     VRAM_Buffer2_Offset     ; level graphics buffer at $0341-$035f
af8f: 20 b0 92     RunParser       jsr     AreaParserTaskHandler   ;update the name table with more level graphics
af92: 60           ExitEng         rts                             ;and after all that, we're finally done!

                   ; -----------------------------------------------------------------------------
af93: ad ff 06     ScrollHandler   lda     Player_X_Scroll         ;load value saved here
af96: 18                           clc
af97: 6d a1 03                     adc     Platform_X_Scroll       ;add value used by left/right platforms
af9a: 8d ff 06                     sta     Player_X_Scroll         ;save as new value here to impose force on scroll
af9d: ad 23 07                     lda     ScrollLock              ;check scroll lock flag
afa0: d0 59                        bne     InitScrlAmt             ;skip a bunch of code here if set
afa2: ad 55 07                     lda     Player_Pos_ForScroll
afa5: c9 50                        cmp     #$50                    ;check player's horizontal screen position
afa7: 90 52                        bcc     InitScrlAmt             ;if less than 80 pixels to the right, branch
afa9: ad 85 07                     lda     SideCollisionTimer      ;if timer related to player's side collision
afac: d0 4d                        bne     InitScrlAmt             ;not expired, branch
afae: ac ff 06                     ldy     Player_X_Scroll         ;get value and decrement by one
afb1: 88                           dey                             ;if value originally set to zero or otherwise
afb2: 30 47                        bmi     InitScrlAmt             ;negative for left movement, branch
afb4: c8                           iny
afb5: c0 02                        cpy     #$02                    ;if value $01, branch and do not decrement
afb7: 90 01                        bcc     ChkNearMid
afb9: 88                           dey                             ;otherwise decrement by one
afba: ad 55 07     ChkNearMid      lda     Player_Pos_ForScroll
afbd: c9 70                        cmp     #$70                    ;check player's horizontal screen position
afbf: 90 03                        bcc     ScrollScreen            ;if less than 112 pixels to the right, branch
afc1: ac ff 06                     ldy     Player_X_Scroll         ;otherwise get original value undecremented
afc4: 98           ScrollScreen    tya
afc5: 8d 75 07                     sta     ScrollAmount            ;save value here
afc8: 18                           clc
afc9: 6d 3d 07                     adc     ScrollThirtyTwo         ;add to value already set here
afcc: 8d 3d 07                     sta     ScrollThirtyTwo         ;save as new value here
afcf: 98                           tya
afd0: 18                           clc
afd1: 6d 1c 07                     adc     ScreenLeft_X_Pos        ;add to left side coordinate
afd4: 8d 1c 07                     sta     ScreenLeft_X_Pos        ;save as new left side coordinate
afd7: 8d 3f 07                     sta     HorizontalScroll        ;save here also
afda: ad 1a 07                     lda     ScreenLeft_PageLoc
afdd: 69 00                        adc     #$00                    ;add carry to page location for left
afdf: 8d 1a 07                     sta     ScreenLeft_PageLoc      ;side of the screen
afe2: 29 01                        and     #$01                    ;get LSB of page location
afe4: 85 00                        sta     $00                     ;save as temp variable for PPU register 1 mirror
afe6: ad 78 07                     lda     Mirror_PPU_CTRL_REG1    ;get PPU register 1 mirror
afe9: 29 fe                        and     #%11111110              ;save all bits except d0
afeb: 05 00                        ora     $00                     ;get saved bit here and save in PPU register 1
afed: 8d 78 07                     sta     Mirror_PPU_CTRL_REG1    ;mirror to be used to set name table later
aff0: 20 38 b0                     jsr     GetScreenPosition       ;figure out where the right side is
aff3: a9 08                        lda     #$08
aff5: 8d 95 07                     sta     ScrollIntervalTimer     ;set scroll timer (residual, not used elsewhere)
aff8: 4c 00 b0                     jmp     ChkPOffscr              ;skip this part

affb: a9 00        InitScrlAmt     lda     #$00
affd: 8d 75 07                     sta     ScrollAmount            ;initialize value here
b000: a2 00        ChkPOffscr      ldx     #$00                    ;set X for player offset
b002: 20 f6 f1                     jsr     GetXOffscreenBits       ;get horizontal offscreen bits for player
b005: 85 00                        sta     $00                     ;save them here
b007: a0 00                        ldy     #$00                    ;load default offset (left side)
b009: 0a                           asl     A                       ;if d7 of offscreen bits are set,
b00a: b0 07                        bcs     KeepOnscr               ;branch with default offset
b00c: c8                           iny                             ;otherwise use different offset (right side)
b00d: a5 00                        lda     $00
b00f: 29 20                        and     #%00100000              ;check offscreen bits for d5 set
b011: f0 1b                        beq     InitPlatScrl            ;if not set, branch ahead of this part
b013: b9 1c 07     KeepOnscr       lda     ScreenLeft_X_Pos,y      ;get left or right side coordinate based on offset
b016: 38                           sec
b017: f9 34 b0                     sbc     X_SubtracterData,y      ;subtract amount based on offset
b01a: 85 86                        sta     Player_X_Position       ;store as player position to prevent movement further
b01c: b9 1a 07                     lda     ScreenLeft_PageLoc,y    ;get left or right page location based on offset
b01f: e9 00                        sbc     #$00                    ;subtract borrow
b021: 85 6d                        sta     Player_PageLoc          ;save as player's page location
b023: a5 0c                        lda     Left_Right_Buttons      ;check saved controller bits
b025: d9 36 b0                     cmp     OffscrJoypadBitsData,y  ;against bits based on offset
b028: f0 04                        beq     InitPlatScrl            ;if not equal, branch
b02a: a9 00                        lda     #$00
b02c: 85 57                        sta     Player_X_Speed          ;otherwise nullify horizontal speed of player
b02e: a9 00        InitPlatScrl    lda     #$00                    ;nullify platform force imposed on scroll
b030: 8d a1 03                     sta     Platform_X_Scroll
b033: 60                           rts

                   X_SubtracterData
b034: 00 10                        .bulk   $00,$10
                   OffscrJoypadBitsData
b036: 01 02                        .bulk   $01,$02

                   ; -----------------------------------------------------------------------------
                   GetScreenPosition
b038: ad 1c 07                     lda     ScreenLeft_X_Pos        ;get coordinate of screen's left boundary
b03b: 18                           clc
b03c: 69 ff                        adc     #$ff                    ;add 255 pixels
b03e: 8d 1d 07                     sta     ScreenRight_X_Pos       ;store as coordinate of screen's right boundary
b041: ad 1a 07                     lda     ScreenLeft_PageLoc      ;get page number where left boundary is
b044: 69 00                        adc     #$00                    ;add carry from before
b046: 8d 1b 07                     sta     ScreenRight_PageLoc     ;store as page number where right boundary is
b049: 60                           rts

                   ; -----------------------------------------------------------------------------
b04a: a5 0e        GameRoutines    lda     GameEngineSubroutine    ;run routine based on number (a few of these routines are 
b04c: 20 04 8e                     jsr     JumpEngine              ; merely placeholders as conditions for other routines)

b04f: 31 91                        .dd2    Entrance_GameTimerSetup
b051: c7 b1                        .dd2    Vine_AutoClimb
b053: 06 b2                        .dd2    SideExitPipeEntry
b055: e5 b1                        .dd2    VerticalPipeEntry
b057: a4 b2                        .dd2    FlagpoleSlide
b059: ca b2                        .dd2    PlayerEndLevel
b05b: cd 91                        .dd2    PlayerLoseLife
b05d: 69 b0                        .dd2    PlayerEntrance
b05f: e9 b0                        .dd2    PlayerCtrlRoutine
b061: 33 b2                        .dd2    PlayerChangeSize
b063: 45 b2                        .dd2    PlayerInjuryBlink
b065: 69 b2                        .dd2    PlayerDeath
b067: 7d b2                        .dd2    PlayerFireFlower

b069: ad 52 07     PlayerEntrance  lda     AltEntranceControl      ;check for mode of alternate entry
b06c: c9 02                        cmp     #$02
b06e: f0 2b                        beq     EntrMode2               ;if found, branch to enter from pipe or with vine
b070: a9 00                        lda     #$00
b072: a4 ce                        ldy     Player_Y_Position       ;if vertical position above a certain
b074: c0 30                        cpy     #$30                    ; point, nullify controller bits and continue
b076: 90 6e                        bcc     AutoControlPlayer       ; with player movement code, do not return
b078: ad 10 07                     lda     PlayerEntranceCtrl      ;check player entry bits from header
b07b: c9 06                        cmp     #$06
b07d: f0 04                        beq     ChkBehPipe              ;if set to 6 or 7, execute pipe intro code
b07f: c9 07                        cmp     #$07                    ;otherwise branch to normal entry
b081: d0 50                        bne     PlayerRdy
b083: ad c4 03     ChkBehPipe      lda     Player_SprAttrib        ;check for sprite attributes
b086: d0 05                        bne     IntroEntr               ;branch if found
b088: a9 01                        lda     #$01
b08a: 4c e6 b0                     jmp     AutoControlPlayer       ;force player to walk to the right

b08d: 20 1f b2     IntroEntr       jsr     EnterSidePipe           ;execute sub to move player to the right
b090: ce de 06                     dec     ChangeAreaTimer         ;decrement timer for change of area
b093: d0 50                        bne     ExitEntr                ;branch to exit if not yet expired
b095: ee 69 07                     inc     DisableIntermediate     ;set flag to skip world and lives display
b098: 4c 15 b3                     jmp     NextArea                ;jump to increment to next area and set modes

b09b: ad 58 07     EntrMode2       lda     JoypadOverride          ;if controller override bits set here,
b09e: d0 0c                        bne     VineEntr                ; branch to enter with vine
b0a0: a9 ff                        lda     #$ff                    ;otherwise, set value here then execute sub
b0a2: 20 00 b2                     jsr     MovePlayerYAxis         ; to move player upwards (note $ff = -1)
b0a5: a5 ce                        lda     Player_Y_Position       ;check to see if player is at a specific coordinate
b0a7: c9 91                        cmp     #$91                    ;if player risen to a certain point (this requires pipes
b0a9: 90 28                        bcc     PlayerRdy               ; to be at specific height to look/function right) branch
b0ab: 60                           rts                             ; to the last part, otherwise leave

b0ac: ad 99 03     VineEntr        lda     VineHeight
b0af: c9 60                        cmp     #$60                    ;check vine height
b0b1: d0 32                        bne     ExitEntr                ;if vine not yet reached maximum height, branch to leave
b0b3: a5 ce                        lda     Player_Y_Position       ;get player's vertical coordinate
b0b5: c9 99                        cmp     #$99                    ;check player's vertical coordinate against preset value
b0b7: a0 00                        ldy     #$00                    ;load default values to be written to 
b0b9: a9 01                        lda     #$01                    ;this value moves player to the right off the vine
b0bb: 90 0a                        bcc     OffVine                 ;if vertical coordinate < preset value, use defaults
b0bd: a9 03                        lda     #$03
b0bf: 85 1d                        sta     Player_State            ;otherwise set player state to climbing
b0c1: c8                           iny                             ;increment value in Y
b0c2: a9 08                        lda     #$08                    ;set block in block buffer to cover hole, then 
b0c4: 8d b4 05                     sta     Block_Buffer_1+180      ; use same value to force player to climb
b0c7: 8c 16 07     OffVine         sty     DisableCollisionDet     ;set collision detection disable flag
b0ca: 20 e6 b0                     jsr     AutoControlPlayer       ;use contents of A to move player up or right, execute sub
b0cd: a5 86                        lda     Player_X_Position
b0cf: c9 48                        cmp     #$48                    ;check player's horizontal position
b0d1: 90 12                        bcc     ExitEntr                ;if not far enough to the right, branch to leave
b0d3: a9 08        PlayerRdy       lda     #$08                    ;set routine to be executed by game engine next frame
b0d5: 85 0e                        sta     GameEngineSubroutine
b0d7: a9 01                        lda     #$01                    ;set to face player to the right
b0d9: 85 33                        sta     PlayerFacingDir
b0db: 4a                           lsr     A                       ;init A
b0dc: 8d 52 07                     sta     AltEntranceControl      ;init mode of entry
b0df: 8d 16 07                     sta     DisableCollisionDet     ;init collision detection disable flag
b0e2: 8d 58 07                     sta     JoypadOverride          ;nullify controller override bits
b0e5: 60           ExitEntr        rts                             ;leave!

                   ; -----------------------------------------------------------------------------
                   ; $07 - used to hold upper limit of high byte when player falls down hole
                   AutoControlPlayer
b0e6: 8d fc 06                     sta     SavedJoypad1Bits        ;override controller bits with contents of A if executing here
                   PlayerCtrlRoutine
b0e9: a5 0e                        lda     GameEngineSubroutine    ;check task here
b0eb: c9 0b                        cmp     #$0b                    ;if certain value is set, branch to skip controller bit 
b0ed: f0 3c                        beq     SizeChk
b0ef: ad 4e 07                     lda     AreaType                ;are we in a water type area?
b0f2: d0 10                        bne     SaveJoyp                ;if not, branch
b0f4: a4 b5                        ldy     Player_Y_HighPos
b0f6: 88                           dey                             ;if not in vertical area between
b0f7: d0 06                        bne     DisJoyp                 ;status bar and bottom, branch
b0f9: a5 ce                        lda     Player_Y_Position
b0fb: c9 d0                        cmp     #$d0                    ;if nearing the bottom of the screen or
b0fd: 90 05                        bcc     SaveJoyp                ; not in the vertical area between status bar or bottom,
b0ff: a9 00        DisJoyp         lda     #$00                    ; disable controller bits
b101: 8d fc 06                     sta     SavedJoypad1Bits
b104: ad fc 06     SaveJoyp        lda     SavedJoypad1Bits        ;otherwise store A and B buttons in $0a
b107: 29 c0                        and     #%11000000
b109: 85 0a                        sta     A_B_Buttons
b10b: ad fc 06                     lda     SavedJoypad1Bits        ;store left and right buttons in $0c
b10e: 29 03                        and     #%00000011
b110: 85 0c                        sta     Left_Right_Buttons
b112: ad fc 06                     lda     SavedJoypad1Bits        ;store up and down buttons in $0b
b115: 29 0c                        and     #%00001100
b117: 85 0b                        sta     Up_Down_Buttons
b119: 29 04                        and     #%00000100              ;check for pressing down
b11b: f0 0e                        beq     SizeChk                 ;if not, branch
b11d: a5 1d                        lda     Player_State            ;check player's state
b11f: d0 0a                        bne     SizeChk                 ;if not on the ground, branch
b121: a4 0c                        ldy     Left_Right_Buttons      ;check left and right
b123: f0 06                        beq     SizeChk                 ;if neither pressed, branch
b125: a9 00                        lda     #$00
b127: 85 0c                        sta     Left_Right_Buttons      ;if pressing down while on the ground,
b129: 85 0b                        sta     Up_Down_Buttons         ; nullify directional bits
b12b: 20 29 b3     SizeChk         jsr     PlayerMovementSubs      ;run movement subroutines
b12e: a0 01                        ldy     #$01                    ;is player small?
b130: ad 54 07                     lda     PlayerSize
b133: d0 09                        bne     ChkMoveDir
b135: a0 00                        ldy     #$00                    ;check for if crouching
b137: ad 14 07                     lda     CrouchingFlag
b13a: f0 02                        beq     ChkMoveDir              ;if not, branch ahead
b13c: a0 02                        ldy     #$02                    ;if big and crouching, load y with 2
b13e: 8c 99 04     ChkMoveDir      sty     Player_BoundBoxCtrl     ;set contents of Y as player's bounding box size control
b141: a9 01                        lda     #$01                    ;set moving direction to right by default
b143: a4 57                        ldy     Player_X_Speed          ;check player's horizontal speed
b145: f0 05                        beq     PlayerSubs              ;if not moving at all horizontally, skip this part
b147: 10 01                        bpl     SetMoveDir              ;if moving to the right, use default moving direction
b149: 0a                           asl     A                       ;otherwise change to move to the left
b14a: 85 45        SetMoveDir      sta     Player_MovingDir        ;set moving direction
b14c: 20 93 af     PlayerSubs      jsr     ScrollHandler           ;move the screen if necessary
b14f: 20 80 f1                     jsr     GetPlayerOffscreenBits  ;get player's offscreen bits
b152: 20 2a f1                     jsr     RelativePlayerPosition  ;get coordinates relative to the screen
b155: a2 00                        ldx     #$00                    ;set offset for player object
b157: 20 9c e2                     jsr     BoundingBoxCore         ;get player's bounding box coordinates
b15a: 20 64 dc                     jsr     PlayerBGCollision       ;do collision detection and process
b15d: a5 ce                        lda     Player_Y_Position
b15f: c9 40                        cmp     #$40                    ;check to see if player is higher than 64th pixel
b161: 90 16                        bcc     PlayerHole              ;if so, branch ahead
b163: a5 0e                        lda     GameEngineSubroutine
b165: c9 05                        cmp     #$05                    ;if running end-of-level routine, branch ahead
b167: f0 10                        beq     PlayerHole
b169: c9 07                        cmp     #$07                    ;if running player entrance routine, branch ahead
b16b: f0 0c                        beq     PlayerHole
b16d: c9 04                        cmp     #$04                    ;if running routines $00-$03, branch ahead
b16f: 90 08                        bcc     PlayerHole
b171: ad c4 03                     lda     Player_SprAttrib
b174: 29 df                        and     #%11011111              ;otherwise nullify player's
b176: 8d c4 03                     sta     Player_SprAttrib        ; background priority flag
b179: a5 b5        PlayerHole      lda     Player_Y_HighPos        ;check player's vertical high byte
b17b: c9 02                        cmp     #$02                    ; for below the screen
b17d: 30 3b                        bmi     ExitCtrl                ;branch to leave if not that far down
b17f: a2 01                        ldx     #$01
b181: 8e 23 07                     stx     ScrollLock              ;set scroll lock
b184: a0 04                        ldy     #$04
b186: 84 07                        sty     $07                     ;set value here
b188: a2 00                        ldx     #$00                    ;use X as flag, and clear for cloud level
b18a: ac 59 07                     ldy     GameTimerExpiredFlag    ;check game timer expiration flag
b18d: d0 05                        bne     HoleDie                 ;if set, branch
b18f: ac 43 07                     ldy     CloudTypeOverride       ;check for cloud type override
b192: d0 16                        bne     ChkHoleX                ;skip to last part if found
b194: e8           HoleDie         inx                             ;set flag in X for player death
b195: a4 0e                        ldy     GameEngineSubroutine
b197: c0 0b                        cpy     #$0b                    ;check for some other routine running
b199: f0 0f                        beq     ChkHoleX                ;if so, branch ahead
b19b: ac 12 07                     ldy     DeathMusicLoaded        ;check value here
b19e: d0 06                        bne     HoleBottom              ;if already set, branch to next part
b1a0: c8                           iny
b1a1: 84 fc                        sty     EventMusicQueue         ;otherwise play death music
b1a3: 8c 12 07                     sty     DeathMusicLoaded        ;and set value here
b1a6: a0 06        HoleBottom      ldy     #$06
b1a8: 84 07                        sty     $07                     ;change value here
b1aa: c5 07        ChkHoleX        cmp     $07                     ;compare vertical high byte with value set here
b1ac: 30 0c                        bmi     ExitCtrl                ;if less, branch to leave
b1ae: ca                           dex                             ;otherwise decrement flag in X
b1af: 30 0a                        bmi     CloudExit               ;if flag was clear, branch to set modes and other values
b1b1: ac b1 07                     ldy     EventMusicBuffer        ;check to see if music is still playing
b1b4: d0 04                        bne     ExitCtrl                ;branch to leave if so
b1b6: a9 06                        lda     #$06                    ;otherwise set to run lose life routine
b1b8: 85 0e                        sta     GameEngineSubroutine    ; on next frame
b1ba: 60           ExitCtrl        rts                             ;leave

b1bb: a9 00        CloudExit       lda     #$00
b1bd: 8d 58 07                     sta     JoypadOverride          ;clear controller override bits if any are set
b1c0: 20 dd b1                     jsr     SetEntr                 ;do sub to set secondary mode
b1c3: ee 52 07                     inc     AltEntranceControl      ;set mode of entry to 3
b1c6: 60                           rts

                   ; -----------------------------------------------------------------------------
b1c7: a5 b5        Vine_AutoClimb  lda     Player_Y_HighPos        ;check to see whether player reached position
b1c9: d0 06                        bne     AutoClimb               ; above the status bar yet and if so, set modes
b1cb: a5 ce                        lda     Player_Y_Position
b1cd: c9 e4                        cmp     #$e4
b1cf: 90 0c                        bcc     SetEntr
b1d1: a9 08        AutoClimb       lda     #%00001000              ;set controller bits override to up
b1d3: 8d 58 07                     sta     JoypadOverride
b1d6: a0 03                        ldy     #$03                    ;set player state to climbing
b1d8: 84 1d                        sty     Player_State
b1da: 4c e6 b0                     jmp     AutoControlPlayer

b1dd: a9 02        SetEntr         lda     #$02                    ;set starting position to override
b1df: 8d 52 07                     sta     AltEntranceControl
b1e2: 4c 13 b2                     jmp     ChgAreaMode             ;set modes

                   ; -----------------------------------------------------------------------------
                   VerticalPipeEntry
b1e5: a9 01                        lda     #$01                    ;set 1 as movement amount
b1e7: 20 00 b2                     jsr     MovePlayerYAxis         ;do sub to move player downwards
b1ea: 20 93 af                     jsr     ScrollHandler           ;do sub to scroll screen with saved force if necessary
b1ed: a0 00                        ldy     #$00                    ;load default mode of entry
b1ef: ad d6 06                     lda     WarpZoneControl         ;check warp zone control variable/flag
b1f2: d0 17                        bne     ChgAreaPipe             ;if set, branch to use mode 0
b1f4: c8                           iny
b1f5: ad 4e 07                     lda     AreaType                ;check for castle level type
b1f8: c9 03                        cmp     #$03
b1fa: d0 0f                        bne     ChgAreaPipe             ;if not castle type level, use mode 1
b1fc: c8                           iny
b1fd: 4c 0b b2                     jmp     ChgAreaPipe             ;otherwise use mode 2

b200: 18           MovePlayerYAxis clc
b201: 65 ce                        adc     Player_Y_Position       ;add contents of A to player position
b203: 85 ce                        sta     Player_Y_Position
b205: 60                           rts

                   ; -----------------------------------------------------------------------------
                   SideExitPipeEntry
b206: 20 1f b2                     jsr     EnterSidePipe           ;execute sub to move player to the right
b209: a0 02                        ldy     #$02
b20b: ce de 06     ChgAreaPipe     dec     ChangeAreaTimer         ;decrement timer for change of area
b20e: d0 0e                        bne     ExitCAPipe
b210: 8c 52 07                     sty     AltEntranceControl      ;when timer expires set mode of alternate entry
b213: ee 74 07     ChgAreaMode     inc     DisableScreenFlag       ;set flag to disable screen output
b216: a9 00                        lda     #$00
b218: 8d 72 07                     sta     OperMode_Task           ;set secondary mode of operation
b21b: 8d 22 07                     sta     Sprite0HitDetectFlag    ;disable sprite 0 check
b21e: 60           ExitCAPipe      rts                             ;leave

b21f: a9 08        EnterSidePipe   lda     #$08                    ;set player's horizontal speed
b221: 85 57                        sta     Player_X_Speed
b223: a0 01                        ldy     #$01                    ;set controller right button by default
b225: a5 86                        lda     Player_X_Position       ;mask out higher nybble of player's
b227: 29 0f                        and     #%00001111              ; horizontal position
b229: d0 03                        bne     RightPipe
b22b: 85 57                        sta     Player_X_Speed          ;if lower nybble = 0, set as horizontal speed
b22d: a8                           tay                             ;and nullify controller bit override here
b22e: 98           RightPipe       tya                             ;use contents of Y to
b22f: 20 e6 b0                     jsr     AutoControlPlayer       ; execute player control routine with ctrl bits nulled
b232: 60                           rts

                   ; -----------------------------------------------------------------------------
                   PlayerChangeSize
b233: ad 47 07                     lda     TimerControl            ;check master timer control
b236: c9 f8                        cmp     #$f8                    ;for specific moment in time
b238: d0 03                        bne     EndChgSize              ;branch if before or after that point
b23a: 4c 55 b2                     jmp     InitChangeSize          ;otherwise run code to get growing/shrinking going

b23d: c9 c4        EndChgSize      cmp     #$c4                    ;check again for another specific moment
b23f: d0 03                        bne     ExitChgSize             ;and branch to leave if before or after that point
b241: 20 73 b2                     jsr     DonePlayerTask          ;otherwise do sub to init timer control and set routine
b244: 60           ExitChgSize     rts                             ;and then leave

                   ; -----------------------------------------------------------------------------
                   PlayerInjuryBlink
b245: ad 47 07                     lda     TimerControl            ;check master timer control
b248: c9 f0                        cmp     #$f0                    ; for specific moment in time
b24a: b0 07                        bcs     ExitBlink               ;branch if before that point
b24c: c9 c8                        cmp     #$c8                    ;check again for another specific point
b24e: f0 23                        beq     DonePlayerTask          ;branch if at that point, and not before or after
b250: 4c e9 b0                     jmp     PlayerCtrlRoutine       ;otherwise run player control routine

b253: d0 13        ExitBlink       bne     ExitBoth                ;do unconditional branch to leave
b255: ac 0b 07     InitChangeSize  ldy     PlayerChangeSizeFlag    ;if growing/shrinking flag already set
b258: d0 0e                        bne     ExitBoth                ;then branch to leave
b25a: 8c 0d 07                     sty     PlayerAnimCtrl          ;otherwise initialize player's animation frame control
b25d: ee 0b 07                     inc     PlayerChangeSizeFlag    ;set growing/shrinking flag
b260: ad 54 07                     lda     PlayerSize
b263: 49 01                        eor     #$01                    ;invert player's size
b265: 8d 54 07                     sta     PlayerSize
b268: 60           ExitBoth        rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used in CyclePlayerPalette to store current palette to cycle
b269: ad 47 07     PlayerDeath     lda     TimerControl            ;check master timer control
b26c: c9 f0                        cmp     #$f0                    ;for specific moment in time
b26e: b0 33                        bcs     ExitDeath               ;branch to leave if before that point
b270: 4c e9 b0                     jmp     PlayerCtrlRoutine       ;otherwise run player control routine

b273: a9 00        DonePlayerTask  lda     #$00
b275: 8d 47 07                     sta     TimerControl            ;initialize master timer control to continue timers
b278: a9 08                        lda     #$08
b27a: 85 0e                        sta     GameEngineSubroutine    ;set player control routine to run next frame
b27c: 60                           rts                             ;leave

                   PlayerFireFlower
b27d: ad 47 07                     lda     TimerControl            ;check master timer control
b280: c9 c0                        cmp     #$c0                    ;for specific moment in time
b282: f0 13                        beq     ResetPalFireFlower      ;branch if at moment, not before or after
b284: a5 09                        lda     FrameCounter            ;get frame counter
b286: 4a                           lsr     A
b287: 4a                           lsr     A                       ;divide by four to change every four frames
                   CyclePlayerPalette
b288: 29 03                        and     #$03                    ;mask out all but d1-d0 (previously d3-d2)
b28a: 85 00                        sta     $00                     ;store result here to use as palette bits
b28c: ad c4 03                     lda     Player_SprAttrib        ;get player attributes
b28f: 29 fc                        and     #%11111100              ;save any other bits but palette bits
b291: 05 00                        ora     $00                     ;add palette bits
b293: 8d c4 03                     sta     Player_SprAttrib        ;store as new player attributes
b296: 60                           rts                             ;and leave

                   ResetPalFireFlower
b297: 20 73 b2                     jsr     DonePlayerTask          ;do sub to init timer control and run player control routine
b29a: ad c4 03     ResetPalStar    lda     Player_SprAttrib        ;get player attributes
b29d: 29 fc                        and     #%11111100              ;mask out palette bits to force palette 0
b29f: 8d c4 03                     sta     Player_SprAttrib        ;store as new player attributes
b2a2: 60                           rts                             ;and leave

b2a3: 60           ExitDeath       rts                             ;leave from death routine

                   ; -----------------------------------------------------------------------------
b2a4: a5 1b        FlagpoleSlide   lda     Enemy_ID+5              ;check special use enemy slot
b2a6: c9 30                        cmp     #FlagpoleFlagObject     ;for flagpole flag object
b2a8: d0 15                        bne     NoFPObj                 ;if not found, branch to something residual
b2aa: ad 13 07                     lda     FlagpoleSoundQueue      ;load flagpole sound
b2ad: 85 ff                        sta     Square1SoundQueue       ;into square 1's sfx queue
b2af: a9 00                        lda     #$00
b2b1: 8d 13 07                     sta     FlagpoleSoundQueue      ;init flagpole sound queue
b2b4: a4 ce                        ldy     Player_Y_Position
b2b6: c0 9e                        cpy     #$9e                    ;check to see if player has slid down
b2b8: b0 02                        bcs     SlidePlayer             ; far enough, and if so, branch with no controller bits set
b2ba: a9 04                        lda     #$04                    ;otherwise force player to climb down (to slide)
b2bc: 4c e6 b0     SlidePlayer     jmp     AutoControlPlayer       ;jump to player control routine

b2bf: e6 0e        NoFPObj         inc     GameEngineSubroutine    ;increment to next routine (this may
b2c1: 60                           rts                             ; be residual code)

                   ; -----------------------------------------------------------------------------
                   Hidden1UpCoinAmts
b2c2: 15 23 16 1b+                 .bulk   $15,$23,$16,$1b,$17,$18,$23,$63

b2ca: a9 01        PlayerEndLevel  lda     #$01                    ;force player to walk to the right
b2cc: 20 e6 b0                     jsr     AutoControlPlayer
b2cf: a5 ce                        lda     Player_Y_Position       ;check player's vertical position
b2d1: c9 ae                        cmp     #$ae
b2d3: 90 0e                        bcc     ChkStop                 ;if player is not yet off the flagpole, skip this part
b2d5: ad 23 07                     lda     ScrollLock              ;if scroll lock not set, branch ahead to next part
b2d8: f0 09                        beq     ChkStop                 ;because we only need to do this part once
b2da: a9 20                        lda     #EndOfLevelMusic
b2dc: 85 fc                        sta     EventMusicQueue         ;load win level music in event music queue
b2de: a9 00                        lda     #$00
b2e0: 8d 23 07                     sta     ScrollLock              ;turn off scroll lock to skip this part later
b2e3: ad 90 04     ChkStop         lda     Player_CollisionBits    ;get player collision bits
b2e6: 4a                           lsr     A                       ;check for d0 set
b2e7: b0 0d                        bcs     RdyNextA                ;if d0 set, skip to next part
b2e9: ad 46 07                     lda     StarFlagTaskControl     ;if star flag task control already set,
b2ec: d0 03                        bne     InCastle                ; go ahead with the rest of the code
b2ee: ee 46 07                     inc     StarFlagTaskControl     ;otherwise set task control now (this gets ball rolling!)
b2f1: a9 20        InCastle        lda     #%00100000              ;set player's background priority bit to
b2f3: 8d c4 03                     sta     Player_SprAttrib        ;give illusion of being inside the castle
b2f6: ad 46 07     RdyNextA        lda     StarFlagTaskControl
b2f9: c9 05                        cmp     #$05                    ;if star flag task control not yet set
b2fb: d0 2b                        bne     ExitNA                  ; beyond last valid task number, branch to leave
b2fd: ee 5c 07                     inc     LevelNumber             ;increment level number used for game logic
b300: ad 5c 07                     lda     LevelNumber
b303: c9 03                        cmp     #$03                    ;check to see if we have yet reached level -4
b305: d0 0e                        bne     NextArea                ; and skip this last part here if not
b307: ac 5f 07                     ldy     WorldNumber             ;get world number as offset
b30a: ad 48 07                     lda     CoinTallyFor1Ups        ;check third area coin tally for bonus 1-ups
b30d: d9 c2 b2                     cmp     Hidden1UpCoinAmts,y     ; against minimum value, if player has not collected
b310: 90 03                        bcc     NextArea                ; at least this number of coins, leave flag clear
b312: ee 5d 07                     inc     Hidden1UpFlag           ;otherwise set hidden 1-up box control flag
b315: ee 60 07     NextArea        inc     AreaNumber              ;increment area number used for address loader
b318: 20 03 9c                     jsr     LoadAreaPointer         ;get new level pointer
b31b: ee 57 07                     inc     FetchNewGameTimerFlag   ;set flag to load new game timer
b31e: 20 13 b2                     jsr     ChgAreaMode             ;do sub to set secondary mode, disable screen and sprite 0
b321: 8d 5b 07                     sta     HalfwayPage             ;reset halfway page to 0 (beginning)
b324: a9 80                        lda     #Silence
b326: 85 fc                        sta     EventMusicQueue         ;silence music and leave
b328: 60           ExitNA          rts

                   ; -----------------------------------------------------------------------------
                   PlayerMovementSubs
b329: a9 00                        lda     #$00                    ;set A to init crouch flag by default
b32b: ac 54 07                     ldy     PlayerSize              ;is player small?
b32e: d0 08                        bne     SetCrouch               ;if so, branch
b330: a5 1d                        lda     Player_State            ;check state of player
b332: d0 07                        bne     ProcMove                ;if not on the ground, branch
b334: a5 0b                        lda     Up_Down_Buttons         ;load controller bits for up and down
b336: 29 04                        and     #%00000100              ;single out bit for down button
b338: 8d 14 07     SetCrouch       sta     CrouchingFlag           ;store value in crouch flag
b33b: 20 50 b4     ProcMove        jsr     PlayerPhysicsSub        ;run sub related to jumping and swimming
b33e: ad 0b 07                     lda     PlayerChangeSizeFlag    ;if growing/shrinking flag set,
b341: d0 16                        bne     NoMoveSub               ; branch to leave
b343: a5 1d                        lda     Player_State
b345: c9 03                        cmp     #$03                    ;get player state
b347: f0 05                        beq     MoveSubs                ;if climbing, branch ahead, leave timer unset
b349: a0 18                        ldy     #$18
b34b: 8c 89 07                     sty     ClimbSlideTimer         ;otherwise reset timer now
b34e: 20 04 8e     MoveSubs        jsr     JumpEngine

b351: 5a b3                        .dd2    OnGroundStateSub
b353: 76 b3                        .dd2    JumpSwimSub
b355: 6d b3                        .dd2    FallingSub
b357: cf b3                        .dd2    ClimbingSub

b359: 60           NoMoveSub       rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used by ClimbingSub to store high vertical adder
                   OnGroundStateSub
b35a: 20 8f b5                     jsr     GetPlayerAnimSpeed      ;do a sub to set animation frame timing
b35d: a5 0c                        lda     Left_Right_Buttons
b35f: f0 02                        beq     GndMove                 ;if left/right controller bits not set, skip instruction
b361: 85 33                        sta     PlayerFacingDir         ;otherwise set new facing direction
b363: 20 cc b5     GndMove         jsr     ImposeFriction          ;do a sub to impose friction on player's walk/run
b366: 20 09 bf                     jsr     MovePlayerHorizontally  ;do another sub to move player horizontally
b369: 8d ff 06                     sta     Player_X_Scroll         ;set returned value as player's movement speed for scroll
b36c: 60                           rts

                   ; -----------------------------------------------------------------------------
b36d: ad 0a 07     FallingSub      lda     VerticalForceDown
b370: 8d 09 07                     sta     VerticalForce           ;dump vertical movement force for falling into main one
b373: 4c ac b3                     jmp     LRAir                   ;movement force, then skip ahead to process left/right movement

                   ; -----------------------------------------------------------------------------
b376: a4 9f        JumpSwimSub     ldy     Player_Y_Speed          ;if player's vertical speed zero
b378: 10 13                        bpl     DumpFall                ; or moving downwards, branch to falling
b37a: a5 0a                        lda     A_B_Buttons
b37c: 29 80                        and     #A_Button               ;check to see if A button is being pressed
b37e: 25 0d                        and     PreviousA_B_Buttons     ; and was pressed in previous frame
b380: d0 11                        bne     ProcSwim                ;if so, branch elsewhere
b382: ad 08 07                     lda     JumpOrigin_Y_Position   ;get vertical position player jumped from
b385: 38                           sec
b386: e5 ce                        sbc     Player_Y_Position       ;subtract current from original vertical coordinate
b388: cd 06 07                     cmp     DiffToHaltJump          ;compare to value set here to see if player is in mid-jump
b38b: 90 06                        bcc     ProcSwim                ;or just starting to jump, if just starting, skip ahead
b38d: ad 0a 07     DumpFall        lda     VerticalForceDown       ;otherwise dump falling into main fractional
b390: 8d 09 07                     sta     VerticalForce
b393: ad 04 07     ProcSwim        lda     SwimmingFlag            ;if swimming flag not set,
b396: f0 14                        beq     LRAir                   ;branch ahead to last part
b398: 20 8f b5                     jsr     GetPlayerAnimSpeed      ;do a sub to get animation frame timing
b39b: a5 ce                        lda     Player_Y_Position
b39d: c9 14                        cmp     #$14                    ;check vertical position against preset value
b39f: b0 05                        bcs     LRWater                 ;if not yet reached a certain position, branch ahead
b3a1: a9 18                        lda     #$18
b3a3: 8d 09 07                     sta     VerticalForce           ;otherwise set fractional
b3a6: a5 0c        LRWater         lda     Left_Right_Buttons      ;check left/right controller bits (check for swimming)
b3a8: f0 02                        beq     LRAir                   ;if not pressing any, skip
b3aa: 85 33                        sta     PlayerFacingDir         ;otherwise set facing direction accordingly
b3ac: a5 0c        LRAir           lda     Left_Right_Buttons      ;check left/right controller bits (check for jumping/falling)
b3ae: f0 03                        beq     JSMove                  ;if not pressing any, skip
b3b0: 20 cc b5                     jsr     ImposeFriction          ;otherwise process horizontal movement
b3b3: 20 09 bf     JSMove          jsr     MovePlayerHorizontally  ;do a sub to move player horizontally
b3b6: 8d ff 06                     sta     Player_X_Scroll         ;set player's speed here, to be used for scroll later
b3b9: a5 0e                        lda     GameEngineSubroutine
b3bb: c9 0b                        cmp     #$0b                    ;check for specific routine selected
b3bd: d0 05                        bne     ExitMov1                ;branch if not set to run
b3bf: a9 28                        lda     #$28
b3c1: 8d 09 07                     sta     VerticalForce           ;otherwise set fractional
b3c4: 4c 4d bf     ExitMov1        jmp     MovePlayerVertically    ;jump to move player vertically, then leave

                   ; -----------------------------------------------------------------------------
b3c7: 0e 04 fc f2  ClimbAdderLow   .bulk   $0e,$04,$fc,$f2
b3cb: 00 00 ff ff  ClimbAdderHigh  .bulk   $00,$00,$ff,$ff

b3cf: ad 16 04     ClimbingSub     lda     Player_YMF_Dummy
b3d2: 18                           clc                             ;add movement force to dummy variable
b3d3: 6d 33 04                     adc     Player_Y_MoveForce      ;save with carry
b3d6: 8d 16 04                     sta     Player_YMF_Dummy
b3d9: a0 00                        ldy     #$00                    ;set default adder here
b3db: a5 9f                        lda     Player_Y_Speed          ;get player's vertical speed
b3dd: 10 01                        bpl     MoveOnVine              ;if not moving upwards, branch
b3df: 88                           dey                             ;otherwise set adder to $ff
b3e0: 84 00        MoveOnVine      sty     $00                     ;store adder here
b3e2: 65 ce                        adc     Player_Y_Position       ;add carry to player's vertical position
b3e4: 85 ce                        sta     Player_Y_Position       ;and store to move player up or down
b3e6: a5 b5                        lda     Player_Y_HighPos
b3e8: 65 00                        adc     $00                     ;add carry to player's page location
b3ea: 85 b5                        sta     Player_Y_HighPos        ;and store
b3ec: a5 0c                        lda     Left_Right_Buttons      ;compare left/right controller bits
b3ee: 2d 90 04                     and     Player_CollisionBits    ;to collision flag
b3f1: f0 2d                        beq     InitCSTimer             ;if not set, skip to end
b3f3: ac 89 07                     ldy     ClimbSlideTimer         ;otherwise check timer 
b3f6: d0 27                        bne     ExitCSub                ;if timer not expired, branch to leave
b3f8: a0 18                        ldy     #$18
b3fa: 8c 89 07                     sty     ClimbSlideTimer         ;otherwise set timer now
b3fd: a2 00                        ldx     #$00                    ;set default offset here
b3ff: a4 33                        ldy     PlayerFacingDir         ;get facing direction
b401: 4a                           lsr     A                       ;move right button controller bit to carry
b402: b0 02                        bcs     ClimbFD                 ;if controller right pressed, branch ahead
b404: e8                           inx
b405: e8                           inx                             ;otherwise increment offset by 2 bytes
b406: 88           ClimbFD         dey                             ;check to see if facing right
b407: f0 01                        beq     CSetFDir                ;if so, branch, do not increment
b409: e8                           inx                             ;otherwise increment by 1 byte
b40a: a5 86        CSetFDir        lda     Player_X_Position
b40c: 18                           clc                             ;add or subtract from player's horizontal position
b40d: 7d c7 b3                     adc     ClimbAdderLow,x         ; using value here as adder and X as offset
b410: 85 86                        sta     Player_X_Position
b412: a5 6d                        lda     Player_PageLoc          ;add or subtract carry or borrow using value here
b414: 7d cb b3                     adc     ClimbAdderHigh,x        ; from the player's page location
b417: 85 6d                        sta     Player_PageLoc
b419: a5 0c                        lda     Left_Right_Buttons      ;get left/right controller bits again
b41b: 49 03                        eor     #%00000011              ;invert them and store them while player
b41d: 85 33                        sta     PlayerFacingDir         ; is on vine to face player in opposite direction
b41f: 60           ExitCSub        rts                             ;then leave

b420: 8d 89 07     InitCSTimer     sta     ClimbSlideTimer         ;initialize timer here
b423: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store offset to friction data
b424: 20 20 1e 28+ JumpMForceData  .bulk   $20,$20,$1e,$28,$28,$0d,$04
b42b: 70 70 60 90+ FallMForceData  .bulk   $70,$70,$60,$90,$90,$0a,$09
b432: fc fc fc fb+ PlayerYSpdData  .bulk   $fc,$fc,$fc,$fb,$fb,$fe,$ff
b439: 00 00 00 00+ InitMForceData  .bulk   $00,$00,$00,$00,$00,$80,$00
b440: d8 e8 f0     MaxLeftXSpdData .bulk   $d8,$e8,$f0
                   MaxRightXSpdData
b443: 28 18 10                     .bulk   $28,$18,$10
b446: 0c                           .dd1    $0c                     ;used for pipe intros
b447: e4 98 d0     FrictionData    .bulk   $e4,$98,$d0
                   Climb_Y_SpeedData
b44a: 00 ff 01                     .bulk   $00,$ff,$01
                   Climb_Y_MForceData
b44d: 00 20 ff                     .bulk   $00,$20,$ff

                   PlayerPhysicsSub
b450: a5 1d                        lda     Player_State            ;check player state
b452: c9 03                        cmp     #$03
b454: d0 23                        bne     CheckForJumping         ;if not climbing, branch
b456: a0 00                        ldy     #$00
b458: a5 0b                        lda     Up_Down_Buttons         ;get controller bits for up/down
b45a: 2d 90 04                     and     Player_CollisionBits    ;check against player's collision detection bits
b45d: f0 06                        beq     ProcClimb               ;if not pressing up or down, branch
b45f: c8                           iny
b460: 29 08                        and     #%00001000              ;check for pressing up
b462: d0 01                        bne     ProcClimb
b464: c8                           iny
b465: be 4d b4     ProcClimb       ldx     Climb_Y_MForceData,y    ;load value here
b468: 8e 33 04                     stx     Player_Y_MoveForce      ;store as vertical movement force
b46b: a9 08                        lda     #$08                    ;load default animation timing
b46d: be 4a b4                     ldx     Climb_Y_SpeedData,y     ;load some other value here
b470: 86 9f                        stx     Player_Y_Speed          ;store as vertical speed
b472: 30 01                        bmi     SetCAnim                ;if climbing down, use default animation timing value
b474: 4a                           lsr     A                       ;otherwise divide timer setting by 2
b475: 8d 0c 07     SetCAnim        sta     PlayerAnimTimerSet      ;store animation timer setting and leave
b478: 60                           rts

b479: ad 0e 07     CheckForJumping lda     JumpspringAnimCtrl      ;if jumpspring animating,
b47c: d0 0a                        bne     NoJump                  ;skip ahead to something else
b47e: a5 0a                        lda     A_B_Buttons             ;check for A button press
b480: 29 80                        and     #A_Button
b482: f0 04                        beq     NoJump                  ;if not, branch to something else
b484: 25 0d                        and     PreviousA_B_Buttons     ;if button not pressed in previous frame, branch
b486: f0 03                        beq     ProcJumping
b488: 4c 1c b5     NoJump          jmp     X_Physics               ;otherwise, jump to something else

b48b: a5 1d        ProcJumping     lda     Player_State            ;check player state
b48d: f0 11                        beq     InitJS                  ;if on the ground, branch
b48f: ad 04 07                     lda     SwimmingFlag            ;if swimming flag not set, jump to do something else
b492: f0 f4                        beq     NoJump                  ; to prevent midair jumping, otherwise continue
b494: ad 82 07                     lda     JumpSwimTimer           ;if jump/swim timer nonzero, branch
b497: d0 07                        bne     InitJS
b499: a5 9f                        lda     Player_Y_Speed          ;check player's vertical speed
b49b: 10 03                        bpl     InitJS                  ;if player's vertical speed motionless or down, branch
b49d: 4c 1c b5                     jmp     X_Physics               ;if timer at zero and player still rising, do not swim

b4a0: a9 20        InitJS          lda     #$20                    ;set jump/swim timer
b4a2: 8d 82 07                     sta     JumpSwimTimer
b4a5: a0 00                        ldy     #$00                    ;initialize vertical force and dummy variable
b4a7: 8c 16 04                     sty     Player_YMF_Dummy
b4aa: 8c 33 04                     sty     Player_Y_MoveForce
b4ad: a5 b5                        lda     Player_Y_HighPos        ;get vertical high and low bytes of jump origin
b4af: 8d 07 07                     sta     JumpOrigin_Y_HighPos    ; and store them next to each other here
b4b2: a5 ce                        lda     Player_Y_Position
b4b4: 8d 08 07                     sta     JumpOrigin_Y_Position
b4b7: a9 01                        lda     #$01                    ;set player state to jumping/swimming
b4b9: 85 1d                        sta     Player_State
b4bb: ad 00 07                     lda     Player_XSpeedAbsolute   ;check value related to walking/running speed
b4be: c9 09                        cmp     #$09
b4c0: 90 10                        bcc     ChkWtr                  ;branch if below certain values, increment Y
b4c2: c8                           iny                             ;for each amount equal or exceeded
b4c3: c9 10                        cmp     #$10
b4c5: 90 0b                        bcc     ChkWtr
b4c7: c8                           iny
b4c8: c9 19                        cmp     #$19
b4ca: 90 06                        bcc     ChkWtr
b4cc: c8                           iny
b4cd: c9 1c                        cmp     #$1c
b4cf: 90 01                        bcc     ChkWtr                  ;note that for jumping, range is 0-4 for Y
b4d1: c8                           iny
b4d2: a9 01        ChkWtr          lda     #$01                    ;set value here (apparently always set to 1)
b4d4: 8d 06 07                     sta     DiffToHaltJump
b4d7: ad 04 07                     lda     SwimmingFlag            ;if swimming flag disabled, branch
b4da: f0 08                        beq     GetYPhy
b4dc: a0 05                        ldy     #$05                    ;otherwise set Y to 5, range is 5-6
b4de: ad 7d 04                     lda     Whirlpool_Flag          ;if whirlpool flag not set, branch
b4e1: f0 01                        beq     GetYPhy
b4e3: c8                           iny                             ;otherwise increment to 6
b4e4: b9 24 b4     GetYPhy         lda     JumpMForceData,y        ;store appropriate jump/swim
b4e7: 8d 09 07                     sta     VerticalForce           ; data here
b4ea: b9 2b b4                     lda     FallMForceData,y
b4ed: 8d 0a 07                     sta     VerticalForceDown
b4f0: b9 39 b4                     lda     InitMForceData,y
b4f3: 8d 33 04                     sta     Player_Y_MoveForce
b4f6: b9 32 b4                     lda     PlayerYSpdData,y
b4f9: 85 9f                        sta     Player_Y_Speed
b4fb: ad 04 07                     lda     SwimmingFlag            ;if swimming flag disabled, branch
b4fe: f0 11                        beq     PJumpSnd
b500: a9 04                        lda     #Sfx_EnemyStomp         ;load swim/goomba stomp sound into
b502: 85 ff                        sta     Square1SoundQueue       ;square 1's sfx queue
b504: a5 ce                        lda     Player_Y_Position
b506: c9 14                        cmp     #$14                    ;check vertical low byte of player position
b508: b0 12                        bcs     X_Physics               ;if below a certain point, branch
b50a: a9 00                        lda     #$00                    ;otherwise reset player's vertical speed
b50c: 85 9f                        sta     Player_Y_Speed          ; and jump to something else to keep player
b50e: 4c 1c b5                     jmp     X_Physics               ; from swimming above water level

b511: a9 01        PJumpSnd        lda     #Sfx_BigJump            ;load big mario's jump sound by default
b513: ac 54 07                     ldy     PlayerSize              ;is mario big?
b516: f0 02                        beq     SJumpSnd
b518: a9 80                        lda     #Sfx_SmallJump          ;if not, load small mario's jump sound
b51a: 85 ff        SJumpSnd        sta     Square1SoundQueue       ;store appropriate jump sound in square 1 sfx queue
b51c: a0 00        X_Physics       ldy     #$00
b51e: 84 00                        sty     $00                     ;init value here
b520: a5 1d                        lda     Player_State            ;if mario is on the ground, branch
b522: f0 09                        beq     ProcPRun
b524: ad 00 07                     lda     Player_XSpeedAbsolute   ;check something that seems to be related
b527: c9 19                        cmp     #$19                    ;to mario's speed
b529: b0 33                        bcs     GetXPhy                 ;if =>$19 branch here
b52b: 90 18                        bcc     ChkRFast                ;if not branch elsewhere

b52d: c8           ProcPRun        iny                             ;if mario on the ground, increment Y
b52e: ad 4e 07                     lda     AreaType                ;check area type
b531: f0 12                        beq     ChkRFast                ;if water type, branch
b533: 88                           dey                             ;decrement Y by default for non-water type area
b534: a5 0c                        lda     Left_Right_Buttons      ;get left/right controller bits
b536: c5 45                        cmp     Player_MovingDir        ;check against moving direction
b538: d0 0b                        bne     ChkRFast                ;if controller bits <> moving direction, skip this part
b53a: a5 0a                        lda     A_B_Buttons             ;check for b button pressed
b53c: 29 40                        and     #B_Button
b53e: d0 19                        bne     SetRTmr                 ;if pressed, skip ahead to set timer
b540: ad 83 07                     lda     RunningTimer            ;check for running timer set
b543: d0 19                        bne     GetXPhy                 ;if set, branch
b545: c8           ChkRFast        iny                             ;if running timer not set or level type is water, 
b546: e6 00                        inc     $00                     ; increment Y again and temp variable in memory
b548: ad 03 07                     lda     RunningSpeed
b54b: d0 07                        bne     FastXSp                 ;if running speed set here, branch
b54d: ad 00 07                     lda     Player_XSpeedAbsolute
b550: c9 21                        cmp     #$21                    ;otherwise check player's walking/running speed
b552: 90 0a                        bcc     GetXPhy                 ;if less than a certain amount, branch ahead
b554: e6 00        FastXSp         inc     $00                     ;if running speed set or speed => $21 increment $00
b556: 4c 5e b5                     jmp     GetXPhy                 ; and jump ahead

b559: a9 0a        SetRTmr         lda     #$0a                    ;if b button pressed, set running timer
b55b: 8d 83 07                     sta     RunningTimer
b55e: b9 40 b4     GetXPhy         lda     MaxLeftXSpdData,y       ;get maximum speed to the left
b561: 8d 50 04                     sta     MaximumLeftSpeed
b564: a5 0e                        lda     GameEngineSubroutine    ;check for specific routine running
b566: c9 07                        cmp     #$07                    ;(player entrance)
b568: d0 02                        bne     GetXPhy2                ;if not running, skip and use old value of Y
b56a: a0 03                        ldy     #$03                    ;otherwise set Y to 3
b56c: b9 43 b4     GetXPhy2        lda     MaxRightXSpdData,y      ;get maximum speed to the right
b56f: 8d 56 04                     sta     MaximumRightSpeed
b572: a4 00                        ldy     $00                     ;get other value in memory
b574: b9 47 b4                     lda     FrictionData,y          ;get value using value in memory as offset
b577: 8d 02 07                     sta     FrictionAdderLow
b57a: a9 00                        lda     #$00
b57c: 8d 01 07                     sta     FrictionAdderHigh       ;init something here
b57f: a5 33                        lda     PlayerFacingDir
b581: c5 45                        cmp     Player_MovingDir        ;check facing direction against moving direction
b583: f0 06                        beq     ExitPhy                 ;if the same, branch to leave
b585: 0e 02 07                     asl     FrictionAdderLow        ;otherwise shift d7 of friction adder low into carry
b588: 2e 01 07                     rol     FrictionAdderHigh       ; then rotate carry onto d0 of friction adder high
b58b: 60           ExitPhy         rts                             ; and then leave

                   ; -----------------------------------------------------------------------------
                   PlayerAnimTmrData
b58c: 02 04 07                     .bulk   $02,$04,$07

                   GetPlayerAnimSpeed
b58f: a0 00                        ldy     #$00                    ;initialize offset in Y
b591: ad 00 07                     lda     Player_XSpeedAbsolute   ;check player's walking/running speed
b594: c9 1c                        cmp     #$1c                    ; against preset amount
b596: b0 15                        bcs     SetRunSpd               ;if greater than a certain amount, branch ahead
b598: c8                           iny                             ;otherwise increment Y
b599: c9 0e                        cmp     #$0e                    ;compare against lower amount
b59b: b0 01                        bcs     ChkSkid                 ;if greater than this but not greater than first, skip increment
b59d: c8                           iny                             ;otherwise increment Y again
b59e: ad fc 06     ChkSkid         lda     SavedJoypad1Bits        ;get controller bits
b5a1: 29 7f                        and     #%01111111              ;mask out A button
b5a3: f0 20                        beq     SetAnimSpd              ;if no other buttons pressed, branch ahead of all this
b5a5: 29 03                        and     #$03                    ;mask out all others except left and right
b5a7: c5 45                        cmp     Player_MovingDir        ;check against moving direction
b5a9: d0 08                        bne     ProcSkid                ;if left/right controller bits <> moving direction, branch
b5ab: a9 00                        lda     #$00                    ;otherwise set zero value here
b5ad: 8d 03 07     SetRunSpd       sta     RunningSpeed            ;store zero or running speed here
b5b0: 4c c5 b5                     jmp     SetAnimSpd

b5b3: ad 00 07     ProcSkid        lda     Player_XSpeedAbsolute   ;check player's walking/running speed
b5b6: c9 0b                        cmp     #$0b                    ;against one last amount
b5b8: b0 0b                        bcs     SetAnimSpd              ;if greater than this amount, branch
b5ba: a5 33                        lda     PlayerFacingDir
b5bc: 85 45                        sta     Player_MovingDir        ;otherwise use facing direction to set moving direction
b5be: a9 00                        lda     #$00
b5c0: 85 57                        sta     Player_X_Speed          ;nullify player's horizontal speed
b5c2: 8d 05 07                     sta     Player_X_MoveForce      ; and dummy variable for player
b5c5: b9 8c b5     SetAnimSpd      lda     PlayerAnimTmrData,y     ;get animation timer setting using Y as offset
b5c8: 8d 0c 07                     sta     PlayerAnimTimerSet
b5cb: 60                           rts

                   ; -----------------------------------------------------------------------------
b5cc: 2d 90 04     ImposeFriction  and     Player_CollisionBits    ;perform AND between left/right controller bits and collision flag
b5cf: c9 00                        cmp     #$00                    ;then compare to zero (this instruction is redundant)
b5d1: d0 08                        bne     JoypFrict               ;if any bits set, branch to next part
b5d3: a5 57                        lda     Player_X_Speed
b5d5: f0 49                        beq     SetAbsSpd               ;if player has no horizontal speed, branch ahead to last part
b5d7: 10 23                        bpl     RghtFrict               ;if player moving to the right, branch to slow
b5d9: 30 03                        bmi     LeftFrict               ;otherwise logic dictates player moving left, branch to slow

b5db: 4a           JoypFrict       lsr     A                       ;put right controller bit into carry
b5dc: 90 1e                        bcc     RghtFrict               ;if left button pressed, carry = 0, thus branch
b5de: ad 05 07     LeftFrict       lda     Player_X_MoveForce      ;load value set here
b5e1: 18                           clc
b5e2: 6d 02 07                     adc     FrictionAdderLow        ;add to it another value set here
b5e5: 8d 05 07                     sta     Player_X_MoveForce      ;store here
b5e8: a5 57                        lda     Player_X_Speed
b5ea: 6d 01 07                     adc     FrictionAdderHigh       ;add value plus carry to horizontal speed
b5ed: 85 57                        sta     Player_X_Speed          ;set as new horizontal speed
b5ef: cd 56 04                     cmp     MaximumRightSpeed       ;compare against maximum value for right movement
b5f2: 30 23                        bmi     XSpdSign                ;if horizontal speed greater negatively, branch
b5f4: ad 56 04                     lda     MaximumRightSpeed       ;otherwise set preset value as horizontal speed
b5f7: 85 57                        sta     Player_X_Speed          ;thus slowing the player's left movement down
b5f9: 4c 20 b6                     jmp     SetAbsSpd               ;skip to the end

b5fc: ad 05 07     RghtFrict       lda     Player_X_MoveForce      ;load value set here
b5ff: 38                           sec
b600: ed 02 07                     sbc     FrictionAdderLow        ;subtract from it another value set here
b603: 8d 05 07                     sta     Player_X_MoveForce      ;store here
b606: a5 57                        lda     Player_X_Speed
b608: ed 01 07                     sbc     FrictionAdderHigh       ;subtract value plus borrow from horizontal speed
b60b: 85 57                        sta     Player_X_Speed          ;set as new horizontal speed
b60d: cd 50 04                     cmp     MaximumLeftSpeed        ;compare against maximum value for left movement
b610: 10 05                        bpl     XSpdSign                ;if horizontal speed greater positively, branch
b612: ad 50 04                     lda     MaximumLeftSpeed        ;otherwise set preset value as horizontal speed
b615: 85 57                        sta     Player_X_Speed          ;thus slowing the player's right movement down
b617: c9 00        XSpdSign        cmp     #$00                    ;if player not moving or moving to the right,
b619: 10 05                        bpl     SetAbsSpd               ; branch and leave horizontal speed value unmodified
b61b: 49 ff                        eor     #$ff
b61d: 18                           clc                             ;otherwise get two's compliment to get absolute
b61e: 69 01                        adc     #$01                    ; unsigned walking/running speed
b620: 8d 00 07     SetAbsSpd       sta     Player_XSpeedAbsolute   ;store walking/running speed here and leave
b623: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store downward movement force in FireballObjCore
                   ; $02 - used to store maximum vertical speed in FireballObjCore
                   ; $07 - used to store pseudorandom bit in BubbleCheck
                   ProcFireball_Bubble
b624: ad 56 07                     lda     PlayerStatus            ;check player's status
b627: c9 02                        cmp     #$02
b629: 90 43                        bcc     ProcAirBubbles          ;if not fiery, branch
b62b: a5 0a                        lda     A_B_Buttons
b62d: 29 40                        and     #B_Button               ;check for b button pressed
b62f: f0 33                        beq     ProcFireballs           ;branch if not pressed
b631: 25 0d                        and     PreviousA_B_Buttons
b633: d0 2f                        bne     ProcFireballs           ;if button pressed in previous frame, branch
b635: ad ce 06                     lda     FireballCounter         ;load fireball counter
b638: 29 01                        and     #%00000001              ;get LSB and use as offset for buffer
b63a: aa                           tax
b63b: b5 24                        lda     Fireball_State,x        ;load fireball state
b63d: d0 25                        bne     ProcFireballs           ;if not inactive, branch
b63f: a4 b5                        ldy     Player_Y_HighPos        ;if player too high or too low, branch
b641: 88                           dey
b642: d0 20                        bne     ProcFireballs
b644: ad 14 07                     lda     CrouchingFlag           ;if player crouching, branch
b647: d0 1b                        bne     ProcFireballs
b649: a5 1d                        lda     Player_State            ;if player's state = climbing, branch
b64b: c9 03                        cmp     #$03
b64d: f0 15                        beq     ProcFireballs
b64f: a9 20                        lda     #Sfx_Fireball           ;play fireball sound effect
b651: 85 ff                        sta     Square1SoundQueue
b653: a9 02                        lda     #$02                    ;load state
b655: 95 24                        sta     Fireball_State,x
b657: ac 0c 07                     ldy     PlayerAnimTimerSet      ;copy animation frame timer setting
b65a: 8c 11 07                     sty     FireballThrowingTimer   ; into fireball throwing timer
b65d: 88                           dey
b65e: 8c 81 07                     sty     PlayerAnimTimer         ;decrement and store in player's animation timer
b661: ee ce 06                     inc     FireballCounter         ;increment fireball counter
b664: a2 00        ProcFireballs   ldx     #$00
b666: 20 89 b6                     jsr     FireballObjCore         ;process first fireball object
b669: a2 01                        ldx     #$01
b66b: 20 89 b6                     jsr     FireballObjCore         ;process second fireball object, then do air bubbles
b66e: ad 4e 07     ProcAirBubbles  lda     AreaType                ;if not water type level, skip the rest of this
b671: d0 13                        bne     BublExit
b673: a2 02                        ldx     #$02                    ;otherwise load counter and use as offset
b675: 86 08        BublLoop        stx     ObjectOffset            ;store offset
b677: 20 f9 b6                     jsr     BubbleCheck             ;check timers and coordinates, create air bubble
b67a: 20 31 f1                     jsr     RelativeBubblePosition  ;get relative coordinates
b67d: 20 91 f1                     jsr     GetBubbleOffscreenBits  ;get offscreen information
b680: 20 e1 ed                     jsr     DrawBubble              ;draw the air bubble
b683: ca                           dex
b684: 10 ef                        bpl     BublLoop                ;do this until all three are handled
b686: 60           BublExit        rts                             ;then leave

                   FireballXSpdData
b687: 40                           .dd1    $40
b688: c0                           .dd1    $c0

b689: 86 08        FireballObjCore stx     ObjectOffset            ;store offset as current object
b68b: b5 24                        lda     Fireball_State,x        ;check for d7 = 1
b68d: 0a                           asl     A
b68e: b0 63                        bcs     FireballExplosion       ;if so, branch to get relative coordinates and draw explosion
b690: b4 24                        ldy     Fireball_State,x        ;if fireball inactive, branch to leave
b692: f0 5e                        beq     NoFBall
b694: 88                           dey                             ;if fireball state set to 1, skip this part and just run it
b695: f0 27                        beq     RunFB
b697: a5 86                        lda     Player_X_Position       ;get player's horizontal position
b699: 69 04                        adc     #$04                    ;add four pixels and store as fireball's horizontal position
b69b: 95 8d                        sta     Fireball_X_Position,x
b69d: a5 6d                        lda     Player_PageLoc          ;get player's page location
b69f: 69 00                        adc     #$00                    ;add carry and store as fireball's page location
b6a1: 95 74                        sta     Fireball_PageLoc,x
b6a3: a5 ce                        lda     Player_Y_Position       ;get player's vertical position and store
b6a5: 95 d5                        sta     Fireball_Y_Position,x
b6a7: a9 01                        lda     #$01                    ;set high byte of vertical position
b6a9: 95 bc                        sta     Fireball_Y_HighPos,x
b6ab: a4 33                        ldy     PlayerFacingDir         ;get player's facing direction
b6ad: 88                           dey                             ;decrement to use as offset here
b6ae: b9 87 b6                     lda     FireballXSpdData,y      ;set horizontal speed of fireball accordingly
b6b1: 95 5e                        sta     Fireball_X_Speed,x
b6b3: a9 04                        lda     #$04                    ;set vertical speed of fireball
b6b5: 95 a6                        sta     Fireball_Y_Speed,x
b6b7: a9 07                        lda     #$07
b6b9: 9d a0 04                     sta     Fireball_BoundBoxCtrl,x ;set bounding box size control for fireball
b6bc: d6 24                        dec     Fireball_State,x        ;decrement state to 1 to skip this part from now on
b6be: 8a           RunFB           txa                             ;add 7 to offset to use
b6bf: 18                           clc                             ; as fireball offset for next routines
b6c0: 69 07                        adc     #$07
b6c2: aa                           tax
b6c3: a9 50                        lda     #$50                    ;set downward movement force here
b6c5: 85 00                        sta     $00
b6c7: a9 03                        lda     #$03                    ;set maximum speed here
b6c9: 85 02                        sta     $02
b6cb: a9 00                        lda     #$00
b6cd: 20 d7 bf                     jsr     ImposeGravity           ;do sub here to impose gravity on fireball and move vertically
b6d0: 20 0f bf                     jsr     MoveObjectHorizontally  ;do another sub to move it horizontally
b6d3: a6 08                        ldx     ObjectOffset            ;return fireball offset to X
b6d5: 20 3b f1                     jsr     RelativeFireballPosition ;get relative coordinates
b6d8: 20 87 f1                     jsr     GetFireballOffscreenBits ;get offscreen information
b6db: 20 2d e2                     jsr     GetFireballBoundBox     ;get bounding box coordinates
b6de: 20 c8 e1                     jsr     FireballBGCollision     ;do fireball to background collision detection
b6e1: ad d2 03                     lda     FBall_OffscreenBits     ;get fireball offscreen bits
b6e4: 29 cc                        and     #%11001100              ;mask out certain bits
b6e6: d0 06                        bne     EraseFB                 ;if any bits still set, branch to kill fireball
b6e8: 20 d9 d6                     jsr     FireballEnemyCollision  ;do fireball to enemy collision detection and deal with collisions
b6eb: 4c de ec                     jmp     DrawFireball            ;draw fireball appropriately and leave

b6ee: a9 00        EraseFB         lda     #$00                    ;erase fireball state
b6f0: 95 24                        sta     Fireball_State,x
b6f2: 60           NoFBall         rts                             ;leave

                   FireballExplosion
b6f3: 20 3b f1                     jsr     RelativeFireballPosition
b6f6: 4c 09 ed                     jmp     DrawExplosion_Fireball

b6f9: bd a8 07     BubbleCheck     lda     PseudoRandomBitReg+1,x  ;get part of LSFR
b6fc: 29 01                        and     #$01
b6fe: 85 07                        sta     $07                     ;store pseudorandom bit here
b700: b5 e4                        lda     Bubble_Y_Position,x     ;get vertical coordinate for air bubble
b702: c9 f8                        cmp     #$f8                    ;if offscreen coordinate not set,
b704: d0 2c                        bne     MoveBubl                ;branch to move air bubble
b706: ad 92 07                     lda     AirBubbleTimer          ;if air bubble timer not expired,
b709: d0 3f                        bne     ExitBubl                ;branch to leave, otherwise create new air bubble
b70b: a0 00        SetupBubble     ldy     #$00                    ;load default value here
b70d: a5 33                        lda     PlayerFacingDir         ;get player's facing direction
b70f: 4a                           lsr     A                       ;move d0 to carry
b710: 90 02                        bcc     PosBubl                 ;branch to use default value if facing left
b712: a0 08                        ldy     #$08                    ;otherwise load alternate value here
b714: 98           PosBubl         tya                             ;use value loaded as adder
b715: 65 86                        adc     Player_X_Position       ;add to player's horizontal position
b717: 95 9c                        sta     Bubble_X_Position,x     ;save as horizontal position for airbubble
b719: a5 6d                        lda     Player_PageLoc
b71b: 69 00                        adc     #$00                    ;add carry to player's page location
b71d: 95 83                        sta     Bubble_PageLoc,x        ;save as page location for airbubble
b71f: a5 ce                        lda     Player_Y_Position
b721: 18                           clc                             ;add eight pixels to player's vertical position
b722: 69 08                        adc     #$08
b724: 95 e4                        sta     Bubble_Y_Position,x     ;save as vertical position for air bubble
b726: a9 01                        lda     #$01
b728: 95 cb                        sta     Bubble_Y_HighPos,x      ;set vertical high byte for air bubble
b72a: a4 07                        ldy     $07                     ;get pseudorandom bit, use as offset
b72c: b9 4d b7                     lda     BubbleTimerData,y       ;get data for air bubble timer
b72f: 8d 92 07                     sta     AirBubbleTimer          ;set air bubble timer
b732: a4 07        MoveBubl        ldy     $07                     ;get pseudorandom bit again, use as offset
b734: bd 2c 04                     lda     Bubble_YMF_Dummy,x
b737: 38                           sec                             ;subtract pseudorandom amount from dummy variable
b738: f9 4b b7                     sbc     Bubble_MForceData,y
b73b: 9d 2c 04                     sta     Bubble_YMF_Dummy,x      ;save dummy variable
b73e: b5 e4                        lda     Bubble_Y_Position,x
b740: e9 00                        sbc     #$00                    ;subtract borrow from airbubble's vertical coordinate
b742: c9 20                        cmp     #$20                    ;if below the status bar,
b744: b0 02                        bcs     Y_Bubl                  ;branch to go ahead and use to move air bubble upwards
b746: a9 f8                        lda     #$f8                    ;otherwise set offscreen coordinate
b748: 95 e4        Y_Bubl          sta     Bubble_Y_Position,x     ;store as new vertical coordinate for air bubble
b74a: 60           ExitBubl        rts                             ;leave

                   Bubble_MForceData
b74b: ff                           .dd1    $ff
b74c: 50                           .dd1    $50
b74d: 40           BubbleTimerData .dd1    $40
b74e: 20                           .dd1    $20

                   ; -----------------------------------------------------------------------------
b74f: ad 70 07     RunGameTimer    lda     OperMode                ;get primary mode of operation
b752: f0 4f                        beq     ExGTimer                ;branch to leave if in title screen mode
b754: a5 0e                        lda     GameEngineSubroutine
b756: c9 08                        cmp     #$08                    ;if routine number less than eight running,
b758: 90 49                        bcc     ExGTimer                ;branch to leave
b75a: c9 0b                        cmp     #$0b                    ;if running death routine,
b75c: f0 45                        beq     ExGTimer                ;branch to leave
b75e: a5 b5                        lda     Player_Y_HighPos
b760: c9 02                        cmp     #$02                    ;if player below the screen,
b762: b0 3f                        bcs     ExGTimer                ;branch to leave regardless of level type
b764: ad 87 07                     lda     GameTimerCtrlTimer      ;if game timer control not yet expired,
b767: d0 3a                        bne     ExGTimer                ;branch to leave
b769: ad f8 07                     lda     GameTimerDisplay
b76c: 0d f9 07                     ora     GameTimerDisplay+1      ;otherwise check game timer digits
b76f: 0d fa 07                     ora     GameTimerDisplay+2
b772: f0 26                        beq     TimeUpOn                ;if game timer digits at 000, branch to time-up code
b774: ac f8 07                     ldy     GameTimerDisplay        ;otherwise check first digit
b777: 88                           dey                             ;if first digit not on 1,
b778: d0 0c                        bne     ResGTCtrl               ;branch to reset game timer control
b77a: ad f9 07                     lda     GameTimerDisplay+1      ;otherwise check second and third digits
b77d: 0d fa 07                     ora     GameTimerDisplay+2
b780: d0 04                        bne     ResGTCtrl               ;if timer not at 100, branch to reset game timer control
b782: a9 40                        lda     #TimeRunningOutMusic
b784: 85 fc                        sta     EventMusicQueue         ;otherwise load time running out music
b786: a9 18        ResGTCtrl       lda     #$18                    ;reset game timer control
b788: 8d 87 07                     sta     GameTimerCtrlTimer
b78b: a0 23                        ldy     #$23                    ;set offset for last digit
b78d: a9 ff                        lda     #$ff                    ;set value to decrement game timer digit
b78f: 8d 39 01                     sta     DigitModifier+5
b792: 20 5f 8f                     jsr     DigitsMathRoutine       ;do sub to decrement game timer slowly
b795: a9 a4                        lda     #$a4                    ;set status nybbles to update game timer display
b797: 4c 06 8f                     jmp     PrintStatusBarNumbers   ;do sub to update the display

b79a: 8d 56 07     TimeUpOn        sta     PlayerStatus            ;init player status (note A will always be zero here)
b79d: 20 31 d9                     jsr     ForceInjury             ;do sub to kill the player (note player is small here)
b7a0: ee 59 07                     inc     GameTimerExpiredFlag    ;set game timer expiration flag
b7a3: 60           ExGTimer        rts                             ;leave

                   ; -----------------------------------------------------------------------------
b7a4: ad 23 07     WarpZoneObject  lda     ScrollLock              ;check for scroll lock flag
b7a7: f0 fa                        beq     ExGTimer                ;branch if not set to leave
b7a9: a5 ce                        lda     Player_Y_Position       ;check to see if player's vertical coordinate has
b7ab: 25 b5                        and     Player_Y_HighPos        ;same bits set as in vertical high byte (why?)
b7ad: d0 f4                        bne     ExGTimer                ;if so, branch to leave
b7af: 8d 23 07                     sta     ScrollLock              ;otherwise nullify scroll lock flag
b7b2: ee d6 06                     inc     WarpZoneControl         ;increment warp zone flag to make warp pipes for warp zone
b7b5: 4c 98 c9                     jmp     EraseEnemyObject        ;kill this object

                   ; -----------------------------------------------------------------------------
                   ; $00 - used in WhirlpoolActivate to store whirlpool length / 2, page location
                   ; of center of whirlpool and also to store movement force exerted on player
                   ; $01 - used in ProcessWhirlpools to store page location of right extent of
                   ; whirlpool and in WhirlpoolActivate to store center of whirlpool
                   ; $02 - used in ProcessWhirlpools to store right extent of whirlpool and in
                   ; WhirlpoolActivate to store maximum vertical speed
                   ProcessWhirlpools
b7b8: ad 4e 07                     lda     AreaType                ;check for water type level
b7bb: d0 37                        bne     ExitWh                  ;branch to leave if not found
b7bd: 8d 7d 04                     sta     Whirlpool_Flag          ;otherwise initialize whirlpool flag
b7c0: ad 47 07                     lda     TimerControl            ;if master timer control set,
b7c3: d0 2f                        bne     ExitWh                  ;branch to leave
b7c5: a0 04                        ldy     #$04                    ;otherwise start with last whirlpool data
b7c7: b9 71 04     WhLoop          lda     Whirlpool_LeftExtent,y  ;get left extent of whirlpool
b7ca: 18                           clc
b7cb: 79 77 04                     adc     Whirlpool_Length,y      ;add length of whirlpool
b7ce: 85 02                        sta     $02                     ;store result as right extent here
b7d0: b9 6b 04                     lda     Whirlpool_PageLoc,y     ;get page location
b7d3: f0 1c                        beq     NextWh                  ;if none or page 0, branch to get next data
b7d5: 69 00                        adc     #$00                    ;add carry
b7d7: 85 01                        sta     $01                     ;store result as page location of right extent here
b7d9: a5 86                        lda     Player_X_Position       ;get player's horizontal position
b7db: 38                           sec
b7dc: f9 71 04                     sbc     Whirlpool_LeftExtent,y  ;subtract left extent
b7df: a5 6d                        lda     Player_PageLoc          ;get player's page location
b7e1: f9 6b 04                     sbc     Whirlpool_PageLoc,y     ;subtract borrow
b7e4: 30 0b                        bmi     NextWh                  ;if player too far left, branch to get next data
b7e6: a5 02                        lda     $02                     ;otherwise get right extent
b7e8: 38                           sec
b7e9: e5 86                        sbc     Player_X_Position       ;subtract player's horizontal coordinate
b7eb: a5 01                        lda     $01                     ;get right extent's page location
b7ed: e5 6d                        sbc     Player_PageLoc          ;subtract borrow
b7ef: 10 04                        bpl     WhirlpoolActivate       ;if player within right extent, branch to whirlpool code
b7f1: 88           NextWh          dey                             ;move onto next whirlpool data
b7f2: 10 d3                        bpl     WhLoop                  ;do this until all whirlpools are checked
b7f4: 60           ExitWh          rts                             ;leave

                   WhirlpoolActivate
b7f5: b9 77 04                     lda     Whirlpool_Length,y      ;get length of whirlpool
b7f8: 4a                           lsr     A                       ;divide by 2
b7f9: 85 00                        sta     $00                     ;save here
b7fb: b9 71 04                     lda     Whirlpool_LeftExtent,y  ;get left extent of whirlpool
b7fe: 18                           clc
b7ff: 65 00                        adc     $00                     ;add length divided by 2
b801: 85 01                        sta     $01                     ;save as center of whirlpool
b803: b9 6b 04                     lda     Whirlpool_PageLoc,y     ;get page location
b806: 69 00                        adc     #$00                    ;add carry
b808: 85 00                        sta     $00                     ;save as page location of whirlpool center
b80a: a5 09                        lda     FrameCounter            ;get frame counter
b80c: 4a                           lsr     A                       ;shift d0 into carry (to run on every other frame)
b80d: 90 2c                        bcc     WhPull                  ;if d0 not set, branch to last part of code
b80f: a5 01                        lda     $01                     ;get center
b811: 38                           sec
b812: e5 86                        sbc     Player_X_Position       ;subtract player's horizontal coordinate
b814: a5 00                        lda     $00                     ;get page location of center
b816: e5 6d                        sbc     Player_PageLoc          ;subtract borrow
b818: 10 0e                        bpl     LeftWh                  ;if player to the left of center, branch
b81a: a5 86                        lda     Player_X_Position       ;otherwise slowly pull player left, towards the center
b81c: 38                           sec
b81d: e9 01                        sbc     #$01                    ;subtract one pixel
b81f: 85 86                        sta     Player_X_Position       ;set player's new horizontal coordinate
b821: a5 6d                        lda     Player_PageLoc
b823: e9 00                        sbc     #$00                    ;subtract borrow
b825: 4c 39 b8                     jmp     SetPWh                  ;jump to set player's new page location

b828: ad 90 04     LeftWh          lda     Player_CollisionBits    ;get player's collision bits
b82b: 4a                           lsr     A                       ;shift d0 into carry
b82c: 90 0d                        bcc     WhPull                  ;if d0 not set, branch
b82e: a5 86                        lda     Player_X_Position       ;otherwise slowly pull player right, towards the center
b830: 18                           clc
b831: 69 01                        adc     #$01                    ;add one pixel
b833: 85 86                        sta     Player_X_Position       ;set player's new horizontal coordinate
b835: a5 6d                        lda     Player_PageLoc
b837: 69 00                        adc     #$00                    ;add carry
b839: 85 6d        SetPWh          sta     Player_PageLoc          ;set player's new page location
b83b: a9 10        WhPull          lda     #$10
b83d: 85 00                        sta     $00                     ;set vertical movement force
b83f: a9 01                        lda     #$01
b841: 8d 7d 04                     sta     Whirlpool_Flag          ;set whirlpool flag to be used later
b844: 85 02                        sta     $02                     ;also set maximum vertical speed
b846: 4a                           lsr     A
b847: aa                           tax                             ;set X for player offset
b848: 4c d7 bf                     jmp     ImposeGravity           ;jump to put whirlpool effect on player vertically, do not return

                   ; -----------------------------------------------------------------------------
                   FlagpoleScoreMods
b84b: 05 02 08 04+                 .bulk   $05,$02,$08,$04,$01
                   FlagpoleScoreDigits
b850: 03 03 04 04+                 .bulk   $03,$03,$04,$04,$04

b855: a2 05        FlagpoleRoutine ldx     #$05                    ;set enemy object offset
b857: 86 08                        stx     ObjectOffset            ; to special use slot
b859: b5 16                        lda     Enemy_ID,x
b85b: c9 30                        cmp     #FlagpoleFlagObject     ;if flagpole flag not found,
b85d: d0 56                        bne     ExitFlagP               ;branch to leave
b85f: a5 0e                        lda     GameEngineSubroutine
b861: c9 04                        cmp     #$04                    ;if flagpole slide routine not running,
b863: d0 31                        bne     SkipScore               ;branch to near the end of code
b865: a5 1d                        lda     Player_State
b867: c9 03                        cmp     #$03                    ;if player state not climbing,
b869: d0 2b                        bne     SkipScore               ;branch to near the end of code
b86b: b5 cf                        lda     Enemy_Y_Position,x      ;check flagpole flag's vertical coordinate
b86d: c9 aa                        cmp     #$aa                    ;if flagpole flag down to a certain point,
b86f: b0 28                        bcs     GiveFPScr               ;branch to end the level
b871: a5 ce                        lda     Player_Y_Position       ;check player's vertical coordinate
b873: c9 a2                        cmp     #$a2                    ;if player down to a certain point,
b875: b0 22                        bcs     GiveFPScr               ;branch to end the level
b877: bd 17 04                     lda     Enemy_YMF_Dummy,x
b87a: 69 ff                        adc     #$ff                    ;add movement amount to dummy variable
b87c: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;save dummy variable
b87f: b5 cf                        lda     Enemy_Y_Position,x      ;get flag's vertical coordinate
b881: 69 01                        adc     #$01                    ;add 1 plus carry to move flag, and
b883: 95 cf                        sta     Enemy_Y_Position,x      ; store vertical coordinate
b885: ad 0e 01                     lda     FlagpoleFNum_YMFDummy
b888: 38                           sec                             ;subtract movement amount from dummy variable
b889: e9 ff                        sbc     #$ff
b88b: 8d 0e 01                     sta     FlagpoleFNum_YMFDummy   ;save dummy variable
b88e: ad 0d 01                     lda     FlagpoleFNum_Y_Pos
b891: e9 01                        sbc     #$01                    ;subtract one plus borrow to move floatey number,
b893: 8d 0d 01                     sta     FlagpoleFNum_Y_Pos      ; and store vertical coordinate here
b896: 4c ac b8     SkipScore       jmp     FPGfx                   ;jump to skip ahead and draw flag and floatey number

b899: ac 0f 01     GiveFPScr       ldy     FlagpoleScore           ;get score offset from earlier (when player touched flagpole)
b89c: b9 4b b8                     lda     FlagpoleScoreMods,y     ;get amount to award player points
b89f: be 50 b8                     ldx     FlagpoleScoreDigits,y   ;get digit with which to award points
b8a2: 9d 34 01                     sta     DigitModifier,x         ;store in digit modifier
b8a5: 20 27 bc                     jsr     AddToScore              ;do sub to award player points depending on height of collision
b8a8: a9 05                        lda     #$05
b8aa: 85 0e                        sta     GameEngineSubroutine    ;set to run end-of-level subroutine on next frame
b8ac: 20 af f1     FPGfx           jsr     GetEnemyOffscreenBits   ;get offscreen information
b8af: 20 52 f1                     jsr     RelativeEnemyPosition   ;get relative coordinates
b8b2: 20 4b e5                     jsr     FlagpoleGfxHandler      ;draw flagpole flag and floatey number
b8b5: 60           ExitFlagP       rts

                   ; -----------------------------------------------------------------------------
                   Jumpspring_Y_PosData
b8b6: 08 10 08 00                  .bulk   $08,$10,$08,$00

                   JumpspringHandler
b8ba: 20 af f1                     jsr     GetEnemyOffscreenBits   ;get offscreen information
b8bd: ad 47 07                     lda     TimerControl            ;check master timer control
b8c0: d0 40                        bne     DrawJSpr                ;branch to last section if set
b8c2: ad 0e 07                     lda     JumpspringAnimCtrl      ;check jumpspring frame control
b8c5: f0 3b                        beq     DrawJSpr                ;branch to last section if not set
b8c7: a8                           tay
b8c8: 88                           dey                             ;subtract one from frame control,
b8c9: 98                           tya                             ; the only way a poor nmos 6502 can
b8ca: 29 02                        and     #%00000010              ; mask out all but d1, original value still in Y
b8cc: d0 07                        bne     DownJSpr                ;if set, branch to move player up
b8ce: e6 ce                        inc     Player_Y_Position
b8d0: e6 ce                        inc     Player_Y_Position       ;move player's vertical position down two pixels
b8d2: 4c d9 b8                     jmp     PosJSpr                 ;skip to next part

b8d5: c6 ce        DownJSpr        dec     Player_Y_Position       ;move player's vertical position up two pixels
b8d7: c6 ce                        dec     Player_Y_Position
b8d9: b5 58        PosJSpr         lda     Jumpspring_FixedYPos,x  ;get permanent vertical position
b8db: 18                           clc
b8dc: 79 b6 b8                     adc     Jumpspring_Y_PosData,y  ;add value using frame control as offset
b8df: 95 cf                        sta     Enemy_Y_Position,x      ;store as new vertical position
b8e1: c0 01                        cpy     #$01                    ;check frame control offset (second frame is $00)
b8e3: 90 0f                        bcc     BounceJS                ;if offset not yet at third frame ($01), skip to next part
b8e5: a5 0a                        lda     A_B_Buttons
b8e7: 29 80                        and     #A_Button               ;check saved controller bits for A button press
b8e9: f0 09                        beq     BounceJS                ;skip to next part if A not pressed
b8eb: 25 0d                        and     PreviousA_B_Buttons     ;check for A button pressed in previous frame
b8ed: d0 05                        bne     BounceJS                ;skip to next part if so
b8ef: a9 f4                        lda     #$f4
b8f1: 8d db 06                     sta     JumpspringForce         ;otherwise write new jumpspring force here
b8f4: c0 03        BounceJS        cpy     #$03                    ;check frame control offset again
b8f6: d0 0a                        bne     DrawJSpr                ;skip to last part if not yet at fifth frame ($03)
b8f8: ad db 06                     lda     JumpspringForce
b8fb: 85 9f                        sta     Player_Y_Speed          ;store jumpspring force as player's new vertical speed
b8fd: a9 00                        lda     #$00
b8ff: 8d 0e 07                     sta     JumpspringAnimCtrl      ;initialize jumpspring frame control
b902: 20 52 f1     DrawJSpr        jsr     RelativeEnemyPosition   ;get jumpspring's relative coordinates
b905: 20 7d e8                     jsr     EnemyGfxHandler         ;draw jumpspring
b908: 20 7a d6                     jsr     OffscreenBoundsCheck    ;check to see if we need to kill it
b90b: ad 0e 07                     lda     JumpspringAnimCtrl      ;if frame control at zero, don't bother
b90e: f0 0d                        beq     ExJSPring               ;trying to animate it, just leave
b910: ad 86 07                     lda     JumpspringTimer
b913: d0 08                        bne     ExJSPring               ;if jumpspring timer not expired yet, leave
b915: a9 04                        lda     #$04
b917: 8d 86 07                     sta     JumpspringTimer         ;otherwise initialize jumpspring timer
b91a: ee 0e 07                     inc     JumpspringAnimCtrl      ;increment frame control to animate jumpspring
b91d: 60           ExJSPring       rts                             ;leave

                   ; -----------------------------------------------------------------------------
b91e: a9 2f        Setup_Vine      lda     #VineObject             ;load identifier for vine object
b920: 95 16                        sta     Enemy_ID,x              ;store in buffer
b922: a9 01                        lda     #$01
b924: 95 0f                        sta     Enemy_Flag,x            ;set flag for enemy object buffer
b926: b9 76 00                     lda     Block_PageLoc,y
b929: 95 6e                        sta     Enemy_PageLoc,x         ;copy page location from previous object
b92b: b9 8f 00                     lda     Block_X_Position,y
b92e: 95 87                        sta     Enemy_X_Position,x      ;copy horizontal coordinate from previous object
b930: b9 d7 00                     lda     Block_Y_Position,y
b933: 95 cf                        sta     Enemy_Y_Position,x      ;copy vertical coordinate from previous object
b935: ac 98 03                     ldy     VineFlagOffset          ;load vine flag/offset to next available vine slot
b938: d0 03                        bne     NextVO                  ;if set at all, don't bother to store vertical
b93a: 8d 9d 03                     sta     VineStart_Y_Position    ;otherwise store vertical coordinate here
b93d: 8a           NextVO          txa                             ;store object offset to next available vine slot
b93e: 99 9a 03                     sta     VineObjOffset,y         ;using vine flag as offset
b941: ee 98 03                     inc     VineFlagOffset          ;increment vine flag offset
b944: a9 04                        lda     #Sfx_GrowVine
b946: 85 fe                        sta     Square2SoundQueue       ;load vine grow sound
b948: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $06-$07 - used as address to block buffer data
                   ; $02 - used as vertical high nybble of block buffer offset
b949: 30 60        VineHeightData  .bulk   $30,$60

                   VineObjectHandler
b94b: e0 05                        cpx     #$05                    ;check enemy offset for special use slot
b94d: d0 68                        bne     ExitVH                  ;if not in last slot, branch to leave
b94f: ac 98 03                     ldy     VineFlagOffset
b952: 88                           dey                             ;decrement vine flag in Y, use as offset
b953: ad 99 03                     lda     VineHeight
b956: d9 49 b9                     cmp     VineHeightData,y        ;if vine has reached certain height,
b959: f0 0f                        beq     RunVSubs                ;branch ahead to skip this part
b95b: a5 09                        lda     FrameCounter            ;get frame counter
b95d: 4a                           lsr     A                       ;shift d1 into carry
b95e: 4a                           lsr     A
b95f: 90 09                        bcc     RunVSubs                ;if d1 not set (2 frames every 4) skip this part
b961: a5 d4                        lda     Enemy_Y_Position+5
b963: e9 01                        sbc     #$01                    ;subtract vertical position of vine
b965: 85 d4                        sta     Enemy_Y_Position+5      ;one pixel every frame it's time
b967: ee 99 03                     inc     VineHeight              ;increment vine height
b96a: ad 99 03     RunVSubs        lda     VineHeight              ;if vine still very small,
b96d: c9 08                        cmp     #$08                    ;branch to leave
b96f: 90 46                        bcc     ExitVH
b971: 20 52 f1                     jsr     RelativeEnemyPosition   ;get relative coordinates of vine,
b974: 20 af f1                     jsr     GetEnemyOffscreenBits   ; and any offscreen bits
b977: a0 00                        ldy     #$00                    ;initialize offset used in draw vine sub
b979: 20 35 e4     VDrawLoop       jsr     DrawVine                ;draw vine
b97c: c8                           iny                             ;increment offset
b97d: cc 98 03                     cpy     VineFlagOffset          ;if offset in Y and offset here
b980: d0 f7                        bne     VDrawLoop               ;do not yet match, loop back to draw more vine
b982: ad d1 03                     lda     Enemy_OffscreenBits
b985: 29 0c                        and     #%00001100              ;mask offscreen bits
b987: f0 10                        beq     WrCMTile                ;if none of the saved offscreen bits set, skip ahead
b989: 88                           dey                             ;otherwise decrement Y to get proper offset again
b98a: be 9a 03     KillVine        ldx     VineObjOffset,y         ;get enemy object offset for this vine object
b98d: 20 98 c9                     jsr     EraseEnemyObject        ;kill this vine object
b990: 88                           dey                             ;decrement Y
b991: 10 f7                        bpl     KillVine                ;if any vine objects left, loop back to kill it
b993: 8d 98 03                     sta     VineFlagOffset          ;initialize vine flag/offset
b996: 8d 99 03                     sta     VineHeight              ;initialize vine height
b999: ad 99 03     WrCMTile        lda     VineHeight              ;check vine height
b99c: c9 20                        cmp     #$20                    ;if vine small (less than 32 pixels tall)
b99e: 90 17                        bcc     ExitVH                  ;then branch ahead to leave
b9a0: a2 06                        ldx     #$06                    ;set offset in X to last enemy slot
b9a2: a9 01                        lda     #$01                    ;set A to obtain horizontal in $04, but we don't care
b9a4: a0 1b                        ldy     #$1b                    ;set Y to offset to get block at ($04, $10) of coordinates
b9a6: 20 f0 e3                     jsr     BlockBufferCollision    ;do a sub to get block buffer address set, return contents
b9a9: a4 02                        ldy     $02
b9ab: c0 d0                        cpy     #$d0                    ;if vertical high nybble offset beyond extent of
b9ad: b0 08                        bcs     ExitVH                  ; current block buffer, branch to leave, do not write
b9af: b1 06                        lda     ($06),y                 ;otherwise check contents of block buffer at 
b9b1: d0 04                        bne     ExitVH                  ; current offset, if not empty, branch to leave
b9b3: a9 26                        lda     #$26
b9b5: 91 06                        sta     ($06),y                 ;otherwise, write climbing metatile to block buffer
b9b7: a6 08        ExitVH          ldx     ObjectOffset            ;get enemy object offset and leave
b9b9: 60                           rts

                   ; -----------------------------------------------------------------------------
b9ba: 0f           CannonBitMasks  .dd1    %00001111
b9bb: 07                           .dd1    %00000111

b9bc: ad 4e 07     ProcessCannons  lda     AreaType                ;get area type
b9bf: f0 6f                        beq     ExCannon                ;if water type area, branch to leave
b9c1: a2 02                        ldx     #$02
b9c3: 86 08        ThreeSChk       stx     ObjectOffset            ;start at third enemy slot
b9c5: b5 0f                        lda     Enemy_Flag,x            ;check enemy buffer flag
b9c7: d0 51                        bne     Chk_BB                  ;if set, branch to check enemy
b9c9: bd a8 07                     lda     PseudoRandomBitReg+1,x  ;otherwise get part of LSFR
b9cc: ac cc 06                     ldy     SecondaryHardMode       ;get secondary hard mode flag, use as offset
b9cf: 39 ba b9                     and     CannonBitMasks,y        ;mask out bits of LSFR as decided by flag
b9d2: c9 06                        cmp     #$06                    ;check to see if lower nybble is above certain value
b9d4: b0 44                        bcs     Chk_BB                  ;if so, branch to check enemy
b9d6: a8                           tay                             ;transfer masked contents of LSFR to Y as pseudorandom offset
b9d7: b9 6b 04                     lda     Cannon_PageLoc,y        ;get page location
b9da: f0 3e                        beq     Chk_BB                  ;if not set or on page 0, branch to check enemy
b9dc: b9 7d 04                     lda     Cannon_Timer,y          ;get cannon timer
b9df: f0 08                        beq     FireCannon              ;if expired, branch to fire cannon
b9e1: e9 00                        sbc     #$00                    ;otherwise subtract borrow (note carry will always be clear here)
b9e3: 99 7d 04                     sta     Cannon_Timer,y          ; to count timer down
b9e6: 4c 1a ba                     jmp     Chk_BB

b9e9: ad 47 07     FireCannon      lda     TimerControl            ;if master timer control set,
b9ec: d0 2c                        bne     Chk_BB                  ;branch to check enemy
b9ee: a9 0e                        lda     #$0e                    ;otherwise we start creating one
b9f0: 99 7d 04                     sta     Cannon_Timer,y          ;first, reset cannon timer
b9f3: b9 6b 04                     lda     Cannon_PageLoc,y        ;get page location of cannon
b9f6: 95 6e                        sta     Enemy_PageLoc,x         ;save as page location of bullet bill
b9f8: b9 71 04                     lda     Cannon_X_Position,y     ;get horizontal coordinate of cannon
b9fb: 95 87                        sta     Enemy_X_Position,x      ;save as horizontal coordinate of bullet bill
b9fd: b9 77 04                     lda     Cannon_Y_Position,y     ;get vertical coordinate of cannon
ba00: 38                           sec
ba01: e9 08                        sbc     #$08                    ;subtract eight pixels (because enemies are 24 pixels tall)
ba03: 95 cf                        sta     Enemy_Y_Position,x      ;save as vertical coordinate of bullet bill
ba05: a9 01                        lda     #$01
ba07: 95 b6                        sta     Enemy_Y_HighPos,x       ;set vertical high byte of bullet bill
ba09: 95 0f                        sta     Enemy_Flag,x            ;set buffer flag
ba0b: 4a                           lsr     A                       ;shift right once to init A
ba0c: 95 1e                        sta     Enemy_State,x           ;then initialize enemy's state
ba0e: a9 09                        lda     #$09
ba10: 9d 9a 04                     sta     Enemy_BoundBoxCtrl,x    ;set bounding box size control for bullet bill
ba13: a9 33                        lda     #BulletBill_CannonVar
ba15: 95 16                        sta     Enemy_ID,x              ;load identifier for bullet bill (cannon variant)
ba17: 4c 2d ba                     jmp     Next3Slt                ;move onto next slot

ba1a: b5 16        Chk_BB          lda     Enemy_ID,x              ;check enemy identifier for bullet bill (cannon variant)
ba1c: c9 33                        cmp     #BulletBill_CannonVar
ba1e: d0 0d                        bne     Next3Slt                ;if not found, branch to get next slot
ba20: 20 7a d6                     jsr     OffscreenBoundsCheck    ;otherwise, check to see if it went offscreen
ba23: b5 0f                        lda     Enemy_Flag,x            ;check enemy buffer flag
ba25: f0 06                        beq     Next3Slt                ;if not set, branch to get next slot
ba27: 20 af f1                     jsr     GetEnemyOffscreenBits   ;otherwise, get offscreen information
ba2a: 20 33 ba                     jsr     BulletBillHandler       ;then do sub to handle bullet bill
ba2d: ca           Next3Slt        dex                             ;move onto next slot
ba2e: 10 93                        bpl     ThreeSChk               ;do this until first three slots are checked
ba30: 60           ExCannon        rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   BulletBillXSpdData
ba31: 18 e8                        .bulk   $18,$e8

                   BulletBillHandler
ba33: ad 47 07                     lda     TimerControl            ;if master timer control set,
ba36: d0 3e                        bne     RunBBSubs               ;branch to run subroutines except movement sub
ba38: b5 1e                        lda     Enemy_State,x
ba3a: d0 2e                        bne     ChkDSte                 ;if bullet bill's state set, branch to check defeated state
ba3c: ad d1 03                     lda     Enemy_OffscreenBits     ;otherwise load offscreen bits
ba3f: 29 0c                        and     #%00001100              ;mask out bits
ba41: c9 0c                        cmp     #%00001100              ;check to see if all bits are set
ba43: f0 40                        beq     KillBB                  ;if so, branch to kill this object
ba45: a0 01                        ldy     #$01                    ;set to move right by default
ba47: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and bullet bill
ba4a: 30 01                        bmi     SetupBB                 ;if enemy to the left of player, branch
ba4c: c8                           iny                             ;otherwise increment to move left
ba4d: 94 46        SetupBB         sty     Enemy_MovingDir,x       ;set bullet bill's moving direction
ba4f: 88                           dey                             ;decrement to use as offset
ba50: b9 31 ba                     lda     BulletBillXSpdData,y    ;get horizontal speed based on moving direction
ba53: 95 58                        sta     BlooperMoveSpeed,x      ;and store it
ba55: a5 00                        lda     $00                     ;get horizontal difference
ba57: 69 28                        adc     #$28                    ;add 40 pixels
ba59: c9 50                        cmp     #$50                    ;if less than a certain amount, player is too close
ba5b: 90 28                        bcc     KillBB                  ;to cannon either on left or right side, thus branch
ba5d: a9 01                        lda     #$01
ba5f: 95 1e                        sta     Enemy_State,x           ;otherwise set bullet bill's state
ba61: a9 0a                        lda     #$0a
ba63: 9d 8a 07                     sta     EnemyFrameTimer,x       ;set enemy frame timer
ba66: a9 08                        lda     #$08
ba68: 85 fe                        sta     Square2SoundQueue       ;play fireworks/gunfire sound
ba6a: b5 1e        ChkDSte         lda     Enemy_State,x           ;check enemy state for d5 set
ba6c: 29 20                        and     #%00100000
ba6e: f0 03                        beq     BBFly                   ;if not set, skip to move horizontally
ba70: 20 63 bf                     jsr     MoveD_EnemyVertically   ;otherwise do sub to move bullet bill vertically
ba73: 20 02 bf     BBFly           jsr     MoveEnemyHorizontally   ;do sub to move bullet bill horizontally
ba76: 20 af f1     RunBBSubs       jsr     GetEnemyOffscreenBits   ;get offscreen information
ba79: 20 52 f1                     jsr     RelativeEnemyPosition   ;get relative coordinates
ba7c: 20 43 e2                     jsr     GetEnemyBoundBox        ;get bounding box coordinates
ba7f: 20 53 d8                     jsr     PlayerEnemyCollision    ;handle player to enemy collisions
ba82: 4c 7d e8                     jmp     EnemyGfxHandler         ;draw the bullet bill and leave

ba85: 20 98 c9     KillBB          jsr     EraseEnemyObject        ;kill bullet bill and leave
ba88: 60                           rts

                   ; -----------------------------------------------------------------------------
                   HammerEnemyOfsData
ba89: 04 04 04 05+                 .bulk   $04,$04,$04,$05,$05,$05,$06,$06,$06
ba92: 10 f0        HammerXSpdData  .bulk   $10,$f0

ba94: ad a8 07     SpawnHammerObj  lda     PseudoRandomBitReg+1    ;get pseudorandom bits from
ba97: 29 07                        and     #$07                    ; second part of LSFR
ba99: d0 05                        bne     SetMOfs                 ;if any bits are set, branch and use as offset
ba9b: ad a8 07                     lda     PseudoRandomBitReg+1
ba9e: 29 08                        and     #%00001000              ;get d3 from same part of LSFR
baa0: a8           SetMOfs         tay                             ;use either d3 or d2-d0 for offset here
baa1: b9 2a 00                     lda     Misc_State,y            ;if any values loaded in
baa4: d0 19                        bne     NoHammer                ; $2a-$32 where offset is then leave with carry clear
baa6: be 89 ba                     ldx     HammerEnemyOfsData,y    ;get offset of enemy slot to check using Y as offset
baa9: b5 0f                        lda     Enemy_Flag,x            ;check enemy buffer flag at offset
baab: d0 12                        bne     NoHammer                ;if buffer flag set, branch to leave with carry clear
baad: a6 08                        ldx     ObjectOffset            ;get original enemy object offset
baaf: 8a                           txa
bab0: 99 ae 06                     sta     HammerEnemyOffset,y     ;save here
bab3: a9 90                        lda     #$90
bab5: 99 2a 00                     sta     Misc_State,y            ;save hammer's state here
bab8: a9 07                        lda     #$07
baba: 99 a2 04                     sta     Misc_BoundBoxCtrl,y     ;set something else entirely, here
babd: 38                           sec                             ;return with carry set
babe: 60                           rts

babf: a6 08        NoHammer        ldx     ObjectOffset            ;get original enemy object offset
bac1: 18                           clc                             ;return with carry clear
bac2: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to set downward force
                   ; $01 - used to set upward force (residual)
                   ; $02 - used to set maximum speed
bac3: ad 47 07     ProcHammerObj   lda     TimerControl            ;if master timer control set
bac6: d0 63                        bne     RunHSubs                ; skip all of this code and go to last subs at the end
bac8: b5 2a                        lda     Misc_State,x            ;otherwise get hammer's state
baca: 29 7f                        and     #%01111111              ;mask out d7
bacc: bc ae 06                     ldy     HammerEnemyOffset,x     ;get enemy object offset that spawned this hammer
bacf: c9 02                        cmp     #$02                    ;check hammer's state
bad1: f0 20                        beq     SetHSpd                 ;if currently at 2, branch
bad3: b0 34                        bcs     SetHPos                 ;if greater than 2, branch elsewhere
bad5: 8a                           txa
bad6: 18                           clc                             ;add 13 bytes to use
bad7: 69 0d                        adc     #$0d                    ; proper misc object
bad9: aa                           tax                             ;return offset to X
bada: a9 10                        lda     #$10
badc: 85 00                        sta     $00                     ;set downward movement force
bade: a9 0f                        lda     #$0f
bae0: 85 01                        sta     $01                     ;set upward movement force (not used)
bae2: a9 04                        lda     #$04
bae4: 85 02                        sta     $02                     ;set maximum vertical speed
bae6: a9 00                        lda     #$00                    ;set A to impose gravity on hammer
bae8: 20 d7 bf                     jsr     ImposeGravity           ;do sub to impose gravity on hammer and move vertically
baeb: 20 0f bf                     jsr     MoveObjectHorizontally  ;do sub to move it horizontally
baee: a6 08                        ldx     ObjectOffset            ;get original misc object offset
baf0: 4c 28 bb                     jmp     RunAllH                 ;branch to essential subroutines

baf3: a9 fe        SetHSpd         lda     #$fe
baf5: 95 ac                        sta     Misc_Y_Speed,x          ;set hammer's vertical speed
baf7: b9 1e 00                     lda     Enemy_State,y           ;get enemy object state
bafa: 29 f7                        and     #%11110111              ;mask out d3
bafc: 99 1e 00                     sta     Enemy_State,y           ;store new state
baff: b6 46                        ldx     Enemy_MovingDir,y       ;get enemy's moving direction
bb01: ca                           dex                             ;decrement to use as offset
bb02: bd 92 ba                     lda     HammerXSpdData,x        ;get proper speed to use based on moving direction
bb05: a6 08                        ldx     ObjectOffset            ;reobtain hammer's buffer offset
bb07: 95 64                        sta     Misc_X_Speed,x          ;set hammer's horizontal speed
bb09: d6 2a        SetHPos         dec     Misc_State,x            ;decrement hammer's state
bb0b: b9 87 00                     lda     Enemy_X_Position,y      ;get enemy's horizontal position
bb0e: 18                           clc
bb0f: 69 02                        adc     #$02                    ;set position 2 pixels to the right
bb11: 95 93                        sta     Misc_X_Position,x       ;store as hammer's horizontal position
bb13: b9 6e 00                     lda     Enemy_PageLoc,y         ;get enemy's page location
bb16: 69 00                        adc     #$00                    ;add carry
bb18: 95 7a                        sta     Misc_PageLoc,x          ;store as hammer's page location
bb1a: b9 cf 00                     lda     Enemy_Y_Position,y      ;get enemy's vertical position
bb1d: 38                           sec
bb1e: e9 0a                        sbc     #$0a                    ;move position 10 pixels upward
bb20: 95 db                        sta     Misc_Y_Position,x       ;store as hammer's vertical position
bb22: a9 01                        lda     #$01
bb24: 95 c2                        sta     Misc_Y_HighPos,x        ;set hammer's vertical high byte
bb26: d0 03                        bne     RunHSubs                ;unconditional branch to skip first routine

bb28: 20 c4 d7     RunAllH         jsr     PlayerHammerCollision   ;handle collisions
bb2b: 20 9b f1     RunHSubs        jsr     GetMiscOffscreenBits    ;get offscreen information
bb2e: 20 48 f1                     jsr     RelativeMiscPosition    ;get relative coordinates
bb31: 20 36 e2                     jsr     GetMiscBoundBox         ;get bounding box coordinates
bb34: 20 dc e4                     jsr     DrawHammer              ;draw the hammer
bb37: 60                           rts                             ;and we are done here

                   ; -----------------------------------------------------------------------------
                   ; $02 - used to store vertical high nybble offset from block buffer routine
                   ; $06 - used to store low byte of block buffer address
bb38: 20 84 bb     CoinBlock       jsr     FindEmptyMiscSlot       ;set offset for empty or last misc object buffer slot
bb3b: b5 76                        lda     Block_PageLoc,x         ;get page location of block object
bb3d: 99 7a 00                     sta     Misc_PageLoc,y          ;store as page location of misc object
bb40: b5 8f                        lda     Block_X_Position,x      ;get horizontal coordinate of block object
bb42: 09 05                        ora     #$05                    ;add 5 pixels
bb44: 99 93 00                     sta     Misc_X_Position,y       ;store as horizontal coordinate of misc object
bb47: b5 d7                        lda     Block_Y_Position,x      ;get vertical coordinate of block object
bb49: e9 10                        sbc     #$10                    ;subtract 16 pixels
bb4b: 99 db 00                     sta     Misc_Y_Position,y       ;store as vertical coordinate of misc object
bb4e: 4c 6c bb                     jmp     JCoinC                  ;jump to rest of code as applies to this misc object

bb51: 20 84 bb     SetupJumpCoin   jsr     FindEmptyMiscSlot       ;set offset for empty or last misc object buffer slot
bb54: bd ea 03                     lda     Block_PageLoc2,x        ;get page location saved earlier
bb57: 99 7a 00                     sta     Misc_PageLoc,y          ;and save as page location for misc object
bb5a: a5 06                        lda     $06                     ;get low byte of block buffer offset
bb5c: 0a                           asl     A
bb5d: 0a                           asl     A                       ;multiply by 16 to use lower nybble
bb5e: 0a                           asl     A
bb5f: 0a                           asl     A
bb60: 09 05                        ora     #$05                    ;add five pixels
bb62: 99 93 00                     sta     Misc_X_Position,y       ;save as horizontal coordinate for misc object
bb65: a5 02                        lda     $02                     ;get vertical high nybble offset from earlier
bb67: 69 20                        adc     #$20                    ;add 32 pixels for the status bar
bb69: 99 db 00                     sta     Misc_Y_Position,y       ;store as vertical coordinate
bb6c: a9 fb        JCoinC          lda     #$fb
bb6e: 99 ac 00                     sta     Misc_Y_Speed,y          ;set vertical speed
bb71: a9 01                        lda     #$01
bb73: 99 c2 00                     sta     Misc_Y_HighPos,y        ;set vertical high byte
bb76: 99 2a 00                     sta     Misc_State,y            ;set state for misc object
bb79: 85 fe                        sta     Square2SoundQueue       ;load coin grab sound
bb7b: 86 08                        stx     ObjectOffset            ;store current control bit as misc object offset 
bb7d: 20 fe bb                     jsr     GiveOneCoin             ;update coin tally on the screen and coin amount variable
bb80: ee 48 07                     inc     CoinTallyFor1Ups        ;increment coin tally used to activate 1-up block flag
bb83: 60                           rts

                   FindEmptyMiscSlot
bb84: a0 08                        ldy     #$08                    ;start at end of misc objects buffer
bb86: b9 2a 00     FMiscLoop       lda     Misc_State,y            ;get misc object state
bb89: f0 07                        beq     UseMiscS                ;branch if none found to use current offset
bb8b: 88                           dey                             ;decrement offset
bb8c: c0 05                        cpy     #$05                    ;do this for three slots
bb8e: d0 f6                        bne     FMiscLoop               ;do this until all slots are checked
bb90: a0 08                        ldy     #$08                    ;if no empty slots found, use last slot
bb92: 8c b7 06     UseMiscS        sty     JumpCoinMiscOffset      ;store offset of misc object buffer here (residual)
bb95: 60                           rts

                   ; -----------------------------------------------------------------------------
bb96: a2 08        MiscObjectsCore ldx     #$08                    ;set at end of misc object buffer
bb98: 86 08        MiscLoop        stx     ObjectOffset            ;store misc object offset here
bb9a: b5 2a                        lda     Misc_State,x            ;check misc object state
bb9c: f0 56                        beq     MiscLoopBack            ;branch to check next slot
bb9e: 0a                           asl     A                       ;otherwise shift d7 into carry
bb9f: 90 06                        bcc     ProcJumpCoin            ;if d7 not set, jumping coin, thus skip to rest of code here
bba1: 20 c3 ba                     jsr     ProcHammerObj           ;otherwise go to process hammer,
bba4: 4c f4 bb                     jmp     MiscLoopBack            ;then check next slot

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to set downward force
                   ; $01 - used to set upward force (residual)
                   ; $02 - used to set maximum speed
bba7: b4 2a        ProcJumpCoin    ldy     Misc_State,x            ;check misc object state
bba9: 88                           dey                             ;decrement to see if it's set to 1
bbaa: f0 1d                        beq     JCoinRun                ;if so, branch to handle jumping coin
bbac: f6 2a                        inc     Misc_State,x            ;otherwise increment state to either start off or as timer
bbae: b5 93                        lda     Misc_X_Position,x       ;get horizontal coordinate for misc object
bbb0: 18                           clc                             ;whether its jumping coin (state 0 only) or floatey number
bbb1: 6d 75 07                     adc     ScrollAmount            ;add current scroll speed
bbb4: 95 93                        sta     Misc_X_Position,x       ;store as new horizontal coordinate
bbb6: b5 7a                        lda     Misc_PageLoc,x          ;get page location
bbb8: 69 00                        adc     #$00                    ;add carry
bbba: 95 7a                        sta     Misc_PageLoc,x          ;store as new page location
bbbc: b5 2a                        lda     Misc_State,x
bbbe: c9 30                        cmp     #$30                    ;check state of object for preset value
bbc0: d0 26                        bne     RunJCSubs               ;if not yet reached, branch to subroutines
bbc2: a9 00                        lda     #$00
bbc4: 95 2a                        sta     Misc_State,x            ;otherwise nullify object state
bbc6: 4c f4 bb                     jmp     MiscLoopBack            ;and move onto next slot

bbc9: 8a           JCoinRun        txa
bbca: 18                           clc                             ;add 13 bytes to offset for next subroutine
bbcb: 69 0d                        adc     #$0d
bbcd: aa                           tax
bbce: a9 50                        lda     #$50                    ;set downward movement amount
bbd0: 85 00                        sta     $00
bbd2: a9 06                        lda     #$06                    ;set maximum vertical speed
bbd4: 85 02                        sta     $02
bbd6: 4a                           lsr     A                       ;divide by 2 and set
bbd7: 85 01                        sta     $01                     ;as upward movement amount (apparently residual)
bbd9: a9 00                        lda     #$00                    ;set A to impose gravity on jumping coin
bbdb: 20 d7 bf                     jsr     ImposeGravity           ;do sub to move coin vertically and impose gravity on it
bbde: a6 08                        ldx     ObjectOffset            ;get original misc object offset
bbe0: b5 ac                        lda     Misc_Y_Speed,x          ;check vertical speed
bbe2: c9 05                        cmp     #$05
bbe4: d0 02                        bne     RunJCSubs               ;if not moving downward fast enough, keep state as-is
bbe6: f6 2a                        inc     Misc_State,x            ;otherwise increment state to change to floatey number
bbe8: 20 48 f1     RunJCSubs       jsr     RelativeMiscPosition    ;get relative coordinates
bbeb: 20 9b f1                     jsr     GetMiscOffscreenBits    ;get offscreen information
bbee: 20 36 e2                     jsr     GetMiscBoundBox         ;get bounding box coordinates (why?)
bbf1: 20 86 e6                     jsr     JCoinGfxHandler         ;draw the coin or floatey number
bbf4: ca           MiscLoopBack    dex                             ;decrement misc object offset
bbf5: 10 a1                        bpl     MiscLoop                ;loop back until all misc objects handled
bbf7: 60                           rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   CoinTallyOffsets
bbf8: 17 1d                        .bulk   $17,$1d
bbfa: 0b 11        ScoreOffsets    .bulk   $0b,$11
                   StatusBarNybbles
bbfc: 02 13                        .bulk   $02,$13

bbfe: a9 01        GiveOneCoin     lda     #$01                    ;set digit modifier to add 1 coin
bc00: 8d 39 01                     sta     DigitModifier+5         ; to the current player's coin tally
bc03: ae 53 07                     ldx     CurrentPlayer           ;get current player on the screen
bc06: bc f8 bb                     ldy     CoinTallyOffsets,x      ;get offset for player's coin tally
bc09: 20 5f 8f                     jsr     DigitsMathRoutine       ;update the coin tally
bc0c: ee 5e 07                     inc     CoinTally               ;increment onscreen player's coin amount
bc0f: ad 5e 07                     lda     CoinTally
bc12: c9 64                        cmp     #100                    ;does player have 100 coins yet?
bc14: d0 0c                        bne     CoinPoints              ;if not, skip all of this
bc16: a9 00                        lda     #$00
bc18: 8d 5e 07                     sta     CoinTally               ;otherwise, reinitialize coin amount
bc1b: ee 5a 07                     inc     NumberOfLives           ;give the player an extra life
bc1e: a9 40                        lda     #Sfx_ExtraLife
bc20: 85 fe                        sta     Square2SoundQueue       ;play 1-up sound
bc22: a9 02        CoinPoints      lda     #$02                    ;set digit modifier to award
bc24: 8d 38 01                     sta     DigitModifier+4         ;200 points to the player
bc27: ae 53 07     AddToScore      ldx     CurrentPlayer           ;get current player
bc2a: bc fa bb                     ldy     ScoreOffsets,x          ;get offset for player's score
bc2d: 20 5f 8f                     jsr     DigitsMathRoutine       ;update the score internally with value in digit modifier
bc30: ac 53 07     GetSBNybbles    ldy     CurrentPlayer           ;get current player
bc33: b9 fc bb                     lda     StatusBarNybbles,y      ;get nybbles based on player, use to update score and coins
bc36: 20 06 8f     UpdateNumber    jsr     PrintStatusBarNumbers   ;print status bar numbers based on nybbles, whatever they be
bc39: ac 00 03                     ldy     VRAM_Buffer1_Offset
bc3c: b9 fb 02                     lda     VRAM_Buffer1-6,y        ;check highest digit of score
bc3f: d0 05                        bne     NoZSup                  ;if zero, overwrite with space tile for zero suppression
bc41: a9 24                        lda     #$24
bc43: 99 fb 02                     sta     VRAM_Buffer1-6,y
bc46: a6 08        NoZSup          ldx     ObjectOffset            ;get enemy object buffer offset
bc48: 60                           rts

                   ; -----------------------------------------------------------------------------
bc49: a9 2e        SetupPowerUp    lda     #PowerUpObject          ;load power-up identifier into
bc4b: 85 1b                        sta     Enemy_ID+5              ;special use slot of enemy object buffer
bc4d: b5 76                        lda     Block_PageLoc,x         ;store page location of block object
bc4f: 85 73                        sta     Enemy_PageLoc+5         ;as page location of power-up object
bc51: b5 8f                        lda     Block_X_Position,x      ;store horizontal coordinate of block object
bc53: 85 8c                        sta     Enemy_X_Position+5      ;as horizontal coordinate of power-up object
bc55: a9 01                        lda     #$01
bc57: 85 bb                        sta     Enemy_Y_HighPos+5       ;set vertical high byte of power-up object
bc59: b5 d7                        lda     Block_Y_Position,x      ;get vertical coordinate of block object
bc5b: 38                           sec
bc5c: e9 08                        sbc     #$08                    ;subtract 8 pixels
bc5e: 85 d4                        sta     Enemy_Y_Position+5      ;and use as vertical coordinate of power-up object
bc60: a9 01        PwrUpJmp        lda     #$01                    ;this is a residual jump point in enemy object jump table
bc62: 85 23                        sta     Enemy_State+5           ;set power-up object's state
bc64: 85 14                        sta     Enemy_Flag+5            ;set buffer flag
bc66: a9 03                        lda     #$03
bc68: 8d 9f 04                     sta     Enemy_BoundBoxCtrl+5    ;set bounding box size control for power-up object
bc6b: a5 39                        lda     PowerUpType
bc6d: c9 02                        cmp     #$02                    ;check currently loaded power-up type
bc6f: b0 0a                        bcs     PutBehind               ;if star or 1-up, branch ahead
bc71: ad 56 07                     lda     PlayerStatus            ;otherwise check player's current status
bc74: c9 02                        cmp     #$02
bc76: 90 01                        bcc     StrType                 ;if player not fiery, use status as power-up type
bc78: 4a                           lsr     A                       ;otherwise shift right to force fire flower type
bc79: 85 39        StrType         sta     PowerUpType             ;store type here
bc7b: a9 20        PutBehind       lda     #%00100000
bc7d: 8d ca 03                     sta     Enemy_SprAttrib+5       ;set background priority bit
bc80: a9 02                        lda     #Sfx_GrowPowerUp
bc82: 85 fe                        sta     Square2SoundQueue       ;load power-up reveal sound and leave
bc84: 60                           rts

                   ; -----------------------------------------------------------------------------
                   PowerUpObjHandler
bc85: a2 05                        ldx     #$05                    ;set object offset for last slot in enemy object buffer
bc87: 86 08                        stx     ObjectOffset
bc89: a5 23                        lda     Enemy_State+5           ;check power-up object's state
bc8b: f0 5d                        beq     ExitPUp                 ;if not set, branch to leave
bc8d: 0a                           asl     A                       ;shift to check if d7 was set in object state
bc8e: 90 23                        bcc     GrowThePowerUp          ;if not set, branch ahead to skip this part
bc90: ad 47 07                     lda     TimerControl            ;if master timer control set,
bc93: d0 43                        bne     RunPUSubs               ;branch ahead to enemy object routines
bc95: a5 39                        lda     PowerUpType             ;check power-up type
bc97: f0 11                        beq     ShroomM                 ;if normal mushroom, branch ahead to move it
bc99: c9 03                        cmp     #$03
bc9b: f0 0d                        beq     ShroomM                 ;if 1-up mushroom, branch ahead to move it
bc9d: c9 02                        cmp     #$02
bc9f: d0 37                        bne     RunPUSubs               ;if not star, branch elsewhere to skip movement
bca1: 20 f9 ca                     jsr     MoveJumpingEnemy        ;otherwise impose gravity on star power-up and make it jump
bca4: 20 63 e1                     jsr     EnemyJump               ;note that green paratroopa shares the same code here 
bca7: 4c d8 bc                     jmp     RunPUSubs               ;then jump to other power-up subroutines

bcaa: 20 77 ca     ShroomM         jsr     MoveNormalEnemy         ;do sub to make mushrooms move
bcad: 20 c1 df                     jsr     EnemyToBGCollisionDet   ;deal with collisions
bcb0: 4c d8 bc                     jmp     RunPUSubs               ;run the other subroutines

bcb3: a5 09        GrowThePowerUp  lda     FrameCounter            ;get frame counter
bcb5: 29 03                        and     #$03                    ;mask out all but 2 LSB
bcb7: d0 19                        bne     ChkPUSte                ;if any bits set here, branch
bcb9: c6 d4                        dec     Enemy_Y_Position+5      ;otherwise decrement vertical coordinate slowly
bcbb: a5 23                        lda     Enemy_State+5           ;load power-up object state
bcbd: e6 23                        inc     Enemy_State+5           ;increment state for next frame (to make power-up rise)
bcbf: c9 11                        cmp     #$11                    ;if power-up object state not yet past 16th pixel,
bcc1: 90 0f                        bcc     ChkPUSte                ;branch ahead to last part here
bcc3: a9 10                        lda     #$10
bcc5: 95 58                        sta     Enemy_X_Speed,x         ;otherwise set horizontal speed
bcc7: a9 80                        lda     #%10000000
bcc9: 85 23                        sta     Enemy_State+5           ;and then set d7 in power-up object's state
bccb: 0a                           asl     A                       ;shift once to init A
bccc: 8d ca 03                     sta     Enemy_SprAttrib+5       ;initialize background priority bit set here
bccf: 2a                           rol     A                       ;rotate A to set right moving direction
bcd0: 95 46                        sta     Enemy_MovingDir,x       ;set moving direction
bcd2: a5 23        ChkPUSte        lda     Enemy_State+5           ;check power-up object's state
bcd4: c9 06                        cmp     #$06                    ;for if power-up has risen enough
bcd6: 90 12                        bcc     ExitPUp                 ;if not, don't even bother running these routines
bcd8: 20 52 f1     RunPUSubs       jsr     RelativeEnemyPosition   ;get coordinates relative to screen
bcdb: 20 af f1                     jsr     GetEnemyOffscreenBits   ;get offscreen bits
bcde: 20 43 e2                     jsr     GetEnemyBoundBox        ;get bounding box coordinates
bce1: 20 d2 e6                     jsr     DrawPowerUp             ;draw the power-up object
bce4: 20 53 d8                     jsr     PlayerEnemyCollision    ;check for collision with player
bce7: 20 7a d6                     jsr     OffscreenBoundsCheck    ;check to see if it went offscreen
bcea: 60           ExitPUp         rts                             ;and we're done

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store metatile from block buffer routine
                   ; $02 - used to store vertical high nybble offset from block buffer routine
                   ; $05 - used to store metatile stored in A at beginning of PlayerHeadCollision
                   ; $06-$07 - used as block buffer address indirect
                   BlockYPosAdderData
bceb: 04 12                        .bulk   $04,$12

                   PlayerHeadCollision
bced: 48                           pha                             ;store metatile number to stack
bcee: a9 11                        lda     #$11                    ;load unbreakable block object state by default
bcf0: ae ee 03                     ldx     SprDataOffset_Ctrl      ;load offset control bit here
bcf3: ac 54 07                     ldy     PlayerSize              ;check player's size
bcf6: d0 02                        bne     DBlockSte               ;if small, branch
bcf8: a9 12                        lda     #$12                    ;otherwise load breakable block object state
bcfa: 95 26        DBlockSte       sta     Block_State,x           ;store into block object buffer
bcfc: 20 6b 8a                     jsr     DestroyBlockMetatile    ;store blank metatile in vram buffer to write to name table
bcff: ae ee 03                     ldx     SprDataOffset_Ctrl      ;load offset control bit
bd02: a5 02                        lda     $02                     ;get vertical high nybble offset used in block buffer routine
bd04: 9d e4 03                     sta     Block_Orig_YPos,x       ;set as vertical coordinate for block object
bd07: a8                           tay
bd08: a5 06                        lda     $06                     ;get low byte of block buffer address used in same routine
bd0a: 9d e6 03                     sta     Block_BBuf_Low,x        ;save as offset here to be used later
bd0d: b1 06                        lda     ($06),y                 ;get contents of block buffer at old address at $06, $07
bd0f: 20 f6 bd                     jsr     BlockBumpedChk          ;do a sub to check which block player bumped head on
bd12: 85 00                        sta     $00                     ;store metatile here
bd14: ac 54 07                     ldy     PlayerSize              ;check player's size
bd17: d0 01                        bne     ChkBrick                ;if small, use metatile itself as contents of A
bd19: 98                           tya                             ;otherwise init A (note: big = 0)
bd1a: 90 25        ChkBrick        bcc     PutMTileB               ;if no match was found in previous sub, skip ahead
bd1c: a0 11                        ldy     #$11                    ;otherwise load unbreakable state into block object buffer
bd1e: 94 26                        sty     Block_State,x           ;note this applies to both player sizes
bd20: a9 c4                        lda     #$c4                    ;load empty block metatile into A for now
bd22: a4 00                        ldy     $00                     ;get metatile from before
bd24: c0 58                        cpy     #$58                    ;is it brick with coins (with line)?
bd26: f0 04                        beq     StartBTmr               ;if so, branch
bd28: c0 5d                        cpy     #$5d                    ;is it brick with coins (without line)?
bd2a: d0 15                        bne     PutMTileB               ;if not, branch ahead to store empty block metatile
bd2c: ad bc 06     StartBTmr       lda     BrickCoinTimerFlag      ;check brick coin timer flag
bd2f: d0 08                        bne     ContBTmr                ;if set, timer expired or counting down, thus branch
bd31: a9 0b                        lda     #$0b
bd33: 8d 9d 07                     sta     BrickCoinTimer          ;if not set, set brick coin timer
bd36: ee bc 06                     inc     BrickCoinTimerFlag      ;and set flag linked to it
bd39: ad 9d 07     ContBTmr        lda     BrickCoinTimer          ;check brick coin timer
bd3c: d0 02                        bne     PutOldMT                ;if not yet expired, branch to use current metatile
bd3e: a0 c4                        ldy     #$c4                    ;otherwise use empty block metatile
bd40: 98           PutOldMT        tya                             ;put metatile into A
bd41: 9d e8 03     PutMTileB       sta     Block_Metatile,x        ;store whatever metatile be appropriate here
bd44: 20 84 bd                     jsr     InitBlock_XY_Pos        ;get block object horizontal coordinates saved
bd47: a4 02                        ldy     $02                     ;get vertical high nybble offset
bd49: a9 23                        lda     #$23
bd4b: 91 06                        sta     ($06),y                 ;write blank metatile $23 to block buffer
bd4d: a9 10                        lda     #$10
bd4f: 8d 84 07                     sta     BlockBounceTimer        ;set block bounce timer
bd52: 68                           pla                             ;pull original metatile from stack
bd53: 85 05                        sta     $05                     ;and save here
bd55: a0 00                        ldy     #$00                    ;set default offset
bd57: ad 14 07                     lda     CrouchingFlag           ;is player crouching?
bd5a: d0 05                        bne     SmallBP                 ;if so, branch to increment offset
bd5c: ad 54 07                     lda     PlayerSize              ;is player big?
bd5f: f0 01                        beq     BigBP                   ;if so, branch to use default offset
bd61: c8           SmallBP         iny                             ;increment for small or big and crouching
bd62: a5 ce        BigBP           lda     Player_Y_Position       ;get player's vertical coordinate
bd64: 18                           clc
bd65: 79 eb bc                     adc     BlockYPosAdderData,y    ;add value determined by size
bd68: 29 f0                        and     #$f0                    ;mask out low nybble to get 16-pixel correspondence
bd6a: 95 d7                        sta     Block_Y_Position,x      ;save as vertical coordinate for block object
bd6c: b4 26                        ldy     Block_State,x           ;get block object state
bd6e: c0 11                        cpy     #$11
bd70: f0 06                        beq     Unbreak                 ;if set to value loaded for unbreakable, branch
bd72: 20 02 be                     jsr     BrickShatter            ;execute code for breakable brick
bd75: 4c 7b bd                     jmp     InvOBit                 ;skip subroutine to do last part of code here

bd78: 20 9b bd     Unbreak         jsr     BumpBlock               ;execute code for unbreakable brick or question block
bd7b: ad ee 03     InvOBit         lda     SprDataOffset_Ctrl      ;invert control bit used by block objects
bd7e: 49 01                        eor     #$01                    ; and floatey numbers
bd80: 8d ee 03                     sta     SprDataOffset_Ctrl
bd83: 60                           rts                             ;leave!

                   ; -----------------------------------------------------------------------------
                   InitBlock_XY_Pos
bd84: a5 86                        lda     Player_X_Position       ;get player's horizontal coordinate
bd86: 18                           clc
bd87: 69 08                        adc     #$08                    ;add eight pixels
bd89: 29 f0                        and     #$f0                    ;mask out low nybble to give 16-pixel correspondence
bd8b: 95 8f                        sta     Block_X_Position,x      ;save as horizontal coordinate for block object
bd8d: a5 6d                        lda     Player_PageLoc
bd8f: 69 00                        adc     #$00                    ;add carry to page location of player
bd91: 95 76                        sta     Block_PageLoc,x         ;save as page location of block object
bd93: 9d ea 03                     sta     Block_PageLoc2,x        ;save elsewhere to be used later
bd96: a5 b5                        lda     Player_Y_HighPos
bd98: 95 be                        sta     Block_Y_HighPos,x       ;save vertical high byte of player into
bd9a: 60                           rts                             ;vertical high byte of block object and leave

                   ; -----------------------------------------------------------------------------
bd9b: 20 1f be     BumpBlock       jsr     CheckTopOfBlock         ;check to see if there's a coin directly above this block
bd9e: a9 02                        lda     #Sfx_Bump
bda0: 85 ff                        sta     Square1SoundQueue       ;play bump sound
bda2: a9 00                        lda     #$00
bda4: 95 60                        sta     Block_X_Speed,x         ;initialize horizontal speed for block object
bda6: 9d 3c 04                     sta     Block_Y_MoveForce,x     ;init fractional movement force
bda9: 85 9f                        sta     Player_Y_Speed          ;init player's vertical speed
bdab: a9 fe                        lda     #$fe
bdad: 95 a8                        sta     Block_Y_Speed,x         ;set vertical speed for block object
bdaf: a5 05                        lda     $05                     ;get original metatile from stack
bdb1: 20 f6 bd                     jsr     BlockBumpedChk          ;do a sub to check which block player bumped head on
bdb4: 90 31                        bcc     ExitBlockChk            ;if no match was found, branch to leave
bdb6: 98                           tya                             ;move block number to A
bdb7: c9 09                        cmp     #$09                    ;if block number was within 0-8 range,
bdb9: 90 02                        bcc     BlockCode               ;branch to use current number
bdbb: e9 05                        sbc     #$05                    ;otherwise subtract 5 for second set to get proper number
bdbd: 20 04 8e     BlockCode       jsr     JumpEngine              ;run appropriate subroutine depending on block number

bdc0: d2 bd                        .dd2    MushFlowerBlock
bdc2: 38 bb                        .dd2    CoinBlock
bdc4: 38 bb                        .dd2    CoinBlock
bdc6: d8 bd                        .dd2    ExtraLifeMushBlock
bdc8: d2 bd                        .dd2    MushFlowerBlock
bdca: df bd                        .dd2    VineBlock
bdcc: d5 bd                        .dd2    StarBlock
bdce: 38 bb                        .dd2    CoinBlock
bdd0: d8 bd                        .dd2    ExtraLifeMushBlock

                   ; -----------------------------------------------------------------------------
bdd2: a9 00        MushFlowerBlock lda     #$00                    ;load mushroom/fire flower into power-up type
bdd4: 2c                           bit ▼   $02a9                   ;BIT instruction opcode
bdd5: a9 02        StarBlock       lda     #$02                    ;load star into power-up type
bdd7: 2c                           bit ▼   $03a9                   ;BIT instruction opcode
                   ExtraLifeMushBlock
bdd8: a9 03                        lda     #$03                    ;load 1-up mushroom into power-up type
bdda: 85 39                        sta     PowerUpType             ;store correct power-up type
bddc: 4c 49 bc                     jmp     SetupPowerUp

bddf: a2 05        VineBlock       ldx     #$05                    ;load last slot for enemy object buffer
bde1: ac ee 03                     ldy     SprDataOffset_Ctrl      ;get control bit
bde4: 20 1e b9                     jsr     Setup_Vine              ;set up vine object
bde7: 60           ExitBlockChk    rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   BrickQBlockMetatiles
bde8: c1 c0 5f 60                  .bulk   $c1,$c0,$5f,$60         ;used by question blocks
                   ; these two sets are functionally identical, but look different
bdec: 55 56 57 58+                 .bulk   $55,$56,$57,$58,$59     ;used by ground level types
bdf1: 5a 5b 5c 5d+                 .bulk   $5a,$5b,$5c,$5d,$5e     ;used by other level types

bdf6: a0 0d        BlockBumpedChk  ldy     #$0d                    ;start at end of metatile data
bdf8: d9 e8 bd     BumpChkLoop     cmp     BrickQBlockMetatiles,y  ;check to see if current metatile matches
bdfb: f0 04                        beq     MatchBump               ;metatile found in block buffer, branch if so
bdfd: 88                           dey                             ;otherwise move onto next metatile
bdfe: 10 f8                        bpl     BumpChkLoop             ;do this until all metatiles are checked
be00: 18                           clc                             ;if none match, return with carry clear
be01: 60           MatchBump       rts                             ;note carry is set if found match

                   ; -----------------------------------------------------------------------------
be02: 20 1f be     BrickShatter    jsr     CheckTopOfBlock         ;check to see if there's a coin directly above this block
be05: a9 01                        lda     #Sfx_BrickShatter
be07: 9d ec 03                     sta     Block_RepFlag,x         ;set flag for block object to immediately replace metatile
be0a: 85 fd                        sta     NoiseSoundQueue         ;load brick shatter sound
be0c: 20 41 be                     jsr     SpawnBrickChunks        ;create brick chunk objects
be0f: a9 fe                        lda     #$fe
be11: 85 9f                        sta     Player_Y_Speed          ;set vertical speed for player
be13: a9 05                        lda     #$05
be15: 8d 39 01                     sta     DigitModifier+5         ;set digit modifier to give player 50 points
be18: 20 27 bc                     jsr     AddToScore              ;do sub to update the score
be1b: ae ee 03                     ldx     SprDataOffset_Ctrl      ;load control bit and leave
be1e: 60                           rts

                   ; -----------------------------------------------------------------------------
be1f: ae ee 03     CheckTopOfBlock ldx     SprDataOffset_Ctrl      ;load control bit
be22: a4 02                        ldy     $02                     ;get vertical high nybble offset used in block buffer
be24: f0 1a                        beq     TopEx                   ;branch to leave if set to zero, because we're at the top
be26: 98                           tya                             ;otherwise set to A
be27: 38                           sec
be28: e9 10                        sbc     #$10                    ;subtract $10 to move up one row in the block buffer
be2a: 85 02                        sta     $02                     ;store as new vertical high nybble offset
be2c: a8                           tay
be2d: b1 06                        lda     ($06),y                 ;get contents of block buffer in same column, one row up
be2f: c9 c2                        cmp     #$c2                    ;is it a coin? (not underwater)
be31: d0 0d                        bne     TopEx                   ;if not, branch to leave
be33: a9 00                        lda     #$00
be35: 91 06                        sta     ($06),y                 ;otherwise put blank metatile where coin was
be37: 20 4d 8a                     jsr     RemoveCoin_Axe          ;write blank metatile to vram buffer
be3a: ae ee 03                     ldx     SprDataOffset_Ctrl      ;get control bit
be3d: 20 51 bb                     jsr     SetupJumpCoin           ;create jumping coin object and update coin variables
be40: 60           TopEx           rts                             ;leave!

                   ; -----------------------------------------------------------------------------
                   SpawnBrickChunks
be41: b5 8f                        lda     Block_X_Position,x      ;set horizontal coordinate of block object
be43: 9d f1 03                     sta     Block_Orig_XPos,x       ; as original horizontal coordinate here
be46: a9 f0                        lda     #$f0
be48: 95 60                        sta     Block_X_Speed,x         ;set horizontal speed for brick chunk objects
be4a: 95 62                        sta     Block_X_Speed+2,x
be4c: a9 fa                        lda     #$fa
be4e: 95 a8                        sta     Block_Y_Speed,x         ;set vertical speed for one
be50: a9 fc                        lda     #$fc
be52: 95 aa                        sta     Block_Y_Speed+2,x       ;set lower vertical speed for the other
be54: a9 00                        lda     #$00
be56: 9d 3c 04                     sta     Block_Y_MoveForce,x     ;init fractional movement force for both
be59: 9d 3e 04                     sta     Block_Y_MoveForce+2,x
be5c: b5 76                        lda     Block_PageLoc,x
be5e: 95 78                        sta     Block_PageLoc+2,x       ;copy page location
be60: b5 8f                        lda     Block_X_Position,x
be62: 95 91                        sta     Block_X_Position+2,x    ;copy horizontal coordinate
be64: b5 d7                        lda     Block_Y_Position,x
be66: 18                           clc                             ;add 8 pixels to vertical coordinate
be67: 69 08                        adc     #$08                    ;and save as vertical coordinate for one of them
be69: 95 d9                        sta     Block_Y_Position+2,x
be6b: a9 fa                        lda     #$fa
be6d: 95 a8                        sta     Block_Y_Speed,x         ;set vertical speed...again??? (redundant)
be6f: 60                           rts

                   ; -----------------------------------------------------------------------------
                   BlockObjectsCore
be70: b5 26                        lda     Block_State,x           ;get state of block object
be72: f0 5d                        beq     UpdSte                  ;if not set, branch to leave
be74: 29 0f                        and     #$0f                    ;mask out high nybble
be76: 48                           pha                             ;push to stack
be77: a8                           tay                             ;put in Y for now
be78: 8a                           txa
be79: 18                           clc
be7a: 69 09                        adc     #$09                    ;add 9 bytes to offset (note two block objects are created
be7c: aa                           tax                             ;when using brick chunks, but only one offset for both)
be7d: 88                           dey                             ;decrement Y to check for solid block state
be7e: f0 33                        beq     BouncingBlockHandler    ;branch if found, otherwise continue for brick chunks
be80: 20 a4 bf                     jsr     ImposeGravityBlock      ;do sub to impose gravity on one block object object
be83: 20 0f bf                     jsr     MoveObjectHorizontally  ;do another sub to move horizontally
be86: 8a                           txa
be87: 18                           clc                             ;move onto next block object
be88: 69 02                        adc     #$02
be8a: aa                           tax
be8b: 20 a4 bf                     jsr     ImposeGravityBlock      ;do sub to impose gravity on other block object
be8e: 20 0f bf                     jsr     MoveObjectHorizontally  ;do another sub to move horizontally
be91: a6 08                        ldx     ObjectOffset            ;get block object offset used for both
be93: 20 59 f1                     jsr     RelativeBlockPosition   ;get relative coordinates
be96: 20 b6 f1                     jsr     GetBlockOffscreenBits   ;get offscreen information
be99: 20 53 ec                     jsr     DrawBrickChunks         ;draw the brick chunks
be9c: 68                           pla                             ;get lower nybble of saved state
be9d: b4 be                        ldy     Block_Y_HighPos,x       ;check vertical high byte of block object
be9f: f0 30                        beq     UpdSte                  ;if above the screen, branch to kill it
bea1: 48                           pha                             ;otherwise save state back into stack
bea2: a9 f0                        lda     #$f0
bea4: d5 d9                        cmp     Block_Y_Position+2,x    ;check to see if bottom block object went
bea6: b0 02                        bcs     ChkTop                  ; to the bottom of the screen, and branch if not
bea8: 95 d9                        sta     Block_Y_Position+2,x    ;otherwise set offscreen coordinate
beaa: b5 d7        ChkTop          lda     Block_Y_Position,x      ;get top block object's vertical coordinate
beac: c9 f0                        cmp     #$f0                    ;see if it went to the bottom of the screen
beae: 68                           pla                             ;pull block object state from stack
beaf: 90 20                        bcc     UpdSte                  ;if not, branch to save state
beb1: b0 1c                        bcs     KillBlock               ;otherwise do unconditional branch to kill it

                   BouncingBlockHandler
beb3: 20 a4 bf                     jsr     ImposeGravityBlock      ;do sub to impose gravity on block object
beb6: a6 08                        ldx     ObjectOffset            ;get block object offset
beb8: 20 59 f1                     jsr     RelativeBlockPosition   ;get relative coordinates
bebb: 20 b6 f1                     jsr     GetBlockOffscreenBits   ;get offscreen information
bebe: 20 d1 eb                     jsr     DrawBlock               ;draw the block
bec1: b5 d7                        lda     Block_Y_Position,x      ;get vertical coordinate
bec3: 29 0f                        and     #$0f                    ;mask out high nybble
bec5: c9 05                        cmp     #$05                    ;check to see if low nybble wrapped around
bec7: 68                           pla                             ;pull state from stack
bec8: b0 07                        bcs     UpdSte                  ;if still above amount, not time to kill block yet, thus branch
beca: a9 01                        lda     #$01
becc: 9d ec 03                     sta     Block_RepFlag,x         ;otherwise set flag to replace metatile
becf: a9 00        KillBlock       lda     #$00                    ;if branched here, nullify object state
bed1: 95 26        UpdSte          sta     Block_State,x           ;store contents of A in block object state
bed3: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $02 - used to store offset to block buffer
                   ; $06-$07 - used to store block buffer address
                   BlockObjMT_Updater
bed4: a2 01                        ldx     #$01                    ;set offset to start with second block object
bed6: 86 08        UpdateLoop      stx     ObjectOffset            ;set offset here
bed8: ad 01 03                     lda     VRAM_Buffer1            ;if vram buffer already being used here,
bedb: d0 21                        bne     NextBUpd                ;branch to move onto next block object
bedd: bd ec 03                     lda     Block_RepFlag,x         ;if flag for block object already clear,
bee0: f0 1c                        beq     NextBUpd                ;branch to move onto next block object
bee2: bd e6 03                     lda     Block_BBuf_Low,x        ;get low byte of block buffer
bee5: 85 06                        sta     $06                     ;store into block buffer address
bee7: a9 05                        lda     #$05
bee9: 85 07                        sta     $07                     ;set high byte of block buffer address
beeb: bd e4 03                     lda     Block_Orig_YPos,x       ;get original vertical coordinate of block object
beee: 85 02                        sta     $02                     ;store here and use as offset to block buffer
bef0: a8                           tay
bef1: bd e8 03                     lda     Block_Metatile,x        ;get metatile to be written
bef4: 91 06                        sta     ($06),y                 ;write it to the block buffer
bef6: 20 61 8a                     jsr     ReplaceBlockMetatile    ;do sub to replace metatile where block object is
bef9: a9 00                        lda     #$00
befb: 9d ec 03                     sta     Block_RepFlag,x         ;clear block object flag
befe: ca           NextBUpd        dex                             ;decrement block object offset
beff: 10 d5                        bpl     UpdateLoop              ;do this until both block objects are dealt with
bf01: 60                           rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store high nybble of horizontal speed as adder
                   ; $01 - used to store low nybble of horizontal speed
                   ; $02 - used to store adder to page location
                   MoveEnemyHorizontally
bf02: e8                           inx                             ;increment offset for enemy offset
bf03: 20 0f bf                     jsr     MoveObjectHorizontally  ;position object horizontally according to
bf06: a6 08                        ldx     ObjectOffset            ; counters, return with saved value in A,
bf08: 60                           rts                             ; put enemy offset back in X and leave

                   MovePlayerHorizontally
bf09: ad 0e 07                     lda     JumpspringAnimCtrl      ;if jumpspring currently animating,
bf0c: d0 3e                        bne     ExXMove                 ;branch to leave
bf0e: aa                           tax                             ;otherwise set zero for offset to use player's stuff
                   MoveObjectHorizontally
bf0f: b5 57                        lda     SprObject_X_Speed,x     ;get currently saved value (horizontal
bf11: 0a                           asl     A                       ; speed, secondary counter, whatever)
bf12: 0a                           asl     A                       ; and move low nybble to high
bf13: 0a                           asl     A
bf14: 0a                           asl     A
bf15: 85 01                        sta     $01                     ;store result here
bf17: b5 57                        lda     SprObject_X_Speed,x     ;get saved value again
bf19: 4a                           lsr     A                       ;move high nybble to low
bf1a: 4a                           lsr     A
bf1b: 4a                           lsr     A
bf1c: 4a                           lsr     A
bf1d: c9 08                        cmp     #$08                    ;if < 8, branch, do not change
bf1f: 90 02                        bcc     SaveXSpd
bf21: 09 f0                        ora     #%11110000              ;otherwise alter high nybble
bf23: 85 00        SaveXSpd        sta     $00                     ;save result here
bf25: a0 00                        ldy     #$00                    ;load default Y value here
bf27: c9 00                        cmp     #$00                    ;if result positive, leave Y alone
bf29: 10 01                        bpl     UseAdder
bf2b: 88                           dey                             ;otherwise decrement Y
bf2c: 84 02        UseAdder        sty     $02                     ;save Y here
bf2e: bd 00 04                     lda     SprObject_X_MoveForce,x ;get whatever number's here
bf31: 18                           clc
bf32: 65 01                        adc     $01                     ;add low nybble moved to high
bf34: 9d 00 04                     sta     SprObject_X_MoveForce,x ;store result here
bf37: a9 00                        lda     #$00                    ;init A
bf39: 2a                           rol     A                       ;rotate carry into d0
bf3a: 48                           pha                             ;push onto stack
bf3b: 6a                           ror     A                       ;rotate d0 back onto carry
bf3c: b5 86                        lda     Player_X_Position,x
bf3e: 65 00                        adc     $00                     ;add carry plus saved value (high nybble moved to low
bf40: 95 86                        sta     Player_X_Position,x     ; plus $f0 if necessary) to object's horizontal position
bf42: b5 6d                        lda     Player_PageLoc,x
bf44: 65 02                        adc     $02                     ;add carry plus other saved value to the
bf46: 95 6d                        sta     Player_PageLoc,x        ; object's page location and save
bf48: 68                           pla
bf49: 18                           clc                             ;pull old carry from stack and add
bf4a: 65 00                        adc     $00                     ; to high nybble moved to low
bf4c: 60           ExXMove         rts                             ;and leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used for downward force
                   ; $01 - used for upward force
                   ; $02 - used for maximum vertical speed
                   MovePlayerVertically
bf4d: a2 00                        ldx     #$00                    ;set X for player offset
bf4f: ad 47 07                     lda     TimerControl
bf52: d0 05                        bne     NoJSChk                 ;if master timer control set, branch ahead
bf54: ad 0e 07                     lda     JumpspringAnimCtrl      ;otherwise check to see if jumpspring is animating
bf57: d0 f3                        bne     ExXMove                 ;branch to leave if so
bf59: ad 09 07     NoJSChk         lda     VerticalForce           ;dump vertical force
bf5c: 85 00                        sta     $00
bf5e: a9 04                        lda     #$04                    ;set maximum vertical speed here
bf60: 4c ad bf                     jmp     ImposeGravitySprObj     ;then jump to move player vertically

                   ; -----------------------------------------------------------------------------
                   MoveD_EnemyVertically
bf63: a0 3d                        ldy     #$3d                    ;set quick movement amount downwards
bf65: b5 1e                        lda     Enemy_State,x           ;then check enemy state
bf67: c9 05                        cmp     #$05                    ;if not set to unique state for spiny's egg, go ahead
bf69: d0 02                        bne     ContVMove               ;and use, otherwise set different movement amount, continue on
                   MoveFallingPlatform
bf6b: a0 20                        ldy     #$20                    ;set movement amount
bf6d: 4c 94 bf     ContVMove       jmp     SetHiMax                ;jump to skip the rest of this

                   ; -----------------------------------------------------------------------------
                   MoveRedPTroopaDown
bf70: a0 00                        ldy     #$00                    ;set Y to move downwards
bf72: 4c 77 bf                     jmp     MoveRedPTroopa          ;skip to movement routine

                   MoveRedPTroopaUp
bf75: a0 01                        ldy     #$01                    ;set Y to move upwards
bf77: e8           MoveRedPTroopa  inx                             ;increment X for enemy offset
bf78: a9 03                        lda     #$03
bf7a: 85 00                        sta     $00                     ;set downward movement amount here
bf7c: a9 06                        lda     #$06
bf7e: 85 01                        sta     $01                     ;set upward movement amount here
bf80: a9 02                        lda     #$02
bf82: 85 02                        sta     $02                     ;set maximum speed here
bf84: 98                           tya                             ;set movement direction in A, and
bf85: 4c d1 bf                     jmp     RedPTroopaGrav          ; jump to move this thing

                   ; -----------------------------------------------------------------------------
                   MoveDropPlatform
bf88: a0 7f                        ldy     #$7f                    ;set movement amount for drop platform
bf8a: d0 02                        bne     SetMdMax                ;skip ahead of other value set here

                   MoveEnemySlowVert
bf8c: a0 0f                        ldy     #$0f                    ;set movement amount for bowser/other objects
bf8e: a9 02        SetMdMax        lda     #$02                    ;set maximum speed in A
bf90: d0 04                        bne     SetXMoveAmt             ;unconditional branch

                   ; -----------------------------------------------------------------------------
                   MoveJ_EnemyVertically
bf92: a0 1c                        ldy     #$1c                    ;set movement amount for podoboo/other objects
bf94: a9 03        SetHiMax        lda     #$03                    ;set maximum speed in A
bf96: 84 00        SetXMoveAmt     sty     $00                     ;set movement amount here
bf98: e8                           inx                             ;increment X for enemy offset
bf99: 20 ad bf                     jsr     ImposeGravitySprObj     ;do a sub to move enemy object downwards
bf9c: a6 08                        ldx     ObjectOffset            ;get enemy object buffer offset and leave
bf9e: 60                           rts

                   ; -----------------------------------------------------------------------------
bf9f: 06 08        MaxSpdBlockData .bulk   $06,$08

bfa1: a0 00        unref_bfa1      ldy     #$00                    ;this part appears to be residual,
bfa3: 2c                           bit ▼   $01a0                   ;no code branches or jumps to it...
                   ImposeGravityBlock
bfa4: a0 01                        ldy     #$01                    ;set offset for maximum speed
bfa6: a9 50                        lda     #$50                    ;set movement amount here
bfa8: 85 00                        sta     $00
bfaa: b9 9f bf                     lda     MaxSpdBlockData,y       ;get maximum speed
                   ImposeGravitySprObj
bfad: 85 02                        sta     $02                     ;set maximum speed here
bfaf: a9 00                        lda     #$00                    ;set value to move downwards
bfb1: 4c d7 bf                     jmp     ImposeGravity           ;jump to the code that actually moves it

                   ; -----------------------------------------------------------------------------
                   MovePlatformDown
bfb4: a9 00                        lda     #$00                    ;save value to stack (if branching here, execute next
bfb6: 2c                           bit ▼   $01a9                   ; part as BIT instruction)
bfb7: a9 01        MovePlatformUp  lda     #$01                    ;save value to stack
bfb9: 48                           pha
bfba: b4 16                        ldy     Enemy_ID,x              ;get enemy object identifier
bfbc: e8                           inx                             ;increment offset for enemy object
bfbd: a9 05                        lda     #$05                    ;load default value here
bfbf: c0 29                        cpy     #$29                    ;residual comparison, object #29 never executes
bfc1: d0 02                        bne     SetDblSpd               ; this code, thus unconditional branch here
bfc3: a9 09                        lda     #$09                    ;residual code
bfc5: 85 00        SetDblSpd       sta     $00                     ;save downward movement amount here
bfc7: a9 0a                        lda     #$0a                    ;save upward movement amount here
bfc9: 85 01                        sta     $01
bfcb: a9 03                        lda     #$03                    ;save maximum vertical speed here
bfcd: 85 02                        sta     $02
bfcf: 68                           pla                             ;get value from stack
bfd0: a8                           tay                             ;use as Y, then move onto code shared by red koopa
bfd1: 20 d7 bf     RedPTroopaGrav  jsr     ImposeGravity           ;do a sub to move object gradually
bfd4: a6 08                        ldx     ObjectOffset            ;get enemy object offset and leave
bfd6: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used for downward force
                   ; $01 - used for upward force
                   ; $07 - used as adder for vertical position
bfd7: 48           ImposeGravity   pha                             ;push value to stack
bfd8: bd 16 04                     lda     SprObject_YMF_Dummy,x
bfdb: 18                           clc                             ;add value in movement force to contents of dummy variable
bfdc: 7d 33 04                     adc     SprObject_Y_MoveForce,x
bfdf: 9d 16 04                     sta     SprObject_YMF_Dummy,x
bfe2: a0 00                        ldy     #$00                    ;set Y to zero by default
bfe4: b5 9f                        lda     SprObject_Y_Speed,x     ;get current vertical speed
bfe6: 10 01                        bpl     AlterYP                 ;if currently moving downwards, do not decrement Y
bfe8: 88                           dey                             ;otherwise decrement Y
bfe9: 84 07        AlterYP         sty     $07                     ;store Y here
bfeb: 75 ce                        adc     SprObject_Y_Position,x  ;add vertical position to vertical speed plus carry
bfed: 95 ce                        sta     SprObject_Y_Position,x  ;store as new vertical position
bfef: b5 b5                        lda     SprObject_Y_HighPos,x
bff1: 65 07                        adc     $07                     ;add carry plus contents of $07 to vertical high byte
bff3: 95 b5                        sta     SprObject_Y_HighPos,x   ;store as new vertical high byte
bff5: bd 33 04                     lda     SprObject_Y_MoveForce,x
bff8: 18                           clc
bff9: 65 00                        adc     $00                     ;add downward movement amount to contents of $0433
bffb: 9d 33 04                     sta     SprObject_Y_MoveForce,x
bffe: b5 9f                        lda     SprObject_Y_Speed,x     ;add carry to vertical speed and store
c000: 69 00                        adc     #$00
c002: 95 9f                        sta     SprObject_Y_Speed,x
c004: c5 02                        cmp     $02                     ;compare to maximum speed
c006: 30 10                        bmi     ChkUpM                  ;if less than preset value, skip this part
c008: bd 33 04                     lda     SprObject_Y_MoveForce,x
c00b: c9 80                        cmp     #$80                    ;if less positively than preset maximum, skip this part
c00d: 90 09                        bcc     ChkUpM
c00f: a5 02                        lda     $02
c011: 95 9f                        sta     SprObject_Y_Speed,x     ;keep vertical speed within maximum value
c013: a9 00                        lda     #$00
c015: 9d 33 04                     sta     SprObject_Y_MoveForce,x ;clear fractional
c018: 68           ChkUpM          pla                             ;get value from stack
c019: f0 2b                        beq     ExVMove                 ;if set to zero, branch to leave
c01b: a5 02                        lda     $02
c01d: 49 ff                        eor     #%11111111              ;otherwise get two's compliment of maximum speed
c01f: a8                           tay
c020: c8                           iny
c021: 84 07                        sty     $07                     ;store two's compliment here
c023: bd 33 04                     lda     SprObject_Y_MoveForce,x
c026: 38                           sec                             ;subtract upward movement amount from contents
c027: e5 01                        sbc     $01                     ; of movement force, note that $01 is twice as large as $00,
c029: 9d 33 04                     sta     SprObject_Y_MoveForce,x ; thus it effectively undoes add we did earlier
c02c: b5 9f                        lda     SprObject_Y_Speed,x
c02e: e9 00                        sbc     #$00                    ;subtract borrow from vertical speed and store
c030: 95 9f                        sta     SprObject_Y_Speed,x
c032: c5 07                        cmp     $07                     ;compare vertical speed to two's compliment
c034: 10 10                        bpl     ExVMove                 ;if less negatively than preset maximum, skip this part
c036: bd 33 04                     lda     SprObject_Y_MoveForce,x
c039: c9 80                        cmp     #$80                    ;check if fractional part is above certain amount,
c03b: b0 09                        bcs     ExVMove                 ;and if so, branch to leave
c03d: a5 07                        lda     $07
c03f: 95 9f                        sta     SprObject_Y_Speed,x     ;keep vertical speed within maximum value
c041: a9 ff                        lda     #$ff
c043: 9d 33 04                     sta     SprObject_Y_MoveForce,x ;clear fractional
c046: 60           ExVMove         rts                             ;leave!

                   ; -----------------------------------------------------------------------------
                   EnemiesAndLoopsCore
c047: b5 0f                        lda     Enemy_Flag,x            ;check data here for MSB set
c049: 48                           pha                             ;save in stack
c04a: 0a                           asl     A
c04b: b0 12                        bcs     ChkBowserF              ;if MSB set in enemy flag, branch ahead of jumps
c04d: 68                           pla                             ;get from stack
c04e: f0 03                        beq     ChkAreaTsk              ;if data zero, branch
c050: 4c 82 c8                     jmp     RunEnemyObjectsCore     ;otherwise, jump to run enemy subroutines

c053: ad 1f 07     ChkAreaTsk      lda     AreaParserTaskNum       ;check number of tasks to perform
c056: 29 07                        and     #$07
c058: c9 07                        cmp     #$07                    ;if at a specific task, jump and leave
c05a: f0 0e                        beq     ExitELCore
c05c: 4c cc c0                     jmp     ProcLoopCommand         ;otherwise, jump to process loop command/load enemies

c05f: 68           ChkBowserF      pla                             ;get data from stack
c060: 29 0f                        and     #%00001111              ;mask out high nybble
c062: a8                           tay
c063: b9 0f 00                     lda     Enemy_Flag,y            ;use as pointer and load same place with different offset
c066: d0 02                        bne     ExitELCore
c068: 95 0f                        sta     Enemy_Flag,x            ;if second enemy flag not set, also clear first one
c06a: 60           ExitELCore      rts

                   ; -----------------------------------------------------------------------------
                   LoopCmdWorldNumber
c06b: 03 03 06 06+                 .bulk   $03,$03,$06,$06,$06,$06,$06,$06,$07,$07,$07
                   LoopCmdPageNumber
c076: 05 09 04 05+                 .bulk   $05,$09,$04,$05,$06,$08,$09,$0a,$06,$0b,$10
                   LoopCmdYPosition
c081: 40 b0 b0 80+                 .bulk   $40,$b0,$b0,$80,$40,$40,$80,$40,$f0,$f0,$f0

                   ExecGameLoopback
c08c: a5 6d                        lda     Player_PageLoc          ;send player back four pages
c08e: 38                           sec
c08f: e9 04                        sbc     #$04
c091: 85 6d                        sta     Player_PageLoc
c093: ad 25 07                     lda     CurrentPageLoc          ;send current page back four pages
c096: 38                           sec
c097: e9 04                        sbc     #$04
c099: 8d 25 07                     sta     CurrentPageLoc
c09c: ad 1a 07                     lda     ScreenLeft_PageLoc      ;subtract four from page location
c09f: 38                           sec                             ; of screen's left border
c0a0: e9 04                        sbc     #$04
c0a2: 8d 1a 07                     sta     ScreenLeft_PageLoc
c0a5: ad 1b 07                     lda     ScreenRight_PageLoc     ;do the same for the page location
c0a8: 38                           sec                             ; of screen's right border
c0a9: e9 04                        sbc     #$04
c0ab: 8d 1b 07                     sta     ScreenRight_PageLoc
c0ae: ad 2a 07                     lda     AreaObjectPageLoc       ;subtract four from page control
c0b1: 38                           sec                             ; for area objects
c0b2: e9 04                        sbc     #$04
c0b4: 8d 2a 07                     sta     AreaObjectPageLoc
c0b7: a9 00                        lda     #$00                    ;initialize page select for both
c0b9: 8d 3b 07                     sta     EnemyObjectPageSel      ; area and enemy objects
c0bc: 8d 2b 07                     sta     AreaObjectPageSel
c0bf: 8d 39 07                     sta     EnemyDataOffset         ;initialize enemy object data offset
c0c2: 8d 3a 07                     sta     EnemyObjectPageLoc      ;and enemy object page control
c0c5: b9 f8 9b                     lda     AreaDataOfsLoopback,y   ;adjust area object offset based on
c0c8: 8d 2c 07                     sta     AreaDataOffset          ; which loop command we encountered
c0cb: 60                           rts

c0cc: ad 45 07     ProcLoopCommand lda     LoopCommand             ;check if loop command was found
c0cf: f0 5e                        beq     ChkEnemyFrenzy
c0d1: ad 26 07                     lda     CurrentColumnPos        ;check to see if we're still on the first page
c0d4: d0 59                        bne     ChkEnemyFrenzy          ;if not, do not loop yet
c0d6: a0 0b                        ldy     #$0b                    ;start at the end of each set of loop data
c0d8: 88           FindLoop        dey
c0d9: 30 54                        bmi     ChkEnemyFrenzy          ;if all data is checked and not match, do not loop
c0db: ad 5f 07                     lda     WorldNumber             ;check to see if one of the world numbers
c0de: d9 6b c0                     cmp     LoopCmdWorldNumber,y    ; matches our current world number
c0e1: d0 f5                        bne     FindLoop
c0e3: ad 25 07                     lda     CurrentPageLoc          ;check to see if one of the page numbers
c0e6: d9 76 c0                     cmp     LoopCmdPageNumber,y     ; matches the page we're currently on
c0e9: d0 ed                        bne     FindLoop
c0eb: a5 ce                        lda     Player_Y_Position       ;check to see if the player is at the correct position
c0ed: d9 81 c0                     cmp     LoopCmdYPosition,y      ;if not, branch to check for world 7
c0f0: d0 23                        bne     WrongChk
c0f2: a5 1d                        lda     Player_State            ;check to see if the player is
c0f4: c9 00                        cmp     #$00                    ;on solid ground (i.e. not jumping or falling)
c0f6: d0 1d                        bne     WrongChk                ;if not, player fails to pass loop, and loopback
c0f8: ad 5f 07                     lda     WorldNumber             ;are we in world 7? (check performed on correct
c0fb: c9 06                        cmp     #World7                 ; vertical position and on solid ground)
c0fd: d0 23                        bne     InitMLp                 ;if not, initialize flags used there, otherwise
c0ff: ee d9 06                     inc     MultiLoopCorrectCntr    ;increment counter for correct progression
c102: ee da 06     IncMLoop        inc     MultiLoopPassCntr       ;increment master multi-part counter
c105: ad da 06                     lda     MultiLoopPassCntr       ;have we done all three parts?
c108: c9 03                        cmp     #$03
c10a: d0 1e                        bne     InitLCmd                ;if not, skip this part
c10c: ad d9 06                     lda     MultiLoopCorrectCntr    ;if so, have we done them all correctly?
c10f: c9 03                        cmp     #$03
c111: f0 0f                        beq     InitMLp                 ;if so, branch past unnecessary check here
c113: d0 07                        bne     DoLpBack                ;unconditional branch if previous branch fails

c115: ad 5f 07     WrongChk        lda     WorldNumber             ;are we in world 7? (check performed on
c118: c9 06                        cmp     #World7                 ; incorrect vertical position or not on solid ground)
c11a: f0 e6                        beq     IncMLoop
c11c: 20 8c c0     DoLpBack        jsr     ExecGameLoopback        ;if player is not in right place, loop back
c11f: 20 71 d0                     jsr     KillAllEnemies
c122: a9 00        InitMLp         lda     #$00                    ;initialize counters used for multi-part loop commands
c124: 8d da 06                     sta     MultiLoopPassCntr
c127: 8d d9 06                     sta     MultiLoopCorrectCntr
c12a: a9 00        InitLCmd        lda     #$00                    ;initialize loop command flag
c12c: 8d 45 07                     sta     LoopCommand
                   ; 
c12f: ad cd 06     ChkEnemyFrenzy  lda     EnemyFrenzyQueue        ;check for enemy object in frenzy queue
c132: f0 10                        beq     ProcessEnemyData        ;if not, skip this part
c134: 95 16                        sta     Enemy_ID,x              ;store as enemy object identifier here
c136: a9 01                        lda     #$01
c138: 95 0f                        sta     Enemy_Flag,x            ;activate enemy object flag
c13a: a9 00                        lda     #$00
c13c: 95 1e                        sta     Enemy_State,x           ;initialize state and frenzy queue
c13e: 8d cd 06                     sta     EnemyFrenzyQueue
c141: 4c 26 c2                     jmp     InitEnemyObject         ;and then jump to deal with this enemy

                   ; -----------------------------------------------------------------------------
                   ; $06 - used to hold page location of extended right boundary
                   ; $07 - used to hold high nybble of position of extended right boundary
                   ProcessEnemyData
c144: ac 39 07                     ldy     EnemyDataOffset         ;get offset of enemy object data
c147: b1 e9                        lda     (EnemyData),y           ;load first byte
c149: c9 ff                        cmp     #$ff                    ;check for EOD terminator
c14b: d0 03                        bne     ChkEndofBuffer
c14d: 4c 16 c2                     jmp     CheckFrenzyBuffer       ;if found, jump to check frenzy buffer, otherwise

c150: 29 0f        ChkEndofBuffer  and     #%00001111              ;check for special row $0e
c152: c9 0e                        cmp     #$0e
c154: f0 0e                        beq     CheckRightBounds        ;if found, branch, otherwise
c156: e0 05                        cpx     #$05                    ;check for end of buffer
c158: 90 0a                        bcc     CheckRightBounds        ;if not at end of buffer, branch
c15a: c8                           iny
c15b: b1 e9                        lda     (EnemyData),y           ;check for specific value here
c15d: 29 3f                        and     #%00111111              ;not sure what this was intended for, exactly
c15f: c9 2e                        cmp     #$2e                    ;this part is quite possibly residual code
c161: f0 01                        beq     CheckRightBounds        ; but it has the effect of keeping enemies out of
c163: 60                           rts                             ; the sixth slot

                   CheckRightBounds
c164: ad 1d 07                     lda     ScreenRight_X_Pos       ;add 48 to pixel coordinate of right boundary
c167: 18                           clc
c168: 69 30                        adc     #$30
c16a: 29 f0                        and     #%11110000              ;store high nybble
c16c: 85 07                        sta     $07
c16e: ad 1b 07                     lda     ScreenRight_PageLoc     ;add carry to page location of right boundary
c171: 69 00                        adc     #$00
c173: 85 06                        sta     $06                     ;store page location + carry
c175: ac 39 07                     ldy     EnemyDataOffset
c178: c8                           iny
c179: b1 e9                        lda     (EnemyData),y           ;if MSB of enemy object is clear, branch to check for row $0f
c17b: 0a                           asl     A
c17c: 90 0b                        bcc     CheckPageCtrlRow
c17e: ad 3b 07                     lda     EnemyObjectPageSel      ;if page select already set, do not set again
c181: d0 06                        bne     CheckPageCtrlRow
c183: ee 3b 07                     inc     EnemyObjectPageSel      ;otherwise, if MSB is set, set page select 
c186: ee 3a 07                     inc     EnemyObjectPageLoc      ; and increment page control
                   CheckPageCtrlRow
c189: 88                           dey
c18a: b1 e9                        lda     (EnemyData),y           ;reread first byte
c18c: 29 0f                        and     #$0f
c18e: c9 0f                        cmp     #$0f                    ;check for special row $0f
c190: d0 19                        bne     PositionEnemyObj        ;if not found, branch to position enemy object
c192: ad 3b 07                     lda     EnemyObjectPageSel      ;if page select set,
c195: d0 14                        bne     PositionEnemyObj        ;branch without reading second byte
c197: c8                           iny
c198: b1 e9                        lda     (EnemyData),y           ;otherwise, get second byte, mask out 2 MSB
c19a: 29 3f                        and     #%00111111
c19c: 8d 3a 07                     sta     EnemyObjectPageLoc      ;store as page control for enemy object data
c19f: ee 39 07                     inc     EnemyDataOffset         ;increment enemy object data offset 2 bytes
c1a2: ee 39 07                     inc     EnemyDataOffset
c1a5: ee 3b 07                     inc     EnemyObjectPageSel      ;set page select for enemy object data and 
c1a8: 4c cc c0                     jmp     ProcLoopCommand         ;jump back to process loop commands again

                   PositionEnemyObj
c1ab: ad 3a 07                     lda     EnemyObjectPageLoc      ;store page control as page location
c1ae: 95 6e                        sta     Enemy_PageLoc,x         ; for enemy object
c1b0: b1 e9                        lda     (EnemyData),y           ;get first byte of enemy object
c1b2: 29 f0                        and     #%11110000
c1b4: 95 87                        sta     Enemy_X_Position,x      ;store column position
c1b6: cd 1d 07                     cmp     ScreenRight_X_Pos       ;check column position against right boundary
c1b9: b5 6e                        lda     Enemy_PageLoc,x         ;without subtracting, then subtract borrow
c1bb: ed 1b 07                     sbc     ScreenRight_PageLoc     ; from page location
c1be: b0 0b                        bcs     CheckRightExtBounds     ;if enemy object beyond or at boundary, branch
c1c0: b1 e9                        lda     (EnemyData),y
c1c2: 29 0f                        and     #%00001111              ;check for special row $0e
c1c4: c9 0e                        cmp     #$0e                    ;if found, jump elsewhere
c1c6: f0 69                        beq     ParseRow0e
c1c8: 4c 50 c2                     jmp     CheckThreeBytes         ;if not found, unconditional jump

                   CheckRightExtBounds
c1cb: a5 07                        lda     $07                     ;check right boundary + 48 against
c1cd: d5 87                        cmp     Enemy_X_Position,x      ; column position without subtracting,
c1cf: a5 06                        lda     $06                     ; then subtract borrow from page control temp
c1d1: f5 6e                        sbc     Enemy_PageLoc,x         ; plus carry
c1d3: 90 41                        bcc     CheckFrenzyBuffer       ;if enemy object beyond extended boundary, branch
c1d5: a9 01                        lda     #$01                    ;store value in vertical high byte
c1d7: 95 b6                        sta     Enemy_Y_HighPos,x
c1d9: b1 e9                        lda     (EnemyData),y           ;get first byte again
c1db: 0a                           asl     A                       ;multiply by four to get the vertical
c1dc: 0a                           asl     A                       ; coordinate
c1dd: 0a                           asl     A
c1de: 0a                           asl     A
c1df: 95 cf                        sta     Enemy_Y_Position,x
c1e1: c9 e0                        cmp     #$e0                    ;do one last check for special row $0e
c1e3: f0 4c                        beq     ParseRow0e              ;(necessary if branched to $c1cb)
c1e5: c8                           iny
c1e6: b1 e9                        lda     (EnemyData),y           ;get second byte of object
c1e8: 29 40                        and     #%01000000              ;check to see if hard mode bit is set
c1ea: f0 05                        beq     CheckForEnemyGroup      ;if not, branch to check for group enemy objects
c1ec: ad cc 06                     lda     SecondaryHardMode       ;if set, check to see if secondary hard mode flag
c1ef: f0 6d                        beq     Inc2B                   ;is on, and if not, branch to skip this object completely
                   CheckForEnemyGroup
c1f1: b1 e9                        lda     (EnemyData),y           ;get second byte and mask out 2 MSB
c1f3: 29 3f                        and     #%00111111
c1f5: c9 37                        cmp     #$37                    ;check for value below $37
c1f7: 90 04                        bcc     BuzzyBeetleMutate
c1f9: c9 3f                        cmp     #$3f                    ;if $37 or greater, check for value
c1fb: 90 31                        bcc     DoGroup                 ;below $3f, branch if below $3f
                   BuzzyBeetleMutate
c1fd: c9 06                        cmp     #Goomba                 ;if below $37, check for goomba
c1ff: d0 07                        bne     StrID                   ; value ($3f or more always fails)
c201: ac 6a 07                     ldy     PrimaryHardMode         ;check if primary hard mode flag is set
c204: f0 02                        beq     StrID                   ; and if so, change goomba to buzzy beetle
c206: a9 02                        lda     #BuzzyBeetle
c208: 95 16        StrID           sta     Enemy_ID,x              ;store enemy object number into buffer
c20a: a9 01                        lda     #$01
c20c: 95 0f                        sta     Enemy_Flag,x            ;set flag for enemy in buffer
c20e: 20 26 c2                     jsr     InitEnemyObject
c211: b5 0f                        lda     Enemy_Flag,x            ;check to see if flag is set
c213: d0 49                        bne     Inc2B                   ;if not, leave, otherwise branch
c215: 60                           rts

                   CheckFrenzyBuffer
c216: ad cb 06                     lda     EnemyFrenzyBuffer       ;if enemy object stored in frenzy buffer
c219: d0 09                        bne     StrFre                  ; then branch ahead to store in enemy object buffer
c21b: ad 98 03                     lda     VineFlagOffset          ;otherwise check vine flag offset
c21e: c9 01                        cmp     #$01
c220: d0 0b                        bne     ExEPar                  ;if other value <> 1, leave
c222: a9 2f                        lda     #VineObject             ;otherwise put vine in enemy identifier
c224: 95 16        StrFre          sta     Enemy_ID,x              ;store contents of frenzy buffer into enemy identifier value
c226: a9 00        InitEnemyObject lda     #$00                    ;initialize enemy state
c228: 95 1e                        sta     Enemy_State,x
c22a: 20 6c c2                     jsr     CheckpointEnemyID       ;jump ahead to run jump engine and subroutines
c22d: 60           ExEPar          rts                             ;then leave

c22e: 4c 1b c7     DoGroup         jmp     HandleGroupEnemies      ;handle enemy group objects

c231: c8           ParseRow0e      iny                             ;increment Y to load third byte of object
c232: c8                           iny
c233: b1 e9                        lda     (EnemyData),y
c235: 4a                           lsr     A                       ;move 3 MSB to the bottom, effectively
c236: 4a                           lsr     A                       ; making %xxx00000 into %00000xxx
c237: 4a                           lsr     A
c238: 4a                           lsr     A
c239: 4a                           lsr     A
c23a: cd 5f 07                     cmp     WorldNumber             ;is it the same world number as we're on?
c23d: d0 0e                        bne     NotUse                  ;if not, do not use (this allows multiple uses
c23f: 88                           dey                             ; of the same area, like the underground bonus areas)
c240: b1 e9                        lda     (EnemyData),y           ;otherwise, get second byte and use as offset
c242: 8d 50 07                     sta     AreaPointer             ; to addresses for level and enemy object data
c245: c8                           iny
c246: b1 e9                        lda     (EnemyData),y           ;get third byte again, and this time mask out
c248: 29 1f                        and     #%00011111              ; the 3 MSB from before, save as page number to be
c24a: 8d 51 07                     sta     EntrancePage            ; used upon entry to area, if area is entered
c24d: 4c 5b c2     NotUse          jmp     Inc3B

c250: ac 39 07     CheckThreeBytes ldy     EnemyDataOffset
c253: b1 e9                        lda     (EnemyData),y
c255: 29 0f                        and     #$0f
c257: c9 0e                        cmp     #$0e
c259: d0 03                        bne     Inc2B
c25b: ee 39 07     Inc3B           inc     EnemyDataOffset
c25e: ee 39 07     Inc2B           inc     EnemyDataOffset
c261: ee 39 07                     inc     EnemyDataOffset
c264: a9 00                        lda     #$00
c266: 8d 3b 07                     sta     EnemyObjectPageSel
c269: a6 08                        ldx     ObjectOffset
c26b: 60                           rts

                   CheckpointEnemyID
c26c: b5 16                        lda     Enemy_ID,x
c26e: c9 15                        cmp     #$15
c270: b0 0d                        bcs     InitEnemyRoutines
c272: a8                           tay
c273: b5 cf                        lda     Enemy_Y_Position,x
c275: 69 08                        adc     #$08
c277: 95 cf                        sta     Enemy_Y_Position,x
c279: a9 01                        lda     #$01
c27b: 9d d8 03                     sta     EnemyOffscrBitsMasked,x
c27e: 98                           tya
                   InitEnemyRoutines
c27f: 20 04 8e                     jsr     JumpEngine

                   ; jump engine table for newly loaded enemy objects
c282: 0e c3                        .dd2    InitNormalEnemy         ;for objects $00-$0f
c284: 0e c3                        .dd2    InitNormalEnemy
c286: 0e c3                        .dd2    InitNormalEnemy
c288: 1e c3                        .dd2    InitRedKoopa
c28a: f0 c2                        .dd2    NoInitCode
c28c: 28 c3                        .dd2    InitHammerBro
c28e: f1 c2                        .dd2    InitGoomba
c290: 42 c3                        .dd2    InitBloober
c292: 6b c3                        .dd2    InitBulletBill
c294: f0 c2                        .dd2    NoInitCode
c296: 75 c3                        .dd2    InitCheepCheep
c298: 75 c3                        .dd2    InitCheepCheep
c29a: f7 c2                        .dd2    InitPodoboo
c29c: 87 c7                        .dd2    InitPiranhaPlant
c29e: d1 c7                        .dd2    InitJumpGPTroopa
c2a0: 4a c3                        .dd2    InitRedPTroopa
c2a2: 3d c3                        .dd2    InitHorizFlySwimEnemy   ;for objects $10-$1f
c2a4: 85 c3                        .dd2    InitLakitu
c2a6: a0 c7                        .dd2    InitEnemyFrenzy
c2a8: f0 c2                        .dd2    NoInitCode
c2aa: a0 c7                        .dd2    InitEnemyFrenzy
c2ac: a0 c7                        .dd2    InitEnemyFrenzy
c2ae: a0 c7                        .dd2    InitEnemyFrenzy
c2b0: a0 c7                        .dd2    InitEnemyFrenzy
c2b2: b8 c7                        .dd2    EndFrenzy
c2b4: f0 c2                        .dd2    NoInitCode
c2b6: f0 c2                        .dd2    NoInitCode
c2b8: 5c c4                        .dd2    InitShortFirebar
c2ba: 5c c4                        .dd2    InitShortFirebar
c2bc: 5c c4                        .dd2    InitShortFirebar
c2be: 5c c4                        .dd2    InitShortFirebar
c2c0: 59 c4                        .dd2    InitLongFirebar
c2c2: f0 c2                        .dd2    NoInitCode              ;for objects $20-$2f
c2c4: f0 c2                        .dd2    NoInitCode
c2c6: f0 c2                        .dd2    NoInitCode
c2c8: f0 c2                        .dd2    NoInitCode
c2ca: df c7                        .dd2    InitBalPlatform
c2cc: 12 c8                        .dd2    InitVertPlatform
c2ce: 3f c8                        .dd2    LargeLiftUp
c2d0: 45 c8                        .dd2    LargeLiftDown
c2d2: 0b c8                        .dd2    InitHoriPlatform
c2d4: 03 c8                        .dd2    InitDropPlatform
c2d6: 0b c8                        .dd2    InitHoriPlatform
c2d8: 4b c8                        .dd2    PlatLiftUp
c2da: 57 c8                        .dd2    PlatLiftDown
c2dc: 49 c5                        .dd2    InitBowser
c2de: 60 bc                        .dd2    PwrUpJmp                ;possibly dummy value
c2e0: 1e b9                        .dd2    Setup_Vine
c2e2: f0 c2                        .dd2    NoInitCode              ;for objects $30-$36
c2e4: f0 c2                        .dd2    NoInitCode
c2e6: f0 c2                        .dd2    NoInitCode
c2e8: f0 c2                        .dd2    NoInitCode
c2ea: f0 c2                        .dd2    NoInitCode
c2ec: 07 c3                        .dd2    InitRetainerObj
c2ee: 81 c8                        .dd2    EndOFEnemyInitCode

                   ; -----------------------------------------------------------------------------
c2f0: 60           NoInitCode      rts                             ;this executed when enemy object has no init code

                   ; -----------------------------------------------------------------------------
c2f1: 20 0e c3     InitGoomba      jsr     InitNormalEnemy         ;set appropriate horizontal speed
c2f4: 4c 46 c3                     jmp     SmallBBox               ;set $09 as bounding box control, set other values

                   ; -----------------------------------------------------------------------------
c2f7: a9 02        InitPodoboo     lda     #$02                    ;set enemy position to below
c2f9: 95 b6                        sta     Enemy_Y_HighPos,x       ; the bottom of the screen
c2fb: 95 cf                        sta     Enemy_Y_Position,x
c2fd: 4a                           lsr     A
c2fe: 9d 96 07                     sta     EnemyIntervalTimer,x    ;set timer for enemy
c301: 4a                           lsr     A
c302: 95 1e                        sta     Enemy_State,x           ;initialize enemy state, then jump to use
c304: 4c 46 c3                     jmp     SmallBBox               ; $09 as bounding box size and set other things

                   ; -----------------------------------------------------------------------------
c307: a9 b8        InitRetainerObj lda     #$b8                    ;set fixed vertical position for
c309: 95 cf                        sta     Enemy_Y_Position,x      ; princess/mushroom retainer object
c30b: 60                           rts

                   ; -----------------------------------------------------------------------------
c30c: f8 f4        NormalXSpdData  .bulk   $f8,$f4

c30e: a0 01        InitNormalEnemy ldy     #$01                    ;load offset of 1 by default
c310: ad 6a 07                     lda     PrimaryHardMode         ;check for primary hard mode flag set
c313: d0 01                        bne     GetESpd
c315: 88                           dey                             ;if not set, decrement offset
c316: b9 0c c3     GetESpd         lda     NormalXSpdData,y        ;get appropriate horizontal speed
c319: 95 58        SetESpd         sta     BlooperMoveSpeed,x      ;store as speed for enemy object
c31b: 4c 5a c3                     jmp     TallBBox                ;branch to set bounding box control and other data

                   ; -----------------------------------------------------------------------------
c31e: 20 0e c3     InitRedKoopa    jsr     InitNormalEnemy         ;load appropriate horizontal speed
c321: a9 01                        lda     #$01                    ;set enemy state for red koopa troopa $03
c323: 95 1e                        sta     Enemy_State,x
c325: 60                           rts

                   ; -----------------------------------------------------------------------------
                   HBroWalkingTimerData
c326: 80 50                        .bulk   $80,$50

c328: a9 00        InitHammerBro   lda     #$00                    ;init horizontal speed and timer used by hammer bro
c32a: 9d a2 03                     sta     HammerThrowingTimer,x   ;apparently to time hammer throwing
c32d: 95 58                        sta     Enemy_X_Speed,x
c32f: ac cc 06                     ldy     SecondaryHardMode       ;get secondary hard mode flag
c332: b9 26 c3                     lda     HBroWalkingTimerData,y
c335: 9d 96 07                     sta     EnemyIntervalTimer,x    ;set value as delay for hammer bro to walk left
c338: a9 0b                        lda     #$0b                    ;set specific value for bounding box size control
c33a: 4c 5c c3                     jmp     SetBBox

                   ; -----------------------------------------------------------------------------
                   InitHorizFlySwimEnemy
c33d: a9 00                        lda     #$00                    ;initialize horizontal speed
c33f: 4c 19 c3                     jmp     SetESpd

                   ; -----------------------------------------------------------------------------
c342: a9 00        InitBloober     lda     #$00                    ;initialize horizontal speed
c344: 95 58                        sta     BlooperMoveSpeed,x
c346: a9 09        SmallBBox       lda     #$09                    ;set specific bounding box size control
c348: d0 12                        bne     SetBBox                 ;unconditional branch

                   ; -----------------------------------------------------------------------------
c34a: a0 30        InitRedPTroopa  ldy     #$30                    ;load central position adder for 48 pixels down
c34c: b5 cf                        lda     Enemy_Y_Position,x      ;set vertical coordinate into location to
c34e: 9d 01 04                     sta     RedPTroopaOrigXPos,x    ; be used as original vertical coordinate
c351: 10 02                        bpl     GetCent                 ;if vertical coordinate < $80
c353: a0 e0                        ldy     #$e0                    ;if => $80, load position adder for 32 pixels up
c355: 98           GetCent         tya                             ;send central position adder to A
c356: 75 cf                        adc     Enemy_Y_Position,x      ;add to current vertical coordinate
c358: 95 58                        sta     RedPTroopaCenterYPos,x  ;store as central vertical coordinate
c35a: a9 03        TallBBox        lda     #$03                    ;set specific bounding box size control
c35c: 9d 9a 04     SetBBox         sta     Enemy_BoundBoxCtrl,x    ;set bounding box control here
c35f: a9 02                        lda     #$02                    ;set moving direction for left
c361: 95 46                        sta     Enemy_MovingDir,x
c363: a9 00        InitVStf        lda     #$00                    ;initialize vertical speed
c365: 95 a0                        sta     Enemy_Y_Speed,x         ; and movement force
c367: 9d 34 04                     sta     Enemy_Y_MoveForce,x
c36a: 60                           rts

                   ; -----------------------------------------------------------------------------
c36b: a9 02        InitBulletBill  lda     #$02                    ;set moving direction for left
c36d: 95 46                        sta     Enemy_MovingDir,x
c36f: a9 09                        lda     #$09                    ;set bounding box control for $09
c371: 9d 9a 04                     sta     Enemy_BoundBoxCtrl,x
c374: 60                           rts

                   ; -----------------------------------------------------------------------------
c375: 20 46 c3     InitCheepCheep  jsr     SmallBBox               ;set vertical bounding box, speed, init others
c378: bd a7 07                     lda     PseudoRandomBitReg,x    ;check one portion of LSFR
c37b: 29 10                        and     #%00010000              ;get d4 from it
c37d: 95 58                        sta     CheepCheepMoveMFlag,x   ;save as movement flag of some sort
c37f: b5 cf                        lda     Enemy_Y_Position,x
c381: 9d 34 04                     sta     CheepCheepOrigYPos,x    ;save original vertical coordinate here
c384: 60                           rts

                   ; -----------------------------------------------------------------------------
c385: ad cb 06     InitLakitu      lda     EnemyFrenzyBuffer       ;check to see if an enemy is already in
c388: d0 0b                        bne     KillLakitu              ; the frenzy buffer, and branch to kill lakitu if so
c38a: a9 00        SetupLakitu     lda     #$00                    ;erase counter for lakitu's reappearance
c38c: 8d d1 06                     sta     LakituReappearTimer
c38f: 20 3d c3                     jsr     InitHorizFlySwimEnemy   ;set $03 as bounding box, set other attributes
c392: 4c d9 c7                     jmp     TallBBox2               ;set $03 as bounding box again (not necessary) and leave

c395: 4c 98 c9     KillLakitu      jmp     EraseEnemyObject

                   ; -----------------------------------------------------------------------------
                   ; $01-$03 - used to hold pseudorandom difference adjusters
                   PRDiffAdjustData
c398: 26 2c 32 38                  .bulk   $26,$2c,$32,$38
c39c: 20 22 24 26                  .bulk   $20,$22,$24,$26
c3a0: 13 14 15 16                  .bulk   $13,$14,$15,$16

                   LakituAndSpinyHandler
c3a4: ad 8f 07                     lda     FrenzyEnemyTimer        ;if timer here not expired, leave
c3a7: d0 3c                        bne     ExLSHand
c3a9: e0 05                        cpx     #$05                    ;if we are on the special use slot, leave
c3ab: b0 38                        bcs     ExLSHand
c3ad: a9 80                        lda     #$80                    ;set timer
c3af: 8d 8f 07                     sta     FrenzyEnemyTimer
c3b2: a0 04                        ldy     #$04                    ;start with the last enemy slot
c3b4: b9 16 00     ChkLak          lda     Enemy_ID,y              ;check all enemy slots to see
c3b7: c9 11                        cmp     #Lakitu                 ;if lakitu is on one of them
c3b9: f0 2b                        beq     CreateSpiny             ;if so, branch out of this loop
c3bb: 88                           dey                             ;otherwise check another slot
c3bc: 10 f6                        bpl     ChkLak                  ;loop until all slots are checked
c3be: ee d1 06                     inc     LakituReappearTimer     ;increment reappearance timer
c3c1: ad d1 06                     lda     LakituReappearTimer
c3c4: c9 07                        cmp     #$07                    ;check to see if we're up to a certain value yet
c3c6: 90 1d                        bcc     ExLSHand                ;if not, leave
c3c8: a2 04                        ldx     #$04                    ;start with the last enemy slot again
c3ca: b5 0f        ChkNoEn         lda     Enemy_Flag,x            ;check enemy buffer flag for non-active enemy slot
c3cc: f0 05                        beq     CreateL                 ;branch out of loop if found
c3ce: ca                           dex                             ;otherwise check next slot
c3cf: 10 f9                        bpl     ChkNoEn                 ;branch until all slots are checked
c3d1: 30 10                        bmi     RetEOfs                 ;if no empty slots were found, branch to leave

c3d3: a9 00        CreateL         lda     #$00                    ;initialize enemy state
c3d5: 95 1e                        sta     Enemy_State,x
c3d7: a9 11                        lda     #Lakitu                 ;create lakitu enemy object
c3d9: 95 16                        sta     Enemy_ID,x
c3db: 20 8a c3                     jsr     SetupLakitu             ;do a sub to set up lakitu
c3de: a9 20                        lda     #$20
c3e0: 20 d8 c5                     jsr     PutAtRightExtent        ;finish setting up lakitu
c3e3: a6 08        RetEOfs         ldx     ObjectOffset            ;get enemy object buffer offset again and leave
c3e5: 60           ExLSHand        rts

                   ; -----------------------------------------------------------------------------
c3e6: a5 ce        CreateSpiny     lda     Player_Y_Position       ;if player above a certain point, branch to leave
c3e8: c9 2c                        cmp     #$2c
c3ea: 90 f9                        bcc     ExLSHand
c3ec: b9 1e 00                     lda     Enemy_State,y           ;if lakitu is not in normal state, branch to leave
c3ef: d0 f4                        bne     ExLSHand
c3f1: b9 6e 00                     lda     Enemy_PageLoc,y         ;store horizontal coordinates (high and low) of lakitu
c3f4: 95 6e                        sta     Enemy_PageLoc,x         ;into the coordinates of the spiny we're going to create
c3f6: b9 87 00                     lda     Enemy_X_Position,y
c3f9: 95 87                        sta     Enemy_X_Position,x
c3fb: a9 01                        lda     #$01                    ;put spiny within vertical screen unit
c3fd: 95 b6                        sta     Enemy_Y_HighPos,x
c3ff: b9 cf 00                     lda     Enemy_Y_Position,y      ;put spiny eight pixels above where lakitu is
c402: 38                           sec
c403: e9 08                        sbc     #$08
c405: 95 cf                        sta     Enemy_Y_Position,x
c407: bd a7 07                     lda     PseudoRandomBitReg,x    ;get 2 LSB of LSFR and save to Y
c40a: 29 03                        and     #%00000011
c40c: a8                           tay
c40d: a2 02                        ldx     #$02
c40f: b9 98 c3     DifLoop         lda     PRDiffAdjustData,y      ;get three values and save them
c412: 95 01                        sta     $01,x                   ;to $01-$03
c414: c8                           iny
c415: c8                           iny                             ;increment Y four bytes for each value
c416: c8                           iny
c417: c8                           iny
c418: ca                           dex                             ;decrement X for each one
c419: 10 f4                        bpl     DifLoop                 ;loop until all three are written
c41b: a6 08                        ldx     ObjectOffset            ;get enemy object buffer offset
c41d: 20 6c cf                     jsr     PlayerLakituDiff        ;move enemy, change direction, get value - difference
c420: a4 57                        ldy     Player_X_Speed          ;check player's horizontal speed
c422: c0 08                        cpy     #$08
c424: b0 0e                        bcs     SetSpSpd                ;if moving faster than a certain amount, branch elsewhere
c426: a8                           tay                             ;otherwise save value in A to Y for now
c427: bd a8 07                     lda     PseudoRandomBitReg+1,x
c42a: 29 03                        and     #%00000011              ;get one of the LSFR parts and save the 2 LSB
c42c: f0 05                        beq     UsePosv                 ;branch if neither bits are set
c42e: 98                           tya
c42f: 49 ff                        eor     #%11111111              ;otherwise get two's compliment of Y
c431: a8                           tay
c432: c8                           iny
c433: 98           UsePosv         tya                             ;put value from A in Y back to A (they will be lost anyway)
c434: 20 46 c3     SetSpSpd        jsr     SmallBBox               ;set bounding box control, init attributes, lose contents of A
c437: a0 02                        ldy     #$02
c439: 95 58                        sta     Enemy_X_Speed,x         ;set horizontal speed to zero because previous contents
c43b: c9 00                        cmp     #$00                    ; of A were lost...branch here will never be taken for
c43d: 30 01                        bmi     SpinyRte                ; the same reason
c43f: 88                           dey
c440: 94 46        SpinyRte        sty     Enemy_MovingDir,x       ;set moving direction to the right
c442: a9 fd                        lda     #$fd
c444: 95 a0                        sta     BlooperMoveCounter,x    ;set vertical speed to move upwards
c446: a9 01                        lda     #$01
c448: 95 0f                        sta     Enemy_Flag,x            ;enable enemy object by setting flag
c44a: a9 05                        lda     #$05
c44c: 95 1e                        sta     Enemy_State,x           ;put spiny in egg state and leave
c44e: 60           ChpChpEx        rts

                   ; -----------------------------------------------------------------------------
                   FirebarSpinSpdData
c44f: 28 38 28 38+                 .bulk   $28,$38,$28,$38,$28
                   FirebarSpinDirData
c454: 00 00 10 10+                 .bulk   $00,$00,$10,$10,$00

c459: 20 75 c5     InitLongFirebar jsr     DuplicateEnemyObj       ;create enemy object for long firebar
                   InitShortFirebar
c45c: a9 00                        lda     #$00                    ;initialize low byte of spin state
c45e: 95 58                        sta     FirebarSpinState_Low,x
c460: b5 16                        lda     Enemy_ID,x              ;subtract $1b from enemy identifier
c462: 38                           sec                             ; to get proper offset for firebar data
c463: e9 1b                        sbc     #$1b
c465: a8                           tay
c466: b9 4f c4                     lda     FirebarSpinSpdData,y    ;get spinning speed of firebar
c469: 9d 88 03                     sta     FirebarSpinSpeed,x
c46c: b9 54 c4                     lda     FirebarSpinDirData,y    ;get spinning direction of firebar
c46f: 95 34                        sta     DestinationPageLoc,x
c471: b5 cf                        lda     Enemy_Y_Position,x
c473: 18                           clc                             ;add four pixels to vertical coordinate
c474: 69 04                        adc     #$04
c476: 95 cf                        sta     Enemy_Y_Position,x
c478: b5 87                        lda     Enemy_X_Position,x
c47a: 18                           clc                             ;add four pixels to horizontal coordinate
c47b: 69 04                        adc     #$04
c47d: 95 87                        sta     Enemy_X_Position,x
c47f: b5 6e                        lda     Enemy_PageLoc,x
c481: 69 00                        adc     #$00                    ;add carry to page location
c483: 95 6e                        sta     Enemy_PageLoc,x
c485: 4c d9 c7                     jmp     TallBBox2               ;set bounding box control (not used) and leave

                   ; -----------------------------------------------------------------------------
                   ; $00-$01 - used to hold pseudorandom bits
                   FlyCCXPositionData
c488: 80 30 40 80                  .bulk   $80,$30,$40,$80
c48c: 30 50 50 70                  .bulk   $30,$50,$50,$70
c490: 20 40 80 a0                  .bulk   $20,$40,$80,$a0
c494: 70 40 90 68                  .bulk   $70,$40,$90,$68
c498: 0e 05 06 0e  FlyCCXSpeedData .bulk   $0e,$05,$06,$0e
c49c: 1c 20 10 0c                  .bulk   $1c,$20,$10,$0c
c4a0: 1e 22 18 14                  .bulk   $1e,$22,$18,$14
c4a4: 10 60 20 48  FlyCCTimerData  .bulk   $10,$60,$20,$48

                   InitFlyingCheepCheep
c4a8: ad 8f 07                     lda     FrenzyEnemyTimer        ;if timer here not expired yet, branch to leave
c4ab: d0 a1                        bne     ChpChpEx
c4ad: 20 46 c3                     jsr     SmallBBox               ;jump to set bounding box size $09 and init other values
c4b0: bd a8 07                     lda     PseudoRandomBitReg+1,x
c4b3: 29 03                        and     #%00000011              ;set pseudorandom offset here
c4b5: a8                           tay
c4b6: b9 a4 c4                     lda     FlyCCTimerData,y        ;load timer with pseudorandom offset
c4b9: 8d 8f 07                     sta     FrenzyEnemyTimer
c4bc: a0 03                        ldy     #$03                    ;load Y with default value
c4be: ad cc 06                     lda     SecondaryHardMode
c4c1: f0 01                        beq     MaxCC                   ;if secondary hard mode flag not set, do not increment Y
c4c3: c8                           iny                             ;otherwise, increment Y to allow as many as four onscreen
c4c4: 84 00        MaxCC           sty     $00                     ;store whatever pseudorandom bits are in Y
c4c6: e4 00                        cpx     $00                     ;compare enemy object buffer offset with Y
c4c8: b0 84                        bcs     ChpChpEx                ;if X => Y, branch to leave
c4ca: bd a7 07                     lda     PseudoRandomBitReg,x
c4cd: 29 03                        and     #%00000011              ;get last two bits of LSFR, first part
c4cf: 85 00                        sta     $00                     ; and store in two places
c4d1: 85 01                        sta     $01
c4d3: a9 fb                        lda     #$fb                    ;set vertical speed for cheep-cheep
c4d5: 95 a0                        sta     Enemy_Y_Speed,x
c4d7: a9 00                        lda     #$00                    ;load default value
c4d9: a4 57                        ldy     Player_X_Speed          ;check player's horizontal speed
c4db: f0 07                        beq     GSeed                   ;if player not moving left or right, skip this part
c4dd: a9 04                        lda     #$04
c4df: c0 19                        cpy     #$19                    ;if moving to the right but not very quickly,
c4e1: 90 01                        bcc     GSeed                   ; do not change A
c4e3: 0a                           asl     A                       ;otherwise, multiply A by 2
c4e4: 48           GSeed           pha                             ;save to stack
c4e5: 18                           clc
c4e6: 65 00                        adc     $00                     ;add to last two bits of LSFR we saved earlier
c4e8: 85 00                        sta     $00                     ;save it there
c4ea: bd a8 07                     lda     PseudoRandomBitReg+1,x
c4ed: 29 03                        and     #%00000011              ;if neither of the last two bits of second LSFR set,
c4ef: f0 07                        beq     RSeed                   ; skip this part and save contents of $00
c4f1: bd a9 07                     lda     PseudoRandomBitReg+2,x
c4f4: 29 0f                        and     #%00001111              ;otherwise overwrite with lower nybble of
c4f6: 85 00                        sta     $00                     ; third LSFR part
c4f8: 68           RSeed           pla                             ;get value from stack we saved earlier
c4f9: 18                           clc
c4fa: 65 01                        adc     $01                     ;add to last two bits of LSFR we saved in other place
c4fc: a8                           tay                             ;use as pseudorandom offset here
c4fd: b9 98 c4                     lda     FlyCCXSpeedData,y       ;get horizontal speed using pseudorandom offset
c500: 95 58                        sta     Enemy_X_Speed,x
c502: a9 01                        lda     #$01                    ;set to move towards the right
c504: 95 46                        sta     Enemy_MovingDir,x
c506: a5 57                        lda     Player_X_Speed          ;if player moving left or right, branch ahead of this part
c508: d0 12                        bne     D2XPos1
c50a: a4 00                        ldy     $00                     ;get first LSFR or third LSFR lower nybble
c50c: 98                           tya                             ;and check for d1 set
c50d: 29 02                        and     #%00000010
c50f: f0 0b                        beq     D2XPos1                 ;if d1 not set, branch
c511: b5 58                        lda     Enemy_X_Speed,x
c513: 49 ff                        eor     #$ff                    ;if d1 set, change horizontal speed
c515: 18                           clc                             ; into two's compliment, thus moving in the opposite
c516: 69 01                        adc     #$01                    ; direction
c518: 95 58                        sta     Enemy_X_Speed,x
c51a: f6 46                        inc     Enemy_MovingDir,x       ;increment to move towards the left
c51c: 98           D2XPos1         tya                             ;get first LSFR or third LSFR lower nybble again
c51d: 29 02                        and     #%00000010
c51f: f0 0f                        beq     D2XPos2                 ;check for d1 set again, branch again if not set
c521: a5 86                        lda     Player_X_Position       ;get player's horizontal position
c523: 18                           clc
c524: 79 88 c4                     adc     FlyCCXPositionData,y    ;if d1 set, add value obtained from pseudorandom offset
c527: 95 87                        sta     Enemy_X_Position,x      ; and save as enemy's horizontal position
c529: a5 6d                        lda     Player_PageLoc          ;get player's page location
c52b: 69 00                        adc     #$00                    ;add carry and jump past this part
c52d: 4c 3c c5                     jmp     FinCCst

c530: a5 86        D2XPos2         lda     Player_X_Position       ;get player's horizontal position
c532: 38                           sec
c533: f9 88 c4                     sbc     FlyCCXPositionData,y    ;if d1 not set, subtract value obtained from pseudorandom
c536: 95 87                        sta     Enemy_X_Position,x      ; offset and save as enemy's horizontal position
c538: a5 6d                        lda     Player_PageLoc          ;get player's page location
c53a: e9 00                        sbc     #$00                    ;subtract borrow
c53c: 95 6e        FinCCst         sta     Enemy_PageLoc,x         ;save as enemy's page location
c53e: a9 01                        lda     #$01
c540: 95 0f                        sta     Enemy_Flag,x            ;set enemy's buffer flag
c542: 95 b6                        sta     Enemy_Y_HighPos,x       ;set enemy's high vertical byte
c544: a9 f8                        lda     #$f8
c546: 95 cf                        sta     Enemy_Y_Position,x      ;put enemy below the screen, and we are done
c548: 60                           rts

                   ; -----------------------------------------------------------------------------
c549: 20 75 c5     InitBowser      jsr     DuplicateEnemyObj       ;jump to create another bowser object
c54c: 8e 68 03                     stx     BowserFront_Offset      ;save offset of first here
c54f: a9 00                        lda     #$00
c551: 8d 63 03                     sta     BowserBodyControls      ;initialize bowser's body controls
c554: 8d 69 03                     sta     BridgeCollapseOffset    ;and bridge collapse offset
c557: b5 87                        lda     Enemy_X_Position,x
c559: 8d 66 03                     sta     BowserOrigXPos          ;store original horizontal position here
c55c: a9 df                        lda     #$df
c55e: 8d 90 07                     sta     BowserFireBreathTimer   ;store something here
c561: 95 46                        sta     Enemy_MovingDir,x       ;and in moving direction
c563: a9 20                        lda     #$20
c565: 8d 64 03                     sta     BowserFeetCounter       ;set bowser's feet timer and in enemy timer
c568: 9d 8a 07                     sta     EnemyFrameTimer,x
c56b: a9 05                        lda     #$05
c56d: 8d 83 04                     sta     BowserHitPoints         ;give bowser 5 hit points
c570: 4a                           lsr     A
c571: 8d 65 03                     sta     BowserMovementSpeed     ;set default movement speed here
c574: 60                           rts

                   ; -----------------------------------------------------------------------------
                   DuplicateEnemyObj
c575: a0 ff                        ldy     #$ff                    ;start at beginning of enemy slots
c577: c8           FSLoop          iny                             ;increment one slot
c578: b9 0f 00                     lda     Enemy_Flag,y            ;check enemy buffer flag for empty slot
c57b: d0 fa                        bne     FSLoop                  ;if set, branch and keep checking
c57d: 8c cf 06                     sty     DuplicateObj_Offset     ;otherwise set offset here
c580: 8a                           txa                             ;transfer original enemy buffer offset
c581: 09 80                        ora     #%10000000              ;store with d7 set as flag in new enemy
c583: 99 0f 00                     sta     Enemy_Flag,y            ; slot as well as enemy offset
c586: b5 6e                        lda     Enemy_PageLoc,x
c588: 99 6e 00                     sta     Enemy_PageLoc,y         ;copy page location and horizontal coordinates
c58b: b5 87                        lda     Enemy_X_Position,x      ; from original enemy to new enemy
c58d: 99 87 00                     sta     Enemy_X_Position,y
c590: a9 01                        lda     #$01
c592: 95 0f                        sta     Enemy_Flag,x            ;set flag as normal for original enemy
c594: 99 b6 00                     sta     Enemy_Y_HighPos,y       ;set high vertical byte for new enemy
c597: b5 cf                        lda     Enemy_Y_Position,x
c599: 99 cf 00                     sta     Enemy_Y_Position,y      ;copy vertical coordinate from original to new
c59c: 60           FlmEx           rts                             ;and then leave

                   ; -----------------------------------------------------------------------------
c59d: 90 80 70 90  FlameYPosData   .bulk   $90,$80,$70,$90
                   FlameYMFAdderData
c5a1: ff 01                        .bulk   $ff,$01

c5a3: ad 8f 07     InitBowserFlame lda     FrenzyEnemyTimer        ;if timer not expired yet, branch to leave
c5a6: d0 f4                        bne     FlmEx
c5a8: 9d 34 04                     sta     Enemy_Y_MoveForce,x     ;reset something here
c5ab: a5 fd                        lda     NoiseSoundQueue
c5ad: 09 02                        ora     #Sfx_BowserFlame        ;load bowser's flame sound into queue
c5af: 85 fd                        sta     NoiseSoundQueue
c5b1: ac 68 03                     ldy     BowserFront_Offset      ;get bowser's buffer offset
c5b4: b9 16 00                     lda     Enemy_ID,y              ;check for bowser
c5b7: c9 2d                        cmp     #Bowser
c5b9: f0 31                        beq     SpawnFromMouth          ;branch if found
c5bb: 20 d9 d1                     jsr     SetFlameTimer           ;get timer data based on flame counter
c5be: 18                           clc
c5bf: 69 20                        adc     #$20                    ;add 32 frames by default
c5c1: ac cc 06                     ldy     SecondaryHardMode
c5c4: f0 03                        beq     SetFrT                  ;if secondary mode flag not set, use as timer setting
c5c6: 38                           sec
c5c7: e9 10                        sbc     #$10                    ;otherwise subtract 16 frames for secondary hard mode
c5c9: 8d 8f 07     SetFrT          sta     FrenzyEnemyTimer        ;set timer accordingly
c5cc: bd a7 07                     lda     PseudoRandomBitReg,x
c5cf: 29 03                        and     #%00000011              ;get 2 LSB from first part of LSFR
c5d1: 9d 17 04                     sta     BowserFlamePRandomOfs,x ;set here
c5d4: a8                           tay                             ;use as offset
c5d5: b9 9d c5                     lda     FlameYPosData,y         ;load vertical position based on pseudorandom offset
                   PutAtRightExtent
c5d8: 95 cf                        sta     Enemy_Y_Position,x      ;set vertical position
c5da: ad 1d 07                     lda     ScreenRight_X_Pos
c5dd: 18                           clc
c5de: 69 20                        adc     #$20                    ;place enemy 32 pixels beyond right side of screen
c5e0: 95 87                        sta     Enemy_X_Position,x
c5e2: ad 1b 07                     lda     ScreenRight_PageLoc
c5e5: 69 00                        adc     #$00                    ;add carry
c5e7: 95 6e                        sta     Enemy_PageLoc,x
c5e9: 4c 1f c6                     jmp     FinishFlame             ;skip this part to finish setting values

c5ec: b9 87 00     SpawnFromMouth  lda     Enemy_X_Position,y      ;get bowser's horizontal position
c5ef: 38                           sec
c5f0: e9 0e                        sbc     #$0e                    ;subtract 14 pixels
c5f2: 95 87                        sta     Enemy_X_Position,x      ;save as flame's horizontal position
c5f4: b9 6e 00                     lda     Enemy_PageLoc,y
c5f7: 95 6e                        sta     Enemy_PageLoc,x         ;copy page location from bowser to flame
c5f9: b9 cf 00                     lda     Enemy_Y_Position,y
c5fc: 18                           clc                             ;add 8 pixels to bowser's vertical position
c5fd: 69 08                        adc     #$08
c5ff: 95 cf                        sta     Enemy_Y_Position,x      ;save as flame's vertical position
c601: bd a7 07                     lda     PseudoRandomBitReg,x
c604: 29 03                        and     #%00000011              ;get 2 LSB from first part of LSFR
c606: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;save here
c609: a8                           tay                             ;use as offset
c60a: b9 9d c5                     lda     FlameYPosData,y         ;get value here using bits as offset
c60d: a0 00                        ldy     #$00                    ;load default offset
c60f: d5 cf                        cmp     Enemy_Y_Position,x      ;compare value to flame's current vertical position
c611: 90 01                        bcc     SetMF                   ;if less, do not increment offset
c613: c8                           iny                             ;otherwise increment now
c614: b9 a1 c5     SetMF           lda     FlameYMFAdderData,y     ;get value here and save
c617: 9d 34 04                     sta     Enemy_Y_MoveForce,x     ; to vertical movement force
c61a: a9 00                        lda     #$00
c61c: 8d cb 06                     sta     EnemyFrenzyBuffer       ;clear enemy frenzy buffer
c61f: a9 08        FinishFlame     lda     #$08                    ;set $08 for bounding box control
c621: 9d 9a 04                     sta     Enemy_BoundBoxCtrl,x
c624: a9 01                        lda     #$01                    ;set high byte of vertical and
c626: 95 b6                        sta     Enemy_Y_HighPos,x       ; enemy buffer flag
c628: 95 0f                        sta     Enemy_Flag,x
c62a: 4a                           lsr     A
c62b: 9d 01 04                     sta     Enemy_X_MoveForce,x     ;initialize horizontal movement force, and
c62e: 95 1e                        sta     Enemy_State,x           ;enemy state
c630: 60                           rts

                   ; -----------------------------------------------------------------------------
                   FireworksXPosData
c631: 00 30 60 60+                 .bulk   $00,$30,$60,$60,$00,$20
                   FireworksYPosData
c637: 60 40 70 40+                 .bulk   $60,$40,$70,$40,$60,$30

c63d: ad 8f 07     InitFireworks   lda     FrenzyEnemyTimer        ;if timer not expired yet, branch to leave
c640: d0 47                        bne     ExitFWk
c642: a9 20                        lda     #$20                    ;otherwise reset timer
c644: 8d 8f 07                     sta     FrenzyEnemyTimer
c647: ce d7 06                     dec     FireworksCounter        ;decrement for each explosion
c64a: a0 06                        ldy     #$06                    ;start at last slot
c64c: 88           StarFChk        dey
c64d: b9 16 00                     lda     Enemy_ID,y              ;check for presence of star flag object
c650: c9 31                        cmp     #StarFlagObject         ;if there isn't a star flag object,
c652: d0 f8                        bne     StarFChk                ; routine goes into infinite loop = crash
c654: b9 87 00                     lda     Enemy_X_Position,y
c657: 38                           sec                             ;get horizontal coordinate of star flag object, then
c658: e9 30                        sbc     #$30                    ;subtract 48 pixels from it and save to
c65a: 48                           pha                             ; the stack
c65b: b9 6e 00                     lda     Enemy_PageLoc,y
c65e: e9 00                        sbc     #$00                    ;subtract the carry from the page location
c660: 85 00                        sta     $00                     ; of the star flag object
c662: ad d7 06                     lda     FireworksCounter        ;get fireworks counter
c665: 18                           clc
c666: 79 1e 00                     adc     Enemy_State,y           ;add state of star flag object (possibly not necessary)
c669: a8                           tay                             ;use as offset
c66a: 68                           pla                             ;get saved horizontal coordinate of star flag - 48 pixels
c66b: 18                           clc
c66c: 79 31 c6                     adc     FireworksXPosData,y     ;add number based on offset of fireworks counter
c66f: 95 87                        sta     Enemy_X_Position,x      ;store as the fireworks object horizontal coordinate
c671: a5 00                        lda     $00
c673: 69 00                        adc     #$00                    ;add carry and store as page location for
c675: 95 6e                        sta     Enemy_PageLoc,x         ; the fireworks object
c677: b9 37 c6                     lda     FireworksYPosData,y     ;get vertical position using same offset
c67a: 95 cf                        sta     Enemy_Y_Position,x      ;and store as vertical coordinate for fireworks object
c67c: a9 01                        lda     #$01
c67e: 95 b6                        sta     Enemy_Y_HighPos,x       ;store in vertical high byte
c680: 95 0f                        sta     Enemy_Flag,x            ;and activate enemy buffer flag
c682: 4a                           lsr     A
c683: 95 58                        sta     ExplosionGfxCounter,x   ;initialize explosion counter
c685: a9 08                        lda     #$08
c687: 95 a0                        sta     ExplosionTimerCounter,x ;set explosion timing counter
c689: 60           ExitFWk         rts

                   ; -----------------------------------------------------------------------------
c68a: 01           Bitmasks        .dd1    %00000001
c68b: 02                           .dd1    %00000010
c68c: 04                           .dd1    %00000100
c68d: 08                           .dd1    %00001000
c68e: 10                           .dd1    %00010000
c68f: 20                           .dd1    %00100000
c690: 40                           .dd1    %01000000
c691: 80                           .dd1    %10000000
c692: 40 30 90 50+ Enemy17YPosData .bulk   $40,$30,$90,$50,$20,$60,$a0,$70
c69a: 0a 0b        SwimCC_IDData   .bulk   $0a,$0b

                   BulletBillCheepCheep
c69c: ad 8f 07                     lda     FrenzyEnemyTimer        ;if timer not expired yet, branch to leave
c69f: d0 6f                        bne     ExF17
c6a1: ad 4e 07                     lda     AreaType                ;are we in a water-type level?
c6a4: d0 57                        bne     DoBulletBills           ;if not, branch elsewhere
c6a6: e0 03                        cpx     #$03                    ;are we past third enemy slot?
c6a8: b0 66                        bcs     ExF17                   ;if so, branch to leave
c6aa: a0 00                        ldy     #$00                    ;load default offset
c6ac: bd a7 07                     lda     PseudoRandomBitReg,x
c6af: c9 aa                        cmp     #$aa                    ;check first part of LSFR against preset value
c6b1: 90 01                        bcc     ChkW2                   ;if less than preset, do not increment offset
c6b3: c8                           iny                             ;otherwise increment
c6b4: ad 5f 07     ChkW2           lda     WorldNumber             ;check world number
c6b7: c9 01                        cmp     #World2
c6b9: f0 01                        beq     Get17ID                 ;if we're on world 2, do not increment offset
c6bb: c8                           iny                             ;otherwise increment
c6bc: 98           Get17ID         tya
c6bd: 29 01                        and     #%00000001              ;mask out all but last bit of offset
c6bf: a8                           tay
c6c0: b9 9a c6                     lda     SwimCC_IDData,y         ;load identifier for cheep-cheeps
c6c3: 95 16        Set17ID         sta     Enemy_ID,x              ;store whatever's in A as enemy identifier
c6c5: ad dd 06                     lda     BitMFilter
c6c8: c9 ff                        cmp     #$ff                    ;if not all bits set, skip init part and compare bits
c6ca: d0 05                        bne     GetRBit
c6cc: a9 00                        lda     #$00                    ;initialize vertical position filter
c6ce: 8d dd 06                     sta     BitMFilter
c6d1: bd a7 07     GetRBit         lda     PseudoRandomBitReg,x    ;get first part of LSFR
c6d4: 29 07                        and     #%00000111              ;mask out all but 3 LSB
c6d6: a8           ChkRBit         tay                             ;use as offset
c6d7: b9 8a c6                     lda     Bitmasks,y              ;load bitmask
c6da: 2c dd 06                     bit     BitMFilter              ;perform AND on filter without changing it
c6dd: f0 07                        beq     AddFBit
c6df: c8                           iny                             ;increment offset
c6e0: 98                           tya
c6e1: 29 07                        and     #%00000111              ;mask out all but 3 LSB thus keeping it 0-7
c6e3: 4c d6 c6                     jmp     ChkRBit                 ;do another check

c6e6: 0d dd 06     AddFBit         ora     BitMFilter              ;add bit to already set bits in filter
c6e9: 8d dd 06                     sta     BitMFilter              ;and store
c6ec: b9 92 c6                     lda     Enemy17YPosData,y       ;load vertical position using offset
c6ef: 20 d8 c5                     jsr     PutAtRightExtent        ;set vertical position and other values
c6f2: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;initialize dummy variable
c6f5: a9 20                        lda     #$20                    ;set timer
c6f7: 8d 8f 07                     sta     FrenzyEnemyTimer
c6fa: 4c 6c c2                     jmp     CheckpointEnemyID       ;process our new enemy object

c6fd: a0 ff        DoBulletBills   ldy     #$ff                    ;start at beginning of enemy slots
c6ff: c8           BB_SLoop        iny                             ;move onto the next slot
c700: c0 05                        cpy     #$05                    ;branch to play sound if we've done all slots
c702: b0 0d                        bcs     FireBulletBill
c704: b9 0f 00                     lda     Enemy_Flag,y            ;if enemy buffer flag not set,
c707: f0 f6                        beq     BB_SLoop                ; loop back and check another slot
c709: b9 16 00                     lda     Enemy_ID,y
c70c: c9 08                        cmp     #BulletBill_FrenzyVar   ;check enemy identifier for
c70e: d0 ef                        bne     BB_SLoop                ; bullet bill object (frenzy variant)
c710: 60           ExF17           rts                             ;if found, leave

c711: a5 fe        FireBulletBill  lda     Square2SoundQueue
c713: 09 08                        ora     #Sfx_Blast              ;play fireworks/gunfire sound
c715: 85 fe                        sta     Square2SoundQueue
c717: a9 08                        lda     #BulletBill_FrenzyVar   ;load identifier for bullet bill object
c719: d0 a8                        bne     Set17ID                 ;unconditional branch

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store Y position of group enemies
                   ; $01 - used to store enemy ID
                   ; $02 - used to store page location of right side of screen
                   ; $03 - used to store X position of right side of screen
                   HandleGroupEnemies
c71b: a0 00                        ldy     #$00                    ;load value for green koopa troopa
c71d: 38                           sec
c71e: e9 37                        sbc     #$37                    ;subtract $37 from second byte read
c720: 48                           pha                             ;save result in stack for now
c721: c9 04                        cmp     #$04                    ;was byte in $3b-$3e range?
c723: b0 0b                        bcs     SnglID                  ;if so, branch
c725: 48                           pha                             ;save another copy to stack
c726: a0 06                        ldy     #Goomba                 ;load value for goomba enemy
c728: ad 6a 07                     lda     PrimaryHardMode         ;if primary hard mode flag not set,
c72b: f0 02                        beq     PullID                  ; branch, otherwise change to value
c72d: a0 02                        ldy     #BuzzyBeetle            ; for buzzy beetle
c72f: 68           PullID          pla                             ;get second copy from stack
c730: 84 01        SnglID          sty     $01                     ;save enemy id here
c732: a0 b0                        ldy     #$b0                    ;load default y coordinate
c734: 29 02                        and     #$02                    ;check to see if d1 was set
c736: f0 02                        beq     SetYGp                  ;if so, move y coordinate up,
c738: a0 70                        ldy     #$70                    ; otherwise branch and use default
c73a: 84 00        SetYGp          sty     $00                     ;save y coordinate here
c73c: ad 1b 07                     lda     ScreenRight_PageLoc     ;get page number of right edge of screen
c73f: 85 02                        sta     $02                     ;save here
c741: ad 1d 07                     lda     ScreenRight_X_Pos       ;get pixel coordinate of right edge
c744: 85 03                        sta     $03                     ;save here
c746: a0 02                        ldy     #$02                    ;load two enemies by default
c748: 68                           pla                             ;get first copy from stack
c749: 4a                           lsr     A                       ;check to see if d0 was set
c74a: 90 01                        bcc     CntGrp                  ;if not, use default value
c74c: c8                           iny                             ;otherwise increment to three enemies
c74d: 8c d3 06     CntGrp          sty     NumberofGroupEnemies    ;save number of enemies here
c750: a2 ff        GrLoop          ldx     #$ff                    ;start at beginning of enemy buffers
c752: e8           GSltLp          inx                             ;increment and branch if past
c753: e0 05                        cpx     #$05                    ;end of buffers
c755: b0 2d                        bcs     NextED
c757: b5 0f                        lda     Enemy_Flag,x            ;check to see if enemy is already
c759: d0 f7                        bne     GSltLp                  ; stored in buffer, and branch if so
c75b: a5 01                        lda     $01
c75d: 95 16                        sta     Enemy_ID,x              ;store enemy object identifier
c75f: a5 02                        lda     $02
c761: 95 6e                        sta     Enemy_PageLoc,x         ;store page location for enemy object
c763: a5 03                        lda     $03
c765: 95 87                        sta     Enemy_X_Position,x      ;store x coordinate for enemy object
c767: 18                           clc
c768: 69 18                        adc     #$18                    ;add 24 pixels for next enemy
c76a: 85 03                        sta     $03
c76c: a5 02                        lda     $02                     ;add carry to page location for
c76e: 69 00                        adc     #$00                    ; next enemy
c770: 85 02                        sta     $02
c772: a5 00                        lda     $00                     ;store y coordinate for enemy object
c774: 95 cf                        sta     Enemy_Y_Position,x
c776: a9 01                        lda     #$01                    ;activate flag for buffer, and
c778: 95 b6                        sta     Enemy_Y_HighPos,x       ; put enemy within the screen vertically
c77a: 95 0f                        sta     Enemy_Flag,x
c77c: 20 6c c2                     jsr     CheckpointEnemyID       ;process each enemy object separately
c77f: ce d3 06                     dec     NumberofGroupEnemies    ;do this until we run out of enemy objects
c782: d0 cc                        bne     GrLoop
c784: 4c 5e c2     NextED          jmp     Inc2B                   ;jump to increment data offset and leave

                   ; -----------------------------------------------------------------------------
                   InitPiranhaPlant
c787: a9 01                        lda     #$01                    ;set initial speed
c789: 95 58                        sta     PiranhaPlant_Y_Speed,x
c78b: 4a                           lsr     A
c78c: 95 1e                        sta     Enemy_State,x           ;initialize enemy state and what would normally
c78e: 95 a0                        sta     PiranhaPlant_MoveFlag,x ; be used as vertical speed, but not in this case
c790: b5 cf                        lda     Enemy_Y_Position,x
c792: 9d 34 04                     sta     PiranhaPlantDownYPos,x  ;save original vertical coordinate here
c795: 38                           sec
c796: e9 18                        sbc     #$18
c798: 9d 17 04                     sta     PiranhaPlantUpYPos,x    ;save original vertical coordinate - 24 pixels here
c79b: a9 09                        lda     #$09
c79d: 4c db c7                     jmp     SetBBox2                ;set specific value for bounding box control

                   ; -----------------------------------------------------------------------------
c7a0: b5 16        InitEnemyFrenzy lda     Enemy_ID,x              ;load enemy identifier
c7a2: 8d cb 06                     sta     EnemyFrenzyBuffer       ;save in enemy frenzy buffer
c7a5: 38                           sec
c7a6: e9 12                        sbc     #$12                    ;subtract 12 and use as offset for jump engine
c7a8: 20 04 8e                     jsr     JumpEngine

c7ab: a4 c3                        .dd2    LakituAndSpinyHandler
c7ad: b7 c7                        .dd2    NoFrenzyCode
c7af: a8 c4                        .dd2    InitFlyingCheepCheep
c7b1: a3 c5                        .dd2    InitBowserFlame
c7b3: 3d c6                        .dd2    InitFireworks
c7b5: 9c c6                        .dd2    BulletBillCheepCheep

                   ; -----------------------------------------------------------------------------
c7b7: 60           NoFrenzyCode    rts

                   ; -----------------------------------------------------------------------------
c7b8: a0 05        EndFrenzy       ldy     #$05                    ;start at last slot
c7ba: b9 16 00     LakituChk       lda     Enemy_ID,y              ;check enemy identifiers
c7bd: c9 11                        cmp     #Lakitu                 ; for lakitu
c7bf: d0 05                        bne     NextFSlot
c7c1: a9 01                        lda     #$01                    ;if found, set state
c7c3: 99 1e 00                     sta     Enemy_State,y
c7c6: 88           NextFSlot       dey                             ;move onto the next slot
c7c7: 10 f1                        bpl     LakituChk               ;do this until all slots are checked
c7c9: a9 00                        lda     #$00
c7cb: 8d cb 06                     sta     EnemyFrenzyBuffer       ;empty enemy frenzy buffer
c7ce: 95 0f                        sta     Enemy_Flag,x            ;disable enemy buffer flag for this object
c7d0: 60                           rts

                   ; -----------------------------------------------------------------------------
                   InitJumpGPTroopa
c7d1: a9 02                        lda     #$02                    ;set for movement to the left
c7d3: 95 46                        sta     Enemy_MovingDir,x
c7d5: a9 f8                        lda     #$f8                    ;set horizontal speed
c7d7: 95 58                        sta     Enemy_X_Speed,x
c7d9: a9 03        TallBBox2       lda     #$03                    ;set specific value for bounding box control
c7db: 9d 9a 04     SetBBox2        sta     Enemy_BoundBoxCtrl,x    ;set bounding box control then leave
c7de: 60                           rts

                   ; -----------------------------------------------------------------------------
c7df: d6 cf        InitBalPlatform dec     Enemy_Y_Position,x      ;raise vertical position by two pixels
c7e1: d6 cf                        dec     Enemy_Y_Position,x
c7e3: ac cc 06                     ldy     SecondaryHardMode       ;if secondary hard mode flag not set,
c7e6: d0 05                        bne     AlignP                  ;branch ahead
c7e8: a0 02                        ldy     #$02                    ;otherwise set value here
c7ea: 20 71 c8                     jsr     PosPlatform             ;do a sub to add or subtract pixels
c7ed: a0 ff        AlignP          ldy     #$ff                    ;set default value here for now
c7ef: ad a0 03                     lda     BalPlatformAlignment    ;get current balance platform alignment
c7f2: 95 1e                        sta     Enemy_State,x           ;set platform alignment to object state here
c7f4: 10 02                        bpl     SetBPA                  ;if old alignment $ff, put $ff as alignment for negative
c7f6: 8a                           txa                             ;if old contents already $ff, put
c7f7: a8                           tay                             ;object offset as alignment to make next positive
c7f8: 8c a0 03     SetBPA          sty     BalPlatformAlignment    ;store whatever value's in Y here
c7fb: a9 00                        lda     #$00
c7fd: 95 46                        sta     Enemy_MovingDir,x       ;init moving direction
c7ff: a8                           tay                             ;init Y
c800: 20 71 c8                     jsr     PosPlatform             ;do a sub to add 8 pixels, then run shared code here
                   ; 
                   InitDropPlatform
c803: a9 ff                        lda     #$ff
c805: 9d a2 03                     sta     PlatformCollisionFlag,x ;set some value here
c808: 4c 28 c8                     jmp     CommonPlatCode          ;then jump ahead to execute more code

                   ; -----------------------------------------------------------------------------
                   InitHoriPlatform
c80b: a9 00                        lda     #$00
c80d: 95 58                        sta     XMoveSecondaryCounter,x ;init one of the moving counters
c80f: 4c 28 c8                     jmp     CommonPlatCode          ;jump ahead to execute more code

                   ; -----------------------------------------------------------------------------
                   InitVertPlatform
c812: a0 40                        ldy     #$40                    ;set default value here
c814: b5 cf                        lda     Enemy_Y_Position,x      ;check vertical position
c816: 10 07                        bpl     SetYO                   ;if above a certain point, skip this part
c818: 49 ff                        eor     #$ff
c81a: 18                           clc                             ;otherwise get two's compliment
c81b: 69 01                        adc     #$01
c81d: a0 c0                        ldy     #$c0                    ;get alternate value to add to vertical position
c81f: 9d 01 04     SetYO           sta     YPlatformTopYPos,x      ;save as top vertical position
c822: 98                           tya
c823: 18                           clc                             ;load value from earlier, add number of pixels 
c824: 75 cf                        adc     Enemy_Y_Position,x      ; to vertical position
c826: 95 58                        sta     YPlatformCenterYPos,x   ;save result as central vertical position
                   ; 
c828: 20 63 c3     CommonPlatCode  jsr     InitVStf                ;do a sub to init certain other values 
c82b: a9 05        SPBBox          lda     #$05                    ;set default bounding box size control
c82d: ac 4e 07                     ldy     AreaType
c830: c0 03                        cpy     #$03                    ;check for castle-type level
c832: f0 07                        beq     CasPBB                  ;use default value if found
c834: ac cc 06                     ldy     SecondaryHardMode       ;otherwise check for secondary hard mode flag
c837: d0 02                        bne     CasPBB                  ;if set, use default value
c839: a9 06                        lda     #$06                    ;use alternate value if not castle or secondary not set
c83b: 9d 9a 04     CasPBB          sta     Enemy_BoundBoxCtrl,x    ;set bounding box size control here and leave
c83e: 60                           rts

                   ; -----------------------------------------------------------------------------
c83f: 20 4b c8     LargeLiftUp     jsr     PlatLiftUp              ;execute code for platforms going up
c842: 4c 48 c8                     jmp     LargeLiftBBox           ;overwrite bounding box for large platforms

c845: 20 57 c8     LargeLiftDown   jsr     PlatLiftDown            ;execute code for platforms going down
c848: 4c 2b c8     LargeLiftBBox   jmp     SPBBox                  ;jump to overwrite bounding box size control

                   ; -----------------------------------------------------------------------------
c84b: a9 10        PlatLiftUp      lda     #$10                    ;set movement amount here
c84d: 9d 34 04                     sta     Enemy_Y_MoveForce,x
c850: a9 ff                        lda     #$ff                    ;set moving speed for platforms going up
c852: 95 a0                        sta     BlooperMoveCounter,x
c854: 4c 60 c8                     jmp     CommonSmallLift         ;skip ahead to part we should be executing

                   ; -----------------------------------------------------------------------------
c857: a9 f0        PlatLiftDown    lda     #$f0                    ;set movement amount here
c859: 9d 34 04                     sta     Enemy_Y_MoveForce,x
c85c: a9 00                        lda     #$00                    ;set moving speed for platforms going down
c85e: 95 a0                        sta     Enemy_Y_Speed,x
                   ; 
c860: a0 01        CommonSmallLift ldy     #$01
c862: 20 71 c8                     jsr     PosPlatform             ;do a sub to add 12 pixels due to preset value 
c865: a9 04                        lda     #$04
c867: 9d 9a 04                     sta     Enemy_BoundBoxCtrl,x    ;set bounding box control for small platforms
c86a: 60                           rts

                   ; -----------------------------------------------------------------------------
c86b: 08 0c f8     PlatPosDataLow  .bulk   $08,$0c,$f8
c86e: 00 00 ff     PlatPosDataHigh .bulk   $00,$00,$ff

c871: b5 87        PosPlatform     lda     Enemy_X_Position,x      ;get horizontal coordinate
c873: 18                           clc
c874: 79 6b c8                     adc     PlatPosDataLow,y        ;add or subtract pixels depending on offset
c877: 95 87                        sta     Enemy_X_Position,x      ;store as new horizontal coordinate
c879: b5 6e                        lda     Enemy_PageLoc,x
c87b: 79 6e c8                     adc     PlatPosDataHigh,y       ;add or subtract page location depending on offset
c87e: 95 6e                        sta     Enemy_PageLoc,x         ;store as new page location
c880: 60                           rts                             ;and go back

                   ; -----------------------------------------------------------------------------
                   EndOFEnemyInitCode
c881: 60                           rts

                   ; -----------------------------------------------------------------------------
                   RunEnemyObjectsCore
c882: a6 08                        ldx     ObjectOffset            ;get offset for enemy object buffer
c884: a9 00                        lda     #$00                    ;load value 0 for jump engine by default
c886: b4 16                        ldy     Enemy_ID,x
c888: c0 15                        cpy     #$15                    ;if enemy object < $15, use default value
c88a: 90 03                        bcc     JmpEO
c88c: 98                           tya                             ;otherwise subtract $14 from the value and use
c88d: e9 14                        sbc     #$14                    ; as value for jump engine
c88f: 20 04 8e     JmpEO           jsr     JumpEngine

c892: e0 c8                        .dd2    RunNormalEnemies        ;for objects $00-$14
c894: 35 c9                        .dd2    RunBowserFlame          ;for objects $15-$1f
c896: 95 d2                        .dd2    RunFireworks
c898: d6 c8                        .dd2    NoRunCode
c89a: d6 c8                        .dd2    NoRunCode
c89c: d6 c8                        .dd2    NoRunCode
c89e: d6 c8                        .dd2    NoRunCode
c8a0: 47 c9                        .dd2    RunFirebarObj
c8a2: 47 c9                        .dd2    RunFirebarObj
c8a4: 47 c9                        .dd2    RunFirebarObj
c8a6: 47 c9                        .dd2    RunFirebarObj
c8a8: 47 c9                        .dd2    RunFirebarObj
c8aa: 47 c9                        .dd2    RunFirebarObj           ;for objects $20-$2f
c8ac: 47 c9                        .dd2    RunFirebarObj
c8ae: 47 c9                        .dd2    RunFirebarObj
c8b0: d6 c8                        .dd2    NoRunCode
c8b2: 65 c9                        .dd2    RunLargePlatform
c8b4: 65 c9                        .dd2    RunLargePlatform
c8b6: 65 c9                        .dd2    RunLargePlatform
c8b8: 65 c9                        .dd2    RunLargePlatform
c8ba: 65 c9                        .dd2    RunLargePlatform
c8bc: 65 c9                        .dd2    RunLargePlatform
c8be: 65 c9                        .dd2    RunLargePlatform
c8c0: 4d c9                        .dd2    RunSmallPlatform
c8c2: 4d c9                        .dd2    RunSmallPlatform
c8c4: 65 d0                        .dd2    RunBowser
c8c6: 85 bc                        .dd2    PowerUpObjHandler
c8c8: 4b b9                        .dd2    VineObjectHandler
c8ca: d6 c8                        .dd2    NoRunCode               ;for objects $30-$35
c8cc: d9 d2                        .dd2    RunStarFlagObj
c8ce: ba b8                        .dd2    JumpspringHandler
c8d0: d6 c8                        .dd2    NoRunCode
c8d2: a4 b7                        .dd2    WarpZoneObject
c8d4: d7 c8                        .dd2    RunRetainerObj

                   ; -----------------------------------------------------------------------------
c8d6: 60           NoRunCode       rts

                   ; -----------------------------------------------------------------------------
c8d7: 20 af f1     RunRetainerObj  jsr     GetEnemyOffscreenBits
c8da: 20 52 f1                     jsr     RelativeEnemyPosition
c8dd: 4c 7d e8                     jmp     EnemyGfxHandler

                   ; -----------------------------------------------------------------------------
                   RunNormalEnemies
c8e0: a9 00                        lda     #$00                    ;init sprite attributes
c8e2: 9d c5 03                     sta     Enemy_SprAttrib,x
c8e5: 20 af f1                     jsr     GetEnemyOffscreenBits
c8e8: 20 52 f1                     jsr     RelativeEnemyPosition
c8eb: 20 7d e8                     jsr     EnemyGfxHandler
c8ee: 20 43 e2                     jsr     GetEnemyBoundBox
c8f1: 20 c1 df                     jsr     EnemyToBGCollisionDet
c8f4: 20 33 da                     jsr     EnemiesCollision
c8f7: 20 53 d8                     jsr     PlayerEnemyCollision
c8fa: ac 47 07                     ldy     TimerControl            ;if master timer control set, skip to last routine
c8fd: d0 03                        bne     SkipMove
c8ff: 20 05 c9                     jsr     EnemyMovementSubs
c902: 4c 7a d6     SkipMove        jmp     OffscreenBoundsCheck

                   ; -----------------------------------------------------------------------------
                   EnemyMovementSubs
c905: b5 16                        lda     Enemy_ID,x
c907: 20 04 8e                     jsr     JumpEngine

c90a: 77 ca                        .dd2    MoveNormalEnemy         ;only objects $00-$14 use this table
c90c: 77 ca                        .dd2    MoveNormalEnemy
c90e: 77 ca                        .dd2    MoveNormalEnemy
c910: 77 ca                        .dd2    MoveNormalEnemy
c912: 77 ca                        .dd2    MoveNormalEnemy
c914: d8 c9                        .dd2    ProcHammerBro
c916: 77 ca                        .dd2    MoveNormalEnemy
c918: 89 cb                        .dd2    MoveBloober
c91a: 36 cc                        .dd2    MoveBulletBill
c91c: 34 c9                        .dd2    NoMoveCode
c91e: 4a cc                        .dd2    MoveSwimmingCheepCheep
c920: 4a cc                        .dd2    MoveSwimmingCheepCheep
c922: b0 c9                        .dd2    MovePodoboo
c924: b0 d3                        .dd2    MovePiranhaPlant
c926: f9 ca                        .dd2    MoveJumpingEnemy
c928: ff ca                        .dd2    ProcMoveRedPTroopa
c92a: 25 cb                        .dd2    MoveFlyGreenPTroopa
c92c: 28 cf                        .dd2    MoveLakitu
c92e: 77 ca                        .dd2    MoveNormalEnemy
c930: 34 c9                        .dd2    NoMoveCode              ;dummy
c932: df ce                        .dd2    MoveFlyingCheepCheep

                   ; -----------------------------------------------------------------------------
c934: 60           NoMoveCode      rts

                   ; -----------------------------------------------------------------------------
c935: 20 eb d1     RunBowserFlame  jsr     ProcBowserFlame
c938: 20 af f1                     jsr     GetEnemyOffscreenBits
c93b: 20 52 f1                     jsr     RelativeEnemyPosition
c93e: 20 43 e2                     jsr     GetEnemyBoundBox
c941: 20 53 d8                     jsr     PlayerEnemyCollision
c944: 4c 7a d6                     jmp     OffscreenBoundsCheck

                   ; -----------------------------------------------------------------------------
c947: 20 3c cd     RunFirebarObj   jsr     ProcFirebar
c94a: 4c 7a d6                     jmp     OffscreenBoundsCheck

                   ; -----------------------------------------------------------------------------
                   RunSmallPlatform
c94d: 20 af f1                     jsr     GetEnemyOffscreenBits
c950: 20 52 f1                     jsr     RelativeEnemyPosition
c953: 20 4c e2                     jsr     SmallPlatformBoundBox
c956: 20 7b db                     jsr     SmallPlatformCollision
c959: 20 52 f1                     jsr     RelativeEnemyPosition
c95c: 20 66 ed                     jsr     DrawSmallPlatform
c95f: 20 55 d6                     jsr     MoveSmallPlatform
c962: 4c 7a d6                     jmp     OffscreenBoundsCheck

                   ; -----------------------------------------------------------------------------
                   RunLargePlatform
c965: 20 af f1                     jsr     GetEnemyOffscreenBits
c968: 20 52 f1                     jsr     RelativeEnemyPosition
c96b: 20 73 e2                     jsr     LargePlatformBoundBox
c96e: 20 45 db                     jsr     LargePlatformCollision
c971: ad 47 07                     lda     TimerControl            ;if master timer control set,
c974: d0 03                        bne     SkipPT                  ; skip subroutine tree
c976: 20 82 c9                     jsr     LargePlatformSubroutines
c979: 20 52 f1     SkipPT          jsr     RelativeEnemyPosition
c97c: 20 c8 e5                     jsr     DrawLargePlatform
c97f: 4c 7a d6                     jmp     OffscreenBoundsCheck

                   ; -----------------------------------------------------------------------------
                   LargePlatformSubroutines
c982: b5 16                        lda     Enemy_ID,x              ;subtract $24 to get proper offset for jump table
c984: 38                           sec
c985: e9 24                        sbc     #$24
c987: 20 04 8e                     jsr     JumpEngine

c98a: 32 d4                        .dd2    BalancePlatform         ;table used by objects $24-$2a
c98c: d3 d5                        .dd2    YMovingPlatform
c98e: 4f d6                        .dd2    MoveLargeLiftPlat
c990: 4f d6                        .dd2    MoveLargeLiftPlat
c992: 07 d6                        .dd2    XMovingPlatform
c994: 31 d6                        .dd2    DropPlatform
c996: 3d d6                        .dd2    RightPlatform

                   ; -----------------------------------------------------------------------------
                   EraseEnemyObject
c998: a9 00                        lda     #$00                    ;clear all enemy object variables
c99a: 95 0f                        sta     Enemy_Flag,x
c99c: 95 16                        sta     Enemy_ID,x
c99e: 95 1e                        sta     Enemy_State,x
c9a0: 9d 10 01                     sta     FloateyNum_Control,x
c9a3: 9d 96 07                     sta     EnemyIntervalTimer,x
c9a6: 9d 25 01                     sta     ShellChainCounter,x
c9a9: 9d c5 03                     sta     Enemy_SprAttrib,x
c9ac: 9d 8a 07                     sta     EnemyFrameTimer,x
c9af: 60                           rts

                   ; -----------------------------------------------------------------------------
c9b0: bd 96 07     MovePodoboo     lda     EnemyIntervalTimer,x    ;check enemy timer
c9b3: d0 16                        bne     PdbM                    ;branch to move enemy if not expired
c9b5: 20 f7 c2                     jsr     InitPodoboo             ;otherwise set up podoboo again
c9b8: bd a8 07                     lda     PseudoRandomBitReg+1,x  ;get part of LSFR
c9bb: 09 80                        ora     #%10000000              ;set d7
c9bd: 9d 34 04                     sta     Enemy_Y_MoveForce,x     ;store as movement force
c9c0: 29 0f                        and     #%00001111              ;mask out high nybble
c9c2: 09 06                        ora     #$06                    ;set for at least six intervals
c9c4: 9d 96 07                     sta     EnemyIntervalTimer,x    ;store as new enemy timer
c9c7: a9 f9                        lda     #$f9
c9c9: 95 a0                        sta     BlooperMoveCounter,x    ;set vertical speed to move podoboo upwards
c9cb: 4c 92 bf     PdbM            jmp     MoveJ_EnemyVertically   ;branch to impose gravity on podoboo

                   ; -----------------------------------------------------------------------------
                   ; $00 - used in HammerBroJumpCode as bitmask
                   HammerThrowTmrData
c9ce: 30 1c                        .bulk   $30,$1c
c9d0: 00 e8 00 18  XSpeedAdderData .bulk   $00,$e8,$00,$18
c9d4: 08 f8 0c f4  RevivedXSpeed   .bulk   $08,$f8,$0c,$f4

c9d8: b5 1e        ProcHammerBro   lda     Enemy_State,x           ;check hammer bro's enemy state for d5 set
c9da: 29 20                        and     #%00100000
c9dc: f0 03                        beq     ChkJH                   ;if not set, go ahead with code
c9de: 4c e5 ca                     jmp     MoveDefeatedEnemy       ;otherwise jump to something else

c9e1: b5 3c        ChkJH           lda     HammerBroJumpTimer,x    ;check jump timer
c9e3: f0 2d                        beq     HammerBroJumpCode       ;if expired, branch to jump
c9e5: d6 3c                        dec     HammerBroJumpTimer,x    ;otherwise decrement jump timer
c9e7: ad d1 03                     lda     Enemy_OffscreenBits
c9ea: 29 0c                        and     #%00001100              ;check offscreen bits
c9ec: d0 6a                        bne     MoveHammerBroXDir       ;if hammer bro a little offscreen, skip to movement code
c9ee: bd a2 03                     lda     HammerThrowingTimer,x   ;check hammer throwing timer
c9f1: d0 17                        bne     DecHT                   ;if not expired, skip ahead, do not throw hammer
c9f3: ac cc 06                     ldy     SecondaryHardMode       ;otherwise get secondary hard mode flag
c9f6: b9 ce c9                     lda     HammerThrowTmrData,y    ;get timer data using flag as offset
c9f9: 9d a2 03                     sta     HammerThrowingTimer,x   ;set as new timer
c9fc: 20 94 ba                     jsr     SpawnHammerObj          ;do a sub here to spawn hammer object
c9ff: 90 09                        bcc     DecHT                   ;if carry clear, hammer not spawned, skip to decrement timer
ca01: b5 1e                        lda     Enemy_State,x
ca03: 09 08                        ora     #%00001000              ;set d3 in enemy state for hammer throw
ca05: 95 1e                        sta     Enemy_State,x
ca07: 4c 58 ca                     jmp     MoveHammerBroXDir       ;jump to move hammer bro

ca0a: de a2 03     DecHT           dec     HammerThrowingTimer,x   ;decrement timer
ca0d: 4c 58 ca                     jmp     MoveHammerBroXDir       ;jump to move hammer bro

                   HammerBroJumpLData
ca10: 20 37                        .bulk   $20,$37

                   HammerBroJumpCode
ca12: b5 1e                        lda     Enemy_State,x           ;get hammer bro's enemy state
ca14: 29 07                        and     #%00000111              ;mask out all but 3 LSB
ca16: c9 01                        cmp     #$01                    ;check for d0 set (for jumping)
ca18: f0 3e                        beq     MoveHammerBroXDir       ;if set, branch ahead to moving code
ca1a: a9 00                        lda     #$00                    ;load default value here
ca1c: 85 00                        sta     $00                     ;save into temp variable for now
ca1e: a0 fa                        ldy     #$fa                    ;set default vertical speed
ca20: b5 cf                        lda     Enemy_Y_Position,x      ;check hammer bro's vertical coordinate
ca22: 30 13                        bmi     SetHJ                   ;if on the bottom half of the screen, use current speed
ca24: a0 fd                        ldy     #$fd                    ;otherwise set alternate vertical speed
ca26: c9 70                        cmp     #$70                    ;check to see if hammer bro is above the middle of screen
ca28: e6 00                        inc     $00                     ;increment preset value to $01
ca2a: 90 0b                        bcc     SetHJ                   ;if above the middle of the screen, use current speed and $01
ca2c: c6 00                        dec     $00                     ;otherwise return value to $00
ca2e: bd a8 07                     lda     PseudoRandomBitReg+1,x  ;get part of LSFR, mask out all but LSB
ca31: 29 01                        and     #$01
ca33: d0 02                        bne     SetHJ                   ;if d0 of LSFR set, branch and use current speed and $00
ca35: a0 fa                        ldy     #$fa                    ;otherwise reset to default vertical speed
ca37: 94 a0        SetHJ           sty     Enemy_Y_Speed,x         ;set vertical speed for jumping
ca39: b5 1e                        lda     Enemy_State,x           ;set d0 in enemy state for jumping
ca3b: 09 01                        ora     #$01
ca3d: 95 1e                        sta     Enemy_State,x
ca3f: a5 00                        lda     $00                     ;load preset value here to use as bitmask
ca41: 3d a9 07                     and     PseudoRandomBitReg+2,x  ;and do bit-wise comparison with part of LSFR
ca44: a8                           tay                             ;then use as offset
ca45: ad cc 06                     lda     SecondaryHardMode       ;check secondary hard mode flag
ca48: d0 01                        bne     HJump
ca4a: a8                           tay                             ;if secondary hard mode flag clear, set offset to 0
ca4b: b9 10 ca     HJump           lda     HammerBroJumpLData,y    ;get jump length timer data using offset from before
ca4e: 9d 8a 07                     sta     EnemyFrameTimer,x       ;save in enemy timer
ca51: bd a8 07                     lda     PseudoRandomBitReg+1,x
ca54: 09 c0                        ora     #%11000000              ;get contents of part of LSFR, set d7 and d6, then
ca56: 95 3c                        sta     HammerBroJumpTimer,x    ;store in jump timer
                   MoveHammerBroXDir
ca58: a0 fc                        ldy     #$fc                    ;move hammer bro a little to the left
ca5a: a5 09                        lda     FrameCounter
ca5c: 29 40                        and     #%01000000              ;change hammer bro's direction every 64 frames
ca5e: d0 02                        bne     Shimmy
ca60: a0 04                        ldy     #$04                    ;if d6 set in counter, move him a little to the right
ca62: 94 58        Shimmy          sty     Enemy_X_Speed,x         ;store horizontal speed
ca64: a0 01                        ldy     #$01                    ;set to face right by default
ca66: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and hammer bro
ca69: 30 0a                        bmi     SetShim                 ;if enemy to the left of player, skip this part
ca6b: c8                           iny                             ;set to face left
ca6c: bd 96 07                     lda     EnemyIntervalTimer,x    ;check walking timer
ca6f: d0 04                        bne     SetShim                 ;if not yet expired, skip to set moving direction
ca71: a9 f8                        lda     #$f8
ca73: 95 58                        sta     Enemy_X_Speed,x         ;otherwise, make the hammer bro walk left towards player
ca75: 94 46        SetShim         sty     Enemy_MovingDir,x       ;set moving direction
                   ; 
ca77: a0 00        MoveNormalEnemy ldy     #$00                    ;init Y to leave horizontal movement as-is 
ca79: b5 1e                        lda     Enemy_State,x
ca7b: 29 40                        and     #%01000000              ;check enemy state for d6 set, if set skip
ca7d: d0 19                        bne     FallE                   ; to move enemy vertically, then horizontally if necessary
ca7f: b5 1e                        lda     Enemy_State,x
ca81: 0a                           asl     A                       ;check enemy state for d7 set
ca82: b0 30                        bcs     SteadM                  ;if set, branch to move enemy horizontally
ca84: b5 1e                        lda     Enemy_State,x
ca86: 29 20                        and     #%00100000              ;check enemy state for d5 set
ca88: d0 5b                        bne     MoveDefeatedEnemy       ;if set, branch to move defeated enemy object
ca8a: b5 1e                        lda     Enemy_State,x
ca8c: 29 07                        and     #%00000111              ;check d2-d0 of enemy state for any set bits
ca8e: f0 24                        beq     SteadM                  ;if enemy in normal state, branch to move enemy horizontally
ca90: c9 05                        cmp     #$05
ca92: f0 04                        beq     FallE                   ;if enemy in state used by spiny's egg, go ahead here
ca94: c9 03                        cmp     #$03
ca96: b0 30                        bcs     ReviveStunned           ;if enemy in states $03 or $04, skip ahead to yet another part
ca98: 20 63 bf     FallE           jsr     MoveD_EnemyVertically   ;do a sub here to move enemy downwards
ca9b: a0 00                        ldy     #$00
ca9d: b5 1e                        lda     Enemy_State,x           ;check for enemy state $02
ca9f: c9 02                        cmp     #$02
caa1: f0 0c                        beq     MEHor                   ;if found, branch to move enemy horizontally
caa3: 29 40                        and     #%01000000              ;check for d6 set
caa5: f0 0d                        beq     SteadM                  ;if not set, branch to something else
caa7: b5 16                        lda     Enemy_ID,x
caa9: c9 2e                        cmp     #PowerUpObject          ;check for power-up object
caab: f0 07                        beq     SteadM
caad: d0 03                        bne     SlowM                   ;if any other object where d6 set, jump to set Y

caaf: 4c 02 bf     MEHor           jmp     MoveEnemyHorizontally   ;jump here to move enemy horizontally for <> $2e and d6 set

cab2: a0 01        SlowM           ldy     #$01                    ;if branched here, increment Y to slow horizontal movement
cab4: b5 58        SteadM          lda     Enemy_X_Speed,x         ;get current horizontal speed
cab6: 48                           pha                             ;save to stack
cab7: 10 02                        bpl     AddHS                   ;if not moving or moving right, skip, leave Y alone
cab9: c8                           iny
caba: c8                           iny                             ;otherwise increment Y to next data
cabb: 18           AddHS           clc
cabc: 79 d0 c9                     adc     XSpeedAdderData,y       ;add value here to slow enemy down if necessary
cabf: 95 58                        sta     Enemy_X_Speed,x         ;save as horizontal speed temporarily
cac1: 20 02 bf                     jsr     MoveEnemyHorizontally   ;then do a sub to move horizontally
cac4: 68                           pla
cac5: 95 58                        sta     Enemy_X_Speed,x         ;get old horizontal speed from stack and return to
cac7: 60                           rts                             ; original memory location, then leave

cac8: bd 96 07     ReviveStunned   lda     EnemyIntervalTimer,x    ;if enemy timer not expired yet,
cacb: d0 1e                        bne     ChkKillGoomba           ; skip ahead to something else
cacd: 95 1e                        sta     Enemy_State,x           ;otherwise initialize enemy state to normal
cacf: a5 09                        lda     FrameCounter
cad1: 29 01                        and     #$01                    ;get d0 of frame counter
cad3: a8                           tay                             ;use as Y and increment for movement direction
cad4: c8                           iny
cad5: 94 46                        sty     Enemy_MovingDir,x       ;store as pseudorandom movement direction
cad7: 88                           dey                             ;decrement for use as pointer
cad8: ad 6a 07                     lda     PrimaryHardMode         ;check primary hard mode flag
cadb: f0 02                        beq     SetRSpd                 ;if not set, use pointer as-is
cadd: c8                           iny
cade: c8                           iny                             ;otherwise increment 2 bytes to next data
cadf: b9 d4 c9     SetRSpd         lda     RevivedXSpeed,y         ;load and store new horizontal speed
cae2: 95 58                        sta     Enemy_X_Speed,x         ;and leave
cae4: 60                           rts

                   MoveDefeatedEnemy
cae5: 20 63 bf                     jsr     MoveD_EnemyVertically   ;execute sub to move defeated enemy downwards
cae8: 4c 02 bf                     jmp     MoveEnemyHorizontally   ;now move defeated enemy horizontally

caeb: c9 0e        ChkKillGoomba   cmp     #$0e                    ;check to see if enemy timer has reached
caed: d0 09                        bne     HKGmba                  ; a certain point, and branch to leave if not
caef: b5 16                        lda     Enemy_ID,x
caf1: c9 06                        cmp     #Goomba                 ;check for goomba object
caf3: d0 03                        bne     HKGmba                  ;branch if not found
caf5: 20 98 c9                     jsr     EraseEnemyObject        ;otherwise, kill this goomba object
caf8: 60           HKGmba          rts                             ;leave!

                   ; -----------------------------------------------------------------------------
                   MoveJumpingEnemy
caf9: 20 92 bf                     jsr     MoveJ_EnemyVertically   ;do a sub to impose gravity on green paratroopa
cafc: 4c 02 bf                     jmp     MoveEnemyHorizontally   ;jump to move enemy horizontally

                   ; -----------------------------------------------------------------------------
                   ProcMoveRedPTroopa
caff: b5 a0                        lda     Enemy_Y_Speed,x
cb01: 1d 34 04                     ora     Enemy_Y_MoveForce,x     ;check for any vertical force or speed
cb04: d0 13                        bne     MoveRedPTUpOrDown       ;branch if any found
cb06: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;initialize something here
cb09: b5 cf                        lda     Enemy_Y_Position,x      ;check current vs. original vertical coordinate
cb0b: dd 01 04                     cmp     RedPTroopaOrigXPos,x
cb0e: b0 09                        bcs     MoveRedPTUpOrDown       ;if current => original, skip ahead to more code
cb10: a5 09                        lda     FrameCounter            ;get frame counter
cb12: 29 07                        and     #%00000111              ;mask out all but 3 LSB
cb14: d0 02                        bne     NoIncPT                 ;if any bits set, branch to leave
cb16: f6 cf                        inc     Enemy_Y_Position,x      ;otherwise increment red paratroopa's vertical position
cb18: 60           NoIncPT         rts                             ;leave

                   MoveRedPTUpOrDown
cb19: b5 cf                        lda     Enemy_Y_Position,x      ;check current vs. central vertical coordinate
cb1b: d5 58                        cmp     RedPTroopaCenterYPos,x
cb1d: 90 03                        bcc     MovPTDwn                ;if current < central, jump to move downwards
cb1f: 4c 75 bf                     jmp     MoveRedPTroopaUp        ;otherwise jump to move upwards

cb22: 4c 70 bf     MovPTDwn        jmp     MoveRedPTroopaDown      ;move downwards

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store adder for movement, also used as adder for platform
                   ; $01 - used to store maximum value for secondary counter
                   MoveFlyGreenPTroopa
cb25: 20 45 cb                     jsr     XMoveCntr_GreenPTroopa  ;do sub to increment primary and secondary counters
cb28: 20 66 cb                     jsr     MoveWithXMCntrs         ;do sub to move green paratroopa accordingly, and horizontally
cb2b: a0 01                        ldy     #$01                    ;set Y to move green paratroopa down
cb2d: a5 09                        lda     FrameCounter
cb2f: 29 03                        and     #%00000011              ;check frame counter 2 LSB for any bits set
cb31: d0 11                        bne     NoMGPT                  ;branch to leave if set to move up/down every fourth frame
cb33: a5 09                        lda     FrameCounter
cb35: 29 40                        and     #%01000000              ;check frame counter for d6 set
cb37: d0 02                        bne     YSway                   ;branch to move green paratroopa down if set
cb39: a0 ff                        ldy     #$ff                    ;otherwise set Y to move green paratroopa up
cb3b: 84 00        YSway           sty     $00                     ;store adder here
cb3d: b5 cf                        lda     Enemy_Y_Position,x
cb3f: 18                           clc                             ;add or subtract from vertical position
cb40: 65 00                        adc     $00                     ; to give green paratroopa a wavy flight
cb42: 95 cf                        sta     Enemy_Y_Position,x
cb44: 60           NoMGPT          rts                             ;leave!

                   XMoveCntr_GreenPTroopa
cb45: a9 13                        lda     #$13                    ;load preset maximum value for secondary counter
                   ; 
                   XMoveCntr_Platform
cb47: 85 01                        sta     $01                     ;store value here
cb49: a5 09                        lda     FrameCounter
cb4b: 29 03                        and     #%00000011              ;branch to leave if not on
cb4d: d0 0d                        bne     NoIncXM                 ;every fourth frame
cb4f: b4 58                        ldy     XMoveSecondaryCounter,x ;get secondary counter
cb51: b5 a0                        lda     XMovePrimaryCounter,x   ;get primary counter
cb53: 4a                           lsr     A
cb54: b0 0a                        bcs     DecSeXM                 ;if d0 of primary counter set, branch elsewhere
cb56: c4 01                        cpy     $01                     ;compare secondary counter to preset maximum value
cb58: f0 03                        beq     IncPXM                  ;if equal, branch ahead of this part
cb5a: f6 58                        inc     XMoveSecondaryCounter,x ;increment secondary counter and leave
cb5c: 60           NoIncXM         rts

cb5d: f6 a0        IncPXM          inc     XMovePrimaryCounter,x   ;increment primary counter and leave
cb5f: 60                           rts

cb60: 98           DecSeXM         tya                             ;put secondary counter in A
cb61: f0 fa                        beq     IncPXM                  ;if secondary counter at zero, branch back
cb63: d6 58                        dec     XMoveSecondaryCounter,x ;otherwise decrement secondary counter and leave
cb65: 60                           rts

cb66: b5 58        MoveWithXMCntrs lda     XMoveSecondaryCounter,x ;save secondary counter to stack
cb68: 48                           pha
cb69: a0 01                        ldy     #$01                    ;set value here by default
cb6b: b5 a0                        lda     XMovePrimaryCounter,x
cb6d: 29 02                        and     #%00000010              ;if d1 of primary counter is
cb6f: d0 0b                        bne     XMRight                 ; set, branch ahead of this part here
cb71: b5 58                        lda     XMoveSecondaryCounter,x
cb73: 49 ff                        eor     #$ff                    ;otherwise change secondary
cb75: 18                           clc                             ;counter to two's compliment
cb76: 69 01                        adc     #$01
cb78: 95 58                        sta     XMoveSecondaryCounter,x
cb7a: a0 02                        ldy     #$02                    ;load alternate value here
cb7c: 94 46        XMRight         sty     Enemy_MovingDir,x       ;store as moving direction
cb7e: 20 02 bf                     jsr     MoveEnemyHorizontally
cb81: 85 00                        sta     $00                     ;save value obtained from sub here
cb83: 68                           pla                             ;get secondary counter from stack
cb84: 95 58                        sta     XMoveSecondaryCounter,x ; and return to original place
cb86: 60                           rts

                   ; -----------------------------------------------------------------------------
cb87: 3f           BlooberBitmasks .dd1    %00111111
cb88: 03                           .dd1    %00000011

cb89: b5 1e        MoveBloober     lda     Enemy_State,x
cb8b: 29 20                        and     #%00100000              ;check enemy state for d5 set
cb8d: d0 4d                        bne     MoveDefeatedBloober     ;branch if set to move defeated bloober
cb8f: ac cc 06                     ldy     SecondaryHardMode       ;use secondary hard mode flag as offset
cb92: bd a8 07                     lda     PseudoRandomBitReg+1,x  ;get LSFR
cb95: 39 87 cb                     and     BlooberBitmasks,y       ;mask out bits in LSFR using bitmask loaded with offset
cb98: d0 12                        bne     BlooberSwim             ;if any bits set, skip ahead to make swim
cb9a: 8a                           txa
cb9b: 4a                           lsr     A                       ;check to see if on second or fourth slot (1 or 3)
cb9c: 90 04                        bcc     FBLeft                  ;if not, branch to figure out moving direction
cb9e: a4 45                        ldy     Player_MovingDir        ;otherwise, load player's moving direction and
cba0: b0 08                        bcs     SBMDir                  ; do an unconditional branch to set

cba2: a0 02        FBLeft          ldy     #$02                    ;set left moving direction by default
cba4: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and bloober
cba7: 10 01                        bpl     SBMDir                  ;if enemy to the right of player, keep left
cba9: 88                           dey                             ;otherwise decrement to set right moving direction
cbaa: 94 46        SBMDir          sty     Enemy_MovingDir,x       ;set moving direction of bloober, then continue on here
cbac: 20 df cb     BlooberSwim     jsr     ProcSwimmingB           ;execute sub to make bloober swim characteristically
cbaf: b5 cf                        lda     Enemy_Y_Position,x      ;get vertical coordinate
cbb1: 38                           sec
cbb2: fd 34 04                     sbc     Enemy_Y_MoveForce,x     ;subtract movement force
cbb5: c9 20                        cmp     #$20                    ;check to see if position is above edge of status bar
cbb7: 90 02                        bcc     SwimX                   ;if so, don't do it
cbb9: 95 cf                        sta     Enemy_Y_Position,x      ;otherwise, set new vertical position, make bloober swim
cbbb: b4 46        SwimX           ldy     Enemy_MovingDir,x       ;check moving direction
cbbd: 88                           dey
cbbe: d0 0e                        bne     LeftSwim                ;if moving to the left, branch to second part
cbc0: b5 87                        lda     Enemy_X_Position,x
cbc2: 18                           clc                             ;add movement speed to horizontal coordinate
cbc3: 75 58                        adc     BlooperMoveSpeed,x
cbc5: 95 87                        sta     Enemy_X_Position,x      ;store result as new horizontal coordinate
cbc7: b5 6e                        lda     Enemy_PageLoc,x
cbc9: 69 00                        adc     #$00                    ;add carry to page location
cbcb: 95 6e                        sta     Enemy_PageLoc,x         ;store as new page location and leave
cbcd: 60                           rts

cbce: b5 87        LeftSwim        lda     Enemy_X_Position,x
cbd0: 38                           sec                             ;subtract movement speed from horizontal coordinate
cbd1: f5 58                        sbc     BlooperMoveSpeed,x
cbd3: 95 87                        sta     Enemy_X_Position,x      ;store result as new horizontal coordinate
cbd5: b5 6e                        lda     Enemy_PageLoc,x
cbd7: e9 00                        sbc     #$00                    ;subtract borrow from page location
cbd9: 95 6e                        sta     Enemy_PageLoc,x         ;store as new page location and leave
cbdb: 60                           rts

                   MoveDefeatedBloober
cbdc: 4c 8c bf                     jmp     MoveEnemySlowVert       ;jump to move defeated bloober downwards

cbdf: b5 a0        ProcSwimmingB   lda     BlooperMoveCounter,x    ;get enemy's movement counter
cbe1: 29 02                        and     #%00000010              ;check for d1 set
cbe3: d0 37                        bne     ChkForFloatdown         ;branch if set
cbe5: a5 09                        lda     FrameCounter
cbe7: 29 07                        and     #%00000111              ;get 3 LSB of frame counter
cbe9: 48                           pha                             ;get 3 LSB of frame counter
cbea: b5 a0                        lda     BlooperMoveCounter,x    ;get enemy's movement counter
cbec: 4a                           lsr     A                       ;check for d0 set
cbed: b0 15                        bcs     SlowSwim                ;branch if set
cbef: 68                           pla                             ;pull 3 LSB of frame counter from the stack
cbf0: d0 11                        bne     BSwimE                  ;branch to leave, execute code only every eighth frame
cbf2: bd 34 04                     lda     Enemy_Y_MoveForce,x
cbf5: 18                           clc                             ;add to movement force to speed up swim
cbf6: 69 01                        adc     #$01
cbf8: 9d 34 04                     sta     Enemy_Y_MoveForce,x     ;set movement force
cbfb: 95 58                        sta     BlooperMoveSpeed,x      ;set as movement speed
cbfd: c9 02                        cmp     #$02
cbff: d0 02                        bne     BSwimE                  ;if certain horizontal speed, branch to leave
cc01: f6 a0                        inc     BlooperMoveCounter,x    ;otherwise increment movement counter
cc03: 60           BSwimE          rts

cc04: 68           SlowSwim        pla                             ;pull 3 LSB of frame counter from the stack
cc05: d0 14                        bne     NoSSw                   ;branch to leave, execute code only every eighth frame
cc07: bd 34 04                     lda     Enemy_Y_MoveForce,x
cc0a: 38                           sec                             ;subtract from movement force to slow swim
cc0b: e9 01                        sbc     #$01
cc0d: 9d 34 04                     sta     Enemy_Y_MoveForce,x     ;set movement force
cc10: 95 58                        sta     BlooperMoveSpeed,x      ;set as movement speed
cc12: d0 07                        bne     NoSSw                   ;if any speed, branch to leave
cc14: f6 a0                        inc     BlooperMoveCounter,x    ;otherwise increment movement counter
cc16: a9 02                        lda     #$02
cc18: 9d 96 07                     sta     EnemyIntervalTimer,x    ;set enemy's timer
cc1b: 60           NoSSw           rts                             ;leave

cc1c: bd 96 07     ChkForFloatdown lda     EnemyIntervalTimer,x    ;get enemy timer
cc1f: f0 08                        beq     ChkNeearPlayer          ;branch if expired
cc21: a5 09        Floatdown       lda     FrameCounter            ;get frame counter
cc23: 4a                           lsr     A                       ;check for d0 set
cc24: b0 02                        bcs     NoFD                    ;branch to leave on every other frame
cc26: f6 cf                        inc     Enemy_Y_Position,x      ;otherwise increment vertical coordinate
cc28: 60           NoFD            rts                             ;leave

cc29: b5 cf        ChkNeearPlayer  lda     Enemy_Y_Position,x      ;get vertical coordinate
cc2b: 69 10                        adc     #$10                    ;add sixteen pixels
cc2d: c5 ce                        cmp     Player_Y_Position       ;compare result with player's vertical coordinate
cc2f: 90 f0                        bcc     Floatdown               ;if modified vertical less than player's, branch
cc31: a9 00                        lda     #$00
cc33: 95 a0                        sta     BlooperMoveCounter,x    ;otherwise nullify movement counter
cc35: 60                           rts

                   ; -----------------------------------------------------------------------------
cc36: b5 1e        MoveBulletBill  lda     Enemy_State,x           ;check bullet bill's enemy object state for d5 set
cc38: 29 20                        and     #%00100000
cc3a: f0 03                        beq     NotDefB                 ;if not set, continue with movement code
cc3c: 4c 92 bf                     jmp     MoveJ_EnemyVertically   ;otherwise jump to move defeated bullet bill downwards

cc3f: a9 e8        NotDefB         lda     #$e8                    ;set bullet bill's horizontal speed
cc41: 95 58                        sta     Enemy_X_Speed,x         ;and move it accordingly (note: this bullet bill
cc43: 4c 02 bf                     jmp     MoveEnemyHorizontally   ; object occurs in frenzy object $17, not from cannons)

                   ; -----------------------------------------------------------------------------
                   ; $02 - used to hold preset values
                   ; $03 - used to hold enemy state
cc46: 40 80        SwimCCXMoveData .bulk   $40,$80
cc48: 04 04                        .bulk   $04,$04                 ;residual data, not used

                   MoveSwimmingCheepCheep
cc4a: b5 1e                        lda     Enemy_State,x           ;check cheep-cheep's enemy object state
cc4c: 29 20                        and     #%00100000              ;for d5 set
cc4e: f0 03                        beq     CCSwim                  ;if not set, continue with movement code
cc50: 4c 8c bf                     jmp     MoveEnemySlowVert       ;otherwise jump to move defeated cheep-cheep downwards

cc53: 85 03        CCSwim          sta     $03                     ;save enemy state in $03
cc55: b5 16                        lda     Enemy_ID,x              ;get enemy identifier
cc57: 38                           sec
cc58: e9 0a                        sbc     #$0a                    ;subtract ten for cheep-cheep identifiers
cc5a: a8                           tay                             ;use as offset
cc5b: b9 46 cc                     lda     SwimCCXMoveData,y       ;load value here
cc5e: 85 02                        sta     $02
cc60: bd 01 04                     lda     Enemy_X_MoveForce,x     ;load horizontal force
cc63: 38                           sec
cc64: e5 02                        sbc     $02                     ;subtract preset value from horizontal force
cc66: 9d 01 04                     sta     Enemy_X_MoveForce,x     ;store as new horizontal force
cc69: b5 87                        lda     Enemy_X_Position,x      ;get horizontal coordinate
cc6b: e9 00                        sbc     #$00                    ;subtract borrow (thus moving it slowly)
cc6d: 95 87                        sta     Enemy_X_Position,x      ;and save as new horizontal coordinate
cc6f: b5 6e                        lda     Enemy_PageLoc,x
cc71: e9 00                        sbc     #$00                    ;subtract borrow again, this time from the
cc73: 95 6e                        sta     Enemy_PageLoc,x         ; page location, then save
cc75: a9 20                        lda     #$20
cc77: 85 02                        sta     $02                     ;save new value here
cc79: e0 02                        cpx     #$02                    ;check enemy object offset
cc7b: 90 49                        bcc     ExSwCC                  ;if in first or second slot, branch to leave
cc7d: b5 58                        lda     CheepCheepMoveMFlag,x   ;check movement flag
cc7f: c9 10                        cmp     #$10                    ;if movement speed set to $00,
cc81: 90 16                        bcc     CCSwimUpwards           ; branch to move upwards
cc83: bd 17 04                     lda     Enemy_YMF_Dummy,x
cc86: 18                           clc
cc87: 65 02                        adc     $02                     ;add preset value to dummy variable to get carry
cc89: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;and save dummy
cc8c: b5 cf                        lda     Enemy_Y_Position,x      ;get vertical coordinate
cc8e: 65 03                        adc     $03                     ;add carry to it plus enemy state to slowly move it downwards
cc90: 95 cf                        sta     Enemy_Y_Position,x      ;save as new vertical coordinate
cc92: b5 b6                        lda     Enemy_Y_HighPos,x
cc94: 69 00                        adc     #$00                    ;add carry to page location and
cc96: 4c ac cc                     jmp     ChkSwimYPos             ;jump to end of movement code

cc99: bd 17 04     CCSwimUpwards   lda     Enemy_YMF_Dummy,x
cc9c: 38                           sec
cc9d: e5 02                        sbc     $02                     ;subtract preset value to dummy variable to get borrow
cc9f: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;and save dummy
cca2: b5 cf                        lda     Enemy_Y_Position,x      ;get vertical coordinate
cca4: e5 03                        sbc     $03                     ;subtract borrow to it plus enemy state to slowly move it upwards
cca6: 95 cf                        sta     Enemy_Y_Position,x      ;save as new vertical coordinate
cca8: b5 b6                        lda     Enemy_Y_HighPos,x
ccaa: e9 00                        sbc     #$00                    ;subtract borrow from page location
ccac: 95 b6        ChkSwimYPos     sta     Enemy_Y_HighPos,x       ;save new page location here
ccae: a0 00                        ldy     #$00                    ;load movement speed to upwards by default
ccb0: b5 cf                        lda     Enemy_Y_Position,x      ;get vertical coordinate
ccb2: 38                           sec
ccb3: fd 34 04                     sbc     CheepCheepOrigYPos,x    ;subtract original coordinate from current
ccb6: 10 07                        bpl     YPDiff                  ;if result positive, skip to next part
ccb8: a0 10                        ldy     #$10                    ;otherwise load movement speed to downwards
ccba: 49 ff                        eor     #$ff
ccbc: 18                           clc                             ;get two's compliment of result
ccbd: 69 01                        adc     #$01                    ; to obtain total difference of original vs. current
ccbf: c9 0f        YPDiff          cmp     #$0f                    ;if difference between original vs. current vertical
ccc1: 90 03                        bcc     ExSwCC                  ; coordinates < 15 pixels, leave movement speed alone
ccc3: 98                           tya
ccc4: 95 58                        sta     CheepCheepMoveMFlag,x   ;otherwise change movement speed
ccc6: 60           ExSwCC          rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used as counter for firebar parts
                   ; $01 - used for oscillated high byte of spin state or to hold horizontal adder
                   ; $02 - used for oscillated high byte of spin state or to hold vertical adder
                   ; $03 - used for mirror data
                   ; $04 - used to store player's sprite 1 X coordinate
                   ; $05 - used to evaluate mirror data
                   ; $06 - used to store either screen X coordinate or sprite data offset
                   ; $07 - used to store screen Y coordinate
                   ; $ed - used to hold maximum length of firebar
                   ; $ef - used to hold high byte of spinstate
                   ; 
                   ; horizontal adder is at first byte + high byte of spinstate, vertical adder is
                   ; same + 8 bytes, two's compliment if greater than $08 for proper oscillation
                   FirebarPosLookupTbl
ccc7: 00 01 03 04+                 .bulk   $00,$01,$03,$04,$05,$06,$07,$07,$08,$00,$03,$06,$09,$0b,$0d,$0e
                                    +      $0f,$10,$00,$04,$09,$0d,$10,$13,$16,$17,$18,$00,$06,$0c,$12,$16
                                    +      $1a,$1d,$1f,$20,$00,$07,$0f,$16,$1c,$21,$25,$27,$28,$00,$09,$12
                                    +      $1b,$21,$27,$2c,$2f,$30,$00,$0b,$15,$1f,$27,$2e,$33,$37,$38,$00
                                    +      $0c,$18,$24,$2d,$35,$3b,$3e,$40,$00,$0e,$1b,$28,$32,$3b,$42,$46
                                    +      $48,$00,$0f,$1f,$2d,$38,$42,$4a,$4e,$50,$00,$11,$22,$31,$3e,$49
                                    +      $51,$56,$58
                   FirebarMirrorData
cd2a: 01 03 02 00                  .bulk   $01,$03,$02,$00
                   FirebarTblOffsets
cd2e: 00 09 12 1b+                 .bulk   $00,$09,$12,$1b,$24,$2d
cd34: 36 3f 48 51+                 .bulk   $36,$3f,$48,$51,$5a,$63
cd3a: 0c 18        FirebarYPos     .bulk   $0c,$18

cd3c: 20 af f1     ProcFirebar     jsr     GetEnemyOffscreenBits   ;get offscreen information
cd3f: ad d1 03                     lda     Enemy_OffscreenBits     ;check for d3 set
cd42: 29 08                        and     #%00001000              ;if so, branch to leave
cd44: d0 74                        bne     SkipFBar
cd46: ad 47 07                     lda     TimerControl            ;if master timer control set, branch
cd49: d0 0a                        bne     SusFbar                 ; ahead of this part
cd4b: bd 88 03                     lda     FirebarSpinSpeed,x      ;load spinning speed of firebar
cd4e: 20 10 d4                     jsr     FirebarSpin             ;modify current spinstate
cd51: 29 1f                        and     #%00011111              ;mask out all but 5 LSB
cd53: 95 a0                        sta     FirebarSpinState_High,x ;and store as new high byte of spinstate
cd55: b5 a0        SusFbar         lda     FirebarSpinState_High,x ;get high byte of spinstate
cd57: b4 16                        ldy     Enemy_ID,x              ;check enemy identifier
cd59: c0 1f                        cpy     #$1f
cd5b: 90 0d                        bcc     SetupGFB                ;if < $1f (long firebar), branch
cd5d: c9 08                        cmp     #$08                    ;check high byte of spinstate
cd5f: f0 04                        beq     SkpFSte                 ;if eight, branch to change
cd61: c9 18                        cmp     #$18
cd63: d0 05                        bne     SetupGFB                ;if not at twenty-four branch to not change
cd65: 18           SkpFSte         clc
cd66: 69 01                        adc     #$01                    ;add one to spinning thing to avoid horizontal state
cd68: 95 a0                        sta     FirebarSpinState_High,x
cd6a: 85 ef        SetupGFB        sta     $ef                     ;save high byte of spinning thing, modified or otherwise
cd6c: 20 52 f1                     jsr     RelativeEnemyPosition   ;get relative coordinates to screen
cd6f: 20 8e ce                     jsr     GetFirebarPosition      ;do a sub here (residual, too early to be used now)
cd72: bc e5 06                     ldy     Enemy_SprDataOffset,x   ;get OAM data offset
cd75: ad b9 03                     lda     Enemy_Rel_YPos          ;get relative vertical coordinate
cd78: 99 00 02                     sta     Sprite_Y_Position,y     ;store as Y in OAM data
cd7b: 85 07                        sta     $07                     ;also save here
cd7d: ad ae 03                     lda     Enemy_Rel_XPos          ;get relative horizontal coordinate
cd80: 99 03 02                     sta     Sprite_X_Position,y     ;store as X in OAM data
cd83: 85 06                        sta     $06                     ;also save here
cd85: a9 01                        lda     #$01
cd87: 85 00                        sta     $00                     ;set $01 value here (not necessary)
cd89: 20 08 ce                     jsr     FirebarCollision        ;draw fireball part and do collision detection
cd8c: a0 05                        ldy     #$05                    ;load value for short firebars by default
cd8e: b5 16                        lda     Enemy_ID,x
cd90: c9 1f                        cmp     #$1f                    ;are we doing a long firebar?
cd92: 90 02                        bcc     SetMFbar                ;no, branch then
cd94: a0 0b                        ldy     #$0b                    ;otherwise load value for long firebars
cd96: 84 ed        SetMFbar        sty     $ed                     ;store maximum value for length of firebars
cd98: a9 00                        lda     #$00
cd9a: 85 00                        sta     $00                     ;initialize counter here
cd9c: a5 ef        DrawFbar        lda     $ef                     ;load high byte of spinstate
cd9e: 20 8e ce                     jsr     GetFirebarPosition      ;get fireball position data depending on firebar part
cda1: 20 bb cd                     jsr     DrawFirebar_Collision   ;position it properly, draw it and do collision detection
cda4: a5 00                        lda     $00                     ;check which firebar part
cda6: c9 04                        cmp     #$04
cda8: d0 08                        bne     NextFbar
cdaa: ac cf 06                     ldy     DuplicateObj_Offset     ;if we arrive at fifth firebar part,
cdad: b9 e5 06                     lda     Enemy_SprDataOffset,y   ; get offset from long firebar and load OAM data offset
cdb0: 85 06                        sta     $06                     ; using long firebar offset, then store as new one here
cdb2: e6 00        NextFbar        inc     $00                     ;move onto the next firebar part
cdb4: a5 00                        lda     $00
cdb6: c5 ed                        cmp     $ed                     ;if we end up at the maximum part, go on and leave
cdb8: 90 e2                        bcc     DrawFbar                ;otherwise go back and do another
cdba: 60           SkipFBar        rts

                   DrawFirebar_Collision
cdbb: a5 03                        lda     $03                     ;store mirror data elsewhere
cdbd: 85 05                        sta     $05
cdbf: a4 06                        ldy     $06                     ;load OAM data offset for firebar
cdc1: a5 01                        lda     $01                     ;load horizontal adder we got from position loader
cdc3: 46 05                        lsr     $05                     ;shift LSB of mirror data
cdc5: b0 04                        bcs     AddHA                   ;if carry was set, skip this part
cdc7: 49 ff                        eor     #$ff
cdc9: 69 01                        adc     #$01                    ;otherwise get two's compliment of horizontal adder
cdcb: 18           AddHA           clc                             ;add horizontal coordinate relative to screen to
cdcc: 6d ae 03                     adc     Enemy_Rel_XPos          ;horizontal adder, modified or otherwise
cdcf: 99 03 02                     sta     Sprite_X_Position,y     ;store as X coordinate here
cdd2: 85 06                        sta     $06                     ;store here for now, note offset is saved in Y still
cdd4: cd ae 03                     cmp     Enemy_Rel_XPos          ;compare X coordinate of sprite to original X of firebar
cdd7: b0 09                        bcs     SubtR1                  ;if sprite coordinate => original coordinate, branch
cdd9: ad ae 03                     lda     Enemy_Rel_XPos
cddc: 38                           sec                             ;otherwise subtract sprite X from the
cddd: e5 06                        sbc     $06                     ; original one and skip this part
cddf: 4c e6 cd                     jmp     ChkFOfs

cde2: 38           SubtR1          sec                             ;subtract original X from the
cde3: ed ae 03                     sbc     Enemy_Rel_XPos          ;current sprite X
cde6: c9 59        ChkFOfs         cmp     #$59                    ;if difference of coordinates within a certain range,
cde8: 90 04                        bcc     VAHandl                 ; continue by handling vertical adder
cdea: a9 f8                        lda     #$f8                    ;otherwise, load offscreen Y coordinate
cdec: d0 15                        bne     SetVFbr                 ; and unconditionally branch to move sprite offscreen

cdee: ad b9 03     VAHandl         lda     Enemy_Rel_YPos          ;if vertical relative coordinate offscreen,
cdf1: c9 f8                        cmp     #$f8                    ;skip ahead of this part and write into sprite Y coordinate
cdf3: f0 0e                        beq     SetVFbr
cdf5: a5 02                        lda     $02                     ;load vertical adder we got from position loader
cdf7: 46 05                        lsr     $05                     ;shift LSB of mirror data one more time
cdf9: b0 04                        bcs     AddVA                   ;if carry was set, skip this part
cdfb: 49 ff                        eor     #$ff
cdfd: 69 01                        adc     #$01                    ;otherwise get two's compliment of second part
cdff: 18           AddVA           clc                             ;add vertical coordinate relative to screen to 
ce00: 6d b9 03                     adc     Enemy_Rel_YPos          ; the second data, modified or otherwise
ce03: 99 00 02     SetVFbr         sta     Sprite_Y_Position,y     ;store as Y coordinate here
ce06: 85 07                        sta     $07                     ;also store here for now
                   FirebarCollision
ce08: 20 ed ec                     jsr     DrawFirebar             ;run sub here to draw current tile of firebar
ce0b: 98                           tya                             ;return OAM data offset and save
ce0c: 48                           pha                             ;to the stack for now
ce0d: ad 9f 07                     lda     StarInvincibleTimer     ;if star mario invincibility timer
ce10: 0d 47 07                     ora     TimerControl            ; or master timer controls set
ce13: d0 70                        bne     NoColFB                 ; then skip all of this
ce15: 85 05                        sta     $05                     ;otherwise initialize counter
ce17: a4 b5                        ldy     Player_Y_HighPos
ce19: 88                           dey                             ;if player's vertical high byte offscreen,
ce1a: d0 69                        bne     NoColFB                 ;skip all of this
ce1c: a4 ce                        ldy     Player_Y_Position       ;get player's vertical position
ce1e: ad 54 07                     lda     PlayerSize              ;get player's size
ce21: d0 05                        bne     AdjSm                   ;if player small, branch to alter variables
ce23: ad 14 07                     lda     CrouchingFlag
ce26: f0 09                        beq     BigJp                   ;if player big and not crouching, jump ahead
ce28: e6 05        AdjSm           inc     $05                     ;if small or big but crouching, execute this part
ce2a: e6 05                        inc     $05                     ;first increment our counter twice (setting $02 as flag)
ce2c: 98                           tya
ce2d: 18                           clc                             ;then add 24 pixels to the player's
ce2e: 69 18                        adc     #$18                    ; vertical coordinate
ce30: a8                           tay
ce31: 98           BigJp           tya                             ;get vertical coordinate, altered or otherwise, from Y
ce32: 38           FBCLoop         sec                             ;subtract vertical position of firebar
ce33: e5 07                        sbc     $07                     ; from the vertical coordinate of the player
ce35: 10 05                        bpl     ChkVFBD                 ;if player lower on the screen than firebar, 
ce37: 49 ff                        eor     #$ff                    ;skip two's compliment part
ce39: 18                           clc                             ;otherwise get two's compliment
ce3a: 69 01                        adc     #$01
ce3c: c9 08        ChkVFBD         cmp     #$08                    ;if difference => 8 pixels, skip ahead of this part
ce3e: b0 1c                        bcs     Chk20fs
ce40: a5 06                        lda     $06                     ;if firebar on far right on the screen, skip this,
ce42: c9 f0                        cmp     #$f0                    ; because, really, what's the point?
ce44: b0 16                        bcs     Chk20fs
ce46: ad 07 02                     lda     Sprite_X_Position+4     ;get OAM X coordinate for sprite #1
ce49: 18                           clc
ce4a: 69 04                        adc     #$04                    ;add four pixels
ce4c: 85 04                        sta     $04                     ;store here
ce4e: 38                           sec                             ;subtract horizontal coordinate of firebar
ce4f: e5 06                        sbc     $06                     ;from the X coordinate of player's sprite 1
ce51: 10 05                        bpl     ChkFBCl                 ;if modded X coordinate to the right of firebar
ce53: 49 ff                        eor     #$ff                    ;skip two's compliment part
ce55: 18                           clc                             ;otherwise get two's compliment
ce56: 69 01                        adc     #$01
ce58: c9 08        ChkFBCl         cmp     #$08                    ;if difference < 8 pixels, collision, thus branch
ce5a: 90 13                        bcc     ChgSDir                 ; to process
ce5c: a5 05        Chk20fs         lda     $05                     ;if value of $02 was set earlier for whatever reason,
ce5e: c9 02                        cmp     #$02                    ; branch to increment OAM offset and leave, no collision
ce60: f0 23                        beq     NoColFB
ce62: a4 05                        ldy     $05                     ;otherwise get temp here and use as offset
ce64: a5 ce                        lda     Player_Y_Position
ce66: 18                           clc
ce67: 79 3a cd                     adc     FirebarYPos,y           ;add value loaded with offset to player's vertical coordinate
ce6a: e6 05                        inc     $05                     ; then increment temp and jump back
ce6c: 4c 32 ce                     jmp     FBCLoop

ce6f: a2 01        ChgSDir         ldx     #$01                    ;set movement direction by default
ce71: a5 04                        lda     $04                     ;if OAM X coordinate of player's sprite 1
ce73: c5 06                        cmp     $06                     ; is greater than horizontal coordinate of firebar
ce75: b0 01                        bcs     SetSDir                 ; then do not alter movement direction
ce77: e8                           inx                             ;otherwise increment it
ce78: 86 46        SetSDir         stx     Enemy_MovingDir         ;store movement direction here
ce7a: a2 00                        ldx     #$00
ce7c: a5 00                        lda     $00                     ;save value written to $00 to stack
ce7e: 48                           pha
ce7f: 20 2c d9                     jsr     InjurePlayer            ;perform sub to hurt or kill player
ce82: 68                           pla
ce83: 85 00                        sta     $00                     ;get value of $00 from stack
ce85: 68           NoColFB         pla                             ;get OAM data offset
ce86: 18                           clc                             ;add four to it and save
ce87: 69 04                        adc     #$04
ce89: 85 06                        sta     $06
ce8b: a6 08                        ldx     ObjectOffset            ;get enemy object buffer offset and leave
ce8d: 60                           rts

                   GetFirebarPosition
ce8e: 48                           pha                             ;save high byte of spinstate to the stack
ce8f: 29 0f                        and     #%00001111              ;mask out low nybble
ce91: c9 09                        cmp     #$09
ce93: 90 05                        bcc     GetHAdder               ;if lower than $09, branch ahead
ce95: 49 0f                        eor     #%00001111              ;otherwise get two's compliment to oscillate
ce97: 18                           clc
ce98: 69 01                        adc     #$01
ce9a: 85 01        GetHAdder       sta     $01                     ;store result, modified or not, here
ce9c: a4 00                        ldy     $00                     ;load number of firebar ball where we're at
ce9e: b9 2e cd                     lda     FirebarTblOffsets,y     ;load offset to firebar position data
cea1: 18                           clc
cea2: 65 01                        adc     $01                     ;add oscillated high byte of spinstate
cea4: a8                           tay                             ; to offset here and use as new offset
cea5: b9 c7 cc                     lda     FirebarPosLookupTbl,y   ;get data here and store as horizontal adder
cea8: 85 01                        sta     $01
ceaa: 68                           pla                             ;pull whatever was in A from the stack
ceab: 48                           pha                             ;save it again because we still need it
ceac: 18                           clc
cead: 69 08                        adc     #$08                    ;add eight this time, to get vertical adder
ceaf: 29 0f                        and     #%00001111              ;mask out high nybble
ceb1: c9 09                        cmp     #$09                    ;if lower than $09, branch ahead
ceb3: 90 05                        bcc     GetVAdder
ceb5: 49 0f                        eor     #%00001111              ;otherwise get two's compliment
ceb7: 18                           clc
ceb8: 69 01                        adc     #$01
ceba: 85 02        GetVAdder       sta     $02                     ;store result here
cebc: a4 00                        ldy     $00
cebe: b9 2e cd                     lda     FirebarTblOffsets,y     ;load offset to firebar position data again
cec1: 18                           clc
cec2: 65 02                        adc     $02                     ;this time add value in $02 to offset here and use as offset
cec4: a8                           tay
cec5: b9 c7 cc                     lda     FirebarPosLookupTbl,y   ;get data here and store as vertica adder
cec8: 85 02                        sta     $02
ceca: 68                           pla                             ;pull out whatever was in A one last time
cecb: 4a                           lsr     A                       ;divide by eight or shift three to the right
cecc: 4a                           lsr     A
cecd: 4a                           lsr     A
cece: a8                           tay                             ;use as offset
cecf: b9 2a cd                     lda     FirebarMirrorData,y     ;load mirroring data here
ced2: 85 03                        sta     $03                     ;store
ced4: 60                           rts

                   ; -----------------------------------------------------------------------------
                   PRandomSubtracter
ced5: f8 a0 70 bd+                 .bulk   $f8,$a0,$70,$bd,$00
ceda: 20 20 20 00+ FlyCCBPriority  .bulk   $20,$20,$20,$00,$00

                   MoveFlyingCheepCheep
cedf: b5 1e                        lda     Enemy_State,x           ;check cheep-cheep's enemy state
cee1: 29 20                        and     #%00100000              ;for d5 set
cee3: f0 08                        beq     FlyCC                   ;branch to continue code if not set
cee5: a9 00                        lda     #$00
cee7: 9d c5 03                     sta     Enemy_SprAttrib,x       ;otherwise clear sprite attributes
ceea: 4c 92 bf                     jmp     MoveJ_EnemyVertically   ;and jump to move defeated cheep-cheep downwards

ceed: 20 02 bf     FlyCC           jsr     MoveEnemyHorizontally   ;move cheep-cheep horizontally based on speed and force
cef0: a0 0d                        ldy     #$0d                    ;set vertical movement amount
cef2: a9 05                        lda     #$05                    ;set maximum speed
cef4: 20 96 bf                     jsr     SetXMoveAmt             ;branch to impose gravity on flying cheep-cheep
cef7: bd 34 04                     lda     Enemy_Y_MoveForce,x
cefa: 4a                           lsr     A                       ;get vertical movement force and
cefb: 4a                           lsr     A                       ;move high nybble to low
cefc: 4a                           lsr     A
cefd: 4a                           lsr     A
cefe: a8                           tay                             ;save as offset (note this tends to go into reach of code)
ceff: b5 cf                        lda     Enemy_Y_Position,x      ;get vertical position
cf01: 38                           sec                             ;subtract pseudorandom value based on offset from position
cf02: f9 d5 ce                     sbc     PRandomSubtracter,y
cf05: 10 05                        bpl     AddCCF                  ;if result within top half of screen, skip this part
cf07: 49 ff                        eor     #$ff
cf09: 18                           clc                             ;otherwise get two's compliment
cf0a: 69 01                        adc     #$01
cf0c: c9 08        AddCCF          cmp     #$08                    ;if result or two's compliment greater than eight,
cf0e: b0 0e                        bcs     BPGet                   ;skip to the end without changing movement force
cf10: bd 34 04                     lda     Enemy_Y_MoveForce,x
cf13: 18                           clc
cf14: 69 10                        adc     #$10                    ;otherwise add to it
cf16: 9d 34 04                     sta     Enemy_Y_MoveForce,x
cf19: 4a                           lsr     A                       ;move high nybble to low again
cf1a: 4a                           lsr     A
cf1b: 4a                           lsr     A
cf1c: 4a                           lsr     A
cf1d: a8                           tay
cf1e: b9 da ce     BPGet           lda     FlyCCBPriority,y        ;load bg priority data and store (this is very likely
cf21: 9d c5 03                     sta     Enemy_SprAttrib,x       ; broken or residual code, value is overwritten before
cf24: 60                           rts                             ; drawing it next frame), then leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to hold horizontal difference
                   ; $01-$03 - used to hold difference adjusters
cf25: 15 30 40     LakituDiffAdj   .bulk   $15,$30,$40

cf28: b5 1e        MoveLakitu      lda     Enemy_State,x           ;check lakitu's enemy state
cf2a: 29 20                        and     #%00100000              ;for d5 set
cf2c: f0 03                        beq     ChkLS                   ;if not set, continue with code
cf2e: 4c 63 bf                     jmp     MoveD_EnemyVertically   ;otherwise jump to move defeated lakitu downwards

cf31: b5 1e        ChkLS           lda     Enemy_State,x           ;if lakitu's enemy state not set at all,
cf33: f0 0b                        beq     Fr12S                   ; go ahead and continue with code
cf35: a9 00                        lda     #$00
cf37: 95 a0                        sta     LakituMoveDirection,x   ;otherwise initialize moving direction to move to left
cf39: 8d cb 06                     sta     EnemyFrenzyBuffer       ;initialize frenzy buffer
cf3c: a9 10                        lda     #$10
cf3e: d0 13                        bne     SetLSpd                 ;load horizontal speed and do unconditional branch

cf40: a9 12        Fr12S           lda     #Spiny
cf42: 8d cb 06                     sta     EnemyFrenzyBuffer       ;set spiny identifier in frenzy buffer
cf45: a0 02                        ldy     #$02
cf47: b9 25 cf     LdLDa           lda     LakituDiffAdj,y         ;load values
cf4a: 99 01 00                     sta     $0001,y                 ;store in zero page
cf4d: 88                           dey
cf4e: 10 f7                        bpl     LdLDa                   ;do this until all values are stired
cf50: 20 6c cf                     jsr     PlayerLakituDiff        ;execute sub to set speed and create spinys
cf53: 95 58        SetLSpd         sta     LakituMoveSpeed,x       ;set movement speed returned from sub
cf55: a0 01                        ldy     #$01                    ;set moving direction to right by default
cf57: b5 a0                        lda     LakituMoveDirection,x
cf59: 29 01                        and     #$01                    ;get LSB of moving direction
cf5b: d0 0a                        bne     SetLMov                 ;if set, branch to the end to use moving direction
cf5d: b5 58                        lda     LakituMoveSpeed,x
cf5f: 49 ff                        eor     #$ff                    ;get two's compliment of moving speed
cf61: 18                           clc
cf62: 69 01                        adc     #$01
cf64: 95 58                        sta     LakituMoveSpeed,x       ;store as new moving speed
cf66: c8                           iny                             ;increment moving direction to left
cf67: 94 46        SetLMov         sty     Enemy_MovingDir,x       ;store moving direction
cf69: 4c 02 bf                     jmp     MoveEnemyHorizontally   ;move lakitu horizontally

                   PlayerLakituDiff
cf6c: a0 00                        ldy     #$00                    ;set Y for default value
cf6e: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between enemy and player
cf71: 10 0a                        bpl     ChkLakDif               ;branch if enemy is to the right of the player
cf73: c8                           iny                             ;increment Y for left of player
cf74: a5 00                        lda     $00
cf76: 49 ff                        eor     #$ff                    ;get two's compliment of low byte of horizontal difference
cf78: 18                           clc
cf79: 69 01                        adc     #$01                    ;store two's compliment as horizontal difference
cf7b: 85 00                        sta     $00
cf7d: a5 00        ChkLakDif       lda     $00                     ;get low byte of horizontal difference
cf7f: c9 3c                        cmp     #$3c                    ;if within a certain distance of player, branch
cf81: 90 1c                        bcc     ChkPSpeed
cf83: a9 3c                        lda     #$3c                    ;otherwise set maximum distance
cf85: 85 00                        sta     $00
cf87: b5 16                        lda     Enemy_ID,x              ;check if lakitu is in our current enemy slot
cf89: c9 11                        cmp     #Lakitu
cf8b: d0 12                        bne     ChkPSpeed               ;if not, branch elsewhere
cf8d: 98                           tya                             ;compare contents of Y, now in A
cf8e: d5 a0                        cmp     LakituMoveDirection,x   ;to what is being used as horizontal movement direction
cf90: f0 0d                        beq     ChkPSpeed               ;if moving toward the player, branch, do not alter
cf92: b5 a0                        lda     LakituMoveDirection,x   ;if moving to the left beyond maximum distance,
cf94: f0 06                        beq     SetLMovD                ; branch and alter without delay
cf96: d6 58                        dec     LakituMoveSpeed,x       ;decrement horizontal speed
cf98: b5 58                        lda     LakituMoveSpeed,x       ;if horizontal speed not yet at zero, branch to leave
cf9a: d0 40                        bne     ExMoveLak
cf9c: 98           SetLMovD        tya                             ;set horizontal direction depending on horizontal
cf9d: 95 a0                        sta     LakituMoveDirection,x   ;difference between enemy and player if necessary
cf9f: a5 00        ChkPSpeed       lda     $00
cfa1: 29 3c                        and     #%00111100              ;mask out all but four bits in the middle
cfa3: 4a                           lsr     A                       ;divide masked difference by four
cfa4: 4a                           lsr     A
cfa5: 85 00                        sta     $00                     ;store as new value
cfa7: a0 00                        ldy     #$00                    ;init offset
cfa9: a5 57                        lda     Player_X_Speed
cfab: f0 24                        beq     SubDifAdj               ;if player not moving horizontally, branch
cfad: ad 75 07                     lda     ScrollAmount
cfb0: f0 1f                        beq     SubDifAdj               ;if scroll speed not set, branch to same place
cfb2: c8                           iny                             ;otherwise increment offset
cfb3: a5 57                        lda     Player_X_Speed
cfb5: c9 19        LCFB5           cmp     #$19                    ;if player not running, branch
cfb7: 90 08                        bcc     ChkSpinyO
cfb9: ad 75 07                     lda     ScrollAmount
cfbc: c9 02                        cmp     #$02                    ;if scroll speed below a certain amount, branch
cfbe: 90 01                        bcc     ChkSpinyO               ; to same place
cfc0: c8                           iny                             ;otherwise increment once more
cfc1: b5 16        ChkSpinyO       lda     Enemy_ID,x              ;check for spiny object
cfc3: c9 12                        cmp     #Spiny
cfc5: d0 04                        bne     ChkEmySpd               ;branch if not found
cfc7: a5 57                        lda     Player_X_Speed          ;if player not moving, skip this part
cfc9: d0 06                        bne     SubDifAdj
cfcb: b5 a0        ChkEmySpd       lda     LakituMoveDirection,x   ;check vertical speed
cfcd: d0 02                        bne     SubDifAdj               ;branch if nonzero
cfcf: a0 00                        ldy     #$00                    ;otherwise reinit offset
cfd1: b9 01 00     SubDifAdj       lda     $0001,y                 ;get one of three saved values from earlier
cfd4: a4 00                        ldy     $00                     ;get saved horizontal difference
cfd6: 38           SPixelLak       sec                             ;subtract one for each pixel of horizontal difference
cfd7: e9 01                        sbc     #$01                    ; from one of three saved values
cfd9: 88                           dey
cfda: 10 fa                        bpl     SPixelLak               ;branch until all pixels are subtracted, to adjust difference
cfdc: 60           ExMoveLak       rts                             ;leave!!!

                   ; -----------------------------------------------------------------------------
                   ; $04-$05 - used to store name table address in little endian order
                   BridgeCollapseData
cfdd: 1a                           .dd1    $1a                     ;axe
cfde: 58                           .dd1    $58                     ;chain
cfdf: 98 96 94 92+                 .bulk   $98,$96,$94,$92,$90,$8e,$8c ;bridge
cfe6: 8a 88 86 84+                 .bulk   $8a,$88,$86,$84,$82,$80

cfec: ae 68 03     BridgeCollapse  ldx     BowserFront_Offset      ;get enemy offset for bowser
cfef: b5 16                        lda     Enemy_ID,x              ;check enemy object identifier for bowser
cff1: c9 2d                        cmp     #Bowser                 ;if not found, branch ahead,
cff3: d0 10                        bne     SetM2                   ; metatile removal not necessary
cff5: 86 08                        stx     ObjectOffset            ;store as enemy offset here
cff7: b5 1e                        lda     Enemy_State,x           ;if bowser in normal state, skip all of this
cff9: f0 1a                        beq     RemoveBridge
cffb: 29 40                        and     #%01000000              ;if bowser's state has d6 clear, skip to silence music
cffd: f0 06                        beq     SetM2
cfff: b5 cf                        lda     Enemy_Y_Position,x      ;check bowser's vertical coordinate
d001: c9 e0                        cmp     #$e0                    ;if bowser not yet low enough, skip this part ahead
d003: 90 0a                        bcc     MoveD_Bowser
d005: a9 80        SetM2           lda     #Silence                ;silence music
d007: 85 fc                        sta     EventMusicQueue
d009: ee 72 07                     inc     OperMode_Task           ;move onto next secondary mode in autoctrl mode
d00c: 4c 71 d0                     jmp     KillAllEnemies          ;jump to empty all enemy slots and then leave  

d00f: 20 8c bf     MoveD_Bowser    jsr     MoveEnemySlowVert       ;do a sub to move bowser downwards
d012: 4c 7b d1                     jmp     BowserGfxHandler        ;jump to draw bowser's front and rear, then leave

d015: ce 64 03     RemoveBridge    dec     BowserFeetCounter       ;decrement timer to control bowser's feet
d018: d0 44                        bne     NoBFall                 ;if not expired, skip all of this
d01a: a9 04                        lda     #$04
d01c: 8d 64 03                     sta     BowserFeetCounter       ;otherwise, set timer now
d01f: ad 63 03                     lda     BowserBodyControls
d022: 49 01                        eor     #$01                    ;invert bit to control bowser's feet
d024: 8d 63 03                     sta     BowserBodyControls
d027: a9 22                        lda     #$22                    ;put high byte of name table address here for now
d029: 85 05                        sta     $05
d02b: ac 69 03                     ldy     BridgeCollapseOffset    ;get bridge collapse offset here
d02e: b9 dd cf                     lda     BridgeCollapseData,y    ;load low byte of name table address and store here
d031: 85 04                        sta     $04
d033: ac 00 03                     ldy     VRAM_Buffer1_Offset     ;increment vram buffer offset
d036: c8                           iny
d037: a2 0c                        ldx     #$0c                    ;set offset for tile data for sub to draw blank metatile
d039: 20 cd 8a                     jsr     RemBridge               ;do sub here to remove bowser's bridge metatiles
d03c: a6 08                        ldx     ObjectOffset            ;get enemy offset
d03e: 20 8f 8a                     jsr     MoveVOffset             ;set new vram buffer offset
d041: a9 08                        lda     #Sfx_Blast              ;load the fireworks/gunfire sound into the square 2 sfx
d043: 85 fe                        sta     Square2SoundQueue       ; queue while at the same time loading the brick
d045: a9 01                        lda     #Sfx_BrickShatter       ; shatter sound into the noise sfx queue thus
d047: 85 fd                        sta     NoiseSoundQueue         ; producing the unique sound of the bridge collapsing 
d049: ee 69 03                     inc     BridgeCollapseOffset    ;increment bridge collapse offset
d04c: ad 69 03                     lda     BridgeCollapseOffset
d04f: c9 0f                        cmp     #$0f                    ;if bridge collapse offset has not yet reached
d051: d0 0b                        bne     NoBFall                 ; the end, go ahead and skip this part
d053: 20 63 c3                     jsr     InitVStf                ;initialize whatever vertical speed bowser has
d056: a9 40                        lda     #%01000000
d058: 95 1e                        sta     Enemy_State,x           ;set bowser's state to one of defeated states (d6 set)
d05a: a9 80                        lda     #Sfx_BowserFall
d05c: 85 fe                        sta     Square2SoundQueue       ;play bowser defeat sound
d05e: 4c 7b d1     NoBFall         jmp     BowserGfxHandler        ;jump to code that draws bowser

                   ; -----------------------------------------------------------------------------
d061: 21 41 11 31  PRandomRange    .bulk   $21,$41,$11,$31

d065: b5 1e        RunBowser       lda     Enemy_State,x           ;if d5 in enemy state is not set
d067: 29 20                        and     #%00100000              ; then branch elsewhere to run bowser
d069: f0 14                        beq     BowserControl
d06b: b5 cf                        lda     Enemy_Y_Position,x      ;otherwise check vertical position
d06d: c9 e0                        cmp     #$e0                    ;if above a certain point, branch to move defeated bowser
d06f: 90 9e                        bcc     MoveD_Bowser            ;otherwise proceed to KillAllEnemies
d071: a2 04        KillAllEnemies  ldx     #$04                    ;start with last enemy slot
d073: 20 98 c9     KillLoop        jsr     EraseEnemyObject        ;branch to kill enemy objects
d076: ca                           dex                             ;move onto next enemy slot
d077: 10 fa                        bpl     KillLoop                ;do this until all slots are emptied
d079: 8d cb 06                     sta     EnemyFrenzyBuffer       ;empty frenzy buffer
d07c: a6 08                        ldx     ObjectOffset            ;get enemy object offset and leave
d07e: 60                           rts

d07f: a9 00        BowserControl   lda     #$00
d081: 8d cb 06                     sta     EnemyFrenzyBuffer       ;empty frenzy buffer
d084: ad 47 07                     lda     TimerControl            ;if master timer control not set,
d087: f0 03                        beq     ChkMouth                ;skip jump and execute code here
d089: 4c 39 d1                     jmp     SkipToFB                ;otherwise, jump over a bunch of code

d08c: ad 63 03     ChkMouth        lda     BowserBodyControls      ;check bowser's mouth
d08f: 10 03                        bpl     FeetTmr                 ;if bit clear, go ahead with code here
d091: 4c 0f d1                     jmp     HammerChk               ;otherwise skip a whole section starting here

d094: ce 64 03     FeetTmr         dec     BowserFeetCounter       ;decrement timer to control bowser's feet
d097: d0 0d                        bne     ResetMDr                ;if not expired, skip this part
d099: a9 20                        lda     #$20                    ;otherwise, reset timer
d09b: 8d 64 03                     sta     BowserFeetCounter
d09e: ad 63 03                     lda     BowserBodyControls      ;and invert bit used
d0a1: 49 01                        eor     #%00000001              ; to control bowser's feet
d0a3: 8d 63 03                     sta     BowserBodyControls
d0a6: a5 09        ResetMDr        lda     FrameCounter            ;check frame counter
d0a8: 29 0f                        and     #%00001111              ;if not on every sixteenth frame, skip
d0aa: d0 04                        bne     B_FaceP                 ; ahead to continue code
d0ac: a9 02                        lda     #$02                    ;otherwise reset moving/facing direction every
d0ae: 95 46                        sta     Enemy_MovingDir,x       ; sixteen frames
d0b0: bd 8a 07     B_FaceP         lda     EnemyFrameTimer,x       ;if timer set here expired,
d0b3: f0 1c                        beq     GetPRCmp                ;branch to next section
d0b5: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and bowser,
d0b8: 10 17                        bpl     GetPRCmp                ; and branch if bowser to the right of the player
d0ba: a9 01                        lda     #$01
d0bc: 95 46                        sta     Enemy_MovingDir,x       ;set bowser to move and face to the right
d0be: a9 02                        lda     #$02
d0c0: 8d 65 03                     sta     BowserMovementSpeed     ;set movement speed
d0c3: a9 20                        lda     #$20
d0c5: 9d 8a 07                     sta     EnemyFrameTimer,x       ;set timer here
d0c8: 8d 90 07                     sta     BowserFireBreathTimer   ;set timer used for bowser's flame
d0cb: b5 87                        lda     Enemy_X_Position,x
d0cd: c9 c8                        cmp     #$c8                    ;if bowser to the right past a certain point,
d0cf: b0 3e                        bcs     HammerChk               ; skip ahead to some other section
d0d1: a5 09        GetPRCmp        lda     FrameCounter            ;get frame counter
d0d3: 29 03                        and     #%00000011
d0d5: d0 38                        bne     HammerChk               ;execute this code every fourth frame, otherwise branch
d0d7: b5 87                        lda     Enemy_X_Position,x
d0d9: cd 66 03                     cmp     BowserOrigXPos          ;if bowser not at original horizontal position,
d0dc: d0 0c                        bne     GetDToO                 ; branch to skip this part
d0de: bd a7 07                     lda     PseudoRandomBitReg,x
d0e1: 29 03                        and     #%00000011              ;get pseudorandom offset
d0e3: a8                           tay
d0e4: b9 61 d0                     lda     PRandomRange,y          ;load value using pseudorandom offset
d0e7: 8d dc 06                     sta     MaxRangeFromOrigin      ; and store here
d0ea: b5 87        GetDToO         lda     Enemy_X_Position,x
d0ec: 18                           clc                             ;add movement speed to bowser's horizontal
d0ed: 6d 65 03                     adc     BowserMovementSpeed     ; coordinate and save as new horizontal position
d0f0: 95 87                        sta     Enemy_X_Position,x
d0f2: b4 46                        ldy     Enemy_MovingDir,x
d0f4: c0 01                        cpy     #$01                    ;if bowser moving and facing to the right, skip ahead
d0f6: f0 17                        beq     HammerChk
d0f8: a0 ff                        ldy     #$ff                    ;set default movement speed here (move left)
d0fa: 38                           sec                             ;get difference of current vs. original
d0fb: ed 66 03                     sbc     BowserOrigXPos          ; horizontal position
d0fe: 10 07                        bpl     CompDtoO                ;if current position to the right of original, skip ahead
d100: 49 ff                        eor     #$ff
d102: 18                           clc                             ;get two's compliment
d103: 69 01                        adc     #$01
d105: a0 01                        ldy     #$01                    ;set alternate movement speed here (move right)
d107: cd dc 06     CompDtoO        cmp     MaxRangeFromOrigin      ;compare difference with pseudorandom value
d10a: 90 03                        bcc     HammerChk               ;if difference < pseudorandom value, leave speed alone
d10c: 8c 65 03                     sty     BowserMovementSpeed     ;otherwise change bowser's movement speed
d10f: bd 8a 07     HammerChk       lda     EnemyFrameTimer,x       ;if timer set here not expired yet, skip ahead to
d112: d0 28                        bne     MakeBJump               ; some other section of code
d114: 20 8c bf                     jsr     MoveEnemySlowVert       ;otherwise start by moving bowser downwards
d117: ad 5f 07                     lda     WorldNumber             ;check world number
d11a: c9 05                        cmp     #World6
d11c: 90 09                        bcc     SetHmrTmr               ;if world 1-5, skip this part (not time to throw hammers yet)
d11e: a5 09                        lda     FrameCounter
d120: 29 03                        and     #%00000011              ;check to see if it's time to execute sub
d122: d0 03                        bne     SetHmrTmr               ;if not, skip sub, otherwise
d124: 20 94 ba                     jsr     SpawnHammerObj          ;execute sub on every fourth frame to spawn misc object (hammer)
d127: b5 cf        SetHmrTmr       lda     Enemy_Y_Position,x      ;get current vertical position
d129: c9 80                        cmp     #$80                    ;if still above a certain point
d12b: 90 1c                        bcc     ChkFireB                ; then skip to world number check for flames
d12d: bd a7 07                     lda     PseudoRandomBitReg,x
d130: 29 03                        and     #%00000011              ;get pseudorandom offset
d132: a8                           tay
d133: b9 61 d0                     lda     PRandomRange,y          ;get value using pseudorandom offset
d136: 9d 8a 07                     sta     EnemyFrameTimer,x       ;set for timer here
d139: 4c 49 d1     SkipToFB        jmp     ChkFireB                ;jump to execute flames code

d13c: c9 01        MakeBJump       cmp     #$01                    ;if timer not yet about to expire,
d13e: d0 09                        bne     ChkFireB                ; skip ahead to next part
d140: d6 cf                        dec     Enemy_Y_Position,x      ;otherwise decrement vertical coordinate
d142: 20 63 c3                     jsr     InitVStf                ;initialize movement amount
d145: a9 fe                        lda     #$fe
d147: 95 a0                        sta     Enemy_Y_Speed,x         ;set vertical speed to move bowser upwards
d149: ad 5f 07     ChkFireB        lda     WorldNumber             ;check world number here
d14c: c9 07                        cmp     #World8                 ;world 8?
d14e: f0 04                        beq     SpawnFBr                ;if so, execute this part here
d150: c9 05                        cmp     #World6                 ;world 6-7?
d152: b0 27                        bcs     BowserGfxHandler        ;if so, skip this part here
d154: ad 90 07     SpawnFBr        lda     BowserFireBreathTimer   ;check timer here
d157: d0 22                        bne     BowserGfxHandler        ;if not expired yet, skip all of this
d159: a9 20                        lda     #$20
d15b: 8d 90 07                     sta     BowserFireBreathTimer   ;set timer here
d15e: ad 63 03                     lda     BowserBodyControls
d161: 49 80                        eor     #%10000000              ;invert bowser's mouth bit to open
d163: 8d 63 03                     sta     BowserBodyControls      ; and close bowser's mouth
d166: 30 e1                        bmi     ChkFireB                ;if bowser's mouth open, loop back
d168: 20 d9 d1                     jsr     SetFlameTimer           ;get timing for bowser's flame
d16b: ac cc 06                     ldy     SecondaryHardMode
d16e: f0 03                        beq     SetFBTmr                ;if secondary hard mode flag not set, skip this
d170: 38                           sec
d171: e9 10                        sbc     #$10                    ;otherwise subtract from value in A
d173: 8d 90 07     SetFBTmr        sta     BowserFireBreathTimer   ;set value as timer here
d176: a9 15                        lda     #$15                    ;put bowser's flame identifier
d178: 8d cb 06                     sta     EnemyFrenzyBuffer       ; in enemy frenzy buffer
                   ; 
                   BowserGfxHandler
d17b: 20 bc d1                     jsr     ProcessBowserHalf       ;do a sub here to process bowser's front
d17e: a0 10                        ldy     #$10                    ;load default value here to position bowser's rear
d180: b5 46                        lda     Enemy_MovingDir,x       ;check moving direction
d182: 4a                           lsr     A
d183: 90 02                        bcc     CopyFToR                ;if moving left, use default
d185: a0 f0                        ldy     #$f0                    ;otherwise load alternate positioning value here
d187: 98           CopyFToR        tya                             ;move bowser's rear object position value to A
d188: 18                           clc
d189: 75 87                        adc     Enemy_X_Position,x      ;add to bowser's front object horizontal coordinate
d18b: ac cf 06                     ldy     DuplicateObj_Offset     ;get bowser's rear object offset
d18e: 99 87 00                     sta     Enemy_X_Position,y      ;store A as bowser's rear horizontal coordinate
d191: b5 cf                        lda     Enemy_Y_Position,x
d193: 18                           clc                             ;add eight pixels to bowser's front object
d194: 69 08                        adc     #$08                    ;vertical coordinate and store as vertical coordinate
d196: 99 cf 00                     sta     Enemy_Y_Position,y      ; for bowser's rear
d199: b5 1e                        lda     Enemy_State,x
d19b: 99 1e 00                     sta     Enemy_State,y           ;copy enemy state directly from front to rear
d19e: b5 46                        lda     Enemy_MovingDir,x
d1a0: 99 46 00                     sta     Enemy_MovingDir,y       ;copy moving direction also
d1a3: a5 08                        lda     ObjectOffset            ;save enemy object offset of front to stack
d1a5: 48                           pha
d1a6: ae cf 06                     ldx     DuplicateObj_Offset     ;put enemy object offset of rear as current
d1a9: 86 08                        stx     ObjectOffset
d1ab: a9 2d                        lda     #Bowser                 ;set bowser's enemy identifier
d1ad: 95 16                        sta     Enemy_ID,x              ;store in bowser's rear object
d1af: 20 bc d1                     jsr     ProcessBowserHalf       ;do a sub here to process bowser's rear
d1b2: 68                           pla
d1b3: 85 08                        sta     ObjectOffset            ;get original enemy object offset
d1b5: aa                           tax
d1b6: a9 00                        lda     #$00                    ;nullify bowser's front/rear graphics flag
d1b8: 8d 6a 03                     sta     BowserGfxFlag
d1bb: 60           ExBgfxH         rts                             ;leave!

                   ProcessBowserHalf
d1bc: ee 6a 03                     inc     BowserGfxFlag           ;increment bowser's graphics flag, then run subroutines
d1bf: 20 d7 c8                     jsr     RunRetainerObj          ;to get offscreen bits, relative position and draw bowser (finally!)
d1c2: b5 1e                        lda     Enemy_State,x
d1c4: d0 f5                        bne     ExBgfxH                 ;if either enemy object not in normal state, branch to leave
d1c6: a9 0a                        lda     #$0a
d1c8: 9d 9a 04                     sta     Enemy_BoundBoxCtrl,x    ;set bounding box size control
d1cb: 20 43 e2                     jsr     GetEnemyBoundBox        ;get bounding box coordinates
d1ce: 4c 53 d8                     jmp     PlayerEnemyCollision    ;do player-to-enemy collision detection

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to hold movement force and tile number
                   ; $01 - used to hold sprite attribute data
d1d1: bf 40 bf bf+ FlameTimerData  .bulk   $bf,$40,$bf,$bf,$bf,$40,$40,$bf

d1d9: ac 67 03     SetFlameTimer   ldy     BowserFlameTimerCtrl    ;load counter as offset
d1dc: ee 67 03                     inc     BowserFlameTimerCtrl    ;increment
d1df: ad 67 03                     lda     BowserFlameTimerCtrl    ;mask out all but 3 LSB
d1e2: 29 07                        and     #%00000111              ; to keep in range of 0-7
d1e4: 8d 67 03                     sta     BowserFlameTimerCtrl
d1e7: b9 d1 d1                     lda     FlameTimerData,y        ;load value to be used then leave
d1ea: 60           ExFl            rts

d1eb: ad 47 07     ProcBowserFlame lda     TimerControl            ;if master timer control flag set,
d1ee: d0 30                        bne     SetGfxF                 ; skip all of this
d1f0: a9 40                        lda     #$40                    ;load default movement force
d1f2: ac cc 06                     ldy     SecondaryHardMode
d1f5: f0 02                        beq     SFlmX                   ;if secondary hard mode flag not set, use default
d1f7: a9 60                        lda     #$60                    ;otherwise load alternate movement force to go faster
d1f9: 85 00        SFlmX           sta     $00                     ;store value here
d1fb: bd 01 04                     lda     Enemy_X_MoveForce,x
d1fe: 38                           sec                             ;subtract value from movement force
d1ff: e5 00                        sbc     $00
d201: 9d 01 04                     sta     Enemy_X_MoveForce,x     ;save new value
d204: b5 87                        lda     Enemy_X_Position,x
d206: e9 01                        sbc     #$01                    ;subtract one from horizontal position to move
d208: 95 87                        sta     Enemy_X_Position,x      ; to the left
d20a: b5 6e                        lda     Enemy_PageLoc,x
d20c: e9 00                        sbc     #$00                    ;subtract borrow from page location
d20e: 95 6e                        sta     Enemy_PageLoc,x
d210: bc 17 04                     ldy     BowserFlamePRandomOfs,x ;get some value here and use as offset
d213: b5 cf                        lda     Enemy_Y_Position,x      ;load vertical coordinate
d215: d9 9d c5                     cmp     FlameYPosData,y         ;compare against coordinate data using $0417,x as offset
d218: f0 06                        beq     SetGfxF                 ;if equal, branch and do not modify coordinate
d21a: 18                           clc
d21b: 7d 34 04                     adc     Enemy_Y_MoveForce,x     ;otherwise add value here to coordinate and store
d21e: 95 cf                        sta     Enemy_Y_Position,x      ;as new vertical coordinate
d220: 20 52 f1     SetGfxF         jsr     RelativeEnemyPosition   ;get new relative coordinates
d223: b5 1e                        lda     Enemy_State,x           ;if bowser's flame not in normal state,
d225: d0 c3                        bne     ExFl                    ; branch to leave
d227: a9 51                        lda     #$51                    ;otherwise, continue
d229: 85 00                        sta     $00                     ;write first tile number
d22b: a0 02                        ldy     #$02                    ;load attributes without vertical flip by default
d22d: a5 09                        lda     FrameCounter
d22f: 29 02                        and     #%00000010              ;invert vertical flip bit every 2 frames
d231: f0 02                        beq     FlmeAt                  ;if d1 not set, write default value
d233: a0 82                        ldy     #$82                    ;otherwise write value with vertical flip bit set
d235: 84 01        FlmeAt          sty     $01                     ;set bowser's flame sprite attributes here
d237: bc e5 06                     ldy     Enemy_SprDataOffset,x   ;get OAM data offset
d23a: a2 00                        ldx     #$00
d23c: ad b9 03     DrawFlameLoop   lda     Enemy_Rel_YPos          ;get Y relative coordinate of current enemy object
d23f: 99 00 02                     sta     Sprite_Y_Position,y     ;write into Y coordinate of OAM data
d242: a5 00                        lda     $00
d244: 99 01 02                     sta     Sprite_Tilenumber,y     ;write current tile number into OAM data
d247: e6 00                        inc     $00                     ;increment tile number to draw more bowser's flame
d249: a5 01                        lda     $01
d24b: 99 02 02                     sta     Sprite_Attributes,y     ;write saved attributes into OAM data
d24e: ad ae 03                     lda     Enemy_Rel_XPos
d251: 99 03 02                     sta     Sprite_X_Position,y     ;write X relative coordinate of current enemy object
d254: 18                           clc
d255: 69 08                        adc     #$08
d257: 8d ae 03                     sta     Enemy_Rel_XPos          ;then add eight to it and store
d25a: c8                           iny
d25b: c8                           iny
d25c: c8                           iny
d25d: c8                           iny                             ;increment Y four times to move onto the next OAM
d25e: e8                           inx                             ;move onto the next OAM, and branch if three
d25f: e0 03                        cpx     #$03                    ; have not yet been done
d261: 90 d9                        bcc     DrawFlameLoop
d263: a6 08                        ldx     ObjectOffset            ;reload original enemy offset
d265: 20 af f1                     jsr     GetEnemyOffscreenBits   ;get offscreen information
d268: bc e5 06                     ldy     Enemy_SprDataOffset,x   ;get OAM data offset
d26b: ad d1 03                     lda     Enemy_OffscreenBits     ;get enemy object offscreen bits
d26e: 4a                           lsr     A                       ;move d0 to carry and result to stack
d26f: 48                           pha
d270: 90 05                        bcc     M3FOfs                  ;branch if carry not set
d272: a9 f8                        lda     #$f8                    ;otherwise move sprite offscreen, this part likely
d274: 99 0c 02                     sta     Sprite_Y_Position+12,y  ; residual since flame is only made of three sprites
d277: 68           M3FOfs          pla                             ;get bits from stack
d278: 4a                           lsr     A                       ;move d1 to carry and move bits back to stack
d279: 48                           pha
d27a: 90 05                        bcc     M2FOfs                  ;branch if carry not set again
d27c: a9 f8                        lda     #$f8                    ;otherwise move third sprite offscreen
d27e: 99 08 02                     sta     Sprite_Y_Position+8,y
d281: 68           M2FOfs          pla                             ;get bits from stack again
d282: 4a                           lsr     A                       ;move d2 to carry and move bits back to stack again
d283: 48                           pha
d284: 90 05                        bcc     M1FOfs                  ;branch if carry not set yet again
d286: a9 f8                        lda     #$f8                    ;otherwise move second sprite offscreen
d288: 99 04 02                     sta     Sprite_Y_Position+4,y
d28b: 68           M1FOfs          pla                             ;get bits from stack one last time
d28c: 4a                           lsr     A                       ;move d3 to carry
d28d: 90 05                        bcc     ExFlmeD                 ;branch if carry not set one last time
d28f: a9 f8                        lda     #$f8
d291: 99 00 02                     sta     Sprite_Y_Position,y     ;otherwise move first sprite offscreen
d294: 60           ExFlmeD         rts                             ;leave

                   ; -----------------------------------------------------------------------------
d295: d6 a0        RunFireworks    dec     ExplosionTimerCounter,x ;decrement explosion timing counter here
d297: d0 0c                        bne     SetupExpl               ;if not expired, skip this part
d299: a9 08                        lda     #$08
d29b: 95 a0                        sta     ExplosionTimerCounter,x ;reset counter
d29d: f6 58                        inc     ExplosionGfxCounter,x   ;increment explosion graphics counter
d29f: b5 58                        lda     ExplosionGfxCounter,x
d2a1: c9 03                        cmp     #$03                    ;check explosion graphics counter
d2a3: b0 18                        bcs     FireworksSoundScore     ;if at a certain point, branch to kill this object
d2a5: 20 52 f1     SetupExpl       jsr     RelativeEnemyPosition   ;get relative coordinates of explosion
d2a8: ad b9 03                     lda     Enemy_Rel_YPos          ;copy relative coordinates
d2ab: 8d ba 03                     sta     Fireball_Rel_YPos       ;from the enemy object to the fireball object
d2ae: ad ae 03                     lda     Enemy_Rel_XPos          ;first vertical, then horizontal
d2b1: 8d af 03                     sta     Fireball_Rel_XPos
d2b4: bc e5 06                     ldy     Enemy_SprDataOffset,x   ;get OAM data offset
d2b7: b5 58                        lda     ExplosionGfxCounter,x   ;get explosion graphics counter
d2b9: 20 17 ed                     jsr     DrawExplosion_Fireworks ;do a sub to draw the explosion then leave
d2bc: 60                           rts

                   FireworksSoundScore
d2bd: a9 00                        lda     #$00                    ;disable enemy buffer flag
d2bf: 95 0f                        sta     Enemy_Flag,x
d2c1: a9 08                        lda     #Sfx_Blast              ;play fireworks/gunfire sound
d2c3: 85 fe                        sta     Square2SoundQueue
d2c5: a9 05                        lda     #$05                    ;set part of score modifier for 500 points
d2c7: 8d 38 01                     sta     DigitModifier+4
d2ca: 4c 36 d3                     jmp     EndAreaPoints           ;jump to award points accordingly then leave

                   ; -----------------------------------------------------------------------------
                   StarFlagYPosAdder
d2cd: 00 00 08 08                  .bulk   $00,$00,$08,$08
                   StarFlagXPosAdder
d2d1: 00 08 00 08                  .bulk   $00,$08,$00,$08
                   StarFlagTileData
d2d5: 54 55 56 57                  .bulk   $54,$55,$56,$57

d2d9: a9 00        RunStarFlagObj  lda     #$00                    ;initialize enemy frenzy buffer
d2db: 8d cb 06                     sta     EnemyFrenzyBuffer
d2de: ad 46 07                     lda     StarFlagTaskControl     ;check star flag object task number here
d2e1: c9 05                        cmp     #$05                    ;if greater than 5, branch to exit
d2e3: b0 2c                        bcs     StarFlagExit
d2e5: 20 04 8e                     jsr     JumpEngine              ;otherwise jump to appropriate sub

d2e8: 11 d3                        .dd2    StarFlagExit
d2ea: f2 d2                        .dd2    GameTimerFireworks
d2ec: 12 d3                        .dd2    AwardGameTimerPoints
d2ee: 4e d3                        .dd2    RaiseFlagSetoffFworks
d2f0: a2 d3                        .dd2    DelayToAreaEnd

                   GameTimerFireworks
d2f2: a0 05                        ldy     #$05                    ;set default state for star flag object
d2f4: ad fa 07                     lda     GameTimerDisplay+2      ;get game timer's last digit
d2f7: c9 01                        cmp     #$01
d2f9: f0 0e                        beq     SetFWC                  ;if last digit of game timer set to 1, skip ahead
d2fb: a0 03                        ldy     #$03                    ;otherwise load new value for state
d2fd: c9 03                        cmp     #$03
d2ff: f0 08                        beq     SetFWC                  ;if last digit of game timer set to 3, skip ahead
d301: a0 00                        ldy     #$00                    ;otherwise load one more potential value for state
d303: c9 06                        cmp     #$06
d305: f0 02                        beq     SetFWC                  ;if last digit of game timer set to 6, skip ahead
d307: a9 ff                        lda     #$ff                    ;otherwise set value for no fireworks
d309: 8d d7 06     SetFWC          sta     FireworksCounter        ;set fireworks counter here
d30c: 94 1e                        sty     Enemy_State,x           ;set whatever state we have in star flag object
                   IncrementSFTask1
d30e: ee 46 07                     inc     StarFlagTaskControl     ;increment star flag object task number
d311: 60           StarFlagExit    rts                             ;leave

                   AwardGameTimerPoints
d312: ad f8 07                     lda     GameTimerDisplay        ;check all game timer digits for any intervals left
d315: 0d f9 07                     ora     GameTimerDisplay+1
d318: 0d fa 07                     ora     GameTimerDisplay+2
d31b: f0 f1                        beq     IncrementSFTask1        ;if no time left on game timer at all, branch to next task
d31d: a5 09                        lda     FrameCounter
d31f: 29 04                        and     #%00000100              ;check frame counter for d2 set (skip ahead
d321: f0 04                        beq     NoTTick                 ; for four frames every four frames) branch if not set
d323: a9 10                        lda     #Sfx_TimerTick
d325: 85 fe                        sta     Square2SoundQueue       ;load timer tick sound
d327: a0 23        NoTTick         ldy     #$23                    ;set offset here to subtract from game timer's last digit
d329: a9 ff                        lda     #$ff                    ;set adder here to $ff, or -1, to subtract one
d32b: 8d 39 01                     sta     DigitModifier+5         ; from the last digit of the game timer
d32e: 20 5f 8f                     jsr     DigitsMathRoutine       ;subtract digit
d331: a9 05                        lda     #$05                    ;set now to add 50 points
d333: 8d 39 01                     sta     DigitModifier+5         ;per game timer interval subtracted
d336: a0 0b        EndAreaPoints   ldy     #$0b                    ;load offset for mario's score by default
d338: ad 53 07                     lda     CurrentPlayer           ;check player on the screen
d33b: f0 02                        beq     ELPGive                 ;if mario, do not change
d33d: a0 11                        ldy     #$11                    ;otherwise load offset for luigi's score
d33f: 20 5f 8f     ELPGive         jsr     DigitsMathRoutine       ;award 50 points per game timer interval
d342: ad 53 07                     lda     CurrentPlayer           ;get player on the screen (or 500 points per
d345: 0a                           asl     A                       ; fireworks explosion if branched here from there)
d346: 0a                           asl     A                       ;shift to high nybble
d347: 0a                           asl     A
d348: 0a                           asl     A
d349: 09 04                        ora     #%00000100              ;add four to set nybble for game timer
d34b: 4c 36 bc                     jmp     UpdateNumber            ;jump to print the new score and game timer

                   RaiseFlagSetoffFworks
d34e: b5 cf                        lda     Enemy_Y_Position,x      ;check star flag's vertical position
d350: c9 72                        cmp     #$72                    ;against preset value
d352: 90 05                        bcc     SetoffF                 ;if star flag higher vertically, branch to other code
d354: d6 cf                        dec     Enemy_Y_Position,x      ;otherwise, raise star flag by one pixel
d356: 4c 65 d3                     jmp     DrawStarFlag            ; and skip this part here

d359: ad d7 06     SetoffF         lda     FireworksCounter        ;check fireworks counter
d35c: f0 38                        beq     DrawFlagSetTimer        ;if no fireworks left to go off, skip this part
d35e: 30 36                        bmi     DrawFlagSetTimer        ;if no fireworks set to go off, skip this part
d360: a9 16                        lda     #Fireworks
d362: 8d cb 06                     sta     EnemyFrenzyBuffer       ;otherwise set fireworks object in frenzy queue
                   ; 
d365: 20 52 f1     DrawStarFlag    jsr     RelativeEnemyPosition   ;get relative coordinates of star flag
d368: bc e5 06                     ldy     Enemy_SprDataOffset,x   ;get OAM data offset
d36b: a2 03                        ldx     #$03                    ;do four sprites
d36d: ad b9 03     DSFloop         lda     Enemy_Rel_YPos          ;get relative vertical coordinate
d370: 18                           clc
d371: 7d cd d2                     adc     StarFlagYPosAdder,x     ;add Y coordinate adder data
d374: 99 00 02                     sta     Sprite_Y_Position,y     ;store as Y coordinate
d377: bd d5 d2                     lda     StarFlagTileData,x      ;get tile number
d37a: 99 01 02                     sta     Sprite_Tilenumber,y     ;store as tile number
d37d: a9 22                        lda     #$22                    ;set palette and background priority bits
d37f: 99 02 02                     sta     Sprite_Attributes,y     ;store as attributes
d382: ad ae 03                     lda     Enemy_Rel_XPos          ;get relative horizontal coordinate
d385: 18                           clc
d386: 7d d1 d2                     adc     StarFlagXPosAdder,x     ;add X coordinate adder data
d389: 99 03 02                     sta     Sprite_X_Position,y     ;store as X coordinate
d38c: c8                           iny
d38d: c8                           iny                             ;increment OAM data offset four bytes
d38e: c8                           iny                             ; for next sprite
d38f: c8                           iny
d390: ca                           dex                             ;move onto next sprite
d391: 10 da                        bpl     DSFloop                 ;do this until all sprites are done
d393: a6 08                        ldx     ObjectOffset            ;get enemy object offset and leave
d395: 60                           rts

                   DrawFlagSetTimer
d396: 20 65 d3                     jsr     DrawStarFlag            ;do sub to draw star flag
d399: a9 06                        lda     #$06
d39b: 9d 96 07                     sta     EnemyIntervalTimer,x    ;set interval timer here
                   IncrementSFTask2
d39e: ee 46 07                     inc     StarFlagTaskControl     ;move onto next task
d3a1: 60                           rts

d3a2: 20 65 d3     DelayToAreaEnd  jsr     DrawStarFlag            ;do sub to draw star flag
d3a5: bd 96 07                     lda     EnemyIntervalTimer,x    ;if interval timer set in previous task
d3a8: d0 05                        bne     StarFlagExit2           ;not yet expired, branch to leave
d3aa: ad b1 07                     lda     EventMusicBuffer        ;if event music buffer empty,
d3ad: f0 ef                        beq     IncrementSFTask2        ;branch to increment task
d3af: 60           StarFlagExit2   rts                             ;otherwise leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to store horizontal difference between player and piranha plant
                   MovePiranhaPlant
d3b0: b5 1e                        lda     Enemy_State,x           ;check enemy state
d3b2: d0 56                        bne     PutinPipe               ;if set at all, branch to leave
d3b4: bd 8a 07                     lda     EnemyFrameTimer,x       ;check enemy's timer here
d3b7: d0 51                        bne     PutinPipe               ;branch to end if not yet expired
d3b9: b5 a0                        lda     PiranhaPlant_MoveFlag,x ;check movement flag
d3bb: d0 23                        bne     SetupToMovePPlant       ;if moving, skip to part ahead
d3bd: b5 58                        lda     PiranhaPlant_Y_Speed,x  ;if currently rising, branch 
d3bf: 30 14                        bmi     ReversePlantSpeed       ;to move enemy upwards out of pipe
d3c1: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and
d3c4: 10 09                        bpl     ChkPlayerNearPipe       ; piranha plant, and branch if enemy to right of player
d3c6: a5 00                        lda     $00                     ;otherwise get saved horizontal difference
d3c8: 49 ff                        eor     #$ff
d3ca: 18                           clc                             ;and change to two's compliment
d3cb: 69 01                        adc     #$01
d3cd: 85 00                        sta     $00                     ;save as new horizontal difference
                   ChkPlayerNearPipe
d3cf: a5 00                        lda     $00                     ;get saved horizontal difference
d3d1: c9 21                        cmp     #$21
d3d3: 90 35                        bcc     PutinPipe               ;if player within a certain distance, branch to leave
                   ReversePlantSpeed
d3d5: b5 58                        lda     PiranhaPlant_Y_Speed,x  ;get vertical speed
d3d7: 49 ff                        eor     #$ff
d3d9: 18                           clc                             ;change to two's compliment
d3da: 69 01                        adc     #$01
d3dc: 95 58                        sta     PiranhaPlant_Y_Speed,x  ;save as new vertical speed
d3de: f6 a0                        inc     PiranhaPlant_MoveFlag,x ;increment to set movement flag
                   SetupToMovePPlant
d3e0: bd 34 04                     lda     PiranhaPlantDownYPos,x  ;get original vertical coordinate (lowest point)
d3e3: b4 58                        ldy     PiranhaPlant_Y_Speed,x  ;get vertical speed
d3e5: 10 03                        bpl     RiseFallPiranhaPlant    ;branch if moving downwards
d3e7: bd 17 04                     lda     PiranhaPlantUpYPos,x    ;otherwise get other vertical coordinate (highest point)
                   RiseFallPiranhaPlant
d3ea: 85 00                        sta     $00                     ;save vertical coordinate here
d3ec: a5 09                        lda     FrameCounter            ;get frame counter
d3ee: 4a                           lsr     A
d3ef: 90 19                        bcc     PutinPipe               ;branch to leave if d0 set (execute code every other frame)
d3f1: ad 47 07                     lda     TimerControl            ;get master timer control
d3f4: d0 14                        bne     PutinPipe               ;branch to leave if set (likely not necessary)
d3f6: b5 cf                        lda     Enemy_Y_Position,x      ;get current vertical coordinate
d3f8: 18                           clc
d3f9: 75 58                        adc     PiranhaPlant_Y_Speed,x  ;add vertical speed to move up or down
d3fb: 95 cf                        sta     Enemy_Y_Position,x      ;save as new vertical coordinate
d3fd: c5 00                        cmp     $00                     ;compare against low or high coordinate
d3ff: d0 09                        bne     PutinPipe               ;branch to leave if not yet reached
d401: a9 00                        lda     #$00
d403: 95 a0                        sta     PiranhaPlant_MoveFlag,x ;otherwise clear movement flag
d405: a9 40                        lda     #$40
d407: 9d 8a 07                     sta     EnemyFrameTimer,x       ;set timer to delay piranha plant movement
d40a: a9 20        PutinPipe       lda     #%00100000              ;set background priority bit in sprite
d40c: 9d c5 03                     sta     Enemy_SprAttrib,x       ; attributes to give illusion of being inside pipe
d40f: 60                           rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   ; $07 - spinning speed
d410: 85 07        FirebarSpin     sta     $07                     ;save spinning speed here
d412: b5 34                        lda     FirebarSpinDirection,x  ;check spinning direction
d414: d0 0e                        bne     SpinCounterClockwise    ;if moving counter-clockwise, branch to other part
d416: a0 18                        ldy     #$18                    ;possibly residual ldy
d418: b5 58                        lda     FirebarSpinState_Low,x
d41a: 18                           clc                             ;add spinning speed to what would normally be
d41b: 65 07                        adc     $07                     ; the horizontal speed
d41d: 95 58                        sta     FirebarSpinState_Low,x
d41f: b5 a0                        lda     FirebarSpinState_High,x ;add carry to what would normally be the vertical speed
d421: 69 00                        adc     #$00
d423: 60                           rts

                   SpinCounterClockwise
d424: a0 08                        ldy     #$08                    ;possibly residual ldy
d426: b5 58                        lda     FirebarSpinState_Low,x
d428: 38                           sec                             ;subtract spinning speed to what would normally be
d429: e5 07                        sbc     $07                     ; the horizontal speed
d42b: 95 58                        sta     FirebarSpinState_Low,x
d42d: b5 a0                        lda     FirebarSpinState_High,x ;add carry to what would normally be the vertical speed
d42f: e9 00                        sbc     #$00
d431: 60                           rts

                   ; -----------------------------------------------------------------------------
                   ; $00 - used to hold collision flag, Y movement force + 5 or low byte of name
                   ; table for rope
                   ; $01 - used to hold high byte of name table for rope
                   ; $02 - used to hold page location of rope
d432: b5 b6        BalancePlatform lda     Enemy_Y_HighPos,x       ;check high byte of vertical position
d434: c9 03                        cmp     #$03
d436: d0 03                        bne     DoBPl
d438: 4c 98 c9                     jmp     EraseEnemyObject        ;if far below screen, kill the object

d43b: b5 1e        DoBPl           lda     Enemy_State,x           ;get object's state (set to $ff or other platform offset)
d43d: 10 01                        bpl     CheckBalPlatform        ;if doing other balance platform, branch to leave
d43f: 60                           rts

                   CheckBalPlatform
d440: a8                           tay                             ;save offset from state as Y
d441: bd a2 03                     lda     PlatformCollisionFlag,x ;get collision flag of platform
d444: 85 00                        sta     $00                     ;store here
d446: b5 46                        lda     Enemy_MovingDir,x       ;get moving direction
d448: f0 03                        beq     ChkForFall
d44a: 4c bb d5                     jmp     PlatformFall            ;if set, jump here

d44d: a9 2d        ChkForFall      lda     #$2d                    ;check if platform is above a certain point
d44f: d5 cf                        cmp     Enemy_Y_Position,x
d451: 90 0f                        bcc     ChkOtherForFall         ;if not, branch elsewhere
d453: c4 00                        cpy     $00                     ;if collision flag is set to same value as
d455: f0 08                        beq     MakePlatformFall        ; enemy state, branch to make platforms fall
d457: 18                           clc
d458: 69 02                        adc     #$02                    ;otherwise add 2 pixels to vertical position
d45a: 95 cf                        sta     Enemy_Y_Position,x      ; of current platform and branch elsewhere
d45c: 4c b1 d5                     jmp     StopPlatforms           ; to make platforms stop

                   MakePlatformFall
d45f: 4c 98 d5                     jmp     InitPlatformFall        ;make platforms fall

d462: d9 cf 00     ChkOtherForFall cmp     Enemy_Y_Position,y      ;check if other platform is above a certain point
d465: 90 0d                        bcc     ChkToMoveBalPlat        ;if not, branch elsewhere
d467: e4 00                        cpx     $00                     ;if collision flag is set to same value as
d469: f0 f4                        beq     MakePlatformFall        ; enemy state, branch to make platforms fall
d46b: 18                           clc
d46c: 69 02                        adc     #$02                    ;otherwise add 2 pixels to vertical position
d46e: 99 cf 00                     sta     Enemy_Y_Position,y      ; of other platform and branch elsewhere
d471: 4c b1 d5                     jmp     StopPlatforms           ;jump to stop movement and do not return

                   ChkToMoveBalPlat
d474: b5 cf                        lda     Enemy_Y_Position,x      ;save vertical position to stack
d476: 48                           pha
d477: bd a2 03                     lda     PlatformCollisionFlag,x ;get collision flag
d47a: 10 18                        bpl     ColFlg                  ;branch if collision
d47c: bd 34 04                     lda     Enemy_Y_MoveForce,x
d47f: 18                           clc                             ;add $05 to contents of moveforce, whatever they be
d480: 69 05                        adc     #$05
d482: 85 00                        sta     $00                     ;store here
d484: b5 a0                        lda     Enemy_Y_Speed,x
d486: 69 00                        adc     #$00                    ;add carry to vertical speed
d488: 30 1a                        bmi     PlatDn                  ;branch if moving downwards
d48a: d0 0c                        bne     PlatUp                  ;branch elsewhere if moving upwards
d48c: a5 00                        lda     $00
d48e: c9 0b                        cmp     #$0b                    ;check if there's still a little force left
d490: 90 0c                        bcc     PlatSt                  ;if not enough, branch to stop movement
d492: b0 04                        bcs     PlatUp                  ;otherwise keep branch to move upwards

d494: c5 08        ColFlg          cmp     ObjectOffset            ;if collision flag matches
d496: f0 0c                        beq     PlatDn                  ; current enemy object offset, branch
d498: 20 b7 bf     PlatUp          jsr     MovePlatformUp          ;do a sub to move upwards
d49b: 4c a7 d4                     jmp     DoOtherPlatform         ;jump ahead to remaining code

d49e: 20 b1 d5     PlatSt          jsr     StopPlatforms           ;do a sub to stop movement
d4a1: 4c a7 d4                     jmp     DoOtherPlatform         ;jump ahead to remaining code

d4a4: 20 b4 bf     PlatDn          jsr     MovePlatformDown        ;do a sub to move downwards
d4a7: b4 1e        DoOtherPlatform ldy     Enemy_State,x           ;get offset of other platform
d4a9: 68                           pla                             ;get old vertical coordinate from stack
d4aa: 38                           sec
d4ab: f5 cf                        sbc     Enemy_Y_Position,x      ;get difference of old vs. new coordinate
d4ad: 18                           clc
d4ae: 79 cf 00                     adc     Enemy_Y_Position,y      ;add difference to vertical coordinate of other
d4b1: 99 cf 00                     sta     Enemy_Y_Position,y      ; platform to move it in the opposite direction
d4b4: bd a2 03                     lda     PlatformCollisionFlag,x ;if no collision, skip this part here
d4b7: 30 04                        bmi     DrawEraseRope
d4b9: aa                           tax                             ;put offset which collision occurred here
d4ba: 20 21 dc                     jsr     PositionPlayerOnVPlat   ; and use it to position player accordingly
d4bd: a4 08        DrawEraseRope   ldy     ObjectOffset            ;get enemy object offset
d4bf: b9 a0 00                     lda     Enemy_Y_Speed,y         ;check to see if current platform is
d4c2: 19 34 04                     ora     Enemy_Y_MoveForce,y     ; moving at all
d4c5: f0 77                        beq     ExitRp                  ;if not, skip all of this and branch to leave
d4c7: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;get vram buffer offset
d4ca: e0 20                        cpx     #$20                    ;if offset beyond a certain point, go ahead
d4cc: b0 70                        bcs     ExitRp                  ; and skip this, branch to leave
d4ce: b9 a0 00                     lda     Enemy_Y_Speed,y
d4d1: 48                           pha                             ;save two copies of vertical speed to stack
d4d2: 48                           pha
d4d3: 20 41 d5                     jsr     SetupPlatformRope       ;do a sub to figure out where to put new bg tiles
d4d6: a5 01                        lda     $01                     ;write name table address to vram buffer
d4d8: 9d 01 03                     sta     VRAM_Buffer1,x          ;first the high byte, then the low
d4db: a5 00                        lda     $00
d4dd: 9d 02 03                     sta     VRAM_Buffer1+1,x
d4e0: a9 02                        lda     #$02                    ;set length for 2 bytes
d4e2: 9d 03 03                     sta     VRAM_Buffer1+2,x
d4e5: b9 a0 00                     lda     Enemy_Y_Speed,y         ;if platform moving upwards, branch 
d4e8: 30 0d                        bmi     EraseR1                 ; to do something else
d4ea: a9 a2                        lda     #$a2
d4ec: 9d 04 03                     sta     VRAM_Buffer1+3,x        ;otherwise put tile numbers for left
d4ef: a9 a3                        lda     #$a3                    ; and right sides of rope in vram buffer
d4f1: 9d 05 03                     sta     VRAM_Buffer1+4,x
d4f4: 4c ff d4                     jmp     OtherRope               ;jump to skip this part

d4f7: a9 24        EraseR1         lda     #$24                    ;put blank tiles in vram buffer
d4f9: 9d 04 03                     sta     VRAM_Buffer1+3,x        ; to erase rope
d4fc: 9d 05 03                     sta     VRAM_Buffer1+4,x
d4ff: b9 1e 00     OtherRope       lda     Enemy_State,y           ;get offset of other platform from state
d502: a8                           tay                             ;use as Y here
d503: 68                           pla                             ;pull second copy of vertical speed from stack
d504: 49 ff                        eor     #$ff                    ;invert bits to reverse speed
d506: 20 41 d5                     jsr     SetupPlatformRope       ;do sub again to figure out where to put bg tiles
d509: a5 01                        lda     $01                     ;write name table address to vram buffer
d50b: 9d 06 03                     sta     VRAM_Buffer1+5,x        ;this time we're doing putting tiles for
d50e: a5 00                        lda     $00                     ; the other platform
d510: 9d 07 03                     sta     VRAM_Buffer1+6,x
d513: a9 02                        lda     #$02
d515: 9d 08 03                     sta     VRAM_Buffer1+7,x        ;set length again for 2 bytes
d518: 68                           pla                             ;pull first copy of vertical speed from stack
d519: 10 0d                        bpl     EraseR2                 ;if moving upwards (note inversion earlier), skip this
d51b: a9 a2                        lda     #$a2
d51d: 9d 09 03                     sta     VRAM_Buffer1+8,x        ;otherwise put tile numbers for left
d520: a9 a3                        lda     #$a3                    ; and right sides of rope in vram
d522: 9d 0a 03                     sta     VRAM_Buffer1+9,x        ;transfer buffer
d525: 4c 30 d5                     jmp     EndRp                   ;jump to skip this part

d528: a9 24        EraseR2         lda     #$24                    ;put blank tiles in vram buffer
d52a: 9d 09 03                     sta     VRAM_Buffer1+8,x        ; to erase rope
d52d: 9d 0a 03                     sta     VRAM_Buffer1+9,x
d530: a9 00        EndRp           lda     #$00                    ;put null terminator at the end
d532: 9d 0b 03                     sta     VRAM_Buffer1+10,x
d535: ad 00 03                     lda     VRAM_Buffer1_Offset     ;add ten bytes to the vram buffer offset
d538: 18                           clc                             ; and store
d539: 69 0a                        adc     #$0a
d53b: 8d 00 03                     sta     VRAM_Buffer1_Offset
d53e: a6 08        ExitRp          ldx     ObjectOffset            ;get enemy object buffer offset and leave
d540: 60                           rts

                   SetupPlatformRope
d541: 48                           pha                             ;save second/third copy to stack
d542: b9 87 00                     lda     Enemy_X_Position,y      ;get horizontal coordinate
d545: 18                           clc
d546: 69 08                        adc     #$08                    ;add eight pixels
d548: ae cc 06                     ldx     SecondaryHardMode       ;if secondary hard mode flag set,
d54b: d0 03                        bne     GetLRp                  ; use coordinate as-is
d54d: 18                           clc
d54e: 69 10                        adc     #$10                    ;otherwise add sixteen more pixels
d550: 48           GetLRp          pha                             ;save modified horizontal coordinate to stack
d551: b9 6e 00                     lda     Enemy_PageLoc,y
d554: 69 00                        adc     #$00                    ;add carry to page location
d556: 85 02                        sta     $02                     ; and save here
d558: 68                           pla                             ;pull modified horizontal coordinate
d559: 29 f0                        and     #%11110000              ; from the stack, mask out low nybble
d55b: 4a                           lsr     A                       ; and shift three bits to the right
d55c: 4a                           lsr     A
d55d: 4a                           lsr     A
d55e: 85 00                        sta     $00                     ;store result here as part of name table low byte
d560: b6 cf                        ldx     Enemy_Y_Position,y      ;get vertical coordinate
d562: 68                           pla                             ;get second/third copy of vertical speed from stack
d563: 10 05                        bpl     GetHRp                  ;skip this part if moving downwards or not at all
d565: 8a                           txa
d566: 18                           clc
d567: 69 08                        adc     #$08                    ;add eight to vertical coordinate and
d569: aa                           tax                             ; save as X
d56a: 8a           GetHRp          txa                             ;move vertical coordinate to A
d56b: ae 00 03                     ldx     VRAM_Buffer1_Offset     ;get vram buffer offset
d56e: 0a                           asl     A
d56f: 2a                           rol     A                       ;rotate d7 to d0 and d6 into carry
d570: 48                           pha                             ;save modified vertical coordinate to stack
d571: 2a                           rol     A                       ;rotate carry to d0, thus d7 and d6 are at 2 LSB
d572: 29 03                        and     #%00000011              ;mask out all bits but d7 and d6, then set
d574: 09 20                        ora     #%00100000              ; d5 to get appropriate high byte of name table
d576: 85 01                        sta     $01                     ; address, then store
d578: a5 02                        lda     $02                     ;get saved page location from earlier
d57a: 29 01                        and     #$01                    ;mask out all but LSB
d57c: 0a                           asl     A
d57d: 0a                           asl     A                       ;shift twice to the left and save with the
d57e: 05 01                        ora     $01                     ; rest of the bits of the high byte, to get
d580: 85 01                        sta     $01                     ; the proper name table and the right place on it
d582: 68                           pla                             ;get modified vertical coordinate from stack
d583: 29 e0                        and     #%11100000              ;mask out low nybble and LSB of high nybble
d585: 18                           clc
d586: 65 00                        adc     $00                     ;add to horizontal part saved here
d588: 85 00                        sta     $00                     ;save as name table low byte
d58a: b9 cf 00                     lda     Enemy_Y_Position,y
d58d: c9 e8                        cmp     #$e8                    ;if vertical position not below the
d58f: 90 06                        bcc     ExPRp                   ; bottom of the screen, we're done, branch to leave
d591: a5 00                        lda     $00
d593: 29 bf                        and     #%10111111              ;mask out d6 of low byte of name table address
d595: 85 00                        sta     $00
d597: 60           ExPRp           rts                             ;leave!

                   InitPlatformFall
d598: 98                           tya                             ;move offset of other platform from Y to X
d599: aa                           tax
d59a: 20 af f1                     jsr     GetEnemyOffscreenBits   ;get offscreen bits
d59d: a9 06                        lda     #$06
d59f: 20 11 da                     jsr     SetupFloateyNumber      ;award 1000 points to player
d5a2: ad ad 03                     lda     Player_Rel_XPos
d5a5: 9d 17 01                     sta     FloateyNum_X_Pos,x      ;put floatey number coordinates where player is
d5a8: a5 ce                        lda     Player_Y_Position
d5aa: 9d 1e 01                     sta     FloateyNum_Y_Pos,x
d5ad: a9 01                        lda     #$01                    ;set moving direction as flag for
d5af: 95 46                        sta     Enemy_MovingDir,x       ; falling platforms
d5b1: 20 63 c3     StopPlatforms   jsr     InitVStf                ;initialize vertical speed and low byte
d5b4: 99 a0 00                     sta     Enemy_Y_Speed,y         ; for both platforms and leave
d5b7: 99 34 04                     sta     Enemy_Y_MoveForce,y
d5ba: 60                           rts

d5bb: 98           PlatformFall    tya                             ;save offset for other platform to stack
d5bc: 48                           pha
d5bd: 20 6b bf                     jsr     MoveFallingPlatform     ;make current platform fall
d5c0: 68                           pla
d5c1: aa                           tax                             ;pull offset from stack and save to X
d5c2: 20 6b bf                     jsr     MoveFallingPlatform     ;make other platform fall
d5c5: a6 08                        ldx     ObjectOffset
d5c7: bd a2 03                     lda     PlatformCollisionFlag,x ;if player not standing on either platform,
d5ca: 30 04                        bmi     ExPF                    ; skip this part
d5cc: aa                           tax                             ;transfer collision flag offset as offset to X
d5cd: 20 21 dc                     jsr     PositionPlayerOnVPlat   ; and position player appropriately
d5d0: a6 08        ExPF            ldx     ObjectOffset            ;get enemy object buffer offset and leave
d5d2: 60                           rts

                   ; -----------------------------------------------------------------------------
d5d3: b5 a0        YMovingPlatform lda     Enemy_Y_Speed,x         ;if platform moving up or down, skip ahead to
d5d5: 1d 34 04                     ora     Enemy_Y_MoveForce,x     ; check on other position
d5d8: d0 15                        bne     ChkYCenterPos
d5da: 9d 17 04                     sta     Enemy_YMF_Dummy,x       ;initialize dummy variable
d5dd: b5 cf                        lda     Enemy_Y_Position,x
d5df: dd 01 04                     cmp     YPlatformTopYPos,x      ;if current vertical position => top position, branch
d5e2: b0 0b                        bcs     ChkYCenterPos           ; ahead of all this
d5e4: a5 09                        lda     FrameCounter
d5e6: 29 07                        and     #%00000111              ;check for every eighth frame
d5e8: d0 02                        bne     SkipIY
d5ea: f6 cf                        inc     Enemy_Y_Position,x      ;increase vertical position every eighth frame
d5ec: 4c fe d5     SkipIY          jmp     ChkYPCollision          ;skip ahead to last part

d5ef: b5 cf        ChkYCenterPos   lda     Enemy_Y_Position,x      ;if current vertical position < central position, branch
d5f1: d5 58                        cmp     YPlatformCenterYPos,x   ; to slow ascent/move downwards
d5f3: 90 06                        bcc     YMDown
d5f5: 20 b7 bf                     jsr     MovePlatformUp          ;otherwise start slowing descent/moving upwards
d5f8: 4c fe d5                     jmp     ChkYPCollision

d5fb: 20 b4 bf     YMDown          jsr     MovePlatformDown        ;start slowing ascent/moving downwards
d5fe: bd a2 03     ChkYPCollision  lda     HammerThrowingTimer,x   ;if collision flag not set here, branch
d601: 30 03                        bmi     ExYPl                   ; to leave
d603: 20 21 dc                     jsr     PositionPlayerOnVPlat   ;otherwise position player appropriately
d606: 60           ExYPl           rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - used as adder to position player hotizontally
d607: a9 0e        XMovingPlatform lda     #$0e                    ;load preset maximum value for secondary counter
d609: 20 47 cb                     jsr     XMoveCntr_Platform      ;do a sub to increment counters for movement
d60c: 20 66 cb                     jsr     MoveWithXMCntrs         ;do a sub to move platform accordingly, and return value
d60f: bd a2 03                     lda     PlatformCollisionFlag,x ;if no collision with player,
d612: 30 1c                        bmi     ExXMP                   ; branch ahead to leave
                   PositionPlayerOnHPlat
d614: a5 86                        lda     Player_X_Position
d616: 18                           clc                             ;add saved value from second subroutine to
d617: 65 00                        adc     $00                     ; current player's position to position
d619: 85 86                        sta     Player_X_Position       ; player accordingly in horizontal position
d61b: a5 6d                        lda     Player_PageLoc          ;get player's page location
d61d: a4 00                        ldy     $00                     ;check to see if saved value here is positive or negative
d61f: 30 05                        bmi     PPHSubt                 ;if negative, branch to subtract
d621: 69 00                        adc     #$00                    ;otherwise add carry to page location
d623: 4c 28 d6                     jmp     SetPVar                 ;jump to skip subtraction

d626: e9 00        PPHSubt         sbc     #$00                    ;subtract borrow from page location
d628: 85 6d        SetPVar         sta     Player_PageLoc          ;save result to player's page location
d62a: 8c a1 03                     sty     Platform_X_Scroll       ;put saved value from second sub here to be used later
d62d: 20 21 dc                     jsr     PositionPlayerOnVPlat   ;position player vertically and appropriately
d630: 60           ExXMP           rts                             ;and we are done here

                   ; -----------------------------------------------------------------------------
d631: bd a2 03     DropPlatform    lda     PlatformCollisionFlag,x ;if no collision between platform and player
d634: 30 06                        bmi     ExDPl                   ; occurred, just leave without moving anything
d636: 20 88 bf                     jsr     MoveDropPlatform        ;otherwise do a sub to move platform down very quickly
d639: 20 21 dc                     jsr     PositionPlayerOnVPlat   ;do a sub to position player appropriately
d63c: 60           ExDPl           rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - residual value from sub
d63d: 20 02 bf     RightPlatform   jsr     MoveEnemyHorizontally   ;move platform with current horizontal speed, if any
d640: 85 00                        sta     $00                     ;store saved value here (residual code)
d642: bd a2 03                     lda     PlatformCollisionFlag,x ;check collision flag, if no collision between player
d645: 30 07                        bmi     ExRPl                   ; and platform, branch ahead, leave speed unaltered
d647: a9 10                        lda     #$10
d649: 95 58                        sta     Enemy_X_Speed,x         ;otherwise set new speed (gets moving if motionless)
d64b: 20 14 d6                     jsr     PositionPlayerOnHPlat   ;use saved value from earlier sub to position player
d64e: 60           ExRPl           rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   MoveLargeLiftPlat
d64f: 20 5b d6                     jsr     MoveLiftPlatforms       ;execute common to all large and small lift platforms
d652: 4c fe d5                     jmp     ChkYPCollision          ;branch to position player correctly

                   MoveSmallPlatform
d655: 20 5b d6                     jsr     MoveLiftPlatforms       ;execute common to all large and small lift platforms
d658: 4c 71 d6                     jmp     ChkSmallPlatCollision   ;branch to position player correctly

                   MoveLiftPlatforms
d65b: ad 47 07                     lda     TimerControl            ;if master timer control set, skip all of this
d65e: d0 19                        bne     ExLiftP                 ; and branch to leave
d660: bd 17 04                     lda     Enemy_YMF_Dummy,x
d663: 18                           clc                             ;add contents of movement amount to whatever's here
d664: 7d 34 04                     adc     Enemy_Y_MoveForce,x
d667: 9d 17 04                     sta     Enemy_YMF_Dummy,x
d66a: b5 cf                        lda     Enemy_Y_Position,x      ;add whatever vertical speed is set to current
d66c: 75 a0                        adc     Enemy_Y_Speed,x         ; vertical position plus carry to move up or down
d66e: 95 cf                        sta     Enemy_Y_Position,x      ; and then leave
d670: 60                           rts

                   ChkSmallPlatCollision
d671: bd a2 03                     lda     PlatformCollisionFlag,x ;get bounding box counter saved in collision flag
d674: f0 03                        beq     ExLiftP                 ;if none found, leave player position alone
d676: 20 19 dc                     jsr     PositionPlayerOnS_Plat  ;use to position player correctly
d679: 60           ExLiftP         rts                             ;then leave

                   ; -----------------------------------------------------------------------------
                   ; $00 - page location of extended left boundary
                   ; $01 - extended left boundary position
                   ; $02 - page location of extended right boundary
                   ; $03 - extended right boundary position
                   OffscreenBoundsCheck
d67a: b5 16                        lda     Enemy_ID,x              ;check for cheep-cheep object
d67c: c9 14                        cmp     #FlyingCheepCheep       ;branch to leave if found
d67e: f0 55                        beq     ExScrnBd
d680: ad 1c 07                     lda     ScreenLeft_X_Pos        ;get horizontal coordinate for left side of screen
d683: b4 16                        ldy     Enemy_ID,x
d685: c0 05                        cpy     #HammerBro              ;check for hammer bro object
d687: f0 04                        beq     LimitB
d689: c0 0d                        cpy     #PiranhaPlant           ;check for piranha plant object
d68b: d0 02                        bne     ExtendLB                ;these two will be erased sooner than others if too far left
d68d: 69 38        LimitB          adc     #56                     ;add 56 pixels to coordinate if hammer bro or piranha plant
d68f: e9 48        ExtendLB        sbc     #72                     ;subtract 72 pixels regardless of enemy object
d691: 85 01                        sta     $01                     ;store result here
d693: ad 1a 07                     lda     ScreenLeft_PageLoc
d696: e9 00                        sbc     #$00                    ;subtract borrow from page location of left side
d698: 85 00                        sta     $00                     ;store result here
d69a: ad 1d 07                     lda     ScreenRight_X_Pos       ;add 72 pixels to the right side horizontal coordinate
d69d: 69 48                        adc     #72
d69f: 85 03                        sta     $03                     ;store result here
d6a1: ad 1b 07                     lda     ScreenRight_PageLoc
d6a4: 69 00                        adc     #$00                    ;then add the carry to the page location
d6a6: 85 02                        sta     $02                     ;and store result here
d6a8: b5 87                        lda     Enemy_X_Position,x      ;compare horizontal coordinate of the enemy object
d6aa: c5 01                        cmp     $01                     ; to modified horizontal left edge coordinate to get carry
d6ac: b5 6e                        lda     Enemy_PageLoc,x
d6ae: e5 00                        sbc     $00                     ;then subtract it from the page coordinate of the enemy object
d6b0: 30 20                        bmi     TooFar                  ;if enemy object is too far left, branch to erase it
d6b2: b5 87                        lda     Enemy_X_Position,x      ;compare horizontal coordinate of the enemy object
d6b4: c5 03                        cmp     $03                     ;to modified horizontal right edge coordinate to get carry
d6b6: b5 6e                        lda     Enemy_PageLoc,x
d6b8: e5 02                        sbc     $02                     ;then subtract it from the page coordinate of the enemy object
d6ba: 30 19                        bmi     ExScrnBd                ;if enemy object is on the screen, leave, do not erase enemy
d6bc: b5 1e                        lda     Enemy_State,x           ;if at this point, enemy is offscreen to the right, so check
d6be: c9 05                        cmp     #HammerBro              ;if in state used by spiny's egg, do not erase
d6c0: f0 13                        beq     ExScrnBd
d6c2: c0 0d                        cpy     #PiranhaPlant           ;if piranha plant, do not erase
d6c4: f0 0f                        beq     ExScrnBd
d6c6: c0 30                        cpy     #FlagpoleFlagObject     ;if flagpole flag, do not erase
d6c8: f0 0b                        beq     ExScrnBd
d6ca: c0 31                        cpy     #StarFlagObject         ;if star flag, do not erase
d6cc: f0 07                        beq     ExScrnBd
d6ce: c0 32                        cpy     #JumpspringObject       ;if jumpspring, do not erase
d6d0: f0 03                        beq     ExScrnBd                ;erase all others too far to the right
d6d2: 20 98 c9     TooFar          jsr     EraseEnemyObject        ;erase object if necessary
d6d5: 60           ExScrnBd        rts                             ;leave

                   ; -----------------------------------------------------------------------------
                   ; some unused space
d6d6: ff ff ff                     .bulk   $ff,$ff,$ff

                   ; -----------------------------------------------------------------------------
                   ; $01 - enemy buffer offset
                   FireballEnemyCollision
d6d9: b5 24                        lda     Fireball_State,x        ;check to see if fireball state is set at all
d6db: f0 56                        beq     ExitFBallEnemy          ;branch to leave if not
d6dd: 0a                           asl     A
d6de: b0 53                        bcs     ExitFBallEnemy          ;branch to leave also if d7 in state is set
d6e0: a5 09                        lda     FrameCounter
d6e2: 4a                           lsr     A                       ;get LSB of frame counter
d6e3: b0 4e                        bcs     ExitFBallEnemy          ;branch to leave if set (do routine every other frame)
d6e5: 8a                           txa
d6e6: 0a                           asl     A                       ;multiply fireball offset by four
d6e7: 0a                           asl     A
d6e8: 18                           clc
d6e9: 69 1c                        adc     #$1c                    ;then add $1c or 28 bytes to it
d6eb: a8                           tay                             ; to use fireball's bounding box coordinates 
d6ec: a2 04                        ldx     #$04
                   FireballEnemyCDLoop
d6ee: 86 01                        stx     $01                     ;store enemy object offset here
d6f0: 98                           tya
d6f1: 48                           pha                             ;push fireball offset to the stack
d6f2: b5 1e                        lda     Enemy_State,x
d6f4: 29 20                        and     #%00100000              ;check to see if d5 is set in enemy state
d6f6: d0 34                        bne     NoFToECol               ;if so, skip to next enemy slot
d6f8: b5 0f                        lda     Enemy_Flag,x            ;check to see if buffer flag is set
d6fa: f0 30                        beq     NoFToECol               ;if not, skip to next enemy slot
d6fc: b5 16                        lda     Enemy_ID,x              ;check enemy identifier
d6fe: c9 24                        cmp     #$24
d700: 90 04                        bcc     GoombaDie               ;if < $24, branch to check further
d702: c9 2b                        cmp     #$2b
d704: 90 26                        bcc     NoFToECol               ;if in range $24-$2a, skip to next enemy slot
d706: c9 06        GoombaDie       cmp     #Goomba                 ;check for goomba identifier
d708: d0 06                        bne     NoGoomba                ;if not found, continue with code
d70a: b5 1e                        lda     Enemy_State,x           ;otherwise check for defeated state
d70c: c9 02                        cmp     #$02                    ;if stomped or otherwise defeated,
d70e: b0 1c                        bcs     NoFToECol               ; skip to next enemy slot
d710: bd d8 03     NoGoomba        lda     EnemyOffscrBitsMasked,x ;if any masked offscreen bits set,
d713: d0 17                        bne     NoFToECol               ; skip to next enemy slot
d715: 8a                           txa
d716: 0a                           asl     A                       ;otherwise multiply enemy offset by four
d717: 0a                           asl     A
d718: 18                           clc
d719: 69 04                        adc     #$04                    ;add 4 bytes to it
d71b: aa                           tax                             ;to use enemy's bounding box coordinates
d71c: 20 27 e3                     jsr     SprObjectCollisionCore  ;do fireball-to-enemy collision detection
d71f: a6 08                        ldx     ObjectOffset            ;return fireball's original offset
d721: 90 09                        bcc     NoFToECol               ;if carry clear, no collision, thus do next enemy slot
d723: a9 80                        lda     #%10000000
d725: 95 24                        sta     Fireball_State,x        ;set d7 in enemy state
d727: a6 01                        ldx     $01                     ;get enemy offset
d729: 20 3e d7                     jsr     HandleEnemyFBallCol     ;jump to handle fireball to enemy collision
d72c: 68           NoFToECol       pla                             ;pull fireball offset from stack
d72d: a8                           tay                             ;put it in Y
d72e: a6 01                        ldx     $01                     ;get enemy object offset
d730: ca                           dex                             ;decrement it
d731: 10 bb                        bpl     FireballEnemyCDLoop     ;loop back until collision detection done on all enemies
d733: a6 08        ExitFBallEnemy  ldx     ObjectOffset            ;get original fireball offset and leave
d735: 60                           rts

                   BowserIdentities
d736: 06                           .dd1    Goomba
d737: 00                           .dd1    GreenKoopa
d738: 02                           .dd1    BuzzyBeetle
d739: 12                           .dd1    Spiny
d73a: 11                           .dd1    Lakitu
d73b: 07                           .dd1    Bloober
d73c: 05                           .dd1    HammerBro
d73d: 2d                           .dd1    Bowser

                   HandleEnemyFBallCol
d73e: 20 52 f1                     jsr     RelativeEnemyPosition   ;get relative coordinate of enemy
d741: a6 01                        ldx     $01                     ;get current enemy object offset
d743: b5 0f                        lda     Enemy_Flag,x            ;check buffer flag for d7 set
d745: 10 0b                        bpl     ChkBuzzyBeetle          ;branch if not set to continue
d747: 29 0f                        and     #%00001111              ;otherwise mask out high nybble and
d749: aa                           tax                             ; use low nybble as enemy offset
d74a: b5 16                        lda     Enemy_ID,x
d74c: c9 2d                        cmp     #Bowser                 ;check enemy identifier for bowser
d74e: f0 0c                        beq     HurtBowser              ;branch if found
d750: a6 01                        ldx     $01                     ;otherwise retrieve current enemy offset
d752: b5 16        ChkBuzzyBeetle  lda     Enemy_ID,x
d754: c9 02                        cmp     #BuzzyBeetle            ;check for buzzy beetle
d756: f0 6b                        beq     ExHCF                   ;branch if found to leave (buzzy beetles fireproof)
d758: c9 2d                        cmp     #Bowser                 ;check for bowser one more time (necessary if d7 of flag was clear)
d75a: d0 2d                        bne     ChkOtherEnemies         ;if not found, branch to check other enemies
d75c: ce 83 04     HurtBowser      dec     BowserHitPoints         ;decrement bowser's hit points
d75f: d0 62                        bne     ExHCF                   ;if bowser still has hit points, branch to leave
d761: 20 63 c3                     jsr     InitVStf                ;otherwise do sub to init vertical speed and movement force
d764: 95 58                        sta     Enemy_X_Speed,x         ;initialize horizontal speed
d766: 8d cb 06                     sta     EnemyFrenzyBuffer       ;init enemy frenzy buffer
d769: a9 fe                        lda     #$fe
d76b: 95 a0                        sta     Enemy_Y_Speed,x         ;set vertical speed to make defeated bowser jump a little
d76d: ac 5f 07                     ldy     WorldNumber             ;use world number as offset
d770: b9 36 d7                     lda     BowserIdentities,y      ;get enemy identifier to replace bowser with
d773: 95 16                        sta     Enemy_ID,x              ;set as new enemy identifier
d775: a9 20                        lda     #$20                    ;set A to use starting value for state
d777: c0 03                        cpy     #$03                    ;check to see if using offset of 3 or more
d779: b0 02                        bcs     SetDBSte                ;branch if so
d77b: 09 03                        ora     #$03                    ;otherwise add 3 to enemy state
d77d: 95 1e        SetDBSte        sta     Enemy_State,x           ;set defeated enemy state
d77f: a9 80                        lda     #Sfx_BowserFall
d781: 85 fe                        sta     Square2SoundQueue       ;load bowser defeat sound
d783: a6 01                        ldx     $01                     ;get enemy offset
d785: a9 09                        lda     #$09                    ;award 5000 points to player for defeating bowser
d787: d0 33                        bne     EnemySmackCore          ;unconditional branch to award points

d789: c9 08        ChkOtherEnemies cmp     #BulletBill_FrenzyVar
d78b: f0 36                        beq     ExHCF                   ;branch to leave if bullet bill (frenzy variant)
d78d: c9 0c                        cmp     #Podoboo
d78f: f0 32                        beq     ExHCF                   ;branch to leave if podoboo
d791: c9 15                        cmp     #$15
d793: b0 2e                        bcs     ExHCF                   ;branch to leave if identifier => $15
                   ShellOrBlockDefeat
d795: b5 16                        lda     Enemy_ID,x              ;check for piranha plant
d797: c9 0d                        cmp     #PiranhaPlant
d799: d0 06                        bne     StnE                    ;branch if not found
d79b: b5 cf                        lda     Enemy_Y_Position,x
d79d: 69 18                        adc     #$18                    ;add 24 pixels to enemy object's vertical position
d79f: 95 cf                        sta     Enemy_Y_Position,x
d7a1: 20 1b e0     StnE            jsr     ChkToStunEnemies        ;do yet another sub
d7a4: b5 1e                        lda     Enemy_State,x
d7a6: 29 1f                        and     #%00011111              ;mask out 2 MSB of enemy object's state
d7a8: 09 20                        ora     #%00100000              ;set d5 to defeat enemy and save as new state
d7aa: 95 1e                        sta     Enemy_State,x
d7ac: a9 02                        lda     #$02                    ;award 200 points by default
d7ae: b4 16                        ldy     Enemy_ID,x              ;check for hammer bro
d7b0: c0 05                        cpy     #HammerBro
d7b2: d0 02                        bne     GoombaPoints            ;branch if not found
d7b4: a9 06                        lda     #$06                    ;award 1000 points for hammer bro
d7b6: c0 06        GoombaPoints    cpy     #Goomba                 ;check for goomba
d7b8: d0 02                        bne     EnemySmackCore          ;branch if not found
d7ba: a9 01                        lda     #$01                    ;award 100 points for goomba
d7bc: 20 11 da     EnemySmackCore  jsr     SetupFloateyNumber      ;update necessary score variables
d7bf: a9 08                        lda     #Sfx_EnemySmack         ;play smack enemy sound
d7c1: 85 ff                        sta     Square1SoundQueue
d7c3: 60           ExHCF           rts                             ;and now let's leave

                   ; -----------------------------------------------------------------------------
                   PlayerHammerCollision
d7c4: a5 09                        lda     FrameCounter            ;get frame counter
d7c6: 4a                           lsr     A                       ;shift d0 into carry
d7c7: 90 36                        bcc     ExPHC                   ;branch to leave if d0 not set to execute every other frame
d7c9: ad 47 07                     lda     TimerControl            ;if either master timer control
d7cc: 0d d6 03                     ora     Misc_OffscreenBits      ; or any offscreen bits for hammer are set,
d7cf: d0 2e                        bne     ExPHC                   ; branch to leave
d7d1: 8a                           txa
d7d2: 0a                           asl     A                       ;multiply misc object offset by four
d7d3: 0a                           asl     A
d7d4: 18                           clc
d7d5: 69 24                        adc     #$24                    ;add 36 or $24 bytes to get proper offset
d7d7: a8                           tay                             ;for misc object bounding box coordinates
d7d8: 20 25 e3                     jsr     PlayerCollisionCore     ;do player-to-hammer collision detection
d7db: a6 08                        ldx     ObjectOffset            ;get misc object offset
d7dd: 90 1b                        bcc     ClHCol                  ;if no collision, then branch
d7df: bd be 06                     lda     Misc_Collision_Flag,x   ;otherwise read collision flag
d7e2: d0 1b                        bne     ExPHC                   ;if collision flag already set, branch to leave
d7e4: a9 01                        lda     #$01
d7e6: 9d be 06                     sta     Misc_Collision_Flag,x   ;otherwise set collision flag now
d7e9: b5 64                        lda     Misc_X_Speed,x
d7eb: 49 ff                        eor     #$ff                    ;get two's compliment of
d7ed: 18                           clc                             ; hammer's horizontal speed
d7ee: 69 01                        adc     #$01
d7f0: 95 64                        sta     Misc_X_Speed,x          ;set to send hammer flying the opposite direction
d7f2: ad 9f 07                     lda     StarInvincibleTimer     ;if star mario invincibility timer set,
d7f5: d0 08                        bne     ExPHC                   ; branch to leave
d7f7: 4c 2c d9                     jmp     InjurePlayer            ;otherwise jump to hurt player, do not return

d7fa: a9 00        ClHCol          lda     #$00                    ;clear collision flag
d7fc: 9d be 06                     sta     Misc_Collision_Flag,x
d7ff: 60           ExPHC           rts

                   ; -----------------------------------------------------------------------------
                   HandlePowerUpCollision
d800: 20 98 c9                     jsr     EraseEnemyObject        ;erase the power-up object
d803: a9 06                        lda     #$06
d805: 20 11 da                     jsr     SetupFloateyNumber      ;award 1000 points to player by default
d808: a9 20                        lda     #Sfx_PowerUpGrab
d80a: 85 fe                        sta     Square2SoundQueue       ;play the power-up sound
d80c: a5 39                        lda     PowerUpType             ;check power-up type
d80e: c9 02                        cmp     #$02
d810: 90 0e                        bcc     Shroom_Flower_PUp       ;if mushroom or fire flower, branch
d812: c9 03                        cmp     #$03
d814: f0 24                        beq     SetFor1Up               ;if 1-up mushroom, branch
d816: a9 23                        lda     #$23                    ;otherwise set star mario invincibility
d818: 8d 9f 07                     sta     StarInvincibleTimer     ; timer, and load the star mario music
d81b: a9 40                        lda     #StarPowerMusic         ; into the area music queue, then leave
d81d: 85 fb                        sta     AreaMusicQueue
d81f: 60                           rts

                   Shroom_Flower_PUp
d820: ad 56 07                     lda     PlayerStatus            ;if player status = small, branch
d823: f0 1b                        beq     UpToSuper
d825: c9 01                        cmp     #$01                    ;if player status not super, leave
d827: d0 23                        bne     NoPUp
d829: a6 08                        ldx     ObjectOffset            ;get enemy offset, not necessary
d82b: a9 02                        lda     #$02                    ;set player status to fiery
d82d: 8d 56 07                     sta     PlayerStatus
d830: 20 f1 85                     jsr     GetPlayerColors         ;run sub to change colors of player
d833: a6 08                        ldx     ObjectOffset            ;get enemy offset again, and again not necessary
d835: a9 0c                        lda     #$0c                    ;set value to be used by subroutine tree (fiery)
d837: 4c 47 d8                     jmp     UpToFiery               ;jump to set values accordingly

d83a: a9 0b        SetFor1Up       lda     #$0b                    ;change 1000 points into 1-up instead
d83c: 9d 10 01                     sta     FloateyNum_Control,x    ; and then leave
d83f: 60                           rts

d840: a9 01        UpToSuper       lda     #$01                    ;set player status to super
d842: 8d 56 07                     sta     PlayerStatus
d845: a9 09                        lda     #$09                    ;set value to be used by subroutine tree (super)
d847: a0 00        UpToFiery       ldy     #$00                    ;set value to be used as new player state
d849: 20 48 d9                     jsr     SetPRout                ;set values to stop certain things in motion
d84c: 60           NoPUp           rts

                   ; -----------------------------------------------------------------------------
                   ResidualXSpdData
d84d: 18 e8                        .bulk   $18,$e8
                   KickedShellXSpdData
d84f: 30 d0                        .bulk   $30,$d0
                   DemotedKoopaXSpdData
d851: 08 f8                        .bulk   $08,$f8

                   PlayerEnemyCollision
d853: a5 09                        lda     FrameCounter            ;check counter for d0 set
d855: 4a                           lsr     A
d856: b0 f4                        bcs     NoPUp                   ;if set, branch to leave
d858: 20 41 dc                     jsr     CheckPlayerVertical     ;if player object is completely offscreen or
d85b: b0 23                        bcs     NoPECol                 ; if down past 224th pixel row, branch to leave
d85d: bd d8 03                     lda     EnemyOffscrBitsMasked,x ;if current enemy is offscreen by any amount,
d860: d0 1e                        bne     NoPECol                 ; go ahead and branch to leave
d862: a5 0e                        lda     GameEngineSubroutine
d864: c9 08                        cmp     #$08                    ;if not set to run player control routine
d866: d0 18                        bne     NoPECol                 ; on next frame, branch to leave
d868: b5 1e                        lda     Enemy_State,x
d86a: 29 20                        and     #%00100000              ;if enemy state has d5 set, branch to leave
d86c: d0 12                        bne     NoPECol
d86e: 20 52 dc                     jsr     GetEnemyBoundBoxOfs     ;get bounding box offset for current enemy object
d871: 20 25 e3                     jsr     PlayerCollisionCore     ;do collision detection on player vs. enemy
d874: a6 08                        ldx     ObjectOffset            ;get enemy object buffer offset
d876: b0 09                        bcs     ChkForPUpCollision      ;if collision, branch past this part here
d878: bd 91 04                     lda     Enemy_CollisionBits,x
d87b: 29 fe                        and     #%11111110              ;otherwise, clear d0 of current enemy object's
d87d: 9d 91 04                     sta     Enemy_CollisionBits,x   ; collision bit
d880: 60           NoPECol         rts

                   ChkForPUpCollision
d881: b4 16                        ldy     Enemy_ID,x
d883: c0 2e                        cpy     #PowerUpObject          ;check for power-up object
d885: d0 03                        bne     EColl                   ;if not found, branch to next part
d887: 4c 00 d8                     jmp     HandlePowerUpCollision  ;otherwise, unconditional jump backwards

d88a: ad 9f 07     EColl           lda     StarInvincibleTimer     ;if star mario invincibility timer expired,
d88d: f0 06                        beq     HandlePECollisions      ; perform task here, otherwise kill enemy like
d88f: 4c 95 d7                     jmp     ShellOrBlockDefeat      ; hit with a shell, or from beneath

                   KickedShellPtsData
d892: 0a 06 04                     .bulk   $0a,$06,$04

                   HandlePECollisions
d895: bd 91 04                     lda     Enemy_CollisionBits,x   ;check enemy collision bits for d0 set
d898: 29 01                        and     #%00000001              ;or for being offscreen at all
d89a: 1d d8 03                     ora     EnemyOffscrBitsMasked,x
d89d: d0 59                        bne     ExPEC                   ;branch to leave if either is true
d89f: a9 01                        lda     #$01
d8a1: 1d 91 04                     ora     Enemy_CollisionBits,x   ;otherwise set d0 now
d8a4: 9d 91 04                     sta     Enemy_CollisionBits,x
d8a7: c0 12                        cpy     #Spiny                  ;branch if spiny
d8a9: f0 4e                        beq     ChkForPlayerInjury
d8ab: c0 0d                        cpy     #PiranhaPlant           ;branch if piranha plant
d8ad: f0 7d                        beq     InjurePlayer
d8af: c0 0c                        cpy     #Podoboo                ;branch if podoboo
d8b1: f0 79                        beq     InjurePlayer
d8b3: c0 33                        cpy     #BulletBill_CannonVar   ;branch if bullet bill
d8b5: f0 42                        beq     ChkForPlayerInjury
d8b7: c0 15                        cpy     #$15                    ;branch if object => $15
d8b9: b0 71                        bcs     InjurePlayer
d8bb: ad 4e 07                     lda     AreaType                ;branch if water type level
d8be: f0 6c                        beq     InjurePlayer
d8c0: b5 1e                        lda     Enemy_State,x           ;branch if d7 of enemy state was set
d8c2: 0a                           asl     A
d8c3: b0 34                        bcs     ChkForPlayerInjury
d8c5: b5 1e                        lda     Enemy_State,x           ;mask out all but 3 LSB of enemy state
d8c7: 29 07                        and     #%00000111
d8c9: c9 02                        cmp     #$02                    ;branch if enemy is in normal or falling state
d8cb: 90 2c                        bcc     ChkForPlayerInjury
d8cd: b5 16                        lda     Enemy_ID,x              ;branch to leave if goomba in defeated state
d8cf: c9 06                        cmp     #$06
d8d1: f0 25                        beq     ExPEC
d8d3: a9 08                        lda     #Sfx_EnemySmack         ;play smack enemy sound
d8d5: 85 ff                        sta     Square1SoundQueue
d8d7: b5 1e                        lda     Enemy_State,x           ;set d7 in enemy state, thus become moving shell
d8d9: 09 80                        ora     #%10000000
d8db: 95 1e                        sta     Enemy_State,x
d8dd: 20 05 da                     jsr     EnemyFacePlayer         ;set moving direction and get offset
d8e0: b9 4f d8                     lda     KickedShellXSpdData,y   ;load and set horizontal speed data with offset
d8e3: 95 58                        sta     Enemy_X_Speed,x
d8e5: a9 03                        lda     #$03                    ;add three to whatever the stomp counter contains
d8e7: 18                           clc                             ; to give points for kicking the shell
d8e8: 6d 84 04                     adc     StompChainCounter
d8eb: bc 96 07                     ldy     EnemyIntervalTimer,x    ;check shell enemy's timer
d8ee: c0 03                        cpy     #$03                    ;if above a certain point, branch using the points
d8f0: b0 03                        bcs     KSPts                   ; data obtained from the stomp counter + 3
d8f2: b9 92 d8                     lda     KickedShellPtsData,y    ;otherwise, set points based on proximity to timer expiration
d8f5: 20 11 da     KSPts           jsr     SetupFloateyNumber      ;set values for floatey number now
d8f8: 60           ExPEC           rts                             ;leave!!!

                   ChkForPlayerInjury
d8f9: a5 9f                        lda     Player_Y_Speed          ;check player's vertical speed
d8fb: 30 02                        bmi     ChkInj                  ;perform procedure below if player moving upwards
d8fd: d0 6a                        bne     EnemyStomped            ;or not at all, and branch elsewhere if moving downwards
d8ff: b5 16        ChkInj          lda     Enemy_ID,x              ;branch if enemy object < $07
d901: c9 07                        cmp     #Bloober
d903: 90 09                        bcc     ChkETmrs
d905: a5 ce                        lda     Player_Y_Position       ;add 12 pixels to player's vertical position
d907: 18                           clc
d908: 69 0c                        adc     #$0c
d90a: d5 cf                        cmp     Enemy_Y_Position,x      ;compare modified player's position to enemy's position
d90c: 90 5b                        bcc     EnemyStomped            ;branch if this player's position above (less than) enemy's
d90e: ad 91 07     ChkETmrs        lda     StompTimer              ;check stomp timer
d911: d0 56                        bne     EnemyStomped            ;branch if set
d913: ad 9e 07                     lda     InjuryTimer             ;check to see if injured invincibility timer still
d916: d0 3d                        bne     ExInjColRoutines        ;counting down, and branch elsewhere to leave if so
d918: ad ad 03                     lda     Player_Rel_XPos
d91b: cd ae 03                     cmp     Enemy_Rel_XPos          ;if player's relative position to the left of enemy's
d91e: 90 03                        bcc     TInjE                   ;relative position, branch here
d920: 4c f6 d9                     jmp     ChkEnemyFaceRight       ;otherwise do a jump here

d923: b5 46        TInjE           lda     Enemy_MovingDir,x       ;if enemy moving towards the left,
d925: c9 01                        cmp     #$01                    ; branch, otherwise do a jump here
d927: d0 03                        bne     InjurePlayer            ; to turn the enemy around
d929: 4c ff d9                     jmp     LInj

d92c: ad 9e 07     InjurePlayer    lda     InjuryTimer             ;check again to see if injured invincibility timer is
d92f: d0 24                        bne     ExInjColRoutines        ; at zero, and branch to leave if so
                   ; 
d931: ae 56 07     ForceInjury     ldx     PlayerStatus            ;check player's status
d934: f0 22                        beq     KillPlayer              ;branch if small
d936: 8d 56 07                     sta     PlayerStatus            ;otherwise set player's status to small
d939: a9 08                        lda     #$08
d93b: 8d 9e 07                     sta     InjuryTimer             ;set injured invincibility timer
d93e: 0a                           asl     A
d93f: 85 ff                        sta     Square1SoundQueue       ;play pipedown/injury sound
d941: 20 f1 85                     jsr     GetPlayerColors         ;change player's palette if necessary
d944: a9 0a                        lda     #$0a                    ;set subroutine to run on next frame
d946: a0 01        SetKRout        ldy     #$01                    ;set new player state
d948: 85 0e        SetPRout        sta     GameEngineSubroutine    ;load new value to run subroutine on next frame
d94a: 84 1d                        sty     Player_State            ;store new player state
d94c: a0 ff                        ldy     #$ff
d94e: 8c 47 07                     sty     TimerControl            ;set master timer control flag to halt timers
d951: c8                           iny
d952: 8c 75 07                     sty     ScrollAmount            ;initialize scroll speed
                   ExInjColRoutines
d955: a6 08                        ldx     ObjectOffset            ;get enemy offset and leave
d957: 60                           rts

d958: 86 57        KillPlayer      stx     Player_X_Speed          ;halt player's horizontal movement by initializing speed
d95a: e8                           inx
d95b: 86 fc                        stx     EventMusicQueue         ;set event music queue to death music
d95d: a9 fc                        lda     #$fc
d95f: 85 9f                        sta     Player_Y_Speed          ;set new vertical speed
d961: a9 0b                        lda     #$0b                    ;set subroutine to run on next frame
d963: d0 e1                        bne     SetKRout                ;branch to set player's state and other things

                   StompedEnemyPtsData
d965: 02 06 05 06                  .bulk   $02,$06,$05,$06

d969: b5 16        EnemyStomped    lda     Enemy_ID,x              ;check for spiny, branch to hurt player
d96b: c9 12                        cmp     #Spiny                  ; if found
d96d: f0 bd                        beq     InjurePlayer
d96f: a9 04                        lda     #Sfx_EnemyStomp         ;otherwise play stomp/swim sound
d971: 85 ff                        sta     Square1SoundQueue
d973: b5 16                        lda     Enemy_ID,x
d975: a0 00                        ldy     #$00                    ;initialize points data offset for stomped enemies
d977: c9 14                        cmp     #FlyingCheepCheep       ;branch for cheep-cheep
d979: f0 1b                        beq     EnemyStompedPts
d97b: c9 08                        cmp     #BulletBill_FrenzyVar   ;branch for either bullet bill object
d97d: f0 17                        beq     EnemyStompedPts
d97f: c9 33                        cmp     #BulletBill_CannonVar
d981: f0 13                        beq     EnemyStompedPts
d983: c9 0c                        cmp     #Podoboo                ;branch for podoboo (this branch is logically impossible
d985: f0 0f                        beq     EnemyStompedPts         ; for cpu to take due to earlier checking of podoboo)
d987: c8                           iny                             ;increment points data offset
d988: c9 05                        cmp     #HammerBro              ;branch for hammer bro
d98a: f0 0a                        beq     EnemyStompedPts
d98c: c8                           iny                             ;increment points data offset
d98d: c9 11                        cmp     #Lakitu                 ;branch for lakitu
d98f: f0 05                        beq     EnemyStompedPts
d991: c8                           iny                             ;increment points data offset
d992: c9 07                        cmp     #Bloober                ;branch if NOT bloober
d994: d0 1d                        bne     ChkForDemoteKoopa
d996: b9 65 d9     EnemyStompedPts lda     StompedEnemyPtsData,y   ;load points data using offset in Y
d999: 20 11 da                     jsr     SetupFloateyNumber      ;run sub to set floatey number controls
d99c: b5 46                        lda     Enemy_MovingDir,x
d99e: 48                           pha                             ;save enemy movement direction to stack
d99f: 20 2f e0                     jsr     SetStun                 ;run sub to kill enemy
d9a2: 68                           pla
d9a3: 95 46                        sta     Enemy_MovingDir,x       ;return enemy movement direction from stack
d9a5: a9 20                        lda     #%00100000
d9a7: 95 1e                        sta     Enemy_State,x           ;set d5 in enemy state
d9a9: 20 63 c3                     jsr     InitVStf                ;nullify vertical speed, physics-related thing,
d9ac: 95 58                        sta     Enemy_X_Speed,x         ; and horizontal speed
d9ae: a9 fd                        lda     #$fd                    ;set player's vertical speed, to give bounce
d9b0: 85 9f                        sta     Player_Y_Speed
d9b2: 60                           rts

                   ChkForDemoteKoopa
d9b3: c9 09                        cmp     #$09                    ;branch elsewhere if enemy object < $09
d9b5: 90 1d                        bcc     HandleStompedShellE
d9b7: 29 01                        and     #%00000001              ;demote koopa paratroopas to ordinary troopas
d9b9: 95 16                        sta     Enemy_ID,x
d9bb: a0 00                        ldy     #$00                    ;return enemy to normal state
d9bd: 94 1e                        sty     Enemy_State,x
d9bf: a9 03                        lda     #$03                    ;award 400 points to the player
d9c1: 20 11 da                     jsr     SetupFloateyNumber
d9c4: 20 63 c3                     jsr     InitVStf                ;nullify physics-related thing and vertical speed
d9c7: 20 05 da                     jsr     EnemyFacePlayer         ;turn enemy around if necessary
d9ca: b9 51 d8                     lda     DemotedKoopaXSpdData,y
d9cd: 95 58                        sta     Enemy_X_Speed,x         ;set appropriate moving speed based on direction
d9cf: 4c f1 d9                     jmp     SBnce                   ;then move onto something else

d9d2: 10 0b        RevivalRateData .bulk   $10,$0b

                   HandleStompedShellE
d9d4: a9 04                        lda     #$04                    ;set defeated state for enemy
d9d6: 95 1e                        sta     Enemy_State,x
d9d8: ee 84 04                     inc     StompChainCounter       ;increment the stomp counter
d9db: ad 84 04                     lda     StompChainCounter       ;add whatever is in the stomp counter
d9de: 18                           clc                             ; to whatever is in the stomp timer
d9df: 6d 91 07                     adc     StompTimer
d9e2: 20 11 da                     jsr     SetupFloateyNumber      ;award points accordingly
d9e5: ee 91 07                     inc     StompTimer              ;increment stomp timer of some sort
d9e8: ac 6a 07                     ldy     PrimaryHardMode         ;check primary hard mode flag
d9eb: b9 d2 d9                     lda     RevivalRateData,y       ;load timer setting according to flag
d9ee: 9d 96 07                     sta     EnemyIntervalTimer,x    ;set as enemy timer to revive stomped enemy
d9f1: a9 fc        SBnce           lda     #$fc                    ;set player's vertical speed for bounce
d9f3: 85 9f                        sta     Player_Y_Speed          ;and then leave!!!
d9f5: 60                           rts

                   ChkEnemyFaceRight
d9f6: b5 46                        lda     Enemy_MovingDir,x       ;check to see if enemy is moving to the right
d9f8: c9 01                        cmp     #$01
d9fa: d0 03                        bne     LInj                    ;if not, branch
d9fc: 4c 2c d9                     jmp     InjurePlayer            ;otherwise go back to hurt player

d9ff: 20 1c db     LInj            jsr     EnemyTurnAround         ;turn the enemy around, if necessary
da02: 4c 2c d9                     jmp     InjurePlayer            ;go back to hurt player

da05: a0 01        EnemyFacePlayer ldy     #$01                    ;set to move right by default
da07: 20 43 e1                     jsr     PlayerEnemyDiff         ;get horizontal difference between player and enemy
da0a: 10 01                        bpl     SFcRt                   ;if enemy is to the right of player, do not increment
da0c: c8                           iny                             ;otherwise, increment to set to move to the left
da0d: 94 46        SFcRt           sty     Enemy_MovingDir,x       ;set moving direction here
da0f: 88                           dey                             ;then decrement to use as a proper offset
da10: 60                           rts

                   SetupFloateyNumber
da11: 9d 10 01                     sta     FloateyNum_Control,x    ;set number of points control for floatey numbers
da14: a9 30                        lda     #$30
da16: 9d 2c 01                     sta     FloateyNum_Timer,x      ;set timer for floatey numbers
da19: b5 cf                        lda     Enemy_Y_Position,x
da1b: 9d 1e 01                     sta     FloateyNum_Y_Pos,x      ;set vertical coordinate
da1e: ad ae 03                     lda     Enemy_Rel_XPos
da21: 9d 17 01                     sta     FloateyNum_X_Pos,x      ;set horizontal coordinate and leave
da24: 60           ExSFN           rts

                   ; -----------------------------------------------------------------------------
                   ; $01 - used to hold enemy offset for second enemy
da25: 80           SetBitsMask     .dd1    %10000000
da26: 40                           .dd1    %01000000
da27: 20                           .dd1    %00100000
da28: 10                           .dd1    %00010000
da29: 08                           .dd1    %00001000
da2a: 04                           .dd1    %00000100
da2b: 02                           .dd1    %00000010
da2c: 7f           ClearBitsMask   .dd1    %01111111
da2d: bf                           .dd1    %10111111
da2e: df                           .dd1    %11011111
da2f: ef                           .dd1    %11101111
da30: f7                           .dd1    %11110111
da31: fb                           .dd1    %11111011
da32: fd                           .dd1    %11111101

                   EnemiesCollision
da33: a5 09                        lda     FrameCounter            ;check counter for d0 set
da35: 4a                           lsr     A
da36: 90 ec                        bcc     ExSFN                   ;if d0 not set, leave
da38: ad 4e 07                     lda     AreaType
da3b: f0 e7                        beq     ExSFN                   ;if water area type, leave
da3d: b5 16                        lda     Enemy_ID,x
da3f: c9 15                        cmp     #$15                    ;if enemy object => $15, branch to leave
da41: b0 6e                        bcs     ExitECRoutine
da43: c9 11                        cmp     #Lakitu                 ;if lakitu, branch to leave
da45: f0 6a                        beq     ExitECRoutine
da47: c9 0d                        cmp     #PiranhaPlant           ;if piranha plant, branch to leave
da49: f0 66                        beq     ExitECRoutine
da4b: bd d8 03                     lda     EnemyOffscrBitsMasked,x ;if masked offscreen bits nonzero, branch to leave
da4e: d0 61                        bne     ExitECRoutine
da50: 20 52 dc                     jsr     GetEnemyBoundBoxOfs     ;otherwise, do sub, get appropriate bounding box offset for
da53: ca                           dex                             ; first enemy we're going to compare, then decrement for second
da54: 30 5b                        bmi     ExitECRoutine           ;branch to leave if there are no other enemies
da56: 86 01        ECLoop          stx     $01                     ;save enemy object buffer offset for second enemy here
da58: 98                           tya                             ;save first enemy's bounding box offset to stack
da59: 48                           pha
da5a: b5 0f                        lda     Enemy_Flag,x            ;check enemy object enable flag
da5c: f0 4c                        beq     ReadyNextEnemy          ;branch if flag not set
da5e: b5 16                        lda     Enemy_ID,x
da60: c9 15                        cmp     #$15                    ;check for enemy object => $15
da62: b0 46                        bcs     ReadyNextEnemy          ;branch if true
da64: c9 11                        cmp     #Lakitu
da66: f0 42                        beq     ReadyNextEnemy          ;branch if enemy object is lakitu
da68: c9 0d                        cmp     #PiranhaPlant
da6a: f0 3e                        beq     ReadyNextEnemy          ;branch if enemy object is piranha plant
da6c: bd d8 03                     lda