pureikyubu/Docs/RE/CardUnlock.txt
ogamespec c21147ccff Cumulative changes all around project, regarding Stage 1
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
2015-09-04 19:45:10 +03:00

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