Level header format Edit
Header (9 bytes): 11 22 33 44 55 66 77 88 99 AB AB AB AB AB AB AB AB AB 1x = level pointer 2x = level pointer 3x = enemy pointer 4x = enemy pointer 5A = level start Y (first 3 bits) 5B = level length 6A = level start X (first 3 bits) 6x = enemy color palette # (bits 4, 5) 6B = level color palette # 7A = level scrolling type 7B = level object set 8A = level start action (first 3 bits) 8x = level graphic set (bits 4-15) 9A = time (first 2 bits) 9B = music Level objects (3/4 bytes each): Y position (3 leftmost bits = object bank ["domain"]) X position Type Length (only if 4 byte object) Enemy objects (3 bytes each): Type X Y Level data: Header followed by all level objects followed by byte $FF Enemy objects (NOT after level objects) followed by byte $FF The game renders objects in the order they appear in the level data. Palettes (size for one obj.set = $C0): Object set 1 at $36CA2, Object set 2 at $36D62 ...
World map Edit
(Big reminder, y position is done funny in SMB3! The range in SMB3 is actually 20 hex (for 0) to a0 hex (for 90), because that is the y position on the screen the top part of the map is.)
A comment on screens: When the screen scrolls over, it first scrolls over half a screen; it then scrolls over another half a screen adding up to a whole screen. Usually, if they're only referring to the x position, and not the scroll of the screen, then the screen number would just be tacked on as the high byte. Now, when referring to the screen scroll, the game has two values stored in memory: the half-value and the whole-value. The whole-value determines the screen it is at, and the half-value determines if it would be scrolled over half from there or not--80 (hex) if so, 00 if not. So a whole-value of 02 and a half-value of 80 (hex) means that it will be scrolled over 2 and a half. When stored in memory in one byte, the upper nybble may be the whole-value, and the half-value would alternate between 8 and 0 for 80 (hex) and 00.
|World||Starting Address (hex)||No. Tiles (hex)||No. Screens|
Each byte represents the index of a 16x16 pixel tile. The table starts in the upper left hand corner of screen 0 (the leftmost screen) and goes to the right until it reaches the rightmost pixel in the screen and then goes to the leftmost portion of the next line. There are always 9 horizontal lines on the map, and after it finishes screen 0 (after 0x90 bytes), then it goes to screen 1 and goes to the top left portion of it. It does this for each successive screen. Map data seems to be terminated by 0xFF.
The table that sets up the 16x16 pixel tiles starts at 18010 (hex); it is 400 (hex) bytes long, and the first 100 (hex) bytes determine the index the 8x8 tile to be culled from the 1000 (hex)-byte CHR bank starting at 45010 (hex) to be placed in the upper left portion of the 16x16 title. The next 100 bytes determine for the lower left, then the upper right, and finally the lower right.
|World||Starting Address (hex)||No. Pointers (hex)|
Each world has its own table of data. Here is the format in the order therein stored:
- First 4 Bytes: The starting index of pointers for each screen. For example, if the index of the first pointer for screen 1 (second screen) is 12(hex), then byte 1 (second byte) should be 12 (hex). Of course, this means that pointers should be ordered by screen number then y position and then x position in ascending order. Beneficii's program SMB3 Map Editor makes sure to do the ordering, then add the starting indices to the first 4 bytes for accurate performance.
(note: for all groups after this, the number of bytes for each one is dependent on the number of pointers for the world in question; substitute the number of pointers for x)
- Y Position/Object Set (x bytes): the high nybble is the y position of the pointer; the low nybble is the object set for that pointer.
- Screen Number/X Position (x bytes): the high nybble is the screen number of the pointer; the low nybble is the x position of the pointer
- Enemy or Sprite Data Address As Loaded Into NES RAM (2 * x bytes): the starting byte for the enemy data in RAM. The ROM address is this plus 10.
- Object Data Address As Loaded Into NES RAM (2 * x bytes): the starting byte for the object data in RAM. The ROM address is this plus 10 plus whatever amount needs to be added for the current object set. This is because different banks are loaded depending on the current object set.
Unlike with pointers, in which each world has its own table, there is one big table for sprites; each world is represented in each group. There are 9 sprites per world; the first world represented as the first 9 bytes of the first group, the second world as the second 9 bytes, and so on. Here's where the variety of types start at (in hex):
Y Position: 16070 Screen Number: 160B8 X Position: 16100 Type: 16148 Item: 16190
Starting location Edit
In the game, the x position Mario's starting space in each world is hardcoded to 20 (hex) and the screen number to 0, in contrast to the y position, which has a table for the first 8 worlds. It took extensive ASM hacking to get around the hardcoding, but it has been accomplished; the IPS file containing the patch is distributed with Beneficii's SMB3 Map Editor. It changes how the game loads 0x20 and the initial screen; then it extensively changes the game over sequence for the game, because it was hardcoded for that also. There are tables for starting screen and x position that come with the patch.
Y Position: 3C39A Screen (hack): 17C90 X Position (hack): 17C88
For the screen, the upper nybble determines the whole-value and the lower nybble determines the half-value.
The first byte in each table does for first world, the second byte second world, etc.
AIRSHIP RETREAT POINTS
There are 12 (hex) airship retreat points per world, and like the sprites, each category has all the worlds in it. The x position has the upper nybble be the x position and the lower nybble be the screen number.
Y Position: 1700E X Position: 1709E