On this page
  1. How it plays
  2. Across the series
  3. Cartridge
  4. Code lineage
  5. Related
  6. Mechanics
  7. References
  8. Sources

Super Mario Bros.: The Lost Levels is Nintendo’s sequel to Super Mario Bros., released in Japan on 3 June 19861 as Super Mario Bros. 2 for the Famicom Disk System1. The manual presents it as another Mario journey in a parallel world, eight new worlds, with a Mario game and a Luigi game2. It was aimed at players who had mastered the first. Miyamoto recalls a “For Super Players” sticker on the package, and a Nintendo interview’s note calls it a tougher challenge developed for advanced players3. Nintendo counts Nintendo's page counts 52 courses, including those opened by meeting conditions, one and a half times the first game's. It names the poison mushroom and a tailwind that carries the player's body along as new tricks, and says Luigi jumps higher than Mario and slips more.4 courses, including those opened by meeting conditions4.

Miyamoto calls it Takashi Tezuka’s directorial debut, and Tezuka says they made it by changing the first game’s difficulty and stage design5. Miyamoto recalls that the team changed Super Mario’s levels using the VS. System, an arcade system based on the Famicom, and, as they played, made “very challenging levels”6. In North America, the Super Mario Bros. 2 that Nintendo released was a different game, a remake of Yume Kojo: Doki Doki Panic7. Retrospectives say this one was held back from North America for its difficulty, but they disagree on who decided8.

Famicom Tsūshin’s chart had it second in its 1 August 1986 issue, a week after it entered at the top9. Famicom Hisshoubon’s three reviewers gave it 3, 2, and 2 of 510. Nasubi Kamen asked whether it had only got harder and saw a push to sell the Disk System; Tokashiki Minoru wanted it on a cartridge, for friends without the drive; Goinkyo missed the first game’s fresh surprise10.

In North America it came out in August 1993, as The Lost Levels in Super Mario All-Stars for the Super NES, which added a save after each level11,12. Nintendo Power warned that it was “waaayy harder” than the original13. On the Wii’s Virtual Console, GameSpot’s Frank Provo gave the original game 6.5 of 1014 in 2007 and called it a level hack of the first14,15. IGN’s 2010 history says it looked exactly like its predecessor but was much harder, with poison mushrooms, warps that send the player back, and wind16.

#How it plays

Mario runs and jumps exactly as in Super Mario Bros.: the same take-off speeds, gravities, frictions, and top speeds17. As there, a jump can start only from the ground, not after walking off a ledge18, and a hit that shrinks him leaves him blinking and safe for the same few seconds19.

Luigi is the other choice on the title screen. He takes off at Mario’s speeds, but under lighter gravity, so the same jump carries him higher. His weaker friction makes him slippery: he takes longer to speed up, slow down, and turn around20,21. Turning against his motion doesn’t brake him twice as hard the way it does Mario. After a castle’s axe, he walks on with Mario’s physics until the next area20.

#Wind and the poison mushroom

From World 5 on, some outdoor stretches blow the player to the right, with leaves and a sound while the wind lasts. On average the push is a quarter of Mario’s walking speed, in the air as well as on the ground22,23,24. It adds to the player’s own speed, so running into it is slower and running with it faster, at any speed22.

The poison mushroom comes from blocks of its own and slides along like a Super Mushroom. Touching it is a hit: small Mario dies, and a bigger Mario drops straight to small. During the blink after a hit, or under a star’s invincibility, it does nothing25. It is drawn as the mushroom is, in its own colors26.

#Springboards and warps

A springboard pushes the player down and up over four steps, then launches them at 7 px a frame, faster than any jump from the ground27,28. Pressing A fresh while the spring is pressed down raises the launch to 12 px a frame. Green springboards, in worlds 2, 3, and 7 and in B and C, launch at 32 px a frame. The flight up and down is the same whether A is held or not, for both brothers27.

A warp zone sends the player to one world, whichever pipe they enter. Some go back: World 3’s leads to World 1, and the warps of worlds 6 to 8 lead to World 529.

#A harder second half

From 4-4 on, and throughout worlds A to D, every level runs in a hard mode30. Enemies marked for it appear, cannons fire more often, and up to four flying Cheep Cheeps come at once instead of three. Hammer bros throw more often, and Bowser breathes fire sooner. The large lifts are narrower31.

Piranha plants are green in worlds 1 to 3. From World 4 on they turn red: they move twice as fast and come out of their pipes even when the player stands closer32. Once no Lakitu is on screen, a new one flies in after a while; from World 7 on, it flies lower33.

#Game over, World 9, and worlds A to D

At a game over, the player can continue or retry. Continue restarts the current world at its first level, with three lives and the score at zero. Retry ends the game34.

Clearing the castle of every world from 1 to 8, without a retry, opens World 9 after 8-4’s ending. A warp that skips a world shuts it unless the player warps back and clears that world’s castle; a continue keeps the record35. World 9 gives one life and no continue, and its four levels loop36.

Each ending after 8-4 is saved to the disk as a star on the title screen. With eight stars, holding A while pressing Start begins at World A, and worlds A to D follow. Their own ending adds no star37.

The flagpole gives an extra life when the coin count’s two digits match the timer’s last digit38. Fireworks go off over the castle when the timer’s last digit matches the coin count’s: three for an odd digit, six for an even one39.

#Across the series

Against Super Mario Bros., most of the code is the same game’s engine, changed in places; the Code lineage table below lists each stretch. The movement and gravity routines are the same instructions40, and so are Mario’s numbers17. The player’s sprites are the same tiles41, and the songs heard in the levels have the same notes42. The levels are new: one short pipe intro is all the level data the two share43.

What changed for play:

  • Two players become two brothers. The menu drops the two-player game and the world select, and Select picks Mario or Luigi44. In Super Mario Bros., Luigi is the second player’s character45; here he has his own physics20.
  • The wind and the poison mushroom are new. The wind runs in the player’s movement code and the game’s frame loop46,47, and the poison mushroom comes from its own blocks48.
  • A star now blocks a poison mushroom. The injury routine also does nothing while a star lasts49.
  • Hard mode starts at 4-4, where Super Mario Bros.’s starts at 5-350. Super Mario Bros.’s other hard mode, which turns Goombas into Buzzy Beetles, never switches on: its checks remain, but nothing sets its flag51.
  • Warps lead by world. Super Mario Bros. picks the destination by which pipe the player enters; here the world, level, and area decide, and every pipe leads to the same place49,52.
  • The springboard changes. Landing on one now sets the falling gravity too, so holding A no longer matters to the flight49, and the green springs are new53.
  • Stomps bounce higher, at one speed for every stomp, and higher still off paratroopas49.
  • Lakitu returns after three checks, where Super Mario Bros. waits for seven54. The red piranha plants are new55, and so are upside-down ones56.
  • Game over offers a continue, where Super Mario Bros.’s game over ends the game50.
  • The flagpole and the fireworks follow the coins. The flagpole life is new53. Super Mario Bros. sets off fireworks when the timer ends in 1, 3, or 6; here the coins’ last digit decides55.

Cartridge

Interactive: rom-parts (needs JavaScript)

64 KB, a cell per 512 bytes, from 345 mapped regions

Code lineage

