z64-tex-ext is an extension of the map format used in N64 Zeldas. What it's basic function is to load and execute code specified in the map header's mesh header command. Normally, a mesh header is something like
0A000000 mmmmmmmm where
m is the address of the mesh data header. The 24-bits after the
0x0A command are usually ignored - this is where this extension comes in. z64-tex-ext uses those 24 bits as an offset of code to execute, assumed to be the same segment (also known as bank) as the offset of the mesh data header,
m. Thus, if a version of the game does not have z64-tex-ext ported to it, the map still runs, as the bits used for the offset of the code are normally ignored by the engine. This extension was created with the intention of making animated textures possible in imported maps, for things such as windows which light up at night, or scrolling water textures. However, it has many other possible uses.
Utilizing the extension
The extension is loaded under the circumstances that:
- It uses the first entry in the jump table for scene-specific functions (most test maps, and maps with no special properties usually use this)
- The code is properly pointed to in the mesh header command
It is loaded to unused memory whenever the map's header offset changes, and is executed that time and each frame afterwards. The current implementation loads the data to
Whenever the user's function is called, it is passed one argument - a pointer to the global context, commonly referred to here as
z_ctxt. It is used for an argument in many, many functions, including some of the built in ones.
Built in functions
To use these functions, be sure to include help_funcs.h in your source and include extern.ld (produced when z64-tex-ext is built)
While actually a macro and not a function, this is part of the helper functions provided by z64-tex-ext. It takes a segmented address (form
bboooooo) and converts it to a RAM pointer (form
80xxxxxx). This is useful when converting something from a map or scene pointer to a specific address to use in a gSPSegment command.
void * seg_to_ram( int
Gives the RAM pointer of segment
void dl_write( void
Writes a display list command to the current display list of
z_ctxt, consisting of the 32-bit words
void set_segment( void
seg to address
ptr in the current display list used by
Porting to other games
You'll probably have to poke around in RAM to get some addresses - try finding the scene table bytes which control which jump table entry is read and break-pointing that data. It should point you in the right direction. As for finding the location of the segment table... Locate the map, scene, or gameplay_keep in RAM and search for their ram offsets
& 0xFFFFFF - their high 8 bits are omitted for some reason in the segment table. You'll probably get
multiple results; but something that is like this is probably it:
00000000 00000000 ssssssss mmmmmmmm
gggggggg ( ... )
s is the scene's offset,
m is the map's offset, and
g is gameplay_keep's offset. Do keep in mind that the map offset is not necessarily the same one as pointed to by map_ptr_ptr (see global.ld), as that pointer is to the current map header.
And remember, patches would be greatly appreciated if you do indeed port to another game. Feel free to fork it if you want to do it that way.