Notes:Mario Kart 64
This page contains notes for the game Mario Kart 64.
A deposit of the now defunct 64.vg/w/.
Functions
Native functions
/* 0x800936B8 */ extern void mk64_draw_text ( int x, int y, char * s, float xscale, float yscale, int u );
/* 0x80057710 */ extern void mk64_debug_text_preface ( void );
/* 0x800577A4 */ extern void mk64_draw_debug_text ( int x, int y, char * );
/* 0x80098DF8 */ extern void mk64_draw_square ( void *, int up_x, int up_y, int low_x, int low_y, u8, u8, u8, u8 );
/* 0x800400D0 */ extern void mk64_mio0_decode ( void * input, void * output );
Symbols
0x800046AC { osViExtendVStart }
Auxiliary symbols for `osViExtendVStart`: 0x80162D5C = __additional_scanline
0x80028F5C { osSyncPrintf, rmonPrintf }
0x8005994C { leoInitUnit_atten }
Auxiliary symbols for `leoInitUnit_atten`:
0x8005C654 { alSynDelete }
0x800CE130 0x800D2B80 { __osViGetCurrentContext, __osViGetNextContext, osPiGetDeviceType, __osGetActiveQueue, __osGetCurrFaultedThread, leoChkUnit_atten }
Auxiliary symbols for `__osViGetCurrentContext`: 0x800EB3AC = __osViCurr Auxiliary symbols for `__osViGetNextContext`: 0x800EB3AC = __osViNext Auxiliary symbols for `osPiGetDeviceType`: 0x800EB3AC = osRomType Auxiliary symbols for `__osGetActiveQueue`: 0x800EB3AC = __osActiveQueue Auxiliary symbols for `__osGetCurrFaultedThread`: 0x800EB3AC = __osFaultedThread Auxiliary symbols for `leoChkUnit_atten`:
0x800D2A10 { osGetThreadPri }
Auxiliary symbols for `osGetThreadPri`: 0x800EB3B0 = __osRunningThread
Extractor
A rudimentary extractor which picks out MIO0 blocks and infers their length via the compression format can be found here. You can also download the Windows binary
Filesystem
Mario Kart 64 doesn't have a single unified filesystem. A search for "MIO0\x00\x00\x10\x00" confirms this. Files are either loaded via distinct tables or through direct lui/addiu operations. This does not dismiss the possibility of being able to change the compression algorithm the ROM uses, however. A hash table could be employed with the original offsets of the file being used as the key. Thus, a DMA function could be intercepted and the proper file loaded regardless of new location.
Map Data
The code that processes the DMA and decompression of map files is dynamically loaded. 0x802AA918: sll t6,a0,2
0x802AA91C: subu t6,t6,a0
0x802AA920: lui t7,0x802c
0x802AA924: addiu t7,t7,-29312
0x802AA928: sll t6,t6,4
0x802AA92C: addu v0,t6,t7
0x802AA930: addiu $sp,$sp,-96
0x802AA934: lui v1,0x800e
0x802AA938: lw v1,-15092(v1)
0x802AA93C: lw t8,0(v0)
0x802AA940: lw t9,4(v0)
0x802AA944: lw t0,8(v0)
0x802AA948: lw t1,12(v0)
0x802AA94C: lw t2,40(v0)
0x802AA950: lw t3,24(v0)
0x802AA954: lw t4,32(v0)
0x802AA958: lw t5,28(v0)
0x802AA95C: lw t6,36(v0)
0x802AA960: lhu t7,44(v0)
0x802AA964: li $at,5
0x802AA968: sw $ra,20($sp)
0x802AA96C: lw a2,16(v0)
0x802AA970: lw a1,20(v0)
0x802AA974: sw t8,72($sp)
0x802AA978: sw t9,68($sp)
0x802AA97C: sw t0,64($sp)
0x802AA980: sw t1,60($sp)
0x802AA984: sw t2,48($sp)
0x802AA988: sw t3,44($sp)
0x802AA98C: sw t4,40($sp)
0x802AA990: sw t5,36($sp)
0x802AA994: sw t6,32($sp)
0x802AA998: beq v1,$at,0x802AA9AC
0x802AA99C: sw t7,28($sp)
0x802AA9A0: li $at,9
0x802AA9A4: bne v1,$at,0x802AA9BC
0x802AA9A8: lui t9,0x8028
0x802AA9AC: lui t8,0x8028
0x802AA9B0: lui $at,0x8016
0x802AA9B4: b 0x802AA9C8
0x802AA9B8: sw t8,-2260($at)
0x802AA9BC: ori t9,t9,0xdf00
0x802AA9C0: lui $at,0x8016
0x802AA9C4: sw t9,-2260($at)
0x802AA9C8: jal 0x802A7D70
0x802AA9CC: or a0,a2,$zero
0x802AA9D0: li a0,9
0x802AA9D4: jal 0x802A7B94
0x802AA9D8: or a1,v0,$zero
0x802AA9DC: lui t0,0x800e
0x802AA9E0: lw t0,-15092(t0)
0x802AA9E4: li $at,5
0x802AA9E8: lw a0,72($sp)
0x802AA9EC: beq t0,$at,0x802AAA08
0x802AA9F0: nop
0x802AA9F4: jal 0x802AA88C /* Map is decompressed further down the line here */
0x802AA9F8: lw a1,68($sp)
0x802AA9FC: li a0,6
Stack trace hereto: (m64p) bt Stack trace for thread 5 (0x801589D0):
- 00 0x800400D0 SRC:0x802AA8E8 ARG:{0x802899C0,0x801CCF10,0x00000001,0x802BA360}
$sp:0x8015AA90 size: 48b
- 01 0x802AA88C SRC:0x802AA9F4 ARG:{0x0084E8E0,0x00852E20,0x00000001,0x802BA360}
$sp:0x8015AAC0 size: 96b
- 02 0x802AA918 SRC:0x80002AF4 ARG:{0x00000008,0x0002C470,0x00000001,0x802BA360}
$sp:0x8015AB20 size: 24b
- 03 0x80002A18 SRC:0x8000271C ARG:{0x8028DF00,0x0002C470,0x00000001,0x802BA360}
$sp:0x8015AB38 size: 24b
- 04 0x80002684 SRC:0x80002884 ARG:{0x00000001,0x00006D6E,0x00000000,0x00000000}
$sp:0x8015AB50 size: ?
For the record, I loaded the first track of the first series.
Storage
The map data array begins at 0x802B8D80. The records are 48 bytes each. The structure appears to follow this format:
struct mk64_map_data_t { unsigned rom_start; unsigned rom_end; ... };