mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
Docs: New TODO moved to EMU, old renamed to old_todo Docs: Old coding style is deprecated (old_style.txt) Docs: Removed mention about CubeDocumented and fixed old emails RE: boot.s, proved first asm line (lis instruction parameter) RE: Added PAL and NTSC Boot and IPL IDA files RE: Some work on NTSC IPL (identified many lib calls, including OS, GX) RE: Added EXI Bootrom descrambler by segher RE: GXInit RE: Internal GX lib structures (GXPrivate.h) RE: More details on lomem (OS versions) RE: OSInit and OS.c RE: OSAlloc (heap allocator) RE: Very first code of Metrowerk runtime (__start.c) Docs: Added copy of http://gcdev.narod.ru Source\Utils: Command processor (Cmd.c) Source\Utils: File wrapper Source\Utils: Gekko disasm cleaned up and ported to plain C Source\Utils: Double-linked lists Source\Utils: Ported old Profiler code Source\Utils: String utils
359 lines
10 KiB
Text
359 lines
10 KiB
Text
|
|
Gamecube memory card unlock reverse engineering.
|
|
|
|
This reversing is not pretending to be compilable, and can be used for
|
|
education purposes only. I dont hold any responsibility for damage of your
|
|
Gamecube clock settings or memory card saves or else, produced from using
|
|
code/information represented in this document.
|
|
|
|
Version 0.1. (12 May 2005)
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
Overview.
|
|
|
|
Memory card unlock is really weirdo operation, because its using GC DSP.
|
|
It proves, that N still have crazy developers and its good.
|
|
|
|
This reversing representing card unlock operation from both CPU and DSP sides.
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
PART I: CPU Side. Unlock call.
|
|
|
|
s32 __CARDUnlock <-- CARD_RESULT
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
PART II: CPU Side. Helper calls.
|
|
|
|
These routines are replacement for stdc's srand and rand.
|
|
|
|
static u32 next = 1; // rand seed
|
|
|
|
u32 CARDRand(void)
|
|
{
|
|
next = next * 0x41C64E6D + 12345;
|
|
|
|
return (next >> 16) & 0x7fff; // RAND_MAX = 0x7fff
|
|
}
|
|
|
|
void CARDSrand(u32 seed)
|
|
{
|
|
next = seed;
|
|
}
|
|
|
|
---
|
|
|
|
u32 exnor_1st(u32 data, int rshift)
|
|
{
|
|
u32 work = data;
|
|
|
|
for(int i=0; i<rshift; i++)
|
|
{
|
|
u32 wk = ~((work >> 23) ^ (work >> 15) ^ (work >> 7) ^ work);
|
|
work = (work >> 1) | ((wk & 2) << 30);
|
|
}
|
|
|
|
return work;
|
|
}
|
|
|
|
|
|
u32 exnor(u32 data, int lshift)
|
|
{
|
|
u32 work = data;
|
|
|
|
for(int i=0; i<lshift; i++)
|
|
{
|
|
u32 wk = ~((work << 23) ^ (work << 15) ^ (work << 7) ^ work);
|
|
work = (work << 1) | ((work >> 30) & 2)
|
|
}
|
|
|
|
return work;
|
|
}
|
|
|
|
---
|
|
|
|
Reverse bit order, for example 0xBC2F1895 will be 0xA918F43D :
|
|
|
|
10111100001011110001100010010101 -> 10101001000110001111010000111101.
|
|
|
|
u32 bitrev(u32 data)
|
|
{
|
|
u32 wk = 0;
|
|
int j = 0, k = 1;
|
|
|
|
for(int i=0; i<32; i++)
|
|
{
|
|
if(i > 15)
|
|
{
|
|
if(i == 31)
|
|
{
|
|
wk |= (data >> 31);
|
|
}
|
|
else
|
|
{
|
|
wk |= (data & (1 << i)) >> k;
|
|
k += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wk |= (data & (1 << i)) << (31 - i - j);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
return wk;
|
|
}
|
|
|
|
---
|
|
|
|
s32 ReadArrayUnlock(s32 chan, u32 data, void *rbuf, s32 rlen, s32 mode)
|
|
{
|
|
CARDControl *card;
|
|
s32 err;
|
|
u8 cmd[5];
|
|
|
|
|
|
ASSERT(0 <= chan && chan < 2);
|
|
|
|
card = &__CARDBlock[chan];
|
|
|
|
if( EXISelect(chan, 0, __CARDFreq) == 0 ) return CARD_RESULT_NOCARD;
|
|
|
|
// Round down data to 4096 bytes (sector number)
|
|
data &= ~(4096 - 1);
|
|
|
|
// Commands for MX25L4004
|
|
// ReadArray 0x52 SA2 SA1 PN BA 0x00 0x00 0x00 0x00
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd[0] = 0x52;
|
|
|
|
if(mode == 0)
|
|
{
|
|
cmd[1] = (data >> 29) & 3;
|
|
cmd[2] = (data >> 21) & 0xff;
|
|
cmd[3] = (data >> 19) & 1;
|
|
cmd[4] = (data >> 12) & 0x7f;
|
|
}
|
|
else
|
|
{
|
|
cmd[1] = (u8)(data >> 24);
|
|
cmd[2] = (u8)(data >> 16);
|
|
}
|
|
|
|
|
|
// EXI error accumulate macro is used widely in libraries, but I think
|
|
// it doesnt have appropriate C-version (since cntlzw) and implemented as
|
|
// macro in SDK private exi.h header.
|
|
// First parameter is error flag and second is returned value of EXI call.
|
|
// In case you interested how its accumulating, here is asm version:
|
|
// cntlzw r0, result
|
|
// rlwinm r0,r0,27,5,31
|
|
// or error,error,r0
|
|
|
|
err = 0;
|
|
|
|
EXIAccumError(err, EXIImmEx(chan, cmd, sizeof(cmd), EXI_WRITE));
|
|
EXIAccumError(err, EXIImmEx(chan, card->workArea, rlen, EXI_WRITE));
|
|
EXIAccumError(err, EXIImmEx(chan, rbuf, rlen, EXI_READ));
|
|
EXIAccumError(err, EXIDeselect(chan));
|
|
|
|
return (err) ? CARD_RESULT_NOCARD : CARD_RESULT_READY;
|
|
}
|
|
|
|
---
|
|
|
|
u32 GetInitVal(void)
|
|
{
|
|
OSTick tick = OSGetTick();
|
|
CARDSrand(tick);
|
|
return (CARDRand() | 0x7FEC0000) & ~(4096 - 1);
|
|
}
|
|
|
|
---
|
|
|
|
00000330 <DummyLen>:
|
|
330: 7c 08 02 a6 mflr r0
|
|
334: 90 01 00 04 stw r0,4(r1)
|
|
338: 94 21 ff e8 stwu r1,-24(r1)
|
|
33c: bf 81 00 08 stmw r28,8(r1)
|
|
340: 3b c0 00 01 li r30,1
|
|
344: 3b 80 00 00 li r28,0
|
|
348: 48 00 00 01 bl 348 <DummyLen+0x18>
|
|
348: R_PPC_REL24 OSGetTick
|
|
34c: 7c 7d 1b 78 mr r29,r3
|
|
350: 7f a3 eb 78 mr r3,r29
|
|
354: 48 00 00 01 bl 354 <DummyLen+0x24>
|
|
354: R_PPC_REL24 CARDSrand
|
|
358: 48 00 00 01 bl 358 <DummyLen+0x28>
|
|
358: R_PPC_REL24 CARDRand
|
|
35c: 7c 7f 1b 78 mr r31,r3
|
|
360: 57 ff 06 fe clrlwi r31,r31,27
|
|
364: 3b ff 00 01 addi r31,r31,1
|
|
368: 48 00 00 3c b 3a4 <DummyLen+0x74>
|
|
36c: 48 00 00 01 bl 36c <DummyLen+0x3c>
|
|
36c: R_PPC_REL24 OSGetTick
|
|
370: 7c 7d 1b 78 mr r29,r3
|
|
374: 7f bf f0 30 slw r31,r29,r30
|
|
378: 3b de 00 01 addi r30,r30,1
|
|
37c: 28 1e 00 10 cmplwi r30,16
|
|
380: 40 81 00 08 ble 388 <DummyLen+0x58>
|
|
384: 3b c0 00 01 li r30,1
|
|
388: 7f e3 fb 78 mr r3,r31
|
|
38c: 48 00 00 01 bl 38c <DummyLen+0x5c>
|
|
38c: R_PPC_REL24 CARDSrand
|
|
390: 48 00 00 01 bl 390 <DummyLen+0x60>
|
|
390: R_PPC_REL24 CARDRand
|
|
394: 7c 7f 1b 78 mr r31,r3
|
|
398: 57 ff 06 fe clrlwi r31,r31,27
|
|
39c: 3b ff 00 01 addi r31,r31,1
|
|
3a0: 3b 9c 00 01 addi r28,r28,1
|
|
3a4: 2c 1f 00 04 cmpwi r31,4
|
|
3a8: 40 80 00 0c bge 3b4 <DummyLen+0x84>
|
|
3ac: 28 1c 00 0a cmplwi r28,10
|
|
3b0: 41 80 ff bc blt 36c <DummyLen+0x3c>
|
|
3b4: 2c 1f 00 04 cmpwi r31,4
|
|
3b8: 40 80 00 08 bge 3c0 <DummyLen+0x90>
|
|
3bc: 3b e0 00 04 li r31,4
|
|
3c0: 7f e3 fb 78 mr r3,r31
|
|
3c4: 80 01 00 1c lwz r0,28(r1)
|
|
3c8: bb 81 00 08 lmw r28,8(r1)
|
|
3cc: 38 21 00 18 addi r1,r1,24
|
|
3d0: 7c 08 03 a6 mtlr r0
|
|
3d4: 4e 80 00 20 blr
|
|
|
|
|
|
--------------------------------------------------------------------------
|
|
|
|
PART III: DSP Side.
|
|
|
|
Disassembly obtained from duddie's GDTOOL.
|
|
|
|
0000 0000 NOP
|
|
0001 0000 NOP
|
|
0002 0000 NOP
|
|
0003 0000 NOP
|
|
0004 0000 NOP
|
|
0005 0000 NOP
|
|
0006 0000 NOP
|
|
0007 0000 NOP
|
|
0008 0000 NOP
|
|
0009 0000 NOP
|
|
000a 0000 NOP
|
|
000b 0000 NOP
|
|
000c 0000 NOP
|
|
000d 0021 HALT
|
|
000e 02ff RTI
|
|
000f 0021 HALT
|
|
0010 1306 SBSET #0x06
|
|
0011 1203 SBCLR #0x03
|
|
0012 1204 SBCLR #0x04
|
|
0013 1305 SBSET #0x05
|
|
0014 0092 00ff LRI $18, #0x00ff
|
|
0016 0088 ffff LRI $8, #0xffff
|
|
0018 0089 ffff LRI $9, #0xffff
|
|
001a 008a ffff LRI $10, #0xffff
|
|
001c 008b ffff LRI $11, #0xffff
|
|
001e 8f00 S16
|
|
001f 02bf 0088 CALL 0x0088
|
|
0021 16fc dcd1 SI @0xfffc, #0xdcd1
|
|
0023 16fd 0000 SI @0xfffd, #0x0000
|
|
0025 16fb 0001 SI @0xfffb, #0x0001
|
|
0027 02bf 008e CALL 0x008e
|
|
0029 25ff LRS $29, @0xffff
|
|
002a 0380 ff00 CMPI $31, #0xff00
|
|
002c 0294 0027 JNE 0x0027
|
|
002e 02bf 008e CALL 0x008e
|
|
0030 1fdf MRR $30, $31
|
|
0031 24ff LRS $28, @0xffff
|
|
0032 0240 0fff ANDI $30, #0x0fff
|
|
0034 0098 0400 LRI $24, #0x0400
|
|
0036 009a 0010 LRI $26, #0x0010
|
|
0038 0099 0000 LRI $25, #0x0000
|
|
003a 8e00 S40
|
|
003b 02bf 0094 CALL 0x0094
|
|
003d 02bf 8644 CALL 0x8644
|
|
003f 02bf 0088 CALL 0x0088
|
|
0041 16fc dcd1 SI @0xfffc, #0xdcd1
|
|
0043 16fd 0003 SI @0xfffd, #0x0003
|
|
0045 16fb 0001 SI @0xfffb, #0x0001
|
|
0047 8f00 S16
|
|
0048 02bf 008e CALL 0x008e
|
|
004a 0380 cdd1 CMPI $31, #0xcdd1
|
|
004c 0294 0048 JNE 0x0048
|
|
004e 27ff LRS $31, @0xffff
|
|
004f 0380 0001 CMPI $31, #0x0001
|
|
0051 0295 005a JEQ 0x005a
|
|
0053 0380 0002 CMPI $31, #0x0002
|
|
0055 0295 8000 JEQ 0x8000
|
|
0057 029f 0048 JMP 0x0048
|
|
0059 0021 HALT
|
|
005a 8e00 S40
|
|
005b 02bf 008e CALL 0x008e
|
|
005d 25ff LRS $29, @0xffff
|
|
005e 02bf 008e CALL 0x008e
|
|
0060 25ff LRS $29, @0xffff
|
|
0061 02bf 008e CALL 0x008e
|
|
0063 25ff LRS $29, @0xffff
|
|
0064 02bf 008e CALL 0x008e
|
|
0066 00c5 ffff LR $5, @0xffff
|
|
0068 0340 0fff ANDI $31, #0x0fff
|
|
006a 1c9f MRR $4, $31
|
|
006b 02bf 008e CALL 0x008e
|
|
006d 00c7 ffff LR $7, @0xffff
|
|
006f 02bf 008e CALL 0x008e
|
|
0071 00c6 ffff LR $6, @0xffff
|
|
0073 02bf 008e CALL 0x008e
|
|
0075 00c0 ffff LR $0, @0xffff
|
|
0077 02bf 008e CALL 0x008e
|
|
0079 20ff LRS $24, @0xffff
|
|
007a 0340 0fff ANDI $31, #0x0fff
|
|
007c 1f5f MRR $26, $31
|
|
007d 02bf 008e CALL 0x008e
|
|
007f 21ff LRS $25, @0xffff
|
|
0080 02bf 008e CALL 0x008e
|
|
0082 23ff LRS $27, @0xffff
|
|
0083 1205 SBCLR #0x05
|
|
0084 1206 SBCLR #0x06
|
|
0085 029f 80b5 JMP 0x80b5
|
|
0087 0021 HALT
|
|
|
|
0088 27fc LRS $31, @0xfffc
|
|
0089 03c0 8000 ANDF $31, #0x8000
|
|
008b 029d 0088 JNZ 0x0088
|
|
008d 02df RET
|
|
|
|
008e 27fe LRS $31, @0xfffe
|
|
008f 03c0 8000 ANDF $31, #0x8000
|
|
0091 029c 008e JZR 0x008e
|
|
0093 02df RET
|
|
|
|
0094 2ece SRS @0xffce, $30
|
|
0095 2ccf SRS @0xffcf, $28
|
|
0096 00f8 ffcd SR @0xffcd, $24
|
|
0098 00f9 ffc9 SR @0xffc9, $25
|
|
009a 00fa ffcb SR @0xffcb, $26
|
|
009c 26c9 LRS $30, @0xffc9
|
|
009d 02c0 0004 ANDF $30, #0x0004
|
|
009f 029d 009c JNZ 0x009c
|
|
00a1 02df RET
|
|
00a2 0000 NOP
|
|
00a3 0000 NOP
|
|
00a4 0000 NOP
|
|
00a5 0000 NOP
|
|
00a6 0000 NOP
|
|
00a7 0000 NOP
|
|
00a8 0000 NOP
|
|
00a9 0000 NOP
|
|
00aa 0000 NOP
|
|
00ab 0000 NOP
|
|
00ac 0000 NOP
|
|
00ad 0000 NOP
|
|
00ae 0000 NOP
|
|
00af 0000 NOP
|