aboutsummaryrefslogtreecommitdiff
path: root/src/NDSCart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/NDSCart.cpp')
-rw-r--r--src/NDSCart.cpp160
1 files changed, 101 insertions, 59 deletions
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 5a2a0d0..a5e0f41 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -19,10 +19,13 @@
#include <stdio.h>
#include <string.h>
#include "NDS.h"
+#include "DSi.h"
#include "NDSCart.h"
#include "ARM.h"
#include "CRC32.h"
+#include "DSi_AES.h"
#include "Platform.h"
+#include "ROMList.h"
namespace NDSCart_SRAM
@@ -473,6 +476,7 @@ u32 CartROMSize;
u32 CartCRC;
u32 CartID;
bool CartIsHomebrew;
+bool CartIsDSi;
u32 CmdEncMode;
u32 DataEncMode;
@@ -555,9 +559,13 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod)
}
}
-void Key1_InitKeycode(u32 idcode, u32 level, u32 mod)
+void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod)
{
- memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax
+ // TODO: source the key data from different possible places
+ if (dsi && NDS::ConsoleType==1)
+ memcpy(Key1_KeyBuf, &DSi::ARM7iBIOS[0xC6D0], 0x1048); // hax
+ else
+ memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax
u32 keycode[3] = {idcode, idcode>>1, idcode<<1};
if (level >= 1) Key1_ApplyKeycode(keycode, mod);
@@ -592,6 +600,15 @@ void Key2_Encrypt(u8* data, u32 len)
}
+void ApplyModcrypt(u32 addr, u32 len, u8* iv)
+{return;
+ u8 key[16];
+
+ DSi_AES::GetModcryptKey(&CartROM[0], key);
+ DSi_AES::ApplyModcrypt(&CartROM[addr], len, key, iv);
+}
+
+
bool Init()
{
if (!NDSCart_SRAM::Init()) return false;
@@ -610,32 +627,19 @@ void DeInit()
void Reset()
{
- SPICnt = 0;
- ROMCnt = 0;
-
- memset(ROMCommand, 0, 8);
- ROMDataOut = 0;
-
- Key2_X = 0;
- Key2_Y = 0;
-
- memset(DataOut, 0, 0x4000);
- DataOutPos = 0;
- DataOutLen = 0;
-
CartInserted = false;
if (CartROM) delete[] CartROM;
CartROM = NULL;
CartROMSize = 0;
CartID = 0;
CartIsHomebrew = false;
+ CartIsDSi = false;
ROMCommandHandler = NULL;
- CmdEncMode = 0;
- DataEncMode = 0;
-
NDSCart_SRAM::Reset();
+
+ ResetCart();
}
void DoSavestate(Savestate* file)
@@ -808,34 +812,21 @@ void ApplyDLDIPatch()
}
-bool ReadROMParams(u32 gamecode, u32* params)
+bool ReadROMParams(u32 gamecode, ROMListEntry* params)
{
- // format for romlist.bin:
- // [gamecode] [ROM size] [save type] [reserved]
- // list must be sorted by gamecode
-
- FILE* f = Platform::OpenDataFile("romlist.bin");
- if (!f) return false;
-
- fseek(f, 0, SEEK_END);
- u32 len = (u32)ftell(f);
- u32 maxlen = len;
- len >>= 4; // 16 bytes per entry
+ u32 len = sizeof(ROMList) / sizeof(ROMListEntry);
u32 offset = 0;
u32 chk_size = len >> 1;
for (;;)
{
u32 key = 0;
- fseek(f, offset + (chk_size << 4), SEEK_SET);
- fread(&key, 4, 1, f);
-
- printf("chk_size=%d, key=%08X, wanted=%08X, offset=%08X\n", chk_size, key, gamecode, offset);
+ ROMListEntry* curentry = &ROMList[offset + chk_size];
+ key = curentry->GameCode;
if (key == gamecode)
{
- fread(params, 4, 3, f);
- fclose(f);
+ memcpy(params, curentry, sizeof(ROMListEntry));
return true;
}
else
@@ -843,22 +834,20 @@ bool ReadROMParams(u32 gamecode, u32* params)
if (key < gamecode)
{
if (chk_size == 0)
- offset += 0x10;
+ offset++;
else
- offset += (chk_size << 4);
+ offset += chk_size;
}
else if (chk_size == 0)
{
- fclose(f);
return false;
}
chk_size >>= 1;
}
- if (offset >= maxlen)
+ if (offset >= len)
{
- fclose(f);
return false;
}
}
@@ -867,15 +856,20 @@ bool ReadROMParams(u32 gamecode, u32* params)
void DecryptSecureArea(u8* out)
{
+ // TODO: source decryption data from different possible sources
+ // * original DS-mode ARM7 BIOS has the key data at 0x30
+ // * .srl ROMs (VC dumps) have encrypted secure areas but have precomputed
+ // decryption data at 0x1000 (and at the beginning of the DSi region if any)
+
u32 gamecode = *(u32*)&CartROM[0x0C];
u32 arm9base = *(u32*)&CartROM[0x20];
memcpy(out, &CartROM[arm9base], 0x800);
- Key1_InitKeycode(gamecode, 2, 2);
+ Key1_InitKeycode(false, gamecode, 2, 2);
Key1_Decrypt((u32*)&out[0]);
- Key1_InitKeycode(gamecode, 3, 2);
+ Key1_InitKeycode(false, gamecode, 3, 2);
for (u32 i = 0; i < 0x800; i += 8)
Key1_Decrypt((u32*)&out[i]);
@@ -898,6 +892,7 @@ bool LoadROM(const char* path, const char* sram, bool direct)
{
// TODO: streaming mode? for really big ROMs or systems with limited RAM
// for now we're lazy
+ // also TODO: validate what we're loading!!
FILE* f = Platform::OpenFile(path, "rb");
if (!f)
@@ -919,6 +914,11 @@ bool LoadROM(const char* path, const char* sram, bool direct)
fread(&gamecode, 4, 1, f);
printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24);
+ u8 unitcode;
+ fseek(f, 0x12, SEEK_SET);
+ fread(&unitcode, 1, 1, f);
+ CartIsDSi = (unitcode & 0x02) != 0;
+
CartROM = new u8[CartROMSize];
memset(CartROM, 0, CartROMSize);
fseek(f, 0, SEEK_SET);
@@ -930,22 +930,23 @@ bool LoadROM(const char* path, const char* sram, bool direct)
CartCRC = CRC32(CartROM, CartROMSize);
printf("ROM CRC32: %08X\n", CartCRC);
- u32 romparams[3];
- if (!ReadROMParams(gamecode, romparams))
+ ROMListEntry romparams;
+ if (!ReadROMParams(gamecode, &romparams))
{
// set defaults
printf("ROM entry not found\n");
- romparams[0] = CartROMSize;
+ romparams.GameCode = gamecode;
+ romparams.ROMSize = CartROMSize;
if (*(u32*)&CartROM[0x20] < 0x4000)
- romparams[1] = 0; // no saveRAM for homebrew
+ romparams.SaveMemType = 0; // no saveRAM for homebrew
else
- romparams[1] = 2; // assume EEPROM 64k (TODO FIXME)
+ romparams.SaveMemType = 2; // assume EEPROM 64k (TODO FIXME)
}
else
- printf("ROM entry: %08X %08X %08X\n", romparams[0], romparams[1], romparams[2]);
+ printf("ROM entry: %08X %08X\n", romparams.ROMSize, romparams.SaveMemType);
- if (romparams[0] != len) printf("!! bad ROM size %d (expected %d) rounded to %d\n", len, romparams[0], CartROMSize);
+ if (romparams.ROMSize != len) printf("!! bad ROM size %d (expected %d) rounded to %d\n", len, romparams.ROMSize, CartROMSize);
// generate a ROM ID
// note: most games don't check the actual value
@@ -957,9 +958,12 @@ bool LoadROM(const char* path, const char* sram, bool direct)
else
CartID |= (0x100 - (CartROMSize >> 28)) << 8;
- if (romparams[1] == 8)
+ if (romparams.SaveMemType == 8)
CartID |= 0x08000000; // NAND flag
+ if (CartIsDSi)
+ CartID |= 0x40000000;
+
printf("Cart ID: %08X\n", CartID);
u32 arm9base = *(u32*)&CartROM[0x20];
@@ -975,11 +979,11 @@ bool LoadROM(const char* path, const char* sram, bool direct)
strncpy((char*)&CartROM[arm9base], "encryObj", 8);
- Key1_InitKeycode(gamecode, 3, 2);
+ Key1_InitKeycode(false, gamecode, 3, 2);
for (u32 i = 0; i < 0x800; i += 8)
Key1_Encrypt((u32*)&CartROM[arm9base + i]);
- Key1_InitKeycode(gamecode, 2, 2);
+ Key1_InitKeycode(false, gamecode, 2, 2);
Key1_Encrypt((u32*)&CartROM[arm9base]);
}
}
@@ -1007,12 +1011,11 @@ bool LoadROM(const char* path, const char* sram, bool direct)
ROMCommandHandler = ROMCommand_Retail;
// encryption
- Key1_InitKeycode(gamecode, 2, 2);
-
+ Key1_InitKeycode(false, gamecode, 2, 2);
// save
printf("Save file: %s\n", sram);
- NDSCart_SRAM::LoadSave(sram, romparams[1]);
+ NDSCart_SRAM::LoadSave(sram, romparams.SaveMemType);
return true;
}
@@ -1023,6 +1026,27 @@ void RelocateSave(const char* path, bool write)
NDSCart_SRAM::RelocateSave(path, write);
}
+void ResetCart()
+{
+ // CHECKME: what if there is a transfer in progress?
+
+ SPICnt = 0;
+ ROMCnt = 0;
+
+ memset(ROMCommand, 0, 8);
+ ROMDataOut = 0;
+
+ Key2_X = 0;
+ Key2_Y = 0;
+
+ memset(DataOut, 0, 0x4000);
+ DataOutPos = 0;
+ DataOutLen = 0;
+
+ CmdEncMode = 0;
+ DataEncMode = 0;
+}
+
void ReadROM(u32 addr, u32 len, u32 offset)
{
if (!CartInserted) return;
@@ -1197,7 +1221,7 @@ void WriteROMCnt(u32 val)
// handle KEY1 encryption as needed.
// KEY2 encryption is implemented in hardware and doesn't need to be handled.
u8 cmd[8];
- if (CmdEncMode == 1)
+ if (CmdEncMode == 1 || CmdEncMode == 11)
{
*(u32*)&cmd[0] = ByteSwap(*(u32*)&ROMCommand[4]);
*(u32*)&cmd[4] = ByteSwap(*(u32*)&ROMCommand[0]);
@@ -1243,11 +1267,23 @@ void WriteROMCnt(u32 val)
break;
case 0x3C:
- if (CartInserted) CmdEncMode = 1;
+ if (CartInserted)
+ {
+ CmdEncMode = 1;
+ Key1_InitKeycode(false, *(u32*)&CartROM[0xC], 2, 2);
+ }
+ break;
+
+ case 0x3D:
+ if (CartInserted && CartIsDSi)
+ {
+ CmdEncMode = 11;
+ Key1_InitKeycode(true, *(u32*)&CartROM[0xC], 1, 2);
+ }
break;
default:
- if (CmdEncMode == 1)
+ if (CmdEncMode == 1 || CmdEncMode == 11)
{
switch (cmd[0] & 0xF0)
{
@@ -1263,6 +1299,12 @@ void WriteROMCnt(u32 val)
case 0x20:
{
u32 addr = (cmd[2] & 0xF0) << 8;
+ if (CmdEncMode == 11)
+ {
+ u32 arm9i_base = *(u32*)&CartROM[0x1C0];
+ addr -= 0x4000;
+ addr += arm9i_base;
+ }
ReadROM(addr, 0x1000, 0);
}
break;