Notes:Mario Kart 64

A deposit of the now defunct 64.vg/w/.

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): $sp:0x8015AA90 size: 48b $sp:0x8015AAC0 size: 96b $sp:0x8015AB20 size: 24b $sp:0x8015AB38 size: 24b $sp:0x8015AB50 size: ?
 * 1) 00 0x800400D0 SRC:0x802AA8E8 ARG:{0x802899C0,0x801CCF10,0x00000001,0x802BA360}
 * 1) 01 0x802AA88C SRC:0x802AA9F4 ARG:{0x0084E8E0,0x00852E20,0x00000001,0x802BA360}
 * 1) 02 0x802AA918 SRC:0x80002AF4 ARG:{0x00000008,0x0002C470,0x00000001,0x802BA360}
 * 1) 03 0x80002A18 SRC:0x8000271C ARG:{0x8028DF00,0x0002C470,0x00000001,0x802BA360}
 * 1) 04 0x80002684 SRC:0x80002884 ARG:{0x00000001,0x00006D6E,0x00000000,0x00000000}

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; ... };