// MIDAS // /////////// // // Project Goal: 100% complete re-creation, in C or C++, of Goldeneye // for the Nintendo 64. // Realistic Goal: Determine based on manual traces what is preventing // Goldeneye from booting in MESS. // Additional Goal: Determine any as-yet unknown debugging modes. // // http://moogle-tech.com/blog/ 80000400: // Boot uint32_t *addr = (uint32_t*)0x8005D2E0; // t0 for(index = 0x00031080; index >= 0; index -= 8) // t1 { *(addr++) = 0; *(addr++) = 0; } 80000424: t2 = 0x80000450 SP = 0x803ab410 Branch to t2 80000450: v0 = 0x00000001 v1 = 0x00000000 a0 = 0x00000000 a1 = 0x70000000 a2 = 0x0000001f a3 = 0x00000001 t0 = 0x007f0000 t0 = 0x007fe000 (t0 |= 0xe000) COP0(Index) = v0 (1) // Programmable pointer into TLB array v1 >>= 12; v1 <<= 6; v1 += a2 (= 0x0000001f) COP0(EntryLo0) = v1 // Low half of TLB entry for even virtual addr a0 >>= 12 a0 <<= 6; a0 += a3 (= 0x00000001) COP0(EntryLo1) = a0 // Low half of entry for odd virtual addr a0 = a1 >> 13; a0 <<= 13; COP0(EntryHi) = a0 // High half of TLB entry COP0(PageMask) = t0 // TLB Page Mask TLB Write Indexed 800004B4: x7_80000510(); uint32_t return0x80020d90() // 0x7/800004BC { return 0x80020d90; // v0 } uint32_t return0x00021990() // 0x7/800004C8 { return 0x00021990; // v0 } uint32_t return0x00033590() // 0x7/800004D4 { return 0x00033590; // v0 } uint32_t return0x00033590() // 0x7/800004E0 { return 0x00033590; // v0 } uint32_t return0x00034b30() // 0x7/800004EC { return 0x00034b30; // v0 } void? call0x7020141c() // 0x7/800004F8 { a3 = 0x7020141c; x7020141c(); } ? x7_80000510() { sp -= 0x40 sp[0x24] = ra; sp[0x20] = s1; sp[0x1C] = s0; s0 = return0x80020d90(); v0 = return0x00021990(); sp[0x34] = v0; t6 = sp[0x34]; v0 = return0x00033590(); s1 = v0 - t6; // s1 = 0x00033590 - 0x00021990 = 0x00011C00 v0 = return0x00033590(); sp[0x28] = v0; v0 = return 0x00034b30(); t7 = sp[0x28]; t2 = 0x70200000; a1 = s0 t8 = v0 - t7 // t8 = 0x00034b30 - 0x00033590 = 0x000015a0 a0 = s1 + t8 // a0 = 0x00011c00 + 0x000015a0 = 0x000131a0 v1 = a0 - 1 // 0x0001319f a2 = 0x80300000 if(v1 < z) goto 0x7/8000058c t9 = 0x70200000 a0 = t9 - s1 // 0x70200000 - 0x00011c00 = 701ee400 v0 = s0 + v1 // 80020d90 + 0x0001319f = 80033f2f do { t0 = Byte[v0] t1 = a0 + v1 // 7020159f v1--; // 0x0001319e v0--; // 0x80033f2e Byte[t1] = t0; }while(v1 >= 0); a0 = t2 - s1 // 0x70200000 - 0x00011c00 = 701ee400 call x7_800004f8(); structs: uint32* word0 = 0x701EE400; // 70201480 // Some sort of buffer or something uint32* word1 = 0x80020D90; // 70201484 uint32 word2 = 0x00000000; // 70201488 uint32 word3 = 0x00000000; // 7020148C uint32* word4 = 0x80300000; // 70201490 uint8 array0[0x14] // 70201494 - 702014A7, incl. uint32 word5 = 0x00000000; // 70201564 uint32 word6 = 0x00000000; // 70201568 uint32 word7 = 0x00000000; // 70201598 UnknownStruct: uint32 word0; // Created on the stack at sp + 0x5ac at 0x70200000 uint32 word1; uint32 word2; uint32 word3; ? x7_80200000() { sp -= 0x5f0; s2 = a0; sp[0x08] = s0; sp[0x0c] = s1; sp[0x10] = s2; sp[0x14] = s3; sp[0x18] = s4; sp[0x1c] = s5; sp[0x20] = s6; sp[0x24] = s7; sp[0x28] = fp; sp[0x2c] = ra; sp[0x5f8] = a2; sp[0x5fc] = a3; sp[0x5a8] = 0; // On first run, a1 = 0x13; // On first run, s2 = 0x803AAE40; UnknownStruct* v1 = (UnknownStruct*)(sp + 0x5ac); for(int index = 0; index < 4; index++) { v1->word0 = v1->word1 = v1->word2 = v1->word3 = 0; v1++; } ra = s2; if(a1 & 3) { for(int s0 = a1; s0 != (a1 - (a1 & 3)); s0--) { sp[0x5a8 + (Word[ra] << 2)]++; ra += 4; } } s0 = a1; while(s0 != 0) { s0 -= 4; ra += 0x10; sp[0x5a8 + (Word[ra] << 2)]++; sp[0x5a8 + (Word[ra - 0x0c] << 2)]++; sp[0x5a8 + (Word[ra - 0x08] << 2)]++; sp[0x5a8 + (Word[ra - 0x04] << 2)]++; } t6 = sp[0x5a8]; // On first run, t6 = 0x06. This is because of the layout of // data at 0x803AAE40: // 7 0 0 7 // 5 5 5 4 // 3 2 2 3 // 5 6 0 0 // 5 0 0 a2 = sp[0x608]; // On first run, a2 = 0x803ab348. a3 = 1; if(a1 == t6) { v0 = 0; Word[sp[0x604]] = 0; Word[so[0x608]] = 0; BranchTo0x70200624(); } s1 = sp[0x608]; t0 = 0x5ac; while(sp[t0] == 0) { t0 += 4; a3++; if(a3 == 0x11) { break; } } s5 = a3; if(s1 < a3) { s1 = a3; } s0 = 0x10; v0 = 0x5e8; while(sp[v0] == 0) { v0 += 4; s0--; if(s0 == 0) { break; } } sp[0x5a0] = s0; if(s0 < s1) { s1 = s0; } Word[a2] = s1; v1 = 1 << a3; if(a3 < s0) { do { t0 += 4; v1 -= sp[t0]; v1 <<= 1; } while(t0 < (0x5a8 + (s0 << 2))); // First run: v1 = 2 } s0--; a3 = 0; Word[v0] = Word[v0] + (v1 - Word[v0]); // First run: t6 = 2; sp[0x78] = 0; ra = 0x5ac; a2 = 0x7c; sp[0x5f4] = a1; v0 -= 4; if(s0 != 0) { t0 = s0 & 3; t0 = 0 - t0; sp[0x5f4] = a1; if(t0 != 0) { a1 = sp + 0x5a8 + ((s0 - (s0 & 3)) << 2); do { a3 += sp[ra]; v0 -= 4; a2 += 4; ra += 4; } while(a1 != v0); t6 = sp + 0x5a8; a1 = sp + 0x5a8; if(v0 != t6) { do { sp[a2 + 0x00] += sp[ra+0x00]; sp[a2 + 0x04] = sp[a2 + 0x00] + sp[ra+0x04]; sp[a2 + 0x08] = sp[a2 - 0x04] + sp[ra+0x08]; sp[a2 + 0x0c] = sp[a2 - 0x08] + sp[ra+0x0c] v0 -= 0x10; a2 += 0x10; ra += 0x10; } while(v0 != a1); } } if(t0 == 0 || (t0 != 0 && v0 != t6)) { a1 = sp + 0x5a8; do { sp[a2 + 0x00] += sp[ra+0x00]; sp[a2 + 0x04] = sp[a2 + 0x00] + sp[ra+0x04]; sp[a2 + 0x08] = sp[a2 - 0x04] + sp[ra+0x08]; sp[a2 + 0x0c] = sp[a2 - 0x08] + sp[ra+0x0c] v0 -= 0x10; a2 += 0x10; ra += 0x10; } while(v0 != a1); } } t3 = sp[0x5f4]; ra = s2; s0 = 0; t1 = sp + 0xbc; a2 = sp + 0x74; } ? x7_80200d04() { // Word[0x70201480] -> v1 (addr) -> v1 (val) -> uint8* buf // Word[0x70201488] -> t2 (addr) -> v0 (val) -> unpackIndex // Byte[0x70201494] -> gNumWords // Word[0x70201564] -> t1 (addr) -> t1 (val) -> unpackWord // Word[0x70201568] -> t0 (addr) -> t0 (val) -> unpackShift sp -= 0x568; sp[0x28] = s0; sp[0x2c] = ra; while(unpackShift < 5) { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } unpackShift -= 5; sp[0x53c] = 0x101 + (unpackWord & 0x1f); unpackWord >>= 5; while(unpackShift < 5) { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } unpackShift -= 5; sp[0x538] = (unpackWord & 0x1f) + 1; unpackWord >>= 5; while(unpackShift < 4) { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } unpackShift -= 4; unpackWord >>= 4; int unknown0 = (unpackedWord & 0x0f) + 4; a0 = 0; if(unknown0 != 0) { int chunkIndex = 0; do { a0++; while(unpackShift < 3) { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } unpackShift -= 3; sp[0x40 + (array0[chunkIndex++] << 2)] = unpackWord & 7; unpackWord >>= 3; }while(unknown0 != a0); } if(a0 < 0x17) { int chunkIndex = a0; while(chunkIndex < 0x13) { sp[0x40 + array0[chunkIndex++] << 2)] = 0; } sp[0x10] = 0; sp[0x14] = sp + 0x550; sp[0x18] = sp + 0x548; sp[0x530] = unpackWord; sp[0x534] = unpackShift; sp[0x548] = 7; a0 = sp + 0x40; a1 = 0x13; a2 = 0x13; a3 = 0x00; x7_80200000(); } } ? x7_80201228() { // Word[0x70201480] -> a2 -> uint8* buf // Word[0x70201488] -> v0 -> unpackIndex // Word[0x70201564] -> t0 (addr) -> a1 (val) -> unpackWord // Word[0x70201568] -> t1 (addr) -> v1 (val) -> unpackShift // Word[0x803AB3B4] -> a3 -> ??? sp -= 0x18; sp[0x14] = ra; if(unpackShift == 0) { do { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } while(v1 == 0); } unpackShift--; Word[0x803AB3B4] = unpackWord & 1; unpackWord >>= 1; if(unpackShift < 2) { do { unpackWord |= buf[unpackIndex++] << unpackShift; unpackShift += 8; } while(unpackShift < 2); } int cmd = unpackWord & 3; unpackShift -= 2; unpackWord = unpackWord >> 2; switch(cmd) { case 0: x7_80200a48(); break; case 1: x7_80200b9c(); break; case 2: x7_80200d04(); break; } } ? x7_80201348() { SP -= 0x38; SP[0x14] = s0; SP[0x18] = s1; SP[0x1c] = s2; SP[0x20] = s3; SP[0x24] = RA; Word[0x7020148c] = 0; Word[0x70201564] = 0; Word[0x70201568] = 0; s0 = 0x70201598; s1 = 0; s2 = 0x70201568; s3 = SP + 0x34; Word[0x70201598] = 0; a0 = s3; x7_80201228(); } ? x7_8020141c() { v0 = 0x70201480; Word[v0] = a0; at = 0x70200000; Word[at+0x1484] = a1; at = 0x70200000; Word[at+0x1490] = a2; t6 = Word[v0]; at = 0x70200000; SP -= 0x18; t7 = t6 + 2; // 0x701EE402 Word[v0] = t7; Word[at+0x148c] = 0; SP[0x14] = RA; at = 0x70200000; Word[at+0x1488] = 0; Call 70201348; }