NDSCart: correctly restrict reading the DSi region on DSi carts

This commit is contained in:
Arisotura 2021-07-22 21:37:34 +02:00
parent ab48461dc5
commit cd4ef575ee
2 changed files with 21 additions and 8 deletions

View File

@ -193,6 +193,7 @@ CartCommon::CartCommon(u8* rom, u32 len, u32 chipid)
u8 unitcode = ROM[0x12]; u8 unitcode = ROM[0x12];
IsDSi = (unitcode & 0x02) != 0; IsDSi = (unitcode & 0x02) != 0;
DSiBase = *(u16*)&ROM[0x92] << 19;
} }
CartCommon::~CartCommon() CartCommon::~CartCommon()
@ -203,12 +204,14 @@ void CartCommon::Reset()
{ {
CmdEncMode = 0; CmdEncMode = 0;
DataEncMode = 0; DataEncMode = 0;
DSiMode = false;
} }
void CartCommon::SetupDirectBoot() void CartCommon::SetupDirectBoot()
{ {
CmdEncMode = 2; CmdEncMode = 2;
DataEncMode = 2; DataEncMode = 2;
DSiMode = false; // TODO!!
} }
void CartCommon::DoSavestate(Savestate* file) void CartCommon::DoSavestate(Savestate* file)
@ -217,6 +220,7 @@ void CartCommon::DoSavestate(Savestate* file)
file->Var32(&CmdEncMode); file->Var32(&CmdEncMode);
file->Var32(&DataEncMode); file->Var32(&DataEncMode);
file->Bool32(&DSiMode);
} }
void CartCommon::LoadSave(const char* path, u32 type) void CartCommon::LoadSave(const char* path, u32 type)
@ -266,13 +270,15 @@ int CartCommon::ROMCommandStart(u8* cmd, u8* data, u32 len)
case 0x3C: case 0x3C:
CmdEncMode = 1; CmdEncMode = 1;
Key1_InitKeycode(false, *(u32*)&ROM[0xC], 2, 2); Key1_InitKeycode(false, *(u32*)&ROM[0xC], 2, 2);
DSiMode = false;
return 0; return 0;
case 0x3D: case 0x3D:
if (IsDSi) if (IsDSi)
{ {
CmdEncMode = 11; CmdEncMode = 1;
Key1_InitKeycode(true, *(u32*)&ROM[0xC], 1, 2); Key1_InitKeycode(true, *(u32*)&ROM[0xC], 1, 2);
DSiMode = true;
} }
return 0; return 0;
@ -280,7 +286,7 @@ int CartCommon::ROMCommandStart(u8* cmd, u8* data, u32 len)
return 0; return 0;
} }
} }
else if (CmdEncMode == 1 || CmdEncMode == 11) else if (CmdEncMode == 1)
{ {
// decrypt the KEY1 command as needed // decrypt the KEY1 command as needed
// (KEY2 commands do not need decrypted because KEY2 is handled entirely by hardware, // (KEY2 commands do not need decrypted because KEY2 is handled entirely by hardware,
@ -309,14 +315,13 @@ int CartCommon::ROMCommandStart(u8* cmd, u8* data, u32 len)
case 0x20: case 0x20:
{ {
u32 addr = (cmddec[2] & 0xF0) << 8; u32 addr = (cmddec[2] & 0xF0) << 8;
if (CmdEncMode == 11) if (DSiMode)
{ {
// the DSi region starts with 0x3000 unreadable bytes // the DSi region starts with 0x3000 unreadable bytes
// similarly to how the DS region starts at 0x1000 with 0x3000 unreadable bytes // similarly to how the DS region starts at 0x1000 with 0x3000 unreadable bytes
// these contain data for KEY1 crypto // these contain data for KEY1 crypto
u32 dsiregion = *(u16*)&ROM[0x92] << 19;
addr -= 0x1000; addr -= 0x1000;
addr += dsiregion; addr += DSiBase;
} }
ReadROM(addr, 0x1000, data, 0); ReadROM(addr, 0x1000, data, 0);
} }
@ -597,9 +602,15 @@ void CartRetail::ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset)
if (addr < 0x8000) if (addr < 0x8000)
addr = 0x8000 + (addr & 0x1FF); addr = 0x8000 + (addr & 0x1FF);
// TODO: protect DSi secure area if (IsDSi && (addr >= DSiBase))
// also protect DSi region if not unlocked {
// and other security shenanigans // for DSi carts:
// * in DSi mode: block the first 0x3000 bytes of the DSi area
// * in DS mode: block the entire DSi area
if ((!DSiMode) || (addr < (DSiBase+0x3000)))
addr = 0x8000 + (addr & 0x1FF);
}
memcpy(data+offset, ROM+addr, len); memcpy(data+offset, ROM+addr, len);
} }

View File

@ -56,6 +56,8 @@ protected:
u32 ROMLength; u32 ROMLength;
u32 ChipID; u32 ChipID;
bool IsDSi; bool IsDSi;
bool DSiMode;
u32 DSiBase;
u32 CmdEncMode; u32 CmdEncMode;
u32 DataEncMode; u32 DataEncMode;