3 ms·
The minus world is technically an out-of-bounds level. The game treats it at world 36-1 (since the digits are tile numbers 0-9, followed by the alphabet, then a
by LocalH 4y ago
The minus world is technically an out-of-bounds level. The game treats it at world 36-1 (since the digits are tile numbers 0-9, followed by the alphabet, then a space tile at $24 or 36). Since doing so reads a whole host of other data out-of-bounds as well, it ends up pointing at the level layout for 2-2, but without the data that properly sets the pipe destination, resulting in an infinitely-looping level.
Other versions of SMB have different minus worlds (and some versions had the bug either fixed as in Super Mario All-Stars, or blocked off as in VS Super Mario Bros). Famicom Disk System version of SMB1 has a three-level minus world that ends with a Bowser fight that completes the game as if it was 8-4.
The minus world is a total bug. It was not designed or intended to exist. The bug was solely the result of the INC WarpZoneCtrl instruction that the video author mentions, which makes the game treat the warp zone pipes as the 4-2 warp zone until the text appears. Remove that INC, and the game will instead dump you out as if you'd gone in the L-pipe prior to the warp zone.
Obviously this bug doesn't exist at all in SMB DX for Game Boy Color, as it is a completely rewritten engine. I would presume the bug didn't exist at all in Super Mario Bros 35.
- vlunkr 4y agoIt’s pretty interesting how the game can continue to function in a level that isn’t supposed to exist. Metroid has similar areas I believe. It’s hard to imagine a modern game or any modern software handling a scenario like that without crashing.
- jaywalk 4y agoI think it's a reflection of how incredibly simplistic these older systems and games really are. Modern games bear no resemblance to them as far as level design and asset storage go.
- morelisp 4y agoSuch bugs are definitely still possible if you’re writing for modern systems in a similar style (large blocks of contiguous memory interpreted only as needed). Just yesterday I was storing my color planes in three separate adjacent buffers for reasons, and if you looped the player off the bottom of the screen it came back up in a different color on the top. Now I need to figure out what to do with that…
- jaywalk 4y agoThat's quite different from an actual, playable level appearing out of a bug.
- morelisp 4y agoNot really - if I had any tilemap structures for the level yet, it would've had a similar effect. The point is this stuff arises whenever you have, like `char level_data[8][4][10][100]` rather than, like `class level { std::vector<actor*> actors; std::vector<sprite*> background; }`. And storing stuff in large contiguous blocks that can be interesting when misinterpreted is still a pretty good way to write modern games if you don't have OO brain rot.
- jaywalk 4y agoSorry, I missed the part where you mentioned that you were writing your game in a similar style to classic games. Of course that does open up the door to similar bugs causing similar results.
- NobodyNada 4y agoIt depends on the game, its level format, and how much error-checking it has. Games written in assembly from the 80's typically did not waste bytes & cycles on assertions/error-checks -- if you're at the point where you're decoding invalid level data, something's already gone so screwed up that it doesn't really matter what happen next. Add to that the fact that older consoles had no memory protection, so there's no such thing as a segmentation fault. You can even read from a memory address that's not mapped to anything, and you won't get an error; you'll get some value back based on analog effects of the memory bus. Pretty much the only ways an NES game can "crash" is by calling an invalid function pointer, corrupting the stack, or getting stuck in an infinite loop somewhere. Otherwise, the game will more-or-less stumble on no matter what you throw at it -- accessing an array out of bounds will usually give you a nonsensical value taken from whatever comes after the array on the cartridge, dereferencing an invalid pointer will just give you some arbitrary data from RAM or ROM, etc. Therefore, the effects of going to an out-of-bounds level can vary from game to game, depending on what sort of format the game uses to store level data. Off the top of my head: - Super Mario Bros. gives you slightly broken versions of regular levels, such as the various Minus Worlds. I haven't looked into the code, but presumably this is because a "level" is really just a header that contains indexes into tables of rooms & enemy lists & whatnot. So, going into an invalid level gives you a weird combination of existing rooms and enemies. - Super Mario Bros. 3's level format has a lot of function pointers, so it usually crashes if you select an invalid level from the map screen. But the levels get decompressed into a big 2D array of tiles in RAM, so if you go out-of-bounds within a level you end up in a world of garbled tiles. Although some of those tiles will call invalid function pointers & crash the game when you interact with them; famously, this can be turned into an arbitrary code execution exploit. Here's a video of a speedrunner exploiting this in real time, manipulating enemies so that their positions in RAM form a short program that triggers the end cutscene: https://youtu.be/mUeozQtSmrg?t=202 https://youtu.be/mUeozQtSmrg?t=202 - Mega Man 2 stores level data as a grid of tiles on the cartridge, but all the levels are stored consecutively, so if you go out-of-bounds you usually end up in a garbled version of another level. - The famous MissingNo. glitch in Pokemon Red and Blue is caused by use of an uninitialized variable that causes a decompression routine to run on bad input, which then triggers a buffer overflow that stomps on part of your save file: https://youtu.be/ZI50XUeN6QE?t=880 https://youtu.be/ZI50XUeN6QE?t=880
- feoren 4y agoThat's because in modern software design, crashing is preferred to continuing to read invalid data, which has no upper limit on the amount of possible permanent damage it could cause. Would you rather have your game crash, or corrupt your 100-hour savegame? Crashing is the more elegant solution to this type of error, and a large percentage of language design after C++ went into turning undefined-behavior scenarios into crash scenarios.
- vlunkr 4y agoYeah I’m not trying to say it’s better or anything, I’m just so unfamiliar with environments where going out of bounds isn’t an immediate failure.
- synu 4y agoReally awesome, thanks for the explanation. You can get some really wild bugs when you write your game in assembly.
- gxqoz 4y agoThis fascinating article [1] on the history of SMB hacking in Japan gives some more details on Minus World-like worlds and how they could be manipulated by "hot swapping" Famicom cartridges. "Players quickly figured out that it was possible to access levels beyond 8-4 by hot-swapping cartridges. What is positively known is that in 1986 a magazine called “FC Bug Boy Special: Super Mario 256W ” was released by JICC Publishing Office in Japan.3 This magazine detailed how to access worlds beyond 8-4 with the hot-swap method.4 It also included data tables and information about these mysterious levels.5 This publication most likely helped information about “256-World” spread through the budding player/hacking community." This ultimately led to the release of the Tonkachi Editor, sort of like a primitive Game Genie where you could laboriously modify memory to more precisely hack together your own levels. "It was a binary editor, but far from the sophisticated software available on today’s computers, it was light and simple at best, and could only patch data displayed in hexadecimal or ASCII code, not move or copy data. Since there was no environment, of course, no printout was possible. Moreover, due to the nature of quick disks, subsequent files could easily be destroyed if they were rewritten on a different drive or other device, and recovering them required a great deal of effort. In fact, even now that I am accustomed to using a Tonkachi, a task that can be done in a few minutes on a PC can take up to an hour or two on the NES if you use a Tonkachi." This ultimately resulted in a ROM Hack version of SMB called Tonkachi Mario released all the way back in 1987, at least a decade before I'd have assumed such hacks were being released. [1] https://glitchcat7.com/the-complete-history-of-kaizo-mario/ https://glitchcat7.com/the-complete-history-of-kaizo-mario/