mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 21:52:48 +00:00
parent
af14376c84
commit
8ebb74b0bc
@ -15,5 +15,5 @@ void NTR_CmdEnter16ByteMode(void);
|
||||
void NTR_CmdReadHeader (u8* buffer);
|
||||
void NTR_CmdReadData (u32 offset, void* buffer);
|
||||
|
||||
bool NTR_Secure_Init (u8* buffer, u32 CartID, int iCardDevice);
|
||||
bool NTR_Secure_Init (u8* buffer, u8* sa_copy, u32 CartID, int iCardDevice);
|
||||
|
||||
|
@ -33,8 +33,7 @@ typedef struct {
|
||||
TwlHeader ntr_header;
|
||||
u8 ntr_padding[0x3000]; // 0x00
|
||||
u8 secure_area[0x4000];
|
||||
TwlHeader twl_header;
|
||||
u8 twl_padding[0x3000]; // 0x00
|
||||
u8 secure_area_enc[0x4000];
|
||||
u8 modcrypt_area[0x4000];
|
||||
u32 cart_type;
|
||||
u32 cart_id;
|
||||
@ -45,7 +44,8 @@ typedef struct {
|
||||
u32 arm9i_rom_offset;
|
||||
} PACKED_ALIGN(16) CartDataNtrTwl;
|
||||
|
||||
DsTime init_time;
|
||||
static DsTime init_time;
|
||||
static bool encrypted_sa = false;
|
||||
|
||||
u32 GetCartName(char* name, CartData* cdata) {
|
||||
if (cdata->cart_type & CART_CTR) {
|
||||
@ -86,8 +86,14 @@ u32 GetCartInfoString(char* info, CartData* cdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 SetSecureAreaEncryption(bool encrypted) {
|
||||
encrypted_sa = encrypted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 InitCartRead(CartData* cdata) {
|
||||
get_dstime(&init_time);
|
||||
encrypted_sa = false;
|
||||
memset(cdata, 0x00, sizeof(CartData));
|
||||
cdata->cart_type = CART_NONE;
|
||||
if (!CART_INSERTED) return 1;
|
||||
@ -153,9 +159,11 @@ u32 InitCartRead(CartData* cdata) {
|
||||
} else { // NTR/TWL cartridges
|
||||
// NTR header
|
||||
TwlHeader* nds_header = (void*)cdata->header;
|
||||
u8 secure_area_enc[0x4000];
|
||||
NTR_CmdReadHeader(cdata->header);
|
||||
if (!(*(cdata->header))) return 1; // error reading the header
|
||||
if (!NTR_Secure_Init(cdata->header, Cart_GetID(), 0)) return 1;
|
||||
if (!NTR_Secure_Init(cdata->header, secure_area_enc, Cart_GetID(), 0)) return 1;
|
||||
|
||||
|
||||
// cartridge size, trimmed size, twl presets
|
||||
if (nds_header->device_capacity >= 15) return 1; // too big, not valid
|
||||
@ -177,11 +185,14 @@ u32 InitCartRead(CartData* cdata) {
|
||||
// We'll only want to use TWL secure init if this is a TWL cartridge.
|
||||
if (cdata->cart_id & 0x40000000U) { // TWL cartridge
|
||||
Cart_Init();
|
||||
NTR_CmdReadHeader(cdata->twl_header);
|
||||
if (!NTR_Secure_Init(cdata->twl_header, Cart_GetID(), 1)) return 1;
|
||||
NTR_CmdReadHeader(cdata->storage);
|
||||
if (!NTR_Secure_Init(cdata->storage, NULL, Cart_GetID(), 1)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// store encrypted secure area
|
||||
memcpy(cdata->storage, secure_area_enc, 0x4000);
|
||||
|
||||
// last safety check
|
||||
if (cdata->data_size > cdata->cart_size) return 1;
|
||||
|
||||
@ -199,7 +210,7 @@ u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata) {
|
||||
u8* buffer8 = (u8*) buffer;
|
||||
if (!CART_INSERTED) return 1;
|
||||
// header
|
||||
u32 header_sectors = (cdata->cart_type & CART_CTR) ? 0x4000/0x200 : 0x8000/0x200;
|
||||
const u32 header_sectors = 0x4000/0x200;
|
||||
if (sector < header_sectors) {
|
||||
u32 header_count = (sector + count > header_sectors) ? header_sectors - sector : count;
|
||||
memcpy(buffer8, cdata->header + (sector * 0x200), header_count * 0x200);
|
||||
@ -219,6 +230,7 @@ u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata) {
|
||||
CTR_CmdReadData(sector + i, 0x200, min(max_read, count - i), buff);
|
||||
buff += max_read * 0x200;
|
||||
}
|
||||
|
||||
// overwrite the card2 savegame with 0xFF
|
||||
u32 card2_offset = getle32(cdata->header + 0x200);
|
||||
if ((card2_offset != 0xFFFFFFFF) &&
|
||||
@ -231,9 +243,24 @@ u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata) {
|
||||
}
|
||||
} else if (cdata->cart_type & CART_NTR) {
|
||||
u8* buff = buffer8;
|
||||
|
||||
// secure area handling
|
||||
const u32 sa_sector_end = 0x8000/0x200;
|
||||
if (sector < sa_sector_end) {
|
||||
CartDataNtrTwl* cdata_twl = (CartDataNtrTwl*) cdata;
|
||||
u8* sa = encrypted_sa ? cdata_twl->secure_area_enc : cdata_twl->secure_area;
|
||||
u32 count_sa = ((sector + count) > sa_sector_end) ? sa_sector_end - sector : count;
|
||||
memcpy(buff, sa + ((sector - header_sectors) * 0x200), count_sa * 0x200);
|
||||
buff += count_sa * 0x200;
|
||||
sector += count_sa;
|
||||
count -= count_sa;
|
||||
}
|
||||
|
||||
// regular cart data
|
||||
u32 off = sector * 0x200;
|
||||
for (u32 i = 0; i < count; i++, off += 0x200, buff += 0x200)
|
||||
NTR_CmdReadData(off, buff);
|
||||
|
||||
// modcrypt area handling
|
||||
if ((cdata->cart_type & CART_TWL) &&
|
||||
((sector+count) * 0x200 > cdata->arm9i_rom_offset) &&
|
||||
@ -248,7 +275,7 @@ u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata) {
|
||||
size_i = MODC_AREA_SIZE - offset_i;
|
||||
if (size_i > (count * 0x200) - (buffer_arm9i - buffer8))
|
||||
size_i = (count * 0x200) - (buffer_arm9i - buffer8);
|
||||
if (size_i) memcpy(buffer_arm9i, cdata->twl_header + 0x4000 + offset_i, size_i);
|
||||
if (size_i) memcpy(buffer_arm9i, cdata->storage + 0x4000 + offset_i, size_i);
|
||||
}
|
||||
} else return 1;
|
||||
return 0;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
typedef struct {
|
||||
u8 header[0x8000]; // NTR header + secure area / CTR header + private header
|
||||
u8 twl_header[0x8000]; // TWL header + modcrypt area / unused
|
||||
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
|
||||
u32 cart_type;
|
||||
u32 cart_id;
|
||||
u64 cart_size;
|
||||
@ -26,6 +26,7 @@ typedef struct {
|
||||
|
||||
u32 GetCartName(char* name, CartData* cdata);
|
||||
u32 GetCartInfoString(char* info, CartData* cdata);
|
||||
u32 SetSecureAreaEncryption(bool encrypted);
|
||||
u32 InitCartRead(CartData* cdata);
|
||||
u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata);
|
||||
u32 ReadCartBytes(void* buffer, u64 offset, u64 count, CartData* cdata);
|
||||
|
@ -231,7 +231,7 @@ void NTR_CmdSecure (u32 flags, void* buffer, u32 length, u8* pcmd)
|
||||
cardPolledTransfer (flags, buffer, length, pcmd);
|
||||
}
|
||||
|
||||
bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice)
|
||||
bool NTR_Secure_Init (u8* header, u8* sa_copy, u32 CartID, int iCardDevice)
|
||||
{
|
||||
u32 iGameCode;
|
||||
u32 iCardHash[0x412] = {0};
|
||||
@ -329,6 +329,7 @@ bool NTR_Secure_Init (u8* header, u32 CartID, int iCardDevice)
|
||||
NTR_CmdSecure (flagsKey1, NULL, 0, cmdData);
|
||||
|
||||
//CycloDS doesn't like the dsi secure area being decrypted
|
||||
if (sa_copy) memcpy(sa_copy, secureArea, 0x4000);
|
||||
if(!iCardDevice && ((nds9Offset != 0x4000) || secureArea[0] || secureArea[1]))
|
||||
{
|
||||
NTR_DecryptSecureArea (iGameCode, iCardHash, nCardHash, iKeyCode, secureArea, iCardDevice);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "gamecart.h"
|
||||
|
||||
#define FAT_LIMIT 0x100000000
|
||||
#define VFLAG_SECURE_AREA_ENC (1UL<<27)
|
||||
#define VFLAG_GAMECART_NFO (1UL<<28)
|
||||
#define VFLAG_JEDECID_AND_SRFG (1UL<<29)
|
||||
#define VFLAG_SAVEGAME (1UL<<30)
|
||||
@ -34,7 +35,7 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
|
||||
vfile->keyslot = 0xFF; // unused
|
||||
vfile->flags = VFLAG_READONLY;
|
||||
|
||||
while (++vdir->index <= 8) {
|
||||
while (++vdir->index <= 9) {
|
||||
if ((vdir->index == 0) && (cdata->data_size < FAT_LIMIT)) { // standard full rom
|
||||
snprintf(vfile->name, 32, "%s.%s", name, ext);
|
||||
vfile->size = cdata->cart_size;
|
||||
@ -53,24 +54,31 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
|
||||
vfile->size = (FAT_LIMIT / 2);
|
||||
vfile->offset = (FAT_LIMIT / 2);
|
||||
return true;
|
||||
} else if ((vdir->index == 5) && (cdata->cart_type & CART_CTR)) { // private header
|
||||
} else if ((vdir->index == 5) && (cdata->data_size < FAT_LIMIT) &&
|
||||
(cdata->cart_type & CART_NTR)) { // encrypted secure area
|
||||
snprintf(vfile->name, 32, "%s.nds.enc", name);
|
||||
vfile->size = cdata->cart_size;
|
||||
if (vfile->size == FAT_LIMIT) vfile->size--;
|
||||
vfile->flags = VFLAG_SECURE_AREA_ENC;
|
||||
return true;
|
||||
} else if ((vdir->index == 6) && (cdata->cart_type & CART_CTR)) { // private header
|
||||
snprintf(vfile->name, 32, "%s-priv.bin", name);
|
||||
vfile->size = PRIV_HDR_SIZE;
|
||||
vfile->flags |= VFLAG_PRIV_HDR;
|
||||
return true;
|
||||
} else if ((vdir->index == 6) && (cdata->save_size > 0)) { // savegame
|
||||
} else if ((vdir->index == 7) && (cdata->save_size > 0)) { // savegame
|
||||
snprintf(vfile->name, 32, "%s.sav", name);
|
||||
vfile->size = cdata->save_size;
|
||||
vfile->flags = VFLAG_SAVEGAME;
|
||||
return true;
|
||||
} else if (vdir->index == 7) { // gamecart info
|
||||
} else if (vdir->index == 8) { // gamecart info
|
||||
char info[256];
|
||||
GetCartInfoString(info, cdata);
|
||||
snprintf(vfile->name, 32, "%s.txt", name);
|
||||
vfile->size = strnlen(info, 255);
|
||||
vfile->flags |= VFLAG_GAMECART_NFO;
|
||||
return true;
|
||||
} else if ((vdir->index == 8) && cdata->save_type.chip) { // JEDEC id and status register
|
||||
} else if ((vdir->index == 9) && cdata->save_type.chip) { // JEDEC id and status register
|
||||
strcpy(vfile->name, "jedecid_and_sreg.bin");
|
||||
vfile->size = JEDECID_AND_SREG_SIZE;
|
||||
vfile->flags |= VFLAG_JEDECID_AND_SRFG;
|
||||
@ -84,6 +92,7 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
|
||||
int ReadVCartFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count) {
|
||||
u32 foffset = vfile->offset + offset;
|
||||
if (!cdata) return -1;
|
||||
|
||||
if (vfile->flags & VFLAG_PRIV_HDR)
|
||||
return ReadCartPrivateHeader(buffer, foffset, count, cdata);
|
||||
else if (vfile->flags & VFLAG_SAVEGAME)
|
||||
@ -92,7 +101,9 @@ int ReadVCartFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count)
|
||||
return ReadCartInfo(buffer, foffset, count, cdata);
|
||||
else if (vfile->flags & VFLAG_JEDECID_AND_SRFG)
|
||||
return ReadCartSaveJedecId(buffer, foffset, count, cdata);
|
||||
else return ReadCartBytes(buffer, foffset, count, cdata);
|
||||
|
||||
SetSecureAreaEncryption(vfile->flags & VFLAG_SECURE_AREA_ENC);
|
||||
return ReadCartBytes(buffer, foffset, count, cdata);
|
||||
}
|
||||
|
||||
int WriteVCartFile(const VirtualFile* vfile, const void* buffer, u64 offset, u64 count) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user