From 3b8608fee2eee6d8466d95174c47a3ce3ec81a1d Mon Sep 17 00:00:00 2001 From: archshift Date: Sun, 10 May 2015 12:51:46 -0700 Subject: [PATCH] Split out NTR and CTR commands into their own files --- source/gamecart/command_ctr.c | 44 +++++++++++++++++++++++ source/gamecart/command_ctr.h | 9 +++++ source/gamecart/command_ntr.c | 24 +++++++++++++ source/gamecart/command_ntr.h | 7 ++++ source/gamecart/protocol.c | 67 ++++++----------------------------- source/gamecart/protocol.h | 3 -- source/main.c | 7 ++-- 7 files changed, 98 insertions(+), 63 deletions(-) create mode 100644 source/gamecart/command_ctr.c create mode 100644 source/gamecart/command_ctr.h create mode 100644 source/gamecart/command_ntr.c create mode 100644 source/gamecart/command_ntr.h diff --git a/source/gamecart/command_ctr.c b/source/gamecart/command_ctr.c new file mode 100644 index 0000000..a1f1c38 --- /dev/null +++ b/source/gamecart/command_ctr.c @@ -0,0 +1,44 @@ +#include "command_ctr.h" + +#include "protocol_ctr.h" + +void CTR_CmdReadSectorSD(u8* aBuffer, u32 aSector) +{ + u64 adr = ((u64)0xBF << 56) | (aSector * 0x200); + const u32 readheader_cmd[4] = { + (u32)(adr >> 32), + (u32)(adr & 0xFFFFFFFF), + 0x00000000, 0x00000000 + }; + CTR_SendCommand(readheader_cmd, 0x200, 1, 0x100802C, aBuffer); +} + +void CTR_CmdReadData(u32 sector, u32 length, u32 blocks, void* buffer) +{ + const u32 read_cmd[4] = { + (0xBF000000 | (u32)(sector >> 23)), + (u32)((sector << 9) & 0xFFFFFFFF), + 0x00000000, 0x00000000 + }; + CTR_SendCommand(read_cmd, length, blocks, 0x100822C, buffer); +} + +void CTR_CmdReadHeader(void* buffer) +{ + static const u32 readheader_cmd[4] = { 0x82000000, 0x00000000, 0x00000000, 0x00000000 }; + CTR_SendCommand(readheader_cmd, 0x200, 1, 0x4802C, buffer); +} + +u32 CTR_CmdGetSecureId(u32 rand1, u32 rand2) +{ + u32 id = 0; + const u32 getid_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(getid_cmd, 0x4, 1, 0x100802C, &id); + return id; +} + +void CTR_CmdSeed(u32 rand1, u32 rand2) +{ + const u32 seed_cmd[4] = { 0x83000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(seed_cmd, 0, 1, 0x100822C, NULL); +} diff --git a/source/gamecart/command_ctr.h b/source/gamecart/command_ctr.h new file mode 100644 index 0000000..9079db5 --- /dev/null +++ b/source/gamecart/command_ctr.h @@ -0,0 +1,9 @@ +#pragma once + +#include "common.h" + +void CTR_CmdReadSectorSD(u8* aBuffer, u32 aSector); +void CTR_CmdReadData(u32 sector, u32 length, u32 blocks, void* buffer); +void CTR_CmdReadHeader(void* buffer); +u32 CTR_CmdGetSecureId(u32 rand1, u32 rand2); +void CTR_CmdSeed(u32 rand1, u32 rand2); diff --git a/source/gamecart/command_ntr.c b/source/gamecart/command_ntr.c new file mode 100644 index 0000000..2f7b363 --- /dev/null +++ b/source/gamecart/command_ntr.c @@ -0,0 +1,24 @@ +#include "command_ntr.h" + +#include "protocol_ntr.h" +#include "misc.h" + +void NTR_CmdReset() +{ + const static u32 reset_cmd[2] = { 0x9F000000, 0x00000000 }; + NTR_SendCommand(reset_cmd, 0x2000, NTRCARD_CLK_SLOW | NTRCARD_DELAY1(0x1FFF) | NTRCARD_DELAY2(0x18), NULL); +} + +int NTR_CmdGetCartId() +{ + int id; + const static u32 getid_cmd[2] = { 0x90000000, 0x00000000 }; + NTR_SendCommand(getid_cmd, 0x4, NTRCARD_CLK_SLOW | NTRCARD_DELAY1(0x1FFF) | NTRCARD_DELAY2(0x18), &id); + return id; +} + +void NTR_CmdEnter16ByteMode() +{ + const static u32 enter16bytemode_cmd[2] = { 0x3E000000, 0x00000000 }; + NTR_SendCommand(enter16bytemode_cmd, 0x0, 0, NULL); +} diff --git a/source/gamecart/command_ntr.h b/source/gamecart/command_ntr.h new file mode 100644 index 0000000..3363bd2 --- /dev/null +++ b/source/gamecart/command_ntr.h @@ -0,0 +1,7 @@ +#pragma once + +#include "common.h" + +void NTR_CmdReset(); +int NTR_CmdGetCartId(); +void NTR_CmdEnter16ByteMode(); diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index 6a6bb6b..be225bf 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -7,6 +7,8 @@ #include "misc.h" #include "protocol_ctr.h" #include "protocol_ntr.h" +#include "command_ctr.h" +#include "command_ntr.h" #include "delay.h" extern u8* bottomScreen; @@ -59,31 +61,12 @@ void SwitchToNTRCARD() void SwitchToCTRCARD() { REG_CTRCARDCNT = 0x10000000; - REG_CARDCONF = (REG_CARDCONF&~3) | 2; -} - -u32 Cart_GetSecureID() -{ - u32 id = 0; - const u32 getid_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(getid_cmd, 0x4, 1, 0x100802C, &id); - return id; + REG_CARDCONF = (REG_CARDCONF & ~3) | 2; } int Cart_IsInserted() { - return (0x9000E2C2 == Cart_GetSecureID() ); -} - -void Cart_ReadSectorSD(u8* aBuffer, u32 aSector) -{ - u64 adr = ((u64)0xBF << 56) | (aSector * 0x200); - const u32 readheader_cmd[4] = { - (u32)(adr >> 32), - (u32)(adr & 0xFFFFFFFF), - 0x00000000, 0x00000000 - }; - CTR_SendCommand( readheader_cmd, 0x200, 1, 0x100802C, aBuffer ); + return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) ); } u32 Cart_GetID() @@ -102,7 +85,7 @@ void Cart_Init() ioDelay(0xF000); REG_NTRCARDROMCNT = 0; - REG_NTRCARDMCNT = REG_NTRCARDMCNT&0xFF; + REG_NTRCARDMCNT &= 0xFF; ioDelay(167550); REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ); @@ -110,20 +93,15 @@ void Cart_Init() while (REG_NTRCARDROMCNT & NTRCARD_BUSY); // Reset - u32 reset_cmd[2] = { 0x9F000000, 0x00000000 }; - NTR_SendCommand(reset_cmd, 0x2000, NTRCARD_CLK_SLOW | NTRCARD_DELAY1(0x1FFF) | NTRCARD_DELAY2(0x18), NULL); - - u32 getid_cmd[2] = { 0x90000000, 0x00000000 }; - NTR_SendCommand(getid_cmd, 0x4, NTRCARD_CLK_SLOW | NTRCARD_DELAY1(0x1FFF) | NTRCARD_DELAY2(0x18), &CartID); + NTR_CmdReset(); + CartID = NTR_CmdGetCartId(); // 3ds if (CartID & 0x10000000) { u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 }; NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response); - u32 enter16bytemode_cmd[2] = { 0x3E000000, 0x00000000 }; - NTR_SendCommand(enter16bytemode_cmd, 0x0, 0, NULL); - + NTR_CmdEnter16ByteMode(); SwitchToCTRCARD(); ioDelay(0xF000); @@ -131,22 +109,6 @@ void Cart_Init() } } -void SendReadCommand( u32 sector, u32 length, u32 blocks, void * buffer ) -{ - const u32 read_cmd[4] = { - (0xBF000000 | (u32)(sector >> 23)), - (u32)((sector << 9) & 0xFFFFFFFF), - 0x00000000, 0x00000000 - }; - CTR_SendCommand(read_cmd, length, blocks, 0x100822C, buffer); -} - -void GetHeader(void * buffer) -{ - static const u32 readheader_cmd[4] = { 0x82000000, 0x00000000, 0x00000000, 0x00000000 }; - CTR_SendCommand(readheader_cmd, 0x200, 1, 0x4802C, buffer); -} - //returns 1 if MAC valid otherwise 0 u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored u8 tmp = REG_AESKEYCNT; @@ -186,7 +148,7 @@ void AES_SetKeyControl(u32 a) { *((volatile u8*)0x10009011) = a | 0x80; } -void Cart_Secure_Init(u32 *buf,u32 *out) +void Cart_Secure_Init(u32 *buf, u32 *out) { AES_SetKeyControl(0x3B); @@ -203,32 +165,23 @@ void Cart_Secure_Init(u32 *buf,u32 *out) rand1 = 0x42434445;//*((vu32*)0x10011000); rand2 = 0x46474849;//*((vu32*)0x10011010); - const u32 seed_cmd[4] = { 0x83000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(seed_cmd, 0, 1, 0x100822C, NULL); + CTR_CmdSeed(rand1, rand2); out[3] = BSWAP32(rand2); out[2] = BSWAP32(rand1); CTR_SetSecSeed(out, false); - //ClearScreen(bottomScreen, RGB(255, 0, 255)); - u32 test = 0; const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); - //ClearScreen(bottomScreen, RGB(0, 255, 0)); - u32 test2 = 0; const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; CTR_SendCommand(A3_cmd, 4, 1, 0x100822C, &test2); - //ClearScreen(bottomScreen, RGB(255, 0, 0)); - const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; CTR_SendCommand(C5_cmd, 0, 1, 0x100822C, NULL); - //ClearScreen(bottomScreen, RGB(0, 0, 255)); - CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); diff --git a/source/gamecart/protocol.h b/source/gamecart/protocol.h index 53e7876..5ed7df1 100644 --- a/source/gamecart/protocol.h +++ b/source/gamecart/protocol.h @@ -5,8 +5,5 @@ u32 BSWAP32(u32 val); void Cart_Init(); int Cart_IsInserted(); -void Cart_ReadSectorSD(u8* aBuffer, u32 aSector); -u32 SendReadCommand(u32 adr, u32 length, u32 blocks, void* buffer); -u32 GetHeader(void* buffer); u32 Cart_GetID(); void Cart_Secure_Init(u32* buf, u32* out); diff --git a/source/main.c b/source/main.c index 6dbeff0..5f0e20a 100644 --- a/source/main.c +++ b/source/main.c @@ -7,6 +7,7 @@ #include "hid.h" #include "fatfs/ff.h" #include "gamecart/protocol.h" +#include "gamecart/command_ctr.h" extern s32 CartID; extern s32 CartID2; @@ -76,7 +77,7 @@ int main() { while((*((vu16*)0x10146000) & 1)); // Wait for button A Debug("Done waiting :)...", 1, 1, 0xFF); - GetHeader(header); + CTR_CmdReadHeader(header); Debug("Done reading header: %08x :)...", *(u32*)&header[0x100]); // TODO: Check first header bytes for "NCSD" or other magic words which should be there for valid NCCHs @@ -90,7 +91,7 @@ int main() { u32 blocks = dumpSize / mediaUnit; //1MB of blocks // Read out the header 0x0000-0x1000 - SendReadCommand( 0, mediaUnit, 8, (void*)(target) ); + CTR_CmdReadData(0, mediaUnit, 8, (void*)(target)); // Create output file - TODO: Put actual information in the file name (game id/name/..?), to have a standardized naming scheme memcpy(String2, "/dump.3ds\0", 10); @@ -135,7 +136,7 @@ int main() { if ((adr2 % (blocks*3)) == blocks*2) Debug("Dumping %08X / %08X - %03d%%",currentSector,cartSize,percent); - SendReadCommand(currentSector, mediaUnit, blocks, (void*)(target + (adr2 * mediaUnit))); + CTR_CmdReadData(currentSector, mediaUnit, blocks, (void*)(target + (adr2 * mediaUnit))); } f_write(&file, target, dumped * mediaUnit, &bytes_written); f_sync(&file);