diff --git a/source/gamecart/command_ntr.c b/source/gamecart/command_ntr.c index db2dff6..21a7270 100644 --- a/source/gamecart/command_ntr.c +++ b/source/gamecart/command_ntr.c @@ -16,7 +16,7 @@ u32 ReadDataFlags = 0; void NTR_CmdReset(void) { cardReset (); - ioDelay(0xF000); + ioDelay2(0xF000); } u32 NTR_CmdGetCartId(void) @@ -34,7 +34,7 @@ void NTR_CmdReadHeader (u8* buffer) { REG_NTRCARDROMCNT=0; REG_NTRCARDMCNT=0; - ioDelay(167550); + ioDelay2(167550); REG_NTRCARDMCNT=NTRCARD_CR1_ENABLE|NTRCARD_CR1_IRQ; REG_NTRCARDROMCNT=NTRCARD_nRESET|NTRCARD_SEC_SEED; while(REG_NTRCARDROMCNT&NTRCARD_BUSY) ; diff --git a/source/gamecart/delay.h b/source/gamecart/delay.h index afad438..98c4b8a 100644 --- a/source/gamecart/delay.h +++ b/source/gamecart/delay.h @@ -7,3 +7,4 @@ #include "common.h" void ioDelay(u32 us); +void ioDelay2(u32 us); diff --git a/source/gamecart/iodelay.s b/source/gamecart/iodelay.s index b3baccd..aa37b8c 100644 --- a/source/gamecart/iodelay.s +++ b/source/gamecart/iodelay.s @@ -15,3 +15,13 @@ ioDelay: subs r0, #1 bgt 1b bx lr + +.global ioDelay2 +.type ioDelay2 STT_FUNC + +@ioDelay2 ( u32 us ) +ioDelay2: +1: + subs r0, #1 + bgt 1b + bx lr diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index c78b520..75a59c1 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -88,6 +88,17 @@ u32 Cart_GetID(void) return CartID; } +void Cart_Reset(void) +{ + ResetCartSlot(); //Seems to reset the cart slot? + + REG_CTRCARDSECCNT &= 0xFFFFFFFB; + ioDelay2(0x40000); + + SwitchToNTRCARD(); + ioDelay2(0x40000); +} + void Cart_Init(void) { ResetCartSlot(); //Seems to reset the cart slot? diff --git a/source/gamecart/protocol.h b/source/gamecart/protocol.h index 2a6c4a9..5bceccf 100644 --- a/source/gamecart/protocol.h +++ b/source/gamecart/protocol.h @@ -17,3 +17,4 @@ int Cart_IsInserted(void); u32 Cart_GetID(void); void Cart_Secure_Init(u32* buf, u32* out); void Cart_Dummy(void); +void Cart_Reset(void); diff --git a/source/gamecart/secure_ntr.c b/source/gamecart/secure_ntr.c index caf5183..82853ff 100644 --- a/source/gamecart/secure_ntr.c +++ b/source/gamecart/secure_ntr.c @@ -71,7 +71,7 @@ void NTR_CryptDown(u32* pCardHash, u32* aPtr) // chosen by fair dice roll. // guaranteed to be random. -#define getRandomNumber() (4) +#define getRandomNumber() (rand()) void NTR_InitKey1 (u8* aCmdData, IKEY1* pKey1, int iCardDevice) { @@ -179,12 +179,31 @@ void NTR_DecryptSecureArea (u32 aGameCode, u32* pCardHash, int nCardHash, u32* p for(int ii=0;ii<0x200;ii+=2) NTR_CryptDown (pCardHash, pSecureArea + ii); } +// Causes the timer to count at (33.514 / 1024) Mhz. +#define TIMER_DIV_1024 (3) +#define TIMER0_DATA (*(vu16*)0x10003000) +#define TIMER0_CR (*(vu16*)0x10003002) +#define TIMER_ENABLE (1<<7) +void NTR_SecureDelay(u16 aTimeout) +{ + /* Using a while loop to check the timeout, + so we have to wait until one before overflow. + This also requires an extra 1 for the timer data. + See GBATek for the normal formula used for card timeout. + */ + TIMER0_DATA=0x10000-(((aTimeout&0x3FFF)+3)); + //TIMER0_CR=TIMER_DIV_256|TIMER_ENABLE; + TIMER0_CR=TIMER_DIV_1024|TIMER_ENABLE; + while(TIMER0_DATA!=0xFFFF); + + // Clear out the timer registers + TIMER0_CR=0; + TIMER0_DATA=0; +} -u32 NTR_GetIDSafe (u32 flags, const u8* command, u32 Delay) +u32 NTR_GetIDSafe (u32 flags, const u8* command) { u32 data = 0; - Delay = 2* (((Delay & 0x3fff) * 1000) / 0x83); - ioDelay (Delay); cardWriteCommand(command); REG_NTRCARDROMCNT = flags | NTRCARD_BLK_SIZE(7); @@ -200,10 +219,8 @@ u32 NTR_GetIDSafe (u32 flags, const u8* command, u32 Delay) return data; } -void NTR_CmdSecure (u32 flags, void* buffer, u32 length, u8* pcmd, u32 Delay) +void NTR_CmdSecure (u32 flags, void* buffer, u32 length, u8* pcmd) { - Delay = 2 * (((Delay & 0x3fff) * 1000) / 0x83); - ioDelay (Delay); cardPolledTransfer (flags, buffer, length, pcmd); } @@ -217,15 +234,15 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice) const u8 cardSeedBytes[]={0xE8,0x4D,0x5A,0xB1,0x17,0x8F,0x99,0xD5}; IKEY1 iKey1 ={0}; bool iCheapCard = (CartID & 0x80000000) != 0; - u32 cardControl13 = *((u32*)(void*)&header[0x60]); - u32 cardControlBF = *((u32*)(void*)&header[0x64]); - u16 readTimeout = *((u16*)(void*)&header[0x6E]); readTimeout*=8; + u32 cardControl13 = *((vu32*)(void*)&header[0x60]); + u32 cardControlBF = *((vu32*)(void*)&header[0x64]); + u16 readTimeout = *((vu16*)(void*)&header[0x6E]); u8 deviceType = header[0x13]; int nCardHash = sizeof (iCardHash) / sizeof (iCardHash[0]); u32 flagsKey1=NTRCARD_ACTIVATE|NTRCARD_nRESET|(cardControl13&(NTRCARD_WR|NTRCARD_CLK_SLOW))|((cardControlBF&(NTRCARD_CLK_SLOW|NTRCARD_DELAY1(0x1FFF)))+((cardControlBF&NTRCARD_DELAY2(0x3F))>>16)); u32 flagsSec=(cardControlBF&(NTRCARD_CLK_SLOW|NTRCARD_DELAY1(0x1FFF)|NTRCARD_DELAY2(0x3F)))|NTRCARD_ACTIVATE|NTRCARD_nRESET|NTRCARD_SEC_EN|NTRCARD_SEC_DAT; - iGameCode = *((u32*)(void*)&header[0x0C]); + iGameCode = *((vu32*)(void*)&header[0x0C]); ReadDataFlags = cardControl13 & ~ NTRCARD_BLK_SIZE(7); NTR_InitKey (iGameCode, iCardHash, nCardHash, iKeyCode, iCardDevice?1:2, iCardDevice); @@ -237,15 +254,16 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice) //Debug("iKey1=%08X %08X %08X", iKey1.iii, iKey1. jjj, iKey1. kkkkk); //Debug("iKey1=%08X %08X %08X", iKey1. llll, iKey1. mmm, iKey1. nnn); - NTR_CmdSecure ((cardControl13 & (NTRCARD_WR | NTRCARD_nRESET | NTRCARD_CLK_SLOW)) | NTRCARD_ACTIVATE, NULL, 0, cmdData, 0); + NTR_CmdSecure ((cardControl13&(NTRCARD_CLK_SLOW|NTRCARD_DELAY2(0x3f)|NTRCARD_DELAY1(0x1fff)))|NTRCARD_ACTIVATE|NTRCARD_nRESET, NULL, 0, cmdData); NTR_CreateEncryptedCommand (NTRCARD_CMD_ACTIVATE_SEC, iCardHash, cmdData, &iKey1, 0); //Debug("cmdData=%02X %02X %02X %02X %02X %02X %02X %02X ", cmdData[0], cmdData[1], cmdData[2], cmdData[3], cmdData[4], cmdData[5], cmdData[6], cmdData[7]); if(iCheapCard) { - NTR_CmdSecure (flagsKey1, NULL, 0, cmdData, 0); + NTR_CmdSecure (flagsKey1, NULL, 0, cmdData); + NTR_SecureDelay(readTimeout); } - NTR_CmdSecure (flagsKey1, NULL, 0, cmdData, readTimeout); + NTR_CmdSecure (flagsKey1, NULL, 0, cmdData); REG_NTRCARDROMCNT = 0; REG_NTRCARDSEEDX_L = cardSeedBytes[deviceType & 0x07] | (iKey1.nnn << 15) | (iKey1.mmm << 27) | 0x6000; @@ -260,11 +278,12 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice) u32 SecureCartID = 0; if(iCheapCard) { - NTR_CmdSecure (flagsKey1, NULL, 0, cmdData, 0); + NTR_CmdSecure (flagsKey1, NULL, 0, cmdData); + NTR_SecureDelay(readTimeout); } - //NTR_CmdSecure (flagsKey1, &SecureCartID, sizeof (SecureCartID), cmdData, readTimeout); - SecureCartID = NTR_GetIDSafe (flagsKey1, cmdData, readTimeout); + //NTR_CmdSecure (flagsKey1, &SecureCartID, sizeof (SecureCartID), cmdData); + SecureCartID = NTR_GetIDSafe (flagsKey1, cmdData); if (SecureCartID != CartID) { @@ -278,16 +297,17 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice) NTR_CreateEncryptedCommand (NTRCARD_CMD_SECURE_READ, iCardHash, cmdData, &iKey1, secureBlockNumber); if (iCheapCard) { - NTR_CmdSecure (flagsSec, NULL, 0, cmdData, 0); + NTR_CmdSecure (flagsSec, NULL, 0, cmdData); + NTR_SecureDelay(readTimeout); for(int ii=8;ii>0;--ii) { - NTR_CmdSecure (flagsSec | NTRCARD_BLK_SIZE(1), secureArea + secureAreaOffset, 0x200, cmdData, readTimeout); + NTR_CmdSecure (flagsSec | NTRCARD_BLK_SIZE(1), secureArea + secureAreaOffset, 0x200, cmdData); secureAreaOffset += 0x200 / sizeof (u32); } } else { - NTR_CmdSecure (flagsSec | NTRCARD_BLK_SIZE(4) | NTRCARD_SEC_LARGE, secureArea + secureAreaOffset, 0x1000, cmdData, readTimeout); + NTR_CmdSecure (flagsSec | NTRCARD_BLK_SIZE(4) | NTRCARD_SEC_LARGE, secureArea + secureAreaOffset, 0x1000, cmdData); secureAreaOffset += 0x1000 / sizeof (u32); } } @@ -295,9 +315,10 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice) NTR_CreateEncryptedCommand (NTRCARD_CMD_DATA_MODE, iCardHash, cmdData, &iKey1, 0); if(iCheapCard) { - NTR_CmdSecure (flagsKey1, NULL, 0, cmdData, 0); + NTR_CmdSecure (flagsKey1, NULL, 0, cmdData); + NTR_SecureDelay(readTimeout); } - NTR_CmdSecure (flagsKey1, NULL, 0, cmdData, readTimeout); + NTR_CmdSecure (flagsKey1, NULL, 0, cmdData); if(!iCardDevice) //CycloDS doesn't like the dsi secure area being decrypted {