Language…
21 users online: bMatSantos, bradcomp, DanMario24YT, DashGamer, Domokun007, eltiolavara9, Green Jerry, hhuxy, lo fang 123, Michel2023, Nayfal, nonamelol1, playagmes169, prisvag, Serena, Shomi,  shovda, SMW Magic, TheXander, Torchkas, Tulip Time Scholarship Games - Guests: 285 - Bots: 351
Users: 64,795 (2,375 active)
Latest user: mathew

Mario/Cape Tilemap Notes

here i will dump a bunch of stuff relating to mario and his cape (mainly their tilemaps)


first, mario's tilemap (common knowledge already but w/e)

mario's tilemap data begins at $00E00C. $00E00C specifically is the tiles for Mario's head (top half).
$00E0CC is the tiles for Mario's body (bottom half).
logically, you would pair the two tables to get mario's full image
(excludes 8x8 tiles, cape, full balloon form, and full cape gliding forms. more on how these work later).
to understand how the table is indexed, first see $00DF16 (named TilesetIndex in all.log):
db $00,$46,$83,$46

$00DF16 is indexed by $19. so small mario gets x00, big mario gets x46, cape mario gets x83, and fire mario
gets the same value as big mario, x46. the value from this table + the value in $13E0 then becomes the index
to the tilemap tables, UNLESS $13E0 is greater than or equal to x3D, in which case $13E0 alone is used as
an index, and $00DF16 is ignored. this whole process is done at $00E3A4

(if you want to see what frames x3D+ are, here)

for the actual values used in the tilemap table, see this image i made a while ago:


basically, the tile values in the tables are converted directly to offsets to $7E2000 (the code responsible
for this is at $00F636. this also handles the cape tile conversions covered later). because the values are
offsets, and can access up to 32kb of data, and because GFX32 is less than 32kb, you can actually use part of
GFX33 for mario's tilemap (this can be seen in the image above)



now for the miscellaneous tiles

remember the index from before? where $00DF16 indexed by $19 is added to $13E0, except if $13E0 is >= x3D in
which case $13E0 alone is used?
well, this same value is used to index the table at $00DF1A (named TileExpansion? in all.log, and yes with the question mark).
the value gathered from this table (a multiple of 4, important) in turn is used to index $00DFDA.
$00DFDA (named Mario8x8Tiles in all.log) is a table comprised of 4-byte groups for the most part, where
the 1st byte is mario's head, the 2nd mario's body, the 3rd mario's 8x8 tile #1, and the 4th mario's 8x8 tile #2
"but werent mario's head and body at $00E00C and $E0CC?"
yes. the values in this table, however, correspond directly to tiles in GFX00. the values for mario's head and
body here are all x00 and x02. in a sense, this table is the REAL tilemap table, because it maps directly to
the sprite GFX, and the other tilemap table handles the dynamic frames that are uploaded to GFX00

note that when i say the values "correspond directly to tiles in GFX00", i LITERALLY mean that. you cannot
access GFX01, as any value above x7F (any negative value) is treated as null and not uploaded.

at the end of $00DFDA you'll see 6 extraneous bytes. these are cape tiles. i'll cover these later

by analyzing $00DF1A and $00DFDA, you can see which frames make use of 8x8 tiles.
of note is the balloon pose. you'll see it in $00DFDA as:
db $00,$02,$02,$80

normally, the 8x8 tiles are, well, 8x8. however, the balloon pose is a special case, and the 1st 8x8 tile
is treated as 16x16. the code responsible for this is at $00E385... which reminds me. i'll explain "$04"
quickly. "$04" in mario's tilemap code holds what size mario's tiles will be (8x8 or 16x16). $00E385 is where
it's stored to.

the format is:
abcdefg-
where:
a = head
b = body
c = 8x8 tile #1
d = 8x8 tile #2
e = cape
f = misc cape tile #1
g = misc cape tile #2

bit clear = 8x8, bit set = 16x16

the default value is xC8. balloon mario is xE8

as for the x-flipping done with balloon mario's extra tile, that's just a simple check in the oam code at $00E3E4



before we get to the cape, let's cover the tile positioning. tile positioning is covered by 4 tables, one
indexing the 2nd which indexes the 3rd & 4th. perplexing, but all this tables-indexing-tables is what allows
mario to be so fluid and dynamic in his animations

up first we have $00DCEC. this table is indexed directly by $13E0 (unless you are small and entering a
horizontal pipe with yoshi [$13E0=x29,$19=x00], in which case an index of x20 is used). note that the values
in this table are all even values. that's because the value gathered from here is OR'ed with mario's direction,
and this new value is used to index the table at $00DD32. thus, the even entries in $00DD32 are for mario
facing left for a certain frame (or set of frames), and the odd entries are for mario facing right for that
same frame (or set of frames)

the value gathered from $00DD32 now acts as an index to 2 separate tables:
$00DD4E (the X-position table) and $00DE32 (the Y-position table). these tables handle all tile positions
(head, body, 8x8 tiles, and cape tiles). cape positions start at table+x84

