SHARE
TWEET

Super Mario Bros.

Whisket Oct 8th, 2018 151 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;SMBDIS.ASM - A COMPREHENSIVE SUPER MARIO BROS. DISASSEMBLY
  2. ;by doppelganger (doppelheathen@gmail.com)
  3.  
  4. ;This file is provided for your own use as-is.  It will require the character rom data
  5. ;and an iNES file header to get it to work.
  6.  
  7. ;There are so many people I have to thank for this, that taking all the credit for
  8. ;myself would be an unforgivable act of arrogance. Without their help this would
  9. ;probably not be possible.  So I thank all the peeps in the nesdev scene whose insight into
  10. ;the 6502 and the NES helped me learn how it works (you guys know who you are, there's no
  11. ;way I could have done this without your help), as well as the authors of x816 and SMB
  12. ;Utility, and the reverse-engineers who did the original Super Mario Bros. Hacking Project,
  13. ;which I compared notes with but did not copy from.  Last but certainly not least, I thank
  14. ;Nintendo for creating this game and the NES, without which this disassembly would
  15. ;only be theory.
  16.  
  17. ;Assembles with x816.
  18.  
  19. ;-------------------------------------------------------------------------------------
  20. ;DEFINES
  21.  
  22. ;NES specific hardware defines
  23.  
  24. PPU_CTRL_REG1         = $2000
  25. PPU_CTRL_REG2         = $2001
  26. PPU_STATUS            = $2002
  27. PPU_SPR_ADDR          = $2003
  28. PPU_SPR_DATA          = $2004
  29. PPU_SCROLL_REG        = $2005
  30. PPU_ADDRESS           = $2006
  31. PPU_DATA              = $2007
  32.  
  33. SND_REGISTER          = $4000
  34. SND_SQUARE1_REG       = $4000
  35. SND_SQUARE2_REG       = $4004
  36. SND_TRIANGLE_REG      = $4008
  37. SND_NOISE_REG         = $400c
  38. SND_DELTA_REG         = $4010
  39. SND_MASTERCTRL_REG    = $4015
  40.  
  41. SPR_DMA               = $4014
  42. JOYPAD_PORT           = $4016
  43. JOYPAD_PORT1          = $4016
  44. JOYPAD_PORT2          = $4017
  45.  
  46. ; GAME SPECIFIC DEFINES
  47.  
  48. ObjectOffset          = $08
  49.  
  50. FrameCounter          = $09
  51.  
  52. SavedJoypadBits       = $06fc
  53. SavedJoypad1Bits      = $06fc
  54. SavedJoypad2Bits      = $06fd
  55. JoypadBitMask         = $074a
  56. JoypadOverride        = $0758
  57.  
  58. A_B_Buttons           = $0a
  59. PreviousA_B_Buttons   = $0d
  60. Up_Down_Buttons       = $0b
  61. Left_Right_Buttons    = $0c
  62.  
  63. GameEngineSubroutine  = $0e
  64.  
  65. Mirror_PPU_CTRL_REG1  = $0778
  66. Mirror_PPU_CTRL_REG2  = $0779
  67.  
  68. OperMode              = $0770
  69. OperMode_Task         = $0772
  70. ScreenRoutineTask     = $073c
  71.  
  72. GamePauseStatus       = $0776
  73. GamePauseTimer        = $0777
  74.  
  75. DemoAction            = $0717
  76. DemoActionTimer       = $0718
  77.  
  78. TimerControl          = $0747
  79. IntervalTimerControl  = $077f
  80.  
  81. Timers                = $0780
  82. SelectTimer           = $0780
  83. PlayerAnimTimer       = $0781
  84. JumpSwimTimer         = $0782
  85. RunningTimer          = $0783
  86. BlockBounceTimer      = $0784
  87. SideCollisionTimer    = $0785
  88. JumpspringTimer       = $0786
  89. GameTimerCtrlTimer    = $0787
  90. ClimbSideTimer        = $0789
  91. EnemyFrameTimer       = $078a
  92. FrenzyEnemyTimer      = $078f
  93. BowserFireBreathTimer = $0790
  94. StompTimer            = $0791
  95. AirBubbleTimer        = $0792
  96. ScrollIntervalTimer   = $0795
  97. EnemyIntervalTimer    = $0796
  98. BrickCoinTimer        = $079d
  99. InjuryTimer           = $079e
  100. StarInvincibleTimer   = $079f
  101. ScreenTimer           = $07a0
  102. WorldEndTimer         = $07a1
  103. DemoTimer             = $07a2
  104.  
  105. Sprite_Data           = $0200
  106.  
  107. Sprite_Y_Position     = $0200
  108. Sprite_Tilenumber     = $0201
  109. Sprite_Attributes     = $0202
  110. Sprite_X_Position     = $0203
  111.  
  112. ScreenEdge_PageLoc    = $071a
  113. ScreenEdge_X_Pos      = $071c
  114. ScreenLeft_PageLoc    = $071a
  115. ScreenRight_PageLoc   = $071b
  116. ScreenLeft_X_Pos      = $071c
  117. ScreenRight_X_Pos     = $071d
  118.  
  119. PlayerFacingDir       = $33
  120. DestinationPageLoc    = $34
  121. VictoryWalkControl    = $35
  122. ScrollFractional      = $0768
  123. PrimaryMsgCounter     = $0719
  124. SecondaryMsgCounter   = $0749
  125.  
  126. HorizontalScroll      = $073f
  127. VerticalScroll        = $0740
  128. ScrollLock            = $0723
  129. ScrollThirtyTwo       = $073d
  130. Player_X_Scroll       = $06ff
  131. Player_Pos_ForScroll  = $0755
  132. ScrollAmount          = $0775
  133.  
  134. AreaData              = $e7
  135. AreaDataLow           = $e7
  136. AreaDataHigh          = $e8
  137. EnemyData             = $e9
  138. EnemyDataLow          = $e9
  139. EnemyDataHigh         = $ea
  140.  
  141. AreaParserTaskNum     = $071f
  142. ColumnSets            = $071e
  143. CurrentPageLoc        = $0725
  144. CurrentColumnPos      = $0726
  145. BackloadingFlag       = $0728
  146. BehindAreaParserFlag  = $0729
  147. AreaObjectPageLoc     = $072a
  148. AreaObjectPageSel     = $072b
  149. AreaDataOffset        = $072c
  150. AreaObjOffsetBuffer   = $072d
  151. AreaObjectLength      = $0730
  152. StaircaseControl      = $0734
  153. AreaObjectHeight      = $0735
  154. MushroomLedgeHalfLen  = $0736
  155. EnemyDataOffset       = $0739
  156. EnemyObjectPageLoc    = $073a
  157. EnemyObjectPageSel    = $073b
  158. MetatileBuffer        = $06a1
  159. BlockBufferColumnPos  = $06a0
  160. CurrentNTAddr_Low     = $0721
  161. CurrentNTAddr_High    = $0720
  162. AttributeBuffer       = $03f9
  163.  
  164. LoopCommand           = $0745
  165.  
  166. DisplayDigits         = $07d7
  167. TopScoreDisplay       = $07d7
  168. ScoreAndCoinDisplay   = $07dd
  169. PlayerScoreDisplay    = $07dd
  170. GameTimerDisplay      = $07f8
  171. DigitModifier         = $0134
  172.  
  173. VerticalFlipFlag      = $0109
  174. FloateyNum_Control    = $0110
  175. ShellChainCounter     = $0125
  176. FloateyNum_Timer      = $012c
  177. FloateyNum_X_Pos      = $0117
  178. FloateyNum_Y_Pos      = $011e
  179. FlagpoleFNum_Y_Pos    = $010d
  180. FlagpoleFNum_YMFDummy = $010e
  181. FlagpoleScore         = $010f
  182. FlagpoleCollisionYPos = $070f
  183. StompChainCounter     = $0484
  184.  
  185. VRAM_Buffer1_Offset   = $0300
  186. VRAM_Buffer1          = $0301
  187. VRAM_Buffer2_Offset   = $0340
  188. VRAM_Buffer2          = $0341
  189. VRAM_Buffer_AddrCtrl  = $0773
  190. Sprite0HitDetectFlag  = $0722
  191. DisableScreenFlag     = $0774
  192. DisableIntermediate   = $0769
  193. ColorRotateOffset     = $06d4
  194.  
  195. TerrainControl        = $0727
  196. AreaStyle             = $0733
  197. ForegroundScenery     = $0741
  198. BackgroundScenery     = $0742
  199. CloudTypeOverride     = $0743
  200. BackgroundColorCtrl   = $0744
  201. AreaType              = $074e
  202. AreaAddrsLOffset      = $074f
  203. AreaPointer           = $0750
  204.  
  205. PlayerEntranceCtrl    = $0710
  206. GameTimerSetting      = $0715
  207. AltEntranceControl    = $0752
  208. EntrancePage          = $0751
  209. NumberOfPlayers       = $077a
  210. WarpZoneControl       = $06d6
  211. ChangeAreaTimer       = $06de
  212.  
  213. MultiLoopCorrectCntr  = $06d9
  214. MultiLoopPassCntr     = $06da
  215.  
  216. FetchNewGameTimerFlag = $0757
  217. GameTimerExpiredFlag  = $0759
  218.  
  219. PrimaryHardMode       = $076a
  220. SecondaryHardMode     = $06cc
  221. WorldSelectNumber     = $076b
  222. WorldSelectEnableFlag = $07fc
  223. ContinueWorld         = $07fd
  224.  
  225. CurrentPlayer         = $0753
  226. PlayerSize            = $0754
  227. PlayerStatus          = $0756
  228.  
  229. OnscreenPlayerInfo    = $075a
  230. NumberofLives         = $075a ;used by current player
  231. HalfwayPage           = $075b
  232. LevelNumber           = $075c ;the actual dash number
  233. Hidden1UpFlag         = $075d
  234. CoinTally             = $075e
  235. WorldNumber           = $075f
  236. AreaNumber            = $0760 ;internal number used to find areas
  237.  
  238. CoinTallyFor1Ups      = $0748
  239.  
  240. OffscreenPlayerInfo   = $0761
  241. OffScr_NumberofLives  = $0761 ;used by offscreen player
  242. OffScr_HalfwayPage    = $0762
  243. OffScr_LevelNumber    = $0763
  244. OffScr_Hidden1UpFlag  = $0764
  245. OffScr_CoinTally      = $0765
  246. OffScr_WorldNumber    = $0766
  247. OffScr_AreaNumber     = $0767
  248.  
  249. BalPlatformAlignment  = $03a0
  250. Platform_X_Scroll     = $03a1
  251. PlatformCollisionFlag = $03a2
  252. YPlatformTopYPos      = $0401
  253. YPlatformCenterYPos   = $58
  254.  
  255. BrickCoinTimerFlag    = $06bc
  256. StarFlagTaskControl   = $0746
  257.  
  258. PseudoRandomBitReg    = $07a7
  259. WarmBootValidation    = $07ff
  260.  
  261. SprShuffleAmtOffset   = $06e0
  262. SprShuffleAmt         = $06e1
  263. SprDataOffset         = $06e4
  264. Player_SprDataOffset  = $06e4
  265. Enemy_SprDataOffset   = $06e5
  266. Block_SprDataOffset   = $06ec
  267. Alt_SprDataOffset     = $06ec
  268. Bubble_SprDataOffset  = $06ee
  269. FBall_SprDataOffset   = $06f1
  270. Misc_SprDataOffset    = $06f3
  271. SprDataOffset_Ctrl    = $03ee
  272.  
  273. Player_State          = $1d
  274. Enemy_State           = $1e
  275. Fireball_State        = $24
  276. Block_State           = $26
  277. Misc_State            = $2a
  278.  
  279. Player_MovingDir      = $45
  280. Enemy_MovingDir       = $46
  281.  
  282. SprObject_X_Speed     = $57
  283. Player_X_Speed        = $57
  284. Enemy_X_Speed         = $58
  285. Fireball_X_Speed      = $5e
  286. Block_X_Speed         = $60
  287. Misc_X_Speed          = $64
  288.  
  289. Jumpspring_FixedYPos  = $58
  290. JumpspringAnimCtrl    = $070e
  291. JumpspringForce       = $06db
  292.  
  293. SprObject_PageLoc     = $6d
  294. Player_PageLoc        = $6d
  295. Enemy_PageLoc         = $6e
  296. Fireball_PageLoc      = $74
  297. Block_PageLoc         = $76
  298. Misc_PageLoc          = $7a
  299. Bubble_PageLoc        = $83
  300.  
  301. SprObject_X_Position  = $86
  302. Player_X_Position     = $86
  303. Enemy_X_Position      = $87
  304. Fireball_X_Position   = $8d
  305. Block_X_Position      = $8f
  306. Misc_X_Position       = $93
  307. Bubble_X_Position     = $9c
  308.  
  309. SprObject_Y_Speed     = $9f
  310. Player_Y_Speed        = $9f
  311. Enemy_Y_Speed         = $a0
  312. Fireball_Y_Speed      = $a6
  313. Block_Y_Speed         = $a8
  314. Misc_Y_Speed          = $ac
  315.  
  316. SprObject_Y_HighPos   = $b5
  317. Player_Y_HighPos      = $b5
  318. Enemy_Y_HighPos       = $b6
  319. Fireball_Y_HighPos    = $bc
  320. Block_Y_HighPos       = $be
  321. Misc_Y_HighPos        = $c2
  322. Bubble_Y_HighPos      = $cb
  323.  
  324. SprObject_Y_Position  = $ce
  325. Player_Y_Position     = $ce
  326. Enemy_Y_Position      = $cf
  327. Fireball_Y_Position   = $d5
  328. Block_Y_Position      = $d7
  329. Misc_Y_Position       = $db
  330. Bubble_Y_Position     = $e4
  331.  
  332. SprObject_Rel_XPos    = $03ad
  333. Player_Rel_XPos       = $03ad
  334. Enemy_Rel_XPos        = $03ae
  335. Fireball_Rel_XPos     = $03af
  336. Bubble_Rel_XPos       = $03b0
  337. Block_Rel_XPos        = $03b1
  338. Misc_Rel_XPos         = $03b3
  339.  
  340. SprObject_Rel_YPos    = $03b8
  341. Player_Rel_YPos       = $03b8
  342. Enemy_Rel_YPos        = $03b9
  343. Fireball_Rel_YPos     = $03ba
  344. Bubble_Rel_YPos       = $03bb
  345. Block_Rel_YPos        = $03bc
  346. Misc_Rel_YPos         = $03be
  347.  
  348. SprObject_SprAttrib   = $03c4
  349. Player_SprAttrib      = $03c4
  350. Enemy_SprAttrib       = $03c5
  351.  
  352. SprObject_X_MoveForce = $0400
  353. Enemy_X_MoveForce     = $0401
  354.  
  355. SprObject_YMF_Dummy   = $0416
  356. Player_YMF_Dummy      = $0416
  357. Enemy_YMF_Dummy       = $0417
  358. Bubble_YMF_Dummy      = $042c
  359.  
  360. SprObject_Y_MoveForce = $0433
  361. Player_Y_MoveForce    = $0433
  362. Enemy_Y_MoveForce     = $0434
  363. Block_Y_MoveForce     = $043c
  364.  
  365. DisableCollisionDet   = $0716
  366. Player_CollisionBits  = $0490
  367. Enemy_CollisionBits   = $0491
  368.  
  369. SprObj_BoundBoxCtrl   = $0499
  370. Player_BoundBoxCtrl   = $0499
  371. Enemy_BoundBoxCtrl    = $049a
  372. Fireball_BoundBoxCtrl = $04a0
  373. Misc_BoundBoxCtrl     = $04a2
  374.  
  375. EnemyFrenzyBuffer     = $06cb
  376. EnemyFrenzyQueue      = $06cd
  377. Enemy_Flag            = $0f
  378. Enemy_ID              = $16
  379.  
  380. PlayerGfxOffset       = $06d5
  381. Player_XSpeedAbsolute = $0700
  382. FrictionAdderHigh     = $0701
  383. FrictionAdderLow      = $0702
  384. RunningSpeed          = $0703
  385. SwimmingFlag          = $0704
  386. Player_X_MoveForce    = $0705
  387. DiffToHaltJump        = $0706
  388. JumpOrigin_Y_HighPos  = $0707
  389. JumpOrigin_Y_Position = $0708
  390. VerticalForce         = $0709
  391. VerticalForceDown     = $070a
  392. PlayerChangeSizeFlag  = $070b
  393. PlayerAnimTimerSet    = $070c
  394. PlayerAnimCtrl        = $070d
  395. DeathMusicLoaded      = $0712
  396. FlagpoleSoundQueue    = $0713
  397. CrouchingFlag         = $0714
  398. MaximumLeftSpeed      = $0450
  399. MaximumRightSpeed     = $0456
  400.  
  401. SprObject_OffscrBits  = $03d0
  402. Player_OffscreenBits  = $03d0
  403. Enemy_OffscreenBits   = $03d1
  404. FBall_OffscreenBits   = $03d2
  405. Bubble_OffscreenBits  = $03d3
  406. Block_OffscreenBits   = $03d4
  407. Misc_OffscreenBits    = $03d6
  408. EnemyOffscrBitsMasked = $03d8
  409.  
  410. Cannon_Offset         = $046a
  411. Cannon_PageLoc        = $046b
  412. Cannon_X_Position     = $0471
  413. Cannon_Y_Position     = $0477
  414. Cannon_Timer          = $047d
  415.  
  416. Whirlpool_Offset      = $046a
  417. Whirlpool_PageLoc     = $046b
  418. Whirlpool_LeftExtent  = $0471
  419. Whirlpool_Length      = $0477
  420. Whirlpool_Flag        = $047d
  421.  
  422. VineFlagOffset        = $0398
  423. VineHeight            = $0399
  424. VineObjOffset         = $039a
  425. VineStart_Y_Position  = $039d
  426.  
  427. Block_Orig_YPos       = $03e4
  428. Block_BBuf_Low        = $03e6
  429. Block_Metatile        = $03e8
  430. Block_PageLoc2        = $03ea
  431. Block_RepFlag         = $03ec
  432. Block_ResidualCounter = $03f0
  433. Block_Orig_XPos       = $03f1
  434.  
  435. BoundingBox_UL_XPos   = $04ac
  436. BoundingBox_UL_YPos   = $04ad
  437. BoundingBox_DR_XPos   = $04ae
  438. BoundingBox_DR_YPos   = $04af
  439. BoundingBox_UL_Corner = $04ac
  440. BoundingBox_LR_Corner = $04ae
  441. EnemyBoundingBoxCoord = $04b0
  442.  
  443. PowerUpType           = $39
  444.  
  445. FireballBouncingFlag  = $3a
  446. FireballCounter       = $06ce
  447. FireballThrowingTimer = $0711
  448.  
  449. HammerEnemyOffset     = $06ae
  450. JumpCoinMiscOffset    = $06b7
  451.  
  452. Block_Buffer_1        = $0500
  453. Block_Buffer_2        = $05d0
  454.  
  455. HammerThrowingTimer   = $03a2
  456. HammerBroJumpTimer    = $3c
  457. Misc_Collision_Flag   = $06be
  458.  
  459. RedPTroopaOrigXPos    = $0401
  460. RedPTroopaCenterYPos  = $58
  461.  
  462. XMovePrimaryCounter   = $a0
  463. XMoveSecondaryCounter = $58
  464.  
  465. CheepCheepMoveMFlag   = $58
  466. CheepCheepOrigYPos    = $0434
  467. BitMFilter            = $06dd
  468.  
  469. LakituReappearTimer   = $06d1
  470. LakituMoveSpeed       = $58
  471. LakituMoveDirection   = $a0
  472.  
  473. FirebarSpinState_Low  = $58
  474. FirebarSpinState_High = $a0
  475. FirebarSpinSpeed      = $0388
  476. FirebarSpinDirection  = $34
  477.  
  478. DuplicateObj_Offset   = $06cf
  479. NumberofGroupEnemies  = $06d3
  480.  
  481. BlooperMoveCounter    = $a0
  482. BlooperMoveSpeed      = $58
  483.  
  484. BowserBodyControls    = $0363
  485. BowserFeetCounter     = $0364
  486. BowserMovementSpeed   = $0365
  487. BowserOrigXPos        = $0366
  488. BowserFlameTimerCtrl  = $0367
  489. BowserFront_Offset    = $0368
  490. BridgeCollapseOffset  = $0369
  491. BowserGfxFlag         = $036a
  492. BowserHitPoints       = $0483
  493. MaxRangeFromOrigin    = $06dc
  494.  
  495. BowserFlamePRandomOfs = $0417
  496.  
  497. PiranhaPlantUpYPos    = $0417
  498. PiranhaPlantDownYPos  = $0434
  499. PiranhaPlant_Y_Speed  = $58
  500. PiranhaPlant_MoveFlag = $a0
  501.  
  502. FireworksCounter      = $06d7
  503. ExplosionGfxCounter   = $58
  504. ExplosionTimerCounter = $a0
  505.  
  506. ;sound related defines
  507. Squ2_NoteLenBuffer    = $07b3
  508. Squ2_NoteLenCounter   = $07b4
  509. Squ2_EnvelopeDataCtrl = $07b5
  510. Squ1_NoteLenCounter   = $07b6
  511. Squ1_EnvelopeDataCtrl = $07b7
  512. Tri_NoteLenBuffer     = $07b8
  513. Tri_NoteLenCounter    = $07b9
  514. Noise_BeatLenCounter  = $07ba
  515. Squ1_SfxLenCounter    = $07bb
  516. Squ2_SfxLenCounter    = $07bd
  517. Sfx_SecondaryCounter  = $07be
  518. Noise_SfxLenCounter   = $07bf
  519.  
  520. PauseSoundQueue       = $fa
  521. Square1SoundQueue     = $ff
  522. Square2SoundQueue     = $fe
  523. NoiseSoundQueue       = $fd
  524. AreaMusicQueue        = $fb
  525. EventMusicQueue       = $fc
  526.  
  527. Square1SoundBuffer    = $f1
  528. Square2SoundBuffer    = $f2
  529. NoiseSoundBuffer      = $f3
  530. AreaMusicBuffer       = $f4
  531. EventMusicBuffer      = $07b1
  532. PauseSoundBuffer      = $07b2
  533.  
  534. MusicData             = $f5
  535. MusicDataLow          = $f5
  536. MusicDataHigh         = $f6
  537. MusicOffset_Square2   = $f7
  538. MusicOffset_Square1   = $f8
  539. MusicOffset_Triangle  = $f9
  540. MusicOffset_Noise     = $07b0
  541.  
  542. NoteLenLookupTblOfs   = $f0
  543. DAC_Counter           = $07c0
  544. NoiseDataLoopbackOfs  = $07c1
  545. NoteLengthTblAdder    = $07c4
  546. AreaMusicBuffer_Alt   = $07c5
  547. PauseModeFlag         = $07c6
  548. GroundMusicHeaderOfs  = $07c7
  549. AltRegContentFlag     = $07ca
  550.  
  551. ;-------------------------------------------------------------------------------------
  552. ;CONSTANTS
  553.  
  554. ;sound effects constants
  555. Sfx_SmallJump         = %10000000
  556. Sfx_Flagpole          = %01000000
  557. Sfx_Fireball          = %00100000
  558. Sfx_PipeDown_Injury   = %00010000
  559. Sfx_EnemySmack        = %00001000
  560. Sfx_EnemyStomp        = %00000100
  561. Sfx_Bump              = %00000010
  562. Sfx_BigJump           = %00000001
  563.  
  564. Sfx_BowserFall        = %10000000
  565. Sfx_ExtraLife         = %01000000
  566. Sfx_PowerUpGrab       = %00100000
  567. Sfx_TimerTick         = %00010000
  568. Sfx_Blast             = %00001000
  569. Sfx_GrowVine          = %00000100
  570. Sfx_GrowPowerUp       = %00000010
  571. Sfx_CoinGrab          = %00000001
  572.  
  573. Sfx_BowserFlame       = %00000010
  574. Sfx_BrickShatter      = %00000001
  575.  
  576. ;music constants
  577. Silence               = %10000000
  578.  
  579. StarPowerMusic        = %01000000
  580. PipeIntroMusic        = %00100000
  581. CloudMusic            = %00010000
  582. CastleMusic           = %00001000
  583. UndergroundMusic      = %00000100
  584. WaterMusic            = %00000010
  585. GroundMusic           = %00000001
  586.  
  587. TimeRunningOutMusic   = %01000000
  588. EndOfLevelMusic       = %00100000
  589. AltGameOverMusic      = %00010000
  590. EndOfCastleMusic      = %00001000
  591. VictoryMusic          = %00000100
  592. GameOverMusic         = %00000010
  593. DeathMusic            = %00000001
  594.  
  595. ;enemy object constants
  596. GreenKoopa            = $00
  597. BuzzyBeetle           = $02
  598. RedKoopa              = $03
  599. HammerBro             = $05
  600. Goomba                = $06
  601. Bloober               = $07
  602. BulletBill_FrenzyVar  = $08
  603. GreyCheepCheep        = $0a
  604. RedCheepCheep         = $0b
  605. Podoboo               = $0c
  606. PiranhaPlant          = $0d
  607. GreenParatroopaJump   = $0e
  608. RedParatroopa         = $0f
  609. GreenParatroopaFly    = $10
  610. Lakitu                = $11
  611. Spiny                 = $12
  612. FlyCheepCheepFrenzy   = $14
  613. FlyingCheepCheep      = $14
  614. BowserFlame           = $15
  615. Fireworks             = $16
  616. BBill_CCheep_Frenzy   = $17
  617. Stop_Frenzy           = $18
  618. Bowser                = $2d
  619. PowerUpObject         = $2e
  620. VineObject            = $2f
  621. FlagpoleFlagObject    = $30
  622. StarFlagObject        = $31
  623. JumpspringObject      = $32
  624. BulletBill_CannonVar  = $33
  625. RetainerObject        = $35
  626. TallEnemy             = $09
  627.  
  628. ;other constants
  629. World1 = 0
  630. World2 = 1
  631. World3 = 2
  632. World4 = 3
  633. World5 = 4
  634. World6 = 5
  635. World7 = 6
  636. World8 = 7
  637. Level1 = 0
  638. Level2 = 1
  639. Level3 = 2
  640. Level4 = 3
  641.  
  642. WarmBootOffset        = <$07d6
  643. ColdBootOffset        = <$07fe
  644. TitleScreenDataOffset = $1ec0
  645. SoundMemory           = $07b0
  646. SwimTileRepOffset     = PlayerGraphicsTable + $9e
  647. MusicHeaderOffsetData = MusicHeaderData - 1
  648. MHD                   = MusicHeaderData
  649.  
  650. A_Button              = %10000000
  651. B_Button              = %01000000
  652. Select_Button         = %00100000
  653. Start_Button          = %00010000
  654. Up_Dir                = %00001000
  655. Down_Dir              = %00000100
  656. Left_Dir              = %00000010
  657. Right_Dir             = %00000001
  658.  
  659. TitleScreenModeValue  = 0
  660. GameModeValue         = 1
  661. VictoryModeValue      = 2
  662. GameOverModeValue     = 3
  663.  
  664. ;-------------------------------------------------------------------------------------
  665. ;DIRECTIVES
  666.  
  667.        .index 8
  668.        .mem 8
  669.  
  670.        .org $8000
  671.  
  672. ;-------------------------------------------------------------------------------------
  673.  
  674. Start:
  675.              sei                          ;pretty standard 6502 type init here
  676.              cld
  677.              lda #%00010000               ;init PPU control register 1
  678.              sta PPU_CTRL_REG1
  679.              ldx #$ff                     ;reset stack pointer
  680.              txs
  681. VBlank1:     lda PPU_STATUS               ;wait two frames
  682.              bpl VBlank1
  683. VBlank2:     lda PPU_STATUS
  684.              bpl VBlank2
  685.              ldy #ColdBootOffset          ;load default cold boot pointer
  686.              ldx #$05                     ;this is where we check for a warm boot
  687. WBootCheck:  lda TopScoreDisplay,x        ;check each score digit in the top score
  688.              cmp #10                      ;to see if we have a valid digit
  689.              bcs ColdBoot                 ;if not, give up and proceed with cold boot
  690.              dex                      
  691.              bpl WBootCheck
  692.              lda WarmBootValidation       ;second checkpoint, check to see if
  693.              cmp #$a5                     ;another location has a specific value
  694.              bne ColdBoot  
  695.              ldy #WarmBootOffset          ;if passed both, load warm boot pointer
  696. ColdBoot:    jsr InitializeMemory         ;clear memory using pointer in Y
  697.              sta SND_DELTA_REG+1          ;reset delta counter load register
  698.              sta OperMode                 ;reset primary mode of operation
  699.              lda #$a5                     ;set warm boot flag
  700.              sta WarmBootValidation    
  701.              sta PseudoRandomBitReg       ;set seed for pseudorandom register
  702.              lda #%00001111
  703.              sta SND_MASTERCTRL_REG       ;enable all sound channels except dmc
  704.              lda #%00000110
  705.              sta PPU_CTRL_REG2            ;turn off clipping for OAM and background
  706.              jsr MoveAllSpritesOffscreen
  707.              jsr InitializeNameTables     ;initialize both name tables
  708.              inc DisableScreenFlag        ;set flag to disable screen output
  709.              lda Mirror_PPU_CTRL_REG1
  710.              ora #%10000000               ;enable NMIs
  711.              jsr WritePPUReg1
  712. EndlessLoop: jmp EndlessLoop              ;endless loop, need I say more?
  713.  
  714. ;-------------------------------------------------------------------------------------
  715. ;$00 - vram buffer address table low, also used for pseudorandom bit
  716. ;$01 - vram buffer address table high
  717.  
  718. VRAM_AddrTable_Low:
  719.       .db <VRAM_Buffer1, <WaterPaletteData, <GroundPaletteData
  720.       .db <UndergroundPaletteData, <CastlePaletteData, <VRAM_Buffer1_Offset
  721.       .db <VRAM_Buffer2, <VRAM_Buffer2, <BowserPaletteData
  722.       .db <DaySnowPaletteData, <NightSnowPaletteData, <MushroomPaletteData
  723.       .db <MarioThanksMessage, <LuigiThanksMessage, <MushroomRetainerSaved
  724.       .db <PrincessSaved1, <PrincessSaved2, <WorldSelectMessage1
  725.       .db <WorldSelectMessage2
  726.  
  727. VRAM_AddrTable_High:
  728.       .db >VRAM_Buffer1, >WaterPaletteData, >GroundPaletteData
  729.       .db >UndergroundPaletteData, >CastlePaletteData, >VRAM_Buffer1_Offset
  730.       .db >VRAM_Buffer2, >VRAM_Buffer2, >BowserPaletteData
  731.       .db >DaySnowPaletteData, >NightSnowPaletteData, >MushroomPaletteData
  732.       .db >MarioThanksMessage, >LuigiThanksMessage, >MushroomRetainerSaved
  733.       .db >PrincessSaved1, >PrincessSaved2, >WorldSelectMessage1
  734.       .db >WorldSelectMessage2
  735.  
  736. VRAM_Buffer_Offset:
  737.       .db <VRAM_Buffer1_Offset, <VRAM_Buffer2_Offset
  738.  
  739. NonMaskableInterrupt:
  740.                lda Mirror_PPU_CTRL_REG1  ;disable NMIs in mirror reg
  741.                and #%01111111            ;save all other bits
  742.                sta Mirror_PPU_CTRL_REG1
  743.                and #%01111110            ;alter name table address to be $2800
  744.                sta PPU_CTRL_REG1         ;(essentially $2000) but save other bits
  745.                lda Mirror_PPU_CTRL_REG2  ;disable OAM and background display by default
  746.                and #%11100110
  747.                ldy DisableScreenFlag     ;get screen disable flag
  748.                bne ScreenOff             ;if set, used bits as-is
  749.                lda Mirror_PPU_CTRL_REG2  ;otherwise reenable bits and save them
  750.                ora #%00011110
  751. ScreenOff:     sta Mirror_PPU_CTRL_REG2  ;save bits for later but not in register at the moment
  752.                and #%11100111            ;disable screen for now
  753.                sta PPU_CTRL_REG2
  754.                ldx PPU_STATUS            ;reset flip-flop and reset scroll registers to zero
  755.                lda #$00
  756.                jsr InitScroll
  757.                sta PPU_SPR_ADDR          ;reset spr-ram address register
  758.                lda #$02                  ;perform spr-ram DMA access on $0200-$02ff
  759.                sta SPR_DMA
  760.                ldx VRAM_Buffer_AddrCtrl  ;load control for pointer to buffer contents
  761.                lda VRAM_AddrTable_Low,x  ;set indirect at $00 to pointer
  762.                sta $00
  763.                lda VRAM_AddrTable_High,x
  764.                sta $01
  765.                jsr UpdateScreen          ;update screen with buffer contents
  766.                ldy #$00
  767.                ldx VRAM_Buffer_AddrCtrl  ;check for usage of $0341
  768.                cpx #$06
  769.                bne InitBuffer
  770.                iny                       ;get offset based on usage
  771. InitBuffer:    ldx VRAM_Buffer_Offset,y
  772.                lda #$00                  ;clear buffer header at last location
  773.                sta VRAM_Buffer1_Offset,x        
  774.                sta VRAM_Buffer1,x
  775.                sta VRAM_Buffer_AddrCtrl  ;reinit address control to $0301
  776.                lda Mirror_PPU_CTRL_REG2  ;copy mirror of $2001 to register
  777.                sta PPU_CTRL_REG2
  778.                jsr SoundEngine           ;play sound
  779.                jsr ReadJoypads           ;read joypads
  780.                jsr PauseRoutine          ;handle pause
  781.                jsr UpdateTopScore
  782.                lda GamePauseStatus       ;check for pause status
  783.                lsr
  784.                bcs PauseSkip
  785.                lda TimerControl          ;if master timer control not set, decrement
  786.                beq DecTimers             ;all frame and interval timers
  787.                dec TimerControl
  788.                bne NoDecTimers
  789. DecTimers:     ldx #$14                  ;load end offset for end of frame timers
  790.                dec IntervalTimerControl  ;decrement interval timer control,
  791.                bpl DecTimersLoop         ;if not expired, only frame timers will decrement
  792.                lda #$14
  793.                sta IntervalTimerControl  ;if control for interval timers expired,
  794.                ldx #$23                  ;interval timers will decrement along with frame timers
  795. DecTimersLoop: lda Timers,x              ;check current timer
  796.                beq SkipExpTimer          ;if current timer expired, branch to skip,
  797.                dec Timers,x              ;otherwise decrement the current timer
  798. SkipExpTimer:  dex                       ;move onto next timer
  799.                bpl DecTimersLoop         ;do this until all timers are dealt with
  800. NoDecTimers:   inc FrameCounter          ;increment frame counter
  801. PauseSkip:     ldx #$00
  802.                ldy #$07
  803.                lda PseudoRandomBitReg    ;get first memory location of LSFR bytes
  804.                and #%00000010            ;mask out all but d1
  805.                sta $00                   ;save here
  806.                lda PseudoRandomBitReg+1  ;get second memory location
  807.                and #%00000010            ;mask out all but d1
  808.                eor $00                   ;perform exclusive-OR on d1 from first and second bytes
  809.                clc                       ;if neither or both are set, carry will be clear
  810.                beq RotPRandomBit
  811.                sec                       ;if one or the other is set, carry will be set
  812. RotPRandomBit: ror PseudoRandomBitReg,x  ;rotate carry into d7, and rotate last bit into carry
  813.                inx                       ;increment to next byte
  814.                dey                       ;decrement for loop
  815.                bne RotPRandomBit
  816.                lda Sprite0HitDetectFlag  ;check for flag here
  817.                beq SkipSprite0
  818. Sprite0Clr:    lda PPU_STATUS            ;wait for sprite 0 flag to clear, which will
  819.                and #%01000000            ;not happen until vblank has ended
  820.                bne Sprite0Clr
  821.                lda GamePauseStatus       ;if in pause mode, do not bother with sprites at all
  822.                lsr
  823.                bcs Sprite0Hit
  824.                jsr MoveSpritesOffscreen
  825.                jsr SpriteShuffler
  826. Sprite0Hit:    lda PPU_STATUS            ;do sprite #0 hit detection
  827.                and #%01000000
  828.                beq Sprite0Hit
  829.                ldy #$14                  ;small delay, to wait until we hit horizontal blank time
  830. HBlankDelay:   dey
  831.                bne HBlankDelay
  832. SkipSprite0:   lda HorizontalScroll      ;set scroll registers from variables
  833.                sta PPU_SCROLL_REG
  834.                lda VerticalScroll
  835.                sta PPU_SCROLL_REG
  836.                lda Mirror_PPU_CTRL_REG1  ;load saved mirror of $2000
  837.                pha
  838.                sta PPU_CTRL_REG1
  839.                lda GamePauseStatus       ;if in pause mode, do not perform operation mode stuff
  840.                lsr
  841.                bcs SkipMainOper
  842.                jsr OperModeExecutionTree ;otherwise do one of many, many possible subroutines
  843. SkipMainOper:  lda PPU_STATUS            ;reset flip-flop
  844.                pla
  845.                ora #%10000000            ;reactivate NMIs
  846.                sta PPU_CTRL_REG1
  847.                rti                       ;we are done until the next frame!
  848.  
  849. ;-------------------------------------------------------------------------------------
  850.  
  851. PauseRoutine:
  852.                lda OperMode           ;are we in victory mode?
  853.                cmp #VictoryModeValue  ;if so, go ahead
  854.                beq ChkPauseTimer
  855.                cmp #GameModeValue     ;are we in game mode?
  856.                bne ExitPause          ;if not, leave
  857.                lda OperMode_Task      ;if we are in game mode, are we running game engine?
  858.                cmp #$03
  859.                bne ExitPause          ;if not, leave
  860. ChkPauseTimer: lda GamePauseTimer     ;check if pause timer is still counting down
  861.                beq ChkStart
  862.                dec GamePauseTimer     ;if so, decrement and leave
  863.                rts
  864. ChkStart:      lda SavedJoypad1Bits   ;check to see if start is pressed
  865.                and #Start_Button      ;on controller 1
  866.                beq ClrPauseTimer
  867.                lda GamePauseStatus    ;check to see if timer flag is set
  868.                and #%10000000         ;and if so, do not reset timer (residual,
  869.                bne ExitPause          ;joypad reading routine makes this unnecessary)
  870.                lda #$2b               ;set pause timer
  871.                sta GamePauseTimer
  872.                lda GamePauseStatus
  873.                tay
  874.                iny                    ;set pause sfx queue for next pause mode
  875.                sty PauseSoundQueue
  876.                eor #%00000001         ;invert d0 and set d7
  877.                ora #%10000000
  878.                bne SetPause           ;unconditional branch
  879. ClrPauseTimer: lda GamePauseStatus    ;clear timer flag if timer is at zero and start button
  880.                and #%01111111         ;is not pressed
  881. SetPause:      sta GamePauseStatus
  882. ExitPause:     rts
  883.  
  884. ;-------------------------------------------------------------------------------------
  885. ;$00 - used for preset value
  886.  
  887. SpriteShuffler:
  888.                ldy AreaType                ;load level type, likely residual code
  889.                lda #$28                    ;load preset value which will put it at
  890.                sta $00                     ;sprite #10
  891.                ldx #$0e                    ;start at the end of OAM data offsets
  892. ShuffleLoop:   lda SprDataOffset,x         ;check for offset value against
  893.                cmp $00                     ;the preset value
  894.                bcc NextSprOffset           ;if less, skip this part
  895.                ldy SprShuffleAmtOffset     ;get current offset to preset value we want to add
  896.                clc
  897.                adc SprShuffleAmt,y         ;get shuffle amount, add to current sprite offset
  898.                bcc StrSprOffset            ;if not exceeded $ff, skip second add
  899.                clc
  900.                adc $00                     ;otherwise add preset value $28 to offset
  901. StrSprOffset:  sta SprDataOffset,x         ;store new offset here or old one if branched to here
  902. NextSprOffset: dex                         ;move backwards to next one
  903.                bpl ShuffleLoop
  904.                ldx SprShuffleAmtOffset     ;load offset
  905.                inx
  906.                cpx #$03                    ;check if offset + 1 goes to 3
  907.                bne SetAmtOffset            ;if offset + 1 not 3, store
  908.                ldx #$00                    ;otherwise, init to 0
  909. SetAmtOffset:  stx SprShuffleAmtOffset
  910.                ldx #$08                    ;load offsets for values and storage
  911.                ldy #$02
  912. SetMiscOffset: lda SprDataOffset+5,y       ;load one of three OAM data offsets
  913.                sta Misc_SprDataOffset-2,x  ;store first one unmodified, but
  914.                clc                         ;add eight to the second and eight
  915.                adc #$08                    ;more to the third one
  916.                sta Misc_SprDataOffset-1,x  ;note that due to the way X is set up,
  917.                clc                         ;this code loads into the misc sprite offsets
  918.                adc #$08
  919.                sta Misc_SprDataOffset,x        
  920.                dex
  921.                dex
  922.                dex
  923.                dey
  924.                bpl SetMiscOffset           ;do this until all misc spr offsets are loaded
  925.                rts
  926.  
  927. ;-------------------------------------------------------------------------------------
  928.  
  929. OperModeExecutionTree:
  930.       lda OperMode     ;this is the heart of the entire program,
  931.       jsr JumpEngine   ;most of what goes on starts here
  932.  
  933.       .dw TitleScreenMode
  934.       .dw GameMode
  935.       .dw VictoryMode
  936.       .dw GameOverMode
  937.  
  938. ;-------------------------------------------------------------------------------------
  939.  
  940. MoveAllSpritesOffscreen:
  941.               ldy #$00                ;this routine moves all sprites off the screen
  942.               .db $2c                 ;BIT instruction opcode
  943.  
  944. MoveSpritesOffscreen:
  945.               ldy #$04                ;this routine moves all but sprite 0
  946.               lda #$f8                ;off the screen
  947. SprInitLoop:  sta Sprite_Y_Position,y ;write 248 into OAM data's Y coordinate
  948.               iny                     ;which will move it off the screen
  949.               iny
  950.               iny
  951.               iny
  952.               bne SprInitLoop
  953.               rts
  954.  
  955. ;-------------------------------------------------------------------------------------
  956.  
  957. TitleScreenMode:
  958.       lda OperMode_Task
  959.       jsr JumpEngine
  960.  
  961.       .dw InitializeGame
  962.       .dw ScreenRoutines
  963.       .dw PrimaryGameSetup
  964.       .dw GameMenuRoutine
  965.  
  966. ;-------------------------------------------------------------------------------------
  967.  
  968. WSelectBufferTemplate:
  969.       .db $04, $20, $73, $01, $00, $00
  970.  
  971. GameMenuRoutine:
  972.               ldy #$00
  973.               lda SavedJoypad1Bits        ;check to see if either player pressed
  974.               ora SavedJoypad2Bits        ;only the start button (either joypad)
  975.               cmp #Start_Button
  976.               beq StartGame
  977.               cmp #A_Button+Start_Button  ;check to see if A + start was pressed
  978.               bne ChkSelect               ;if not, branch to check select button
  979. StartGame:    jmp ChkContinue             ;if either start or A + start, execute here
  980. ChkSelect:    cmp #Select_Button          ;check to see if the select button was pressed
  981.               beq SelectBLogic            ;if so, branch reset demo timer
  982.               ldx DemoTimer               ;otherwise check demo timer
  983.               bne ChkWorldSel             ;if demo timer not expired, branch to check world selection
  984.               sta SelectTimer             ;set controller bits here if running demo
  985.               jsr DemoEngine              ;run through the demo actions
  986.               bcs ResetTitle              ;if carry flag set, demo over, thus branch
  987.               jmp RunDemo                 ;otherwise, run game engine for demo
  988. ChkWorldSel:  ldx WorldSelectEnableFlag   ;check to see if world selection has been enabled
  989.               beq NullJoypad
  990.               cmp #B_Button               ;if so, check to see if the B button was pressed
  991.               bne NullJoypad
  992.               iny                         ;if so, increment Y and execute same code as select
  993. SelectBLogic: lda DemoTimer               ;if select or B pressed, check demo timer one last time
  994.               beq ResetTitle              ;if demo timer expired, branch to reset title screen mode
  995.               lda #$18                    ;otherwise reset demo timer
  996.               sta DemoTimer
  997.               lda SelectTimer             ;check select/B button timer
  998.               bne NullJoypad              ;if not expired, branch
  999.               lda #$10                    ;otherwise reset select button timer
  1000.               sta SelectTimer
  1001.               cpy #$01                    ;was the B button pressed earlier?  if so, branch
  1002.               beq IncWorldSel             ;note this will not be run if world selection is disabled
  1003.               lda NumberOfPlayers         ;if no, must have been the select button, therefore
  1004.               eor #%00000001              ;change number of players and draw icon accordingly
  1005.               sta NumberOfPlayers
  1006.               jsr DrawMushroomIcon
  1007.               jmp NullJoypad
  1008. IncWorldSel:  ldx WorldSelectNumber       ;increment world select number
  1009.               inx
  1010.               txa
  1011.               and #%00000111              ;mask out higher bits
  1012.               sta WorldSelectNumber       ;store as current world select number
  1013.               jsr GoContinue
  1014. UpdateShroom: lda WSelectBufferTemplate,x ;write template for world select in vram buffer
  1015.               sta VRAM_Buffer1-1,x        ;do this until all bytes are written
  1016.               inx
  1017.               cpx #$06
  1018.               bmi UpdateShroom
  1019.               ldy WorldNumber             ;get world number from variable and increment for
  1020.               iny                         ;proper display, and put in blank byte before
  1021.               sty VRAM_Buffer1+3          ;null terminator
  1022. NullJoypad:   lda #$00                    ;clear joypad bits for player 1
  1023.               sta SavedJoypad1Bits
  1024. RunDemo:      jsr GameCoreRoutine         ;run game engine
  1025.               lda GameEngineSubroutine    ;check to see if we're running lose life routine
  1026.               cmp #$06
  1027.               bne ExitMenu                ;if not, do not do all the resetting below
  1028. ResetTitle:   lda #$00                    ;reset game modes, disable
  1029.               sta OperMode                ;sprite 0 check and disable
  1030.               sta OperMode_Task           ;screen output
  1031.               sta Sprite0HitDetectFlag
  1032.               inc DisableScreenFlag
  1033.               rts
  1034. ChkContinue:  ldy DemoTimer               ;if timer for demo has expired, reset modes
  1035.               beq ResetTitle
  1036.               asl                         ;check to see if A button was also pushed
  1037.               bcc StartWorld1             ;if not, don't load continue function's world number
  1038.               lda ContinueWorld           ;load previously saved world number for secret
  1039.               jsr GoContinue              ;continue function when pressing A + start
  1040. StartWorld1:  jsr LoadAreaPointer
  1041.               inc Hidden1UpFlag           ;set 1-up box flag for both players
  1042.               inc OffScr_Hidden1UpFlag
  1043.               inc FetchNewGameTimerFlag   ;set fetch new game timer flag
  1044.               inc OperMode                ;set next game mode
  1045.               lda WorldSelectEnableFlag   ;if world select flag is on, then primary
  1046.               sta PrimaryHardMode         ;hard mode must be on as well
  1047.               lda #$00
  1048.               sta OperMode_Task           ;set game mode here, and clear demo timer
  1049.               sta DemoTimer
  1050.               ldx #$17
  1051.               lda #$00
  1052. InitScores:   sta ScoreAndCoinDisplay,x   ;clear player scores and coin displays
  1053.               dex
  1054.               bpl InitScores
  1055. ExitMenu:     rts
  1056. GoContinue:   sta WorldNumber             ;start both players at the first area
  1057.               sta OffScr_WorldNumber      ;of the previously saved world number
  1058.               ldx #$00                    ;note that on power-up using this function
  1059.               stx AreaNumber              ;will make no difference
  1060.               stx OffScr_AreaNumber  
  1061.               rts
  1062.  
  1063. ;-------------------------------------------------------------------------------------
  1064.  
  1065. MushroomIconData:
  1066.       .db $07, $22, $49, $83, $ce, $24, $24, $00
  1067.  
  1068. DrawMushroomIcon:
  1069.               ldy #$07                ;read eight bytes to be read by transfer routine
  1070. IconDataRead: lda MushroomIconData,y  ;note that the default position is set for a
  1071.               sta VRAM_Buffer1-1,y    ;1-player game
  1072.               dey
  1073.               bpl IconDataRead
  1074.               lda NumberOfPlayers     ;check number of players
  1075.               beq ExitIcon            ;if set to 1-player game, we're done
  1076.               lda #$24                ;otherwise, load blank tile in 1-player position
  1077.               sta VRAM_Buffer1+3
  1078.               lda #$ce                ;then load shroom icon tile in 2-player position
  1079.               sta VRAM_Buffer1+5
  1080. ExitIcon:     rts
  1081.  
  1082. ;-------------------------------------------------------------------------------------
  1083.  
  1084. DemoActionData:
  1085.       .db $01, $80, $02, $81, $41, $80, $01
  1086.       .db $42, $c2, $02, $80, $41, $c1, $41, $c1
  1087.       .db $01, $c1, $01, $02, $80, $00
  1088.  
  1089. DemoTimingData:
  1090.       .db $9b, $10, $18, $05, $2c, $20, $24
  1091.       .db $15, $5a, $10, $20, $28, $30, $20, $10
  1092.       .db $80, $20, $30, $30, $01, $ff, $00
  1093.  
  1094. DemoEngine:
  1095.           ldx DemoAction         ;load current demo action
  1096.           lda DemoActionTimer    ;load current action timer
  1097.           bne DoAction           ;if timer still counting down, skip
  1098.           inx
  1099.           inc DemoAction         ;if expired, increment action, X, and
  1100.           sec                    ;set carry by default for demo over
  1101.           lda DemoTimingData-1,x ;get next timer
  1102.           sta DemoActionTimer    ;store as current timer
  1103.           beq DemoOver           ;if timer already at zero, skip
  1104. DoAction: lda DemoActionData-1,x ;get and perform action (current or next)
  1105.           sta SavedJoypad1Bits
  1106.           dec DemoActionTimer    ;decrement action timer
  1107.           clc                    ;clear carry if demo still going
  1108. DemoOver: rts
  1109.  
  1110. ;-------------------------------------------------------------------------------------
  1111.  
  1112. VictoryMode:
  1113.             jsr VictoryModeSubroutines  ;run victory mode subroutines
  1114.             lda OperMode_Task           ;get current task of victory mode
  1115.             beq AutoPlayer              ;if on bridge collapse, skip enemy processing
  1116.             ldx #$00
  1117.             stx ObjectOffset            ;otherwise reset enemy object offset
  1118.             jsr EnemiesAndLoopsCore     ;and run enemy code
  1119. AutoPlayer: jsr RelativePlayerPosition  ;get player's relative coordinates
  1120.             jmp PlayerGfxHandler        ;draw the player, then leave
  1121.  
  1122. VictoryModeSubroutines:
  1123.       lda OperMode_Task
  1124.       jsr JumpEngine
  1125.  
  1126.       .dw BridgeCollapse
  1127.       .dw SetupVictoryMode
  1128.       .dw PlayerVictoryWalk
  1129.       .dw PrintVictoryMessages
  1130.       .dw PlayerEndWorld
  1131.  
  1132. ;-------------------------------------------------------------------------------------
  1133.  
  1134. SetupVictoryMode:
  1135.       ldx ScreenRight_PageLoc  ;get page location of right side of screen
  1136.       inx                      ;increment to next page
  1137.       stx DestinationPageLoc   ;store here
  1138.       lda #EndOfCastleMusic
  1139.       sta EventMusicQueue      ;play win castle music
  1140.       jmp IncModeTask_B        ;jump to set next major task in victory mode
  1141.  
  1142. ;-------------------------------------------------------------------------------------
  1143.  
  1144. PlayerVictoryWalk:
  1145.              ldy #$00                ;set value here to not walk player by default
  1146.              sty VictoryWalkControl
  1147.              lda Player_PageLoc      ;get player's page location
  1148.              cmp DestinationPageLoc  ;compare with destination page location
  1149.              bne PerformWalk         ;if page locations don't match, branch
  1150.              lda Player_X_Position   ;otherwise get player's horizontal position
  1151.              cmp #$60                ;compare with preset horizontal position
  1152.              bcs DontWalk            ;if still on other page, branch ahead
  1153. PerformWalk: inc VictoryWalkControl  ;otherwise increment value and Y
  1154.              iny                     ;note Y will be used to walk the player
  1155. DontWalk:    tya                     ;put contents of Y in A and
  1156.              jsr AutoControlPlayer   ;use A to move player to the right or not
  1157.              lda ScreenLeft_PageLoc  ;check page location of left side of screen
  1158.              cmp DestinationPageLoc  ;against set value here
  1159.              beq ExitVWalk           ;branch if equal to change modes if necessary
  1160.              lda ScrollFractional
  1161.              clc                     ;do fixed point math on fractional part of scroll
  1162.              adc #$80        
  1163.              sta ScrollFractional    ;save fractional movement amount
  1164.              lda #$01                ;set 1 pixel per frame
  1165.              adc #$00                ;add carry from previous addition
  1166.              tay                     ;use as scroll amount
  1167.              jsr ScrollScreen        ;do sub to scroll the screen
  1168.              jsr UpdScrollVar        ;do another sub to update screen and scroll variables
  1169.              inc VictoryWalkControl  ;increment value to stay in this routine
  1170. ExitVWalk:   lda VictoryWalkControl  ;load value set here
  1171.              beq IncModeTask_A       ;if zero, branch to change modes
  1172.              rts                     ;otherwise leave
  1173.  
  1174. ;-------------------------------------------------------------------------------------
  1175.  
  1176. PrintVictoryMessages:
  1177.                lda SecondaryMsgCounter   ;load secondary message counter
  1178.                bne IncMsgCounter         ;if set, branch to increment message counters
  1179.                lda PrimaryMsgCounter     ;otherwise load primary message counter
  1180.                beq ThankPlayer           ;if set to zero, branch to print first message
  1181.                cmp #$09                  ;if at 9 or above, branch elsewhere (this comparison
  1182.                bcs IncMsgCounter         ;is residual code, counter never reaches 9)
  1183.                ldy WorldNumber           ;check world number
  1184.                cpy #World8
  1185.                bne MRetainerMsg          ;if not at world 8, skip to next part
  1186.                cmp #$03                  ;check primary message counter again
  1187.                bcc IncMsgCounter         ;if not at 3 yet (world 8 only), branch to increment
  1188.                sbc #$01                  ;otherwise subtract one
  1189.                jmp ThankPlayer           ;and skip to next part
  1190. MRetainerMsg:  cmp #$02                  ;check primary message counter
  1191.                bcc IncMsgCounter         ;if not at 2 yet (world 1-7 only), branch
  1192. ThankPlayer:   tay                       ;put primary message counter into Y
  1193.                bne SecondPartMsg         ;if counter nonzero, skip this part, do not print first message
  1194.                lda CurrentPlayer         ;otherwise get player currently on the screen
  1195.                beq EvalForMusic          ;if mario, branch
  1196.                iny                       ;otherwise increment Y once for luigi and
  1197.                bne EvalForMusic          ;do an unconditional branch to the same place
  1198. SecondPartMsg: iny                       ;increment Y to do world 8's message
  1199.                lda WorldNumber
  1200.                cmp #World8               ;check world number
  1201.                beq EvalForMusic          ;if at world 8, branch to next part
  1202.                dey                       ;otherwise decrement Y for world 1-7's message
  1203.                cpy #$04                  ;if counter at 4 (world 1-7 only)
  1204.                bcs SetEndTimer           ;branch to set victory end timer
  1205.                cpy #$03                  ;if counter at 3 (world 1-7 only)
  1206.                bcs IncMsgCounter         ;branch to keep counting
  1207. EvalForMusic:  cpy #$03                  ;if counter not yet at 3 (world 8 only), branch
  1208.                bne PrintMsg              ;to print message only (note world 1-7 will only
  1209.                lda #VictoryMusic         ;reach this code if counter = 0, and will always branch)
  1210.                sta EventMusicQueue       ;otherwise load victory music first (world 8 only)
  1211. PrintMsg:      tya                       ;put primary message counter in A
  1212.                clc                       ;add $0c or 12 to counter thus giving an appropriate value,
  1213.                adc #$0c                  ;($0c-$0d = first), ($0e = world 1-7's), ($0f-$12 = world 8's)
  1214.                sta VRAM_Buffer_AddrCtrl  ;write message counter to vram address controller
  1215. IncMsgCounter: lda SecondaryMsgCounter
  1216.                clc
  1217.                adc #$04                      ;add four to secondary message counter
  1218.                sta SecondaryMsgCounter
  1219.                lda PrimaryMsgCounter
  1220.                adc #$00                      ;add carry to primary message counter
  1221.                sta PrimaryMsgCounter
  1222.                cmp #$07                      ;check primary counter one more time
  1223. SetEndTimer:   bcc ExitMsgs                  ;if not reached value yet, branch to leave
  1224.                lda #$06
  1225.                sta WorldEndTimer             ;otherwise set world end timer
  1226. IncModeTask_A: inc OperMode_Task             ;move onto next task in mode
  1227. ExitMsgs:      rts                           ;leave
  1228.  
  1229. ;-------------------------------------------------------------------------------------
  1230.  
  1231. PlayerEndWorld:
  1232.                lda WorldEndTimer          ;check to see if world end timer expired
  1233.                bne EndExitOne             ;branch to leave if not
  1234.                ldy WorldNumber            ;check world number
  1235.                cpy #World8                ;if on world 8, player is done with game,
  1236.                bcs EndChkBButton          ;thus branch to read controller
  1237.                lda #$00
  1238.                sta AreaNumber             ;otherwise initialize area number used as offset
  1239.                sta LevelNumber            ;and level number control to start at area 1
  1240.                sta OperMode_Task          ;initialize secondary mode of operation
  1241.                inc WorldNumber            ;increment world number to move onto the next world
  1242.                jsr LoadAreaPointer        ;get area address offset for the next area
  1243.                inc FetchNewGameTimerFlag  ;set flag to load game timer from header
  1244.                lda #GameModeValue
  1245.                sta OperMode               ;set mode of operation to game mode
  1246. EndExitOne:    rts                        ;and leave
  1247. EndChkBButton: lda SavedJoypad1Bits
  1248.                ora SavedJoypad2Bits       ;check to see if B button was pressed on
  1249.                and #B_Button              ;either controller
  1250.                beq EndExitTwo             ;branch to leave if not
  1251.                lda #$01                   ;otherwise set world selection flag
  1252.                sta WorldSelectEnableFlag
  1253.                lda #$ff                   ;remove onscreen player's lives
  1254.                sta NumberofLives
  1255.                jsr TerminateGame          ;do sub to continue other player or end game
  1256. EndExitTwo:    rts                        ;leave
  1257.  
  1258. ;-------------------------------------------------------------------------------------
  1259.  
  1260. ;data is used as tiles for numbers
  1261. ;that appear when you defeat enemies
  1262. FloateyNumTileData:
  1263.       .db $ff, $ff ;dummy
  1264.       .db $f6, $fb ; "100"
  1265.       .db $f7, $fb ; "200"
  1266.       .db $f8, $fb ; "400"
  1267.       .db $f9, $fb ; "500"
  1268.       .db $fa, $fb ; "800"
  1269.       .db $f6, $50 ; "1000"
  1270.       .db $f7, $50 ; "2000"
  1271.       .db $f8, $50 ; "4000"
  1272.       .db $f9, $50 ; "5000"
  1273.       .db $fa, $50 ; "8000"
  1274.       .db $fd, $fe ; "1-UP"
  1275.  
  1276. ;high nybble is digit number, low nybble is number to
  1277. ;add to the digit of the player's score
  1278. ScoreUpdateData:
  1279.       .db $ff ;dummy
  1280.       .db $41, $42, $44, $45, $48
  1281.       .db $31, $32, $34, $35, $38, $00
  1282.  
  1283. FloateyNumbersRoutine:
  1284.               lda FloateyNum_Control,x     ;load control for floatey number
  1285.               beq EndExitOne               ;if zero, branch to leave
  1286.               cmp #$0b                     ;if less than $0b, branch
  1287.               bcc ChkNumTimer
  1288.               lda #$0b                     ;otherwise set to $0b, thus keeping
  1289.               sta FloateyNum_Control,x     ;it in range
  1290. ChkNumTimer:  tay                          ;use as Y
  1291.               lda FloateyNum_Timer,x       ;check value here
  1292.               bne DecNumTimer              ;if nonzero, branch ahead
  1293.               sta FloateyNum_Control,x     ;initialize floatey number control and leave
  1294.               rts
  1295. DecNumTimer:  dec FloateyNum_Timer,x       ;decrement value here
  1296.               cmp #$2b                     ;if not reached a certain point, branch  
  1297.               bne ChkTallEnemy
  1298.               cpy #$0b                     ;check offset for $0b
  1299.               bne LoadNumTiles             ;branch ahead if not found
  1300.               inc NumberofLives            ;give player one extra life (1-up)
  1301.               lda #Sfx_ExtraLife
  1302.               sta Square2SoundQueue        ;and play the 1-up sound
  1303. LoadNumTiles: lda ScoreUpdateData,y        ;load point value here
  1304.               lsr                          ;move high nybble to low
  1305.               lsr
  1306.               lsr
  1307.               lsr
  1308.               tax                          ;use as X offset, essentially the digit
  1309.               lda ScoreUpdateData,y        ;load again and this time
  1310.               and #%00001111               ;mask out the high nybble
  1311.               sta DigitModifier,x          ;store as amount to add to the digit
  1312.               jsr AddToScore               ;update the score accordingly
  1313. ChkTallEnemy: ldy Enemy_SprDataOffset,x    ;get OAM data offset for enemy object
  1314.               lda Enemy_ID,x               ;get enemy object identifier
  1315.               cmp #Spiny
  1316.               beq FloateyPart              ;branch if spiny
  1317.               cmp #PiranhaPlant
  1318.               beq FloateyPart              ;branch if piranha plant
  1319.               cmp #HammerBro
  1320.               beq GetAltOffset             ;branch elsewhere if hammer bro
  1321.               cmp #GreyCheepCheep
  1322.               beq FloateyPart              ;branch if cheep-cheep of either color
  1323.               cmp #RedCheepCheep
  1324.               beq FloateyPart
  1325.               cmp #TallEnemy
  1326.               bcs GetAltOffset             ;branch elsewhere if enemy object => $09
  1327.               lda Enemy_State,x
  1328.               cmp #$02                     ;if enemy state defeated or otherwise
  1329.               bcs FloateyPart              ;$02 or greater, branch beyond this part
  1330. GetAltOffset: ldx SprDataOffset_Ctrl       ;load some kind of control bit
  1331.               ldy Alt_SprDataOffset,x      ;get alternate OAM data offset
  1332.               ldx ObjectOffset             ;get enemy object offset again
  1333. FloateyPart:  lda FloateyNum_Y_Pos,x       ;get vertical coordinate for
  1334.               cmp #$18                     ;floatey number, if coordinate in the
  1335.               bcc SetupNumSpr              ;status bar, branch
  1336.               sbc #$01
  1337.               sta FloateyNum_Y_Pos,x       ;otherwise subtract one and store as new
  1338. SetupNumSpr:  lda FloateyNum_Y_Pos,x       ;get vertical coordinate
  1339.               sbc #$08                     ;subtract eight and dump into the
  1340.               jsr DumpTwoSpr               ;left and right sprite's Y coordinates
  1341.               lda FloateyNum_X_Pos,x       ;get horizontal coordinate
  1342.               sta Sprite_X_Position,y      ;store into X coordinate of left sprite
  1343.               clc
  1344.               adc #$08                     ;add eight pixels and store into X
  1345.               sta Sprite_X_Position+4,y    ;coordinate of right sprite
  1346.               lda #$02
  1347.               sta Sprite_Attributes,y      ;set palette control in attribute bytes
  1348.               sta Sprite_Attributes+4,y    ;of left and right sprites
  1349.               lda FloateyNum_Control,x
  1350.               asl                          ;multiply our floatey number control by 2
  1351.               tax                          ;and use as offset for look-up table
  1352.               lda FloateyNumTileData,x
  1353.               sta Sprite_Tilenumber,y      ;display first half of number of points
  1354.               lda FloateyNumTileData+1,x
  1355.               sta Sprite_Tilenumber+4,y    ;display the second half
  1356.               ldx ObjectOffset             ;get enemy object offset and leave
  1357.               rts
  1358.  
  1359. ;-------------------------------------------------------------------------------------
  1360.  
  1361. ScreenRoutines:
  1362.       lda ScreenRoutineTask        ;run one of the following subroutines
  1363.       jsr JumpEngine
  1364.    
  1365.       .dw InitScreen
  1366.       .dw SetupIntermediate
  1367.       .dw WriteTopStatusLine
  1368.       .dw WriteBottomStatusLine
  1369.       .dw DisplayTimeUp
  1370.       .dw ResetSpritesAndScreenTimer
  1371.       .dw DisplayIntermediate
  1372.       .dw ResetSpritesAndScreenTimer
  1373.       .dw AreaParserTaskControl
  1374.       .dw GetAreaPalette
  1375.       .dw GetBackgroundColor
  1376.       .dw GetAlternatePalette1
  1377.       .dw DrawTitleScreen
  1378.       .dw ClearBuffersDrawIcon
  1379.       .dw WriteTopScore
  1380.  
  1381. ;-------------------------------------------------------------------------------------
  1382.  
  1383. InitScreen:
  1384.       jsr MoveAllSpritesOffscreen ;initialize all sprites including sprite #0
  1385.       jsr InitializeNameTables    ;and erase both name and attribute tables
  1386.       lda OperMode
  1387.       beq NextSubtask             ;if mode still 0, do not load
  1388.       ldx #$03                    ;into buffer pointer
  1389.       jmp SetVRAMAddr_A
  1390.  
  1391. ;-------------------------------------------------------------------------------------
  1392.  
  1393. SetupIntermediate:
  1394.       lda BackgroundColorCtrl  ;save current background color control
  1395.       pha                      ;and player status to stack
  1396.       lda PlayerStatus
  1397.       pha
  1398.       lda #$00                 ;set background color to black
  1399.       sta PlayerStatus         ;and player status to not fiery
  1400.       lda #$02                 ;this is the ONLY time background color control
  1401.       sta BackgroundColorCtrl  ;is set to less than 4
  1402.       jsr GetPlayerColors
  1403.       pla                      ;we only execute this routine for
  1404.       sta PlayerStatus         ;the intermediate lives display
  1405.       pla                      ;and once we're done, we return bg
  1406.       sta BackgroundColorCtrl  ;color ctrl and player status from stack
  1407.       jmp IncSubtask           ;then move onto the next task
  1408.  
  1409. ;-------------------------------------------------------------------------------------
  1410.  
  1411. AreaPalette:
  1412.       .db $01, $02, $03, $04
  1413.  
  1414. GetAreaPalette:
  1415.                ldy AreaType             ;select appropriate palette to load
  1416.                ldx AreaPalette,y        ;based on area type
  1417. SetVRAMAddr_A: stx VRAM_Buffer_AddrCtrl ;store offset into buffer control
  1418. NextSubtask:   jmp IncSubtask           ;move onto next task
  1419.  
  1420. ;-------------------------------------------------------------------------------------
  1421. ;$00 - used as temp counter in GetPlayerColors
  1422.  
  1423. BGColorCtrl_Addr:
  1424.       .db $00, $09, $0a, $04
  1425.  
  1426. BackgroundColors:
  1427.       .db $22, $22, $0f, $0f ;used by area type if bg color ctrl not set
  1428.       .db $0f, $22, $0f, $0f ;used by background color control if set
  1429.  
  1430. PlayerColors:
  1431.       .db $22, $16, $27, $18 ;mario's colors
  1432.       .db $22, $30, $27, $19 ;luigi's colors
  1433.       .db $22, $37, $27, $16 ;fiery (used by both)
  1434.  
  1435. GetBackgroundColor:
  1436.            ldy BackgroundColorCtrl   ;check background color control
  1437.            beq NoBGColor             ;if not set, increment task and fetch palette
  1438.            lda BGColorCtrl_Addr-4,y  ;put appropriate palette into vram
  1439.            sta VRAM_Buffer_AddrCtrl  ;note that if set to 5-7, $0301 will not be read
  1440. NoBGColor: inc ScreenRoutineTask     ;increment to next subtask and plod on through
  1441.      
  1442. GetPlayerColors:
  1443.                ldx VRAM_Buffer1_Offset  ;get current buffer offset
  1444.                ldy #$00
  1445.                lda CurrentPlayer        ;check which player is on the screen
  1446.                beq ChkFiery
  1447.                ldy #$04                 ;load offset for luigi
  1448. ChkFiery:      lda PlayerStatus         ;check player status
  1449.                cmp #$02
  1450.                bne StartClrGet          ;if fiery, load alternate offset for fiery player
  1451.                ldy #$08
  1452. StartClrGet:   lda #$03                 ;do four colors
  1453.                sta $00
  1454. ClrGetLoop:    lda PlayerColors,y       ;fetch player colors and store them
  1455.                sta VRAM_Buffer1+3,x     ;in the buffer
  1456.                iny
  1457.                inx
  1458.                dec $00
  1459.                bpl ClrGetLoop
  1460.                ldx VRAM_Buffer1_Offset  ;load original offset from before
  1461.                ldy BackgroundColorCtrl  ;if this value is four or greater, it will be set
  1462.                bne SetBGColor           ;therefore use it as offset to background color
  1463.                ldy AreaType             ;otherwise use area type bits from area offset as offset
  1464. SetBGColor:    lda BackgroundColors,y   ;to background color instead
  1465.                sta VRAM_Buffer1+3,x
  1466.                lda #$3f                 ;set for sprite palette address
  1467.                sta VRAM_Buffer1,x       ;save to buffer
  1468.                lda #$10
  1469.                sta VRAM_Buffer1+1,x
  1470.                lda #$04                 ;write length byte to buffer
  1471.                sta VRAM_Buffer1+2,x
  1472.                lda #$00                 ;now the null terminator
  1473.                sta VRAM_Buffer1+7,x
  1474.                txa                      ;move the buffer pointer ahead 7 bytes
  1475.                clc                      ;in case we want to write anything else later
  1476.                adc #$07
  1477. SetVRAMOffset: sta VRAM_Buffer1_Offset  ;store as new vram buffer offset
  1478.                rts
  1479.  
  1480. ;-------------------------------------------------------------------------------------
  1481.  
  1482. GetAlternatePalette1:
  1483.                lda AreaStyle            ;check for mushroom level style
  1484.                cmp #$01
  1485.                bne NoAltPal
  1486.                lda #$0b                 ;if found, load appropriate palette
  1487. SetVRAMAddr_B: sta VRAM_Buffer_AddrCtrl
  1488. NoAltPal:      jmp IncSubtask           ;now onto the next task
  1489.  
  1490. ;-------------------------------------------------------------------------------------
  1491.  
  1492. WriteTopStatusLine:
  1493.       lda #$00          ;select main status bar
  1494.       jsr WriteGameText ;output it
  1495.       jmp IncSubtask    ;onto the next task
  1496.  
  1497. ;-------------------------------------------------------------------------------------
  1498.  
  1499. WriteBottomStatusLine:
  1500.       jsr GetSBNybbles        ;write player's score and coin tally to screen
  1501.       ldx VRAM_Buffer1_Offset
  1502.       lda #$20                ;write address for world-area number on screen
  1503.       sta VRAM_Buffer1,x
  1504.       lda #$73
  1505.       sta VRAM_Buffer1+1,x
  1506.       lda #$03                ;write length for it
  1507.       sta VRAM_Buffer1+2,x
  1508.       ldy WorldNumber         ;first the world number
  1509.       iny
  1510.       tya
  1511.       sta VRAM_Buffer1+3,x
  1512.       lda #$28                ;next the dash
  1513.       sta VRAM_Buffer1+4,x
  1514.       ldy LevelNumber         ;next the level number
  1515.       iny                     ;increment for proper number display
  1516.       tya
  1517.       sta VRAM_Buffer1+5,x    
  1518.       lda #$00                ;put null terminator on
  1519.       sta VRAM_Buffer1+6,x
  1520.       txa                     ;move the buffer offset up by 6 bytes
  1521.       clc
  1522.       adc #$06
  1523.       sta VRAM_Buffer1_Offset
  1524.       jmp IncSubtask
  1525.  
  1526. ;-------------------------------------------------------------------------------------
  1527.  
  1528. DisplayTimeUp:
  1529.           lda GameTimerExpiredFlag  ;if game timer not expired, increment task
  1530.           beq NoTimeUp              ;control 2 tasks forward, otherwise, stay here
  1531.           lda #$00
  1532.           sta GameTimerExpiredFlag  ;reset timer expiration flag
  1533.           lda #$02                  ;output time-up screen to buffer
  1534.           jmp OutputInter
  1535. NoTimeUp: inc ScreenRoutineTask     ;increment control task 2 tasks forward
  1536.           jmp IncSubtask
  1537.  
  1538. ;-------------------------------------------------------------------------------------
  1539.  
  1540. DisplayIntermediate:
  1541.                lda OperMode                 ;check primary mode of operation
  1542.                beq NoInter                  ;if in title screen mode, skip this
  1543.                cmp #GameOverModeValue       ;are we in game over mode?
  1544.                beq GameOverInter            ;if so, proceed to display game over screen
  1545.                lda AltEntranceControl       ;otherwise check for mode of alternate entry
  1546.                bne NoInter                  ;and branch if found
  1547.                ldy AreaType                 ;check if we are on castle level
  1548.                cpy #$03                     ;and if so, branch (possibly residual)
  1549.                beq PlayerInter
  1550.                lda DisableIntermediate      ;if this flag is set, skip intermediate lives display
  1551.                bne NoInter                  ;and jump to specific task, otherwise
  1552. PlayerInter:   jsr DrawPlayer_Intermediate  ;put player in appropriate place for
  1553.                lda #$01                     ;lives display, then output lives display to buffer
  1554. OutputInter:   jsr WriteGameText
  1555.                jsr ResetScreenTimer
  1556.                lda #$00
  1557.                sta DisableScreenFlag        ;reenable screen output
  1558.                rts
  1559. GameOverInter: lda #$12                     ;set screen timer
  1560.                sta ScreenTimer
  1561.                lda #$03                     ;output game over screen to buffer
  1562.                jsr WriteGameText
  1563.                jmp IncModeTask_B
  1564. NoInter:       lda #$08                     ;set for specific task and leave
  1565.                sta ScreenRoutineTask
  1566.                rts
  1567.  
  1568. ;-------------------------------------------------------------------------------------
  1569.  
  1570. AreaParserTaskControl:
  1571.            inc DisableScreenFlag     ;turn off screen
  1572. TaskLoop:  jsr AreaParserTaskHandler ;render column set of current area
  1573.            lda AreaParserTaskNum     ;check number of tasks
  1574.            bne TaskLoop              ;if tasks still not all done, do another one
  1575.            dec ColumnSets            ;do we need to render more column sets?
  1576.            bpl OutputCol
  1577.            inc ScreenRoutineTask     ;if not, move on to the next task
  1578. OutputCol: lda #$06                  ;set vram buffer to output rendered column set
  1579.            sta VRAM_Buffer_AddrCtrl  ;on next NMI
  1580.            rts
  1581.  
  1582. ;-------------------------------------------------------------------------------------
  1583.  
  1584. ;$00 - vram buffer address table low
  1585. ;$01 - vram buffer address table high
  1586.  
  1587. DrawTitleScreen:
  1588.             lda OperMode                 ;are we in title screen mode?
  1589.             bne IncModeTask_B            ;if not, exit
  1590.             lda #>TitleScreenDataOffset  ;load address $1ec0 into
  1591.             sta PPU_ADDRESS              ;the vram address register
  1592.             lda #<TitleScreenDataOffset
  1593.             sta PPU_ADDRESS
  1594.             lda #$03                     ;put address $0300 into
  1595.             sta $01                      ;the indirect at $00
  1596.             ldy #$00
  1597.             sty $00
  1598.             lda PPU_DATA                 ;do one garbage read
  1599. OutputTScr: lda PPU_DATA                 ;get title screen from chr-rom
  1600.             sta ($00),y                  ;store 256 bytes into buffer
  1601.             iny
  1602.             bne ChkHiByte                ;if not past 256 bytes, do not increment
  1603.             inc $01                      ;otherwise increment high byte of indirect
  1604. ChkHiByte:  lda $01                      ;check high byte?
  1605.             cmp #$04                     ;at $0400?
  1606.             bne OutputTScr               ;if not, loop back and do another
  1607.             cpy #$3a                     ;check if offset points past end of data
  1608.             bcc OutputTScr               ;if not, loop back and do another
  1609.             lda #$05                     ;set buffer transfer control to $0300,
  1610.             jmp SetVRAMAddr_B            ;increment task and exit
  1611.  
  1612. ;-------------------------------------------------------------------------------------
  1613.  
  1614. ClearBuffersDrawIcon:
  1615.              lda OperMode               ;check game mode
  1616.              bne IncModeTask_B          ;if not title screen mode, leave
  1617.              ldx #$00                   ;otherwise, clear buffer space
  1618. TScrClear:   sta VRAM_Buffer1-1,x
  1619.              sta VRAM_Buffer1-1+$100,x
  1620.              dex
  1621.              bne TScrClear
  1622.              jsr DrawMushroomIcon       ;draw player select icon
  1623. IncSubtask:  inc ScreenRoutineTask      ;move onto next task
  1624.              rts
  1625.  
  1626. ;-------------------------------------------------------------------------------------
  1627.  
  1628. WriteTopScore:
  1629.                lda #$fa           ;run display routine to display top score on title
  1630.                jsr UpdateNumber
  1631. IncModeTask_B: inc OperMode_Task  ;move onto next mode
  1632.                rts
  1633.  
  1634. ;-------------------------------------------------------------------------------------
  1635.  
  1636. GameText:
  1637. TopStatusBarLine:
  1638.   .db $20, $43, $05, $16, $0a, $1b, $12, $18 ; "MARIO"
  1639.   .db $20, $52, $0b, $20, $18, $1b, $15, $0d ; "WORLD  TIME"
  1640.   .db $24, $24, $1d, $12, $16, $0e
  1641.   .db $20, $68, $05, $00, $24, $24, $2e, $29 ; score trailing digit and coin display
  1642.   .db $23, $c0, $7f, $aa ; attribute table data, clears name table 0 to palette 2
  1643.   .db $23, $c2, $01, $ea ; attribute table data, used for coin icon in status bar
  1644.   .db $ff ; end of data block
  1645.  
  1646. WorldLivesDisplay:
  1647.   .db $21, $cd, $07, $24, $24 ; cross with spaces used on
  1648.   .db $29, $24, $24, $24, $24 ; lives display
  1649.   .db $21, $4b, $09, $20, $18 ; "WORLD  - " used on lives display
  1650.   .db $1b, $15, $0d, $24, $24, $28, $24
  1651.   .db $22, $0c, $47, $24 ; possibly used to clear time up
  1652.   .db $23, $dc, $01, $ba ; attribute table data for crown if more than 9 lives
  1653.   .db $ff
  1654.  
  1655. TwoPlayerTimeUp:
  1656.   .db $21, $cd, $05, $16, $0a, $1b, $12, $18 ; "MARIO"
  1657. OnePlayerTimeUp:
  1658.   .db $22, $0c, $07, $1d, $12, $16, $0e, $24, $1e, $19 ; "TIME UP"
  1659.   .db $ff
  1660.  
  1661. TwoPlayerGameOver:
  1662.   .db $21, $cd, $05, $16, $0a, $1b, $12, $18 ; "MARIO"
  1663. OnePlayerGameOver:
  1664.   .db $22, $0b, $09, $10, $0a, $16, $0e, $24 ; "GAME OVER"
  1665.   .db $18, $1f, $0e, $1b
  1666.   .db $ff
  1667.  
  1668. WarpZoneWelcome:
  1669.   .db $25, $84, $15, $20, $0e, $15, $0c, $18, $16 ; "WELCOME TO WARP ZONE!"
  1670.   .db $0e, $24, $1d, $18, $24, $20, $0a, $1b, $19
  1671.   .db $24, $23, $18, $17, $0e, $2b
  1672.   .db $26, $25, $01, $24         ; placeholder for left pipe
  1673.   .db $26, $2d, $01, $24         ; placeholder for middle pipe
  1674.   .db $26, $35, $01, $24         ; placeholder for right pipe
  1675.   .db $27, $d9, $46, $aa         ; attribute data
  1676.   .db $27, $e1, $45, $aa
  1677.   .db $ff
  1678.  
  1679. LuigiName:
  1680.   .db $15, $1e, $12, $10, $12    ; "LUIGI", no address or length
  1681.  
  1682. WarpZoneNumbers:
  1683.   .db $04, $03, $02, $00         ; warp zone numbers, note spaces on middle
  1684.   .db $24, $05, $24, $00         ; zone, partly responsible for
  1685.   .db $08, $07, $06, $00         ; the minus world
  1686.  
  1687. GameTextOffsets:
  1688.   .db TopStatusBarLine-GameText, TopStatusBarLine-GameText
  1689.   .db WorldLivesDisplay-GameText, WorldLivesDisplay-GameText
  1690.   .db TwoPlayerTimeUp-GameText, OnePlayerTimeUp-GameText
  1691.   .db TwoPlayerGameOver-GameText, OnePlayerGameOver-GameText
  1692.   .db WarpZoneWelcome-GameText, WarpZoneWelcome-GameText
  1693.  
  1694. WriteGameText:
  1695.                pha                      ;save text number to stack
  1696.                asl
  1697.                tay                      ;multiply by 2 and use as offset
  1698.                cpy #$04                 ;if set to do top status bar or world/lives display,
  1699.                bcc LdGameText           ;branch to use current offset as-is
  1700.                cpy #$08                 ;if set to do time-up or game over,
  1701.                bcc Chk2Players          ;branch to check players
  1702.                ldy #$08                 ;otherwise warp zone, therefore set offset
  1703. Chk2Players:   lda NumberOfPlayers      ;check for number of players
  1704.                bne LdGameText           ;if there are two, use current offset to also print name
  1705.                iny                      ;otherwise increment offset by one to not print name
  1706. LdGameText:    ldx GameTextOffsets,y    ;get offset to message we want to print
  1707.                ldy #$00
  1708. GameTextLoop:  lda GameText,x           ;load message data
  1709.                cmp #$ff                 ;check for terminator
  1710.                beq EndGameText          ;branch to end text if found
  1711.                sta VRAM_Buffer1,y       ;otherwise write data to buffer
  1712.                inx                      ;and increment increment
  1713.                iny
  1714.                bne GameTextLoop         ;do this for 256 bytes if no terminator found
  1715. EndGameText:   lda #$00                 ;put null terminator at end
  1716.                sta VRAM_Buffer1,y
  1717.                pla                      ;pull original text number from stack
  1718.                tax
  1719.                cmp #$04                 ;are we printing warp zone?
  1720.                bcs PrintWarpZoneNumbers
  1721.                dex                      ;are we printing the world/lives display?
  1722.                bne CheckPlayerName      ;if not, branch to check player's name
  1723.                lda NumberofLives        ;otherwise, check number of lives
  1724.                clc                      ;and increment by one for display
  1725.                adc #$01
  1726.                cmp #10                  ;more than 9 lives?
  1727.                bcc PutLives
  1728.                sbc #10                  ;if so, subtract 10 and put a crown tile
  1729.                ldy #$9f                 ;next to the difference...strange things happen if
  1730.                sty VRAM_Buffer1+7       ;the number of lives exceeds 19
  1731. PutLives:      sta VRAM_Buffer1+8
  1732.                ldy WorldNumber          ;write world and level numbers (incremented for display)
  1733.                iny                      ;to the buffer in the spaces surrounding the dash
  1734.                sty VRAM_Buffer1+19
  1735.                ldy LevelNumber
  1736.                iny
  1737.                sty VRAM_Buffer1+21      ;we're done here
  1738.                rts
  1739.  
  1740. CheckPlayerName:
  1741.              lda NumberOfPlayers    ;check number of players
  1742.              beq ExitChkName        ;if only 1 player, leave
  1743.              lda CurrentPlayer      ;load current player
  1744.              dex                    ;check to see if current message number is for time up
  1745.              bne ChkLuigi
  1746.              ldy OperMode           ;check for game over mode
  1747.              cpy #GameOverModeValue
  1748.              beq ChkLuigi
  1749.              eor #%00000001         ;if not, must be time up, invert d0 to do other player
  1750. ChkLuigi:    lsr
  1751.              bcc ExitChkName        ;if mario is current player, do not change the name
  1752.              ldy #$04
  1753. NameLoop:    lda LuigiName,y        ;otherwise, replace "MARIO" with "LUIGI"
  1754.              sta VRAM_Buffer1+3,y
  1755.              dey
  1756.              bpl NameLoop           ;do this until each letter is replaced
  1757. ExitChkName: rts
  1758.  
  1759. PrintWarpZoneNumbers:
  1760.              sbc #$04               ;subtract 4 and then shift to the left
  1761.              asl                    ;twice to get proper warp zone number
  1762.              asl                    ;offset
  1763.              tax
  1764.              ldy #$00
  1765. WarpNumLoop: lda WarpZoneNumbers,x  ;print warp zone numbers into the
  1766.              sta VRAM_Buffer1+27,y  ;placeholders from earlier
  1767.              inx
  1768.              iny                    ;put a number in every fourth space
  1769.              iny
  1770.              iny
  1771.              iny
  1772.              cpy #$0c
  1773.              bcc WarpNumLoop
  1774.              lda #$2c               ;load new buffer pointer at end of message
  1775.              jmp SetVRAMOffset
  1776.  
  1777. ;-------------------------------------------------------------------------------------
  1778.  
  1779. ResetSpritesAndScreenTimer:
  1780.          lda ScreenTimer             ;check if screen timer has expired
  1781.          bne NoReset                 ;if not, branch to leave
  1782.          jsr MoveAllSpritesOffscreen ;otherwise reset sprites now
  1783.  
  1784. ResetScreenTimer:
  1785.          lda #$07                    ;reset timer again
  1786.          sta ScreenTimer
  1787.          inc ScreenRoutineTask       ;move onto next task
  1788. NoReset: rts
  1789.  
  1790. ;-------------------------------------------------------------------------------------
  1791. ;$00 - temp vram buffer offset
  1792. ;$01 - temp metatile buffer offset
  1793. ;$02 - temp metatile graphics table offset
  1794. ;$03 - used to store attribute bits
  1795. ;$04 - used to determine attribute table row
  1796. ;$05 - used to determine attribute table column
  1797. ;$06 - metatile graphics table address low
  1798. ;$07 - metatile graphics table address high
  1799.  
  1800. RenderAreaGraphics:
  1801.             lda CurrentColumnPos         ;store LSB of where we're at
  1802.             and #$01
  1803.             sta $05
  1804.             ldy VRAM_Buffer2_Offset      ;store vram buffer offset
  1805.             sty $00
  1806.             lda CurrentNTAddr_Low        ;get current name table address we're supposed to render
  1807.             sta VRAM_Buffer2+1,y
  1808.             lda CurrentNTAddr_High
  1809.             sta VRAM_Buffer2,y
  1810.             lda #$9a                     ;store length byte of 26 here with d7 set
  1811.             sta VRAM_Buffer2+2,y         ;to increment by 32 (in columns)
  1812.             lda #$00                     ;init attribute row
  1813.             sta $04
  1814.             tax
  1815. DrawMTLoop: stx $01                      ;store init value of 0 or incremented offset for buffer
  1816.             lda MetatileBuffer,x         ;get first metatile number, and mask out all but 2 MSB
  1817.             and #%11000000
  1818.             sta $03                      ;store attribute table bits here
  1819.             asl                          ;note that metatile format is:
  1820.             rol                          ;%xx000000 - attribute table bits,
  1821.             rol                          ;%00xxxxxx - metatile number
  1822.             tay                          ;rotate bits to d1-d0 and use as offset here
  1823.             lda MetatileGraphics_Low,y   ;get address to graphics table from here
  1824.             sta $06
  1825.             lda MetatileGraphics_High,y
  1826.             sta $07
  1827.             lda MetatileBuffer,x         ;get metatile number again
  1828.             asl                          ;multiply by 4 and use as tile offset
  1829.             asl
  1830.             sta $02
  1831.             lda AreaParserTaskNum        ;get current task number for level processing and
  1832.             and #%00000001               ;mask out all but LSB, then invert LSB, multiply by 2
  1833.             eor #%00000001               ;to get the correct column position in the metatile,
  1834.             asl                          ;then add to the tile offset so we can draw either side
  1835.             adc $02                      ;of the metatiles
  1836.             tay
  1837.             ldx $00                      ;use vram buffer offset from before as X
  1838.             lda ($06),y
  1839.             sta VRAM_Buffer2+3,x         ;get first tile number (top left or top right) and store
  1840.             iny
  1841.             lda ($06),y                  ;now get the second (bottom left or bottom right) and store
  1842.             sta VRAM_Buffer2+4,x
  1843.             ldy $04                      ;get current attribute row
  1844.             lda $05                      ;get LSB of current column where we're at, and
  1845.             bne RightCheck               ;branch if set (clear = left attrib, set = right)
  1846.             lda $01                      ;get current row we're rendering
  1847.             lsr                          ;branch if LSB set (clear = top left, set = bottom left)
  1848.             bcs LLeft
  1849.             rol $03                      ;rotate attribute bits 3 to the left
  1850.             rol $03                      ;thus in d1-d0, for upper left square
  1851.             rol $03
  1852.             jmp SetAttrib
  1853. RightCheck: lda $01                      ;get LSB of current row we're rendering
  1854.             lsr                          ;branch if set (clear = top right, set = bottom right)
  1855.             bcs NextMTRow
  1856.             lsr $03                      ;shift attribute bits 4 to the right
  1857.             lsr $03                      ;thus in d3-d2, for upper right square
  1858.             lsr $03
  1859.             lsr $03
  1860.             jmp SetAttrib
  1861. LLeft:      lsr $03                      ;shift attribute bits 2 to the right
  1862.             lsr $03                      ;thus in d5-d4 for lower left square
  1863. NextMTRow:  inc $04                      ;move onto next attribute row  
  1864. SetAttrib:  lda AttributeBuffer,y        ;get previously saved bits from before
  1865.             ora $03                      ;if any, and put new bits, if any, onto
  1866.             sta AttributeBuffer,y        ;the old, and store
  1867.             inc $00                      ;increment vram buffer offset by 2
  1868.             inc $00
  1869.             ldx $01                      ;get current gfx buffer row, and check for
  1870.             inx                          ;the bottom of the screen
  1871.             cpx #$0d
  1872.             bcc DrawMTLoop               ;if not there yet, loop back
  1873.             ldy $00                      ;get current vram buffer offset, increment by 3
  1874.             iny                          ;(for name table address and length bytes)
  1875.             iny
  1876.             iny
  1877.             lda #$00
  1878.             sta VRAM_Buffer2,y           ;put null terminator at end of data for name table
  1879.             sty VRAM_Buffer2_Offset      ;store new buffer offset
  1880.             inc CurrentNTAddr_Low        ;increment name table address low
  1881.             lda CurrentNTAddr_Low        ;check current low byte
  1882.             and #%00011111               ;if no wraparound, just skip this part
  1883.             bne ExitDrawM
  1884.             lda #$80                     ;if wraparound occurs, make sure low byte stays
  1885.             sta CurrentNTAddr_Low        ;just under the status bar
  1886.             lda CurrentNTAddr_High       ;and then invert d2 of the name table address high
  1887.             eor #%00000100               ;to move onto the next appropriate name table
  1888.             sta CurrentNTAddr_High
  1889. ExitDrawM:  jmp SetVRAMCtrl              ;jump to set buffer to $0341 and leave
  1890.  
  1891. ;-------------------------------------------------------------------------------------
  1892. ;$00 - temp attribute table address high (big endian order this time!)
  1893. ;$01 - temp attribute table address low
  1894.  
  1895. RenderAttributeTables:
  1896.              lda CurrentNTAddr_Low    ;get low byte of next name table address
  1897.              and #%00011111           ;to be written to, mask out all but 5 LSB,
  1898.              sec                      ;subtract four
  1899.              sbc #$04
  1900.              and #%00011111           ;mask out bits again and store
  1901.              sta $01
  1902.              lda CurrentNTAddr_High   ;get high byte and branch if borrow not set
  1903.              bcs SetATHigh
  1904.              eor #%00000100           ;otherwise invert d2
  1905. SetATHigh:   and #%00000100           ;mask out all other bits
  1906.              ora #$23                 ;add $2300 to the high byte and store
  1907.              sta $00
  1908.              lda $01                  ;get low byte - 4, divide by 4, add offset for
  1909.              lsr                      ;attribute table and store
  1910.              lsr
  1911.              adc #$c0                 ;we should now have the appropriate block of
  1912.              sta $01                  ;attribute table in our temp address
  1913.              ldx #$00
  1914.              ldy VRAM_Buffer2_Offset  ;get buffer offset
  1915. AttribLoop:  lda $00
  1916.              sta VRAM_Buffer2,y       ;store high byte of attribute table address
  1917.              lda $01
  1918.              clc                      ;get low byte, add 8 because we want to start
  1919.              adc #$08                 ;below the status bar, and store
  1920.              sta VRAM_Buffer2+1,y
  1921.              sta $01                  ;also store in temp again
  1922.              lda AttributeBuffer,x    ;fetch current attribute table byte and store
  1923.              sta VRAM_Buffer2+3,y     ;in the buffer
  1924.              lda #$01
  1925.              sta VRAM_Buffer2+2,y     ;store length of 1 in buffer
  1926.              lsr
  1927.              sta AttributeBuffer,x    ;clear current byte in attribute buffer
  1928.              iny                      ;increment buffer offset by 4 bytes
  1929.              iny
  1930.              iny
  1931.              iny
  1932.              inx                      ;increment attribute offset and check to see
  1933.              cpx #$07                 ;if we're at the end yet
  1934.              bcc AttribLoop
  1935.              sta VRAM_Buffer2,y       ;put null terminator at the end
  1936.              sty VRAM_Buffer2_Offset  ;store offset in case we want to do any more
  1937. SetVRAMCtrl: lda #$06
  1938.              sta VRAM_Buffer_AddrCtrl ;set buffer to $0341 and leave
  1939.              rts
  1940.  
  1941. ;-------------------------------------------------------------------------------------
  1942.  
  1943. ;$00 - used as temporary counter in ColorRotation
  1944.  
  1945. ColorRotatePalette:
  1946.        .db $27, $27, $27, $17, $07, $17
  1947.  
  1948. BlankPalette:
  1949.        .db $3f, $0c, $04, $ff, $ff, $ff, $ff, $00
  1950.  
  1951. ;used based on area type
  1952. Palette3Data:
  1953.        .db $0f, $07, $12, $0f
  1954.        .db $0f, $07, $17, $0f
  1955.        .db $0f, $07, $17, $1c
  1956.        .db $0f, $07, $17, $00
  1957.  
  1958. ColorRotation:
  1959.               lda FrameCounter         ;get frame counter
  1960.               and #$07                 ;mask out all but three LSB
  1961.               bne ExitColorRot         ;branch if not set to zero to do this every eighth frame
  1962.               ldx VRAM_Buffer1_Offset  ;check vram buffer offset
  1963.               cpx #$31
  1964.               bcs ExitColorRot         ;if offset over 48 bytes, branch to leave
  1965.               tay                      ;otherwise use frame counter's 3 LSB as offset here
  1966. GetBlankPal:  lda BlankPalette,y       ;get blank palette for palette 3
  1967.               sta VRAM_Buffer1,x       ;store it in the vram buffer
  1968.               inx                      ;increment offsets
  1969.               iny
  1970.               cpy #$08
  1971.               bcc GetBlankPal          ;do this until all bytes are copied
  1972.               ldx VRAM_Buffer1_Offset  ;get current vram buffer offset
  1973.               lda #$03
  1974.               sta $00                  ;set counter here
  1975.               lda AreaType             ;get area type
  1976.               asl                      ;multiply by 4 to get proper offset
  1977.               asl
  1978.               tay                      ;save as offset here
  1979. GetAreaPal:   lda Palette3Data,y       ;fetch palette to be written based on area type
  1980.               sta VRAM_Buffer1+3,x     ;store it to overwrite blank palette in vram buffer
  1981.               iny
  1982.               inx
  1983.               dec $00                  ;decrement counter
  1984.               bpl GetAreaPal           ;do this until the palette is all copied
  1985.               ldx VRAM_Buffer1_Offset  ;get current vram buffer offset
  1986.               ldy ColorRotateOffset    ;get color cycling offset
  1987.               lda ColorRotatePalette,y
  1988.               sta VRAM_Buffer1+4,x     ;get and store current color in second slot of palette
  1989.               lda VRAM_Buffer1_Offset
  1990.               clc                      ;add seven bytes to vram buffer offset
  1991.               adc #$07
  1992.               sta VRAM_Buffer1_Offset
  1993.               inc ColorRotateOffset    ;increment color cycling offset
  1994.               lda ColorRotateOffset
  1995.               cmp #$06                 ;check to see if it's still in range
  1996.               bcc ExitColorRot         ;if so, branch to leave
  1997.               lda #$00
  1998.               sta ColorRotateOffset    ;otherwise, init to keep it in range
  1999. ExitColorRot: rts                      ;leave
  2000.  
  2001. ;-------------------------------------------------------------------------------------
  2002. ;$00 - temp store for offset control bit
  2003. ;$01 - temp vram buffer offset
  2004. ;$02 - temp store for vertical high nybble in block buffer routine
  2005. ;$03 - temp adder for high byte of name table address
  2006. ;$04, $05 - name table address low/high
  2007. ;$06, $07 - block buffer address low/high
  2008.  
  2009. BlockGfxData:
  2010.        .db $45, $45, $47, $47
  2011.        .db $47, $47, $47, $47
  2012.        .db $57, $58, $59, $5a
  2013.        .db $24, $24, $24, $24
  2014.        .db $26, $26, $26, $26
  2015.  
  2016. RemoveCoin_Axe:
  2017.               ldy #$41                 ;set low byte so offset points to $0341
  2018.               lda #$03                 ;load offset for default blank metatile
  2019.               ldx AreaType             ;check area type
  2020.               bne WriteBlankMT         ;if not water type, use offset
  2021.               lda #$04                 ;otherwise load offset for blank metatile used in water
  2022. WriteBlankMT: jsr PutBlockMetatile     ;do a sub to write blank metatile to vram buffer
  2023.               lda #$06
  2024.               sta VRAM_Buffer_AddrCtrl ;set vram address controller to $0341 and leave
  2025.               rts
  2026.  
  2027. ReplaceBlockMetatile:
  2028.        jsr WriteBlockMetatile    ;write metatile to vram buffer to replace block object
  2029.        inc Block_ResidualCounter ;increment unused counter (residual code)
  2030.        dec Block_RepFlag,x       ;decrement flag (residual code)
  2031.        rts                       ;leave
  2032.  
  2033. DestroyBlockMetatile:
  2034.        lda #$00       ;force blank metatile if branched/jumped to this point
  2035.  
  2036. WriteBlockMetatile:
  2037.              ldy #$03                ;load offset for blank metatile
  2038.              cmp #$00                ;check contents of A for blank metatile
  2039.              beq UseBOffset          ;branch if found (unconditional if branched from 8a6b)
  2040.              ldy #$00                ;load offset for brick metatile w/ line
  2041.              cmp #$58
  2042.              beq UseBOffset          ;use offset if metatile is brick with coins (w/ line)
  2043.              cmp #$51
  2044.              beq UseBOffset          ;use offset if metatile is breakable brick w/ line
  2045.              iny                     ;increment offset for brick metatile w/o line
  2046.              cmp #$5d
  2047.              beq UseBOffset          ;use offset if metatile is brick with coins (w/o line)
  2048.              cmp #$52
  2049.              beq UseBOffset          ;use offset if metatile is breakable brick w/o line
  2050.              iny                     ;if any other metatile, increment offset for empty block
  2051. UseBOffset:  tya                     ;put Y in A
  2052.              ldy VRAM_Buffer1_Offset ;get vram buffer offset
  2053.              iny                     ;move onto next byte
  2054.              jsr PutBlockMetatile    ;get appropriate block data and write to vram buffer
  2055. MoveVOffset: dey                     ;decrement vram buffer offset
  2056.              tya                     ;add 10 bytes to it
  2057.              clc
  2058.              adc #10
  2059.              jmp SetVRAMOffset       ;branch to store as new vram buffer offset
  2060.  
  2061. PutBlockMetatile:
  2062.             stx $00               ;store control bit from SprDataOffset_Ctrl
  2063.             sty $01               ;store vram buffer offset for next byte
  2064.             asl
  2065.             asl                   ;multiply A by four and use as X
  2066.             tax
  2067.             ldy #$20              ;load high byte for name table 0
  2068.             lda $06               ;get low byte of block buffer pointer
  2069.             cmp #$d0              ;check to see if we're on odd-page block buffer
  2070.             bcc SaveHAdder        ;if not, use current high byte
  2071.             ldy #$24              ;otherwise load high byte for name table 1
  2072. SaveHAdder: sty $03               ;save high byte here
  2073.             and #$0f              ;mask out high nybble of block buffer pointer
  2074.             asl                   ;multiply by 2 to get appropriate name table low byte
  2075.             sta $04               ;and then store it here
  2076.             lda #$00
  2077.             sta $05               ;initialize temp high byte
  2078.             lda $02               ;get vertical high nybble offset used in block buffer routine
  2079.             clc
  2080.             adc #$20              ;add 32 pixels for the status bar
  2081.             asl
  2082.             rol $05               ;shift and rotate d7 onto d0 and d6 into carry
  2083.             asl
  2084.             rol $05               ;shift and rotate d6 onto d0 and d5 into carry
  2085.             adc $04               ;add low byte of name table and carry to vertical high nybble
  2086.             sta $04               ;and store here
  2087.             lda $05               ;get whatever was in d7 and d6 of vertical high nybble
  2088.             adc #$00              ;add carry
  2089.             clc
  2090.             adc $03               ;then add high byte of name table
  2091.             sta $05               ;store here
  2092.             ldy $01               ;get vram buffer offset to be used
  2093. RemBridge:  lda BlockGfxData,x    ;write top left and top right
  2094.             sta VRAM_Buffer1+2,y  ;tile numbers into first spot
  2095.             lda BlockGfxData+1,x
  2096.             sta VRAM_Buffer1+3,y
  2097.             lda BlockGfxData+2,x  ;write bottom left and bottom
  2098.             sta VRAM_Buffer1+7,y  ;right tiles numbers into
  2099.             lda BlockGfxData+3,x  ;second spot
  2100.             sta VRAM_Buffer1+8,y
  2101.             lda $04
  2102.             sta VRAM_Buffer1,y    ;write low byte of name table
  2103.             clc                   ;into first slot as read
  2104.             adc #$20              ;add 32 bytes to value
  2105.             sta VRAM_Buffer1+5,y  ;write low byte of name table
  2106.             lda $05               ;plus 32 bytes into second slot
  2107.             sta VRAM_Buffer1-1,y  ;write high byte of name
  2108.             sta VRAM_Buffer1+4,y  ;table address to both slots
  2109.             lda #$02
  2110.             sta VRAM_Buffer1+1,y  ;put length of 2 in
  2111.             sta VRAM_Buffer1+6,y  ;both slots
  2112.             lda #$00
  2113.             sta VRAM_Buffer1+9,y  ;put null terminator at end
  2114.             ldx $00               ;get offset control bit here
  2115.             rts                   ;and leave
  2116.  
  2117. ;-------------------------------------------------------------------------------------
  2118. ;METATILE GRAPHICS TABLE
  2119.  
  2120. MetatileGraphics_Low:
  2121.   .db <Palette0_MTiles, <Palette1_MTiles, <Palette2_MTiles, <Palette3_MTiles
  2122.  
  2123. MetatileGraphics_High:
  2124.   .db >Palette0_MTiles, >Palette1_MTiles, >Palette2_MTiles, >Palette3_MTiles
  2125.  
  2126. Palette0_MTiles:
  2127.   .db $24, $24, $24, $24 ;blank
  2128.   .db $27, $27, $27, $27 ;black metatile
  2129.   .db $24, $24, $24, $35 ;bush left
  2130.   .db $36, $25, $37, $25 ;bush middle
  2131.   .db $24, $38, $24, $24 ;bush right
  2132.   .db $24, $30, $30, $26 ;mountain left
  2133.   .db $26, $26, $34, $26 ;mountain left bottom/middle center
  2134.   .db $24, $31, $24, $32 ;mountain middle top
  2135.   .db $33, $26, $24, $33 ;mountain right
  2136.   .db $34, $26, $26, $26 ;mountain right bottom
  2137.   .db $26, $26, $26, $26 ;mountain middle bottom
  2138.   .db $24, $c0, $24, $c0 ;bridge guardrail
  2139.   .db $24, $7f, $7f, $24 ;chain
  2140.   .db $b8, $ba, $b9, $bb ;tall tree top, top half
  2141.   .db $b8, $bc, $b9, $bd ;short tree top
  2142.   .db $ba, $bc, $bb, $bd ;tall tree top, bottom half
  2143.   .db $60, $64, $61, $65 ;warp pipe end left, points up
  2144.   .db $62, $66, $63, $67 ;warp pipe end right, points up
  2145.   .db $60, $64, $61, $65 ;decoration pipe end left, points up
  2146.   .db $62, $66, $63, $67 ;decoration pipe end right, points up
  2147.   .db $68, $68, $69, $69 ;pipe shaft left
  2148.   .db $26, $26, $6a, $6a ;pipe shaft right
  2149.   .db $4b, $4c, $4d, $4e ;tree ledge left edge
  2150.   .db $4d, $4f, $4d, $4f ;tree ledge middle
  2151.   .db $4d, $4e, $50, $51 ;tree ledge right edge
  2152.   .db $6b, $70, $2c, $2d ;mushroom left edge
  2153.   .db $6c, $71, $6d, $72 ;mushroom middle
  2154.   .db $6e, $73, $6f, $74 ;mushroom right edge
  2155.   .db $86, $8a, $87, $8b ;sideways pipe end top
  2156.   .db $88, $8c, $88, $8c ;sideways pipe shaft top
  2157.   .db $89, $8d, $69, $69 ;sideways pipe joint top
  2158.   .db $8e, $91, $8f, $92 ;sideways pipe end bottom
  2159.   .db $26, $93, $26, $93 ;sideways pipe shaft bottom
  2160.   .db $90, $94, $69, $69 ;sideways pipe joint bottom
  2161.   .db $a4, $e9, $ea, $eb ;seaplant
  2162.   .db $24, $24, $24, $24 ;blank, used on bricks or blocks that are hit
  2163.   .db $24, $2f, $24, $3d ;flagpole ball
  2164.   .db $a2, $a2, $a3, $a3 ;flagpole shaft
  2165.   .db $24, $24, $24, $24 ;blank, used in conjunction with vines
  2166.  
  2167. Palette1_MTiles:
  2168.   .db $a2, $a2, $a3, $a3 ;vertical rope
  2169.   .db $99, $24, $99, $24 ;horizontal rope
  2170.   .db $24, $a2, $3e, $3f ;left pulley
  2171.   .db $5b, $5c, $24, $a3 ;right pulley
  2172.   .db $24, $24, $24, $24 ;blank used for balance rope
  2173.   .db $9d, $47, $9e, $47 ;castle top
  2174.   .db $47, $47, $27, $27 ;castle window left
  2175.   .db $47, $47, $47, $47 ;castle brick wall
  2176.   .db $27, $27, $47, $47 ;castle window right
  2177.   .db $a9, $47, $aa, $47 ;castle top w/ brick
  2178.   .db $9b, $27, $9c, $27 ;entrance top
  2179.   .db $27, $27, $27, $27 ;entrance bottom
  2180.   .db $52, $52, $52, $52 ;green ledge stump
  2181.   .db $80, $a0, $81, $a1 ;fence
  2182.   .db $be, $be, $bf, $bf ;tree trunk
  2183.   .db $75, $ba, $76, $bb ;mushroom stump top
  2184.   .db $ba, $ba, $bb, $bb ;mushroom stump bottom
  2185.   .db $45, $47, $45, $47 ;breakable brick w/ line
  2186.   .db $47, $47, $47, $47 ;breakable brick
  2187.   .db $45, $47, $45, $47 ;breakable brick (not used)
  2188.   .db $b4, $b6, $b5, $b7 ;cracked rock terrain
  2189.   .db $45, $47, $45, $47 ;brick with line (power-up)
  2190.   .db $45, $47, $45, $47 ;brick with line (vine)
  2191.   .db $45, $47, $45, $47 ;brick with line (star)
  2192.   .db $45, $47, $45, $47 ;brick with line (coins)
  2193.   .db $45, $47, $45, $47 ;brick with line (1-up)
  2194.   .db $47, $47, $47, $47 ;brick (power-up)
  2195.   .db $47, $47, $47, $47 ;brick (vine)
  2196.   .db $47, $47, $47, $47 ;brick (star)
  2197.   .db $47, $47, $47, $47 ;brick (coins)
  2198.   .db $47, $47, $47, $47 ;brick (1-up)
  2199.   .db $24, $24, $24, $24 ;hidden block (1 coin)
  2200.   .db $24, $24, $24, $24 ;hidden block (1-up)
  2201.   .db $ab, $ac, $ad, $ae ;solid block (3-d block)
  2202.   .db $5d, $5e, $5d, $5e ;solid block (white wall)
  2203.   .db $c1, $24, $c1, $24 ;bridge
  2204.   .db $c6, $c8, $c7, $c9 ;bullet bill cannon barrel
  2205.   .db $ca, $cc, $cb, $cd ;bullet bill cannon top
  2206.   .db $2a, $2a, $40, $40 ;bullet bill cannon bottom
  2207.   .db $24, $24, $24, $24 ;blank used for jumpspring
  2208.   .db $24, $47, $24, $47 ;half brick used for jumpspring
  2209.   .db $82, $83, $84, $85 ;solid block (water level, green rock)
  2210.   .db $24, $47, $24, $47 ;half brick (???)
  2211.   .db $86, $8a, $87, $8b ;water pipe top
  2212.   .db $8e, $91, $8f, $92 ;water pipe bottom
  2213.   .db $24, $2f, $24, $3d ;flag ball (residual object)
  2214.  
  2215. Palette2_MTiles:
  2216.   .db $24, $24, $24, $35 ;cloud left
  2217.   .db $36, $25, $37, $25 ;cloud middle
  2218.   .db $24, $38, $24, $24 ;cloud right
  2219.   .db $24, $24, $39, $24 ;cloud bottom left
  2220.   .db $3a, $24, $3b, $24 ;cloud bottom middle
  2221.   .db $3c, $24, $24, $24 ;cloud bottom right
  2222.   .db $41, $26, $41, $26 ;water/lava top
  2223.   .db $26, $26, $26, $26 ;water/lava
  2224.   .db $b0, $b1, $b2, $b3 ;cloud level terrain
  2225.   .db $77, $79, $77, $79 ;bowser's bridge
  2226.      
  2227. Palette3_MTiles:
  2228.   .db $53, $55, $54, $56 ;question block (coin)
  2229.   .db $53, $55, $54, $56 ;question block (power-up)
  2230.   .db $a5, $a7, $a6, $a8 ;coin
  2231.   .db $c2, $c4, $c3, $c5 ;underwater coin
  2232.   .db $57, $59, $58, $5a ;empty block
  2233.   .db $7b, $7d, $7c, $7e ;axe
  2234.  
  2235. ;-------------------------------------------------------------------------------------
  2236. ;VRAM BUFFER DATA FOR LOCATIONS IN PRG-ROM
  2237.  
  2238. WaterPaletteData:
  2239.   .db $3f, $00, $20
  2240.   .db $0f, $15, $12, $25  
  2241.   .db $0f, $3a, $1a, $0f
  2242.   .db $0f, $30, $12, $0f
  2243.   .db $0f, $27, $12, $0f
  2244.   .db $22, $16, $27, $18
  2245.   .db $0f, $10, $30, $27
  2246.   .db $0f, $16, $30, $27
  2247.   .db $0f, $0f, $30, $10
  2248.   .db $00
  2249.  
  2250. GroundPaletteData:
  2251.   .db $3f, $00, $20
  2252.   .db $0f, $29, $1a, $0f
  2253.   .db $0f, $36, $17, $0f
  2254.   .db $0f, $30, $21, $0f
  2255.   .db $0f, $27, $17, $0f
  2256.   .db $0f, $16, $27, $18
  2257.   .db $0f, $1a, $30, $27
  2258.   .db $0f, $16, $30, $27
  2259.   .db $0f, $0f, $36, $17
  2260.   .db $00
  2261.  
  2262. UndergroundPaletteData:
  2263.   .db $3f, $00, $20
  2264.   .db $0f, $29, $1a, $09
  2265.   .db $0f, $3c, $1c, $0f
  2266.   .db $0f, $30, $21, $1c
  2267.   .db $0f, $27, $17, $1c
  2268.   .db $0f, $16, $27, $18
  2269.   .db $0f, $1c, $36, $17
  2270.   .db $0f, $16, $30, $27
  2271.   .db $0f, $0c, $3c, $1c
  2272.   .db $00
  2273.  
  2274. CastlePaletteData:
  2275.   .db $3f, $00, $20
  2276.   .db $0f, $30, $10, $00
  2277.   .db $0f, $30, $10, $00
  2278.   .db $0f, $30, $16, $00
  2279.   .db $0f, $27, $17, $00
  2280.   .db $0f, $16, $27, $18
  2281.   .db $0f, $1c, $36, $17
  2282.   .db $0f, $16, $30, $27
  2283.   .db $0f, $00, $30, $10
  2284.   .db $00
  2285.  
  2286. DaySnowPaletteData:
  2287.   .db $3f, $00, $04
  2288.   .db $22, $30, $00, $10
  2289.   .db $00
  2290.  
  2291. NightSnowPaletteData:
  2292.   .db $3f, $00, $04
  2293.   .db $0f, $30, $00, $10
  2294.   .db $00
  2295.  
  2296. MushroomPaletteData:
  2297.   .db $3f, $00, $04
  2298.   .db $22, $27, $16, $0f
  2299.   .db $00
  2300.  
  2301. BowserPaletteData:
  2302.   .db $3f, $14, $04
  2303.   .db $0f, $1a, $30, $27
  2304.   .db $00
  2305.  
  2306. MarioThanksMessage:
  2307. ;"THANK YOU MARIO!"
  2308.   .db $25, $48, $10
  2309.   .db $1d, $11, $0a, $17, $14, $24
  2310.   .db $22, $18, $1e, $24
  2311.   .db $16, $0a, $1b, $12, $18, $2b
  2312.   .db $00
  2313.  
  2314. LuigiThanksMessage:
  2315. ;"THANK YOU LUIGI!"
  2316.   .db $25, $48, $10
  2317.   .db $1d, $11, $0a, $17, $14, $24
  2318.   .db $22, $18, $1e, $24
  2319.   .db $15, $1e, $12, $10, $12, $2b
  2320.   .db $00
  2321.  
  2322. MushroomRetainerSaved:
  2323. ;"BUT OUR PRINCESS IS IN"
  2324.   .db $25, $c5, $16
  2325.   .db $0b, $1e, $1d, $24, $18, $1e, $1b, $24
  2326.   .db $19, $1b, $12, $17, $0c, $0e, $1c, $1c, $24
  2327.   .db $12, $1c, $24, $12, $17
  2328. ;"ANOTHER CASTLE!"
  2329.   .db $26, $05, $0f
  2330.   .db $0a, $17, $18, $1d, $11, $0e, $1b, $24
  2331.   .db $0c, $0a, $1c, $1d, $15, $0e, $2b, $00
  2332.  
  2333. PrincessSaved1:
  2334. ;"YOUR QUEST IS OVER."
  2335.   .db $25, $a7, $13
  2336.   .db $22, $18, $1e, $1b, $24
  2337.   .db $1a, $1e, $0e, $1c, $1d, $24
  2338.   .db $12, $1c, $24, $18, $1f, $0e, $1b, $af
  2339.   .db $00
  2340.  
  2341. PrincessSaved2:
  2342. ;"WE PRESENT YOU A NEW QUEST."
  2343.   .db $25, $e3, $1b
  2344.   .db $20, $0e, $24
  2345.   .db $19, $1b, $0e, $1c, $0e, $17, $1d, $24
  2346.   .db $22, $18, $1e, $24, $0a, $24, $17, $0e, $20, $24
  2347.   .db $1a, $1e, $0e, $1c, $1d, $af
  2348.   .db $00
  2349.  
  2350. WorldSelectMessage1:
  2351. ;"PUSH BUTTON B"
  2352.   .db $26, $4a, $0d
  2353.   .db $19, $1e, $1c, $11, $24
  2354.   .db $0b, $1e, $1d, $1d, $18, $17, $24, $0b
  2355.   .db $00
  2356.  
  2357. WorldSelectMessage2:
  2358. ;"TO SELECT A WORLD"
  2359.   .db $26, $88, $11
  2360.   .db $1d, $18, $24, $1c, $0e, $15, $0e, $0c, $1d, $24
  2361.   .db $0a, $24, $20, $18, $1b, $15, $0d
  2362.   .db $00
  2363.  
  2364. ;-------------------------------------------------------------------------------------
  2365. ;$04 - address low to jump address
  2366. ;$05 - address high to jump address
  2367. ;$06 - jump address low
  2368. ;$07 - jump address high
  2369.  
  2370. JumpEngine:
  2371.        asl          ;shift bit from contents of A
  2372.        tay
  2373.        pla          ;pull saved return address from stack
  2374.        sta $04      ;save to indirect
  2375.        pla
  2376.        sta $05
  2377.        iny
  2378.        lda ($04),y  ;load pointer from indirect
  2379.        sta $06      ;note that if an RTS is performed in next routine
  2380.        iny          ;it will return to the execution before the sub
  2381.        lda ($04),y  ;that called this routine
  2382.        sta $07
  2383.        jmp ($06)    ;jump to the address we loaded
  2384.  
  2385. ;-------------------------------------------------------------------------------------
  2386.  
  2387. InitializeNameTables:
  2388.               lda PPU_STATUS            ;reset flip-flop
  2389.               lda Mirror_PPU_CTRL_REG1  ;load mirror of ppu reg $2000
  2390.               ora #%00010000            ;set sprites for first 4k and background for second 4k
  2391.               and #%11110000            ;clear rest of lower nybble, leave higher alone
  2392.               jsr WritePPUReg1
  2393.               lda #$24                  ;set vram address to start of name table 1
  2394.               jsr WriteNTAddr
  2395.               lda #$20                  ;and then set it to name table 0
  2396. WriteNTAddr:  sta PPU_ADDRESS
  2397.               lda #$00
  2398.               sta PPU_ADDRESS
  2399.               ldx #$04                  ;clear name table with blank tile #24
  2400.               ldy #$c0
  2401.               lda #$24
  2402. InitNTLoop:   sta PPU_DATA              ;count out exactly 768 tiles
  2403.               dey
  2404.               bne InitNTLoop
  2405.               dex
  2406.               bne InitNTLoop
  2407.               ldy #64                   ;now to clear the attribute table (with zero this time)
  2408.               txa
  2409.               sta VRAM_Buffer1_Offset   ;init vram buffer 1 offset
  2410.               sta VRAM_Buffer1          ;init vram buffer 1
  2411. InitATLoop:   sta PPU_DATA
  2412.               dey
  2413.               bne InitATLoop
  2414.               sta HorizontalScroll      ;reset scroll variables
  2415.               sta VerticalScroll
  2416.               jmp InitScroll            ;initialize scroll registers to zero
  2417.  
  2418. ;-------------------------------------------------------------------------------------
  2419. ;$00 - temp joypad bit
  2420.  
  2421. ReadJoypads:
  2422.               lda #$01               ;reset and clear strobe of joypad ports
  2423.               sta JOYPAD_PORT
  2424.               lsr
  2425.               tax                    ;start with joypad 1's port
  2426.               sta JOYPAD_PORT
  2427.               jsr ReadPortBits
  2428.               inx                    ;increment for joypad 2's port
  2429. ReadPortBits: ldy #$08
  2430. PortLoop:     pha                    ;push previous bit onto stack
  2431.               lda JOYPAD_PORT,x      ;read current bit on joypad port
  2432.               sta $00                ;check d1 and d0 of port output
  2433.               lsr                    ;this is necessary on the old
  2434.               ora $00                ;famicom systems in japan
  2435.               lsr
  2436.               pla                    ;read bits from stack
  2437.               rol                    ;rotate bit from carry flag
  2438.               dey
  2439.               bne PortLoop           ;count down bits left
  2440.               sta SavedJoypadBits,x  ;save controller status here always
  2441.               pha
  2442.               and #%00110000         ;check for select or start
  2443.               and JoypadBitMask,x    ;if neither saved state nor current state
  2444.               beq Save8Bits          ;have any of these two set, branch
  2445.               pla
  2446.               and #%11001111         ;otherwise store without select
  2447.               sta SavedJoypadBits,x  ;or start bits and leave
  2448.               rts
  2449. Save8Bits:    pla
  2450.               sta JoypadBitMask,x    ;save with all bits in another place and leave
  2451.               rts
  2452.  
  2453. ;-------------------------------------------------------------------------------------
  2454. ;$00 - vram buffer address table low
  2455. ;$01 - vram buffer address table high
  2456.  
  2457. WriteBufferToScreen:
  2458.                sta PPU_ADDRESS           ;store high byte of vram address
  2459.                iny
  2460.                lda ($00),y               ;load next byte (second)
  2461.                sta PPU_ADDRESS           ;store low byte of vram address
  2462.                iny
  2463.                lda ($00),y               ;load next byte (third)
  2464.                asl                       ;shift to left and save in stack
  2465.                pha
  2466.                lda Mirror_PPU_CTRL_REG1  ;load mirror of $2000,
  2467.                ora #%00000100            ;set ppu to increment by 32 by default
  2468.                bcs SetupWrites           ;if d7 of third byte was clear, ppu will
  2469.                and #%11111011            ;only increment by 1
  2470. SetupWrites:   jsr WritePPUReg1          ;write to register
  2471.                pla                       ;pull from stack and shift to left again
  2472.                asl
  2473.                bcc GetLength             ;if d6 of third byte was clear, do not repeat byte
  2474.                ora #%00000010            ;otherwise set d1 and increment Y
  2475.                iny
  2476. GetLength:     lsr                       ;shift back to the right to get proper length
  2477.                lsr                       ;note that d1 will now be in carry
  2478.                tax
  2479. OutputToVRAM:  bcs RepeatByte            ;if carry set, repeat loading the same byte
  2480.                iny                       ;otherwise increment Y to load next byte
  2481. RepeatByte:    lda ($00),y               ;load more data from buffer and write to vram
  2482.                sta PPU_DATA
  2483.                dex                       ;done writing?
  2484.                bne OutputToVRAM
  2485.                sec          
  2486.                tya
  2487.                adc $00                   ;add end length plus one to the indirect at $00
  2488.                sta $00                   ;to allow this routine to read another set of updates
  2489.                lda #$00
  2490.                adc $01
  2491.                sta $01
  2492.                lda #$3f                  ;sets vram address to $3f00
  2493.                sta PPU_ADDRESS
  2494.                lda #$00
  2495.                sta PPU_ADDRESS
  2496.                sta PPU_ADDRESS           ;then reinitializes it for some reason
  2497.                sta PPU_ADDRESS
  2498. UpdateScreen:  ldx PPU_STATUS            ;reset flip-flop
  2499.                ldy #$00                  ;load first byte from indirect as a pointer
  2500.                lda ($00),y  
  2501.                bne WriteBufferToScreen   ;if byte is zero we have no further updates to make here
  2502. InitScroll:    sta PPU_SCROLL_REG        ;store contents of A into scroll registers
  2503.                sta PPU_SCROLL_REG        ;and end whatever subroutine led us here
  2504.                rts
  2505.  
  2506. ;-------------------------------------------------------------------------------------
  2507.  
  2508. WritePPUReg1:
  2509.                sta PPU_CTRL_REG1         ;write contents of A to PPU register 1
  2510.                sta Mirror_PPU_CTRL_REG1  ;and its mirror
  2511.                rts
  2512.  
  2513. ;-------------------------------------------------------------------------------------
  2514. ;$00 - used to store status bar nybbles
  2515. ;$02 - used as temp vram offset
  2516. ;$03 - used to store length of status bar number
  2517.  
  2518. ;status bar name table offset and length data
  2519. StatusBarData:
  2520.       .db $f0, $06 ; top score display on title screen
  2521.       .db $62, $06 ; player score
  2522.       .db $62, $06
  2523.       .db $6d, $02 ; coin tally
  2524.       .db $6d, $02
  2525.       .db $7a, $03 ; game timer
  2526.  
  2527. StatusBarOffset:
  2528.       .db $06, $0c, $12, $18, $1e, $24
  2529.  
  2530. PrintStatusBarNumbers:
  2531.       sta $00            ;store player-specific offset
  2532.       jsr OutputNumbers  ;use first nybble to print the coin display
  2533.       lda $00            ;move high nybble to low
  2534.       lsr                ;and print to score display
  2535.       lsr
  2536.       lsr
  2537.       lsr
  2538.  
  2539. OutputNumbers:
  2540.              clc                      ;add 1 to low nybble
  2541.              adc #$01
  2542.              and #%00001111           ;mask out high nybble
  2543.              cmp #$06
  2544.              bcs ExitOutputN
  2545.              pha                      ;save incremented value to stack for now and
  2546.              asl                      ;shift to left and use as offset
  2547.              tay
  2548.              ldx VRAM_Buffer1_Offset  ;get current buffer pointer
  2549.              lda #$20                 ;put at top of screen by default
  2550.              cpy #$00                 ;are we writing top score on title screen?
  2551.              bne SetupNums
  2552.              lda #$22                 ;if so, put further down on the screen
  2553. SetupNums:   sta VRAM_Buffer1,x
  2554.              lda StatusBarData,y      ;write low vram address and length of thing
  2555.              sta VRAM_Buffer1+1,x     ;we're printing to the buffer
  2556.              lda StatusBarData+1,y
  2557.              sta VRAM_Buffer1+2,x
  2558.              sta $03                  ;save length byte in counter
  2559.              stx $02                  ;and buffer pointer elsewhere for now
  2560.              pla                      ;pull original incremented value from stack
  2561.              tax
  2562.              lda StatusBarOffset,x    ;load offset to value we want to write
  2563.              sec
  2564.              sbc StatusBarData+1,y    ;subtract from length byte we read before
  2565.              tay                      ;use value as offset to display digits
  2566.              ldx $02
  2567. DigitPLoop:  lda DisplayDigits,y      ;write digits to the buffer
  2568.              sta VRAM_Buffer1+3,x    
  2569.              inx
  2570.              iny
  2571.              dec $03                  ;do this until all the digits are written
  2572.              bne DigitPLoop
  2573.              lda #$00                 ;put null terminator at end
  2574.              sta VRAM_Buffer1+3,x
  2575.              inx                      ;increment buffer pointer by 3
  2576.              inx
  2577.              inx
  2578.              stx VRAM_Buffer1_Offset  ;store it in case we want to use it again
  2579. ExitOutputN: rts
  2580.  
  2581. ;-------------------------------------------------------------------------------------
  2582.  
  2583. DigitsMathRoutine:
  2584.             lda OperMode              ;check mode of operation
  2585.             cmp #TitleScreenModeValue
  2586.             beq EraseDMods            ;if in title screen mode, branch to lock score
  2587.             ldx #$05
  2588. AddModLoop: lda DigitModifier,x       ;load digit amount to increment
  2589.             clc
  2590.             adc DisplayDigits,y       ;add to current digit
  2591.             bmi BorrowOne             ;if result is a negative number, branch to subtract
  2592.             cmp #10
  2593.             bcs CarryOne              ;if digit greater than $09, branch to add
  2594. StoreNewD:  sta DisplayDigits,y       ;store as new score or game timer digit
  2595.             dey                       ;move onto next digits in score or game timer
  2596.             dex                       ;and digit amounts to increment
  2597.             bpl AddModLoop            ;loop back if we're not done yet
  2598. EraseDMods: lda #$00                  ;store zero here
  2599.             ldx #$06                  ;start with the last digit
  2600. EraseMLoop: sta DigitModifier-1,x     ;initialize the digit amounts to increment
  2601.             dex
  2602.             bpl EraseMLoop            ;do this until they're all reset, then leave
  2603.             rts
  2604. BorrowOne:  dec DigitModifier-1,x     ;decrement the previous digit, then put $09 in
  2605.             lda #$09                  ;the game timer digit we're currently on to "borrow
  2606.             bne StoreNewD             ;the one", then do an unconditional branch back
  2607. CarryOne:   sec                       ;subtract ten from our digit to make it a
  2608.             sbc #10                   ;proper BCD number, then increment the digit
  2609.             inc DigitModifier-1,x     ;preceding current digit to "carry the one" properly
  2610.             jmp StoreNewD             ;go back to just after we branched here
  2611.  
  2612. ;-------------------------------------------------------------------------------------
  2613.  
  2614. UpdateTopScore:
  2615.       ldx #$05          ;start with mario's score
  2616.       jsr TopScoreCheck
  2617.       ldx #$0b          ;now do luigi's score
  2618.  
  2619. TopScoreCheck:
  2620.               ldy #$05                 ;start with the lowest digit
  2621.               sec          
  2622. GetScoreDiff: lda PlayerScoreDisplay,x ;subtract each player digit from each high score digit
  2623.               sbc TopScoreDisplay,y    ;from lowest to highest, if any top score digit exceeds
  2624.               dex                      ;any player digit, borrow will be set until a subsequent
  2625.               dey                      ;subtraction clears it (player digit is higher than top)
  2626.               bpl GetScoreDiff      
  2627.               bcc NoTopSc              ;check to see if borrow is still set, if so, no new high score
  2628.               inx                      ;increment X and Y once to the start of the score
  2629.               iny
  2630. CopyScore:    lda PlayerScoreDisplay,x ;store player's score digits into high score memory area
  2631.               sta TopScoreDisplay,y
  2632.               inx
  2633.               iny
  2634.               cpy #$06                 ;do this until we have stored them all
  2635.               bcc CopyScore
  2636. NoTopSc:      rts
  2637.  
  2638. ;-------------------------------------------------------------------------------------
  2639.  
  2640. DefaultSprOffsets:
  2641.       .db $04, $30, $48, $60, $78, $90, $a8, $c0
  2642.       .db $d8, $e8, $24, $f8, $fc, $28, $2c
  2643.  
  2644. Sprite0Data:
  2645.       .db $18, $ff, $23, $58
  2646.  
  2647. ;-------------------------------------------------------------------------------------
  2648.  
  2649. InitializeGame:
  2650.              ldy #$6f              ;clear all memory as in initialization procedure,
  2651.              jsr InitializeMemory  ;but this time, clear only as far as $076f
  2652.              ldy #$1f
  2653. ClrSndLoop:  sta SoundMemory,y     ;clear out memory used
  2654.              dey                   ;by the sound engines
  2655.              bpl ClrSndLoop
  2656.              lda #$18              ;set demo timer
  2657.              sta DemoTimer
  2658.              jsr LoadAreaPointer
  2659.  
  2660. InitializeArea:
  2661.                ldy #$4b                 ;clear all memory again, only as far as $074b
  2662.                jsr InitializeMemory     ;this is only necessary if branching from
  2663.                ldx #$21
  2664.                lda #$00
  2665. ClrTimersLoop: sta Timers,x             ;clear out memory between
  2666.                dex                      ;$0780 and $07a1
  2667.                bpl ClrTimersLoop
  2668.                lda HalfwayPage
  2669.                ldy AltEntranceControl   ;if AltEntranceControl not set, use halfway page, if any found
  2670.                beq StartPage
  2671.                lda EntrancePage         ;otherwise use saved entry page number here
  2672. StartPage:     sta ScreenLeft_PageLoc   ;set as value here
  2673.                sta CurrentPageLoc       ;also set as current page
  2674.                sta BackloadingFlag      ;set flag here if halfway page or saved entry page number found
  2675.                jsr GetScreenPosition    ;get pixel coordinates for screen borders
  2676.                ldy #$20                 ;if on odd numbered page, use $2480 as start of rendering
  2677.                and #%00000001           ;otherwise use $2080, this address used later as name table
  2678.                beq SetInitNTHigh        ;address for rendering of game area
  2679.                ldy #$24
  2680. SetInitNTHigh: sty CurrentNTAddr_High   ;store name table address
  2681.                ldy #$80
  2682.                sty CurrentNTAddr_Low
  2683.                asl                      ;store LSB of page number in high nybble
  2684.                asl                      ;of block buffer column position
  2685.                asl
  2686.                asl
  2687.                sta BlockBufferColumnPos
  2688.                dec AreaObjectLength     ;set area object lengths for all empty
  2689.                dec AreaObjectLength+1
  2690.                dec AreaObjectLength+2
  2691.                lda #$0b                 ;set value for renderer to update 12 column sets
  2692.                sta ColumnSets           ;12 column sets = 24 metatile columns = 1 1/2 screens
  2693.                jsr GetAreaDataAddrs     ;get enemy and level addresses and load header
  2694.                lda PrimaryHardMode      ;check to see if primary hard mode has been activated
  2695.                bne SetSecHard           ;if so, activate the secondary no matter where we're at
  2696.                lda WorldNumber          ;otherwise check world number
  2697.                cmp #World5              ;if less than 5, do not activate secondary
  2698.                bcc CheckHalfway
  2699.                bne SetSecHard           ;if not equal to, then world > 5, thus activate
  2700.                lda LevelNumber          ;otherwise, world 5, so check level number
  2701.                cmp #Level3              ;if 1 or 2, do not set secondary hard mode flag
  2702.                bcc CheckHalfway
  2703. SetSecHard:    inc SecondaryHardMode    ;set secondary hard mode flag for areas 5-3 and beyond
  2704. CheckHalfway:  lda HalfwayPage
  2705.                beq DoneInitArea
  2706.                lda #$02                 ;if halfway page set, overwrite start position from header
  2707.                sta PlayerEntranceCtrl
  2708. DoneInitArea:  lda #Silence             ;silence music
  2709.                sta AreaMusicQueue
  2710.                lda #$01                 ;disable screen output
  2711.                sta DisableScreenFlag
  2712.                inc OperMode_Task        ;increment one of the modes
  2713.                rts
  2714.  
  2715. ;-------------------------------------------------------------------------------------
  2716.  
  2717. PrimaryGameSetup:
  2718.       lda #$01
  2719.       sta FetchNewGameTimerFlag   ;set flag to load game timer from header
  2720.       sta PlayerSize              ;set player's size to small
  2721.       lda #$02
  2722.       sta NumberofLives           ;give each player three lives
  2723.       sta OffScr_NumberofLives
  2724.  
  2725. SecondaryGameSetup:
  2726.              lda #$00
  2727.              sta DisableScreenFlag     ;enable screen output
  2728.              tay
  2729. ClearVRLoop: sta VRAM_Buffer1-1,y      ;clear buffer at $0300-$03ff
  2730.              iny
  2731.              bne ClearVRLoop
  2732.              sta GameTimerExpiredFlag  ;clear game timer exp flag
  2733.              sta DisableIntermediate   ;clear skip lives display flag
  2734.              sta BackloadingFlag       ;clear value here
  2735.              lda #$ff
  2736.              sta BalPlatformAlignment  ;initialize balance platform assignment flag
  2737.              lda ScreenLeft_PageLoc    ;get left side page location
  2738.              lsr Mirror_PPU_CTRL_REG1  ;shift LSB of ppu register #1 mirror out
  2739.              and #$01                  ;mask out all but LSB of page location
  2740.              ror                       ;rotate LSB of page location into carry then onto mirror
  2741.              rol Mirror_PPU_CTRL_REG1  ;this is to set the proper PPU name table
  2742.              jsr GetAreaMusic          ;load proper music into queue
  2743.              lda #$38                  ;load sprite shuffle amounts to be used later
  2744.              sta SprShuffleAmt+2
  2745.              lda #$48
  2746.              sta SprShuffleAmt+1
  2747.              lda #$58
  2748.              sta SprShuffleAmt
  2749.              ldx #$0e                  ;load default OAM offsets into $06e4-$06f2
  2750. ShufAmtLoop: lda DefaultSprOffsets,x
  2751.              sta SprDataOffset,x
  2752.              dex                       ;do this until they're all set
  2753.              bpl ShufAmtLoop
  2754.              ldy #$03                  ;set up sprite #0
  2755. ISpr0Loop:   lda Sprite0Data,y
  2756.              sta Sprite_Data,y
  2757.              dey
  2758.              bpl ISpr0Loop
  2759.              jsr DoNothing2            ;these jsrs doesn't do anything useful
  2760.              jsr DoNothing1
  2761.              inc Sprite0HitDetectFlag  ;set sprite #0 check flag
  2762.              inc OperMode_Task         ;increment to next task
  2763.              rts
  2764.  
  2765. ;-------------------------------------------------------------------------------------
  2766.  
  2767. ;$06 - RAM address low
  2768. ;$07 - RAM address high
  2769.  
  2770. InitializeMemory:
  2771.               ldx #$07          ;set initial high byte to $0700-$07ff
  2772.               lda #$00          ;set initial low byte to start of page (at $00 of page)
  2773.               sta $06
  2774. InitPageLoop: stx $07
  2775. InitByteLoop: cpx #$01          ;check to see if we're on the stack ($0100-$01ff)
  2776.               bne InitByte      ;if not, go ahead anyway
  2777.               cpy #$60          ;otherwise, check to see if we're at $0160-$01ff
  2778.               bcs SkipByte      ;if so, skip write
  2779. InitByte:     sta ($06),y       ;otherwise, initialize byte with current low byte in Y
  2780. SkipByte:     dey
  2781.               cpy #$ff          ;do this until all bytes in page have been erased
  2782.               bne InitByteLoop
  2783.               dex               ;go onto the next page
  2784.               bpl InitPageLoop  ;do this until all pages of memory have been erased
  2785.               rts
  2786.  
  2787. ;-------------------------------------------------------------------------------------
  2788.  
  2789. MusicSelectData:
  2790.       .db WaterMusic, GroundMusic, UndergroundMusic, CastleMusic
  2791.       .db CloudMusic, PipeIntroMusic
  2792.  
  2793. GetAreaMusic:
  2794.              lda OperMode           ;if in title screen mode, leave
  2795.              beq ExitGetM
  2796.              lda AltEntranceControl ;check for specific alternate mode of entry
  2797.              cmp #$02               ;if found, branch without checking starting position
  2798.              beq ChkAreaType        ;from area object data header
  2799.              ldy #$05               ;select music for pipe intro scene by default
  2800.              lda PlayerEntranceCtrl ;check value from level header for certain values
  2801.              cmp #$06
  2802.              beq StoreMusic         ;load music for pipe intro scene if header
  2803.              cmp #$07               ;start position either value $06 or $07
  2804.              beq StoreMusic
  2805. ChkAreaType: ldy AreaType           ;load area type as offset for music bit
  2806.              lda CloudTypeOverride
  2807.              beq StoreMusic         ;check for cloud type override
  2808.              ldy #$04               ;select music for cloud type level if found
  2809. StoreMusic:  lda MusicSelectData,y  ;otherwise select appropriate music for level type
  2810.              sta AreaMusicQueue     ;store in queue and leave
  2811. ExitGetM:    rts
  2812.  
  2813. ;-------------------------------------------------------------------------------------
  2814.  
  2815. PlayerStarting_X_Pos:
  2816.       .db $28, $18
  2817.       .db $38, $28
  2818.  
  2819. AltYPosOffset:
  2820.       .db $08, $00
  2821.  
  2822. PlayerStarting_Y_Pos:
  2823.       .db $00, $20, $b0, $50, $00, $00, $b0, $b0
  2824.       .db $f0
  2825.  
  2826. PlayerBGPriorityData:
  2827.       .db $00, $20, $00, $00, $00, $00, $00, $00
  2828.  
  2829. GameTimerData:
  2830.       .db $20 ;dummy byte, used as part of bg priority data
  2831.       .db $04, $03, $02
  2832.  
  2833. Entrance_GameTimerSetup:
  2834.           lda ScreenLeft_PageLoc      ;set current page for area objects
  2835.           sta Player_PageLoc          ;as page location for player
  2836.           lda #$28                    ;store value here
  2837.           sta VerticalForceDown       ;for fractional movement downwards if necessary
  2838.           lda #$01                    ;set high byte of player position and
  2839.           sta PlayerFacingDir         ;set facing direction so that player faces right
  2840.           sta Player_Y_HighPos
  2841.           lda #$00                    ;set player state to on the ground by default
  2842.           sta Player_State
  2843.           dec Player_CollisionBits    ;initialize player's collision bits
  2844.           ldy #$00                    ;initialize halfway page
  2845.           sty HalfwayPage      
  2846.           lda AreaType                ;check area type
  2847.           bne ChkStPos                ;if water type, set swimming flag, otherwise do not set
  2848.           iny
  2849. ChkStPos: sty SwimmingFlag
  2850.           ldx PlayerEntranceCtrl      ;get starting position loaded from header
  2851.           ldy AltEntranceControl      ;check alternate mode of entry flag for 0 or 1
  2852.           beq SetStPos
  2853.           cpy #$01
  2854.           beq SetStPos
  2855.           ldx AltYPosOffset-2,y       ;if not 0 or 1, override $0710 with new offset in X
  2856. SetStPos: lda PlayerStarting_X_Pos,y  ;load appropriate horizontal position
  2857.           sta Player_X_Position       ;and vertical positions for the player, using
  2858.           lda PlayerStarting_Y_Pos,x  ;AltEntranceControl as offset for horizontal and either $0710
  2859.           sta Player_Y_Position       ;or value that overwrote $0710 as offset for vertical
  2860.           lda PlayerBGPriorityData,x
  2861.           sta Player_SprAttrib        ;set player sprite attributes using offset in X
  2862.           jsr GetPlayerColors         ;get appropriate player palette
  2863.           ldy GameTimerSetting        ;get timer control value from header
  2864.           beq ChkOverR                ;if set to zero, branch (do not use dummy byte for this)
  2865.           lda FetchNewGameTimerFlag   ;do we need to set the game timer? if not, use
  2866.           beq ChkOverR                ;old game timer setting
  2867.           lda GameTimerData,y         ;if game timer is set and game timer flag is also set,
  2868.           sta GameTimerDisplay        ;use value of game timer control for first digit of game timer
  2869.           lda #$01
  2870.           sta GameTimerDisplay+2      ;set last digit of game timer to 1
  2871.           lsr
  2872.           sta GameTimerDisplay+1      ;set second digit of game timer
  2873.           sta FetchNewGameTimerFlag   ;clear flag for game timer reset
  2874.           sta StarInvincibleTimer     ;clear star mario timer
  2875. ChkOverR: ldy JoypadOverride          ;if controller bits not set, branch to skip this part
  2876.           beq ChkSwimE
  2877.           lda #$03                    ;set player state to climbing
  2878.           sta Player_State
  2879.           ldx #$00                    ;set offset for first slot, for block object
  2880.           jsr InitBlock_XY_Pos
  2881.           lda #$f0                    ;set vertical coordinate for block object
  2882.           sta Block_Y_Position
  2883.           ldx #$05                    ;set offset in X for last enemy object buffer slot
  2884.           ldy #$00                    ;set offset in Y for object coordinates used earlier
  2885.           jsr Setup_Vine              ;do a sub to grow vine
  2886. ChkSwimE: ldy AreaType                ;if level not water-type,
  2887.           bne SetPESub                ;skip this subroutine
  2888.           jsr SetupBubble             ;otherwise, execute sub to set up air bubbles
  2889. SetPESub: lda #$07                    ;set to run player entrance subroutine
  2890.           sta GameEngineSubroutine    ;on the next frame of game engine
  2891.           rts
  2892.  
  2893. ;-------------------------------------------------------------------------------------
  2894.  
  2895. ;page numbers are in order from -1 to -4
  2896. HalfwayPageNybbles:
  2897.       .db $56, $40
  2898.       .db $65, $70
  2899.       .db $66, $40
  2900.       .db $66, $40
  2901.       .db $66, $40
  2902.       .db $66, $60
  2903.       .db $65, $70
  2904.       .db $00, $00
  2905.  
  2906. PlayerLoseLife:
  2907.              inc DisableScreenFlag    ;disable screen and sprite 0 check
  2908.              lda #$00
  2909.              sta Sprite0HitDetectFlag
  2910.              lda #Silence             ;silence music
  2911.              sta EventMusicQueue
  2912.              dec NumberofLives        ;take one life from player
  2913.              bpl StillInGame          ;if player still has lives, branch
  2914.              lda #$00
  2915.              sta OperMode_Task        ;initialize mode task,
  2916.              lda #GameOverModeValue   ;switch to game over mode
  2917.              sta OperMode             ;and leave
  2918.              rts
  2919. StillInGame: lda WorldNumber          ;multiply world number by 2 and use
  2920.              asl                      ;as offset
  2921.              tax
  2922.              lda LevelNumber          ;if in area -3 or -4, increment
  2923.              and #$02                 ;offset by one byte, otherwise
  2924.              beq GetHalfway           ;leave offset alone
  2925.              inx
  2926. GetHalfway:  ldy HalfwayPageNybbles,x ;get halfway page number with offset
  2927.              lda LevelNumber          ;check area number's LSB
  2928.              lsr
  2929.              tya                      ;if in area -2 or -4, use lower nybble
  2930.              bcs MaskHPNyb
  2931.              lsr                      ;move higher nybble to lower if area
  2932.              lsr                      ;number is -1 or -3
  2933.              lsr
  2934.              lsr
  2935. MaskHPNyb:   and #%00001111           ;mask out all but lower nybble
  2936.              cmp ScreenLeft_PageLoc
  2937.              beq SetHalfway           ;left side of screen must be at the halfway page,
  2938.              bcc SetHalfway           ;otherwise player must start at the
  2939.              lda #$00                 ;beginning of the level
  2940. SetHalfway:  sta HalfwayPage          ;store as halfway page for player
  2941.              jsr TransposePlayers     ;switch players around if 2-player game
  2942.              jmp ContinueGame         ;continue the game
  2943.  
  2944. ;-------------------------------------------------------------------------------------
  2945.  
  2946. GameOverMode:
  2947.       lda OperMode_Task
  2948.       jsr JumpEngine
  2949.      
  2950.       .dw SetupGameOver
  2951.       .dw ScreenRoutines
  2952.       .dw RunGameOver
  2953.  
  2954. ;-------------------------------------------------------------------------------------
  2955.  
  2956. SetupGameOver:
  2957.       lda #$00                  ;reset screen routine task control for title screen, game,
  2958.       sta ScreenRoutineTask     ;and game over modes
  2959.       sta Sprite0HitDetectFlag  ;disable sprite 0 check
  2960.       lda #GameOverMusic
  2961.       sta EventMusicQueue       ;put game over music in secondary queue
  2962.       inc DisableScreenFlag     ;disable screen output
  2963.       inc OperMode_Task         ;set secondary mode to 1
  2964.       rts
  2965.  
  2966. ;-------------------------------------------------------------------------------------
  2967.  
  2968. RunGameOver:
  2969.       lda #$00              ;reenable screen
  2970.       sta DisableScreenFlag
  2971.       lda SavedJoypad1Bits  ;check controller for start pressed
  2972.       and #Start_Button
  2973.       bne TerminateGame
  2974.       lda ScreenTimer       ;if not pressed, wait for
  2975.       bne GameIsOn          ;screen timer to expire
  2976. TerminateGame:
  2977.       lda #Silence          ;silence music
  2978.       sta EventMusicQueue
  2979.       jsr TransposePlayers  ;check if other player can keep
  2980.       bcc ContinueGame      ;going, and do so if possible
  2981.       lda WorldNumber       ;otherwise put world number of current
  2982.       sta ContinueWorld     ;player into secret continue function variable
  2983.       lda #$00
  2984.       asl                   ;residual ASL instruction
  2985.       sta OperMode_Task     ;reset all modes to title screen and
  2986.       sta ScreenTimer       ;leave
  2987.       sta OperMode
  2988.       rts
  2989.  
  2990. ContinueGame:
  2991.            jsr LoadAreaPointer       ;update level pointer with
  2992.            lda #$01                  ;actual world and area numbers, then
  2993.            sta PlayerSize            ;reset player's size, status, and
  2994.            inc FetchNewGameTimerFlag ;set game timer flag to reload
  2995.            lda #$00                  ;game timer from header
  2996.            sta TimerControl          ;also set flag for timers to count again
  2997.            sta PlayerStatus
  2998.            sta GameEngineSubroutine  ;reset task for game core
  2999.            sta OperMode_Task         ;set modes and leave
  3000.            lda #$01                  ;if in game over mode, switch back to
  3001.            sta OperMode              ;game mode, because game is still on
  3002. GameIsOn:  rts
  3003.  
  3004. TransposePlayers:
  3005.            sec                       ;set carry flag by default to end game
  3006.            lda NumberOfPlayers       ;if only a 1 player game, leave
  3007.            beq ExTrans
  3008.            lda OffScr_NumberofLives  ;does offscreen player have any lives left?
  3009.            bmi ExTrans               ;branch if not
  3010.            lda CurrentPlayer         ;invert bit to update
  3011.            eor #%00000001            ;which player is on the screen
  3012.            sta CurrentPlayer
  3013.            ldx #$06
  3014. TransLoop: lda OnscreenPlayerInfo,x    ;transpose the information
  3015.            pha                         ;of the onscreen player
  3016.            lda OffscreenPlayerInfo,x   ;with that of the offscreen player
  3017.            sta OnscreenPlayerInfo,x
  3018.            pla
  3019.            sta OffscreenPlayerInfo,x
  3020.            dex
  3021.            bpl TransLoop
  3022.            clc            ;clear carry flag to get game going
  3023. ExTrans:   rts
  3024.  
  3025. ;-------------------------------------------------------------------------------------
  3026.  
  3027. DoNothing1:
  3028.       lda #$ff       ;this is residual code, this value is
  3029.       sta $06c9      ;not used anywhere in the program
  3030. DoNothing2:
  3031.       rts
  3032.  
  3033. ;-------------------------------------------------------------------------------------
  3034.  
  3035. AreaParserTaskHandler:
  3036.               ldy AreaParserTaskNum     ;check number of tasks here
  3037.               bne DoAPTasks             ;if already set, go ahead
  3038.               ldy #$08
  3039.               sty AreaParserTaskNum     ;otherwise, set eight by default
  3040. DoAPTasks:    dey
  3041.               tya
  3042.               jsr AreaParserTasks
  3043.               dec AreaParserTaskNum     ;if all tasks not complete do not
  3044.               bne SkipATRender          ;render attribute table yet
  3045.               jsr RenderAttributeTables
  3046. SkipATRender: rts
  3047.  
  3048. AreaParserTasks:
  3049.       jsr JumpEngine
  3050.  
  3051.       .dw IncrementColumnPos
  3052.       .dw RenderAreaGraphics
  3053.       .dw RenderAreaGraphics
  3054.       .dw AreaParserCore
  3055.       .dw IncrementColumnPos
  3056.       .dw RenderAreaGraphics
  3057.       .dw RenderAreaGraphics
  3058.       .dw AreaParserCore
  3059.  
  3060. ;-------------------------------------------------------------------------------------
  3061.  
  3062. IncrementColumnPos:
  3063.            inc CurrentColumnPos     ;increment column where we're at
  3064.            lda CurrentColumnPos
  3065.            and #%00001111           ;mask out higher nybble
  3066.            bne NoColWrap
  3067.            sta CurrentColumnPos     ;if no bits left set, wrap back to zero (0-f)
  3068.            inc CurrentPageLoc       ;and increment page number where we're at
  3069. NoColWrap: inc BlockBufferColumnPos ;increment column offset where we're at
  3070.            lda BlockBufferColumnPos
  3071.            and #%00011111           ;mask out all but 5 LSB (0-1f)
  3072.            sta BlockBufferColumnPos ;and save
  3073.            rts
  3074.  
  3075. ;-------------------------------------------------------------------------------------
  3076. ;$00 - used as counter, store for low nybble for background, ceiling byte for terrain
  3077. ;$01 - used to store floor byte for terrain
  3078. ;$07 - used to store terrain metatile
  3079. ;$06-$07 - used to store block buffer address
  3080.  
  3081. BSceneDataOffsets:
  3082.       .db $00, $30, $60
  3083.  
  3084. BackSceneryData:
  3085.    .db $93, $00, $00, $11, $12, $12, $13, $00 ;clouds
  3086.    .db $00, $51, $52, $53, $00, $00, $00, $00
  3087.    .db $00, $00, $01, $02, $02, $03, $00, $00
  3088.    .db $00, $00, $00, $00, $91, $92, $93, $00
  3089.    .db $00, $00, $00, $51, $52, $53, $41, $42
  3090.    .db $43, $00, $00, $00, $00, $00, $91, $92
  3091.  
  3092.    .db $97, $87, $88, $89, $99, $00, $00, $00 ;mountains and bushes
  3093.    .db $11, $12, $13, $a4, $a5, $a5, $a5, $a6
  3094.    .db $97, $98, $99, $01, $02, $03, $00, $a4
  3095.    .db $a5, $a6, $00, $11, $12, $12, $12, $13
  3096.    .db $00, $00, $00, $00, $01, $02, $02, $03
  3097.    .db $00, $a4, $a5, $a5, $a6, $00, $00, $00
  3098.  
  3099.    .db $11, $12, $12, $13, $00, $00, $00, $00 ;trees and fences
  3100.    .db $00, $00, $00, $9c, $00, $8b, $aa, $aa
  3101.    .db $aa, $aa, $11, $12, $13, $8b, $00, $9c
  3102.    .db $9c, $00, $00, $01, $02, $03, $11, $12
  3103.    .db $12, $13, $00, $00, $00, $00, $aa, $aa
  3104.    .db $9c, $aa, $00, $8b, $00, $01, $02, $03
  3105.  
  3106. BackSceneryMetatiles:
  3107.    .db $80, $83, $00 ;cloud left
  3108.    .db $81, $84, $00 ;cloud middle
  3109.    .db $82, $85, $00 ;cloud right
  3110.    .db $02, $00, $00 ;bush left
  3111.    .db $03, $00, $00 ;bush middle
  3112.    .db $04, $00, $00 ;bush right
  3113.    .db $00, $05, $06 ;mountain left
  3114.    .db $07, $06, $0a ;mountain middle
  3115.    .db $00, $08, $09 ;mountain right
  3116.    .db $4d, $00, $00 ;fence
  3117.    .db $0d, $0f, $4e ;tall tree
  3118.    .db $0e, $4e, $4e ;short tree
  3119.  
  3120. FSceneDataOffsets:
  3121.       .db $00, $0d, $1a
  3122.  
  3123. ForeSceneryData:
  3124.    .db $86, $87, $87, $87, $87, $87, $87   ;in water
  3125.    .db $87, $87, $87, $87, $69, $69
  3126.  
  3127.    .db $00, $00, $00, $00, $00, $45, $47   ;wall
  3128.    .db $47, $47, $47, $47, $00, $00
  3129.  
  3130.    .db $00, $00, $00, $00, $00, $00, $00   ;over water
  3131.    .db $00, $00, $00, $00, $86, $87
  3132.  
  3133. TerrainMetatiles:
  3134.       .db $69, $54, $52, $62
  3135.  
  3136. TerrainRenderBits:
  3137.       .db %00000000, %00000000 ;no ceiling or floor
  3138.       .db %00000000, %00011000 ;no ceiling, floor 2
  3139.       .db %00000001, %00011000 ;ceiling 1, floor 2
  3140.       .db %00000111, %00011000 ;ceiling 3, floor 2
  3141.       .db %00001111, %00011000 ;ceiling 4, floor 2
  3142.       .db %11111111, %00011000 ;ceiling 8, floor 2
  3143.       .db %00000001, %00011111 ;ceiling 1, floor 5
  3144.       .db %00000111, %00011111 ;ceiling 3, floor 5
  3145.       .db %00001111, %00011111 ;ceiling 4, floor 5
  3146.       .db %10000001, %00011111 ;ceiling 1, floor 6
  3147.       .db %00000001, %00000000 ;ceiling 1, no floor
  3148.       .db %10001111, %00011111 ;ceiling 4, floor 6
  3149.       .db %11110001, %00011111 ;ceiling 1, floor 9
  3150.       .db %11111001, %00011000 ;ceiling 1, middle 5, floor 2
  3151.       .db %11110001, %00011000 ;ceiling 1, middle 4, floor 2
  3152.       .db %11111111, %00011111 ;completely solid top to bottom
  3153.  
  3154. AreaParserCore:
  3155.       lda BackloadingFlag       ;check to see if we are starting right of start
  3156.       beq RenderSceneryTerrain  ;if not, go ahead and render background, foreground and terrain
  3157.       jsr ProcessAreaData       ;otherwise skip ahead and load level data
  3158.  
  3159. RenderSceneryTerrain:
  3160.           ldx #$0c
  3161.           lda #$00
  3162. ClrMTBuf: sta MetatileBuffer,x       ;clear out metatile buffer
  3163.           dex
  3164.           bpl ClrMTBuf
  3165.           ldy BackgroundScenery      ;do we need to render the background scenery?
  3166.           beq RendFore               ;if not, skip to check the foreground
  3167.           lda CurrentPageLoc         ;otherwise check for every third page
  3168. ThirdP:   cmp #$03
  3169.           bmi RendBack               ;if less than three we're there
  3170.           sec
  3171.           sbc #$03                   ;if 3 or more, subtract 3 and
  3172.           bpl ThirdP                 ;do an unconditional branch
  3173. RendBack: asl                        ;move results to higher nybble
  3174.           asl
  3175.           asl
  3176.           asl
  3177.           adc BSceneDataOffsets-1,y  ;add to it offset loaded from here
  3178.           adc CurrentColumnPos       ;add to the result our current column position
  3179.           tax
  3180.           lda BackSceneryData,x      ;load data from sum of offsets
  3181.           beq RendFore               ;if zero, no scenery for that part
  3182.           pha
  3183.           and #$0f                   ;save to stack and clear high nybble
  3184.           sec
  3185.           sbc #$01                   ;subtract one (because low nybble is $01-$0c)
  3186.           sta $00                    ;save low nybble
  3187.           asl                        ;multiply by three (shift to left and add result to old one)
  3188.           adc $00                    ;note that since d7 was nulled, the carry flag is always clear
  3189.           tax                        ;save as offset for background scenery metatile data
  3190.           pla                        ;get high nybble from stack, move low
  3191.           lsr
  3192.           lsr
  3193.           lsr
  3194.           lsr
  3195.           tay                        ;use as second offset (used to determine height)
  3196.           lda #$03                   ;use previously saved memory location for counter
  3197.           sta $00
  3198. SceLoop1: lda BackSceneryMetatiles,x ;load metatile data from offset of (lsb - 1) * 3
  3199.           sta MetatileBuffer,y       ;store into buffer from offset of (msb / 16)
  3200.           inx
  3201.           iny
  3202.           cpy #$0b                   ;if at this location, leave loop
  3203.           beq RendFore
  3204.           dec $00                    ;decrement until counter expires, barring exception
  3205.           bne SceLoop1
  3206. RendFore: ldx ForegroundScenery      ;check for foreground data needed or not
  3207.           beq RendTerr               ;if not, skip this part
  3208.           ldy FSceneDataOffsets-1,x  ;load offset from location offset by header value, then
  3209.           ldx #$00                   ;reinit X
  3210. SceLoop2: lda ForeSceneryData,y      ;load data until counter expires
  3211.           beq NoFore                 ;do not store if zero found
  3212.           sta MetatileBuffer,x
  3213. NoFore:   iny
  3214.           inx
  3215.           cpx #$0d                   ;store up to end of metatile buffer
  3216.           bne SceLoop2
  3217. RendTerr: ldy AreaType               ;check world type for water level
  3218.           bne TerMTile               ;if not water level, skip this part
  3219.           lda WorldNumber            ;check world number, if not world number eight
  3220.           cmp #World8                ;then skip this part
  3221.           bne TerMTile
  3222.           lda #$62                   ;if set as water level and world number eight,
  3223.           jmp StoreMT                ;use castle wall metatile as terrain type
  3224. TerMTile: lda TerrainMetatiles,y     ;otherwise get appropriate metatile for area type
  3225.           ldy CloudTypeOverride      ;check for cloud type override
  3226.           beq StoreMT                ;if not set, keep value otherwise
  3227.           lda #$88                   ;use cloud block terrain
  3228. StoreMT:  sta $07                    ;store value here
  3229.           ldx #$00                   ;initialize X, use as metatile buffer offset
  3230.           lda TerrainControl         ;use yet another value from the header
  3231.           asl                        ;multiply by 2 and use as yet another offset
  3232.           tay
  3233. TerrLoop: lda TerrainRenderBits,y    ;get one of the terrain rendering bit data
  3234.           sta $00
  3235.           iny                        ;increment Y and use as offset next time around
  3236.           sty $01
  3237.           lda CloudTypeOverride      ;skip if value here is zero
  3238.           beq NoCloud2
  3239.           cpx #$00                   ;otherwise, check if we're doing the ceiling byte
  3240.           beq NoCloud2
  3241.           lda $00                    ;if not, mask out all but d3
  3242.           and #%00001000
  3243.           sta $00
  3244. NoCloud2: ldy #$00                   ;start at beginning of bitmasks
  3245. TerrBChk: lda Bitmasks,y             ;load bitmask, then perform AND on contents of first byte
  3246.           bit $00
  3247.           beq NextTBit               ;if not set, skip this part (do not write terrain to buffer)
  3248.           lda $07
  3249.           sta MetatileBuffer,x       ;load terrain type metatile number and store into buffer here
  3250. NextTBit: inx                        ;continue until end of buffer
  3251.           cpx #$0d
  3252.           beq RendBBuf               ;if we're at the end, break out of this loop
  3253.           lda AreaType               ;check world type for underground area
  3254.           cmp #$02
  3255.           bne EndUChk                ;if not underground, skip this part
  3256.           cpx #$0b
  3257.           bne EndUChk                ;if we're at the bottom of the screen, override
  3258.           lda #$54                   ;old terrain type with ground level terrain type
  3259.           sta $07
  3260. EndUChk:  iny                        ;increment bitmasks offset in Y
  3261.           cpy #$08
  3262.           bne TerrBChk               ;if not all bits checked, loop back    
  3263.           ldy $01
  3264.           bne TerrLoop               ;unconditional branch, use Y to load next byte
  3265. RendBBuf: jsr ProcessAreaData        ;do the area data loading routine now
  3266.           lda BlockBufferColumnPos
  3267.           jsr GetBlockBufferAddr     ;get block buffer address from where we're at
  3268.           ldx #$00
  3269.           ldy #$00                   ;init index regs and start at beginning of smaller buffer
  3270. ChkMTLow: sty $00
  3271.           lda MetatileBuffer,x       ;load stored metatile number
  3272.           and #%11000000             ;mask out all but 2 MSB
  3273.           asl
  3274.           rol                        ;make %xx000000 into %000000xx
  3275.           rol
  3276.           tay                        ;use as offset in Y
  3277.           lda MetatileBuffer,x       ;reload original unmasked value here
  3278.           cmp BlockBuffLowBounds,y   ;check for certain values depending on bits set
  3279.           bcs StrBlock               ;if equal or greater, branch
  3280.           lda #$00                   ;if less, init value before storing
  3281. StrBlock: ldy $00                    ;get offset for block buffer
  3282.           sta ($06),y                ;store value into block buffer
  3283.           tya
  3284.           clc                        ;add 16 (move down one row) to offset
  3285.           adc #$10
  3286.           tay
  3287.           inx                        ;increment column value
  3288.           cpx #$0d
  3289.           bcc ChkMTLow               ;continue until we pass last row, then leave
  3290.           rts
  3291.  
  3292. ;numbers lower than these with the same attribute bits
  3293. ;will not be stored in the block buffer
  3294. BlockBuffLowBounds:
  3295.       .db $10, $51, $88, $c0
  3296.  
  3297. ;-------------------------------------------------------------------------------------
  3298. ;$00 - used to store area object identifier
  3299. ;$07 - used as adder to find proper area object code
  3300.  
  3301. ProcessAreaData:
  3302.             ldx #$02                 ;start at the end of area object buffer
  3303. ProcADLoop: stx ObjectOffset
  3304.             lda #$00                 ;reset flag
  3305.             sta BehindAreaParserFlag
  3306.             ldy AreaDataOffset       ;get offset of area data pointer
  3307.             lda (AreaData),y         ;get first byte of area object
  3308.             cmp #$fd                 ;if end-of-area, skip all this crap
  3309.             beq RdyDecode
  3310.             lda AreaObjectLength,x   ;check area object buffer flag
  3311.             bpl RdyDecode            ;if buffer not negative, branch, otherwise
  3312.             iny
  3313.             lda (AreaData),y         ;get second byte of area object
  3314.             asl                      ;check for page select bit (d7), branch if not set
  3315.             bcc Chk1Row13
  3316.             lda AreaObjectPageSel    ;check page select
  3317.             bne Chk1Row13
  3318.             inc AreaObjectPageSel    ;if not already set, set it now
  3319.             inc AreaObjectPageLoc    ;and increment page location
  3320. Chk1Row13:  dey
  3321.             lda (AreaData),y         ;reread first byte of level object
  3322.             and #$0f                 ;mask out high nybble
  3323.             cmp #$0d                 ;row 13?
  3324.             bne Chk1Row14
  3325.             iny                      ;if so, reread second byte of level object
  3326.             lda (AreaData),y
  3327.             dey                      ;decrement to get ready to read first byte
  3328.             and #%01000000           ;check for d6 set (if not, object is page control)
  3329.             bne CheckRear
  3330.             lda AreaObjectPageSel    ;if page select is set, do not reread
  3331.             bne CheckRear
  3332.             iny                      ;if d6 not set, reread second byte
  3333.             lda (AreaData),y
  3334.             and #%00011111           ;mask out all but 5 LSB and store in page control
  3335.             sta AreaObjectPageLoc
  3336.             inc AreaObjectPageSel    ;increment page select
  3337.             jmp NextAObj
  3338. Chk1Row14:  cmp #$0e                 ;row 14?
  3339.             bne CheckRear
  3340.             lda BackloadingFlag      ;check flag for saved page number and branch if set
  3341.             bne RdyDecode            ;to render the object (otherwise bg might not look right)
  3342. CheckRear:  lda AreaObjectPageLoc    ;check to see if current page of level object is
  3343.             cmp CurrentPageLoc       ;behind current page of renderer
  3344.             bcc SetBehind            ;if so branch
  3345. RdyDecode:  jsr DecodeAreaData       ;do sub and do not turn on flag
  3346.             jmp ChkLength
  3347. SetBehind:  inc BehindAreaParserFlag ;turn on flag if object is behind renderer
  3348. NextAObj:   jsr IncAreaObjOffset     ;increment buffer offset and move on
  3349. ChkLength:  ldx ObjectOffset         ;get buffer offset
  3350.             lda AreaObjectLength,x   ;check object length for anything stored here
  3351.             bmi ProcLoopb            ;if not, branch to handle loopback
  3352.             dec AreaObjectLength,x   ;otherwise decrement length or get rid of it
  3353. ProcLoopb:  dex                      ;decrement buffer offset
  3354.             bpl ProcADLoop           ;and loopback unless exceeded buffer
  3355.             lda BehindAreaParserFlag ;check for flag set if objects were behind renderer
  3356.             bne ProcessAreaData      ;branch if true to load more level data, otherwise
  3357.             lda BackloadingFlag      ;check for flag set if starting right of page $00
  3358.             bne ProcessAreaData      ;branch if true to load more level data, otherwise leave
  3359. EndAParse:  rts
  3360.  
  3361. IncAreaObjOffset:
  3362.       inc AreaDataOffset    ;increment offset of level pointer
  3363.       inc AreaDataOffset
  3364.       lda #$00              ;reset page select
  3365.       sta AreaObjectPageSel
  3366.       rts
  3367.  
  3368. DecodeAreaData:
  3369.           lda AreaObjectLength,x     ;check current buffer flag
  3370.           bmi Chk1stB
  3371.           ldy AreaObjOffsetBuffer,x  ;if not, get offset from buffer
  3372. Chk1stB:  ldx #$10                   ;load offset of 16 for special row 15
  3373.           lda (AreaData),y           ;get first byte of level object again
  3374.           cmp #$fd
  3375.           beq EndAParse              ;if end of level, leave this routine
  3376.           and #$0f                   ;otherwise, mask out low nybble
  3377.           cmp #$0f                   ;row 15?
  3378.           beq ChkRow14               ;if so, keep the offset of 16
  3379.           ldx #$08                   ;otherwise load offset of 8 for special row 12
  3380.           cmp #$0c                   ;row 12?
  3381.           beq ChkRow14               ;if so, keep the offset value of 8
  3382.           ldx #$00                   ;otherwise nullify value by default
  3383. ChkRow14: stx $07                    ;store whatever value we just loaded here
  3384.           ldx ObjectOffset           ;get object offset again
  3385.           cmp #$0e                   ;row 14?
  3386.           bne ChkRow13
  3387.           lda #$00                   ;if so, load offset with $00
  3388.           sta $07
  3389.           lda #$2e                   ;and load A with another value
  3390.           bne NormObj                ;unconditional branch
  3391. ChkRow13: cmp #$0d                   ;row 13?
  3392.           bne ChkSRows
  3393.           lda #$22                   ;if so, load offset with 34
  3394.           sta $07
  3395.           iny                        ;get next byte
  3396.           lda (AreaData),y
  3397.           and #%01000000             ;mask out all but d6 (page control obj bit)
  3398.           beq LeavePar               ;if d6 clear, branch to leave (we handled this earlier)
  3399.           lda (AreaData),y           ;otherwise, get byte again
  3400.           and #%01111111             ;mask out d7
  3401.           cmp #$4b                   ;check for loop command in low nybble
  3402.           bne Mask2MSB               ;(plus d6 set for object other than page control)
  3403.           inc LoopCommand            ;if loop command, set loop command flag
  3404. Mask2MSB: and #%00111111             ;mask out d7 and d6
  3405.           jmp NormObj                ;and jump
  3406. ChkSRows: cmp #$0c                   ;row 12-15?
  3407.           bcs SpecObj
  3408.           iny                        ;if not, get second byte of level object
  3409.           lda (AreaData),y
  3410.           and #%01110000             ;mask out all but d6-d4
  3411.           bne LrgObj                 ;if any bits set, branch to handle large object
  3412.           lda #$16
  3413.           sta $07                    ;otherwise set offset of 24 for small object
  3414.           lda (AreaData),y           ;reload second byte of level object
  3415.           and #%00001111             ;mask out higher nybble and jump
  3416.           jmp NormObj
  3417. LrgObj:   sta $00                    ;store value here (branch for large objects)
  3418.           cmp #$70                   ;check for vertical pipe object
  3419.           bne NotWPipe
  3420.           lda (AreaData),y           ;if not, reload second byte
  3421.           and #%00001000             ;mask out all but d3 (usage control bit)
  3422.           beq NotWPipe               ;if d3 clear, branch to get original value
  3423.           lda #$00                   ;otherwise, nullify value for warp pipe
  3424.           sta $00
  3425. NotWPipe: lda $00                    ;get value and jump ahead
  3426.           jmp MoveAOId
  3427. SpecObj:  iny                        ;branch here for rows 12-15
  3428.           lda (AreaData),y
  3429.           and #%01110000             ;get next byte and mask out all but d6-d4
  3430. MoveAOId: lsr                        ;move d6-d4 to lower nybble
  3431.           lsr
  3432.           lsr
  3433.           lsr
  3434. NormObj:  sta $00                    ;store value here (branch for small objects and rows 13 and 14)
  3435.           lda AreaObjectLength,x     ;is there something stored here already?
  3436.           bpl RunAObj                ;if so, branch to do its particular sub
  3437.           lda AreaObjectPageLoc      ;otherwise check to see if the object we've loaded is on the
  3438.           cmp CurrentPageLoc         ;same page as the renderer, and if so, branch
  3439.           beq InitRear
  3440.           ldy AreaDataOffset         ;if not, get old offset of level pointer
  3441.           lda (AreaData),y           ;and reload first byte
  3442.           and #%00001111
  3443.           cmp #$0e                   ;row 14?
  3444.           bne LeavePar
  3445.           lda BackloadingFlag        ;if so, check backloading flag
  3446.           bne StrAObj                ;if set, branch to render object, else leave
  3447. LeavePar: rts
  3448. InitRear: lda BackloadingFlag        ;check backloading flag to see if it's been initialized
  3449.           beq BackColC               ;branch to column-wise check
  3450.           lda #$00                   ;if not, initialize both backloading and
  3451.           sta BackloadingFlag        ;behind-renderer flags and leave
  3452.           sta BehindAreaParserFlag
  3453.           sta ObjectOffset
  3454. LoopCmdE: rts
  3455. BackColC: ldy AreaDataOffset         ;get first byte again
  3456.           lda (AreaData),y
  3457.           and #%11110000             ;mask out low nybble and move high to low
  3458.           lsr
  3459.           lsr
  3460.           lsr
  3461.           lsr
  3462.           cmp CurrentColumnPos       ;is this where we're at?
  3463.           bne LeavePar               ;if not, branch to leave
  3464. StrAObj:  lda AreaDataOffset         ;if so, load area obj offset and store in buffer
  3465.           sta AreaObjOffsetBuffer,x
  3466.           jsr IncAreaObjOffset       ;do sub to increment to next object data
  3467. RunAObj:  lda $00                    ;get stored value and add offset to it
  3468.           clc                        ;then use the jump engine with current contents of A
  3469.           adc $07
  3470.           jsr JumpEngine
  3471.  
  3472. ;large objects (rows $00-$0b or 00-11, d6-d4 set)
  3473.       .dw VerticalPipe         ;used by warp pipes
  3474.       .dw AreaStyleObject
  3475.       .dw RowOfBricks
  3476.       .dw RowOfSolidBlocks
  3477.       .dw RowOfCoins
  3478.       .dw ColumnOfBricks
  3479.       .dw ColumnOfSolidBlocks
  3480.       .dw VerticalPipe         ;used by decoration pipes
  3481.  
  3482. ;objects for special row $0c or 12
  3483.       .dw Hole_Empty
  3484.       .dw PulleyRopeObject
  3485.       .dw Bridge_High
  3486.       .dw Bridge_Middle
  3487.       .dw Bridge_Low
  3488.       .dw Hole_Water
  3489.       .dw QuestionBlockRow_High
  3490.       .dw QuestionBlockRow_Low
  3491.  
  3492. ;objects for special row $0f or 15
  3493.       .dw EndlessRope
  3494.       .dw BalancePlatRope
  3495.       .dw CastleObject
  3496.       .dw StaircaseObject
  3497.       .dw ExitPipe
  3498.       .dw FlagBalls_Residual
  3499.  
  3500. ;small objects (rows $00-$0b or 00-11, d6-d4 all clear)
  3501.       .dw QuestionBlock     ;power-up
  3502.       .dw QuestionBlock     ;coin
  3503.       .dw QuestionBlock     ;hidden, coin
  3504.       .dw Hidden1UpBlock    ;hidden, 1-up
  3505.       .dw BrickWithItem     ;brick, power-up
  3506.       .dw BrickWithItem     ;brick, vine
  3507.       .dw BrickWithItem     ;brick, star
  3508.       .dw BrickWithCoins    ;brick, coins
  3509.       .dw BrickWithItem     ;brick, 1-up
  3510.       .dw WaterPipe
  3511.       .dw EmptyBlock
  3512.       .dw Jumpspring
  3513.  
  3514. ;objects for special row $0d or 13 (d6 set)
  3515.       .dw IntroPipe
  3516.       .dw FlagpoleObject
  3517.       .dw AxeObj
  3518.       .dw ChainObj
  3519.       .dw CastleBridgeObj
  3520.       .dw ScrollLockObject_Warp
  3521.       .dw ScrollLockObject
  3522.       .dw ScrollLockObject
  3523.       .dw AreaFrenzy            ;flying cheep-cheeps
  3524.       .dw AreaFrenzy            ;bullet bills or swimming cheep-cheeps
  3525.       .dw AreaFrenzy            ;stop frenzy
  3526.       .dw LoopCmdE
  3527.  
  3528. ;object for special row $0e or 14
  3529.       .dw AlterAreaAttributes
  3530.  
  3531. ;-------------------------------------------------------------------------------------
  3532. ;(these apply to all area object subroutines in this section unless otherwise stated)
  3533. ;$00 - used to store offset used to find object code
  3534. ;$07 - starts with adder from area parser, used to store row offset
  3535.  
  3536. AlterAreaAttributes:
  3537.          ldy AreaObjOffsetBuffer,x ;load offset for level object data saved in buffer
  3538.          iny                       ;load second byte
  3539.          lda (AreaData),y
  3540.          pha                       ;save in stack for now
  3541.          and #%01000000
  3542.          bne Alter2                ;branch if d6 is set
  3543.          pla
  3544.          pha                       ;pull and push offset to copy to A
  3545.          and #%00001111            ;mask out high nybble and store as
  3546.          sta TerrainControl        ;new terrain height type bits
  3547.          pla
  3548.          and #%00110000            ;pull and mask out all but d5 and d4
  3549.          lsr                       ;move bits to lower nybble and store
  3550.          lsr                       ;as new background scenery bits
  3551.          lsr
  3552.          lsr
  3553.          sta BackgroundScenery     ;then leave
  3554.          rts
  3555. Alter2:  pla
  3556.          and #%00000111            ;mask out all but 3 LSB
  3557.          cmp #$04                  ;if four or greater, set color control bits
  3558.          bcc SetFore               ;and nullify foreground scenery bits
  3559.          sta BackgroundColorCtrl
  3560.          lda #$00
  3561. SetFore: sta ForegroundScenery     ;otherwise set new foreground scenery bits
  3562.          rts
  3563.  
  3564. ;--------------------------------
  3565.  
  3566. ScrollLockObject_Warp:
  3567.          ldx #$04            ;load value of 4 for game text routine as default
  3568.          lda WorldNumber     ;warp zone (4-3-2), then check world number
  3569.          beq WarpNum
  3570.          inx                 ;if world number > 1, increment for next warp zone (5)
  3571.          ldy AreaType        ;check area type
  3572.          dey
  3573.          bne WarpNum         ;if ground area type, increment for last warp zone
  3574.          inx                 ;(8-7-6) and move on
  3575. WarpNum: txa
  3576.          sta WarpZoneControl ;store number here to be used by warp zone routine
  3577.          jsr WriteGameText   ;print text and warp zone numbers
  3578.          lda #PiranhaPlant
  3579.          jsr KillEnemies     ;load identifier for piranha plants and do sub
  3580.  
  3581. ScrollLockObject:
  3582.       lda ScrollLock      ;invert scroll lock to turn it on
  3583.       eor #%00000001
  3584.       sta ScrollLock
  3585.       rts
  3586.  
  3587. ;--------------------------------
  3588. ;$00 - used to store enemy identifier in KillEnemies
  3589.  
  3590. KillEnemies:
  3591.            sta $00           ;store identifier here
  3592.            lda #$00
  3593.            ldx #$04          ;check for identifier in enemy object buffer
  3594. KillELoop: ldy Enemy_ID,x
  3595.            cpy $00           ;if not found, branch
  3596.            bne NoKillE
  3597.            sta Enemy_Flag,x  ;if found, deactivate enemy object flag
  3598. NoKillE:   dex               ;do this until all slots are checked
  3599.            bpl KillELoop
  3600.            rts
  3601.  
  3602. ;--------------------------------
  3603.  
  3604. FrenzyIDData:
  3605.       .db FlyCheepCheepFrenzy, BBill_CCheep_Frenzy, Stop_Frenzy
  3606.  
  3607. AreaFrenzy:  ldx $00               ;use area object identifier bit as offset
  3608.              lda FrenzyIDData-8,x  ;note that it starts at 8, thus weird address here
  3609.              ldy #$05
  3610. FreCompLoop: dey                   ;check regular slots of enemy object buffer
  3611.              bmi ExitAFrenzy       ;if all slots checked and enemy object not found, branch to store
  3612.              cmp Enemy_ID,y    ;check for enemy object in buffer versus frenzy object
  3613.              bne FreCompLoop
  3614.              lda #$00              ;if enemy object already present, nullify queue and leave
  3615. ExitAFrenzy: sta EnemyFrenzyQueue  ;store enemy into frenzy queue
  3616.              rts
  3617.  
  3618. ;--------------------------------
  3619. ;$06 - used by MushroomLedge to store length
  3620.  
  3621. AreaStyleObject:
  3622.       lda AreaStyle        ;load level object style and jump to the right sub
  3623.       jsr JumpEngine
  3624.       .dw TreeLedge        ;also used for cloud type levels
  3625.       .dw MushroomLedge
  3626.       .dw BulletBillCannon
  3627.  
  3628. TreeLedge:
  3629.           jsr GetLrgObjAttrib     ;get row and length of green ledge
  3630.           lda AreaObjectLength,x  ;check length counter for expiration
  3631.           beq EndTreeL  
  3632.           bpl MidTreeL
  3633.           tya
  3634.           sta AreaObjectLength,x  ;store lower nybble into buffer flag as length of ledge
  3635.           lda CurrentPageLoc
  3636.           ora CurrentColumnPos    ;are we at the start of the level?
  3637.           beq MidTreeL
  3638.           lda #$16                ;render start of tree ledge
  3639.           jmp NoUnder
  3640. MidTreeL: ldx $07
  3641.           lda #$17                ;render middle of tree ledge
  3642.           sta MetatileBuffer,x    ;note that this is also used if ledge position is
  3643.           lda #$4c                ;at the start of level for continuous effect
  3644.           jmp AllUnder            ;now render the part underneath
  3645. EndTreeL: lda #$18                ;render end of tree ledge
  3646.           jmp NoUnder
  3647.  
  3648. MushroomLedge:
  3649.           jsr ChkLrgObjLength        ;get shroom dimensions
  3650.           sty $06                    ;store length here for now
  3651.           bcc EndMushL
  3652.           lda AreaObjectLength,x     ;divide length by 2 and store elsewhere
  3653.           lsr
  3654.           sta MushroomLedgeHalfLen,x
  3655.           lda #$19                   ;render start of mushroom
  3656.           jmp NoUnder
  3657. EndMushL: lda #$1b                   ;if at the end, render end of mushroom
  3658.           ldy AreaObjectLength,x
  3659.           beq NoUnder
  3660.           lda MushroomLedgeHalfLen,x ;get divided length and store where length
  3661.           sta $06                    ;was stored originally
  3662.           ldx $07
  3663.           lda #$1a
  3664.           sta MetatileBuffer,x       ;render middle of mushroom
  3665.           cpy $06                    ;are we smack dab in the center?
  3666.           bne MushLExit              ;if not, branch to leave
  3667.           inx
  3668.           lda #$4f
  3669.           sta MetatileBuffer,x       ;render stem top of mushroom underneath the middle
  3670.           lda #$50
  3671. AllUnder: inx
  3672.           ldy #$0f                   ;set $0f to render all way down
  3673.           jmp RenderUnderPart       ;now render the stem of mushroom
  3674. NoUnder:  ldx $07                    ;load row of ledge
  3675.           ldy #$00                   ;set 0 for no bottom on this part
  3676.           jmp RenderUnderPart
  3677.  
  3678. ;--------------------------------
  3679.  
  3680. ;tiles used by pulleys and rope object
  3681. PulleyRopeMetatiles:
  3682.       .db $42, $41, $43
  3683.  
  3684. PulleyRopeObject:
  3685.            jsr ChkLrgObjLength       ;get length of pulley/rope object
  3686.            ldy #$00                  ;initialize metatile offset
  3687.            bcs RenderPul             ;if starting, render left pulley
  3688.            iny
  3689.            lda AreaObjectLength,x    ;if not at the end, render rope
  3690.            bne RenderPul
  3691.            iny                       ;otherwise render right pulley
  3692. RenderPul: lda PulleyRopeMetatiles,y
  3693.            sta MetatileBuffer        ;render at the top of the screen
  3694. MushLExit: rts                       ;and leave
  3695.  
  3696. ;--------------------------------
  3697. ;$06 - used to store upper limit of rows for CastleObject
  3698.  
  3699. CastleMetatiles:
  3700.       .db $00, $45, $45, $45, $00
  3701.       .db $00, $48, $47, $46, $00
  3702.       .db $45, $49, $49, $49, $45
  3703.       .db $47, $47, $4a, $47, $47
  3704.       .db $47, $47, $4b, $47, $47
  3705.       .db $49, $49, $49, $49, $49
  3706.       .db $47, $4a, $47, $4a, $47
  3707.       .db $47, $4b, $47, $4b, $47
  3708.       .db $47, $47, $47, $47, $47
  3709.       .db $4a, $47, $4a, $47, $4a
  3710.       .db $4b, $47, $4b, $47, $4b
  3711.  
  3712. CastleObject:
  3713.             jsr GetLrgObjAttrib      ;save lower nybble as starting row
  3714.             sty $07                  ;if starting row is above $0a, game will crash!!!
  3715.             ldy #$04
  3716.             jsr ChkLrgObjFixedLength ;load length of castle if not already loaded
  3717.             txa                  
  3718.             pha                      ;save obj buffer offset to stack
  3719.             ldy AreaObjectLength,x   ;use current length as offset for castle data
  3720.             ldx $07                  ;begin at starting row
  3721.             lda #$0b
  3722.             sta $06                  ;load upper limit of number of rows to print
  3723. CRendLoop:  lda CastleMetatiles,y    ;load current byte using offset
  3724.             sta MetatileBuffer,x
  3725.             inx                      ;store in buffer and increment buffer offset
  3726.             lda $06
  3727.             beq ChkCFloor            ;have we reached upper limit yet?
  3728.             iny                      ;if not, increment column-wise
  3729.             iny                      ;to byte in next row
  3730.             iny
  3731.             iny
  3732.             iny
  3733.             dec $06                  ;move closer to upper limit
  3734. ChkCFloor:  cpx #$0b                 ;have we reached the row just before floor?
  3735.             bne CRendLoop            ;if not, go back and do another row
  3736.             pla
  3737.             tax                      ;get obj buffer offset from before
  3738.             lda CurrentPageLoc
  3739.             beq ExitCastle           ;if we're at page 0, we do not need to do anything else
  3740.             lda AreaObjectLength,x   ;check length
  3741.             cmp #$01                 ;if length almost about to expire, put brick at floor
  3742.             beq PlayerStop
  3743.             ldy $07                  ;check starting row for tall castle ($00)
  3744.             bne NotTall
  3745.             cmp #$03                 ;if found, then check to see if we're at the second column
  3746.             beq PlayerStop
  3747. NotTall:    cmp #$02                 ;if not tall castle, check to see if we're at the third column
  3748.             bne ExitCastle           ;if we aren't and the castle is tall, don't create flag yet
  3749.             jsr GetAreaObjXPosition  ;otherwise, obtain and save horizontal pixel coordinate
  3750.             pha
  3751.             jsr FindEmptyEnemySlot   ;find an empty place on the enemy object buffer
  3752.             pla
  3753.             sta Enemy_X_Position,x   ;then write horizontal coordinate for star flag
  3754.             lda CurrentPageLoc
  3755.             sta Enemy_PageLoc,x      ;set page location for star flag
  3756.             lda #$01
  3757.             sta Enemy_Y_HighPos,x    ;set vertical high byte
  3758.             sta Enemy_Flag,x         ;set flag for buffer
  3759.             lda #$90
  3760.             sta Enemy_Y_Position,x   ;set vertical coordinate
  3761.             lda #StarFlagObject      ;set star flag value in buffer itself
  3762.             sta Enemy_ID,x
  3763.             rts
  3764. PlayerStop: ldy #$52                 ;put brick at floor to stop player at end of level
  3765.             sty MetatileBuffer+10    ;this is only done if we're on the second column
  3766. ExitCastle: rts
  3767.  
  3768. ;--------------------------------
  3769.  
  3770. WaterPipe:
  3771.       jsr GetLrgObjAttrib     ;get row and lower nybble
  3772.       ldy AreaObjectLength,x  ;get length (residual code, water pipe is 1 col thick)
  3773.       ldx $07                 ;get row
  3774.       lda #$6b
  3775.       sta MetatileBuffer,x    ;draw something here and below it
  3776.       lda #$6c
  3777.       sta MetatileBuffer+1,x
  3778.       rts
  3779.  
  3780. ;--------------------------------
  3781. ;$05 - used to store length of vertical shaft in RenderSidewaysPipe
  3782. ;$06 - used to store leftover horizontal length in RenderSidewaysPipe
  3783. ; and vertical length in VerticalPipe and GetPipeHeight
  3784.  
  3785. IntroPipe:
  3786.                ldy #$03                 ;check if length set, if not set, set it
  3787.                jsr ChkLrgObjFixedLength
  3788.                ldy #$0a                 ;set fixed value and render the sideways part
  3789.                jsr RenderSidewaysPipe
  3790.                bcs NoBlankP             ;if carry flag set, not time to draw vertical pipe part
  3791.                ldx #$06                 ;blank everything above the vertical pipe part
  3792. VPipeSectLoop: lda #$00                 ;all the way to the top of the screen
  3793.                sta MetatileBuffer,x     ;because otherwise it will look like exit pipe
  3794.                dex
  3795.                bpl VPipeSectLoop
  3796.                lda VerticalPipeData,y   ;draw the end of the vertical pipe part
  3797.                sta MetatileBuffer+7
  3798. NoBlankP:      rts
  3799.  
  3800. SidePipeShaftData:
  3801.       .db $15, $14  ;used to control whether or not vertical pipe shaft
  3802.       .db $00, $00  ;is drawn, and if so, controls the metatile number
  3803. SidePipeTopPart:
  3804.       .db $15, $1e  ;top part of sideways part of pipe
  3805.       .db $1d, $1c
  3806. SidePipeBottomPart:
  3807.       .db $15, $21  ;bottom part of sideways part of pipe
  3808.       .db $20, $1f
  3809.  
  3810. ExitPipe:
  3811.       ldy #$03                 ;check if length set, if not set, set it
  3812.       jsr ChkLrgObjFixedLength
  3813.       jsr GetLrgObjAttrib      ;get vertical length, then plow on through RenderSidewaysPipe
  3814.  
  3815. RenderSidewaysPipe:
  3816.               dey                       ;decrement twice to make room for shaft at bottom
  3817.               dey                       ;and store here for now as vertical length
  3818.               sty $05
  3819.               ldy AreaObjectLength,x    ;get length left over and store here
  3820.               sty $06
  3821.               ldx $05                   ;get vertical length plus one, use as buffer offset
  3822.               inx
  3823.               lda SidePipeShaftData,y   ;check for value $00 based on horizontal offset
  3824.               cmp #$00
  3825.               beq DrawSidePart          ;if found, do not draw the vertical pipe shaft
  3826.               ldx #$00
  3827.               ldy $05                   ;init buffer offset and get vertical length
  3828.               jsr RenderUnderPart       ;and render vertical shaft using tile number in A
  3829.               clc                       ;clear carry flag to be used by IntroPipe
  3830. DrawSidePart: ldy $06                   ;render side pipe part at the bottom
  3831.               lda SidePipeTopPart,y
  3832.               sta MetatileBuffer,x      ;note that the pipe parts are stored
  3833.               lda SidePipeBottomPart,y  ;backwards horizontally
  3834.               sta MetatileBuffer+1,x
  3835.               rts
  3836.  
  3837. VerticalPipeData:
  3838.       .db $11, $10 ;used by pipes that lead somewhere
  3839.       .db $15, $14
  3840.       .db $13, $12 ;used by decoration pipes
  3841.       .db $15, $14
  3842.  
  3843. VerticalPipe:
  3844.           jsr GetPipeHeight
  3845.           lda $00                  ;check to see if value was nullified earlier
  3846.           beq WarpPipe             ;(if d3, the usage control bit of second byte, was set)
  3847.           iny
  3848.           iny
  3849.           iny
  3850.           iny                      ;add four if usage control bit was not set
  3851. WarpPipe: tya                      ;save value in stack
  3852.           pha
  3853.           lda AreaNumber
  3854.           ora WorldNumber          ;if at world 1-1, do not add piranha plant ever
  3855.           beq DrawPipe
  3856.           ldy AreaObjectLength,x   ;if on second column of pipe, branch
  3857.           beq DrawPipe             ;(because we only need to do this once)
  3858.           jsr FindEmptyEnemySlot   ;check for an empty moving data buffer space
  3859.           bcs DrawPipe             ;if not found, too many enemies, thus skip
  3860.           jsr GetAreaObjXPosition  ;get horizontal pixel coordinate
  3861.           clc
  3862.           adc #$08                 ;add eight to put the piranha plant in the center
  3863.           sta Enemy_X_Position,x   ;store as enemy's horizontal coordinate
  3864.           lda CurrentPageLoc       ;add carry to current page number
  3865.           adc #$00
  3866.           sta Enemy_PageLoc,x      ;store as enemy's page coordinate
  3867.           lda #$01
  3868.           sta Enemy_Y_HighPos,x
  3869.           sta Enemy_Flag,x         ;activate enemy flag
  3870.           jsr GetAreaObjYPosition  ;get piranha plant's vertical coordinate and store here
  3871.           sta Enemy_Y_Position,x
  3872.           lda #PiranhaPlant        ;write piranha plant's value into buffer
  3873.           sta Enemy_ID,x
  3874.           jsr InitPiranhaPlant
  3875. DrawPipe: pla                      ;get value saved earlier and use as Y
  3876.           tay
  3877.           ldx $07                  ;get buffer offset
  3878.           lda VerticalPipeData,y   ;draw the appropriate pipe with the Y we loaded earlier
  3879.           sta MetatileBuffer,x     ;render the top of the pipe
  3880.           inx
  3881.           lda VerticalPipeData+2,y ;render the rest of the pipe
  3882.           ldy $06                  ;subtract one from length and render the part underneath
  3883.           dey
  3884.           jmp RenderUnderPart
  3885.      
  3886. GetPipeHeight:
  3887.       ldy #$01       ;check for length loaded, if not, load
  3888.       jsr ChkLrgObjFixedLength ;pipe length of 2 (horizontal)
  3889.       jsr GetLrgObjAttrib
  3890.       tya            ;get saved lower nybble as height
  3891.       and #$07       ;save only the three lower bits as
  3892.       sta $06        ;vertical length, then load Y with
  3893.       ldy AreaObjectLength,x    ;length left over
  3894.       rts
  3895.  
  3896. FindEmptyEnemySlot:
  3897.               ldx #$00          ;start at first enemy slot
  3898. EmptyChkLoop: clc               ;clear carry flag by default
  3899.               lda Enemy_Flag,x  ;check enemy buffer for nonzero
  3900.               beq ExitEmptyChk  ;if zero, leave
  3901.               inx
  3902.               cpx #$05          ;if nonzero, check next value
  3903.               bne EmptyChkLoop
  3904. ExitEmptyChk: rts               ;if all values nonzero, carry flag is set
  3905.  
  3906. ;--------------------------------
  3907.  
  3908. Hole_Water:
  3909.       jsr ChkLrgObjLength   ;get low nybble and save as length
  3910.       lda #$86              ;render waves
  3911.       sta MetatileBuffer+10
  3912.       ldx #$0b
  3913.       ldy #$01              ;now render the water underneath
  3914.       lda #$87
  3915.       jmp RenderUnderPart
  3916.  
  3917. ;--------------------------------
  3918.  
  3919. QuestionBlockRow_High:
  3920.       lda #$03    ;start on the fourth row
  3921.       .db $2c     ;BIT instruction opcode
  3922.  
  3923. QuestionBlockRow_Low:
  3924.       lda #$07             ;start on the eighth row
  3925.       pha                  ;save whatever row to the stack for now
  3926.       jsr ChkLrgObjLength  ;get low nybble and save as length
  3927.       pla
  3928.       tax                  ;render question boxes with coins
  3929.       lda #$c0
  3930.       sta MetatileBuffer,x
  3931.       rts
  3932.  
  3933. ;--------------------------------
  3934.  
  3935. Bridge_High:
  3936.       lda #$06  ;start on the seventh row from top of screen
  3937.       .db $2c   ;BIT instruction opcode
  3938.  
  3939. Bridge_Middle:
  3940.       lda #$07  ;start on the eighth row
  3941.       .db $2c   ;BIT instruction opcode
  3942.  
  3943. Bridge_Low:
  3944.       lda #$09             ;start on the tenth row
  3945.       pha                  ;save whatever row to the stack for now
  3946.       jsr ChkLrgObjLength  ;get low nybble and save as length
  3947.       pla
  3948.       tax                  ;render bridge railing
  3949.       lda #$0b
  3950.       sta MetatileBuffer,x
  3951.       inx
  3952.       ldy #$00             ;now render the bridge itself
  3953.       lda #$63
  3954.       jmp RenderUnderPart
  3955.  
  3956. ;--------------------------------
  3957.  
  3958. FlagBalls_Residual:
  3959.       jsr GetLrgObjAttrib  ;get low nybble from object byte
  3960.       ldx #$02             ;render flag balls on third row from top
  3961.       lda #$6d             ;of screen downwards based on low nybble
  3962.       jmp RenderUnderPart
  3963.  
  3964. ;--------------------------------
  3965.  
  3966. FlagpoleObject:
  3967.       lda #$24                 ;render flagpole ball on top
  3968.       sta MetatileBuffer
  3969.       ldx #$01                 ;now render the flagpole shaft
  3970.       ldy #$08
  3971.       lda #$25
  3972.       jsr RenderUnderPart
  3973.       lda #$61                 ;render solid block at the bottom
  3974.       sta MetatileBuffer+10
  3975.       jsr GetAreaObjXPosition
  3976.       sec                      ;get pixel coordinate of where the flagpole is,
  3977.       sbc #$08                 ;subtract eight pixels and use as horizontal
  3978.       sta Enemy_X_Position+5   ;coordinate for the flag
  3979.       lda CurrentPageLoc
  3980.       sbc #$00                 ;subtract borrow from page location and use as
  3981.       sta Enemy_PageLoc+5      ;page location for the flag
  3982.       lda #$30
  3983.       sta Enemy_Y_Position+5   ;set vertical coordinate for flag
  3984.       lda #$b0
  3985.       sta FlagpoleFNum_Y_Pos   ;set initial vertical coordinate for flagpole's floatey number
  3986.       lda #FlagpoleFlagObject
  3987.       sta Enemy_ID+5           ;set flag identifier, note that identifier and coordinates
  3988.       inc Enemy_Flag+5         ;use last space in enemy object buffer
  3989.       rts
  3990.  
  3991. ;--------------------------------
  3992.  
  3993. EndlessRope:
  3994.       ldx #$00       ;render rope from the top to the bottom of screen
  3995.       ldy #$0f
  3996.       jmp DrawRope
  3997.  
  3998. BalancePlatRope:
  3999.           txa                 ;save object buffer offset for now
  4000.           pha
  4001.           ldx #$01            ;blank out all from second row to the bottom
  4002.           ldy #$0f            ;with blank used for balance platform rope
  4003.           lda #$44
  4004.           jsr RenderUnderPart
  4005.           pla                 ;get back object buffer offset
  4006.           tax
  4007.           jsr GetLrgObjAttrib ;get vertical length from lower nybble
  4008.           ldx #$01
  4009. DrawRope: lda #$40            ;render the actual rope
  4010.           jmp RenderUnderPart
  4011.  
  4012. ;--------------------------------
  4013.  
  4014. CoinMetatileData:
  4015.       .db $c3, $c2, $c2, $c2
  4016.  
  4017. RowOfCoins:
  4018.       ldy AreaType            ;get area type
  4019.       lda CoinMetatileData,y  ;load appropriate coin metatile
  4020.       jmp GetRow
  4021.  
  4022. ;--------------------------------
  4023.  
  4024. C_ObjectRow:
  4025.       .db $06, $07, $08
  4026.  
  4027. C_ObjectMetatile:
  4028.       .db $c5, $0c, $89
  4029.  
  4030. CastleBridgeObj:
  4031.       ldy #$0c                  ;load length of 13 columns
  4032.       jsr ChkLrgObjFixedLength
  4033.       jmp ChainObj
  4034.  
  4035. AxeObj:
  4036.       lda #$08                  ;load bowser's palette into sprite portion of palette
  4037.       sta VRAM_Buffer_AddrCtrl
  4038.  
  4039. ChainObj:
  4040.       ldy $00                   ;get value loaded earlier from decoder
  4041.       ldx C_ObjectRow-2,y       ;get appropriate row and metatile for object
  4042.       lda C_ObjectMetatile-2,y
  4043.       jmp ColObj
  4044.  
  4045. EmptyBlock:
  4046.         jsr GetLrgObjAttrib  ;get row location
  4047.         ldx $07
  4048.         lda #$c4
  4049. ColObj: ldy #$00             ;column length of 1
  4050.         jmp RenderUnderPart
  4051.  
  4052. ;--------------------------------
  4053.  
  4054. SolidBlockMetatiles:
  4055.       .db $69, $61, $61, $62
  4056.  
  4057. BrickMetatiles:
  4058.       .db $22, $51, $52, $52
  4059.       .db $88 ;used only by row of bricks object
  4060.  
  4061. RowOfBricks:
  4062.             ldy AreaType           ;load area type obtained from area offset pointer
  4063.             lda CloudTypeOverride  ;check for cloud type override
  4064.             beq DrawBricks
  4065.             ldy #$04               ;if cloud type, override area type
  4066. DrawBricks: lda BrickMetatiles,y   ;get appropriate metatile
  4067.             jmp GetRow             ;and go render it
  4068.  
  4069. RowOfSolidBlocks:
  4070.          ldy AreaType               ;load area type obtained from area offset pointer
  4071.          lda SolidBlockMetatiles,y  ;get metatile
  4072. GetRow:  pha                        ;store metatile here
  4073.          jsr ChkLrgObjLength        ;get row number, load length
  4074. DrawRow: ldx $07
  4075.          ldy #$00                   ;set vertical height of 1
  4076.          pla
  4077.          jmp RenderUnderPart        ;render object
  4078.  
  4079. ColumnOfBricks:
  4080.       ldy AreaType          ;load area type obtained from area offset
  4081.       lda BrickMetatiles,y  ;get metatile (no cloud override as for row)
  4082.       jmp GetRow2
  4083.  
  4084. ColumnOfSolidBlocks:
  4085.          ldy AreaType               ;load area type obtained from area offset
  4086.          lda SolidBlockMetatiles,y  ;get metatile
  4087. GetRow2: pha                        ;save metatile to stack for now
  4088.          jsr GetLrgObjAttrib        ;get length and row
  4089.          pla                        ;restore metatile
  4090.          ldx $07                    ;get starting row
  4091.          jmp RenderUnderPart        ;now render the column
  4092.  
  4093. ;--------------------------------
  4094.  
  4095. BulletBillCannon:
  4096.              jsr GetLrgObjAttrib      ;get row and length of bullet bill cannon
  4097.              ldx $07                  ;start at first row
  4098.              lda #$64                 ;render bullet bill cannon
  4099.              sta MetatileBuffer,x
  4100.              inx
  4101.              dey                      ;done yet?
  4102.              bmi SetupCannon
  4103.              lda #$65                 ;if not, render middle part
  4104.              sta MetatileBuffer,x
  4105.              inx
  4106.              dey                      ;done yet?
  4107.              bmi SetupCannon
  4108.              lda #$66                 ;if not, render bottom until length expires
  4109.              jsr RenderUnderPart
  4110. SetupCannon: ldx Cannon_Offset        ;get offset for data used by cannons and whirlpools
  4111.              jsr GetAreaObjYPosition  ;get proper vertical coordinate for cannon
  4112.              sta Cannon_Y_Position,x  ;and store it here
  4113.              lda CurrentPageLoc
  4114.              sta Cannon_PageLoc,x     ;store page number for cannon here
  4115.              jsr GetAreaObjXPosition  ;get proper horizontal coordinate for cannon
  4116.              sta Cannon_X_Position,x  ;and store it here
  4117.              inx
  4118.              cpx #$06                 ;increment and check offset
  4119.              bcc StrCOffset           ;if not yet reached sixth cannon, branch to save offset
  4120.              ldx #$00                 ;otherwise initialize it
  4121. StrCOffset:  stx Cannon_Offset        ;save new offset and leave
  4122.              rts
  4123.  
  4124. ;--------------------------------
  4125.  
  4126. StaircaseHeightData:
  4127.       .db $07, $07, $06, $05, $04, $03, $02, $01, $00
  4128.  
  4129. StaircaseRowData:
  4130.       .db $03, $03, $04, $05, $06, $07, $08, $09, $0a
  4131.  
  4132. StaircaseObject:
  4133.            jsr ChkLrgObjLength       ;check and load length
  4134.            bcc NextStair             ;if length already loaded, skip init part
  4135.            lda #$09                  ;start past the end for the bottom
  4136.            sta StaircaseControl      ;of the staircase
  4137. NextStair: dec StaircaseControl      ;move onto next step (or first if starting)
  4138.            ldy StaircaseControl
  4139.            ldx StaircaseRowData,y    ;get starting row and height to render
  4140.            lda StaircaseHeightData,y
  4141.            tay
  4142.            lda #$61                  ;now render solid block staircase
  4143.            jmp RenderUnderPart
  4144.  
  4145. ;--------------------------------
  4146.  
  4147. Jumpspring:
  4148.       jsr GetLrgObjAttrib
  4149.       jsr FindEmptyEnemySlot      ;find empty space in enemy object buffer
  4150.       jsr GetAreaObjXPosition     ;get horizontal coordinate for jumpspring
  4151.       sta Enemy_X_Position,x      ;and store
  4152.       lda CurrentPageLoc          ;store page location of jumpspring
  4153.       sta Enemy_PageLoc,x
  4154.       jsr GetAreaObjYPosition     ;get vertical coordinate for jumpspring
  4155.       sta Enemy_Y_Position,x      ;and store
  4156.       sta Jumpspring_FixedYPos,x  ;store as permanent coordinate here
  4157.       lda #JumpspringObject
  4158.       sta Enemy_ID,x              ;write jumpspring object to enemy object buffer
  4159.       ldy #$01
  4160.       sty Enemy_Y_HighPos,x       ;store vertical high byte
  4161.       inc Enemy_Flag,x            ;set flag for enemy object buffer
  4162.       ldx $07
  4163.       lda #$67                    ;draw metatiles in two rows where jumpspring is
  4164.       sta MetatileBuffer,x
  4165.       lda #$68
  4166.       sta MetatileBuffer+1,x
  4167.       rts
  4168.  
  4169. ;--------------------------------
  4170. ;$07 - used to save ID of brick object
  4171.  
  4172. Hidden1UpBlock:
  4173.       lda Hidden1UpFlag  ;if flag not set, do not render object
  4174.       beq ExitDecBlock
  4175.       lda #$00           ;if set, init for the next one
  4176.       sta Hidden1UpFlag
  4177.       jmp BrickWithItem  ;jump to code shared with unbreakable bricks
  4178.  
  4179. QuestionBlock:
  4180.       jsr GetAreaObjectID ;get value from level decoder routine
  4181.       jmp DrawQBlk        ;go to render it
  4182.  
  4183. BrickWithCoins:
  4184.       lda #$00                 ;initialize multi-coin timer flag
  4185.       sta BrickCoinTimerFlag
  4186.  
  4187. BrickWithItem:
  4188.           jsr GetAreaObjectID         ;save area object ID
  4189.           sty $07              
  4190.           lda #$00                    ;load default adder for bricks with lines
  4191.           ldy AreaType                ;check level type for ground level
  4192.           dey
  4193.           beq BWithL                  ;if ground type, do not start with 5
  4194.           lda #$05                    ;otherwise use adder for bricks without lines
  4195. BWithL:   clc                         ;add object ID to adder
  4196.           adc $07
  4197.           tay                         ;use as offset for metatile
  4198. DrawQBlk: lda BrickQBlockMetatiles,y  ;get appropriate metatile for brick (question block
  4199.           pha                         ;if branched to here from question block routine)
  4200.           jsr GetLrgObjAttrib         ;get row from location byte
  4201.           jmp DrawRow                 ;now render the object
  4202.  
  4203. GetAreaObjectID:
  4204.               lda $00    ;get value saved from area parser routine
  4205.               sec
  4206.               sbc #$00   ;possibly residual code
  4207.               tay        ;save to Y
  4208. ExitDecBlock: rts
  4209.  
  4210. ;--------------------------------
  4211.  
  4212. HoleMetatiles:
  4213.       .db $87, $00, $00, $00
  4214.  
  4215. Hole_Empty:
  4216.             jsr ChkLrgObjLength          ;get lower nybble and save as length
  4217.             bcc NoWhirlP                 ;skip this part if length already loaded
  4218.             lda AreaType                 ;check for water type level
  4219.             bne NoWhirlP                 ;if not water type, skip this part
  4220.             ldx Whirlpool_Offset         ;get offset for data used by cannons and whirlpools
  4221.             jsr GetAreaObjXPosition      ;get proper vertical coordinate of where we're at
  4222.             sec
  4223.             sbc #$10                     ;subtract 16 pixels
  4224.             sta Whirlpool_LeftExtent,x   ;store as left extent of whirlpool
  4225.             lda CurrentPageLoc           ;get page location of where we're at
  4226.             sbc #$00                     ;subtract borrow
  4227.             sta Whirlpool_PageLoc,x      ;save as page location of whirlpool
  4228.             iny
  4229.             iny                          ;increment length by 2
  4230.             tya
  4231.             asl                          ;multiply by 16 to get size of whirlpool
  4232.             asl                          ;note that whirlpool will always be
  4233.             asl                          ;two blocks bigger than actual size of hole
  4234.             asl                          ;and extend one block beyond each edge
  4235.             sta Whirlpool_Length,x       ;save size of whirlpool here
  4236.             inx
  4237.             cpx #$05                     ;increment and check offset
  4238.             bcc StrWOffset               ;if not yet reached fifth whirlpool, branch to save offset
  4239.             ldx #$00                     ;otherwise initialize it
  4240. StrWOffset: stx Whirlpool_Offset         ;save new offset here
  4241. NoWhirlP:   ldx AreaType                 ;get appropriate metatile, then
  4242.             lda HoleMetatiles,x          ;render the hole proper
  4243.             ldx #$08
  4244.             ldy #$0f                     ;start at ninth row and go to bottom, run RenderUnderPart
  4245.  
  4246. ;--------------------------------
  4247.  
  4248. RenderUnderPart:
  4249.              sty AreaObjectHeight  ;store vertical length to render
  4250.              ldy MetatileBuffer,x  ;check current spot to see if there's something
  4251.              beq DrawThisRow       ;we need to keep, if nothing, go ahead
  4252.              cpy #$17
  4253.              beq WaitOneRow        ;if middle part (tree ledge), wait until next row
  4254.              cpy #$1a
  4255.              beq WaitOneRow        ;if middle part (mushroom ledge), wait until next row
  4256.              cpy #$c0
  4257.              beq DrawThisRow       ;if question block w/ coin, overwrite
  4258.              cpy #$c0
  4259.              bcs WaitOneRow        ;if any other metatile with palette 3, wait until next row
  4260.              cpy #$54
  4261.              bne DrawThisRow       ;if cracked rock terrain, overwrite
  4262.              cmp #$50
  4263.              beq WaitOneRow        ;if stem top of mushroom, wait until next row
  4264. DrawThisRow: sta MetatileBuffer,x  ;render contents of A from routine that called this
  4265. WaitOneRow:  inx
  4266.              cpx #$0d              ;stop rendering if we're at the bottom of the screen
  4267.              bcs ExitUPartR
  4268.              ldy AreaObjectHeight  ;decrement, and stop rendering if there is no more length
  4269.              dey
  4270.              bpl RenderUnderPart
  4271. ExitUPartR:  rts
  4272.  
  4273. ;--------------------------------
  4274.  
  4275. ChkLrgObjLength:
  4276.         jsr GetLrgObjAttrib     ;get row location and size (length if branched to from here)
  4277.  
  4278. ChkLrgObjFixedLength:
  4279.         lda AreaObjectLength,x  ;check for set length counter
  4280.         clc                     ;clear carry flag for not just starting
  4281.         bpl LenSet              ;if counter not set, load it, otherwise leave alone
  4282.         tya                     ;save length into length counter
  4283.         sta AreaObjectLength,x
  4284.         sec                     ;set carry flag if just starting
  4285. LenSet: rts
  4286.  
  4287.  
  4288. GetLrgObjAttrib:
  4289.       ldy AreaObjOffsetBuffer,x ;get offset saved from area obj decoding routine
  4290.       lda (AreaData),y          ;get first byte of level object
  4291.       and #%00001111
  4292.       sta $07                   ;save row location
  4293.       iny
  4294.       lda (AreaData),y          ;get next byte, save lower nybble (length or height)
  4295.       and #%00001111            ;as Y, then leave
  4296.       tay
  4297.       rts
  4298.  
  4299. ;--------------------------------
  4300.  
  4301. GetAreaObjXPosition:
  4302.       lda CurrentColumnPos    ;multiply current offset where we're at by 16
  4303.       asl                     ;to obtain horizontal pixel coordinate
  4304.       asl
  4305.       asl
  4306.       asl
  4307.       rts
  4308.  
  4309. ;--------------------------------
  4310.  
  4311. GetAreaObjYPosition:
  4312.       lda $07  ;multiply value by 16
  4313.       asl
  4314.       asl      ;this will give us the proper vertical pixel coordinate
  4315.       asl
  4316.       asl
  4317.       clc
  4318.       adc #32  ;add 32 pixels for the status bar
  4319.       rts
  4320.  
  4321. ;-------------------------------------------------------------------------------------
  4322. ;$06-$07 - used to store block buffer address used as indirect
  4323.  
  4324. BlockBufferAddr:
  4325.       .db <Block_Buffer_1, <Block_Buffer_2
  4326.       .db >Block_Buffer_1, >Block_Buffer_2
  4327.  
  4328. GetBlockBufferAddr:
  4329.       pha                      ;take value of A, save
  4330.       lsr                      ;move high nybble to low
  4331.       lsr
  4332.       lsr
  4333.       lsr
  4334.       tay                      ;use nybble as pointer to high byte
  4335.       lda BlockBufferAddr+2,y  ;of indirect here
  4336.       sta $07
  4337.       pla
  4338.       and #%00001111           ;pull from stack, mask out high nybble
  4339.       clc
  4340.       adc BlockBufferAddr,y    ;add to low byte
  4341.       sta $06                  ;store here and leave
  4342.       rts
  4343.  
  4344. ;-------------------------------------------------------------------------------------
  4345.  
  4346. ;unused space
  4347.       .db $ff, $ff
  4348.  
  4349. ;-------------------------------------------------------------------------------------
  4350.  
  4351. AreaDataOfsLoopback:
  4352.       .db $12, $36, $0e, $0e, $0e, $32, $32, $32, $0a, $26, $40
  4353.  
  4354. ;-------------------------------------------------------------------------------------
  4355.  
  4356. LoadAreaPointer:
  4357.              jsr FindAreaPointer  ;find it and store it here
  4358.              sta AreaPointer
  4359. GetAreaType: and #%01100000       ;mask out all but d6 and d5
  4360.              asl
  4361.              rol
  4362.              rol
  4363.              rol                  ;make %0xx00000 into %000000xx
  4364.              sta AreaType         ;save 2 MSB as area type
  4365.              rts
  4366.  
  4367. FindAreaPointer:
  4368.       ldy WorldNumber        ;load offset from world variable
  4369.       lda WorldAddrOffsets,y
  4370.       clc                    ;add area number used to find data
  4371.       adc AreaNumber
  4372.       tay
  4373.       lda AreaAddrOffsets,y  ;from there we have our area pointer
  4374.       rts
  4375.  
  4376.  
  4377. GetAreaDataAddrs:
  4378.             lda AreaPointer          ;use 2 MSB for Y
  4379.             jsr GetAreaType
  4380.             tay
  4381.             lda AreaPointer          ;mask out all but 5 LSB
  4382.             and #%00011111
  4383.             sta AreaAddrsLOffset     ;save as low offset
  4384.             lda EnemyAddrHOffsets,y  ;load base value with 2 altered MSB,
  4385.             clc                      ;then add base value to 5 LSB, result
  4386.             adc AreaAddrsLOffset     ;becomes offset for level data
  4387.             tay
  4388.             lda EnemyDataAddrLow,y   ;use offset to load pointer
  4389.             sta EnemyDataLow
  4390.             lda EnemyDataAddrHigh,y
  4391.             sta EnemyDataHigh
  4392.             ldy AreaType             ;use area type as offset
  4393.             lda AreaDataHOffsets,y   ;do the same thing but with different base value
  4394.             clc
  4395.             adc AreaAddrsLOffset        
  4396.             tay
  4397.             lda AreaDataAddrLow,y    ;use this offset to load another pointer
  4398.             sta AreaDataLow
  4399.             lda AreaDataAddrHigh,y
  4400.             sta AreaDataHigh
  4401.             ldy #$00                 ;load first byte of header
  4402.             lda (AreaData),y    
  4403.             pha                      ;save it to the stack for now
  4404.             and #%00000111           ;save 3 LSB for foreground scenery or bg color control
  4405.             cmp #$04
  4406.             bcc StoreFore
  4407.             sta BackgroundColorCtrl  ;if 4 or greater, save value here as bg color control
  4408.             lda #$00
  4409. StoreFore:  sta ForegroundScenery    ;if less, save value here as foreground scenery
  4410.             pla                      ;pull byte from stack and push it back
  4411.             pha
  4412.             and #%00111000           ;save player entrance control bits
  4413.             lsr                      ;shift bits over to LSBs
  4414.             lsr
  4415.             lsr
  4416.             sta PlayerEntranceCtrl       ;save value here as player entrance control
  4417.             pla                      ;pull byte again but do not push it back
  4418.             and #%11000000           ;save 2 MSB for game timer setting
  4419.             clc
  4420.             rol                      ;rotate bits over to LSBs
  4421.             rol
  4422.             rol
  4423.             sta GameTimerSetting     ;save value here as game timer setting
  4424.             iny
  4425.             lda (AreaData),y         ;load second byte of header
  4426.             pha                      ;save to stack
  4427.             and #%00001111           ;mask out all but lower nybble
  4428.             sta TerrainControl
  4429.             pla                      ;pull and push byte to copy it to A
  4430.             pha
  4431.             and #%00110000           ;save 2 MSB for background scenery type
  4432.             lsr
  4433.             lsr                      ;shift bits to LSBs
  4434.             lsr
  4435.             lsr
  4436.             sta BackgroundScenery    ;save as background scenery
  4437.             pla          
  4438.             and #%11000000
  4439.             clc
  4440.             rol                      ;rotate bits over to LSBs
  4441.             rol
  4442.             rol
  4443.             cmp #%00000011           ;if set to 3, store here
  4444.             bne StoreStyle           ;and nullify other value
  4445.             sta CloudTypeOverride    ;otherwise store value in other place
  4446.             lda #$00
  4447. StoreStyle: sta AreaStyle
  4448.             lda AreaDataLow          ;increment area data address by 2 bytes
  4449.             clc
  4450.             adc #$02
  4451.             sta AreaDataLow
  4452.             lda AreaDataHigh
  4453.             adc #$00
  4454.             sta AreaDataHigh
  4455.             rts
  4456.  
  4457. ;-------------------------------------------------------------------------------------
  4458. ;GAME LEVELS DATA
  4459.  
  4460. WorldAddrOffsets:
  4461.       .db World1Areas-AreaAddrOffsets, World2Areas-AreaAddrOffsets
  4462.       .db World3Areas-AreaAddrOffsets, World4Areas-AreaAddrOffsets
  4463.       .db World5Areas-AreaAddrOffsets, World6Areas-AreaAddrOffsets
  4464.       .db World7Areas-AreaAddrOffsets, World8Areas-AreaAddrOffsets
  4465.  
  4466. AreaAddrOffsets:
  4467. World1Areas: .db $25, $29, $c0, $26, $60
  4468. World2Areas: .db $28, $29, $01, $27, $62
  4469. World3Areas: .db $24, $35, $20, $63
  4470. World4Areas: .db $22, $29, $41, $2c, $61
  4471. World5Areas: .db $2a, $31, $26, $62
  4472. World6Areas: .db $2e, $23, $2d, $60
  4473. World7Areas: .db $33, $29, $01, $27, $64
  4474. World8Areas: .db $30, $32, $21, $65
  4475.  
  4476. ;bonus area data offsets, included here for comparison purposes
  4477. ;underground bonus area  - c2
  4478. ;cloud area 1 (day)      - 2b
  4479. ;cloud area 2 (night)    - 34
  4480. ;water area (5-2/6-2)    - 00
  4481. ;water area (8-4)        - 02
  4482. ;warp zone area (4-2)    - 2f
  4483.  
  4484. EnemyAddrHOffsets:
  4485.       .db $1f, $06, $1c, $00
  4486.  
  4487. EnemyDataAddrLow:
  4488.       .db <E_CastleArea1, <E_CastleArea2, <E_CastleArea3, <E_CastleArea4, <E_CastleArea5, <E_CastleArea6
  4489.       .db <E_GroundArea1, <E_GroundArea2, <E_GroundArea3, <E_GroundArea4, <E_GroundArea5, <E_GroundArea6
  4490.       .db <E_GroundArea7, <E_GroundArea8, <E_GroundArea9, <E_GroundArea10, <E_GroundArea11, <E_GroundArea12
  4491.       .db <E_GroundArea13, <E_GroundArea14, <E_GroundArea15, <E_GroundArea16, <E_GroundArea17, <E_GroundArea18
  4492.       .db <E_GroundArea19, <E_GroundArea20, <E_GroundArea21, <E_GroundArea22, <E_UndergroundArea1
  4493.       .db <E_UndergroundArea2, <E_UndergroundArea3, <E_WaterArea1, <E_WaterArea2, <E_WaterArea3
  4494.  
  4495. EnemyDataAddrHigh:
  4496.       .db >E_CastleArea1, >E_CastleArea2, >E_CastleArea3, >E_CastleArea4, >E_CastleArea5, >E_CastleArea6
  4497.       .db >E_GroundArea1, >E_GroundArea2, >E_GroundArea3, >E_GroundArea4, >E_GroundArea5, >E_GroundArea6
  4498.       .db >E_GroundArea7, >E_GroundArea8, >E_GroundArea9, >E_GroundArea10, >E_GroundArea11, >E_GroundArea12
  4499.       .db >E_GroundArea13, >E_GroundArea14, >E_GroundArea15, >E_GroundArea16, >E_GroundArea17, >E_GroundArea18
  4500.       .db >E_GroundArea19, >E_GroundArea20, >E_GroundArea21, >E_GroundArea22, >E_UndergroundArea1
  4501.       .db >E_UndergroundArea2, >E_UndergroundArea3, >E_WaterArea1, >E_WaterArea2, >E_WaterArea3
  4502.  
  4503. AreaDataHOffsets:
  4504.       .db $00, $03, $19, $1c
  4505.  
  4506. AreaDataAddrLow:
  4507.       .db <L_WaterArea1, <L_WaterArea2, <L_WaterArea3, <L_GroundArea1, <L_GroundArea2, <L_GroundArea3
  4508.       .db <L_GroundArea4, <L_GroundArea5, <L_GroundArea6, <L_GroundArea7, <L_GroundArea8, <L_GroundArea9
  4509.       .db <L_GroundArea10, <L_GroundArea11, <L_GroundArea12, <L_GroundArea13, <L_GroundArea14, <L_GroundArea15
  4510.       .db <L_GroundArea16, <L_GroundArea17, <L_GroundArea18, <L_GroundArea19, <L_GroundArea20, <L_GroundArea21
  4511.       .db <L_GroundArea22, <L_UndergroundArea1, <L_UndergroundArea2, <L_UndergroundArea3, <L_CastleArea1
  4512.       .db <L_CastleArea2, <L_CastleArea3, <L_CastleArea4, <L_CastleArea5, <L_CastleArea6
  4513.  
  4514. AreaDataAddrHigh:
  4515.       .db >L_WaterArea1, >L_WaterArea2, >L_WaterArea3, >L_GroundArea1, >L_GroundArea2, >L_GroundArea3
  4516.       .db >L_GroundArea4, >L_GroundArea5, >L_GroundArea6, >L_GroundArea7, >L_GroundArea8, >L_GroundArea9
  4517.       .db >L_GroundArea10, >L_GroundArea11, >L_GroundArea12, >L_GroundArea13, >L_GroundArea14, >L_GroundArea15
  4518.       .db >L_GroundArea16, >L_GroundArea17, >L_GroundArea18, >L_GroundArea19, >L_GroundArea20, >L_GroundArea21
  4519.       .db >L_GroundArea22, >L_UndergroundArea1, >L_UndergroundArea2, >L_UndergroundArea3, >L_CastleArea1
  4520.       .db >L_CastleArea2, >L_CastleArea3, >L_CastleArea4, >L_CastleArea5, >L_CastleArea6
  4521.  
  4522. ;ENEMY OBJECT DATA
  4523.  
  4524. ;level 1-4/6-4
  4525. E_CastleArea1:
  4526.       .db $76, $dd, $bb, $4c, $ea, $1d, $1b, $cc, $56, $5d
  4527.       .db $16, $9d, $c6, $1d, $36, $9d, $c9, $1d, $04, $db
  4528.       .db $49, $1d, $84, $1b, $c9, $5d, $88, $95, $0f, $08
  4529.       .db $30, $4c, $78, $2d, $a6, $28, $90, $b5
  4530.       .db $ff
  4531.  
  4532. ;level 4-4
  4533. E_CastleArea2:
  4534.       .db $0f, $03, $56, $1b, $c9, $1b, $0f, $07, $36, $1b
  4535.       .db $aa, $1b, $48, $95, $0f, $0a, $2a, $1b, $5b, $0c
  4536.       .db $78, $2d, $90, $b5
  4537.       .db $ff
  4538.  
  4539. ;level 2-4/5-4
  4540. E_CastleArea3:
  4541.       .db $0b, $8c, $4b, $4c, $77, $5f, $eb, $0c, $bd, $db
  4542.       .db $19, $9d, $75, $1d, $7d, $5b, $d9, $1d, $3d, $dd
  4543.       .db $99, $1d, $26, $9d, $5a, $2b, $8a, $2c, $ca, $1b
  4544.       .db $20, $95, $7b, $5c, $db, $4c, $1b, $cc, $3b, $cc
  4545.       .db $78, $2d, $a6, $28, $90, $b5
  4546.       .db $ff
  4547.  
  4548. ;level 3-4
  4549. E_CastleArea4:
  4550.       .db $0b, $8c, $3b, $1d, $8b, $1d, $ab, $0c, $db, $1d
  4551.       .db $0f, $03, $65, $1d, $6b, $1b, $05, $9d, $0b, $1b
  4552.       .db $05, $9b, $0b, $1d, $8b, $0c, $1b, $8c, $70, $15
  4553.       .db $7b, $0c, $db, $0c, $0f, $08, $78, $2d, $a6, $28
  4554.       .db $90, $b5
  4555.       .db $ff
  4556.  
  4557. ;level 7-4
  4558. E_CastleArea5:
  4559.       .db $27, $a9, $4b, $0c, $68, $29, $0f, $06, $77, $1b
  4560.       .db $0f, $0b, $60, $15, $4b, $8c, $78, $2d, $90, $b5
  4561.       .db $ff
  4562.  
  4563. ;level 8-4
  4564. E_CastleArea6:
  4565.       .db $0f, $03, $8e, $65, $e1, $bb, $38, $6d, $a8, $3e, $e5, $e7
  4566.       .db $0f, $08, $0b, $02, $2b, $02, $5e, $65, $e1, $bb, $0e
  4567.       .db $db, $0e, $bb, $8e, $db, $0e, $fe, $65, $ec, $0f, $0d
  4568.       .db $4e, $65, $e1, $0f, $0e, $4e, $02, $e0, $0f, $10, $fe, $e5, $e1
  4569.       .db $1b, $85, $7b, $0c, $5b, $95, $78, $2d, $90, $b5
  4570.       .db $ff
  4571.  
  4572. ;level 3-3
  4573. E_GroundArea1:
  4574.       .db $a5, $86, $e4, $28, $18, $a8, $45, $83, $69, $03
  4575.       .db $c6, $29, $9b, $83, $16, $a4, $88, $24, $e9, $28
  4576.       .db $05, $a8, $7b, $28, $24, $8f, $c8, $03, $e8, $03
  4577.       .db $46, $a8, $85, $24, $c8, $24
  4578.       .db $ff
  4579.  
  4580. ;level 8-3
  4581. E_GroundArea2:
  4582.       .db $eb, $8e, $0f, $03, $fb, $05, $17, $85, $db, $8e
  4583.       .db $0f, $07, $57, $05, $7b, $05, $9b, $80, $2b, $85
  4584.       .db $fb, $05, $0f, $0b, $1b, $05, $9b, $05
  4585.       .db $ff
  4586.  
  4587. ;level 4-1
  4588. E_GroundArea3:
  4589.       .db $2e, $c2, $66, $e2, $11, $0f, $07, $02, $11, $0f, $0c
  4590.       .db $12, $11
  4591.       .db $ff
  4592.  
  4593. ;level 6-2
  4594. E_GroundArea4:
  4595.       .db $0e, $c2, $a8, $ab, $00, $bb, $8e, $6b, $82, $de, $00, $a0
  4596.       .db $33, $86, $43, $06, $3e, $b4, $a0, $cb, $02, $0f, $07
  4597.       .db $7e, $42, $a6, $83, $02, $0f, $0a, $3b, $02, $cb, $37
  4598.       .db $0f, $0c, $e3, $0e
  4599.       .db $ff
  4600.  
  4601. ;level 3-1
  4602. E_GroundArea5:
  4603.       .db $9b, $8e, $ca, $0e, $ee, $42, $44, $5b, $86, $80, $b8
  4604.       .db $1b, $80, $50, $ba, $10, $b7, $5b, $00, $17, $85
  4605.       .db $4b, $05, $fe, $34, $40, $b7, $86, $c6, $06, $5b, $80
  4606.       .db $83, $00, $d0, $38, $5b, $8e, $8a, $0e, $a6, $00
  4607.       .db $bb, $0e, $c5, $80, $f3, $00
  4608.       .db $ff
  4609.  
  4610. ;level 1-1
  4611. E_GroundArea6:
  4612.       .db $1e, $c2, $00, $6b, $06, $8b, $86, $63, $b7, $0f, $05
  4613.       .db $03, $06, $23, $06, $4b, $b7, $bb, $00, $5b, $b7
  4614.       .db $fb, $37, $3b, $b7, $0f, $0b, $1b, $37
  4615.       .db $ff
  4616.  
  4617. ;level 1-3/5-3
  4618. E_GroundArea7:
  4619.       .db $2b, $d7, $e3, $03, $c2, $86, $e2, $06, $76, $a5
  4620.       .db $a3, $8f, $03, $86, $2b, $57, $68, $28, $e9, $28
  4621.       .db $e5, $83, $24, $8f, $36, $a8, $5b, $03
  4622.       .db $ff
  4623.  
  4624. ;level 2-3/7-3
  4625. E_GroundArea8:
  4626.       .db $0f, $02, $78, $40, $48, $ce, $f8, $c3, $f8, $c3
  4627.       .db $0f, $07, $7b, $43, $c6, $d0, $0f, $8a, $c8, $50
  4628.       .db $ff
  4629.  
  4630. ;level 2-1
  4631. E_GroundArea9:
  4632.       .db $85, $86, $0b, $80, $1b, $00, $db, $37, $77, $80
  4633.       .db $eb, $37, $fe, $2b, $20, $2b, $80, $7b, $38, $ab, $b8
  4634.       .db $77, $86, $fe, $42, $20, $49, $86, $8b, $06, $9b, $80
  4635.       .db $7b, $8e, $5b, $b7, $9b, $0e, $bb, $0e, $9b, $80
  4636. ;end of data terminator here is also used by pipe intro area
  4637. E_GroundArea10:
  4638.       .db $ff
  4639.  
  4640. ;level 5-1
  4641. E_GroundArea11:
  4642.       .db $0b, $80, $60, $38, $10, $b8, $c0, $3b, $db, $8e
  4643.       .db $40, $b8, $f0, $38, $7b, $8e, $a0, $b8, $c0, $b8
  4644.       .db $fb, $00, $a0, $b8, $30, $bb, $ee, $42, $88, $0f, $0b
  4645.       .db $2b, $0e, $67, $0e
  4646.       .db $ff
  4647.  
  4648. ;cloud level used in levels 2-1 and 5-2
  4649. E_GroundArea12:
  4650.       .db $0a, $aa, $0e, $28, $2a, $0e, $31, $88
  4651.       .db $ff
  4652.  
  4653. ;level 4-3
  4654. E_GroundArea13:
  4655.       .db $c7, $83, $d7, $03, $42, $8f, $7a, $03, $05, $a4
  4656.       .db $78, $24, $a6, $25, $e4, $25, $4b, $83, $e3, $03
  4657.       .db $05, $a4, $89, $24, $b5, $24, $09, $a4, $65, $24
  4658.       .db $c9, $24, $0f, $08, $85, $25
  4659.       .db $ff
  4660.  
  4661. ;level 6-3
  4662. E_GroundArea14:
  4663.       .db $cd, $a5, $b5, $a8, $07, $a8, $76, $28, $cc, $25
  4664.       .db $65, $a4, $a9, $24, $e5, $24, $19, $a4, $0f, $07
  4665.       .db $95, $28, $e6, $24, $19, $a4, $d7, $29, $16, $a9
  4666.       .db $58, $29, $97, $29
  4667.       .db $ff
  4668.  
  4669. ;level 6-1
  4670. E_GroundArea15:
  4671.       .db $0f, $02, $02, $11, $0f, $07, $02, $11
  4672.       .db $ff
  4673.  
  4674. ;warp zone area used in level 4-2
  4675. E_GroundArea16:
  4676.       .db $ff
  4677.  
  4678. ;level 8-1
  4679. E_GroundArea17:
  4680.       .db $2b, $82, $ab, $38, $de, $42, $e2, $1b, $b8, $eb
  4681.       .db $3b, $db, $80, $8b, $b8, $1b, $82, $fb, $b8, $7b
  4682.       .db $80, $fb, $3c, $5b, $bc, $7b, $b8, $1b, $8e, $cb
  4683.       .db $0e, $1b, $8e, $0f, $0d, $2b, $3b, $bb, $b8, $eb, $82
  4684.       .db $4b, $b8, $bb, $38, $3b, $b7, $bb, $02, $0f, $13
  4685.       .db $1b, $00, $cb, $80, $6b, $bc
  4686.       .db $ff
  4687.  
  4688. ;level 5-2
  4689. E_GroundArea18:
  4690.       .db $7b, $80, $ae, $00, $80, $8b, $8e, $e8, $05, $f9, $86
  4691.       .db $17, $86, $16, $85, $4e, $2b, $80, $ab, $8e, $87, $85
  4692.       .db $c3, $05, $8b, $82, $9b, $02, $ab, $02, $bb, $86
  4693.       .db $cb, $06, $d3, $03, $3b, $8e, $6b, $0e, $a7, $8e
  4694.       .db $ff
  4695.  
  4696. ;level 8-2
  4697. E_GroundArea19:
  4698.       .db $29, $8e, $52, $11, $83, $0e, $0f, $03, $9b, $0e
  4699.       .db $2b, $8e, $5b, $0e, $cb, $8e, $fb, $0e, $fb, $82
  4700.       .db $9b, $82, $bb, $02, $fe, $42, $e8, $bb, $8e, $0f, $0a
  4701.       .db $ab, $0e, $cb, $0e, $f9, $0e, $88, $86, $a6, $06
  4702.       .db $db, $02, $b6, $8e
  4703.       .db $ff
  4704.  
  4705. ;level 7-1
  4706. E_GroundArea20:
  4707.       .db $ab, $ce, $de, $42, $c0, $cb, $ce, $5b, $8e, $1b, $ce
  4708.       .db $4b, $85, $67, $45, $0f, $07, $2b, $00, $7b, $85
  4709.       .db $97, $05, $0f, $0a, $92, $02
  4710.       .db $ff
  4711.  
  4712. ;cloud level used in levels 3-1 and 6-2
  4713. E_GroundArea21:
  4714.       .db $0a, $aa, $0e, $24, $4a, $1e, $23, $aa
  4715.       .db $ff
  4716.  
  4717. ;level 3-2
  4718. E_GroundArea22:
  4719.       .db $1b, $80, $bb, $38, $4b, $bc, $eb, $3b, $0f, $04
  4720.       .db $2b, $00, $ab, $38, $eb, $00, $cb, $8e, $fb, $80
  4721.       .db $ab, $b8, $6b, $80, $fb, $3c, $9b, $bb, $5b, $bc
  4722.       .db $fb, $00, $6b, $b8, $fb, $38
  4723.       .db $ff
  4724.  
  4725. ;level 1-2
  4726. E_UndergroundArea1:
  4727.       .db $0b, $86, $1a, $06, $db, $06, $de, $c2, $02, $f0, $3b
  4728.       .db $bb, $80, $eb, $06, $0b, $86, $93, $06, $f0, $39
  4729.       .db $0f, $06, $60, $b8, $1b, $86, $a0, $b9, $b7, $27
  4730.       .db $bd, $27, $2b, $83, $a1, $26, $a9, $26, $ee, $25, $0b
  4731.       .db $27, $b4
  4732.       .db $ff
  4733.  
  4734. ;level 4-2
  4735. E_UndergroundArea2:
  4736.       .db $0f, $02, $1e, $2f, $60, $e0, $3a, $a5, $a7, $db, $80
  4737.       .db $3b, $82, $8b, $02, $fe, $42, $68, $70, $bb, $25, $a7
  4738.       .db $2c, $27, $b2, $26, $b9, $26, $9b, $80, $a8, $82
  4739.       .db $b5, $27, $bc, $27, $b0, $bb, $3b, $82, $87, $34
  4740.       .db $ee, $25, $6b
  4741.       .db $ff
  4742.  
  4743. ;underground bonus rooms area used in many levels
  4744. E_UndergroundArea3:
  4745.       .db $1e, $a5, $0a, $2e, $28, $27, $2e, $33, $c7, $0f, $03, $1e, $40, $07
  4746.       .db $2e, $30, $e7, $0f, $05, $1e, $24, $44, $0f, $07, $1e, $22, $6a
  4747.       .db $2e, $23, $ab, $0f, $09, $1e, $41, $68, $1e, $2a, $8a, $2e, $23, $a2
  4748.       .db $2e, $32, $ea
  4749.       .db $ff
  4750.  
  4751. ;water area used in levels 5-2 and 6-2
  4752. E_WaterArea1:
  4753.       .db $3b, $87, $66, $27, $cc, $27, $ee, $31, $87, $ee, $23, $a7
  4754.       .db $3b, $87, $db, $07
  4755.       .db $ff
  4756.  
  4757. ;level 2-2/7-2
  4758. E_WaterArea2:
  4759.       .db $0f, $01, $2e, $25, $2b, $2e, $25, $4b, $4e, $25, $cb, $6b, $07
  4760.       .db $97, $47, $e9, $87, $47, $c7, $7a, $07, $d6, $c7
  4761.       .db $78, $07, $38, $87, $ab, $47, $e3, $07, $9b, $87
  4762.       .db $0f, $09, $68, $47, $db, $c7, $3b, $c7
  4763.       .db $ff
  4764.  
  4765. ;water area used in level 8-4
  4766. E_WaterArea3:
  4767.       .db $47, $9b, $cb, $07, $fa, $1d, $86, $9b, $3a, $87
  4768.       .db $56, $07, $88, $1b, $07, $9d, $2e, $65, $f0
  4769.       .db $ff
  4770.  
  4771. ;AREA OBJECT DATA
  4772.  
  4773. ;level 1-4/6-4
  4774. L_CastleArea1:
  4775.       .db $9b, $07
  4776.       .db $05, $32, $06, $33, $07, $34, $ce, $03, $dc, $51
  4777.       .db $ee, $07, $73, $e0, $74, $0a, $7e, $06, $9e, $0a
  4778.       .db $ce, $06, $e4, $00, $e8, $0a, $fe, $0a, $2e, $89
  4779.       .db $4e, $0b, $54, $0a, $14, $8a, $c4, $0a, $34, $8a
  4780.       .db $7e, $06, $c7, $0a, $01, $e0, $02, $0a, $47, $0a
  4781.       .db $81, $60, $82, $0a, $c7, $0a, $0e, $87, $7e, $02
  4782.       .db $a7, $02, $b3, $02, $d7, $02, $e3, $02, $07, $82
  4783.       .db $13, $02, $3e, $06, $7e, $02, $ae, $07, $fe, $0a
  4784.       .db $0d, $c4, $cd, $43, $ce, $09, $de, $0b, $dd, $42
  4785.       .db $fe, $02, $5d, $c7
  4786.       .db $fd
  4787.  
  4788. ;level 4-4
  4789. L_CastleArea2:
  4790.       .db $5b, $07
  4791.       .db $05, $32, $06, $33, $07, $34, $5e, $0a, $68, $64
  4792.       .db $98, $64, $a8, $64, $ce, $06, $fe, $02, $0d, $01
  4793.       .db $1e, $0e, $7e, $02, $94, $63, $b4, $63, $d4, $63
  4794.       .db $f4, $63, $14, $e3, $2e, $0e, $5e, $02, $64, $35
  4795.       .db $88, $72, $be, $0e, $0d, $04, $ae, $02, $ce, $08
  4796.       .db $cd, $4b, $fe, $02, $0d, $05, $68, $31, $7e, $0a
  4797.       .db $96, $31, $a9, $63, $a8, $33, $d5, $30, $ee, $02
  4798.       .db $e6, $62, $f4, $61, $04, $b1, $08, $3f, $44, $33
  4799.       .db $94, $63, $a4, $31, $e4, $31, $04, $bf, $08, $3f
  4800.       .db $04, $bf, $08, $3f, $cd, $4b, $03, $e4, $0e, $03
  4801.       .db $2e, $01, $7e, $06, $be, $02, $de, $06, $fe, $0a
  4802.       .db $0d, $c4, $cd, $43, $ce, $09, $de, $0b, $dd, $42
  4803.       .db $fe, $02, $5d, $c7
  4804.       .db $fd
  4805.  
  4806. ;level 2-4/5-4
  4807. L_CastleArea3:
  4808.       .db $9b, $07
  4809.       .db $05, $32, $06, $33, $07, $34, $fe, $00, $27, $b1
  4810.       .db $65, $32, $75, $0a, $71, $00, $b7, $31, $08, $e4
  4811.       .db $18, $64, $1e, $04, $57, $3b, $bb, $0a, $17, $8a
  4812.       .db $27, $3a, $73, $0a, $7b, $0a, $d7, $0a, $e7, $3a
  4813.       .db $3b, $8a, $97, $0a, $fe, $08, $24, $8a, $2e, $00
  4814.       .db $3e, $40, $38, $64, $6f, $00, $9f, $00, $be, $43
  4815.       .db $c8, $0a, $c9, $63, $ce, $07, $fe, $07, $2e, $81
  4816.       .db $66, $42, $6a, $42, $79, $0a, $be, $00, $c8, $64
  4817.       .db $f8, $64, $08, $e4, $2e, $07, $7e, $03, $9e, $07
  4818.       .db $be, $03, $de, $07, $fe, $0a, $03, $a5, $0d, $44
  4819.       .db $cd, $43, $ce, $09, $dd, $42, $de, $0b, $fe, $02
  4820.       .db $5d, $c7
  4821.       .db $fd
  4822.  
  4823. ;level 3-4
  4824. L_CastleArea4:
  4825.       .db $9b, $07
  4826.       .db $05, $32, $06, $33, $07, $34, $fe, $06, $0c, $81
  4827.       .db $39, $0a, $5c, $01, $89, $0a, $ac, $01, $d9, $0a
  4828.       .db $fc, $01, $2e, $83, $a7, $01, $b7, $00, $c7, $01
  4829.       .db $de, $0a, $fe, $02, $4e, $83, $5a, $32, $63, $0a
  4830.       .db $69, $0a, $7e, $02, $ee, $03, $fa, $32, $03, $8a
  4831.       .db $09, $0a, $1e, $02, $ee, $03, $fa, $32, $03, $8a
  4832.       .db $09, $0a, $14, $42, $1e, $02, $7e, $0a, $9e, $07
  4833.       .db $fe, $0a, $2e, $86, $5e, $0a, $8e, $06, $be, $0a
  4834.       .db $ee, $07, $3e, $83, $5e, $07, $fe, $0a, $0d, $c4
  4835.       .db $41, $52, $51, $52, $cd, $43, $ce, $09, $de, $0b
  4836.       .db $dd, $42, $fe, $02, $5d, $c7
  4837.       .db $fd
  4838.  
  4839. ;level 7-4
  4840. L_CastleArea5:
  4841.       .db $5b, $07
  4842.       .db $05, $32, $06, $33, $07, $34, $fe, $0a, $ae, $86
  4843.       .db $be, $07, $fe, $02, $0d, $02, $27, $32, $46, $61
  4844.       .db $55, $62, $5e, $0e, $1e, $82, $68, $3c, $74, $3a
  4845.       .db $7d, $4b, $5e, $8e, $7d, $4b, $7e, $82, $84, $62
  4846.       .db $94, $61, $a4, $31, $bd, $4b, $ce, $06, $fe, $02
  4847.       .db $0d, $06, $34, $31, $3e, $0a, $64, $32, $75, $0a
  4848.       .db $7b, $61, $a4, $33, $ae, $02, $de, $0e, $3e, $82
  4849.       .db $64, $32, $78, $32, $b4, $36, $c8, $36, $dd, $4b
  4850.       .db $44, $b2, $58, $32, $94, $63, $a4, $3e, $ba, $30
  4851.       .db $c9, $61, $ce, $06, $dd, $4b, $ce, $86, $dd, $4b
  4852.       .db $fe, $02, $2e, $86, $5e, $02, $7e, $06, $fe, $02
  4853.       .db $1e, $86, $3e, $02, $5e, $06, $7e, $02, $9e, $06
  4854.       .db $fe, $0a, $0d, $c4, $cd, $43, $ce, $09, $de, $0b
  4855.       .db $dd, $42, $fe, $02, $5d, $c7
  4856.       .db $fd
  4857.  
  4858. ;level 8-4
  4859. L_CastleArea6:
  4860.       .db $5b, $06
  4861.       .db $05, $32, $06, $33, $07, $34, $5e, $0a, $ae, $02
  4862.       .db $0d, $01, $39, $73, $0d, $03, $39, $7b, $4d, $4b
  4863.       .db $de, $06, $1e, $8a, $ae, $06, $c4, $33, $16, $fe
  4864.       .db $a5, $77, $fe, $02, $fe, $82, $0d, $07, $39, $73
  4865.       .db $a8, $74, $ed, $4b, $49, $fb, $e8, $74, $fe, $0a
  4866.       .db $2e, $82, $67, $02, $84, $7a, $87, $31, $0d, $0b
  4867.       .db $fe, $02, $0d, $0c, $39, $73, $5e, $06, $c6, $76
  4868.       .db $45, $ff, $be, $0a, $dd, $48, $fe, $06, $3d, $cb
  4869.       .db $46, $7e, $ad, $4a, $fe, $82, $39, $f3, $a9, $7b
  4870.       .db $4e, $8a, $9e, $07, $fe, $0a, $0d, $c4, $cd, $43
  4871.       .db $ce, $09, $de, $0b, $dd, $42, $fe, $02, $5d, $c7
  4872.       .db $fd
  4873.  
  4874. ;level 3-3
  4875. L_GroundArea1:
  4876.       .db $94, $11
  4877.       .db $0f, $26, $fe, $10, $28, $94, $65, $15, $eb, $12
  4878.       .db $fa, $41, $4a, $96, $54, $40, $a4, $42, $b7, $13
  4879.       .db $e9, $19, $f5, $15, $11, $80, $47, $42, $71, $13
  4880.       .db $80, $41, $15, $92, $1b, $1f, $24, $40, $55, $12
  4881.       .db $64, $40, $95, $12, $a4, $40, $d2, $12, $e1, $40
  4882.       .db $13, $c0, $2c, $17, $2f, $12, $49, $13, $83, $40
  4883.       .db $9f, $14, $a3, $40, $17, $92, $83, $13, $92, $41
  4884.       .db $b9, $14, $c5, $12, $c8, $40, $d4, $40, $4b, $92
  4885.       .db $78, $1b, $9c, $94, $9f, $11, $df, $14, $fe, $11
  4886.       .db $7d, $c1, $9e, $42, $cf, $20
  4887.       .db $fd
  4888.  
  4889. ;level 8-3
  4890. L_GroundArea2:
  4891.       .db $90, $b1
  4892.       .db $0f, $26, $29, $91, $7e, $42, $fe, $40, $28, $92
  4893.       .db $4e, $42, $2e, $c0, $57, $73, $c3, $25, $c7, $27
  4894.       .db $23, $84, $33, $20, $5c, $01, $77, $63, $88, $62
  4895.       .db $99, $61, $aa, $60, $bc, $01, $ee, $42, $4e, $c0
  4896.       .db $69, $11, $7e, $42, $de, $40, $f8, $62, $0e, $c2
  4897.       .db $ae, $40, $d7, $63, $e7, $63, $33, $a7, $37, $27
  4898.       .db $43, $04, $cc, $01, $e7, $73, $0c, $81, $3e, $42
  4899.       .db $0d, $0a, $5e, $40, $88, $72, $be, $42, $e7, $87
  4900.       .db $fe, $40, $39, $e1, $4e, $00, $69, $60, $87, $60
  4901.       .db $a5, $60, $c3, $31, $fe, $31, $6d, $c1, $be, $42
  4902.       .db $ef, $20
  4903.       .db $fd
  4904.  
  4905. ;level 4-1
  4906. L_GroundArea3:
  4907.       .db $52, $21
  4908.       .db $0f, $20, $6e, $40, $58, $f2, $93, $01, $97, $00
  4909.       .db $0c, $81, $97, $40, $a6, $41, $c7, $40, $0d, $04
  4910.       .db $03, $01, $07, $01, $23, $01, $27, $01, $ec, $03
  4911.       .db $ac, $f3, $c3, $03, $78, $e2, $94, $43, $47, $f3
  4912.       .db $74, $43, $47, $fb, $74, $43, $2c, $f1, $4c, $63
  4913.       .db $47, $00, $57, $21, $5c, $01, $7c, $72, $39, $f1
  4914.       .db $ec, $02, $4c, $81, $d8, $62, $ec, $01, $0d, $0d
  4915.       .db $0f, $38, $c7, $07, $ed, $4a, $1d, $c1, $5f, $26
  4916.       .db $fd
  4917.  
  4918. ;level 6-2
  4919. L_GroundArea4:
  4920.       .db $54, $21
  4921.       .db $0f, $26, $a7, $22, $37, $fb, $73, $20, $83, $07
  4922.       .db $87, $02, $93, $20, $c7, $73, $04, $f1, $06, $31
  4923.       .db $39, $71, $59, $71, $e7, $73, $37, $a0, $47, $04
  4924.       .db $86, $7c, $e5, $71, $e7, $31, $33, $a4, $39, $71
  4925.       .db $a9, $71, $d3, $23, $08, $f2, $13, $05, $27, $02
  4926.       .db $49, $71, $75, $75, $e8, $72, $67, $f3, $99, $71
  4927.       .db $e7, $20, $f4, $72, $f7, $31, $17, $a0, $33, $20
  4928.       .db $39, $71, $73, $28, $bc, $05, $39, $f1, $79, $71
  4929.       .db $a6, $21, $c3, $06, $d3, $20, $dc, $00, $fc, $00
  4930.       .db $07, $a2, $13, $21, $5f, $32, $8c, $00, $98, $7a
  4931.       .db $c7, $63, $d9, $61, $03, $a2, $07, $22, $74, $72
  4932.       .db $77, $31, $e7, $73, $39, $f1, $58, $72, $77, $73
  4933.       .db $d8, $72, $7f, $b1, $97, $73, $b6, $64, $c5, $65
  4934.       .db $d4, $66, $e3, $67, $f3, $67, $8d, $c1, $cf, $26
  4935.       .db $fd
  4936.  
  4937. ;level 3-1
  4938. L_GroundArea5:
  4939.       .db $52, $31
  4940.       .db $0f, $20, $6e, $66, $07, $81, $36, $01, $66, $00
  4941.       .db $a7, $22, $08, $f2, $67, $7b, $dc, $02, $98, $f2
  4942.       .db $d7, $20, $39, $f1, $9f, $33, $dc, $27, $dc, $57
  4943.       .db $23, $83, $57, $63, $6c, $51, $87, $63, $99, $61
  4944.       .db $a3, $06, $b3, $21, $77, $f3, $f3, $21, $f7, $2a
  4945.       .db $13, $81, $23, $22, $53, $00, $63, $22, $e9, $0b
  4946.       .db $0c, $83, $13, $21, $16, $22, $33, $05, $8f, $35
  4947.       .db $ec, $01, $63, $a0, $67, $20, $73, $01, $77, $01
  4948.       .db $83, $20, $87, $20, $b3, $20, $b7, $20, $c3, $01
  4949.       .db $c7, $00, $d3, $20, $d7, $20, $67, $a0, $77, $07
  4950.       .db $87, $22, $e8, $62, $f5, $65, $1c, $82, $7f, $38
  4951.       .db $8d, $c1, $cf, $26
  4952.       .db $fd
  4953.  
  4954. ;level 1-1
  4955. L_GroundArea6:
  4956.       .db $50, $21
  4957.       .db $07, $81, $47, $24, $57, $00, $63, $01, $77, $01
  4958.       .db $c9, $71, $68, $f2, $e7, $73, $97, $fb, $06, $83
  4959.       .db $5c, $01, $d7, $22, $e7, $00, $03, $a7, $6c, $02
  4960.       .db $b3, $22, $e3, $01, $e7, $07, $47, $a0, $57, $06
  4961.       .db $a7, $01, $d3, $00, $d7, $01, $07, $81, $67, $20
  4962.       .db $93, $22, $03, $a3, $1c, $61, $17, $21, $6f, $33
  4963.       .db $c7, $63, $d8, $62, $e9, $61, $fa, $60, $4f, $b3
  4964.       .db $87, $63, $9c, $01, $b7, $63, $c8, $62, $d9, $61
  4965.       .db $ea, $60, $39, $f1, $87, $21, $a7, $01, $b7, $20
  4966.       .db $39, $f1, $5f, $38, $6d, $c1, $af, $26
  4967.       .db $fd
  4968.  
  4969. ;level 1-3/5-3
  4970. L_GroundArea7:
  4971.       .db $90, $11
  4972.       .db $0f, $26, $fe, $10, $2a, $93, $87, $17, $a3, $14
  4973.       .db $b2, $42, $0a, $92, $19, $40, $36, $14, $50, $41
  4974.       .db $82, $16, $2b, $93, $24, $41, $bb, $14, $b8, $00
  4975.       .db $c2, $43, $c3, $13, $1b, $94, $67, $12, $c4, $15
  4976.       .db $53, $c1, $d2, $41, $12, $c1, $29, $13, $85, $17
  4977.       .db $1b, $92, $1a, $42, $47, $13, $83, $41, $a7, $13
  4978.       .db $0e, $91, $a7, $63, $b7, $63, $c5, $65, $d5, $65
  4979.       .db $dd, $4a, $e3, $67, $f3, $67, $8d, $c1, $ae, $42
  4980.       .db $df, $20
  4981.       .db $fd
  4982.  
  4983. ;level 2-3/7-3
  4984. L_GroundArea8:
  4985.       .db $90, $11
  4986.       .db $0f, $26, $6e, $10, $8b, $17, $af, $32, $d8, $62
  4987.       .db $e8, $62, $fc, $3f, $ad, $c8, $f8, $64, $0c, $be
  4988.       .db $43, $43, $f8, $64, $0c, $bf, $73, $40, $84, $40
  4989.       .db $93, $40, $a4, $40, $b3, $40, $f8, $64, $48, $e4
  4990.       .db $5c, $39, $83, $40, $92, $41, $b3, $40, $f8, $64
  4991.       .db $48, $e4, $5c, $39, $f8, $64, $13, $c2, $37, $65
  4992.       .db $4c, $24, $63, $00, $97, $65, $c3, $42, $0b, $97
  4993.       .db $ac, $32, $f8, $64, $0c, $be, $53, $45, $9d, $48
  4994.       .db $f8, $64, $2a, $e2, $3c, $47, $56, $43, $ba, $62
  4995.       .db $f8, $64, $0c, $b7, $88, $64, $bc, $31, $d4, $45
  4996.       .db $fc, $31, $3c, $b1, $78, $64, $8c, $38, $0b, $9c
  4997.       .db $1a, $33, $18, $61, $28, $61, $39, $60, $5d, $4a
  4998.       .db $ee, $11, $0f, $b8, $1d, $c1, $3e, $42, $6f, $20
  4999.       .db $fd
  5000.  
  5001. ;level 2-1
  5002. L_GroundArea9:
  5003.       .db $52, $31
  5004.       .db $0f, $20, $6e, $40, $f7, $20, $07, $84, $17, $20
  5005.       .db $4f, $34, $c3, $03, $c7, $02, $d3, $22, $27, $e3
  5006.       .db $39, $61, $e7, $73, $5c, $e4, $57, $00, $6c, $73
  5007.       .db $47, $a0, $53, $06, $63, $22, $a7, $73, $fc, $73
  5008.       .db $13, $a1, $33, $05, $43, $21, $5c, $72, $c3, $23
  5009.       .db $cc, $03, $77, $fb, $ac, $02, $39, $f1, $a7, $73
  5010.       .db $d3, $04, $e8, $72, $e3, $22, $26, $f4, $bc, $02
  5011.       .db $8c, $81, $a8, $62, $17, $87, $43, $24, $a7, $01
  5012.       .db $c3, $04, $08, $f2, $97, $21, $a3, $02, $c9, $0b
  5013.       .db $e1, $69, $f1, $69, $8d, $c1, $cf, $26
  5014.       .db $fd
  5015.  
  5016. ;pipe intro area
  5017. L_GroundArea10:
  5018.       .db $38, $11
  5019.       .db $0f, $26, $ad, $40, $3d, $c7
  5020.       .db $fd
  5021.  
  5022. ;level 5-1
  5023. L_GroundArea11:
  5024.       .db $95, $b1
  5025.       .db $0f, $26, $0d, $02, $c8, $72, $1c, $81, $38, $72
  5026.       .db $0d, $05, $97, $34, $98, $62, $a3, $20, $b3, $06
  5027.       .db $c3, $20, $cc, $03, $f9, $91, $2c, $81, $48, $62
  5028.       .db $0d, $09, $37, $63, $47, $03, $57, $21, $8c, $02
  5029.       .db $c5, $79, $c7, $31, $f9, $11, $39, $f1, $a9, $11
  5030.       .db $6f, $b4, $d3, $65, $e3, $65, $7d, $c1, $bf, $26
  5031.       .db $fd
  5032.  
  5033. ;cloud level used in levels 2-1 and 5-2
  5034. L_GroundArea12:
  5035.       .db $00, $c1
  5036.       .db $4c, $00, $f4, $4f, $0d, $02, $02, $42, $43, $4f
  5037.       .db $52, $c2, $de, $00, $5a, $c2, $4d, $c7
  5038.       .db $fd
  5039.  
  5040. ;level 4-3
  5041. L_GroundArea13:
  5042.       .db $90, $51
  5043.       .db $0f, $26, $ee, $10, $0b, $94, $33, $14, $42, $42
  5044.       .db $77, $16, $86, $44, $02, $92, $4a, $16, $69, $42
  5045.       .db $73, $14, $b0, $00, $c7, $12, $05, $c0, $1c, $17
  5046.       .db $1f, $11, $36, $12, $8f, $14, $91, $40, $1b, $94
  5047.       .db $35, $12, $34, $42, $60, $42, $61, $12, $87, $12
  5048.       .db $96, $40, $a3, $14, $1c, $98, $1f, $11, $47, $12
  5049.       .db $9f, $15, $cc, $15, $cf, $11, $05, $c0, $1f, $15
  5050.       .db $39, $12, $7c, $16, $7f, $11, $82, $40, $98, $12
  5051.       .db $df, $15, $16, $c4, $17, $14, $54, $12, $9b, $16
  5052.       .db $28, $94, $ce, $01, $3d, $c1, $5e, $42, $8f, $20
  5053.       .db $fd
  5054.  
  5055. ;level 6-3
  5056. L_GroundArea14:
  5057.       .db $97, $11
  5058.       .db $0f, $26, $fe, $10, $2b, $92, $57, $12, $8b, $12
  5059.       .db $c0, $41, $f7, $13, $5b, $92, $69, $0b, $bb, $12
  5060.       .db $b2, $46, $19, $93, $71, $00, $17, $94, $7c, $14
  5061.       .db $7f, $11, $93, $41, $bf, $15, $fc, $13, $ff, $11
  5062.       .db $2f, $95, $50, $42, $51, $12, $58, $14, $a6, $12
  5063.       .db $db, $12, $1b, $93, $46, $43, $7b, $12, $8d, $49
  5064.       .db $b7, $14, $1b, $94, $49, $0b, $bb, $12, $fc, $13
  5065.       .db $ff, $12, $03, $c1, $2f, $15, $43, $12, $4b, $13
  5066.       .db $77, $13, $9d, $4a, $15, $c1, $a1, $41, $c3, $12
  5067.       .db $fe, $01, $7d, $c1, $9e, $42, $cf, $20
  5068.       .db $fd
  5069.  
  5070. ;level 6-1
  5071. L_GroundArea15:
  5072.       .db $52, $21
  5073.       .db $0f, $20, $6e, $44, $0c, $f1, $4c, $01, $aa, $35
  5074.       .db $d9, $34, $ee, $20, $08, $b3, $37, $32, $43, $04
  5075.       .db $4e, $21, $53, $20, $7c, $01, $97, $21, $b7, $07
  5076.       .db $9c, $81, $e7, $42, $5f, $b3, $97, $63, $ac, $02
  5077.       .db $c5, $41, $49, $e0, $58, $61, $76, $64, $85, $65
  5078.       .db $94, $66, $a4, $22, $a6, $03, $c8, $22, $dc, $02
  5079.       .db $68, $f2, $96, $42, $13, $82, $17, $02, $af, $34
  5080.       .db $f6, $21, $fc, $06, $26, $80, $2a, $24, $36, $01
  5081.       .db $8c, $00, $ff, $35, $4e, $a0, $55, $21, $77, $20
  5082.       .db $87, $07, $89, $22, $ae, $21, $4c, $82, $9f, $34
  5083.       .db $ec, $01, $03, $e7, $13, $67, $8d, $4a, $ad, $41
  5084.       .db $0f, $a6
  5085.       .db $fd
  5086.  
  5087. ;warp zone area used in level 4-2
  5088. L_GroundArea16:
  5089.       .db $10, $51
  5090.       .db $4c, $00, $c7, $12, $c6, $42, $03, $92, $02, $42
  5091.       .db $29, $12, $63, $12, $62, $42, $69, $14, $a5, $12
  5092.       .db $a4, $42, $e2, $14, $e1, $44, $f8, $16, $37, $c1
  5093.       .db $8f, $38, $02, $bb, $28, $7a, $68, $7a, $a8, $7a
  5094.       .db $e0, $6a, $f0, $6a, $6d, $c5
  5095.       .db $fd
  5096.  
  5097. ;level 8-1
  5098. L_GroundArea17:
  5099.       .db $92, $31
  5100.       .db $0f, $20, $6e, $40, $0d, $02, $37, $73, $ec, $00
  5101.       .db $0c, $80, $3c, $00, $6c, $00, $9c, $00, $06, $c0
  5102.       .db $c7, $73, $06, $83, $28, $72, $96, $40, $e7, $73
  5103.       .db $26, $c0, $87, $7b, $d2, $41, $39, $f1, $c8, $f2
  5104.       .db $97, $e3, $a3, $23, $e7, $02, $e3, $07, $f3, $22
  5105.       .db $37, $e3, $9c, $00, $bc, $00, $ec, $00, $0c, $80
  5106.       .db $3c, $00, $86, $21, $a6, $06, $b6, $24, $5c, $80
  5107.       .db $7c, $00, $9c, $00, $29, $e1, $dc, $05, $f6, $41
  5108.       .db $dc, $80, $e8, $72, $0c, $81, $27, $73, $4c, $01
  5109.       .db $66, $74, $0d, $11, $3f, $35, $b6, $41, $2c, $82
  5110.       .db $36, $40, $7c, $02, $86, $40, $f9, $61, $39, $e1
  5111.       .db $ac, $04, $c6, $41, $0c, $83, $16, $41, $88, $f2
  5112.       .db $39, $f1, $7c, $00, $89, $61, $9c, $00, $a7, $63
  5113.       .db $bc, $00, $c5, $65, $dc, $00, $e3, $67, $f3, $67
  5114.       .db $8d, $c1, $cf, $26
  5115.       .db $fd
  5116.  
  5117. ;level 5-2
  5118. L_GroundArea18:
  5119.       .db $55, $b1
  5120.       .db $0f, $26, $cf, $33, $07, $b2, $15, $11, $52, $42
  5121.       .db $99, $0b, $ac, $02, $d3, $24, $d6, $42, $d7, $25
  5122.       .db $23, $84, $cf, $33, $07, $e3, $19, $61, $78, $7a
  5123.       .db $ef, $33, $2c, $81, $46, $64, $55, $65, $65, $65
  5124.       .db $ec, $74, $47, $82, $53, $05, $63, $21, $62, $41
  5125.       .db $96, $22, $9a, $41, $cc, $03, $b9, $91, $39, $f1
  5126.       .db $63, $26, $67, $27, $d3, $06, $fc, $01, $18, $e2
  5127.       .db $d9, $07, $e9, $04, $0c, $86, $37, $22, $93, $24
  5128.       .db $87, $84, $ac, $02, $c2, $41, $c3, $23, $d9, $71
  5129.       .db $fc, $01, $7f, $b1, $9c, $00, $a7, $63, $b6, $64
  5130.       .db $cc, $00, $d4, $66, $e3, $67, $f3, $67, $8d, $c1
  5131.       .db $cf, $26
  5132.       .db $fd
  5133.  
  5134. ;level 8-2
  5135. L_GroundArea19:
  5136.       .db $50, $b1
  5137.       .db $0f, $26, $fc, $00, $1f, $b3, $5c, $00, $65, $65
  5138.       .db $74, $66, $83, $67, $93, $67, $dc, $73, $4c, $80
  5139.       .db $b3, $20, $c9, $0b, $c3, $08, $d3, $2f, $dc, $00
  5140.       .db $2c, $80, $4c, $00, $8c, $00, $d3, $2e, $ed, $4a
  5141.       .db $fc, $00, $d7, $a1, $ec, $01, $4c, $80, $59, $11
  5142.       .db $d8, $11, $da, $10, $37, $a0, $47, $04, $99, $11
  5143.       .db $e7, $21, $3a, $90, $67, $20, $76, $10, $77, $60
  5144.       .db $87, $07, $d8, $12, $39, $f1, $ac, $00, $e9, $71
  5145.       .db $0c, $80, $2c, $00, $4c, $05, $c7, $7b, $39, $f1
  5146.       .db $ec, $00, $f9, $11, $0c, $82, $6f, $34, $f8, $11
  5147.       .db $fa, $10, $7f, $b2, $ac, $00, $b6, $64, $cc, $01
  5148.       .db $e3, $67, $f3, $67, $8d, $c1, $cf, $26
  5149.       .db $fd
  5150.  
  5151. ;level 7-1
  5152. L_GroundArea20:
  5153.       .db $52, $b1
  5154.       .db $0f, $20, $6e, $45, $39, $91, $b3, $04, $c3, $21
  5155.       .db $c8, $11, $ca, $10, $49, $91, $7c, $73, $e8, $12
  5156.       .db $88, $91, $8a, $10, $e7, $21, $05, $91, $07, $30
  5157.       .db $17, $07, $27, $20, $49, $11, $9c, $01, $c8, $72
  5158.       .db $23, $a6, $27, $26, $d3, $03, $d8, $7a, $89, $91
  5159.       .db $d8, $72, $39, $f1, $a9, $11, $09, $f1, $63, $24
  5160.       .db $67, $24, $d8, $62, $28, $91, $2a, $10, $56, $21
  5161.       .db $70, $04, $79, $0b, $8c, $00, $94, $21, $9f, $35
  5162.       .db $2f, $b8, $3d, $c1, $7f, $26
  5163.       .db $fd
  5164.  
  5165. ;cloud level used in levels 3-1 and 6-2
  5166. L_GroundArea21:
  5167.       .db $06, $c1
  5168.       .db $4c, $00, $f4, $4f, $0d, $02, $06, $20, $24, $4f
  5169.       .db $35, $a0, $36, $20, $53, $46, $d5, $20, $d6, $20
  5170.       .db $34, $a1, $73, $49, $74, $20, $94, $20, $b4, $20
  5171.       .db $d4, $20, $f4, $20, $2e, $80, $59, $42, $4d, $c7
  5172.       .db $fd
  5173.  
  5174. ;level 3-2
  5175. L_GroundArea22:
  5176.       .db $96, $31
  5177.       .db $0f, $26, $0d, $03, $1a, $60, $77, $42, $c4, $00
  5178.       .db $c8, $62, $b9, $e1, $d3, $06, $d7, $07, $f9, $61
  5179.       .db $0c, $81, $4e, $b1, $8e, $b1, $bc, $01, $e4, $50
  5180.       .db $e9, $61, $0c, $81, $0d, $0a, $84, $43, $98, $72
  5181.       .db $0d, $0c, $0f, $38, $1d, $c1, $5f, $26
  5182.       .db $fd
  5183.  
  5184. ;level 1-2
  5185. L_UndergroundArea1:
  5186.       .db $48, $0f
  5187.       .db $0e, $01, $5e, $02, $a7, $00, $bc, $73, $1a, $e0
  5188.       .db $39, $61, $58, $62, $77, $63, $97, $63, $b8, $62
  5189.       .db $d6, $07, $f8, $62, $19, $e1, $75, $52, $86, $40
  5190.       .db $87, $50, $95, $52, $93, $43, $a5, $21, $c5, $52
  5191.       .db $d6, $40, $d7, $20, $e5, $06, $e6, $51, $3e, $8d
  5192.       .db $5e, $03, $67, $52, $77, $52, $7e, $02, $9e, $03
  5193.       .db $a6, $43, $a7, $23, $de, $05, $fe, $02, $1e, $83
  5194.       .db $33, $54, $46, $40, $47, $21, $56, $04, $5e, $02
  5195.       .db $83, $54, $93, $52, $96, $07, $97, $50, $be, $03
  5196.       .db $c7, $23, $fe, $02, $0c, $82, $43, $45, $45, $24
  5197.       .db $46, $24, $90, $08, $95, $51, $78, $fa, $d7, $73
  5198.       .db $39, $f1, $8c, $01, $a8, $52, $b8, $52, $cc, $01
  5199.       .db $5f, $b3, $97, $63, $9e, $00, $0e, $81, $16, $24
  5200.       .db $66, $04, $8e, $00, $fe, $01, $08, $d2, $0e, $06
  5201.       .db $6f, $47, $9e, $0f, $0e, $82, $2d, $47, $28, $7a
  5202.       .db $68, $7a, $a8, $7a, $ae, $01, $de, $0f, $6d, $c5
  5203.       .db $fd
  5204.  
  5205. ;level 4-2
  5206. L_UndergroundArea2:
  5207.       .db $48, $0f
  5208.       .db $0e, $01, $5e, $02, $bc, $01, $fc, $01, $2c, $82
  5209.       .db $41, $52, $4e, $04, $67, $25, $68, $24, $69, $24
  5210.       .db $ba, $42, $c7, $04, $de, $0b, $b2, $87, $fe, $02
  5211.       .db $2c, $e1, $2c, $71, $67, $01, $77, $00, $87, $01
  5212.       .db $8e, $00, $ee, $01, $f6, $02, $03, $85, $05, $02
  5213.       .db $13, $21, $16, $02, $27, $02, $2e, $02, $88, $72
  5214.       .db $c7, $20, $d7, $07, $e4, $76, $07, $a0, $17, $06
  5215.       .db $48, $7a, $76, $20, $98, $72, $79, $e1, $88, $62
  5216.       .db $9c, $01, $b7, $73, $dc, $01, $f8, $62, $fe, $01
  5217.       .db $08, $e2, $0e, $00, $6e, $02, $73, $20, $77, $23
  5218.       .db $83, $04, $93, $20, $ae, $00, $fe, $0a, $0e, $82
  5219.       .db $39, $71, $a8, $72, $e7, $73, $0c, $81, $8f, $32
  5220.       .db $ae, $00, $fe, $04, $04, $d1, $17, $04, $26, $49
  5221.       .db $27, $29, $df, $33, $fe, $02, $44, $f6, $7c, $01
  5222.       .db $8e, $06, $bf, $47, $ee, $0f, $4d, $c7, $0e, $82
  5223.       .db $68, $7a, $ae, $01, $de, $0f, $6d, $c5
  5224.       .db $fd
  5225.  
  5226. ;underground bonus rooms area used in many levels
  5227. L_UndergroundArea3:
  5228.       .db $48, $01
  5229.       .db $0e, $01, $00, $5a, $3e, $06, $45, $46, $47, $46
  5230.       .db $53, $44, $ae, $01, $df, $4a, $4d, $c7, $0e, $81
  5231.       .db $00, $5a, $2e, $04, $37, $28, $3a, $48, $46, $47
  5232.       .db $c7, $07, $ce, $0f, $df, $4a, $4d, $c7, $0e, $81
  5233.       .db $00, $5a, $33, $53, $43, $51, $46, $40, $47, $50
  5234.       .db $53, $04, $55, $40, $56, $50, $62, $43, $64, $40
  5235.       .db $65, $50, $71, $41, $73, $51, $83, $51, $94, $40
  5236.       .db $95, $50, $a3, $50, $a5, $40, $a6, $50, $b3, $51
  5237.       .db $b6, $40, $b7, $50, $c3, $53, $df, $4a, $4d, $c7
  5238.       .db $0e, $81, $00, $5a, $2e, $02, $36, $47, $37, $52
  5239.       .db $3a, $49, $47, $25, $a7, $52, $d7, $04, $df, $4a
  5240.       .db $4d, $c7, $0e, $81, $00, $5a, $3e, $02, $44, $51
  5241.       .db $53, $44, $54, $44, $55, $24, $a1, $54, $ae, $01
  5242.       .db $b4, $21, $df, $4a, $e5, $07, $4d, $c7
  5243.       .db $fd
  5244.  
  5245. ;water area used in levels 5-2 and 6-2
  5246. L_WaterArea1:
  5247.       .db $41, $01
  5248.       .db $b4, $34, $c8, $52, $f2, $51, $47, $d3, $6c, $03
  5249.       .db $65, $49, $9e, $07, $be, $01, $cc, $03, $fe, $07
  5250.       .db $0d, $c9, $1e, $01, $6c, $01, $62, $35, $63, $53
  5251.       .db $8a, $41, $ac, $01, $b3, $53, $e9, $51, $26, $c3
  5252.       .db $27, $33, $63, $43, $64, $33, $ba, $60, $c9, $61
  5253.       .db $ce, $0b, $e5, $09, $ee, $0f, $7d, $ca, $7d, $47
  5254.       .db $fd
  5255.  
  5256. ;level 2-2/7-2
  5257. L_WaterArea2:
  5258.       .db $41, $01
  5259.       .db $b8, $52, $ea, $41, $27, $b2, $b3, $42, $16, $d4
  5260.       .db $4a, $42, $a5, $51, $a7, $31, $27, $d3, $08, $e2
  5261.       .db $16, $64, $2c, $04, $38, $42, $76, $64, $88, $62
  5262.       .db $de, $07, $fe, $01, $0d, $c9, $23, $32, $31, $51
  5263.       .db $98, $52, $0d, $c9, $59, $42, $63, $53, $67, $31
  5264.       .db $14, $c2, $36, $31, $87, $53, $17, $e3, $29, $61
  5265.       .db $30, $62, $3c, $08, $42, $37, $59, $40, $6a, $42
  5266.       .db $99, $40, $c9, $61, $d7, $63, $39, $d1, $58, $52
  5267.       .db $c3, $67, $d3, $31, $dc, $06, $f7, $42, $fa, $42
  5268.       .db $23, $b1, $43, $67, $c3, $34, $c7, $34, $d1, $51
  5269.       .db $43, $b3, $47, $33, $9a, $30, $a9, $61, $b8, $62
  5270.       .db $be, $0b, $d5, $09, $de, $0f, $0d, $ca, $7d, $47
  5271.       .db $fd
  5272.  
  5273. ;water area used in level 8-4
  5274. L_WaterArea3:
  5275.       .db $49, $0f
  5276.       .db $1e, $01, $39, $73, $5e, $07, $ae, $0b, $1e, $82
  5277.       .db $6e, $88, $9e, $02, $0d, $04, $2e, $0b, $45, $09
  5278.       .db $4e, $0f, $ed, $47
  5279.       .db $fd
  5280.  
  5281. ;-------------------------------------------------------------------------------------
  5282.  
  5283. ;unused space
  5284.       .db $ff
  5285.  
  5286. ;-------------------------------------------------------------------------------------
  5287.  
  5288. ;indirect jump routine called when
  5289. ;$0770 is set to 1
  5290. GameMode:
  5291.       lda OperMode_Task
  5292.       jsr JumpEngine
  5293.  
  5294.       .dw InitializeArea
  5295.       .dw ScreenRoutines
  5296.       .dw SecondaryGameSetup
  5297.       .dw GameCoreRoutine
  5298.  
  5299. ;-------------------------------------------------------------------------------------
  5300.  
  5301. GameCoreRoutine:
  5302.       ldx CurrentPlayer          ;get which player is on the screen
  5303.       lda SavedJoypadBits,x      ;use appropriate player's controller bits
  5304.       sta SavedJoypadBits        ;as the master controller bits
  5305.       jsr GameRoutines           ;execute one of many possible subs
  5306.       lda OperMode_Task          ;check major task of operating mode
  5307.       cmp #$03                   ;if we are supposed to be here,
  5308.       bcs GameEngine             ;branch to the game engine itself
  5309.       rts
  5310.  
  5311. GameEngine:
  5312.               jsr ProcFireball_Bubble    ;process fireballs and air bubbles
  5313.               ldx #$00
  5314. ProcELoop:    stx ObjectOffset           ;put incremented offset in X as enemy object offset
  5315.               jsr EnemiesAndLoopsCore    ;process enemy objects
  5316.               jsr FloateyNumbersRoutine  ;process floatey numbers
  5317.               inx
  5318.               cpx #$06                   ;do these two subroutines until the whole buffer is done
  5319.               bne ProcELoop
  5320.               jsr GetPlayerOffscreenBits ;get offscreen bits for player object
  5321.               jsr RelativePlayerPosition ;get relative coordinates for player object
  5322.               jsr PlayerGfxHandler       ;draw the player
  5323.               jsr BlockObjMT_Updater     ;replace block objects with metatiles if necessary
  5324.               ldx #$01
  5325.               stx ObjectOffset           ;set offset for second
  5326.               jsr BlockObjectsCore       ;process second block object
  5327.               dex
  5328.               stx ObjectOffset           ;set offset for first
  5329.               jsr BlockObjectsCore       ;process first block object
  5330.               jsr MiscObjectsCore        ;process misc objects (hammer, jumping coins)
  5331.               jsr ProcessCannons         ;process bullet bill cannons
  5332.               jsr ProcessWhirlpools      ;process whirlpools
  5333.               jsr FlagpoleRoutine        ;process the flagpole
  5334.               jsr RunGameTimer           ;count down the game timer
  5335.               jsr ColorRotation          ;cycle one of the background colors
  5336.               lda Player_Y_HighPos
  5337.               cmp #$02                   ;if player is below the screen, don't bother with the music
  5338.               bpl NoChgMus
  5339.               lda StarInvincibleTimer    ;if star mario invincibility timer at zero,
  5340.               beq ClrPlrPal              ;skip this part
  5341.               cmp #$04
  5342.               bne NoChgMus               ;if not yet at a certain point, continue
  5343.               lda IntervalTimerControl   ;if interval timer not yet expired,
  5344.               bne NoChgMus               ;branch ahead, don't bother with the music
  5345.               jsr GetAreaMusic           ;to re-attain appropriate level music
  5346. NoChgMus:     ldy StarInvincibleTimer    ;get invincibility timer
  5347.               lda FrameCounter           ;get frame counter
  5348.               cpy #$08                   ;if timer still above certain point,
  5349.               bcs CycleTwo               ;branch to cycle player's palette quickly
  5350.               lsr                        ;otherwise, divide by 8 to cycle every eighth frame
  5351.               lsr
  5352. CycleTwo:     lsr                        ;if branched here, divide by 2 to cycle every other frame
  5353.               jsr CyclePlayerPalette     ;do sub to cycle the palette (note: shares fire flower code)
  5354.               jmp SaveAB                 ;then skip this sub to finish up the game engine
  5355. ClrPlrPal:    jsr ResetPalStar           ;do sub to clear player's palette bits in attributes
  5356. SaveAB:       lda A_B_Buttons            ;save current A and B button
  5357.               sta PreviousA_B_Buttons    ;into temp variable to be used on next frame
  5358.               lda #$00
  5359.               sta Left_Right_Buttons     ;nullify left and right buttons temp variable
  5360. UpdScrollVar: lda VRAM_Buffer_AddrCtrl
  5361.               cmp #$06                   ;if vram address controller set to 6 (one of two $0341s)
  5362.               beq ExitEng                ;then branch to leave
  5363.               lda AreaParserTaskNum      ;otherwise check number of tasks
  5364.               bne RunParser
  5365.               lda ScrollThirtyTwo        ;get horizontal scroll in 0-31 or $00-$20 range
  5366.               cmp #$20                   ;check to see if exceeded $21
  5367.               bmi ExitEng                ;branch to leave if not
  5368.               lda ScrollThirtyTwo
  5369.               sbc #$20                   ;otherwise subtract $20 to set appropriately
  5370.               sta ScrollThirtyTwo        ;and store
  5371.               lda #$00                   ;reset vram buffer offset used in conjunction with
  5372.               sta VRAM_Buffer2_Offset    ;level graphics buffer at $0341-$035f
  5373. RunParser:    jsr AreaParserTaskHandler  ;update the name table with more level graphics
  5374. ExitEng:      rts                        ;and after all that, we're finally done!
  5375.  
  5376. ;-------------------------------------------------------------------------------------
  5377.  
  5378. ScrollHandler:
  5379.             lda Player_X_Scroll       ;load value saved here
  5380.             clc
  5381.             adc Platform_X_Scroll     ;add value used by left/right platforms
  5382.             sta Player_X_Scroll       ;save as new value here to impose force on scroll
  5383.             lda ScrollLock            ;check scroll lock flag
  5384.             bne InitScrlAmt           ;skip a bunch of code here if set
  5385.             lda Player_Pos_ForScroll
  5386.             cmp #$50                  ;check player's horizontal screen position
  5387.             bcc InitScrlAmt           ;if less than 80 pixels to the right, branch
  5388.             lda SideCollisionTimer    ;if timer related to player's side collision
  5389.             bne InitScrlAmt           ;not expired, branch
  5390.             ldy Player_X_Scroll       ;get value and decrement by one
  5391.             dey                       ;if value originally set to zero or otherwise
  5392.             bmi InitScrlAmt           ;negative for left movement, branch
  5393.             iny
  5394.             cpy #$02                  ;if value $01, branch and do not decrement
  5395.             bcc ChkNearMid
  5396.             dey                       ;otherwise decrement by one
  5397. ChkNearMid: lda Player_Pos_ForScroll
  5398.             cmp #$70                  ;check player's horizontal screen position
  5399.             bcc ScrollScreen          ;if less than 112 pixels to the right, branch
  5400.             ldy Player_X_Scroll       ;otherwise get original value undecremented
  5401.  
  5402. ScrollScreen:
  5403.               tya
  5404.               sta ScrollAmount          ;save value here
  5405.               clc
  5406.               adc ScrollThirtyTwo       ;add to value already set here
  5407.               sta ScrollThirtyTwo       ;save as new value here
  5408.               tya
  5409.               clc
  5410.               adc ScreenLeft_X_Pos      ;add to left side coordinate
  5411.               sta ScreenLeft_X_Pos      ;save as new left side coordinate
  5412.               sta HorizontalScroll      ;save here also
  5413.               lda ScreenLeft_PageLoc
  5414.               adc #$00                  ;add carry to page location for left
  5415.               sta ScreenLeft_PageLoc    ;side of the screen
  5416.               and #$01                  ;get LSB of page location
  5417.               sta $00                   ;save as temp variable for PPU register 1 mirror
  5418.               lda Mirror_PPU_CTRL_REG1  ;get PPU register 1 mirror
  5419.               and #%11111110            ;save all bits except d0
  5420.               ora $00                   ;get saved bit here and save in PPU register 1
  5421.               sta Mirror_PPU_CTRL_REG1  ;mirror to be used to set name table later
  5422.               jsr GetScreenPosition     ;figure out where the right side is
  5423.               lda #$08
  5424.               sta ScrollIntervalTimer   ;set scroll timer (residual, not used elsewhere)
  5425.               jmp ChkPOffscr            ;skip this part
  5426. InitScrlAmt:  lda #$00
  5427.               sta ScrollAmount          ;initialize value here
  5428. ChkPOffscr:   ldx #$00                  ;set X for player offset
  5429.               jsr GetXOffscreenBits     ;get horizontal offscreen bits for player
  5430.               sta $00                   ;save them here
  5431.               ldy #$00                  ;load default offset (left side)
  5432.               asl                       ;if d7 of offscreen bits are set,
  5433.               bcs KeepOnscr             ;branch with default offset
  5434.               iny                         ;otherwise use different offset (right side)
  5435.               lda $00
  5436.               and #%00100000              ;check offscreen bits for d5 set
  5437.               beq InitPlatScrl            ;if not set, branch ahead of this part
  5438. KeepOnscr:    lda ScreenEdge_X_Pos,y      ;get left or right side coordinate based on offset
  5439.               sec
  5440.               sbc X_SubtracterData,y      ;subtract amount based on offset
  5441.               sta Player_X_Position       ;store as player position to prevent movement further
  5442.               lda ScreenEdge_PageLoc,y    ;get left or right page location based on offset
  5443.               sbc #$00                    ;subtract borrow
  5444.               sta Player_PageLoc          ;save as player's page location
  5445.               lda Left_Right_Buttons      ;check saved controller bits
  5446.               cmp OffscrJoypadBitsData,y  ;against bits based on offset
  5447.               beq InitPlatScrl            ;if not equal, branch
  5448.               lda #$00
  5449.               sta Player_X_Speed          ;otherwise nullify horizontal speed of player
  5450. InitPlatScrl: lda #$00                    ;nullify platform force imposed on scroll
  5451.               sta Platform_X_Scroll
  5452.               rts
  5453.  
  5454. X_SubtracterData:
  5455.       .db $00, $10
  5456.  
  5457. OffscrJoypadBitsData:
  5458.       .db $01, $02
  5459.  
  5460. ;-------------------------------------------------------------------------------------
  5461.  
  5462. GetScreenPosition:
  5463.       lda ScreenLeft_X_Pos    ;get coordinate of screen's left boundary
  5464.       clc
  5465.       adc #$ff                ;add 255 pixels
  5466.       sta ScreenRight_X_Pos   ;store as coordinate of screen's right boundary
  5467.       lda ScreenLeft_PageLoc  ;get page number where left boundary is
  5468.       adc #$00                ;add carry from before
  5469.       sta ScreenRight_PageLoc ;store as page number where right boundary is
  5470.       rts
  5471.  
  5472. ;-------------------------------------------------------------------------------------
  5473.  
  5474. GameRoutines:
  5475.       lda GameEngineSubroutine  ;run routine based on number (a few of these routines are  
  5476.       jsr JumpEngine            ;merely placeholders as conditions for other routines)
  5477.  
  5478.       .dw Entrance_GameTimerSetup
  5479.       .dw Vine_AutoClimb
  5480.       .dw SideExitPipeEntry
  5481.       .dw VerticalPipeEntry
  5482.       .dw FlagpoleSlide
  5483.       .dw PlayerEndLevel
  5484.       .dw PlayerLoseLife
  5485.       .dw PlayerEntrance
  5486.       .dw PlayerCtrlRoutine
  5487.       .dw PlayerChangeSize
  5488.       .dw PlayerInjuryBlink
  5489.       .dw PlayerDeath
  5490.       .dw PlayerFireFlower
  5491.  
  5492. ;-------------------------------------------------------------------------------------
  5493.  
  5494. PlayerEntrance:
  5495.             lda AltEntranceControl    ;check for mode of alternate entry
  5496.             cmp #$02
  5497.             beq EntrMode2             ;if found, branch to enter from pipe or with vine
  5498.             lda #$00      
  5499.             ldy Player_Y_Position     ;if vertical position above a certain
  5500.             cpy #$30                  ;point, nullify controller bits and continue
  5501.             bcc AutoControlPlayer     ;with player movement code, do not return
  5502.             lda PlayerEntranceCtrl    ;check player entry bits from header
  5503.             cmp #$06
  5504.             beq ChkBehPipe            ;if set to 6 or 7, execute pipe intro code
  5505.             cmp #$07                  ;otherwise branch to normal entry
  5506.             bne PlayerRdy
  5507. ChkBehPipe: lda Player_SprAttrib      ;check for sprite attributes
  5508.             bne IntroEntr             ;branch if found
  5509.             lda #$01
  5510.             jmp AutoControlPlayer     ;force player to walk to the right
  5511. IntroEntr:  jsr EnterSidePipe         ;execute sub to move player to the right
  5512.             dec ChangeAreaTimer       ;decrement timer for change of area
  5513.             bne ExitEntr              ;branch to exit if not yet expired
  5514.             inc DisableIntermediate   ;set flag to skip world and lives display
  5515.             jmp NextArea              ;jump to increment to next area and set modes
  5516. EntrMode2:  lda JoypadOverride        ;if controller override bits set here,
  5517.             bne VineEntr              ;branch to enter with vine
  5518.             lda #$ff                  ;otherwise, set value here then execute sub
  5519.             jsr MovePlayerYAxis       ;to move player upwards (note $ff = -1)
  5520.             lda Player_Y_Position     ;check to see if player is at a specific coordinate
  5521.             cmp #$91                  ;if player risen to a certain point (this requires pipes
  5522.             bcc PlayerRdy             ;to be at specific height to look/function right) branch
  5523.             rts                       ;to the last part, otherwise leave
  5524. VineEntr:   lda VineHeight
  5525.             cmp #$60                  ;check vine height
  5526.             bne ExitEntr              ;if vine not yet reached maximum height, branch to leave
  5527.             lda Player_Y_Position     ;get player's vertical coordinate
  5528.             cmp #$99                  ;check player's vertical coordinate against preset value
  5529.             ldy #$00                  ;load default values to be written to
  5530.             lda #$01                  ;this value moves player to the right off the vine
  5531.             bcc OffVine               ;if vertical coordinate < preset value, use defaults
  5532.             lda #$03
  5533.             sta Player_State          ;otherwise set player state to climbing
  5534.             iny                       ;increment value in Y
  5535.             lda #$08                  ;set block in block buffer to cover hole, then
  5536.             sta Block_Buffer_1+$b4    ;use same value to force player to climb
  5537. OffVine:    sty DisableCollisionDet   ;set collision detection disable flag
  5538.             jsr AutoControlPlayer     ;use contents of A to move player up or right, execute sub
  5539.             lda Player_X_Position
  5540.             cmp #$48                  ;check player's horizontal position
  5541.             bcc ExitEntr              ;if not far enough to the right, branch to leave
  5542. PlayerRdy:  lda #$08                  ;set routine to be executed by game engine next frame
  5543.             sta GameEngineSubroutine
  5544.             lda #$01                  ;set to face player to the right
  5545.             sta PlayerFacingDir
  5546.             lsr                       ;init A
  5547.             sta AltEntranceControl    ;init mode of entry
  5548.             sta DisableCollisionDet   ;init collision detection disable flag
  5549.             sta JoypadOverride        ;nullify controller override bits
  5550. ExitEntr:   rts                       ;leave!
  5551.  
  5552. ;-------------------------------------------------------------------------------------
  5553. ;$07 - used to hold upper limit of high byte when player falls down hole
  5554.  
  5555. AutoControlPlayer:
  5556.       sta SavedJoypadBits         ;override controller bits with contents of A if executing here
  5557.  
  5558. PlayerCtrlRoutine:
  5559.             lda GameEngineSubroutine    ;check task here
  5560.             cmp #$0b                    ;if certain value is set, branch to skip controller bit loading
  5561.             beq SizeChk
  5562.             lda AreaType                ;are we in a water type area?
  5563.             bne SaveJoyp                ;if not, branch
  5564.             ldy Player_Y_HighPos
  5565.             dey                         ;if not in vertical area between
  5566.             bne DisJoyp                 ;status bar and bottom, branch
  5567.             lda Player_Y_Position
  5568.             cmp #$d0                    ;if nearing the bottom of the screen or
  5569.             bcc SaveJoyp                ;not in the vertical area between status bar or bottom,
  5570. DisJoyp:    lda #$00                    ;disable controller bits
  5571.             sta SavedJoypadBits
  5572. SaveJoyp:   lda SavedJoypadBits         ;otherwise store A and B buttons in $0a
  5573.             and #%11000000
  5574.             sta A_B_Buttons
  5575.             lda SavedJoypadBits         ;store left and right buttons in $0c
  5576.             and #%00000011
  5577.             sta Left_Right_Buttons
  5578.             lda SavedJoypadBits         ;store up and down buttons in $0b
  5579.             and #%00001100
  5580.             sta Up_Down_Buttons
  5581.             and #%00000100              ;check for pressing down
  5582.             beq SizeChk                 ;if not, branch
  5583.             lda Player_State            ;check player's state
  5584.             bne SizeChk                 ;if not on the ground, branch
  5585.             ldy Left_Right_Buttons      ;check left and right
  5586.             beq SizeChk                 ;if neither pressed, branch
  5587.             lda #$00
  5588.             sta Left_Right_Buttons      ;if pressing down while on the ground,
  5589.             sta Up_Down_Buttons         ;nullify directional bits
  5590. SizeChk:    jsr PlayerMovementSubs      ;run movement subroutines
  5591.             ldy #$01                    ;is player small?
  5592.             lda PlayerSize
  5593.             bne ChkMoveDir
  5594.             ldy #$00                    ;check for if crouching
  5595.             lda CrouchingFlag
  5596.             beq ChkMoveDir              ;if not, branch ahead
  5597.             ldy #$02                    ;if big and crouching, load y with 2
  5598. ChkMoveDir: sty Player_BoundBoxCtrl     ;set contents of Y as player's bounding box size control
  5599.             lda #$01                    ;set moving direction to right by default
  5600.             ldy Player_X_Speed          ;check player's horizontal speed
  5601.             beq PlayerSubs              ;if not moving at all horizontally, skip this part
  5602.             bpl SetMoveDir              ;if moving to the right, use default moving direction
  5603.             asl                         ;otherwise change to move to the left
  5604. SetMoveDir: sta Player_MovingDir        ;set moving direction
  5605. PlayerSubs: jsr ScrollHandler           ;move the screen if necessary
  5606.             jsr GetPlayerOffscreenBits  ;get player's offscreen bits
  5607.             jsr RelativePlayerPosition  ;get coordinates relative to the screen
  5608.             ldx #$00                    ;set offset for player object
  5609.             jsr BoundingBoxCore         ;get player's bounding box coordinates
  5610.             jsr PlayerBGCollision       ;do collision detection and process
  5611.             lda Player_Y_Position
  5612.             cmp #$40                    ;check to see if player is higher than 64th pixel
  5613.             bcc PlayerHole              ;if so, branch ahead
  5614.             lda GameEngineSubroutine
  5615.             cmp #$05                    ;if running end-of-level routine, branch ahead
  5616.             beq PlayerHole
  5617.             cmp #$07                    ;if running player entrance routine, branch ahead
  5618.             beq PlayerHole
  5619.             cmp #$04                    ;if running routines $00-$03, branch ahead
  5620.             bcc PlayerHole
  5621.             lda Player_SprAttrib
  5622.             and #%11011111              ;otherwise nullify player's
  5623.             sta Player_SprAttrib        ;background priority flag
  5624. PlayerHole: lda Player_Y_HighPos        ;check player's vertical high byte
  5625.             cmp #$02                    ;for below the screen
  5626.             bmi ExitCtrl                ;branch to leave if not that far down
  5627.             ldx #$01
  5628.             stx ScrollLock              ;set scroll lock
  5629.             ldy #$04
  5630.             sty $07                     ;set value here
  5631.             ldx #$00                    ;use X as flag, and clear for cloud level
  5632.             ldy GameTimerExpiredFlag    ;check game timer expiration flag
  5633.             bne HoleDie                 ;if set, branch
  5634.             ldy CloudTypeOverride       ;check for cloud type override
  5635.             bne ChkHoleX                ;skip to last part if found
  5636. HoleDie:    inx                         ;set flag in X for player death
  5637.             ldy GameEngineSubroutine
  5638.             cpy #$0b                    ;check for some other routine running
  5639.             beq ChkHoleX                ;if so, branch ahead
  5640.             ldy DeathMusicLoaded        ;check value here
  5641.             bne HoleBottom              ;if already set, branch to next part
  5642.             iny
  5643.             sty EventMusicQueue         ;otherwise play death music
  5644.             sty DeathMusicLoaded        ;and set value here
  5645. HoleBottom: ldy #$06
  5646.             sty $07                     ;change value here
  5647. ChkHoleX:   cmp $07                     ;compare vertical high byte with value set here
  5648.             bmi ExitCtrl                ;if less, branch to leave
  5649.             dex                         ;otherwise decrement flag in X
  5650.             bmi CloudExit               ;if flag was clear, branch to set modes and other values
  5651.             ldy EventMusicBuffer        ;check to see if music is still playing
  5652.             bne ExitCtrl                ;branch to leave if so
  5653.             lda #$06                    ;otherwise set to run lose life routine
  5654.             sta GameEngineSubroutine    ;on next frame
  5655. ExitCtrl:   rts                         ;leave
  5656.  
  5657. CloudExit:
  5658.       lda #$00
  5659.       sta JoypadOverride      ;clear controller override bits if any are set
  5660.       jsr SetEntr             ;do sub to set secondary mode
  5661.       inc AltEntranceControl  ;set mode of entry to 3
  5662.       rts
  5663.  
  5664. ;-------------------------------------------------------------------------------------
  5665.  
  5666. Vine_AutoClimb:
  5667.            lda Player_Y_HighPos   ;check to see whether player reached position
  5668.            bne AutoClimb          ;above the status bar yet and if so, set modes
  5669.            lda Player_Y_Position
  5670.            cmp #$e4
  5671.            bcc SetEntr
  5672. AutoClimb: lda #%00001000         ;set controller bits override to up
  5673.            sta JoypadOverride
  5674.            ldy #$03               ;set player state to climbing
  5675.            sty Player_State
  5676.            jmp AutoControlPlayer
  5677. SetEntr:   lda #$02               ;set starting position to override
  5678.            sta AltEntranceControl
  5679.            jmp ChgAreaMode        ;set modes
  5680.  
  5681. ;-------------------------------------------------------------------------------------
  5682.  
  5683. VerticalPipeEntry:
  5684.       lda #$01             ;set 1 as movement amount
  5685.       jsr MovePlayerYAxis  ;do sub to move player downwards
  5686.       jsr ScrollHandler    ;do sub to scroll screen with saved force if necessary
  5687.       ldy #$00             ;load default mode of entry
  5688.       lda WarpZoneControl  ;check warp zone control variable/flag
  5689.       bne ChgAreaPipe      ;if set, branch to use mode 0
  5690.       iny
  5691.       lda AreaType         ;check for castle level type
  5692.       cmp #$03
  5693.       bne ChgAreaPipe      ;if not castle type level, use mode 1
  5694.       iny
  5695.       jmp ChgAreaPipe      ;otherwise use mode 2
  5696.  
  5697. MovePlayerYAxis:
  5698.       clc
  5699.       adc Player_Y_Position ;add contents of A to player position
  5700.       sta Player_Y_Position
  5701.       rts
  5702.  
  5703. ;-------------------------------------------------------------------------------------
  5704.  
  5705. SideExitPipeEntry:
  5706.              jsr EnterSidePipe         ;execute sub to move player to the right
  5707.              ldy #$02
  5708. ChgAreaPipe: dec ChangeAreaTimer       ;decrement timer for change of area
  5709.              bne ExitCAPipe
  5710.              sty AltEntranceControl    ;when timer expires set mode of alternate entry
  5711. ChgAreaMode: inc DisableScreenFlag     ;set flag to disable screen output
  5712.              lda #$00
  5713.              sta OperMode_Task         ;set secondary mode of operation
  5714.              sta Sprite0HitDetectFlag  ;disable sprite 0 check
  5715. ExitCAPipe:  rts                       ;leave
  5716.  
  5717. EnterSidePipe:
  5718.            lda #$08               ;set player's horizontal speed
  5719.            sta Player_X_Speed
  5720.            ldy #$01               ;set controller right button by default
  5721.            lda Player_X_Position  ;mask out higher nybble of player's
  5722.            and #%00001111         ;horizontal position
  5723.            bne RightPipe
  5724.            sta Player_X_Speed     ;if lower nybble = 0, set as horizontal speed
  5725.            tay                    ;and nullify controller bit override here
  5726. RightPipe: tya                    ;use contents of Y to
  5727.            jsr AutoControlPlayer  ;execute player control routine with ctrl bits nulled
  5728.            rts
  5729.  
  5730. ;-------------------------------------------------------------------------------------
  5731.  
  5732. PlayerChangeSize:
  5733.              lda TimerControl    ;check master timer control
  5734.              cmp #$f8            ;for specific moment in time
  5735.              bne EndChgSize      ;branch if before or after that point
  5736.              jmp InitChangeSize  ;otherwise run code to get growing/shrinking going
  5737. EndChgSize:  cmp #$c4            ;check again for another specific moment
  5738.              bne ExitChgSize     ;and branch to leave if before or after that point
  5739.              jsr DonePlayerTask  ;otherwise do sub to init timer control and set routine
  5740. ExitChgSize: rts                 ;and then leave
  5741.  
  5742. ;-------------------------------------------------------------------------------------
  5743.  
  5744. PlayerInjuryBlink:
  5745.            lda TimerControl       ;check master timer control
  5746.            cmp #$f0               ;for specific moment in time
  5747.            bcs ExitBlink          ;branch if before that point
  5748.            cmp #$c8               ;check again for another specific point
  5749.            beq DonePlayerTask     ;branch if at that point, and not before or after
  5750.            jmp PlayerCtrlRoutine  ;otherwise run player control routine
  5751. ExitBlink: bne ExitBoth           ;do unconditional branch to leave
  5752.