FromToMatchBytesWhat
Super Mario Bros. area-parser-task-handler … get-block-buffer-addrSuper Mario Bros.: The Lost Levels area-parser-task-handler … get-block-buffer-addrchanged2,422The area parser and its object builders (`AreaParserTaskHandler` through `GetBlockBufferAddr`) are Super Mario Bros.'s, with most changes in the metatile numbers they write, which shift with the renumbered metatiles (bridges, flagpole, coins, bricks, cannons, stairs, blocks, water pipe). Beyond those: the object jump table gains entries, the wind on and off commands among them, so three offsets into it change; `ScrollLockObject_Warp` picks the warp zone's destination by world, level and area; the third ledge style uses metatiles $8A-$8C and draws no stem, where Super Mario Bros.'s mushroom ledge uses $19-$1B with a stem (and `RenderUnderPart` drops its stem checks); the vertical pipes place a piranha plant through a shared `SetupPiranhaPlant`, with no exception for world 1-1; `Jumpspring` places nothing when no enemy slot is free. `IncrementColumnPos`, `AlterAreaAttributes`, `KillEnemies` and the object position helpers are byte for byte the same.
Super Mario Bros. chr-backgroundSuper Mario Bros.: The Lost Levels chr-backgroundchanged3,200Background tiles `$24`-`$EB` are Super Mario Bros.'s but for 65 of their 200: `$28`, `$29`, `$2B`-`$2D`, `$30`-`$3C`, `$45`, `$47`, `$4B`, `$4C`, `$4E`-`$52`, `$5D`, `$5E`, `$6B`-`$76`, `$80`, `$81`, `$9B`-`$9E`, `$A0`, `$A1`, `$A9`, `$AA`, `$AF`, `$B4`-`$BD`, `$C0`, `$C1` and `$CF` differ.
Super Mario Bros. chr-fontSuper Mario Bros.: The Lost Levels chr-fontrewritten576The font, background tiles `$00`-`$23` (the digits and A to Z), keeps Super Mario Bros.'s layout, so `GameText` spells with the same numbers, but every one of its 36 tiles differs from Super Mario Bros.'s.
Super Mario Bros. chr-sprites-objectsSuper Mario Bros.: The Lost Levels chr-spriteschanged2,816Sprite tiles `$50`-`$FF` are Super Mario Bros.'s but for 15: `$5B`, `$76`-`$7B`, `$85`, `$86`, `$D8`, `$DA`, `$DB` and `$FD`-`$FF` differ, among them `$76`-`$79`, Super Mario Bros.'s mushroom, which The Lost Levels' enemy table now draws, and the mushrooms' new tiles.
Super Mario Bros. chr-sprites-playerSuper Mario Bros.: The Lost Levels chr-spritesidentical1,280The player's 80 sprite tiles, `$00`-`$4F` of the sprite pattern table, are Super Mario Bros.'s byte for byte.
Super Mario Bros. draw-vine … draw-sprite-objectSuper Mario Bros.: The Lost Levels draw-vine … draw-sprite-objectchanged3,800The sprite drawing code (`DrawVine` through `DrawSpriteObject`) is Super Mario Bros.'s with these changes: `DrawPowerUp` draws every mushroom from tiles $D8, $DA, $DB and $FF where Super Mario Bros. uses $76-$79, and gives the poison mushroom, a fifth row, palette 3; `EnemyGfxHandler`'s tile table takes up $76-$79, and the handler also flips the upside-down piranha plants and colors the jumpsprings green on world numbers 2, 3 and 7; `RenderPlayerSub` plays the skid sound; `FlagpoleGfxHandler`'s score table gains the 1-up; `GetYOffscreenBits` has two of its tables' halves swapped, its instructions unchanged; `DrawBlock` uses a renumbered metatile. 12 regions, `PlayerGfxHandler` among them, differ only in their addresses, and five, `DrawSpriteObject` among them, are byte for byte the same.
Super Mario Bros. enemies-and-loops-core … init-jump-gp-troopaSuper Mario Bros.: The Lost Levels enemies-and-loops-core … init-jump-gp-troopachanged2,033Enemy spawning and set-up (`EnemiesAndLoopsCore` through `InitJumpGPTroopa`) are Super Mario Bros.'s with these changes: `ProcLoopCommand` reads 12 loop entries where Super Mario Bros. reads 11, and takes each loop's number of checks from a new `MultiLoopCount` table where Super Mario Bros. special-cases world 7; `ProcessEnemyData` skips a check in world 9 and gives one enemy code a piranha plant set-up; `InitHammerBro` checks the world; `LakituAndSpinyHandler` brings Lakitu back once `LakituReappearTimer` reaches 3, where Super Mario Bros. waits until it reaches 7, and brings him back lower on the screen in worlds 7 to 9 and A to D; `InitBowser` first erases any other Bowser; `InitPiranhaPlant` patches the plant's palette and pipe distance, green in worlds 1 to 3 and red from world 4 and in A to D; `InitJumpGPTroopa` starts the jumping paratroopa at x speed $F4 where Super Mario Bros. uses $F8. Of its 27 regions, 15 differ only in their addresses and 5 are byte for byte the same.
Super Mario Bros. fireball-enemy-collision … block-buffer-collisionSuper Mario Bros.: The Lost Levels fireball-enemy-collision … block-buffer-collisionchanged3,511The collision code (`FireballEnemyCollision` through `BlockBufferCollision`) is Super Mario Bros.'s with the upside-down piranha plant, the poison mushroom and the renumbered metatiles added: the fireball, enemy, background and stomp checks treat the upside-down plant like a piranha plant; `HandlePowerUpCollision` injures the player on power-up type 4; `InjurePlayer` also does nothing while the star's `StarInvincibleTimer` runs; `HandlePECollisions` checks for the cannon's Bullet Bill before the piranha plants and Podoboo, where Super Mario Bros. checks it after them; `PlayerEnemyCollision` decides a stomp with LDY, DEY, BPL on the vertical speed where Super Mario Bros. uses BMI and BNE (the two disagree only at speed $80); every stomp bounces the player through a new `SetBounce`, at vertical speed $FA, or $F8 off red paratroopas and flying green paratroopas, where Super Mario Bros. sets $FD after a stomp that defeats an enemy and $FC after one that demotes a paratroopa or knocks an enemy into its shell; `HandleClimbing` gives a life for grabbing the flagpole when the coin tally's digits and the timer's last digit match; `HandlePipeEntry` sends the player to the warp zone's one destination whichever pipe they take, where Super Mario Bros. picks by the pipe's x position; `HandleCoinMetatile`'s axe restores Mario's physics; `ChkForLandJumpSpring` sets `VerticalForceDown` to $70 as well as `VerticalForce`; `PlayerHammerCollision` also skips while the player is off screen; `HandleEToBGCollision` bounces a power-up on a bumped block without stunning it and never demotes a piranha plant; `CheckPlayerVertical` drops its test of how far down the screen the player is; one bounding box grows from $14 to $16. The platform collisions, `LandEnemyProperly`, the side checks and `BlockBufferCollision` differ only in their addresses, and three regions, `PlayerCollisionCore` among them, are byte for byte the same.
Super Mario Bros. floatey-numbers-routine … reset-screen-timerSuper Mario Bros.: The Lost Levels floatey-numbers-routine … reset-screen-timerchanged910The score numbers, the screen setup tasks, the status bar and the game's text (`FloateyNumbersRoutine` through `ResetScreenTimer`) are Super Mario Bros.'s with these changes: `GetPlayerColors` no longer picks a palette row by `CurrentPlayer` (Super Mario Bros.'s table has a row for Luigi); `WriteBottomStatusLine` goes through a new `GetWorldNumForDisplay`, which shows worlds A to D as letters; `DisplayIntermediate` blanks the screen after the world and lives screen in world 9, and `DisplayTimeUp` writes its text and resets the screen timer itself where Super Mario Bros. jumps into `DisplayIntermediate`; `ClearBuffersDrawIcon`'s title-screen part moves to the title code; the screen task list gains `DemoReset`; `GameText` drops the two-player and Luigi texts and adds CONTINUE and RETRY to the game-over screen. `InitScreen`, `SetupIntermediate`, `GetAreaPalette`, `GetAlternatePalette1`, `WriteTopStatusLine`, `AreaParserTaskControl` and `ResetScreenTimer` keep every instruction, with only addresses changed.
Super Mario Bros. game-core-routine … get-screen-positionSuper Mario Bros.: The Lost Levels game-core-routine … get-screen-positionchanged363`GameCoreRoutine` and `ScrollHandler` are Super Mario Bros.'s with three changes: the game mode's task list gains `GameModeDiskRoutines` at its head and the core no longer reads the current player's saved joypad bits; each frame of play calls `SimulateWind` once a disk file beyond worlds 1 to 4 is loaded; `ScrollHandler` waits for the status bar's timer IRQ before it scrolls and keeps the name table in `NameTableSelect`, where Super Mario Bros. sets it in its PPU control mirror. `GetScreenPosition` is byte for byte the same.
Super Mario Bros. game-menu-routineSuper Mario Bros.: The Lost Levels game-menu-routine … demo-enginechanged261`GameMenuRoutine` and `DemoEngine` are Super Mario Bros.'s menu and demo, rewritten in part: the menu drops the one- or two-player choice and the world select, and starts the game at world 1, or at world A when A is held and the game has been beaten 8 times; Select switches between Mario and Luigi; the demo plays new button presses and durations through the same code.
Super Mario Bros. game-routines … impose-frictionSuper Mario Bros.: The Lost Levels game-routines … impose-frictionchanged1,518The player's control and movement code (`GameRoutines` through `ImposeFriction`) is Super Mario Bros.'s, instruction for instruction in 14 of its 19 regions, with these changes: `OnGroundStateSub` and the jump and swim code move the player through a new `JmpMove`, which lets the wind push them (`BlowPlayerAround`) once a disk file beyond worlds 1 to 4 is loaded; `PlayerPhysicsSub`'s friction table moves up to follow the fall forces, inside the 17 bytes that `LoadPhysicsData` overwrites with Mario's or Luigi's set; `PlayerEndLevel` queues the level-end music once, guarded by a new `FlagpoleMusicFlag`, where Super Mario Bros. queues it whenever `ScrollLock` is set, and sets the hidden 1-up's flag on 10 coins in any world, where Super Mario Bros. reads a per-world table, and starts world 9 over after 9-4; `PlayerDeath` shares one RTS. The entrances, pipes, size change, injury blink, flagpole slide, falling, climbing, animation speed and `ImposeFriction` differ only in their addresses.
Super Mario Bros. init-bal-platform … run-fireworksSuper Mario Bros.: The Lost Levels init-bal-platform … run-fireworkschanged2,798The platforms' set-up, the enemy object loop, the enemies' movers, Bowser and the fireworks (`InitBalPlatform` through `RunFireworks`, 32 regions) are Super Mario Bros.'s instruction for instruction, with two changes: the enemy movers' jump table (`EnemyMovementSubs`) sends enemy 4, the upside-down piranha plant, to the new `MoveUpsideDownPiranhaP`, where Super Mario Bros. has `MoveNormalEnemy`; `MoveSwimmingCheepCheep` adds $40 to a swimming Cheep Cheep's vertical fraction each frame where Super Mario Bros. adds $20. Three of the regions are byte for byte the same, and the rest differ only in the addresses of their calls, jumps and tables.
Super Mario Bros. jump-engine … update-screenSuper Mario Bros.: The Lost Levels jump-engine … update-screenrelocated240`JumpEngine`, `InitializeNameTables`, `ReadJoypads` and `UpdateScreen` are Super Mario Bros.'s, instruction for instruction: `JumpEngine` is byte for byte the same, and the other three differ only in the addresses of their calls, jumps and tables.
Super Mario Bros. load-area-pointer … world-addr-offsetsSuper Mario Bros.: The Lost Levels load-area-pointer … area-data-addrschanged456`LoadAreaPointer`, `FindAreaPointer` and `GetAreaDataAddrs` are Super Mario Bros.'s, with the area data address tables made tables of words (indexed with an ASL) where Super Mario Bros. keeps separate low and high byte tables; the tables themselves hold The Lost Levels' worlds, and `AreaDataOfsLoopback` its 12 loop points. Of the level data, only the 9-byte pipe intro area (`L_GroundArea10`) is byte for byte Super Mario Bros.'s.
Super Mario Bros. move-object-horizontally … impose-gravitySuper Mario Bros.: The Lost Levels move-object-horizontally … impose-gravityrelocated325The movement and gravity routines (`MoveObjectHorizontally` through `ImposeGravity`) are Super Mario Bros.'s, instruction for instruction: `ImposeGravity` and `MoveDropPlatform` are byte for byte the same, and the other seven differ only in the addresses of their calls and jumps.
Super Mario Bros. music-handlerSuper Mario Bros.: The Lost Levels alt-sound-enginerewritten856`AlternateSoundEngine`, the ending's sound engine in `SM2DATA3`, is a rewrite of Super Mario Bros.'s `MusicHandler` that keeps its note and length code: it has no event or area music buffers and no time-running-out handling, steps through a list of patterns with `PatternNumber`, reading each pattern's header from `MusicHeaderData`, has its own pause and silence code, and plays the ending's music on the disk system's wavetable channel as well as the square, triangle and noise channels, with its own waveform, envelope and modulation tables.
Super Mario Bros. music-header-data … star-cloud-m-dataSuper Mario Bros.: The Lost Levels music-header-data … star-cloud-m-datachanged1,713SM2MAIN's music data is Super Mario Bros.'s less the victory theme: the headers lose `VictoryMusHdr` and their offsets shift by its five bytes, the residual header bytes differ, and `VictoryMusData` is gone from between the castle-clear music and the frequency tables, with two of the three unused bytes after it (the ending's music lives in `SM2DATA3`). The notes of every other song and the frequency, note-length and envelope tables after them are byte for byte the same.
Super Mario Bros. print-status-bar-numbers … run-game-overSuper Mario Bros.: The Lost Levels print-status-bar-numbers … run-game-overchanged846The status bar numbers, game setup, lives and game over (`PrintStatusBarNumbers` through `RunGameOver`) are Super Mario Bros.'s with a new `GameOverSubs` dispatch among them and these changes: the status bar's digit tables lose the second player's entries; `UpdateTopScore` checks one score where Super Mario Bros. checks two; `DigitsMathRoutine` drops a compare with zero before its BEQ; `DefaultSprOffsets` loses the sprite 0 data; `InitializeArea` loads the player's physics (`LoadPhysicsData`) and sets the secondary hard mode flag from 4-4 on and in all of worlds A to D (`HardWorldFlag`), where Super Mario Bros. sets it from 5-3 on or once the primary hard mode flag is set; `SecondaryGameSetup` sets the name table and switches on the status bar's IRQ split, where Super Mario Bros. sets the second player's lives and switches on the sprite 0 check; `InitializeMemory` also spares $0100-$0108; `PlayerLoseLife` reads its own halfway pages and no longer swaps players; `RunGameOver` opens the continue-or-retry menu (or, in world 9, ends the game) where Super Mario Bros. ends the game on Start or when the screen timer runs out and then hands over to the other player if they have lives left. `GetAreaMusic` and `Entrance_GameTimerSetup` keep every instruction, though the level timer's digits moved from $07F8 to $07EC.
Super Mario Bros. proc-fireballs … vine-object-handlerSuper Mario Bros.: The Lost Levels proc-fireballs … vine-object-handlerchanged1,013Fireballs, the level timer and the stage objects (`ProcFireballs` through `VineObjectHandler`) are Super Mario Bros.'s with these changes: `RunGameTimer` tests the player's height with BPL instead of BCS and points at the timer digits' new place; `WarpZoneObject` no longer counts up `WarpZoneControl`; `FlagpoleRoutine` gives a life for the new sixth flagpole score; `JumpspringHandler` launches with the green springs' force on world numbers 2, 3 and 7; `VineObjectHandler` erases the vine and its metatiles once it goes off the left of the screen. `ProcFireballs` and `ProcessWhirlpools` differ only in their addresses, and `SetupVine` is byte for byte the same.
Super Mario Bros. process-cannons … block-obj-mt-updaterSuper Mario Bros.: The Lost Levels process-cannons … block-obj-mt-updaterchanged1,358Cannons, hammers, coins, power-ups and blocks (`ProcessCannons` through `BlockObjMT_Updater`) are Super Mario Bros.'s with the poison mushroom added and one player: `BumpBlock`'s contents table gains poison mushroom blocks and `MushFlowerBlock` gains `PoisonMushBlock`, which sets power-up type 4; `PowerUpObjHandler` walks types 4 and 5 like a mushroom; `BlockBumpedChk` checks 19 block metatiles where Super Mario Bros. checks 14; `GiveOneCoin` and `AddToScore` use fixed offsets where Super Mario Bros. indexes by `CurrentPlayer`; the head-collision and coin checks use the renumbered metatiles. `SetupPowerUp` is byte for byte Super Mario Bros.'s, though the poison mushroom now passes through it, and so are `InitBlock_XY_Pos` and `SpawnBrickChunks`; the cannons, hammers, jumping coins, brick shatter and bouncing blocks differ only in their addresses.
Super Mario Bros. render-area-graphics … water-palette-dataSuper Mario Bros.: The Lost Levels render-area-graphics … water-palette-datachanged1,266The background renderer, the metatile tables and the area palettes (`RenderAreaGraphics` through the palette data) are Super Mario Bros.'s with the metatiles renumbered: The Lost Levels inserts new metatiles, so `ReplaceBlockMetatile` compares against shifted numbers ($56, $4F, $5C and $50 for Super Mario Bros.'s $58, $51, $5D and $52), and `MetatileGraphics_Low` moves some entries and adds others. The palette data region also holds two new messages. `RenderAttributeTables` is byte for byte the same, and `RenderAreaGraphics` and `ColorRotatePalette` differ only in their addresses.
Super Mario Bros. run-star-flag-obj … offscreen-bounds-checkSuper Mario Bros.: The Lost Levels run-star-flag-obj … offscreen-bounds-checkchanged1,047`RunStarFlagObj` through `OffscreenBoundsCheck` are Super Mario Bros.'s with these changes: `RunStarFlagObj` sets off fireworks when the timer's last digit matches the coin tally's, where Super Mario Bros. matches the timer's last digit against 1, 3 and 6, and adds its points to the one player's score; `MovePiranhaPlant` moves red piranha plants (the patched palette) every frame; `BalancePlatform` leaves a platform alone when its partner is no balance platform; `OffscreenBoundsCheck` treats upside-down piranha plants like upright ones. `FirebarSpin` is byte for byte the same, and the moving platforms differ only in their addresses.
Super Mario Bros. sound-engine … music-handlerSuper Mario Bros.: The Lost Levels sound-engine … music-handlerchanged1,705The sound engine (`SoundEngine` through `MusicHandler`) is Super Mario Bros.'s with two new sounds in the noise handler: the skid, played on the triangle channel from `SkidSfxFreqData`, and the wind, played from `WindFreqEnvData`; both tables sit after the square 2 handler. `SoundEngine`, `Dump_Squ1_Regs`, `Square1SfxHandler` and `MusicHandler` differ only in their addresses.
Super Mario Bros. star-cloud-m-dataSuper Mario Bros.: The Lost Levels star-cloud-m-dataidentical1,2991,299 bytes of The Lost Levels' music are Super Mario Bros.'s byte for byte: the last bytes of the music headers and the notes of every song SM2MAIN plays, from the star music (`Star_CloudMData`) through the ground music's parts, death, castle, game over, time running out, level end, underground, water and the castle-clear music (`EndOfCastleMusData`).
Super Mario Bros. start … move-all-sprites-offscreenSuper Mario Bros.: The Lost Levels start … move-all-sprites-offscreenchanged664The Lost Levels' boot, NMI and pause code (`Start` through `MoveAllSpritesOffscreen`) is Super Mario Bros.'s with these changes: `Start` sets mirroring through the disk drive's control register, keeps `WorldNumber` across the reset and sets the BIOS's IRQ flag; the NMI arms the drive's timer IRQ to split the status bar from the level, where Super Mario Bros. waits for the sprite 0 hit, and its VRAM address table is one table of 31 words where Super Mario Bros. has low and high byte tables of 19; `PauseRoutine` allows a pause in game-mode task 4 instead of 3, the game mode's task list having gained a disk task at its head. `SpriteShuffler` and `MoveAllSpritesOffscreen` are byte for byte the same, and the operating-mode dispatch differs only in its addresses.
Super Mario Bros. victory-mode … print-victory-messagesSuper Mario Bros.: The Lost Levels victory-mode … print-victory-messageschanged357The castle victory sequence (`VictoryMode` through `PrintVictoryMessages`) is Super Mario Bros.'s with these changes: on world 8, which world D also uses, `VictoryMode` runs a second task list that loads the ending from disk; `SetupVictoryMode` also sets the world's bit in `CompletedWorlds` and queues the castle-clear music; `PrintVictoryMessages` loses Super Mario Bros.'s world 8 branch and its victory music, and gains `EndCastleAward`, which counts the remaining time into points. `DrawTitleScreen`, which sits in the middle, shrinks to a few instructions that queue a layout held in the program, where Super Mario Bros. copies it out of CHR ROM. `PlayerVictoryWalk` keeps every instruction; only its addresses and one branch's distance differ.

Mechanics

MechanicKindHow
JumpSpeed from the runSuper Mario Bros.'s jumps: the faster the run-up, the higher the jump
GravitySwitch on releaseSuper Mario Bros.'s light pull while A is held on the way up, lighter still for Luigi
Variable jump heightGravity switchSuper Mario Bros.'s held jump; Luigi's lighter gravity carries him higher
RunningRun buttonSuper Mario Bros.'s top speeds; Luigi takes longer to speed up, stop, and turn
Invincibility framesSlow timerSuper Mario Bros.'s blink after a hit
WindArea pusha steady push to the right in some outdoor stretches, on average a quarter of Mario's walking speed
SpringboardTimed pressa fresh press of A on the spring launches higher, and green springs launch far higher
Difficulty rampLevel flagfrom 4-4 on, and in worlds A to D, extra enemies appear and hammer bros, Bowser, and the cannons get more aggressive
Enemy spawningGenerateda new Lakitu flies in sooner than in Super Mario Bros. once none is on screen
ContinueUnlimitedat every game over outside World 9, Continue restarts the world from its first level
Extra lifeOther conditiongrabbing the flagpole gives a life when the coin count's two digits match the timer's last digit
Coyote timeNonea jump starts only from the ground, as in Super Mario Bros.
Every claim about this game, by concept (65)
generalThe disk side of Super Mario Bros.: The Lost Levels, counted by part of the game: each stretch of code or data in its eight files goes to the part its code shows it serves, and the value sums the bytes of each part.Code
A warp zone leads to one world, whichever of its pipes the player takes. In world 1 it leads to world 2 from the first underground area, to world 3 from a ground area, and to world 4 from any other; in world 3, back to world 1; in world 5, to world 6 from one ground area (the 12th in the area table, which the disassembly's comment places at 5-1), to world 8 from any other ground area, and to world 7 from any other area; in worlds 2, 4, and 6 to 9, to world 5, which from 6 to 8 is back. In worlds A to D it goes by level: from a second level to world B, a third to world C, a fourth to world D; the table holds no world for a first level.Code
Clearing a world's castle sets that world's bit in a record of completed worlds. After the ending that follows 8-4, the game goes on to World 9 if all eight bits are set, and back to the title screen if any is missing; after D-4 it always goes back to the title. The record is cleared when a game starts and when the player picks Retry at a game over, and Continue keeps it, so a world skipped by a warp counts only if the player warps back and clears its castle.Code
World 9 begins with one life. A game over there ends the game, with no continue menu. Its four levels loop: after 9-4 the game starts 9-1 again.Code
Each time the ending loads, after 8-4 or D-4, the count of games beaten goes up by one, to at most 24 (a short read of the ending's files resets it to 0 first). After 8-4 the game writes the count to the disk's save file (a disk error aside); after D-4 it doesn't, and the title screen, which reloads the disk's first files after a game in worlds A to D or from world 5 on, reads the saved count back, so D-4 adds nothing. The title screen shows a star for each game beaten, in two rows of 12. With 8 or more, holding A while pressing Start begins the game at World A, loading worlds A to D, with their own halfway points, from the disk.Code
Piranha plants are green in worlds 1 to 3 and red in worlds 4 to 9 and A to D. A green one stays in its pipe while the player is less than 33 px from it across, and moves on every second frame; a red one stays in only while the player is less than 19 px away, and moves on every frame.Code
Fireworks go off over the castle when the timer's last digit matches the coin count's last digit as the level ends: three when the digit is odd, six when it is even, and none when they differ.Code
The game came out in Japan on 3 June 1986, as Super Mario Bros. 2 for the Famicom Disk System.Publisher
Famicom Tsūshin's chart in its 1 August 1986 issue lists the disk card at 2,500 yen.Magazine
The manual opens with a letter, "To Super Players", that presents the game as another Mario journey in a parallel world, eight new worlds of varied courses. It says the game has a Mario game and a Luigi game, with Luigi leaping more recklessly than Mario, and warns players not to eat the poison mushroom when it appears.Manual
The game was aimed at players who had mastered the first. Miyamoto recalls a sticker on the package that said "For Super Players", and a note to Nintendo's NES Classic interview describes it as a tougher challenge developed for advanced players. Nintendo's page today pitches it at people who played Super Mario Bros. to exhaustion, with a higher difficulty. Iwata, interviewing the All-Stars developers in 2010, described it the same way: he said they made it for advanced players, and Sugiyama agreed.Web
Nintendo's page counts 52 courses, including those opened by meeting conditions, one and a half times the first game's. It names the poison mushroom and a tailwind that carries the player's body along as new tricks, and says Luigi jumps higher than Mario and slips more.Publisher
Miyamoto calls the game Takashi Tezuka's directorial debut. Tezuka says they made it by changing the first game's difficulty and stage design, and Miyamoto that work on Super Mario Bros. 3 began after it, in the spring of 1986.Interview
Miyamoto recalls that the team used the arcade VS. System, based on the Famicom, to make Super Mario, started changing its levels because they could, and, as they played, made "very challenging levels", and that the game gave infinite 1-ups early to prepare players for what came. IGN's 2010 history says its later stages came from Vs. Super Mario Bros.Web
In America, the Super Mario Bros. 2 that Nintendo released was a different game. Koji Kondo says the Japanese Super Mario Bros. 2 continued the first game directly, while in America it was a remake of Yume Kojo: Doki Doki Panic.Interview
Retrospectives say the game was kept from North America for its difficulty. IGN's 2010 history says Nintendo judged it beyond North American players and canceled its release there; GameSpot's 2007 review puts the call on the head of Nintendo of America; Den of Geek's 2024 article names Howard Phillips.Web
Famicom Tsūshin's shop chart in its 1 August 1986 issue placed the game second, behind Makaimura, and its note said the game had appeared at the top only the week before.Magazine
Famicom Hisshoubon's three reviewers gave it 3, 2, and 2 hearts of 5. Nasubi Kamen asked whether it had only got harder, thought it a cut job, and saw a plain push to sell the Disk System; Tokashiki Minoru, 15, wanted it on a cartridge for friends without a Disk System; Goinkyo no longer felt the first game's fresh surprise and fun, and wondered whether that was because it came across as a pack of bugs and tricks.Magazine
GameSpot's Frank Provo scored the 2007 Wii Virtual Console release 6.5 of 10, calling it a level hack of the first game whose levels are "infinitely more sadistic".Web
GameSpot's October 2007 review says the Wii Virtual Console sold the original, unedited Disk System game for 600 Wii points.Web
Super Mario All-Stars for the Super Famicom collected the game in July 1993, as The Lost Levels, with Super Mario Bros. 1 to 3; it came out in North America in August 1993. Sugiyama, who says he worked on it as an assistant director and designer under another main director, recalls, if he remembers correctly, that Miyamoto proposed the collection; he thinks the idea was to include The Lost Levels to give a game few had played on the Disk System another chance. He says the team added saving, after each level in The Lost Levels, as significant help.Interview
The name The Lost Levels is the one the game carries in English. The earliest use read here is Nintendo Power's September 1993 issue, whose editor explained that the game had been released only in Japan, as Super Mario Bros. 2; who coined the name isn't known.Magazine
Nintendo Power's September 1993 review of Super Mario All-Stars warned that The Lost Levels was "waaayy harder" than the first game, recommended starting with Luigi for his higher jump, and ran a World 9 Challenge: a photo of World 9, reached without warping, by 31 October 1993 earned an iron-on patch.Magazine
IGN's 2010 history describes the game as looking exactly like its predecessor but much harder, with poisonous mushrooms, warps that send the player back, and weather that blows Mario off course.Web
The Lost Levels' boot, NMI and pause code (Start through MoveAllSpritesOffscreen) is Super Mario Bros.'s with these changes: Start sets mirroring through the disk drive's control register, keeps WorldNumber across the reset and sets the BIOS's IRQ flag; the NMI arms the drive's timer IRQ to split the status bar from the level, where Super Mario Bros. waits for the sprite 0 hit, and its VRAM address table is one table of 31 words where Super Mario Bros. has low and high byte tables of 19; PauseRoutine allows a pause in game-mode task 4 instead of 3, the game mode's task list having gained a disk task at its head. SpriteShuffler and MoveAllSpritesOffscreen are byte for byte the same, and the operating-mode dispatch differs only in its addresses.Code
The castle victory sequence (VictoryMode through PrintVictoryMessages) is Super Mario Bros.'s with these changes: on world 8, which world D also uses, VictoryMode runs a second task list that loads the ending from disk; SetupVictoryMode also sets the world's bit in CompletedWorlds and queues the castle-clear music; PrintVictoryMessages loses Super Mario Bros.'s world 8 branch and its victory music, and gains EndCastleAward, which counts the remaining time into points. DrawTitleScreen, which sits in the middle, shrinks to a few instructions that queue a layout held in the program, where Super Mario Bros. copies it out of CHR ROM. PlayerVictoryWalk keeps every instruction; only its addresses and one branch's distance differ.Code
The score numbers, the screen setup tasks, the status bar and the game's text (FloateyNumbersRoutine through ResetScreenTimer) are Super Mario Bros.'s with these changes: GetPlayerColors no longer picks a palette row by CurrentPlayer (Super Mario Bros.'s table has a row for Luigi); WriteBottomStatusLine goes through a new GetWorldNumForDisplay, which shows worlds A to D as letters; DisplayIntermediate blanks the screen after the world and lives screen in world 9, and DisplayTimeUp writes its text and resets the screen timer itself where Super Mario Bros. jumps into DisplayIntermediate; ClearBuffersDrawIcon's title-screen part moves to the title code; the screen task list gains DemoReset; GameText drops the two-player and Luigi texts and adds CONTINUE and RETRY to the game-over screen. InitScreen, SetupIntermediate, GetAreaPalette, GetAlternatePalette1, WriteTopStatusLine, AreaParserTaskControl and ResetScreenTimer keep every instruction, with only addresses changed.Code
The background renderer, the metatile tables and the area palettes (RenderAreaGraphics through the palette data) are Super Mario Bros.'s with the metatiles renumbered: The Lost Levels inserts new metatiles, so ReplaceBlockMetatile compares against shifted numbers ($56, $4F, $5C and $50 for Super Mario Bros.'s $58, $51, $5D and $52), and MetatileGraphics_Low moves some entries and adds others. The palette data region also holds two new messages. RenderAttributeTables is byte for byte the same, and RenderAreaGraphics and ColorRotatePalette differ only in their addresses.Code
JumpEngine, InitializeNameTables, ReadJoypads and UpdateScreen are Super Mario Bros.'s, instruction for instruction: JumpEngine is byte for byte the same, and the other three differ only in the addresses of their calls, jumps and tables.Code
The status bar numbers, game setup, lives and game over (PrintStatusBarNumbers through RunGameOver) are Super Mario Bros.'s with a new GameOverSubs dispatch among them and these changes: the status bar's digit tables lose the second player's entries; UpdateTopScore checks one score where Super Mario Bros. checks two; DigitsMathRoutine drops a compare with zero before its BEQ; DefaultSprOffsets loses the sprite 0 data; InitializeArea loads the player's physics (LoadPhysicsData) and sets the secondary hard mode flag from 4-4 on and in all of worlds A to D (HardWorldFlag), where Super Mario Bros. sets it from 5-3 on or once the primary hard mode flag is set; SecondaryGameSetup sets the name table and switches on the status bar's IRQ split, where Super Mario Bros. sets the second player's lives and switches on the sprite 0 check; InitializeMemory also spares $0100-$0108; PlayerLoseLife reads its own halfway pages and no longer swaps players; RunGameOver opens the continue-or-retry menu (or, in world 9, ends the game) where Super Mario Bros. ends the game on Start or when the screen timer runs out and then hands over to the other player if they have lives left. GetAreaMusic and Entrance_GameTimerSetup keep every instruction, though the level timer's digits moved from $07F8 to $07EC.Code
The area parser and its object builders (AreaParserTaskHandler through GetBlockBufferAddr) are Super Mario Bros.'s, with most changes in the metatile numbers they write, which shift with the renumbered metatiles (bridges, flagpole, coins, bricks, cannons, stairs, blocks, water pipe). Beyond those: the object jump table gains entries, the wind on and off commands among them, so three offsets into it change; ScrollLockObject_Warp picks the warp zone's destination by world, level and area; the third ledge style uses metatiles $8A-$8C and draws no stem, where Super Mario Bros.'s mushroom ledge uses $19-$1B with a stem (and RenderUnderPart drops its stem checks); the vertical pipes place a piranha plant through a shared SetupPiranhaPlant, with no exception for world 1-1; Jumpspring places nothing when no enemy slot is free. IncrementColumnPos, AlterAreaAttributes, KillEnemies and the object position helpers are byte for byte the same.Code
GameCoreRoutine and ScrollHandler are Super Mario Bros.'s with three changes: the game mode's task list gains GameModeDiskRoutines at its head and the core no longer reads the current player's saved joypad bits; each frame of play calls SimulateWind once a disk file beyond worlds 1 to 4 is loaded; ScrollHandler waits for the status bar's timer IRQ before it scrolls and keeps the name table in NameTableSelect, where Super Mario Bros. sets it in its PPU control mirror. GetScreenPosition is byte for byte the same.Code
The player's control and movement code (GameRoutines through ImposeFriction) is Super Mario Bros.'s, instruction for instruction in 14 of its 19 regions, with these changes: OnGroundStateSub and the jump and swim code move the player through a new JmpMove, which lets the wind push them (BlowPlayerAround) once a disk file beyond worlds 1 to 4 is loaded; PlayerPhysicsSub's friction table moves up to follow the fall forces, inside the 17 bytes that LoadPhysicsData overwrites with Mario's or Luigi's set; PlayerEndLevel queues the level-end music once, guarded by a new FlagpoleMusicFlag, where Super Mario Bros. queues it whenever ScrollLock is set, and sets the hidden 1-up's flag on 10 coins in any world, where Super Mario Bros. reads a per-world table, and starts world 9 over after 9-4; PlayerDeath shares one RTS. The entrances, pipes, size change, injury blink, flagpole slide, falling, climbing, animation speed and ImposeFriction differ only in their addresses.Code
Fireballs, the level timer and the stage objects (ProcFireballs through VineObjectHandler) are Super Mario Bros.'s with these changes: RunGameTimer tests the player's height with BPL instead of BCS and points at the timer digits' new place; WarpZoneObject no longer counts up WarpZoneControl; FlagpoleRoutine gives a life for the new sixth flagpole score; JumpspringHandler launches with the green springs' force on world numbers 2, 3 and 7; VineObjectHandler erases the vine and its metatiles once it goes off the left of the screen. ProcFireballs and ProcessWhirlpools differ only in their addresses, and SetupVine is byte for byte the same.Code
Cannons, hammers, coins, power-ups and blocks (ProcessCannons through BlockObjMT_Updater) are Super Mario Bros.'s with the poison mushroom added and one player: BumpBlock's contents table gains poison mushroom blocks and MushFlowerBlock gains PoisonMushBlock, which sets power-up type 4; PowerUpObjHandler walks types 4 and 5 like a mushroom; BlockBumpedChk checks 19 block metatiles where Super Mario Bros. checks 14; GiveOneCoin and AddToScore use fixed offsets where Super Mario Bros. indexes by CurrentPlayer; the head-collision and coin checks use the renumbered metatiles. SetupPowerUp is byte for byte Super Mario Bros.'s, though the poison mushroom now passes through it, and so are InitBlock_XY_Pos and SpawnBrickChunks; the cannons, hammers, jumping coins, brick shatter and bouncing blocks differ only in their addresses.Code
Enemy spawning and set-up (EnemiesAndLoopsCore through InitJumpGPTroopa) are Super Mario Bros.'s with these changes: ProcLoopCommand reads 12 loop entries where Super Mario Bros. reads 11, and takes each loop's number of checks from a new MultiLoopCount table where Super Mario Bros. special-cases world 7; ProcessEnemyData skips a check in world 9 and gives one enemy code a piranha plant set-up; InitHammerBro checks the world; LakituAndSpinyHandler brings Lakitu back once LakituReappearTimer reaches 3, where Super Mario Bros. waits until it reaches 7, and brings him back lower on the screen in worlds 7 to 9 and A to D; InitBowser first erases any other Bowser; InitPiranhaPlant patches the plant's palette and pipe distance, green in worlds 1 to 3 and red from world 4 and in A to D; InitJumpGPTroopa starts the jumping paratroopa at x speed $F4 where Super Mario Bros. uses $F8. Of its 27 regions, 15 differ only in their addresses and 5 are byte for byte the same.Code
The platforms' set-up, the enemy object loop, the enemies' movers, Bowser and the fireworks (InitBalPlatform through RunFireworks, 32 regions) are Super Mario Bros.'s instruction for instruction, with two changes: the enemy movers' jump table (EnemyMovementSubs) sends enemy 4, the upside-down piranha plant, to the new MoveUpsideDownPiranhaP, where Super Mario Bros. has MoveNormalEnemy; MoveSwimmingCheepCheep adds $40 to a swimming Cheep Cheep's vertical fraction each frame where Super Mario Bros. adds $20. Three of the regions are byte for byte the same, and the rest differ only in the addresses of their calls, jumps and tables.Code
RunStarFlagObj through OffscreenBoundsCheck are Super Mario Bros.'s with these changes: RunStarFlagObj sets off fireworks when the timer's last digit matches the coin tally's, where Super Mario Bros. matches the timer's last digit against 1, 3 and 6, and adds its points to the one player's score; MovePiranhaPlant moves red piranha plants (the patched palette) every frame; BalancePlatform leaves a platform alone when its partner is no balance platform; OffscreenBoundsCheck treats upside-down piranha plants like upright ones. FirebarSpin is byte for byte the same, and the moving platforms differ only in their addresses.Code
The collision code (FireballEnemyCollision through BlockBufferCollision) is Super Mario Bros.'s with the upside-down piranha plant, the poison mushroom and the renumbered metatiles added: the fireball, enemy, background and stomp checks treat the upside-down plant like a piranha plant; HandlePowerUpCollision injures the player on power-up type 4; InjurePlayer also does nothing while the star's StarInvincibleTimer runs; HandlePECollisions checks for the cannon's Bullet Bill before the piranha plants and Podoboo, where Super Mario Bros. checks it after them; PlayerEnemyCollision decides a stomp with LDY, DEY, BPL on the vertical speed where Super Mario Bros. uses BMI and BNE (the two disagree only at speed $80); every stomp bounces the player through a new SetBounce, at vertical speed $FA, or $F8 off red paratroopas and flying green paratroopas, where Super Mario Bros. sets $FD after a stomp that defeats an enemy and $FC after one that demotes a paratroopa or knocks an enemy into its shell; HandleClimbing gives a life for grabbing the flagpole when the coin tally's digits and the timer's last digit match; HandlePipeEntry sends the player to the warp zone's one destination whichever pipe they take, where Super Mario Bros. picks by the pipe's x position; HandleCoinMetatile's axe restores Mario's physics; ChkForLandJumpSpring sets VerticalForceDown to $70 as well as VerticalForce; PlayerHammerCollision also skips while the player is off screen; HandleEToBGCollision bounces a power-up on a bumped block without stunning it and never demotes a piranha plant; CheckPlayerVertical drops its test of how far down the screen the player is; one bounding box grows from $14 to $16. The platform collisions, LandEnemyProperly, the side checks and BlockBufferCollision differ only in their addresses, and three regions, PlayerCollisionCore among them, are byte for byte the same.Code
GameMenuRoutine and DemoEngine are Super Mario Bros.'s menu and demo, rewritten in part: the menu drops the one- or two-player choice and the world select, and starts the game at world 1, or at world A when A is held and the game has been beaten 8 times; Select switches between Mario and Luigi; the demo plays new button presses and durations through the same code.Code
The sound engine (SoundEngine through MusicHandler) is Super Mario Bros.'s with two new sounds in the noise handler: the skid, played on the triangle channel from SkidSfxFreqData, and the wind, played from WindFreqEnvData; both tables sit after the square 2 handler. SoundEngine, Dump_Squ1_Regs, Square1SfxHandler and MusicHandler differ only in their addresses.Code
AlternateSoundEngine, the ending's sound engine in SM2DATA3, is a rewrite of Super Mario Bros.'s MusicHandler that keeps its note and length code: it has no event or area music buffers and no time-running-out handling, steps through a list of patterns with PatternNumber, reading each pattern's header from MusicHeaderData, has its own pause and silence code, and plays the ending's music on the disk system's wavetable channel as well as the square, triangle and noise channels, with its own waveform, envelope and modulation tables.Code
The player's 80 sprite tiles, $00-$4F of the sprite pattern table, are Super Mario Bros.'s byte for byte.Code
Sprite tiles $50-$FF are Super Mario Bros.'s but for 15: $5B, $76-$7B, $85, $86, $D8, $DA, $DB and $FD-$FF differ, among them $76-$79, Super Mario Bros.'s mushroom, which The Lost Levels' enemy table now draws, and the mushrooms' new tiles.Code
The font, background tiles $00-$23 (the digits and A to Z), keeps Super Mario Bros.'s layout, so GameText spells with the same numbers, but every one of its 36 tiles differs from Super Mario Bros.'s.Code
Background tiles $24-$EB are Super Mario Bros.'s but for 65 of their 200: $28, $29, $2B-$2D, $30-$3C, $45, $47, $4B, $4C, $4E-$52, $5D, $5E, $6B-$76, $80, $81, $9B-$9E, $A0, $A1, $A9, $AA, $AF, $B4-$BD, $C0, $C1 and $CF differ.Code
ContinueAt a game over outside World 9, Select switches between CONTINUE and RETRY and Start picks. Continue restarts the current world at its first level, small, with three lives, the score and coins at zero, and the hidden 1-up available again. Retry ends the game and clears the record of completed worlds.Code
Coyote timeProcJumping starts a jump only while Player_State is 0, on the ground, or while the player is swimming, as Super Mario Bros.'s does. Walking off a ledge doesn't keep that state: PlayerBGCollision sets a player in the normal or climbing state to falling (or, swimming, to state 1) on each frame of play before it looks for ground, and only landing on a block sets the state back to 0, so out of water a jump can't start after walking off a ledge. The background check skips that step only during the game's scripted routines (GameEngineSubroutine 0 to 3 and $0B).Code
Difficulty rampEvery area from World 4-4 on, and every area of worlds A to D, starts with the secondary hard mode flag set; the areas of worlds 1 to 3 and 4-1 to 4-3 start without it. The memory clear at the start of each area resets it first.Code
With the secondary hard mode flag set: enemies the level data marks for hard mode appear, where otherwise they are skipped; a Bullet Bill cannon is picked to fire when a pseudorandom number masked to three bits is below 6 (6 of 8 values, against 6 of 16 with four bits); up to four flying Cheep Cheeps at once instead of three; hammer bros throw on a shorter timer ($1C against $30), can take the longer of two jump timers ($37 against $20), and in worlds 1 to 6 wait a shorter time before walking left ($50 against $80; in worlds 7 to 9 they don't wait either way, and worlds A to D, which share world numbers 1 to 4 and always have the flag, take $50); Bloopers pick a new direction when two pseudorandom bits are clear rather than six, and then a Blooper in an even enemy slot turns toward the player, one in an odd slot takes the player's moving direction; Bowser's fire breath and the flames that fly in on their own come 16 timer ticks sooner, and the flames move faster ($60 subtracted from their fractional position each frame, against $40); and the large lifts are drawn four sprites wide instead of six with a smaller box, as they always are in castles, with balance platforms and their ropes placed for the shorter width.Code
The code keeps the primary hard mode flag's checks, which turn Goombas into Buzzy Beetles, start walking enemies faster ($F4 against $F8), and revive stomped enemies sooner and send them off faster. Nothing in The Lost Levels' code sets the flag, and starting a game clears it, so none of these takes effect. Super Mario Bros. sets it from its world select flag when a game starts.Code
Enemy spawningWhile Lakitu's stretch of a level runs, the game checks every 128 frames whether a Lakitu is on screen. When none is, it counts the check, and on the third it sends a new Lakitu if an enemy slot is free (if none is, it tries again at the next check); the count starts over when a Lakitu is set up. The new one flies high in worlds 1 to 6 ($20) and lower in worlds 7 to 9 and A to D ($60). When one is on screen, the same check leads to the Spiny throw, not covered here.Code
Extra lifeGrabbing the flagpole gives an extra life in place of the height's points when the coin count's two digits are the same and match the timer's last digit (11 coins with the timer ending in 1, for example).Code
GravityThe movement and gravity routines (MoveObjectHorizontally through ImposeGravity) are Super Mario Bros.'s, instruction for instruction: ImposeGravity and MoveDropPlatform are byte for byte the same, and the other seven differ only in the addresses of their calls and jumps.Code
Invincibility framesA hit on big Mario sets InjuryTimer to 8, as in Super Mario Bros., and the timer counts down once every 21 frames with the interval timers, through the same timer loop as Super Mario Bros.'s.Code
JumpThe Lost Levels keeps Super Mario Bros.'s movement tables for Mario byte for byte. Take-off speeds, held and falling gravities, frictions, and top speeds all match.Code
Picking Luigi copies his own gravities and frictions over Mario's: held gravity $18–$22 for the five jump rows against Mario's $1E–$28, falling gravity $3E–$5D against $60–$90, and friction $B4, $68, $A0 against $E4, $98, $D0. It also writes an RTS over the ASL that doubles Mario's friction when he faces away from his motion. His take-off speeds are Mario's. Each area's setup loads the chosen player's set; the axe at the end of a castle loads Mario's set and ASL back for the walk that follows, whoever is playing, until the next area loads the player's own again.Code
Level loadingLoadAreaPointer, FindAreaPointer and GetAreaDataAddrs are Super Mario Bros.'s, with the area data address tables made tables of words (indexed with an ASL) where Super Mario Bros. keeps separate low and high byte tables; the tables themselves hold The Lost Levels' worlds, and AreaDataOfsLoopback its 12 loop points. Of the level data, only the 9-byte pipe intro area (L_GroundArea10) is byte for byte Super Mario Bros.'s.Code
MetaspritesThe sprite drawing code (DrawVine through DrawSpriteObject) is Super Mario Bros.'s with these changes: DrawPowerUp draws every mushroom from tiles $D8, $DA, $DB and $FF where Super Mario Bros. uses $76-$79, and gives the poison mushroom, a fifth row, palette 3; EnemyGfxHandler's tile table takes up $76-$79, and the handler also flips the upside-down piranha plants and colors the jumpsprings green on world numbers 2, 3 and 7; RenderPlayerSub plays the skid sound; FlagpoleGfxHandler's score table gains the 1-up; GetYOffscreenBits has two of its tables' halves swapped, its instructions unchanged; DrawBlock uses a renumbered metatile. 12 regions, PlayerGfxHandler among them, differ only in their addresses, and five, DrawSpriteObject among them, are byte for byte the same.Code
Music driverSM2MAIN's music data is Super Mario Bros.'s less the victory theme: the headers lose VictoryMusHdr and their offsets shift by its five bytes, the residual header bytes differ, and VictoryMusData is gone from between the castle-clear music and the frequency tables, with two of the three unused bytes after it (the ending's music lives in SM2DATA3). The notes of every other song and the frequency, note-length and envelope tables after them are byte for byte the same.Code
1,299 bytes of The Lost Levels' music are Super Mario Bros.'s byte for byte: the last bytes of the music headers and the notes of every song SM2MAIN plays, from the star music (Star_CloudMData) through the ground music's parts, death, castle, game over, time running out, level end, underground, water and the castle-clear music (EndOfCastleMusData).Code
Power-upA poison mushroom comes out of a block of its own kind, and stays a poison mushroom whatever the player's size, where an ordinary mushroom block gives a fire flower to a big or fiery player. It slides along like a mushroom. Touching it removes it and runs the injury routine: a small player dies, and a big or fiery one drops straight to small, with the blink that follows any hit. During that blink, or while a star's invincibility lasts, it is removed and does nothing.Code
The poison mushroom is drawn from the same four tiles as the mushroom and the 1-up mushroom ($D8, $DA, $DB, $FF) in sprite palette 3, where the mushroom uses palette 2 and the 1-up palette 1. Like them it keeps its colors, where the fire flower and the star cycle theirs.Code
SpringboardLanding on a springboard sets both the held and the falling gravity to $70 and a launch speed of −7 px a frame ($F9). Over the spring's four steps it carries the player down 2 px a step, then up 2 px a step, and on the last step it launches them. A press of A, not held from before, in the second step or later raises the launch to −12 px a frame ($F4), or to −32 px a frame ($E0) on the green springboards of world numbers 2, 3, and 7, which the letter worlds share as B and C, since the test reads the world number without the letter-world flag. With both gravities at $70, the bounce rises and falls under one pull whether A is held or not, for Mario and Luigi alike. While the game's timers are stopped the spring waits.Code
WindWind blows the player to the right. An area object turns it on (WindOn) and another off (WindOff), and the setup that runs at the start of every area clears it. While it is on, and only in ground-type areas (underground, water, and castle areas stay calm), it moves the player 1 px right on every fourth frame while the frame counter is below 128 and on every second frame from 128 to 255: 96 px every 256 frames, 0.375 px a frame on average. The push is added to the position after the player's own move, on the ground and in the air but not while climbing, so it adds to a rightward speed and takes from a leftward one whatever the speed, and the screen scrolls with it. Its leaves and sound play while it is on, in every type of area. None of it runs until the game has loaded a disk file beyond worlds 1 to 4 (worlds 5 to 8, the ending, or worlds A to D): before that, FileListNumber is 0 and both calls are skipped.Code

References

  1. ^ abThe game came out in Japan on 3 June 1986, as Super Mario Bros. 2 for the Famicom Disk System.PublisherNintendo, Virtual Console SMB 2 · Iwata Asks, Mario 25th · Super Mario Bros. 2 (FDS) manual
    How we know
    1986年6月3日にディスクシステム用ソフトとして発売されました
    Virtual Console page, introduction · archived copy ↗
    Super Mario Bros. 2: The second Super Mario action game released for the Family Computer Disk System on June 3, 1986.
    footnote 5 · archived copy ↗
    To Super Players June 3, 1986
    p. 2, "To Super Players" · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  2. ^The manual opens with a letter, "To Super Players", that presents the game as another Mario journey in a parallel world, eight new worlds of varied courses. It says the game has a Mario game and a Luigi game, with Luigi leaping more recklessly than Mario, and warns players not to eat the poison mushroom when it appears.ManualSuper Mario Bros. 2 (FDS) manual · Nintendo, Virtual Console SMB 2
    How we know
    つのマリオの旅(パラレルワールド)を創ってみました。 … この変化に富んだコースの新しい8ワールド … マリオゲームとルイージゲームがあり … ルイージはマリオより無鉄砲に飛び上がります。 … 食べないようにしてください
    p. 2, "To Super Players" · archived copy ↗
    本作は『スーパーマリオブラザーズ』のパラレルワールドを舞台にした、マリオとルイージの新たな冒険のお話です。
    Virtual Console page, introduction · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  3. ^The game was aimed at players who had mastered the first. Miyamoto recalls a sticker on the package that said "For Super Players", and a note to Nintendo's NES Classic interview describes it as a tougher challenge developed for advanced players. Nintendo's page today pitches it at people who played Super Mario Bros. to exhaustion, with a higher difficulty. Iwata, interviewing the All-Stars developers in 2010, described it the same way: he said they made it for advanced players, and Sugiyama agreed.WebNintendo Channel Miyamoto interview (TMK transcript) · Iwata Asks, Super Mario All-Stars · NES Classic developer interview · Nintendo, Famicom SMB 2 pagerevised
    How we know
    But we thought it would be hard for first time players so we put a sticker on the package that said "For Super Players".
    Super Mario Bros.: The Lost Levels · archived copy ↗
    Some might not have been fully satisfied by the first Super Mario, so we made The Lost Levels for advanced players.
    Iwata · archived copy ↗
    It looked and played very similar to the first Super Mario Bros., but with a tougher challenge level developed for advanced players.
    footnote 6 · archived copy ↗
    『スーパーマリオブラザーズ』を遊び尽くした人に向けた、前作よりも高い難易度!
    introduction · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  4. ^ abNintendo's page counts 52 courses, including those opened by meeting conditions, one and a half times the first game's. It names the poison mushroom and a tailwind that carries the player's body along as new tricks, and says Luigi jumps higher than Mario and slips more.PublisherNintendo, Famicom SMB 2 page
    How we know
    条件を満たすと遊べるものも含めて全52コース。 前作の1.5倍ものコースが待ち受けている。 … 取るとダメージを受ける「毒キノコ」や体が勝手に流される「追い風」など … ルイージはマリオよりジャンプが高く、滑りやすい。
    introduction · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  5. ^Miyamoto calls the game Takashi Tezuka's directorial debut. Tezuka says they made it by changing the first game's difficulty and stage design, and Miyamoto that work on Super Mario Bros. 3 began after it, in the spring of 1986.InterviewNES Classic developer interview
    How we know
    had been Tezuka-san's directorial debut. That went well, so we decided to make a completely new game.
    Miyamoto · archived copy ↗
    We made Super Mario Bros.: The Lost Levels by changing the original game's difficulty and stage design
    Tezuka · archived copy ↗
    We began after Super Mario Bros.: The Lost Levels in the spring of 1986
    Miyamoto · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  6. ^Miyamoto recalls that the team used the arcade VS. System, based on the Famicom, to make Super Mario, started changing its levels because they could, and, as they played, made "very challenging levels", and that the game gave infinite 1-ups early to prepare players for what came. IGN's 2010 history says its later stages came from Vs. Super Mario Bros.WebNintendo Channel Miyamoto interview (TMK transcript) · IGN, History of Super Mario Bros.revised
    How we know
    There was an arcade system called the VS system that was based off of the Famicom. We decided to use that to make Super Mario and we started changing the levels because we could. As we played with it we made very challenging levels. We thought it would be fun if the levels got even harder, and we worked on it. … We made it so you could get infinite 1-UPs from the beginning to prepare you for the levels to come
    Super Mario Bros.: The Lost Levels · archived copy ↗
    Latter stages were cannibalized from "Vs. Super Mario Bros.", a largely redesigned arcade port of the original.
    Super Mario Bros. 2 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  7. ^In America, the Super Mario Bros. 2 that Nintendo released was a different game. Koji Kondo says the Japanese Super Mario Bros. 2 continued the first game directly, while in America it was a remake of Yume Kojo: Doki Doki Panic.InterviewIwata Asks, Super Mario All-Starsrevised
    How we know
    What we called Super Mario Bros. 2 in Japan … was a direct continuation to the original Super Mario Bros., but in America it was a remake of Yume Kojo: Doki Doki Panic.
    Kondo · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  8. ^ abRetrospectives say the game was kept from North America for its difficulty. IGN's 2010 history says Nintendo judged it beyond North American players and canceled its release there; GameSpot's 2007 review puts the call on the head of Nintendo of America; Den of Geek's 2024 article names Howard Phillips.WebIGN, History of Super Mario Bros. · GameSpot, The Lost Levels review · Den of Geek, the "real" Super Mario Bros. 2
    How we know
    Nintendo decided Mario 2's difficulty level exceeded North American skill level. Rather than risk the franchise's popularity, they canceled its stateside release and looked for an alternative.
    Super Mario Bros. 2 · archived copy ↗
    However, the head honcho of Nintendo of America at the time felt the game would be too challenging for players in the west.
    review, first paragraph · archived copy ↗
    It was famed Nintendo Power creator Howard Phillips who made the decision to not import the Japanese version of the game for that reason.
    I'm Sorry, You're Just Too Darn Difficult · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  9. ^ abFamicom Tsūshin's shop chart in its 1 August 1986 issue placed the game second, behind Makaimura, and its note said the game had appeared at the top only the week before.MagazineFamitsu 4
    How we know
    今週堂々の1位は『魔界村』だ。
    p. 4, Famitsu TOP 30 · archived copy ↗
    おやっ、先週トップで登場したばかりなのに、もう1ランクダウン
    p. 4, Famitsu TOP 30, no. 2 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  10. ^ abFamicom Hisshoubon's three reviewers gave it 3, 2, and 2 hearts of 5. Nasubi Kamen asked whether it had only got harder, thought it a cut job, and saw a plain push to sell the Disk System; Tokashiki Minoru, 15, wanted it on a cartridge for friends without a Disk System; Goinkyo no longer felt the first game's fresh surprise and fun, and wondered whether that was because it came across as a pack of bugs and tricks.MagazineFamicom Hisshoubon 6
    How we know
    ねえ、これただムズかしくなっただけ?他に変化はないの? … 手抜きだと思う … ディスクシステムを買わせようというのもみえみえ … 絶対カセットで出してほしかった。ボクはディスクシステムを持ってるからうれしかったけど、持ってない友だちはかわいそうだ。 … しかし前作マリオの様な、新鮮な驚きや楽しさはもう感じなかった … バグ・裏ワザパックという印象が強いからだろうか。
    p. 119, cross review, Super Mario Bros. 2 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  11. ^ abSuper Mario All-Stars for the Super Famicom collected the game in July 1993, as The Lost Levels, with Super Mario Bros. 1 to 3; it came out in North America in August 1993. Sugiyama, who says he worked on it as an assistant director and designer under another main director, recalls, if he remembers correctly, that Miyamoto proposed the collection; he thinks the idea was to include The Lost Levels to give a game few had played on the Disk System another chance. He says the team added saving, after each level in The Lost Levels, as significant help.InterviewIwata Asks, Super Mario All-Stars · Nintendo, Super NES Games · Nintendo Power 52revised
    How we know
    Super Mario All-Stars: Released for the Super Famicom system in July 1993. It includes four games: Super Mario Bros., Super Mario Bros. 2, Super Mario Bros. 3 and Super Mario Bros.: The Lost Levels.
    footnote 1 · archived copy ↗
    Super Mario All-Stars Nintendo August 1993
    Super Mario All-Stars · archived copy ↗
    Release Date August 1993
    p. 100, Pak Watch · archived copy ↗
    Someone else was the main director. I lent support as an assistant director and designer. … If I remember correctly, Miyamoto-san brought it up a little while after development of Super Mario Kart … I think the idea was to include the Lost Levels … a game not many had played on the Disk System, thereby giving people another opportunity to play it. … That made it possible to save after each level in The Lost Levels. The intention was to offer some significant help.
    Sugiyama · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  12. ^ abThe name The Lost Levels is the one the game carries in English. The earliest use read here is Nintendo Power's September 1993 issue, whose editor explained that the game had been released only in Japan, as Super Mario Bros. 2; who coined the name isn't known.MagazineNintendo Power 52 · Iwata Asks, Mario 25th
    How we know
    Levels was originally released only in Japan … and was titled Super Mario Bros. 2, while the SMB 2 that you all know is called Super Mario Bros. USA in Japan.
    p. 7, Editor's Corner · archived copy ↗
    This game is known as Super Mario Bros.: The Lost Levels in the US.
    footnote 5 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  13. ^Nintendo Power's September 1993 review of Super Mario All-Stars warned that The Lost Levels was "waaayy harder" than the first game, recommended starting with Luigi for his higher jump, and ran a World 9 Challenge: a photo of World 9, reached without warping, by 31 October 1993 earned an iron-on patch.MagazineNintendo Power 52
    How we know
    This game is waaayy harder than the original SMB.
    p. 16 · archived copy ↗
    Luigi can jump higher, so we recommend playing with Luigi when you first begin to play the game.
    p. 18 · archived copy ↗
    you can only reach World 9 of the Lost Levels if you play every single torturous level. Absolutely no warping! … Send us a photo of your accomplishment, and we'll send you this great iron-on patch. … The deadline is October 31, 1993.
    p. 22, World 9 Challenge · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  14. ^ abGameSpot's Frank Provo scored the 2007 Wii Virtual Console release 6.5 of 10, calling it a level hack of the first game whose levels are "infinitely more sadistic".WebGameSpot, The Lost Levels review
    How we know
    Basically just a level hack for the original Super Mario Bros.
    The Bad · archived copy ↗
    the level layouts aren't as memorable, and they're infinitely more sadistic
    review · archived copy ↗
    If you want a tough Super Mario Bros., here you go
    The Good · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  15. ^GameSpot's October 2007 review says the Wii Virtual Console sold the original, unedited Disk System game for 600 Wii points.WebGameSpot, The Lost Levels review
    How we know
    At 600 Wii points, the original, unedited rendition of Super Mario Bros. 2 is a decent buy
    review, last paragraph · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  16. ^IGN's 2010 history describes the game as looking exactly like its predecessor but much harder, with poisonous mushrooms, warps that send the player back, and weather that blows Mario off course.WebIGN, History of Super Mario Bros.
    How we know
    Visually, it looked exactly like its predecessor, but it was harder... much harder. … some mushrooms were poisonous, some warps sent you back instead of forward, and inclement weather regularly kicked Mario off-course in mid-chasm jump.
    Super Mario Bros. 2 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  17. ^ abThe Lost Levels keeps Super Mario Bros.'s movement tables for Mario byte for byte. Take-off speeds, held and falling gravities, frictions, and top speeds all match.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1
    How we know
    4955JumpMForceData:
    4956      .byte $20, $20, $1e, $28, $28, $0d, $04
    ⋮
    4958FallMForceData:
    4959      .byte $70, $70, $60, $90, $90, $0a, $09
    ⋮
    4961FrictionData:
    4962      .byte $e4, $98, $d0
    ⋮
    4964PlayerYSpdData:
    4965      .byte $fc, $fc, $fc, $fb, $fb, $fe, $ff
    ⋮
    4967InitMForceData:
    4968      .byte $00, $00, $00, $00, $00, $80, $00
    ⋮
    4970MaxLeftXSpdData:
    4971      .byte $d8, $e8, $f0
    ⋮
    
    sm2main.asm lines 4955–4974 at 9c40114 · upstream ↗
    4858JumpMForceData:
    4859	.db $20, $20, $1e, $28, $28, $0d, $04
    ⋮
    4861FallMForceData:
    4862	.db $70, $70, $60, $90, $90, $0a, $09
    ⋮
    4864PlayerYSpdData:
    4865	.db $fc, $fc, $fc, $fb, $fb, $fe, $ff
    ⋮
    4867InitMForceData:
    4868	.db $00, $00, $00, $00, $00, $80, $00
    ⋮
    4870MaxLeftXSpdData:
    4871	.db $d8, $e8, $f0
    ⋮
    4873MaxRightXSpdData:
    4874	.db $28, $18, $10
    ⋮
    
    src/prg.asm lines 4858–4878 at 1cc3c92 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  18. ^ProcJumping starts a jump only while Player_State is 0, on the ground, or while the player is swimming, as Super Mario Bros.'s does. Walking off a ledge doesn't keep that state: PlayerBGCollision sets a player in the normal or climbing state to falling (or, swimming, to state 1) on each frame of play before it looks for ground, and only landing on a block sets the state back to 0, so out of water a jump can't start after walking off a ledge. The background check skips that step only during the game's scripted routines (GameEngineSubroutine 0 to 3 and $0B).Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1revised
    How we know
    5015ProcJumping:
    5016           lda Player_State           ;check player state
    5017           beq InitJS                 ;if on the ground, branch
    5018           lda SwimmingFlag           ;if swimming flag not set, jump to do something else
    5019           beq NoJump                 ;to prevent midair jumping, otherwise continue
    
    sm2main.asm lines 5015–5019 at 9c40114 · upstream ↗
    10936          lda GameEngineSubroutine
    10937          cmp #$0b                  ;if running routine #11 or $0b
    10938          beq ExPBGCol              ;branch to leave
    10939          cmp #$04
    10940          bcc ExPBGCol              ;if running routines $00-$03 branch to leave
    10941          lda #$01                  ;load default player state for swimming
    10942          ldy SwimmingFlag          ;if swimming flag set,
    10943          bne SetPSte               ;branch ahead to set default state
    10944          lda Player_State          ;if player in normal state,
    10945          beq SetFallS              ;branch to set default state for falling
    10946          cmp #$03
    10947          bne ChkOnScr              ;if in any other state besides climbing, skip to next part
    ⋮
    
    sm2main.asm lines 10936–10949 at 9c40114 · upstream ↗
    11046LandPlyr: jsr ChkForLandJumpSpring   ;do sub to check for jumpspring metatiles and deal with it
    11047          lda #$f0
    11048          and Player_Y_Position      ;mask out lower nybble of player's vertical position
    11049          sta Player_Y_Position      ;and store as new vertical position to land player properly
    11050          jsr HandlePipeEntry        ;do sub to process potential pipe entry
    11051          lda #$00
    11052          sta Player_Y_Speed         ;initialize vertical speed and fractional
    11053          sta Player_Y_MoveForce     ;movement force to stop player's vertical movement
    11054          sta StompChainCounter      ;initialize enemy stomp counter
    11055InitSteP: lda #$00
    11056          sta Player_State           ;set player's state to normal
    
    sm2main.asm lines 11046–11056 at 9c40114 · upstream ↗
    4921ProcJumping:
    4922	LDA Player_State                             ; check player state
    4923	BEQ InitJS                                   ; if on the ground, branch
    4924	LDA SwimmingFlag                             ; if swimming flag not set, jump to do something else
    4925	BEQ NoJump                                   ; to prevent midair jumping, otherwise continue
    
    src/prg.asm lines 4921–4925 at 1cc3c92 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-21.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  19. ^A hit on big Mario sets InjuryTimer to 8, as in Super Mario Bros., and the timer counts down once every 21 frames with the interval timers, through the same timer loop as Super Mario Bros.'s.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1revised
    How we know
    10424      lda InjuryTimer          ;check again to see if either of the two
    10425      ora StarInvincibleTimer  ;invincibility timers have expired, branch if not
    10426      bne ExInjColRoutines
    ⋮
    10428ForceInjury:
    10429          ldx PlayerStatus          ;check player's status
    10430          beq KillPlayer            ;branch if small
    10431          sta PlayerStatus          ;otherwise set player's status to small
    10432          lda #$08
    10433          sta InjuryTimer           ;set injured invincibility timer
    
    sm2main.asm lines 10424–10433 at 9c40114 · upstream ↗
    928   ldx #$14                  ;set offset to decrement only frame timers
    929   dec IntervalTimerControl  ;if interval timer control not expired, branch
    930   bpl DecrTheTimers         ;to skip and thus decrement only frame timers
    931   lda #$14
    932   sta IntervalTimerControl  ;otherwise reset interval timer control to 20 frames
    933   ldx #$23                  ;and load offset to decrement frame and interval timers
    
    sm2main.asm lines 928–933 at 9c40114 · upstream ↗
    81Timers                = $0780
    ⋮
    99InjuryTimer           = $079e
    
    sm2main.asm lines 81–99 at 9c40114 · upstream ↗
    10583InjurePlayer:
    10584	LDA InjuryTimer                              ; check again to see if injured invincibility timer is
    10585	BNE ExInjColRoutines                         ; at zero, and branch to leave if so
    ⋮
    10587ForceInjury:
    10588	LDX PlayerStatus                             ; check player's status
    10589	BEQ KillPlayer                               ; branch if small
    10590	STA PlayerStatus                             ; otherwise set player's status to small
    10591	LDA #$08
    10592	STA InjuryTimer                              ; set injured invincibility timer
    
    src/prg.asm lines 10583–10592 at 1cc3c92 · upstream ↗
    126DecTimers:
    127	LDX #$14                                     ; load end offset for end of frame timers
    128	DEC IntervalTimerControl                     ; decrement interval timer control,
    129	BPL DecTimersLoop                            ; if not expired, only frame timers will decrement
    130	LDA #$14
    131	STA IntervalTimerControl                     ; if control for interval timers expired,
    132	LDX #$23                                     ; interval timers will decrement along with frame timers
    133DecTimersLoop:
    134	LDA Timers,x                                 ; check current timer
    135	BEQ SkipExpTimer                             ; if current timer expired, branch to skip,
    136	DEC Timers,x                                 ; otherwise decrement the current timer
    137SkipExpTimer:
    ⋮
    
    src/prg.asm lines 126–139 at 1cc3c92 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  20. ^ abcPicking Luigi copies his own gravities and frictions over Mario's: held gravity $18–$22 for the five jump rows against Mario's $1E–$28, falling gravity $3E–$5D against $60–$90, and friction $B4, $68, $A0 against $E4, $98, $D0. It also writes an RTS over the ASL that doubles Mario's friction when he faces away from his motion. His take-off speeds are Mario's. Each area's setup loads the chosen player's set; the axe at the end of a castle loads Mario's set and ASL back for the walk that follows, whoever is playing, until the next area loads the player's own again.Codedoppelganger's SMB2J disassembly
    How we know
    14477;jump, fall and friction physics data used with mario and luigi
    14478;note luigi's higher jump, but with lesser friction
    14479JumpFrictionData:
    14480  .byte $20, $20, $1e, $28, $28, $0d, $04
    14481  .byte $70, $70, $60, $90, $90, $0a, $09
    ⋮
    14483  .byte $e4, $98, $d0
    ⋮
    14485  .byte $18, $18, $18, $22, $22, $0d, $04
    14486  .byte $42, $42, $3e, $5d, $5d, $0a, $09
    ⋮
    14488  .byte $b4, $68, $a0
    
    sm2main.asm lines 14477–14488 at 9c40114 · upstream ↗
    14490LoadPhysicsData:
    14491  ldx #$60               ;use luigi's offsets and RTS opcode
    14492  ldy #$21
    14493  lda SelectedPlayer     ;if selected luigi, branch to continue
    14494  bne ModifyPhysics
    14495LoadMarioPhysics:
    14496  ldx #$0e               ;otherwise use mario's offsets and ASL opcode
    14497  ldy #$10
    14498ModifyPhysics:
    14499  stx PhyOpcode          ;load opcode into friction code to modify it
    14500  ldx #$10
    14501MPhyLoop:
    ⋮
    
    sm2main.asm lines 14490–14507 at 9c40114 · upstream ↗
    5124           lda PlayerFacingDir
    5125           cmp Player_MovingDir       ;check facing direction against moving direction
    5126           beq ExitPhy                ;if the same, branch to leave
    5127PhyOpcode: asl FrictionAdderLow       ;otherwise multiply friction by 2
    5128           rol FrictionAdderHigh      ;then leave (or just leave, if code was modified earlier
    5129ExitPhy:   rts
    
    sm2main.asm lines 5124–5129 at 9c40114 · upstream ↗
    2605DoneInitArea:  lda #Silence             ;silence music
    2606               sta AreaMusicQueue
    2607               lda #$01                 ;disable screen output
    2608               sta DisableScreenFlag
    2609               jsr LoadPhysicsData
    2610               inc OperMode_Task        ;increment task for this mode
    2611               rts
    
    sm2main.asm lines 2605–2611 at 9c40114 · upstream ↗
    11158HandleAxeMetatile:
    11159       lda #$00
    11160       sta OperMode_Task   ;reset secondary mode
    11161       lda #$02
    11162       sta OperMode        ;set primary mode to victory mode
    11163       jsr LoadMarioPhysics
    11164       lda #$18
    11165       sta Player_X_Speed  ;set horizontal speed and continue to erase axe metatile
    
    sm2main.asm lines 11158–11165 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  21. ^FrictionData gives Mario's acceleration and braking per frame: $E4 running, $98 walking, and $D0 walking while still fast from a run, in 1/4096 px/frame.CodeXkeeper0/smb1
    How we know
    4877FrictionData:
    4878	.db $e4, $98, $d0
    
    src/prg.asm lines 4877–4878 at 1cc3c92 · upstream ↗
    5037	LDY $00                                      ; get other value in memory
    5038	LDA FrictionData,y                           ; get value using value in memory as offset
    5039	STA FrictionAdderLow
    5040	LDA #$00
    5041	STA FrictionAdderHigh                        ; init something here
    
    src/prg.asm lines 5037–5041 at 1cc3c92 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  22. ^ abWind blows the player to the right. An area object turns it on (WindOn) and another off (WindOff), and the setup that runs at the start of every area clears it. While it is on, and only in ground-type areas (underground, water, and castle areas stay calm), it moves the player 1 px right on every fourth frame while the frame counter is below 128 and on every second frame from 128 to 255: 96 px every 256 frames, 0.375 px a frame on average. The push is added to the position after the player's own move, on the ground and in the air but not while climbing, so it adds to a rightward speed and takes from a leftward one whatever the speed, and the screen scrolls with it. Its leaves and sound play while it is on, in every type of area. None of it runs until the game has loaded a disk file beyond worlds 1 to 4 (worlds 5 to 8, the ending, or worlds A to D): before that, FileListNumber is 0 and both calls are skipped.Codedoppelganger's SMB2J disassemblyrevised
    How we know
    179BlowPlayerAround:
    180        lda WindFlag            ;if wind is turned off, just exit
    181        beq ExBlow
    182        lda AreaType            ;don't blow the player around unless
    183        cmp #$01                ;the area is ground type
    184        bne ExBlow
    185        ldy #$01
    186        lda FrameCounter        ;branch to set d0 if on an odd frame
    187        asl
    188        bcs BThr                ;otherwise wind will only blow
    189        ldy #$03                ;one out of every four frames
    190BThr:   sty $00
    ⋮
    
    sm2data2.asm lines 179–202 at 9c40114 · upstream ↗
    322BlowPlayerAround:
    323        lda WindFlag            ;if wind is turned off, just exit
    324        beq ExBlow
    325        lda AreaType            ;don't blow the player around unless
    326        cmp #$01                ;the area is ground type
    327        bne ExBlow
    328        ldy #$01
    329        lda FrameCounter
    330        asl
    331        bcs BThr
    332        ldy #$03
    333BThr:   sty $00
    ⋮
    
    sm2data4.asm lines 322–345 at 9c40114 · upstream ↗
    4848JmpMove: jsr MovePlayerHorizontally ;do another sub to move player horizontally
    4849         sta Player_X_Scroll        ;set returned value as player's movement speed for scroll
    4850         lda FileListNumber         ;if in worlds 1-4 don't bother checking for wind
    4851         beq ExOGSS
    4852         jsr BlowPlayerAround
    4853ExOGSS:  rts
    
    sm2main.asm lines 4848–4853 at 9c40114 · upstream ↗
    4892JSMove:   jsr JmpMove
    
    sm2main.asm line 4892 at 9c40114 · upstream ↗
    4830MoveSubs:  jsr JumpEngine
    ⋮
    4832      .word OnGroundStateSub
    4833      .word JumpSwimSub
    4834      .word FallingSub
    4835      .word ClimbingSub
    
    sm2main.asm lines 4830–4835 at 9c40114 · upstream ↗
    4273              lda FileListNumber
    4274              beq NoWind                 ;if in worlds 1-4, skip ahead
    4275              jsr SimulateWind           ;otherwise, simulate wind where needed
    
    sm2main.asm lines 4273–4275 at 9c40114 · upstream ↗
    217SimulateWind:
    218          lda WindFlag             ;if no wind, branch to leave
    219          beq ExSimW
    220          lda #$04                 ;play wind sfx
    221          sta NoiseSoundQueue
    
    sm2data2.asm lines 217–221 at 9c40114 · upstream ↗
    264WindOn:
    265     lda #$01         ;branch to turn the wind on
    266     bne WOn
    267WindOff:
    268     lda #$00         ;turn the wind off
    269WOn: sta WindFlag
    270     rts
    
    sm2data2.asm lines 264–270 at 9c40114 · upstream ↗
    4236      .word InitializeArea
    4237      .word ScreenRoutines
    4238      .word SecondaryGameSetup
    4239      .word GameCoreRoutine
    
    sm2main.asm lines 4236–4239 at 9c40114 · upstream ↗
    2615SecondaryGameSetup:
    2616       lda #$00
    2617       sta DisableScreenFlag    ;reenable screen, reset some flags
    2618       sta WindFlag
    
    sm2main.asm lines 2615–2618 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  23. ^Mario's top ground speed is $18 walking and $28 running (B held).CodeXkeeper0/smb1 · Jdaster64 n.d.
    How we know
    4873MaxRightXSpdData:
    4874	.db $28, $18, $10
    
    src/prg.asm lines 4873–4874 at 1cc3c92 · upstream ↗
    5009	AND #B_Button
    5010	BNE SetRTmr                                  ; if pressed, skip ahead to set timer
    ⋮
    5014	INY                                          ; if running timer not set or level type is water,
    
    src/prg.asm lines 5000–5014 at 1cc3c92 · upstream ↗
    Maximum walk speed (normal, castle cutscene) 01900 | Maximum running speed 02900
    SMB PHYSICS 101 / GROUND PHYSICS, Mario table · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-27.

    In the claim ledger

  24. ^Horizontal speeds are 4.4 fixed point, whole pixels and sixteenths per frame; MoveObjectHorizontally shifts the sixteenths into the subpixel byte.CodeXkeeper0/smb1
    How we know
    6495	ASL                                          ; and move low nybble to high
    6496	ASL
    6497	ASL
    ⋮
    6500	LSR                                          ; move high nybble to low
    6501	LSR
    6502	LSR
    6503	LSR
    
    src/prg.asm lines 6492–6503 at 1cc3c92 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-27.

    In the claim ledger

  25. ^A poison mushroom comes out of a block of its own kind, and stays a poison mushroom whatever the player's size, where an ordinary mushroom block gives a fire flower to a big or fiery player. It slides along like a mushroom. Touching it removes it and runs the injury routine: a small player dies, and a big or fiery one drops straight to small, with the blink that follows any hit. During that blink, or while a star's invincibility lasts, it is removed and does nothing.Codedoppelganger's SMB2J disassembly
    How we know
    6308BlockCode: jsr JumpEngine          ;run appropriate subroutine depending on block number
    ⋮
    6310      .word MushFlowerBlock
    6311      .word PoisonMushBlock
    6312      .word CoinBlock
    6313      .word CoinBlock
    6314      .word ExtraLifeMushBlock
    6315      .word PoisonMushBlock
    6316      .word MushFlowerBlock
    6317      .word MushFlowerBlock
    6318      .word PoisonMushBlock
    6319      .word VineBlock
    6320      .word StarBlock
    ⋮
    
    sm2main.asm lines 6308–6339 at 9c40114 · upstream ↗
    6123           lda PowerUpType
    6124           cmp #$02                  ;check currently loaded power-up type
    6125           bcs PutBehind             ;if star or 1-up, branch ahead
    6126           lda PlayerStatus          ;otherwise check player's current status
    6127           cmp #$02
    6128           bcc StrType               ;if player not fiery, use status as power-up type
    6129           lsr                       ;otherwise shift right to force fire flower type
    6130StrType:   sta PowerUpType           ;store type here
    
    sm2main.asm lines 6123–6130 at 9c40114 · upstream ↗
    6148         lda PowerUpType            ;check power-up type
    6149         beq ShroomM                ;if normal mushroom, branch ahead to move it
    6150         cmp #$03
    6151         beq ShroomM                ;if 1-up mushroom, branch ahead to move it
    6152         cmp #$04
    6153         beq ShroomM
    6154         cmp #$05
    6155         beq ShroomM
    
    sm2main.asm lines 6148–6155 at 9c40114 · upstream ↗
    6161ShroomM: jsr MoveNormalEnemy        ;do sub to make mushrooms move
    
    sm2main.asm line 6161 at 9c40114 · upstream ↗
    10253HandlePowerUpCollision:
    10254      jsr EraseEnemyObject    ;erase the power-up object
    10255      lda PowerUpType
    10256      cmp #$04                ;check power-up type
    10257      bne Safe                ;if not a poison shroom, branch
    10258      jmp InjurePlayer        ;otherwise injure the player properly
    
    sm2main.asm lines 10253–10258 at 9c40114 · upstream ↗
    10423InjurePlayer:
    10424      lda InjuryTimer          ;check again to see if either of the two
    10425      ora StarInvincibleTimer  ;invincibility timers have expired, branch if not
    10426      bne ExInjColRoutines
    ⋮
    10428ForceInjury:
    10429          ldx PlayerStatus          ;check player's status
    10430          beq KillPlayer            ;branch if small
    10431          sta PlayerStatus          ;otherwise set player's status to small
    10432          lda #$08
    10433          sta InjuryTimer           ;set injured invincibility timer
    10434          asl
    10435          sta Square1SoundQueue     ;play pipedown/injury sound
    ⋮
    
    sm2main.asm lines 10423–10436 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  26. ^The poison mushroom is drawn from the same four tiles as the mushroom and the 1-up mushroom ($D8, $DA, $DB, $FF) in sprite palette 3, where the mushroom uses palette 2 and the 1-up palette 1. Like them it keeps its colors, where the fire flower and the star cycle theirs.Codedoppelganger's SMB2J disassembly
    How we know
    12527PowerUpGfxTable:
    12528      .byte $d8, $da, $db, $ff ;regular mushroom
    12529      .byte $d6, $d6, $d9, $d9 ;fire flower
    12530      .byte $8d, $8d, $e4, $e4 ;star
    12531      .byte $d8, $da, $db, $ff ;1-up mushroom
    12532      .byte $d8, $da, $db, $ff ;poison mushroom
    ⋮
    12534PowerUpAttributes:
    12535      .byte $02, $01, $02, $01, $03
    
    sm2main.asm lines 12527–12535 at 9c40114 · upstream ↗
    12565        ldy Enemy_SprDataOffset+5  ;get sprite data offset again
    12566        pla                        ;pull saved power-up type from the stack
    12567        beq PUpOfs                 ;if regular mushroom, 1-up mushroom
    12568        cmp #$03                   ;or poison mushroom, branch
    12569        beq PUpOfs                 ;do not change colors or flip them
    12570        cmp #$04
    12571        beq PUpOfs
    
    sm2main.asm lines 12565–12571 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  27. ^ abLanding on a springboard sets both the held and the falling gravity to $70 and a launch speed of −7 px a frame ($F9). Over the spring's four steps it carries the player down 2 px a step, then up 2 px a step, and on the last step it launches them. A press of A, not held from before, in the second step or later raises the launch to −12 px a frame ($F4), or to −32 px a frame ($E0) on the green springboards of world numbers 2, 3, and 7, which the letter worlds share as B and C, since the test reads the world number without the letter-world flag. With both gravities at $70, the bounce rises and falls under one pull whether A is held or not, for Mario and Luigi alike. While the game's timers are stopped the spring waits.Codedoppelganger's SMB2J disassembly
    How we know
    11291ChkForLandJumpSpring:
    11292        jsr ChkJumpspringMetatiles  ;do sub to check if player landed on jumpspring
    11293        bcc ExCJSp                  ;if carry not set, jumpspring not found, therefore leave
    11294        lda #$70
    11295        sta VerticalForce           ;otherwise set vertical movement force for player
    11296        sta VerticalForceDown
    11297        lda #$f9
    11298        sta JumpspringForce         ;set default jumpspring force
    11299        lda #$03
    11300        sta JumpspringTimer         ;set jumpspring timer to be used later
    11301        lsr
    11302        sta JumpspringAnimCtrl      ;set jumpspring animation control to start animating
    ⋮
    
    sm2main.asm lines 11291–11303 at 9c40114 · upstream ↗
    5574JumpspringHandler:
    5575           jsr GetEnemyOffscreenBits   ;get offscreen information
    5576           lda TimerControl            ;check master timer control
    5577           bne DrawJSpr                ;branch to last section if set
    5578           lda JumpspringAnimCtrl      ;check jumpspring frame control
    5579           beq DrawJSpr                ;branch to last section if not set
    5580           tay
    5581           dey                         ;subtract one from frame control in A,
    5582           tya                         ;the only way a poor NMOS 6502 can
    5583           and #%00000010              ;mask out all but d1, original value still in Y
    5584           bne DownJSpr                ;if set, branch to move player up
    5585           inc Player_Y_Position
    ⋮
    
    sm2main.asm lines 5574–5620 at 9c40114 · upstream ↗
    12672       lda #$02
    12673       ldy WorldNumber             ;if the world number is not 2, 3 or 7
    12674       cpy #$01                    ;then use regular attributes for jumpsprings
    12675       beq GrnJS                   ;which will paint them red
    12676       cpy #$02
    12677       beq GrnJS                   ;otherwise use alternate attributes
    12678       cpy #$06                    ;to get the green superhigh jumpsprings
    12679       bne RedJS
    12680GrnJS: lsr
    12681RedJS: sta EnemyAttributeData+$18  ;set jumpspring gfx attributes in the lookup table
    12682       sta EnemyAttributeData+$19
    12683       sta EnemyAttributeData+$1a
    
    sm2main.asm lines 12672–12683 at 9c40114 · upstream ↗
    6575MovePlayerVertically:
    6576         ldx #$00                ;set X for player offset
    6577         lda TimerControl
    6578         bne NoJSChk             ;if master timer control set, branch ahead
    6579         lda JumpspringAnimCtrl  ;otherwise check to see if jumpspring is animating
    6580         bne ExXMove             ;branch to leave if so
    6581NoJSChk: lda VerticalForce       ;dump vertical force 
    6582         sta $00
    6583         lda #$04                ;set maximum vertical speed here
    6584         jmp ImposeGravitySprObj ;then jump to move player vertically
    
    sm2main.asm lines 6575–6584 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  28. ^PlayerYSpdData starts a jump at −4 px/frame (rows 0–2) or −5 px/frame (rows 3–4).CodeXkeeper0/smb1 · Jdaster64 n.d.
    How we know
    4864PlayerYSpdData:
    4865	.db $fc, $fc, $fc, $fb, $fb, $fe, $ff
    
    src/prg.asm lines 4864–4865 at 1cc3c92 · upstream ↗
    4972	LDA PlayerYSpdData,y
    4973	STA Player_Y_Speed
    
    src/prg.asm lines 4972–4973 at 1cc3c92 · upstream ↗
    04000 | 04000 | 05000
    JUMPING/VERTICAL PHYSICS, Mario table, Initial Velocity (−Y) · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-27.

    In the claim ledger

  29. ^A warp zone leads to one world, whichever of its pipes the player takes. In world 1 it leads to world 2 from the first underground area, to world 3 from a ground area, and to world 4 from any other; in world 3, back to world 1; in world 5, to world 6 from one ground area (the 12th in the area table, which the disassembly's comment places at 5-1), to world 8 from any other ground area, and to world 7 from any other area; in worlds 2, 4, and 6 to 9, to world 5, which from 6 to 8 is back. In worlds A to D it goes by level: from a second level to world B, a third to world C, a fourth to world D; the table holds no world for a first level.Codedoppelganger's SMB2J disassembly
    How we know
    3425ScrollLockObject_Warp:
    3426         ldx #$80                 ;use base number for warp to world 2
    3427         lda HardWorldFlag        ;if on worlds A-D, skip ahead to next part
    3428         bne WarpWorldsAThruD     ;note d7 is set in all entries to prevent zero condition
    3429         lda WorldNumber          ;from happening in warp zone code elsewhere
    3430         bne WarpWorlds2Thru8     ;if not on world 1, branch to handle a different way
    3431         ldy AreaType             ;check to see if on ground level type
    3432         dey                      ;branch if so to add one to the number
    3433         beq W1Warp2
    3434         lda AreaAddrsLOffset     ;if on first underground level, branch to use base number
    3435         beq W1Warp1
    3436         inx                      ;otherwise add two to the number and use it
    ⋮
    
    sm2main.asm lines 3425–3468 at 9c40114 · upstream ↗
    1689WarpZoneNumbers:
    1690  .byte $02, $03, $04, $01, $06, $07, $08, $05, $0b, $0c, $0d
    
    sm2main.asm lines 1689–1690 at 9c40114 · upstream ↗
    11332          lda WarpZoneControl       ;check warp zone control
    11333          beq ExPipeE               ;branch to leave if none found
    11334          and #%00001111            ;mask out all but lower nybble
    11335          tax                       ;save as offset, then use to load warp zone destination
    11336          lda WarpZoneNumbers,x
    11337          ldy HardWorldFlag         ;if playing worlds A-D, branch to skip this part
    11338          beq SetWDest
    11339          sec
    11340          sbc #$09                  ;otherwise subtract 9 to get correct world number
    11341SetWDest: tay
    11342          dey                       ;decrement for use as world number
    11343          sty WorldNumber           ;store as world number and offset
    
    sm2main.asm lines 11332–11343 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  30. ^Every area from World 4-4 on, and every area of worlds A to D, starts with the secondary hard mode flag set; the areas of worlds 1 to 3 and 4-1 to 4-3 start without it. The memory clear at the start of each area resets it first.Codedoppelganger's SMB2J disassembly
    How we know
    2557InitializeArea:
    2558               ldy #$4b                 ;clear all memory again, only as far as $074b
    2559               jsr InitializeMemory     ;this is only necessary in game mode
    
    sm2main.asm lines 2557–2559 at 9c40114 · upstream ↗
    2591               lda HardWorldFlag        ;check to see if we're in worlds A-D
    2592               bne SetSecHard           ;if so, activate the secondary no matter where we're at
    2593               lda WorldNumber          ;otherwise check world number
    2594               cmp #World4              ;if less than 4, do not activate secondary
    2595               bcc CheckHalfway
    2596               bne SetSecHard           ;if not equal to, then world > 4, thus activate
    2597               lda LevelNumber          ;otherwise, world 4, so check level number
    2598               cmp #Level4              ;if not 4, do not set secondary hard mode flag
    2599               bcc CheckHalfway
    2600SetSecHard:    inc SecondaryHardMode    ;set secondary hard mode flag for areas 4-4 and beyond
    
    sm2main.asm lines 2591–2600 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  31. ^With the secondary hard mode flag set: enemies the level data marks for hard mode appear, where otherwise they are skipped; a Bullet Bill cannon is picked to fire when a pseudorandom number masked to three bits is below 6 (6 of 8 values, against 6 of 16 with four bits); up to four flying Cheep Cheeps at once instead of three; hammer bros throw on a shorter timer ($1C against $30), can take the longer of two jump timers ($37 against $20), and in worlds 1 to 6 wait a shorter time before walking left ($50 against $80; in worlds 7 to 9 they don't wait either way, and worlds A to D, which share world numbers 1 to 4 and always have the flag, take $50); Bloopers pick a new direction when two pseudorandom bits are clear rather than six, and then a Blooper in an even enemy slot turns toward the player, one in an odd slot takes the player's moving direction; Bowser's fire breath and the flames that fly in on their own come 16 timer ticks sooner, and the flames move faster ($60 subtracted from their fractional position each frame, against $40); and the large lifts are drawn four sprites wide instead of six with a smaller box, as they always are in castles, with balance platforms and their ropes placed for the shorter width.Codedoppelganger's SMB2J disassemblyrevised
    How we know
    6968        iny
    6969        lda (EnemyData),y        ;get second byte of object
    6970        and #%01000000           ;check to see if hard mode bit is set
    6971        beq CheckForEnemyGroup   ;if not, branch to check for group enemy objects
    6972        lda SecondaryHardMode    ;if set, check to see if secondary hard mode flag
    6973        beq Inc2B                ;is on, and if not, branch to skip this object completely
    
    sm2main.asm lines 6968–6973 at 9c40114 · upstream ↗
    5753CannonBitmasks:
    5754      .byte %00001111, %00000111
    
    sm2main.asm lines 5753–5754 at 9c40114 · upstream ↗
    5763           lda PseudoRandomBitReg+1,x  ;otherwise get part of LSFR
    5764           ldy SecondaryHardMode       ;get secondary hard mode flag, use as offset
    5765           and CannonBitmasks,y        ;mask out bits of LSFR as decided by flag
    5766           cmp #$06                    ;check to see if lower nybble is above certain value
    5767           bcs Chk_BB                  ;if so, branch to check enemy
    
    sm2main.asm lines 5763–5767 at 9c40114 · upstream ↗
    7408         ldy #$03                   ;load Y with default value
    7409         lda SecondaryHardMode
    7410         beq MaxCC                  ;if secondary hard mode flag not set, do not increment Y
    7411         iny                        ;otherwise, increment Y to allow as many as four onscreen
    7412MaxCC:   sty $00                    ;store whatever pseudorandom bits are in Y
    7413         cpx $00                    ;compare enemy object buffer offset with Y
    7414         bcs ChpChpEx               ;if X => Y, branch to leave
    
    sm2main.asm lines 7408–7414 at 9c40114 · upstream ↗
    8207HammerThrowTmrData:
    8208      .byte $30, $1c
    
    sm2main.asm lines 8207–8208 at 9c40114 · upstream ↗
    8227       lda HammerThrowingTimer,x  ;check hammer throwing timer
    8228       bne DecHT                  ;if not expired, skip ahead, do not throw hammer
    8229       ldy SecondaryHardMode      ;otherwise get secondary hard mode flag
    8230       lda HammerThrowTmrData,y   ;get timer data using flag as offset
    8231       sta HammerThrowingTimer,x  ;set as new timer
    
    sm2main.asm lines 8227–8231 at 9c40114 · upstream ↗
    8241HammerBroJumpLData:
    8242      .byte $20, $37
    
    sm2main.asm lines 8241–8242 at 9c40114 · upstream ↗
    8267       lda $00                     ;load preset value here to use as bitmask
    8268       and PseudoRandomBitReg+2,x  ;and do bit-wise comparison with part of LSFR
    8269       tay                         ;then use as offset
    8270       lda SecondaryHardMode       ;check secondary hard mode flag
    8271       bne HJump
    8272       tay                         ;if secondary hard mode flag clear, set offset to 0
    8273HJump: lda HammerBroJumpLData,y    ;get jump length timer data using offset from before
    
    sm2main.asm lines 8267–8273 at 9c40114 · upstream ↗
    7166HBroWalkingTimerData:
    7167      .byte $80, $50
    
    sm2main.asm lines 7166–7167 at 9c40114 · upstream ↗
    7173       lda WorldNumber             ;if on worlds 7-9, branch to skip the walk delay
    7174       cmp #World7
    7175       bcs NoHBI
    7176       ldy SecondaryHardMode       ;get secondary hard mode flag
    7177       lda HBroWalkingTimerData,y
    7178       sta EnemyIntervalTimer,x    ;set value as delay for hammer bro to walk left
    
    sm2main.asm lines 7173–7178 at 9c40114 · upstream ↗
    8469BlooberBitmasks:
    8470      .byte %00111111, %00000011
    
    sm2main.asm lines 8469–8470 at 9c40114 · upstream ↗
    8476        ldy SecondaryHardMode      ;use secondary hard mode flag as offset
    8477        lda PseudoRandomBitReg+1,x ;get LSFR
    8478        and BlooberBitmasks,y      ;mask out bits in LSFR using bitmask loaded with offset
    8479        bne BlooberSwim            ;if any bits set, skip ahead to make swim
    8480        txa
    8481        lsr                        ;check to see if on second or fourth slot (1 or 3)
    8482        bcc FBLeft                 ;if not, branch to figure out moving direction
    8483        ldy Player_MovingDir       ;otherwise, load player's moving direction and
    8484        bcs SBMDir                 ;do an unconditional branch to set
    8485FBLeft: ldy #$02                   ;set left moving direction by default
    8486        jsr PlayerEnemyDiff        ;get horizontal difference between player and bloober
    8487        bpl SBMDir                 ;if enemy to the right of player, keep left
    ⋮
    
    sm2main.asm lines 8476–8488 at 9c40114 · upstream ↗
    9257           jsr SetFlameTimer          ;get timing for bowser's flame
    9258           ldy SecondaryHardMode
    9259           beq SetFBTmr               ;if secondary hard mode flag not set, skip this
    9260           sec
    9261           sbc #$10                   ;otherwise subtract from value in A
    9262SetFBTmr:  sta BowserFireBreathTimer  ;set value as timer here
    
    sm2main.asm lines 9257–9262 at 9c40114 · upstream ↗
    7554        jsr SetFlameTimer           ;get timer data based on flame counter
    7555        clc
    7556        adc #$20                    ;add 32 frames by default
    7557        ldy SecondaryHardMode
    7558        beq SetFrT                  ;if secondary mode flag not set, use as timer setting
    7559        sec
    7560        sbc #$10                    ;otherwise subtract 16 frames for secondary hard mode
    7561SetFrT: sta FrenzyEnemyTimer        ;set timer accordingly
    
    sm2main.asm lines 7554–7561 at 9c40114 · upstream ↗
    9331         lda #$40                    ;load default movement force
    9332         ldy SecondaryHardMode
    9333         beq SFlmX                   ;if secondary hard mode flag not set, use default
    9334         lda #$60                    ;otherwise load alternate movement force to go faster
    9335SFlmX:   sta $00                     ;store value here
    
    sm2main.asm lines 9331–9335 at 9c40114 · upstream ↗
    12395      ldy AreaType
    12396      cpy #$03                    ;check for castle-type level
    12397      beq ShrinkPlatform
    12398      ldy SecondaryHardMode       ;check for secondary hard mode flag set
    12399      beq SetLast2Platform        ;branch if not set elsewhere
    ⋮
    12401ShrinkPlatform:
    12402      lda #$f8                    ;load offscreen coordinate if flag set or castle-type level
    
    sm2main.asm lines 12395–12402 at 9c40114 · upstream ↗
    7935SPBBox: lda #$05                  ;set default bounding box size control
    7936        ldy AreaType
    7937        cpy #$03                  ;check for castle-type level
    7938        beq CasPBB                ;use default value if found
    7939        ldy SecondaryHardMode     ;otherwise check for secondary hard mode flag
    7940        bne CasPBB                ;if set, use default value
    7941        lda #$06                  ;use alternate value if not castle or secondary not set
    7942CasPBB: sta Enemy_BoundBoxCtrl,x  ;set bounding box size control here and leave
    
    sm2main.asm lines 7935–7942 at 9c40114 · upstream ↗
    7885        ldy SecondaryHardMode     ;if secondary hard mode flag not set,
    7886        bne AlignP                ;branch ahead
    7887        ldy #$02                  ;otherwise set value here
    7888        jsr PosPlatform           ;do a sub to add or subtract pixels
    
    sm2main.asm lines 7885–7888 at 9c40114 · upstream ↗
    7985PlatPosDataLow:
    7986      .byte $08,$0c,$f8
    
    sm2main.asm lines 7985–7986 at 9c40114 · upstream ↗
    9813SetupPlatformRope:
    9814        pha                     ;save second/third copy to stack
    9815        lda Enemy_X_Position,y  ;get horizontal coordinate
    9816        clc
    9817        adc #$08                ;add eight pixels
    9818        ldx SecondaryHardMode   ;if secondary hard mode flag set,
    9819        bne GetLRp              ;use coordinate as-is
    9820        clc
    9821        adc #$10                ;otherwise add sixteen more pixels
    
    sm2main.asm lines 9813–9821 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  32. ^Piranha plants are green in worlds 1 to 3 and red in worlds 4 to 9 and A to D. A green one stays in its pipe while the player is less than 33 px from it across, and moves on every second frame; a red one stays in only while the player is less than 19 px away, and moves on every frame.Codedoppelganger's SMB2J disassembly
    How we know
    7805InitPiranhaPlant:
    7806         lda #$22                     ;set default attribute and range data here
    7807         sta $00                      ;range data is used to detect how close player is
    7808         lda #$13                     ;to the piranha plant to keep it inside the pipe
    7809         sta $01                      ;default data makes red piranha plants
    7810         lda HardWorldFlag
    7811         bne PatchPP                  ;use default data if in worlds A-D
    7812         lda WorldNumber
    7813         cmp #$03
    7814         bcs PatchPP                  ;use default data if in worlds 4-8
    7815         dec $00
    7816         lda #$21                     ;otherwise make green piranha plant instead
    ⋮
    
    sm2main.asm lines 7805–7821 at 9c40114 · upstream ↗
    9593ChkPlayerNearPipe:
    9594      lda $00                     ;get saved horizontal difference
    9595      cmp #$21
    9596      bcc PutinPipe               ;if player within a certain distance, branch to leave
    
    sm2main.asm lines 9593–9596 at 9c40114 · upstream ↗
    9612RiseFallPiranhaPlant:
    9613       sta $00                     ;save vertical coordinate here
    9614       lda EnemyAttributeData+PiranhaPlant
    9615       cmp #$22                    ;check for red piranha plants
    9616       beq RedPP                   ;if found, skip to next part to execute code on every frame
    9617       lda FrameCounter            ;get frame counter
    9618       lsr
    9619       bcc PutinPipe               ;branch to leave if d0 set (execute code every other frame)
    
    sm2main.asm lines 9612–9619 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  33. ^While Lakitu's stretch of a level runs, the game checks every 128 frames whether a Lakitu is on screen. When none is, it counts the check, and on the third it sends a new Lakitu if an enemy slot is free (if none is, it tries again at the next check); the count starts over when a Lakitu is set up. The new one flies high in worlds 1 to 6 ($20) and lower in worlds 7 to 9 and A to D ($60). When one is on screen, the same check leads to the Spiny throw, not covered here.Codedoppelganger's SMB2J disassembly
    How we know
    7251LakituAndSpinyHandler:
    7252          lda FrenzyEnemyTimer    ;if timer here not expired, leave
    7253          bne ExLSHand
    7254          cpx #$05                ;if we are on the special use slot, leave
    7255          bcs ExLSHand
    7256          lda #$80                ;set timer
    7257          sta FrenzyEnemyTimer
    7258          ldy #$04                ;start with the last enemy slot
    7259ChkLak:   lda Enemy_ID,y          ;check all enemy slots to see
    7260          cmp #Lakitu             ;if lakitu is on one of them
    7261          beq CreateSpiny         ;if so, branch out of this loop
    7262          dey                     ;otherwise check another slot
    ⋮
    
    sm2main.asm lines 7251–7288 at 9c40114 · upstream ↗
    7234SetupLakitu:
    7235      lda #$00                   ;erase counter for lakitu's reappearance
    7236      sta LakituReappearTimer
    
    sm2main.asm lines 7234–7236 at 9c40114 · upstream ↗
    928   ldx #$14                  ;set offset to decrement only frame timers
    929   dec IntervalTimerControl  ;if interval timer control not expired, branch
    930   bpl DecrTheTimers         ;to skip and thus decrement only frame timers
    931   lda #$14
    932   sta IntervalTimerControl  ;otherwise reset interval timer control to 20 frames
    933   ldx #$23                  ;and load offset to decrement frame and interval timers
    
    sm2main.asm lines 928–933 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  34. ^At a game over outside World 9, Select switches between CONTINUE and RETRY and Start picks. Continue restarts the current world at its first level, small, with three lives, the score and coins at zero, and the hidden 1-up available again. Retry ends the game and clears the record of completed worlds.Codedoppelganger's SMB2J disassembly
    How we know
    14431GameOverMenu:
    14432            lda SavedJoypadBits          ;if player pressed the start button
    14433            and #Start_Button            ;then either continue or start over
    14434            bne ContinueOrRetry
    14435            lda SavedJoypadBits
    14436            and #Select_Button           ;if player pressed the select button
    14437            beq ChgSel                   ;then branch to select "continue" or "retry"
    14438            ldx SelectTimer              ;if select timer not expired while
    14439            bne ChgSel                   ;pressing select, skip this
    14440            lsr
    14441            sta SelectTimer              ;otherwise set the select timer
    14442            lda ContinueMenuSelect
    ⋮
    
    sm2main.asm lines 14431–14444 at 9c40114 · upstream ↗
    14455ContinueOrRetry:
    14456  lda ContinueMenuSelect       ;if player selected "continue"
    14457  beq Continue                 ;then branch to continue
    14458  lda #$00
    14459  sta CompletedWorlds          ;otherwise init completed worlds flags
    14460  jmp TerminateGame            ;and end the game
    ⋮
    14462Continue:
    14463        ldy #$02
    14464        sty NumberofLives           ;give three lives
    14465        sta LevelNumber
    14466        sta AreaNumber              ;put at x-1 of the current world
    14467        sta CoinTally
    ⋮
    
    sm2main.asm lines 14455–14473 at 9c40114 · upstream ↗
    2869ContinueGame:
    2870           jsr LoadAreaPointer       ;update level pointer with
    2871           lda #$01                  ;actual world and area numbers, then
    2872           sta PlayerSize            ;reset player's size, status, and
    2873           inc FetchNewGameTimerFlag ;set game timer flag to reload
    2874           lda #$00                  ;game timer from header
    2875           sta TimerControl          ;also set flag for timers to count again
    2876           sta PlayerStatus
    2877           sta GameEngineSubroutine  ;reset task for game core
    2878           sta OperMode_Task         ;set modes and leave
    2879           lda #$01                  ;if in game over mode, switch back to
    2880           sta OperMode              ;game mode, because game is still on
    ⋮
    
    sm2main.asm lines 2869–2881 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  35. ^Clearing a world's castle sets that world's bit in a record of completed worlds. After the ending that follows 8-4, the game goes on to World 9 if all eight bits are set, and back to the title screen if any is missing; after D-4 it always goes back to the title. The record is cleared when a game starts and when the player picks Retry at a game over, and Continue keeps it, so a world skipped by a warp counts only if the player warps back and clears its castle.Codedoppelganger's SMB2J disassembly
    How we know
    1185WorldBits:
    1186    .byte $01, $02, $04, $08, $10, $20, $40, $80
    ⋮
    1188SetupVictoryMode:
    1189         ldx ScreenRight_PageLoc ;get page location of right side of screen
    1190         inx                     ;increment to next page
    1191         stx DestinationPageLoc
    1192         ldy WorldNumber
    1193         lda WorldBits,y
    1194         ora CompletedWorlds     ;set bit according to the world the player was in
    1195         sta CompletedWorlds
    
    sm2main.asm lines 1185–1195 at 9c40114 · upstream ↗
    428BackToNormal:
    429    lda #>SoundEngine        ;reset sound engine vector
    430    sta SoundEngineJSRCode+2  ;to run the original one
    431    lda #<SoundEngine
    432    sta SoundEngineJSRCode+1
    433    lda #$00
    434    sta DiskIOTask           ;erase task numbers
    435    sta OperMode_Task
    436    lda HardWorldFlag        ;if in world D, branch to end the game
    437    bne EndTheGame
    438    lda CompletedWorlds      ;if completed all worlds without skipping over any
    439    cmp #$ff                 ;then branch elsewhere (note warping backwards may
    ⋮
    
    sm2data3.asm lines 428–451 at 9c40114 · upstream ↗
    14692              lda SavedJoypadBits         ;check to see if the player pressed start
    14693              and #Start_Button
    14694              beq ChkSelect               ;if not, branch to check other buttons
    14695              lda #$00
    14696              sta CompletedWorlds
    14697              sta DiskIOTask
    14698              sta HardWorldFlag
    
    sm2main.asm lines 14692–14698 at 9c40114 · upstream ↗
    14455ContinueOrRetry:
    14456  lda ContinueMenuSelect       ;if player selected "continue"
    14457  beq Continue                 ;then branch to continue
    14458  lda #$00
    14459  sta CompletedWorlds          ;otherwise init completed worlds flags
    14460  jmp TerminateGame            ;and end the game
    
    sm2main.asm lines 14455–14460 at 9c40114 · upstream ↗
    14462Continue:
    14463        ldy #$02
    14464        sty NumberofLives           ;give three lives
    14465        sta LevelNumber
    14466        sta AreaNumber              ;put at x-1 of the current world
    14467        sta CoinTally
    14468        ldy #$0b
    14469ISCont: sta ScoreAndCoinDisplay,y   ;reset score
    14470        dey
    14471        bpl ISCont
    14472        inc Hidden1UpFlag           ;allow 1-up to be found again
    14473        jmp ContinueGame
    
    sm2main.asm lines 14462–14473 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  36. ^World 9 begins with one life. A game over there ends the game, with no continue menu. Its four levels loop: after 9-4 the game starts 9-1 again.Codedoppelganger's SMB2J disassembly
    How we know
    446GoToWorld9:
    447    lda #$00
    448    sta CompletedWorlds      ;init completed worlds flag
    449    sta NumberofLives        ;give the player one life
    450    sta FantasyW9MsgFlag
    451    jmp NextWorld            ;run world 9
    
    sm2data3.asm lines 446–451 at 9c40114 · upstream ↗
    2850RunGameOver:
    2851       lda #$00
    2852       sta DisableScreenFlag
    2853       lda WorldNumber       ;if on world 9, branch on to end the game
    2854       cmp #World9
    2855       beq W9End
    2856       jmp GameOverMenu      ;otherwise run game over menu
    2857W9End: lda ScreenTimer
    2858       bne ExRGO
    ⋮
    2860TerminateGame:
    2861       lda #Silence          ;silence music
    2862       sta EventMusicQueue
    ⋮
    
    sm2main.asm lines 2850–2867 at 9c40114 · upstream ↗
    4793NextArea: inc AreaNumber            ;increment area number used for address loader
    4794          lda WorldNumber
    4795          cmp #$08
    4796          bne NotW9                 ;if not at end of world 9-4, branch
    4797          lda LevelNumber           ;otherwise reset level and area numbers properly
    4798          cmp #$04
    4799          bne NotW9
    4800          lda #$00
    4801          sta LevelNumber
    4802          sta AreaNumber
    4803NotW9:    jsr LoadAreaPointer       ;get new level pointer
    
    sm2main.asm lines 4793–4803 at 9c40114 · upstream ↗
    1303NextWorld: lda #$00
    1304           sta AreaNumber            ;reset area/level numbers to start the next world
    1305           sta LevelNumber
    1306           sta OperMode_Task
    1307           lda WorldNumber
    1308           clc
    1309           adc #$01                  ;add one, but only up to world 9
    1310           cmp #World9
    1311           bcc NoPast9
    1312           lda #World9               ;make world 9 loop forever (or until game is over)
    1313NoPast9:   sta WorldNumber           ;update the world number
    
    sm2main.asm lines 1303–1313 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  37. ^Each time the ending loads, after 8-4 or D-4, the count of games beaten goes up by one, to at most 24 (a short read of the ending's files resets it to 0 first). After 8-4 the game writes the count to the disk's save file (a disk error aside); after D-4 it doesn't, and the title screen, which reloads the disk's first files after a game in worlds A to D or from world 5 on, reads the saved count back, so D-4 adds nothing. The title screen shows a star for each game beaten, in two rows of 12. With 8 or more, holding A while pressing Start begins the game at World A, loading worlds A to D, with their own halfway points, from the disk.Codedoppelganger's SMB2J disassembly
    How we know
    14261LoadEnding:
    14262        lda #$02                 ;set filelist number to load SM2DATA3, SM2CHAR2 and SM2SAVE
    14263        sta FileListNumber
    14264        jsr LoadFiles            ;load them now
    14265        bne ReturnedError
    14266        jsr CheckFileCount       ;check to see if loaded the correct number of files
    14267        beq AddBeatenGame        ;if so, continue
    14268        lda #$00                 ;otherwise reset count of games beaten
    14269        sta GamesBeatenCount
    14270AddBeatenGame:
    14271        lda GamesBeatenCount     ;get the new count of games beaten we loaded (or reset)
    14272        clc                      ;add one to it, to a maximum of 24/$18
    ⋮
    
    sm2main.asm lines 14261–14280 at 9c40114 · upstream ↗
    391RunMushroomRetainers:
    392       jsr MushroomRetainersForW8  ;draw and flash the seven mushroom retainers
    393       lda AltMusicBuffer          ;if still playing victory music, branch to leave
    394       bne ExRMR
    395       lda HardWorldFlag           ;if on world D, branch elsewhere
    396       bne BackToNormal
    397       inc OperMode_Task           ;otherwise just move onto the last task
    398ExRMR: rts
    ⋮
    400EndingDiskRoutines:
    401    lda DiskIOTask
    402    jsr JumpEngine
    ⋮
    404    .word DiskScreen
    ⋮
    
    sm2data3.asm lines 391–426 at 9c40114 · upstream ↗
    14180LoadWorlds1Thru4:
    14181           lda NotColdFlag       ;if not set, just cold booted, thus no need to check world info
    14182           beq InitWorldPos
    14183           lda HardWorldFlag     ;if player was playing worlds A-D, skip ahead
    14184           bne LW14Files         ;otherwise check the world number
    14185           lda WorldNumber
    14186           cmp #World5           ;if world number was less than 5, files still in memory
    14187           bcc InitWorldPos      ;thus skip to the end, no need to load them again
    14188LW14Files: lda #$00              ;set filelist number to reload SM2MAIN, SM2CHAR1 and SM2SAVE
    14189           sta FileListNumber
    14190           jsr LoadFiles         ;now reload those files
    14191           bne ReturnedError     ;if returned with error number, branch
    ⋮
    
    sm2main.asm lines 14180–14193 at 9c40114 · upstream ↗
    14301World14List:
    14302      .byte $01, $05, $0f, $ff
    14303World58List:
    14304      .byte $20, $ff
    14305EndingList:
    14306      .byte $10, $30, $0f, $ff
    14307WorldADList:
    14308      .byte $40, $ff
    
    sm2main.asm lines 14301–14308 at 9c40114 · upstream ↗
    14832            ldy #$33                 ;set up offset in the title screen tiles
    14833            lda #$0c                 ;set up counter to print up to 12 stars per row
    14834            sta $00
    14835            ldx #$00                 ;init star counter
    14836PrintStars: lda #$26                 ;print blank by default
    14837            cpx GamesBeatenCount     ;check star counter against games beaten
    14838            bcs PrintToTS            ;if counted up to games beaten, print the blank
    14839            lda #$f1                 ;otherwise print a star for a beaten game
    14840PrintToTS:  sta TitleScreenGfxData,y ;print to title screen
    14841            iny
    14842            dec $00                  ;decrement until done printing a row
    14843            bne NextStarR
    ⋮
    
    sm2main.asm lines 14832–14847 at 9c40114 · upstream ↗
    14692              lda SavedJoypadBits         ;check to see if the player pressed start
    14693              and #Start_Button
    14694              beq ChkSelect               ;if not, branch to check other buttons
    14695              lda #$00
    14696              sta CompletedWorlds
    14697              sta DiskIOTask
    14698              sta HardWorldFlag
    14699              lda GamesBeatenCount        ;check to see if player has beaten
    14700              cmp #$08                    ;the game at least 8 times
    14701              bcc StG                     ;if not, start the game as usual at world 1
    14702              lda SavedJoypadBits
    14703              and #A_Button               ;check if the player pressed A + start
    ⋮
    
    sm2main.asm lines 14692–14706 at 9c40114 · upstream ↗
    14147LoadHardWorlds:
    14148         lda HardWorldFlag         ;if this is not set, skip this
    14149         beq NoLoadHW
    14150         lda #$03
    14151         sta FileListNumber        ;set filelist number to load SM2DATA4
    14152         jsr LoadFiles
    14153         bne ReturnedError         ;if returned with error number, branch
    14154         jsr CheckFileCount        ;check to see if loaded the correct number of files
    14155         bne BadFileCount          ;if not, branch to set error code
    14156NoLoadHW:
    14157         jsr LoadAreaPointer       ;update area pointer to get world 1 or A
    14158         lda HardWorldFlag         ;if this is not set, skip this
    ⋮
    
    sm2main.asm lines 14147–14160 at 9c40114 · upstream ↗
    1196         lda HardWorldFlag       ;if not playing worlds A-D, branch to skip this
    1197         beq W1Thru8
    1198         lda WorldNumber         ;otherwise, if not on world D, branch to skip this
    1199         cmp #World4             ;(note worlds A-D use values 0-3 in this variable)
    1200         bcc W1Thru8
    1201         lda #World8             ;if on world D, set world number to 8 to satisfy
    1202         sta WorldNumber         ;end of game condition in later victory mode subs
    
    sm2main.asm lines 1196–1202 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  38. ^Grabbing the flagpole gives an extra life in place of the height's points when the coin count's two digits are the same and match the timer's last digit (11 coins with the timer ending in 1, for example).Codedoppelganger's SMB2J disassembly
    How we know
    11219ChkFlagpoleYPosLoop:
    11220       cmp FlagpoleYPosData,x    ;compare with current vertical coordinate data
    11221       bcs MtchF                 ;if player's => current, branch to use current offset
    11222       dex                       ;otherwise decrement offset to use 
    11223       bne ChkFlagpoleYPosLoop   ;do this until all data is checked (use last one if all checked)
    11224MtchF: stx FlagpoleScore         ;store offset here to be used later
    11225       lda CoinDisplay
    11226       cmp CoinDisplay+1         ;check to see if coin tally digits are the same
    11227       bne RunFR                 ;if not, branch to use flagpole score data as-is
    11228       cmp GameTimerDisplay+2    ;check to see if the last digit of game timer matches
    11229       bne RunFR                 ;the two digits, if not, branch to use data as-is
    11230       lda #$05
    ⋮
    
    sm2main.asm lines 11219–11231 at 9c40114 · upstream ↗
    5551GiveFPScr: ldy FlagpoleScore         ;get score offset from earlier (when player touched flagpole)
    5552           cpy #$05
    5553           bne NoEL4F                ;if set to give player an extra life, do so now
    5554           inc NumberofLives
    5555           lda #$40
    5556           sta $fe
    5557           jmp NoSc4F
    5558NoEL4F:    lda FlagpoleScoreMods,y   ;get amount to award player points
    5559           ldx FlagpoleScoreDigits,y ;get digit with which to award points
    
    sm2main.asm lines 5551–5559 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  39. ^Fireworks go off over the castle when the timer's last digit matches the coin count's last digit as the level ends: three when the digit is odd, six when it is even, and none when they differ.Codedoppelganger's SMB2J disassembly
    How we know
    9470GameTimerFireworks:
    9471         lda GameTimerDisplay+2 ;check to see if last digit of timer matches
    9472         cmp CoinDisplay+1      ;the last digit in the coin tally
    9473         bne NoFWks             ;if not, skip the fireworks
    9474         and #$01
    9475         beq EvenDgs            ;if so, check to see if they are both odd or even
    9476         ldy #$03
    9477         lda #$03               ;if they are both odd, set state and counter
    9478         bne SetFWC             ;for 3 fireworks to go off
    9479EvenDgs: ldy #$00               ;if they are both even, set state and counter
    9480         lda #$06               ;for 6 fireworks to go off
    9481         bne SetFWC
    ⋮
    
    sm2main.asm lines 9470–9485 at 9c40114 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  40. ^The movement and gravity routines (MoveObjectHorizontally through ImposeGravity) are Super Mario Bros.'s, instruction for instruction: ImposeGravity and MoveDropPlatform are byte for byte the same, and the other seven differ only in the addresses of their calls and jumps.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    6487MovePlayerHorizontally:
    
    src/prg.asm lines 6482–6722 at 1cc3c92 · upstream ↗
    6525MovePlayerHorizontally:
    
    sm2main.asm lines 6520–6748 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $BF02-$C046. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $8AD3-$8C17. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  41. ^The player's 80 sprite tiles, $00-$4F of the sprite pattern table, are Super Mario Bros.'s byte for byte.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    33.incbin "smb1.chr"
    
    smb1.asm line 33 at 1cc3c92 · upstream ↗
    61.incbin "SM2CHAR1.CHR"
    
    fdswrap.asm line 61 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): CHR $0000-$04FF. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2CHAR1 CHR $0000-$04FF. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  42. ^1,299 bytes of The Lost Levels' music are Super Mario Bros.'s byte for byte: the last bytes of the music headers and the notes of every song SM2MAIN plays, from the star music (Star_CloudMData) through the ground music's parts, death, castle, game over, time running out, level end, underground, water and the castle-clear music (EndOfCastleMusData).CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    125GroundM_P1Data:
    
    src/music-data.asm lines 114–347 at 1cc3c92 · upstream ↗
    16352GroundM_P1Data:
    
    sm2main.asm lines 16341–16574 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $F9B5-$FEC7. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $D9EC-$DEFE. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  43. ^LoadAreaPointer, FindAreaPointer and GetAreaDataAddrs are Super Mario Bros.'s, with the area data address tables made tables of words (indexed with an ASL) where Super Mario Bros. keeps separate low and high byte tables; the tables themselves hold The Lost Levels' worlds, and AreaDataOfsLoopback its 12 loop points. Of the level data, only the 9-byte pipe intro area (L_GroundArea10) is byte for byte Super Mario Bros.'s.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1 · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    14565            asl
    
    sm2main.asm line 14565 at 9c40114 · upstream ↗
    lda EnemyDataAddrs+1,y
    sm2main.asm#L14567-L14567 · upstream ↗
    3948	.db $12, $36, $0e, $0e, $0e, $32, $32, $32, $0a, $26, $40
    
    src/prg.asm line 3948 at 1cc3c92 · upstream ↗
    14526L_GroundArea10:
    
    sm2main.asm line 14526 at 9c40114 · upstream ↗
    247L_GroundArea10:
    
    src/levels/objects.asm line 247 at 1cc3c92 · upstream ↗
    3952LoadAreaPointer:
    
    src/prg.asm lines 3948–4054 at 1cc3c92 · upstream ↗
    9AreaAddrOffsets:
    
    src/levels/levels.asm lines 4–71 at 1cc3c92 · upstream ↗
    GetAreaType: and #%01100000
    sm2main.asm#L14536-L14686 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $9BF8-$9D6F. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $C2A4-$C46B. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  44. ^GameMenuRoutine and DemoEngine are Super Mario Bros.'s menu and demo, rewritten in part: the menu drops the one- or two-player choice and the world select, and starts the game at world 1, or at world A when A is held and the game has been beaten 8 times; Select switches between Mario and Luigi; the demo plays new button presses and durations through the same code.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    CMP #A_Button+Start_Button
    src/prg.asm#L336-L337 · upstream ↗
    LDX WorldSelectEnableFlag
    src/prg.asm#L350-L350 · upstream ↗
    inc HardWorldFlag
    sm2main.asm#L14699-L14705 · upstream ↗
    14729              sta SelectedPlayer
    
    sm2main.asm lines 14727–14729 at 9c40114 · upstream ↗
    460	.db $01, $80, $02, $81, $41, $80, $01
    
    src/prg.asm line 460 at 1cc3c92 · upstream ↗
    14783  .byte $01, $81, $01, $81, $01, $81, $02, $01
    
    sm2main.asm line 14783 at 9c40114 · upstream ↗
    330GameMenuRoutine:
    
    src/prg.asm lines 328–485 at 1cc3c92 · upstream ↗
    14706StG:          jmp StartGame
    
    sm2main.asm lines 14692–14806 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $823F-$831C; $8340-$838A. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $C46E-$C572. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  45. ^A second player plays Luigi on controller 2, taking turns with the first.ManualSuper Mario Bros. instruction booklet · Computer Entertainer, June 1986
    How we know
    Controller 2 — for second player in 2 player game … moves Mario (Luigi
    2. Names of Controller Parts · archived copy ↗
    (Solo or 2-player alternating; Pause.)
    review of Super Mario Bros. · archived copy ↗

    The quote matches our archived copy.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  46. ^The player's control and movement code (GameRoutines through ImposeFriction) is Super Mario Bros.'s, instruction for instruction in 14 of its 19 regions, with these changes: OnGroundStateSub and the jump and swim code move the player through a new JmpMove, which lets the wind push them (BlowPlayerAround) once a disk file beyond worlds 1 to 4 is loaded; PlayerPhysicsSub's friction table moves up to follow the fall forces, inside the 17 bytes that LoadPhysicsData overwrites with Mario's or Luigi's set; PlayerEndLevel queues the level-end music once, guarded by a new FlagpoleMusicFlag, where Super Mario Bros. queues it whenever ScrollLock is set, and sets the hidden 1-up's flag on 10 coins in any world, where Super Mario Bros. reads a per-world table, and starts world 9 over after 9-4; PlayerDeath shares one RTS. The entrances, pipes, size change, injury blink, flagpole slide, falling, climbing, animation speed and ImposeFriction differ only in their addresses.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1 · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”revised
    How we know
    4852         jsr BlowPlayerAround
    
    sm2main.asm lines 4848–4852 at 9c40114 · upstream ↗
    JSR MovePlayerHorizontally
    src/prg.asm#L4788-L4789 · upstream ↗
    4892JSMove:   jsr JmpMove
    
    sm2main.asm line 4892 at 9c40114 · upstream ↗
    4878	.db $e4, $98, $d0
    
    src/prg.asm line 4878 at 1cc3c92 · upstream ↗
    4962      .byte $e4, $98, $d0
    
    sm2main.asm line 4962 at 9c40114 · upstream ↗
    CMP Hidden1UpCoinAmts,y
    src/prg.asm#L4686-L4686 · upstream ↗
    inc FlagpoleMusicFlag
    sm2main.asm#L4768-L4772 · upstream ↗
    LDA ScrollLock
    src/prg.asm#L4660-L4663 · upstream ↗
    cmp #$0a
    sm2main.asm#L4790-L4790 · upstream ↗
    4795          cmp #$08
    
    sm2main.asm lines 4794–4802 at 9c40114 · upstream ↗
    14503  sta JumpMForceData,x
    
    sm2main.asm lines 14490–14504 at 9c40114 · upstream ↗
    4286PlayerEntrance:
    
    src/prg.asm lines 4267–5135 at 1cc3c92 · upstream ↗
    4428PlayerEntrance:
    
    sm2main.asm lines 4411–5207 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $B04A-$B623. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $7BA2-$818F. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  47. ^GameCoreRoutine and ScrollHandler are Super Mario Bros.'s with three changes: the game mode's task list gains GameModeDiskRoutines at its head and the core no longer reads the current player's saved joypad bits; each frame of play calls SimulateWind once a disk file beyond worlds 1 to 4 is loaded; ScrollHandler waits for the status bar's timer IRQ before it scrolls and keeps the name table in NameTableSelect, where Super Mario Bros. sets it in its PPU control mirror. GetScreenPosition is byte for byte the same.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    LDA SavedJoypadBits,x
    src/prg.asm#L4081-L4083 · upstream ↗
    4235      .word GameModeDiskRoutines
    
    sm2main.asm line 4235 at 9c40114 · upstream ↗
    jsr SimulateWind
    sm2main.asm#L4275-L4275 · upstream ↗
    4341              lda IRQAckFlag
    
    sm2main.asm line 4341 at 9c40114 · upstream ↗
    LDA Mirror_PPU_CTRL_REG1
    src/prg.asm#L4206-L4209 · upstream ↗
    sta NameTableSelect
    sm2main.asm#L4357-L4357 · upstream ↗
    4090GameEngine:
    
    src/prg.asm lines 4081–4262 at 1cc3c92 · upstream ↗
    4241GameCoreRoutine:
    
    sm2main.asm lines 4232–4406 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $AEEA-$B049. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $7A37-$7BA1. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  48. ^Cannons, hammers, coins, power-ups and blocks (ProcessCannons through BlockObjMT_Updater) are Super Mario Bros.'s with the poison mushroom added and one player: BumpBlock's contents table gains poison mushroom blocks and MushFlowerBlock gains PoisonMushBlock, which sets power-up type 4; PowerUpObjHandler walks types 4 and 5 like a mushroom; BlockBumpedChk checks 19 block metatiles where Super Mario Bros. checks 14; GiveOneCoin and AddToScore use fixed offsets where Super Mario Bros. indexes by CurrentPlayer; the head-collision and coin checks use the renumbered metatiles. SetupPowerUp is byte for byte Super Mario Bros.'s, though the poison mushroom now passes through it, and so are InitBlock_XY_Pos and SpawnBrickChunks; the cannons, hammers, jumping coins, brick shatter and bouncing blocks differ only in their addresses.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1 · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    cmp #$0d
    sm2main.asm#L6305-L6305 · upstream ↗
    6319      .word VineBlock
    
    sm2main.asm lines 6319–6322 at 9c40114 · upstream ↗
    lda #$04
    sm2main.asm#L6333-L6333 · upstream ↗
    6152         cmp #$04
    
    sm2main.asm lines 6152–6155 at 9c40114 · upstream ↗
    LDY #$0d
    src/prg.asm#L6312-L6312 · upstream ↗
    ldy #$12
    sm2main.asm#L6358-L6358 · upstream ↗
    LDX CurrentPlayer
    src/prg.asm#L6011-L6012 · upstream ↗
    ldy #$11
    sm2main.asm#L6071-L6071 · upstream ↗
    lda #$c5
    sm2main.asm#L6227-L6227 · upstream ↗
    5665ProcessCannons:
    
    src/prg.asm lines 5663–6474 at 1cc3c92 · upstream ↗
    5756ProcessCannons:
    
    sm2main.asm lines 5754–6512 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $B9BA-$BF01. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $8585-$8AD2. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  49. ^ abcdThe collision code (FireballEnemyCollision through BlockBufferCollision) is Super Mario Bros.'s with the upside-down piranha plant, the poison mushroom and the renumbered metatiles added: the fireball, enemy, background and stomp checks treat the upside-down plant like a piranha plant; HandlePowerUpCollision injures the player on power-up type 4; InjurePlayer also does nothing while the star's StarInvincibleTimer runs; HandlePECollisions checks for the cannon's Bullet Bill before the piranha plants and Podoboo, where Super Mario Bros. checks it after them; PlayerEnemyCollision decides a stomp with LDY, DEY, BPL on the vertical speed where Super Mario Bros. uses BMI and BNE (the two disagree only at speed $80); every stomp bounces the player through a new SetBounce, at vertical speed $FA, or $F8 off red paratroopas and flying green paratroopas, where Super Mario Bros. sets $FD after a stomp that defeats an enemy and $FC after one that demotes a paratroopa or knocks an enemy into its shell; HandleClimbing gives a life for grabbing the flagpole when the coin tally's digits and the timer's last digit match; HandlePipeEntry sends the player to the warp zone's one destination whichever pipe they take, where Super Mario Bros. picks by the pipe's x position; HandleCoinMetatile's axe restores Mario's physics; ChkForLandJumpSpring sets VerticalForceDown to $70 as well as VerticalForce; PlayerHammerCollision also skips while the player is off screen; HandleEToBGCollision bounces a power-up on a bumped block without stunning it and never demotes a piranha plant; CheckPlayerVertical drops its test of how far down the screen the player is; one bounding box grows from $14 to $16. The platform collisions, LandEnemyProperly, the side checks and BlockBufferCollision differ only in their addresses, and three regions, PlayerCollisionCore among them, are byte for byte the same.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1 · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”revised
    How we know
    cpy #UpsideDownPiranhaP
    sm2main.asm#L10190-L10190 · upstream ↗
    jmp InjurePlayer
    sm2main.asm#L10255-L10258 · upstream ↗
    ora StarInvincibleTimer
    sm2main.asm#L10424-L10425 · upstream ↗
    cpy #BulletBill_CannonVar
    sm2main.asm#L10356-L10361 · upstream ↗
    CPY #Podoboo
    src/prg.asm#L10515-L10520 · upstream ↗
    11296        sta VerticalForceDown
    
    sm2main.asm lines 11294–11296 at 9c40114 · upstream ↗
    LDA Player_Y_Speed
    src/prg.asm#L10556-L10558 · upstream ↗
    ldy Player_Y_Speed
    sm2main.asm#L10399-L10401 · upstream ↗
    LDA #$fd
    src/prg.asm#L10661-L10662 · upstream ↗
    LDA #$fc
    src/prg.asm#L10695-L10697 · upstream ↗
    cmp #RedParatroopa
    sm2main.asm#L10533-L10541 · upstream ↗
    sta FlagpoleScore
    sm2main.asm#L11225-L11231 · upstream ↗
    LDA Player_X_Position
    src/prg.asm#L11521-L11529 · upstream ↗
    11336          lda WarpZoneNumbers,x
    
    sm2main.asm lines 11334–11336 at 9c40114 · upstream ↗
    11163       jsr LoadMarioPhysics
    
    sm2main.asm line 11163 at 9c40114 · upstream ↗
    ora Misc_OffscreenBits
    sm2main.asm#L10224-L10224 · upstream ↗
    11511NoDemote:  cmp #PowerUpObject
    
    sm2main.asm lines 11501–11515 at 9c40114 · upstream ↗
    LDY Player_Y_HighPos
    src/prg.asm#L11066-L11072 · upstream ↗
    12036	.db $03, $0e, $0d, $14
    
    src/prg.asm line 12036 at 1cc3c92 · upstream ↗
    11827      .byte $03, $0e, $0d, $16
    
    sm2main.asm line 11827 at 9c40114 · upstream ↗
    10242FireballEnemyCDLoop:
    
    src/prg.asm lines 10227–12360 at 1cc3c92 · upstream ↗
    10085FireballEnemyCDLoop:
    
    sm2main.asm lines 10070–12141 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $D6D9-$E431. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $A319-$B0CF. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  50. ^ abThe status bar numbers, game setup, lives and game over (PrintStatusBarNumbers through RunGameOver) are Super Mario Bros.'s with a new GameOverSubs dispatch among them and these changes: the status bar's digit tables lose the second player's entries; UpdateTopScore checks one score where Super Mario Bros. checks two; DigitsMathRoutine drops a compare with zero before its BEQ; DefaultSprOffsets loses the sprite 0 data; InitializeArea loads the player's physics (LoadPhysicsData) and sets the secondary hard mode flag from 4-4 on and in all of worlds A to D (HardWorldFlag), where Super Mario Bros. sets it from 5-3 on or once the primary hard mode flag is set; SecondaryGameSetup sets the name table and switches on the status bar's IRQ split, where Super Mario Bros. sets the second player's lives and switches on the sprite 0 check; InitializeMemory also spares $0100-$0108; PlayerLoseLife reads its own halfway pages and no longer swaps players; RunGameOver opens the continue-or-retry menu (or, in world 9, ends the game) where Super Mario Bros. ends the game on Start or when the screen timer runs out and then hands over to the other player if they have lives left. GetAreaMusic and Entrance_GameTimerSetup keep every instruction, though the level timer's digits moved from $07F8 to $07EC.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”revised
    How we know
    1990	.db $06, $0c, $12, $18, $1e, $24
    
    src/prg.asm line 1990 at 1cc3c92 · upstream ↗
    2087	JSR TopScoreCheck
    
    src/prg.asm line 2087 at 1cc3c92 · upstream ↗
    2050	CMP #TitleScreenModeValue
    
    src/prg.asm line 2050 at 1cc3c92 · upstream ↗
    2119	.db $18, $ff, $23, $58
    
    src/prg.asm line 2119 at 1cc3c92 · upstream ↗
    2444      .byte $06, $0c, $12, $18
    
    sm2main.asm line 2444 at 9c40114 · upstream ↗
    lda HardWorldFlag
    sm2main.asm#L2591-L2598 · upstream ↗
    CMP #Level3
    src/prg.asm#L2172-L2179 · upstream ↗
    2609               jsr LoadPhysicsData
    
    sm2main.asm line 2609 at 9c40114 · upstream ↗
    2631             sta NameTableSelect
    
    sm2main.asm line 2631 at 9c40114 · upstream ↗
    INC Sprite0HitDetectFlag
    src/prg.asm#L2245-L2245 · upstream ↗
    2645             inc IRQUpdateFlag
    
    sm2main.asm line 2645 at 9c40114 · upstream ↗
    cpy #$09
    sm2main.asm#L2660-L2661 · upstream ↗
    JSR TransposePlayers
    src/prg.asm#L2441-L2441 · upstream ↗
    2472	AND #Start_Button
    
    src/prg.asm lines 2472–2473 at 1cc3c92 · upstream ↗
    jmp GameOverMenu
    sm2main.asm#L2854-L2856 · upstream ↗
    sta GameTimerDisplay
    sm2main.asm#L2751-L2751 · upstream ↗
    1989StatusBarOffset:
    
    src/prg.asm lines 1982–2534 at 1cc3c92 · upstream ↗
    2443StatusBarOffset:
    
    sm2main.asm lines 2438–2881 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $8EF4-$92AF. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $6D6D-$70BA. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  51. ^The code keeps the primary hard mode flag's checks, which turn Goombas into Buzzy Beetles, start walking enemies faster ($F4 against $F8), and revive stomped enemies sooner and send them off faster. Nothing in The Lost Levels' code sets the flag, and starting a game clears it, so none of these takes effect. Super Mario Bros. sets it from its world select flag when a game starts.Codedoppelganger's SMB2J disassembly · Xkeeper0/smb1
    How we know
    6983BuzzyBeetleMutate:
    6984        cmp #Goomba          ;if below $37, check for goomba
    6985        bne StrID            ;value ($3f or more always fails)
    6986        ldy PrimaryHardMode  ;check if primary hard mode flag is set
    6987        beq StrID            ;and if so, change goomba to buzzy beetle
    6988        lda #BuzzyBeetle
    6989StrID:  sta Enemy_ID,x       ;store enemy object number into buffer
    
    sm2main.asm lines 6983–6989 at 9c40114 · upstream ↗
    7751        pha                       ;save another copy to stack
    7752        ldy #Goomba               ;load value for goomba enemy
    7753        lda PrimaryHardMode       ;if primary hard mode flag not set,
    7754        beq PullID                ;branch, otherwise change to value
    7755        ldy #BuzzyBeetle          ;for buzzy beetle
    7756PullID: pla                       ;get second copy from stack
    
    sm2main.asm lines 7751–7756 at 9c40114 · upstream ↗
    7148NormalXSpdData:
    7149      .byte $f8, $f4
    ⋮
    7151InitNormalEnemy:
    7152         ldy #$01              ;load offset of 1 by default
    7153         lda PrimaryHardMode   ;check for primary hard mode flag set
    7154         bne GetESpd
    7155         dey                   ;if not set, decrement offset
    7156GetESpd: lda NormalXSpdData,y  ;get appropriate horizontal speed
    7157SetESpd: sta Enemy_X_Speed,x   ;store as speed for enemy object
    
    sm2main.asm lines 7148–7157 at 9c40114 · upstream ↗
    8213RevivedXSpeed:
    8214      .byte $08, $f8, $0c, $f4
    
    sm2main.asm lines 8213–8214 at 9c40114 · upstream ↗
    8351         lda PrimaryHardMode       ;check primary hard mode flag
    8352         beq SetRSpd               ;if not set, use pointer as-is
    8353         iny
    8354         iny                       ;otherwise increment 2 bytes to next data
    8355SetRSpd: lda RevivedXSpeed,y       ;load and store new horizontal speed
    8356         sta Enemy_X_Speed,x       ;and leave
    
    sm2main.asm lines 8351–8356 at 9c40114 · upstream ↗
    10518RevivalRateData:
    10519      .byte $10, $0b
    
    sm2main.asm lines 10518–10519 at 9c40114 · upstream ↗
    10530       ldy PrimaryHardMode        ;check primary hard mode flag
    10531       lda RevivalRateData,y      ;load timer setting according to flag
    10532       sta EnemyIntervalTimer,x   ;set as enemy timer to revive stomped enemy
    
    sm2main.asm lines 10530–10532 at 9c40114 · upstream ↗
    14848            ldy #$6f                 ;clear all memory as in initialization procedure,
    14849            jsr InitializeMemory     ;but this time, clear only as far as $076f
    
    sm2main.asm lines 14848–14849 at 9c40114 · upstream ↗
    415	LDA WorldSelectEnableFlag                    ; if world select flag is on, then primary
    416	STA PrimaryHardMode                          ; hard mode must be on as well
    
    src/prg.asm lines 415–416 at 1cc3c92 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  52. ^The area parser and its object builders (AreaParserTaskHandler through GetBlockBufferAddr) are Super Mario Bros.'s, with most changes in the metatile numbers they write, which shift with the renumbered metatiles (bridges, flagpole, coins, bricks, cannons, stairs, blocks, water pipe). Beyond those: the object jump table gains entries, the wind on and off commands among them, so three offsets into it change; ScrollLockObject_Warp picks the warp zone's destination by world, level and area; the third ledge style uses metatiles $8A-$8C and draws no stem, where Super Mario Bros.'s mushroom ledge uses $19-$1B with a stem (and RenderUnderPart drops its stem checks); the vertical pipes place a piranha plant through a shared SetupPiranhaPlant, with no exception for world 1-1; Jumpspring places nothing when no enemy slot is free. IncrementColumnPos, AlterAreaAttributes, KillEnemies and the object position helpers are byte for byte the same.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    LDA #$2e
    src/prg.asm#L2925-L2925 · upstream ↗
    lda #$36
    sm2main.asm#L3246-L3246 · upstream ↗
    .word WindOn
    sm2main.asm#L3385-L3386 · upstream ↗
    lda WorldNumber
    sm2main.asm#L3429-L3429 · upstream ↗
    LDA #$19
    src/prg.asm#L3215-L3215 · upstream ↗
    3229	LDA #$4f
    
    src/prg.asm line 3229 at 1cc3c92 · upstream ↗
    lda #$8a
    sm2main.asm#L3550-L3550 · upstream ↗
    3560          rts
    
    sm2main.asm line 3560 at 9c40114 · upstream ↗
    3852	CPY #$54
    
    src/prg.asm lines 3852–3855 at 1cc3c92 · upstream ↗
    4145             cpy #$8b
    
    sm2main.asm line 4145 at 9c40114 · upstream ↗
    3428	LDA AreaNumber
    
    src/prg.asm lines 3428–3430 at 1cc3c92 · upstream ↗
    3772SetupPiranhaPlant:
    
    sm2main.asm lines 3772–3773 at 9c40114 · upstream ↗
    bcs NoJs
    sm2main.asm#L4040-L4040 · upstream ↗
    2543DoAPTasks:
    
    src/prg.asm lines 2539–3938 at 1cc3c92 · upstream ↗
    2897DoAPTasks:    dey
    ⋮
    3759          dey
    ⋮
    4083          dey
    ⋮
    4156             dey
    
    sm2main.asm lines 2893–4227 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $92B0-$9BF5. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $70C1-$7A36. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  53. ^ abFireballs, the level timer and the stage objects (ProcFireballs through VineObjectHandler) are Super Mario Bros.'s with these changes: RunGameTimer tests the player's height with BPL instead of BCS and points at the timer digits' new place; WarpZoneObject no longer counts up WarpZoneControl; FlagpoleRoutine gives a life for the new sixth flagpole score; JumpspringHandler launches with the green springs' force on world numbers 2, 3 and 7; VineObjectHandler erases the vine and its metatiles once it goes off the left of the screen. ProcFireballs and ProcessWhirlpools differ only in their addresses, and SetupVine is byte for byte the same.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    BCS ExGTimer
    src/prg.asm#L5324-L5324 · upstream ↗
    bpl ExGTimer
    sm2main.asm#L5387-L5387 · upstream ↗
    LDY #$23
    src/prg.asm#L5342-L5342 · upstream ↗
    ldy #$17
    sm2main.asm#L5404-L5404 · upstream ↗
    INC WarpZoneControl
    src/prg.asm#L5364-L5364 · upstream ↗
    5554           inc NumberofLives
    
    sm2main.asm lines 5552–5557 at 9c40114 · upstream ↗
    cpy #World7
    sm2main.asm#L5604-L5611 · upstream ↗
    5714ChkVOffscr: lda Enemy_X_Position+5
    
    sm2main.asm lines 5714–5724 at 9c40114 · upstream ↗
    5174ProcFireballs:
    
    src/prg.asm lines 5143–5658 at 1cc3c92 · upstream ↗
    5246ProcFireballs:
    
    sm2main.asm lines 5215–5749 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $B624-$B9B9. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $8190-$8584. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  54. ^Enemy spawning and set-up (EnemiesAndLoopsCore through InitJumpGPTroopa) are Super Mario Bros.'s with these changes: ProcLoopCommand reads 12 loop entries where Super Mario Bros. reads 11, and takes each loop's number of checks from a new MultiLoopCount table where Super Mario Bros. special-cases world 7; ProcessEnemyData skips a check in world 9 and gives one enemy code a piranha plant set-up; InitHammerBro checks the world; LakituAndSpinyHandler brings Lakitu back once LakituReappearTimer reaches 3, where Super Mario Bros. waits until it reaches 7, and brings him back lower on the screen in worlds 7 to 9 and A to D; InitBowser first erases any other Bowser; InitPiranhaPlant patches the plant's palette and pipe distance, green in worlds 1 to 3 and red from world 4 and in A to D; InitJumpGPTroopa starts the jumping paratroopa at x speed $F4 where Super Mario Bros. uses $F8. Of its 27 regions, 15 differ only in their addresses and 5 are byte for byte the same.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”revised
    How we know
    LDY #$0b
    src/prg.asm#L6797-L6797 · upstream ↗
    ldy #$0c
    sm2main.asm#L6832-L6832 · upstream ↗
    CMP #World7
    src/prg.asm#L6813-L6815 · upstream ↗
    6850          cmp MultiLoopCount,y
    
    sm2main.asm line 6850 at 9c40114 · upstream ↗
    cmp #World9
    sm2main.asm#L7018-L7020 · upstream ↗
    7174       cmp #World7
    
    sm2main.asm lines 7173–7175 at 9c40114 · upstream ↗
    CMP #$07
    src/prg.asm#L7275-L7276 · upstream ↗
    cmp #$03
    sm2main.asm#L7265-L7266 · upstream ↗
    7280          ldy HardWorldFlag
    
    sm2main.asm lines 7280–7285 at 9c40114 · upstream ↗
    KKCheck: cpy ObjectOffset
    sm2main.asm#L7483-L7493 · upstream ↗
    sta EnemyAttributeData+PiranhaPlant
    sm2main.asm#L7810-L7821 · upstream ↗
    LDA #$f8
    src/prg.asm#L7895-L7895 · upstream ↗
    lda #$f4
    sm2main.asm#L7874-L7874 · upstream ↗
    6734ChkAreaTsk:
    
    src/prg.asm lines 6727–7901 at 1cc3c92 · upstream ↗
    ChkAreaTsk: lda AreaParserTaskNum
    sm2main.asm#L6758-L7878 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $C047-$C7DE. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $8C23-$9413. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  55. ^ abRunStarFlagObj through OffscreenBoundsCheck are Super Mario Bros.'s with these changes: RunStarFlagObj sets off fireworks when the timer's last digit matches the coin tally's, where Super Mario Bros. matches the timer's last digit against 1, 3 and 6, and adds its points to the one player's score; MovePiranhaPlant moves red piranha plants (the patched palette) every frame; BalancePlatform leaves a platform alone when its partner is no balance platform; OffscreenBoundsCheck treats upside-down piranha plants like upright ones. FirebarSpin is byte for byte the same, and the moving platforms differ only in their addresses.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”
    How we know
    9610	CMP #$06
    
    src/prg.asm lines 9602–9611 at 1cc3c92 · upstream ↗
    cmp CoinDisplay+1
    sm2main.asm#L9472-L9472 · upstream ↗
    LDA CurrentPlayer
    src/prg.asm#L9643-L9643 · upstream ↗
    cmp #$22
    sm2main.asm#L9615-L9615 · upstream ↗
    cmp #$24
    sm2main.asm#L9682-L9684 · upstream ↗
    cpy #PiranhaPlant
    sm2main.asm#L10023-L10023 · upstream ↗
    9581StarFlagXPosAdder:
    
    src/prg.asm lines 9579–10216 at 1cc3c92 · upstream ↗
    9450StarFlagXPosAdder:
    
    sm2main.asm lines 9448–10064 at 9c40114 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $D2CD-$D6D5. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $9F02-$A318. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  56. ^The platforms' set-up, the enemy object loop, the enemies' movers, Bowser and the fireworks (InitBalPlatform through RunFireworks, 32 regions) are Super Mario Bros.'s instruction for instruction, with two changes: the enemy movers' jump table (EnemyMovementSubs) sends enemy 4, the upside-down piranha plant, to the new MoveUpsideDownPiranhaP, where Super Mario Bros. has MoveNormalEnemy; MoveSwimmingCheepCheep adds $40 to a swimming Cheep Cheep's vertical fraction each frame where Super Mario Bros. adds $20. Three of the regions are byte for byte the same, and the rest differ only in the addresses of their calls, jumps and tables.CodeXkeeper0/smb1 · doppelganger's SMB2J disassembly · “Super Mario Bros. (World)” · “Super Mario Bros. 2 (Japan) (En)”revised
    How we know
    MoveNormalEnemy
    src/prg.asm#L8124-L8124 · upstream ↗
    MoveUpsideDownPiranhaP
    sm2main.asm#L8093-L8093 · upstream ↗
    8682	LDA #$20
    
    src/prg.asm lines 8682–8683 at 1cc3c92 · upstream ↗
    8621        lda #$40
    
    sm2main.asm lines 8621–8622 at 9c40114 · upstream ↗
    ADC $02
    src/prg.asm#L8689-L8691 · upstream ↗
    7912AlignP:
    
    src/prg.asm lines 7906–9574 at 1cc3c92 · upstream ↗
    AlignP: ldy #$ff
    sm2main.asm#L7883-L9443 · upstream ↗

    In the cartridge (“Super Mario Bros. (World)”): $C7DF-$D2CC. We don't reproduce the bytes.

    In the cartridge (“Super Mario Bros. 2 (Japan) (En)”): SM2MAIN $9414-$9F01. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

Sources

Code

Primary

Secondary