the tables are basically comprised of 8 byte groups (you'll notice that most values in $00DD32 are multiples
of 8). these 8 byte groups are actually 4 16bit values: mario's head, body, 8x8 tile #1, and 8x8 tile #2
very simple. the 16bit values are technically offsets added to $7E (for Xpos) or $80 (for Ypos), those RAM
addresses being mario's position relative to the screen

for the most part, the even groups of 8 bytes are for mario facing left and the odd groups of 8 bytes
are for mario facing right.





so that's mario's tilemap. now i'll cover the lovely cape tilemap

... i guess i'll start with what i mentioned earlier: $00DFDA
at index x2C you have 6 tiles relating to the cape:
db $04,$7F,$4A,$5B,$4B,$5A

again, these are direct offsets to tiles in GFX00. $04 is the dynamic cape image, $7F is a dynamic misc cape
tile, and the rest are static misc cape tiles.


$13E0 acts as an index to $00E18E. $00E18E contains indexes to the junk that starts at $00E1D4.

when i first saw $00E1D4 and the data following, i thought nintendo was trolling big-time and combined 5
tables into 1 to save space. thankfully, that isn't really the case; $00E1D4 is *technically* a single
table comprised of 5-byte groups. i say *technically* because some compression is present (if there was
no compression, then $00E18E would only contain multiples of 5).

the format of each 5 byte group is:

MASK,DYNAMIC,POSITION,TILE1,TILE2

MASK is TSB'd directly to $78, and is thus used to mask cape tiles when they aren't needed (like if a frame
only requires 1 cape tile instead of the 3 that are present). HOWEVER, note that when MASK is applied,
$78 has been LSR'd 4 times already (during the processing of mario's 4 main tiles)
so instead of:
dlucapLU

$78 is:
----dluc

and the values in MASK reflect this, only affecting the low 3 bits.
bit 7 of MASK technically signifies that the tile should use a different OAM index (a higher one, to give the cape tile higher priority)

POSITION is much like $00DCEC, in that it's OR'ed with mario's direction and becomes an index to $00E21A,
which then indexes the main X/Y position tables which i explained earlier

DYNAMIC is weird. if it's less than 4, then an image from the table at $00E23A is uploaded. let
me explain:

$13DF is the cape's frame, like $13E0 for mario. if DYNAMIC is less than 4, then $13DF gets multiplied by
4 and OR'd with DYNAMIC, and this becomes an index to $00E23A. $00E23A thus contains the actual fluttering cape images;
the others in $00E1D4 are mainly for gliding (and wall-running, and climbing, and... you get the point)

except for the first 4 bytes, $00E23A uses the same value in each 4 byte group. pretty dumb, right? well, yeah.
but the index for $00E23A is also the index for $00E266. $00E266 is the position table; the values here being
used instead of POSITION. also contains many same values, but whatever...

i sorta mentioned that $00E23A/$00E266 is 4-byte groups. the 1st is "mario standing" (actually most of
mario's standard frames), the 2nd is mario crouching (on yoshi too, also entering horiz pipe), the 3rd is
mario riding yoshi, and the 4th is "about to use yoshi tongue"

oops, forgot to mention that the tile values from $00E23A are direct offsets to tiles in GFX32. so unlike
mario's tilemap, which has an odd mapping format, the cape tilemap is just standard offsets to GFX32.
this means that cape tiles can only use the first page of GFX32 (which is why you only see cape tiles on
the first page of GFX32 and not the others).


anyways, if DYNAMIC is NOT less than 4, then, well, it becomes a direct offset to GFX32 like i explained above.

note that DYNAMIC is always a 16x16 tile, and TILE1 and TILE2 are always 8x8. and POSITION represents all 3 as a starting index,
unless DYNAMIC is less than 4 (like i explained earlier)

DYNAMIC is uploaded to tile $04 in GFX00
TILE1 is a direct offset to GFX32. this tile is uploaded to tile $7F in GFX00
TILE2 is an index to $00DFDA, mainly the last 4 values (which are the 4 misc cape tiles in GFX00)





... and I think that's it. comments or questions are welcome
1: Which graphical values from $00E1D4 correspond to each mario frame?

(or: What does the values compare from ROM $00E1D4 to RAM address $13E0, as well as $13DF?)

2: I made the first question of this thread, Yay!

EDIT: A list of equivelent player frame names is enough for #1
if i have the time, i'll make a chart of sorts. but for now follow this:

Originally posted by me
$13E0 acts as an index to $00E18E. $00E18E contains indexes to the junk that starts at $00E1D4.
i finally made that chart (hope alcaro doesnt mind me putting it on his server)

https://loli.muncher.se/mariocape/

you'll see a lot of "null", mainly with extra tile 1 & 2 (and position). since the majority of frames dont use them, the bytes reserved for them are used for the beginning of a new index, effectively "compressing" the table. only 4 of the cape gliding frames make use of all 5 bytes. i could have just left all of the null entries blank, but w/e...