actually make DSi-mode direct boot work to some extent
This commit is contained in:
parent
b84155e891
commit
523552a92d
322
src/DSi.cpp
322
src/DSi.cpp
|
@ -25,6 +25,7 @@
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
#include "NDSCart.h"
|
#include "NDSCart.h"
|
||||||
|
#include "SPI.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
|
@ -187,37 +188,310 @@ void Reset()
|
||||||
ARM7Write16(eaddr+0x42, 0x0001);
|
ARM7Write16(eaddr+0x42, 0x0001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecryptModcryptArea(u32 offset, u32 size, u8* iv)
|
||||||
|
{
|
||||||
|
AES_ctx ctx;
|
||||||
|
u8 key[16];
|
||||||
|
u8 tmp[16];
|
||||||
|
|
||||||
|
if ((offset == 0) || (size == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((NDSCart::Header.DSiCryptoFlags & (1<<4)) ||
|
||||||
|
(NDSCart::Header.AppFlags & (1<<7)))
|
||||||
|
{
|
||||||
|
// dev key
|
||||||
|
memcpy(key, &NDSCart::CartROM[0], 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 keyX[16], keyY[16];
|
||||||
|
|
||||||
|
*(u32*)&keyX[0] = 0x746E694E;
|
||||||
|
*(u32*)&keyX[4] = 0x6F646E65;
|
||||||
|
keyX[8] = NDSCart::Header.GameCode[0];
|
||||||
|
keyX[9] = NDSCart::Header.GameCode[1];
|
||||||
|
keyX[10] = NDSCart::Header.GameCode[2];
|
||||||
|
keyX[11] = NDSCart::Header.GameCode[3];
|
||||||
|
keyX[12] = NDSCart::Header.GameCode[3];
|
||||||
|
keyX[13] = NDSCart::Header.GameCode[2];
|
||||||
|
keyX[14] = NDSCart::Header.GameCode[1];
|
||||||
|
keyX[15] = NDSCart::Header.GameCode[0];
|
||||||
|
|
||||||
|
memcpy(keyY, NDSCart::Header.DSiARM9iHash, 16);
|
||||||
|
|
||||||
|
DSi_AES::DeriveNormalKey(keyX, keyY, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DSi_AES::Swap16(key, tmp);
|
||||||
|
DSi_AES::Swap16(tmp, iv);
|
||||||
|
AES_init_ctx_iv(&ctx, key, tmp);
|
||||||
|
|
||||||
|
// find a matching binary area
|
||||||
|
|
||||||
|
u32 binaryaddr, binarysize;
|
||||||
|
|
||||||
|
// CHECKME: GBAtek says the modcrypt area should be the same size, or bigger,
|
||||||
|
// than the binary area being considered
|
||||||
|
// but I have seen modcrypt areas smaller than the ARM9i binary
|
||||||
|
#define BINARY_GOOD(name) \
|
||||||
|
((offset >= NDSCart::Header.name##ROMOffset) && \
|
||||||
|
(offset+size) <= (NDSCart::Header.name##ROMOffset+NDSCart::Header.name##Size))
|
||||||
|
|
||||||
|
if (BINARY_GOOD(ARM9))
|
||||||
|
{
|
||||||
|
binaryaddr = NDSCart::Header.ARM9RAMAddress;
|
||||||
|
binarysize = NDSCart::Header.ARM9Size;
|
||||||
|
}
|
||||||
|
else if (BINARY_GOOD(ARM7))
|
||||||
|
{
|
||||||
|
binaryaddr = NDSCart::Header.ARM7RAMAddress;
|
||||||
|
binarysize = NDSCart::Header.ARM7Size;
|
||||||
|
}
|
||||||
|
else if (BINARY_GOOD(DSiARM9i))
|
||||||
|
{
|
||||||
|
binaryaddr = NDSCart::Header.DSiARM9iRAMAddress;
|
||||||
|
binarysize = NDSCart::Header.DSiARM9iSize;
|
||||||
|
}
|
||||||
|
else if (BINARY_GOOD(DSiARM7i))
|
||||||
|
{
|
||||||
|
binaryaddr = NDSCart::Header.DSiARM7iRAMAddress;
|
||||||
|
binarysize = NDSCart::Header.DSiARM7iSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
#undef BINARY_GOOD
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size; i+=16)
|
||||||
|
{
|
||||||
|
u8 data[16];
|
||||||
|
|
||||||
|
*(u32*)&data[0] = ARM9Read32(binaryaddr+i);
|
||||||
|
*(u32*)&data[4] = ARM9Read32(binaryaddr+i+4);
|
||||||
|
*(u32*)&data[8] = ARM9Read32(binaryaddr+i+8);
|
||||||
|
*(u32*)&data[12] = ARM9Read32(binaryaddr+i+12);
|
||||||
|
|
||||||
|
DSi_AES::Swap16(tmp, data);
|
||||||
|
AES_CTR_xcrypt_buffer(&ctx, tmp, 16);
|
||||||
|
DSi_AES::Swap16(data, tmp);
|
||||||
|
|
||||||
|
ARM9Write32(binaryaddr+i, *(u32*)&data[0]);
|
||||||
|
ARM9Write32(binaryaddr+i+4, *(u32*)&data[4]);
|
||||||
|
ARM9Write32(binaryaddr+i+8, *(u32*)&data[8]);
|
||||||
|
ARM9Write32(binaryaddr+i+12, *(u32*)&data[12]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetupDirectBoot()
|
void SetupDirectBoot()
|
||||||
{
|
{
|
||||||
// If loading a NDS directly, this value should be set
|
bool dsmode = false;
|
||||||
// depending on the console type in the header at offset 12h
|
|
||||||
switch (NDSCart::Header.UnitCode)
|
// TODO: add controls for forcing DS or DSi mode?
|
||||||
|
if (!(NDSCart::Header.UnitCode & 0x02))
|
||||||
|
dsmode = true;
|
||||||
|
|
||||||
|
// TODO: RAM size!!
|
||||||
|
|
||||||
|
if (dsmode)
|
||||||
{
|
{
|
||||||
case 0x00: /* NDS Image */
|
|
||||||
// on a pure NDS Image, we disable all extended features
|
|
||||||
// TODO: For now keep the features enabled, as you can run pure NDS in NDS Emulation anyway
|
|
||||||
SCFG_BIOS = 0x0303;
|
SCFG_BIOS = 0x0303;
|
||||||
break;
|
|
||||||
case 0x02: /* DSi Enhanced Image */
|
// no NWRAM Mapping
|
||||||
SCFG_BIOS = 0x0303;
|
for (int i = 0; i < 4; i++)
|
||||||
break;
|
MapNWRAM_A(i, 0);
|
||||||
default:
|
for (int i = 0; i < 8; i++)
|
||||||
SCFG_BIOS = 0x0101; // TODO: should be zero when booting from BIOS
|
MapNWRAM_B(i, 0);
|
||||||
break;
|
for (int i = 0; i < 8; i++)
|
||||||
|
MapNWRAM_C(i, 0);
|
||||||
|
|
||||||
|
// No NWRAM Window
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
MapNWRAMRange(0, i, 0);
|
||||||
|
MapNWRAMRange(1, i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NDS::MapSharedWRAM(3);
|
||||||
|
|
||||||
|
// TODO: clock speed!
|
||||||
}
|
}
|
||||||
// no NWRAM Mapping
|
else
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
MapNWRAM_A(i, 0);
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
MapNWRAM_B(i, 0);
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
MapNWRAM_C(i, 0);
|
|
||||||
// No NWRAM Window
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
{
|
||||||
MapNWRAMRange(0, i, 0);
|
SCFG_BIOS = 0x0101;
|
||||||
MapNWRAMRange(1, i, 0);
|
|
||||||
|
// WRAM mapping
|
||||||
|
|
||||||
|
MBK[0][8] = 0;
|
||||||
|
MBK[1][8] = 0;
|
||||||
|
|
||||||
|
u32 mbk[12];
|
||||||
|
memcpy(mbk, &NDSCart::CartROM[0x180], 12*4);
|
||||||
|
|
||||||
|
MapNWRAM_A(0, mbk[0] & 0xFF);
|
||||||
|
MapNWRAM_A(1, (mbk[0] >> 8) & 0xFF);
|
||||||
|
MapNWRAM_A(2, (mbk[0] >> 16) & 0xFF);
|
||||||
|
MapNWRAM_A(3, mbk[0] >> 24);
|
||||||
|
|
||||||
|
MapNWRAM_B(0, mbk[1] & 0xFF);
|
||||||
|
MapNWRAM_B(1, (mbk[1] >> 8) & 0xFF);
|
||||||
|
MapNWRAM_B(2, (mbk[1] >> 16) & 0xFF);
|
||||||
|
MapNWRAM_B(3, mbk[1] >> 24);
|
||||||
|
MapNWRAM_B(4, mbk[2] & 0xFF);
|
||||||
|
MapNWRAM_B(5, (mbk[2] >> 8) & 0xFF);
|
||||||
|
MapNWRAM_B(6, (mbk[2] >> 16) & 0xFF);
|
||||||
|
MapNWRAM_B(7, mbk[2] >> 24);
|
||||||
|
|
||||||
|
MapNWRAM_C(0, mbk[3] & 0xFF);
|
||||||
|
MapNWRAM_C(1, (mbk[3] >> 8) & 0xFF);
|
||||||
|
MapNWRAM_C(2, (mbk[3] >> 16) & 0xFF);
|
||||||
|
MapNWRAM_C(3, mbk[3] >> 24);
|
||||||
|
MapNWRAM_C(4, mbk[4] & 0xFF);
|
||||||
|
MapNWRAM_C(5, (mbk[4] >> 8) & 0xFF);
|
||||||
|
MapNWRAM_C(6, (mbk[4] >> 16) & 0xFF);
|
||||||
|
MapNWRAM_C(7, mbk[4] >> 24);
|
||||||
|
|
||||||
|
MapNWRAMRange(0, 0, mbk[5]);
|
||||||
|
MapNWRAMRange(0, 1, mbk[6]);
|
||||||
|
MapNWRAMRange(0, 2, mbk[7]);
|
||||||
|
|
||||||
|
MapNWRAMRange(1, 0, mbk[8]);
|
||||||
|
MapNWRAMRange(1, 1, mbk[9]);
|
||||||
|
MapNWRAMRange(1, 2, mbk[10]);
|
||||||
|
|
||||||
|
MBK[0][8] = mbk[11] & 0x00FFFF0F;
|
||||||
|
MBK[1][8] = mbk[11] & 0x00FFFF0F;
|
||||||
|
|
||||||
|
NDS::MapSharedWRAM(mbk[11] >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 arm9start = 0;
|
||||||
|
|
||||||
|
// load the ARM9 secure area
|
||||||
|
if (NDSCart::Header.ARM9ROMOffset >= 0x4000 && NDSCart::Header.ARM9ROMOffset < 0x8000)
|
||||||
|
{
|
||||||
|
u8 securearea[0x800];
|
||||||
|
NDSCart::DecryptSecureArea(securearea);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x800; i+=4)
|
||||||
|
{
|
||||||
|
ARM9Write32(NDSCart::Header.ARM9RAMAddress+i, *(u32*)&securearea[i]);
|
||||||
|
arm9start += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = arm9start; i < NDSCart::Header.ARM9Size; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.ARM9ROMOffset+i];
|
||||||
|
ARM9Write32(NDSCart::Header.ARM9RAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < NDSCart::Header.ARM7Size; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.ARM7ROMOffset+i];
|
||||||
|
ARM7Write32(NDSCart::Header.ARM7RAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!dsmode) && (NDSCart::Header.DSiCryptoFlags & (1<<0)))
|
||||||
|
{
|
||||||
|
// load DSi-specific regions
|
||||||
|
|
||||||
|
for (u32 i = 0; i < NDSCart::Header.DSiARM9iSize; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.DSiARM9iROMOffset+i];
|
||||||
|
ARM9Write32(NDSCart::Header.DSiARM9iRAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < NDSCart::Header.DSiARM7iSize; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.DSiARM7iROMOffset+i];
|
||||||
|
ARM7Write32(NDSCart::Header.DSiARM7iRAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt any modcrypt areas
|
||||||
|
|
||||||
|
if (NDSCart::Header.DSiCryptoFlags & (1<<1))
|
||||||
|
{
|
||||||
|
DecryptModcryptArea(NDSCart::Header.DSiModcrypt1Offset,
|
||||||
|
NDSCart::Header.DSiModcrypt1Size,
|
||||||
|
NDSCart::Header.DSiARM9Hash);
|
||||||
|
DecryptModcryptArea(NDSCart::Header.DSiModcrypt2Offset,
|
||||||
|
NDSCart::Header.DSiModcrypt2Size,
|
||||||
|
NDSCart::Header.DSiARM7Hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECKME: some of these are 'only for NDS ROM', presumably
|
||||||
|
// only for when loading a cart? (as opposed to DSiWare)
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x160; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[i];
|
||||||
|
ARM9Write32(0x02FFFA80+i, tmp);
|
||||||
|
ARM9Write32(0x02FFFE00+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x1000; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[i];
|
||||||
|
ARM9Write32(0x02FFC000+i, tmp);
|
||||||
|
ARM9Write32(0x02FFE000+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DSi_NAND::Init(SDMMCFile, &DSi::ARM7iBIOS[0x8308]))
|
||||||
|
{
|
||||||
|
u8 userdata[0x1B0];
|
||||||
|
DSi_NAND::ReadUserData(userdata);
|
||||||
|
for (u32 i = 0; i < 0x128; i+=4)
|
||||||
|
ARM9Write32(0x02000400+i, *(u32*)&userdata[0x88+i]);
|
||||||
|
|
||||||
|
u8 hwinfoS[0xA4];
|
||||||
|
u8 hwinfoN[0x9C];
|
||||||
|
DSi_NAND::ReadHardwareInfo(hwinfoS, hwinfoN);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x14; i+=4)
|
||||||
|
ARM9Write32(0x02000600+i, *(u32*)&hwinfoN[0x88+i]);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x18; i+=4)
|
||||||
|
ARM9Write32(0x02FFFD68+i, *(u32*)&hwinfoS[0x88+i]);
|
||||||
|
|
||||||
|
DSi_NAND::DeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 nwifiver = SPI_Firmware::GetNWifiVersion();
|
||||||
|
ARM9Write8(0x020005E0, nwifiver);
|
||||||
|
|
||||||
|
// TODO: these should be taken from the wifi firmware in NAND
|
||||||
|
// but, hey, this works too.
|
||||||
|
if (nwifiver == 1)
|
||||||
|
{
|
||||||
|
ARM9Write16(0x020005E2, 0xB57E);
|
||||||
|
ARM9Write32(0x020005E4, 0x00500400);
|
||||||
|
ARM9Write32(0x020005E8, 0x00500000);
|
||||||
|
ARM9Write32(0x020005EC, 0x0002E000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ARM9Write16(0x020005E2, 0x5BCA);
|
||||||
|
ARM9Write32(0x020005E4, 0x00520000);
|
||||||
|
ARM9Write32(0x020005E8, 0x00520000);
|
||||||
|
ARM9Write32(0x020005EC, 0x00020000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: the shit at 02FFD7B0..02FFDC00
|
||||||
|
// and some other extra shit?
|
||||||
|
|
||||||
|
ARM9Write32(0x02FFFC00, NDSCart::CartID);
|
||||||
|
ARM9Write16(0x02FFFC40, 0x0001); // boot indicator
|
||||||
|
|
||||||
|
ARM9Write8(0x02FFFDFA, DSi_BPTWL::GetBootFlag() | 0x80);
|
||||||
|
ARM9Write8(0x02FFFDFB, 0x01);
|
||||||
|
|
||||||
|
NDS::ARM7BIOSProt = 0x20;
|
||||||
|
|
||||||
|
// TODO: SCFG setup, permissions, etc
|
||||||
|
|
||||||
|
SPI_Firmware::SetupDirectBoot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftReset()
|
void SoftReset()
|
||||||
|
|
|
@ -576,63 +576,4 @@ void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// utility
|
|
||||||
|
|
||||||
void GetModcryptKey(u8* romheader, u8* key)
|
|
||||||
{
|
|
||||||
if ((romheader[0x01C] & 0x04) || (romheader[0x1BF] & 0x80))
|
|
||||||
{
|
|
||||||
// dev key
|
|
||||||
memcpy(key, &romheader[0x000], 16);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*u8 oldkeys[16*3];
|
|
||||||
memcpy(&oldkeys[16*0], KeyX[0], 16);
|
|
||||||
memcpy(&oldkeys[16*1], KeyY[0], 16);
|
|
||||||
memcpy(&oldkeys[16*2], KeyNormal[0], 16);
|
|
||||||
|
|
||||||
KeyX[0][8] = romheader[0x00C];
|
|
||||||
KeyX[0][9] = romheader[0x00D];
|
|
||||||
KeyX[0][10] = romheader[0x00E];
|
|
||||||
KeyX[0][11] = romheader[0x00F];
|
|
||||||
KeyX[0][12] = romheader[0x00F];
|
|
||||||
KeyX[0][13] = romheader[0x00E];
|
|
||||||
KeyX[0][14] = romheader[0x00D];
|
|
||||||
KeyX[0][15] = romheader[0x00C];
|
|
||||||
|
|
||||||
memcpy(KeyY[0], &romheader[0x350], 16);
|
|
||||||
|
|
||||||
DeriveNormalKey(0);
|
|
||||||
memcpy(key, KeyNormal[0], 16);
|
|
||||||
|
|
||||||
memcpy(KeyX[0], &oldkeys[16*0], 16);
|
|
||||||
memcpy(KeyY[0], &oldkeys[16*1], 16);
|
|
||||||
memcpy(KeyNormal[0], &oldkeys[16*2], 16);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplyModcrypt(u8* data, u32 len, u8* key, u8* iv)
|
|
||||||
{
|
|
||||||
u8 key_rev[16], iv_rev[16];
|
|
||||||
u8 data_rev[16];
|
|
||||||
u8 oldkeys[16*2];
|
|
||||||
memcpy(&oldkeys[16*0], Ctx.RoundKey, 16);
|
|
||||||
memcpy(&oldkeys[16*1], Ctx.Iv, 16);
|
|
||||||
|
|
||||||
Swap16(key_rev, key);
|
|
||||||
Swap16(iv_rev, iv);
|
|
||||||
AES_init_ctx_iv(&Ctx, key_rev, iv_rev);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < len; i += 16)
|
|
||||||
{
|
|
||||||
Swap16(data_rev, &data[i]);
|
|
||||||
AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16);
|
|
||||||
Swap16(&data[i], data_rev);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(Ctx.RoundKey, &oldkeys[16*0], 16);
|
|
||||||
memcpy(Ctx.Iv, &oldkeys[16*1], 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,6 @@ void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask);
|
||||||
|
|
||||||
void Swap16(u8* dst, u8* src);
|
void Swap16(u8* dst, u8* src);
|
||||||
void DeriveNormalKey(u8* keyX, u8* keyY, u8* normalkey);
|
void DeriveNormalKey(u8* keyX, u8* keyY, u8* normalkey);
|
||||||
void GetModcryptKey(u8* romheader, u8* key);
|
|
||||||
void ApplyModcrypt(u8* data, u32 len, u8* key, u8* iv);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -384,7 +384,7 @@ u16 PDataDMAReadMMIO()
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Read8(u32 addr)
|
u8 Read8(u32 addr)
|
||||||
{
|
{printf("DSP READ8 %08X\n", addr);
|
||||||
if (!(DSi::SCFG_EXT[0] & (1<<18)))
|
if (!(DSi::SCFG_EXT[0] & (1<<18)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -413,7 +413,7 @@ u8 Read8(u32 addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
u16 Read16(u32 addr)
|
u16 Read16(u32 addr)
|
||||||
{
|
{printf("DSP READ16 %08X\n", addr);
|
||||||
if (!(DSi::SCFG_EXT[0] & (1<<18)))
|
if (!(DSi::SCFG_EXT[0] & (1<<18)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ u32 Read32(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write8(u32 addr, u8 val)
|
void Write8(u32 addr, u8 val)
|
||||||
{
|
{printf("DSP WRITE8 %08X %02X\n", addr, val);
|
||||||
if (!(DSi::SCFG_EXT[0] & (1<<18))) return;
|
if (!(DSi::SCFG_EXT[0] & (1<<18))) return;
|
||||||
|
|
||||||
if (!DSPCatchUp()) return;
|
if (!DSPCatchUp()) return;
|
||||||
|
@ -488,7 +488,7 @@ void Write8(u32 addr, u8 val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Write16(u32 addr, u16 val)
|
void Write16(u32 addr, u16 val)
|
||||||
{
|
{printf("DSP WRITE16 %08X %04X\n", addr, val);
|
||||||
if (!(DSi::SCFG_EXT[0] & (1<<18))) return;
|
if (!(DSi::SCFG_EXT[0] & (1<<18))) return;
|
||||||
|
|
||||||
if (!DSPCatchUp()) return;
|
if (!DSPCatchUp()) return;
|
||||||
|
|
|
@ -72,6 +72,8 @@ void Reset()
|
||||||
Registers[0x81] = 0x64;
|
Registers[0x81] = 0x64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 GetBootFlag() { return Registers[0x70]; }
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
//printf("BPTWL: start\n");
|
//printf("BPTWL: start\n");
|
||||||
|
|
|
@ -19,6 +19,13 @@
|
||||||
#ifndef DSI_I2C_H
|
#ifndef DSI_I2C_H
|
||||||
#define DSI_I2C_H
|
#define DSI_I2C_H
|
||||||
|
|
||||||
|
namespace DSi_BPTWL
|
||||||
|
{
|
||||||
|
|
||||||
|
u8 GetBootFlag();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace DSi_I2C
|
namespace DSi_I2C
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -436,6 +436,77 @@ bool ESDecrypt(u8* data, u32 len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ReadHardwareInfo(u8* dataS, u8* dataN)
|
||||||
|
{
|
||||||
|
FIL file;
|
||||||
|
FRESULT res;
|
||||||
|
u32 nread;
|
||||||
|
|
||||||
|
res = f_open(&file, "0:/sys/HWINFO_S.dat", FA_OPEN_EXISTING | FA_READ);
|
||||||
|
if (res == FR_OK)
|
||||||
|
{
|
||||||
|
f_read(&file, dataS, 0xA4, &nread);
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = f_open(&file, "0:/sys/HWINFO_N.dat", FA_OPEN_EXISTING | FA_READ);
|
||||||
|
if (res == FR_OK)
|
||||||
|
{
|
||||||
|
f_read(&file, dataN, 0x9C, &nread);
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ReadUserData(u8* data)
|
||||||
|
{
|
||||||
|
FIL file;
|
||||||
|
FRESULT res;
|
||||||
|
u32 nread;
|
||||||
|
|
||||||
|
FIL f1, f2;
|
||||||
|
int v1, v2;
|
||||||
|
|
||||||
|
res = f_open(&f1, "0:/shared1/TWLCFG0.dat", FA_OPEN_EXISTING | FA_READ);
|
||||||
|
if (res != FR_OK)
|
||||||
|
v1 = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 tmp;
|
||||||
|
f_lseek(&f1, 0x81);
|
||||||
|
f_read(&f1, &tmp, 1, &nread);
|
||||||
|
v1 = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = f_open(&f2, "0:/shared1/TWLCFG1.dat", FA_OPEN_EXISTING | FA_READ);
|
||||||
|
if (res != FR_OK)
|
||||||
|
v2 = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 tmp;
|
||||||
|
f_lseek(&f2, 0x81);
|
||||||
|
f_read(&f2, &tmp, 1, &nread);
|
||||||
|
v2 = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v1 < 0 && v2 < 0) return;
|
||||||
|
|
||||||
|
if (v2 > v1)
|
||||||
|
{
|
||||||
|
file = f2;
|
||||||
|
f_close(&f1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file = f1;
|
||||||
|
f_close(&f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_lseek(&file, 0);
|
||||||
|
f_read(&file, data, 0x1B0, &nread);
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
|
||||||
void PatchTSC()
|
void PatchTSC()
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
|
@ -39,6 +39,9 @@ void DeInit();
|
||||||
|
|
||||||
void GetIDs(u8* emmc_cid, u64& consoleid);
|
void GetIDs(u8* emmc_cid, u64& consoleid);
|
||||||
|
|
||||||
|
void ReadHardwareInfo(u8* dataS, u8* dataN);
|
||||||
|
|
||||||
|
void ReadUserData(u8* data);
|
||||||
void PatchTSC();
|
void PatchTSC();
|
||||||
|
|
||||||
void ListTitles(u32 category, std::vector<u32>& titlelist);
|
void ListTitles(u32 category, std::vector<u32>& titlelist);
|
||||||
|
|
146
src/NDS.cpp
146
src/NDS.cpp
|
@ -341,94 +341,86 @@ void SetupDirectBoot()
|
||||||
{
|
{
|
||||||
if (ConsoleType == 1)
|
if (ConsoleType == 1)
|
||||||
{
|
{
|
||||||
// With the BIOS select in SCFG_BIOS and the initialization od
|
|
||||||
// SCFG_BIOS depending on the Header->UnitType, we can now boot
|
|
||||||
// directly in the roms.
|
|
||||||
// There are some more SCFG Settings that change depending on
|
|
||||||
// the unit type, so this is experimental
|
|
||||||
printf("!! DIRECT BOOT NOT STABLE IN DSI MODE\n");
|
|
||||||
DSi::SetupDirectBoot();
|
DSi::SetupDirectBoot();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
u32 bootparams[8];
|
|
||||||
memcpy(bootparams, &NDSCart::CartROM[0x20], 8*4);
|
|
||||||
|
|
||||||
printf("ARM9: offset=%08X entry=%08X RAM=%08X size=%08X\n",
|
|
||||||
bootparams[0], bootparams[1], bootparams[2], bootparams[3]);
|
|
||||||
printf("ARM7: offset=%08X entry=%08X RAM=%08X size=%08X\n",
|
|
||||||
bootparams[4], bootparams[5], bootparams[6], bootparams[7]);
|
|
||||||
|
|
||||||
MapSharedWRAM(3);
|
|
||||||
|
|
||||||
u32 arm9start = 0;
|
|
||||||
|
|
||||||
// load the ARM9 secure area
|
|
||||||
if (bootparams[0] >= 0x4000 && bootparams[0] < 0x8000)
|
|
||||||
{
|
{
|
||||||
u8 securearea[0x800];
|
MapSharedWRAM(3);
|
||||||
NDSCart::DecryptSecureArea(securearea);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x800; i+=4)
|
u32 arm9start = 0;
|
||||||
|
|
||||||
|
// load the ARM9 secure area
|
||||||
|
if (NDSCart::Header.ARM9ROMOffset >= 0x4000 && NDSCart::Header.ARM9ROMOffset < 0x8000)
|
||||||
{
|
{
|
||||||
ARM9Write32(bootparams[2]+i, *(u32*)&securearea[i]);
|
u8 securearea[0x800];
|
||||||
arm9start += 4;
|
NDSCart::DecryptSecureArea(securearea);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x800; i+=4)
|
||||||
|
{
|
||||||
|
ARM9Write32(NDSCart::Header.ARM9RAMAddress+i, *(u32*)&securearea[i]);
|
||||||
|
arm9start += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECKME: firmware seems to load this in 0x200 byte chunks
|
||||||
|
|
||||||
|
for (u32 i = arm9start; i < NDSCart::Header.ARM9Size; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.ARM9ROMOffset+i];
|
||||||
|
ARM9Write32(NDSCart::Header.ARM9RAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < NDSCart::Header.ARM7Size; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[NDSCart::Header.ARM7ROMOffset+i];
|
||||||
|
ARM7Write32(NDSCart::Header.ARM7RAMAddress+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x170; i+=4)
|
||||||
|
{
|
||||||
|
u32 tmp = *(u32*)&NDSCart::CartROM[i];
|
||||||
|
ARM9Write32(0x027FFE00+i, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARM9Write32(0x027FF800, NDSCart::CartID);
|
||||||
|
ARM9Write32(0x027FF804, NDSCart::CartID);
|
||||||
|
ARM9Write16(0x027FF808, NDSCart::Header.HeaderCRC16);
|
||||||
|
ARM9Write16(0x027FF80A, NDSCart::Header.SecureAreaCRC16);
|
||||||
|
|
||||||
|
ARM9Write16(0x027FF850, 0x5835);
|
||||||
|
|
||||||
|
ARM9Write32(0x027FFC00, NDSCart::CartID);
|
||||||
|
ARM9Write32(0x027FFC04, NDSCart::CartID);
|
||||||
|
ARM9Write16(0x027FFC08, NDSCart::Header.HeaderCRC16);
|
||||||
|
ARM9Write16(0x027FFC0A, NDSCart::Header.SecureAreaCRC16);
|
||||||
|
|
||||||
|
ARM9Write16(0x027FFC10, 0x5835);
|
||||||
|
ARM9Write16(0x027FFC30, 0xFFFF);
|
||||||
|
ARM9Write16(0x027FFC40, 0x0001);
|
||||||
|
|
||||||
|
ARM7BIOSProt = 0x1204;
|
||||||
|
|
||||||
|
SPI_Firmware::SetupDirectBoot(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECKME: firmware seems to load this in 0x200 byte chunks
|
|
||||||
|
|
||||||
for (u32 i = arm9start; i < bootparams[3]; i+=4)
|
|
||||||
{
|
|
||||||
u32 tmp = *(u32*)&NDSCart::CartROM[bootparams[0]+i];
|
|
||||||
ARM9Write32(bootparams[2]+i, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < bootparams[7]; i+=4)
|
|
||||||
{
|
|
||||||
u32 tmp = *(u32*)&NDSCart::CartROM[bootparams[4]+i];
|
|
||||||
ARM7Write32(bootparams[6]+i, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x170; i+=4)
|
|
||||||
{
|
|
||||||
u32 tmp = *(u32*)&NDSCart::CartROM[i];
|
|
||||||
ARM9Write32(0x027FFE00+i, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ARM9Write32(0x027FF800, NDSCart::CartID);
|
|
||||||
ARM9Write32(0x027FF804, NDSCart::CartID);
|
|
||||||
ARM9Write16(0x027FF808, *(u16*)&NDSCart::CartROM[0x15E]);
|
|
||||||
ARM9Write16(0x027FF80A, *(u16*)&NDSCart::CartROM[0x6C]);
|
|
||||||
|
|
||||||
ARM9Write16(0x027FF850, 0x5835);
|
|
||||||
|
|
||||||
ARM9Write32(0x027FFC00, NDSCart::CartID);
|
|
||||||
ARM9Write32(0x027FFC04, NDSCart::CartID);
|
|
||||||
ARM9Write16(0x027FFC08, *(u16*)&NDSCart::CartROM[0x15E]);
|
|
||||||
ARM9Write16(0x027FFC0A, *(u16*)&NDSCart::CartROM[0x6C]);
|
|
||||||
|
|
||||||
ARM9Write16(0x027FFC10, 0x5835);
|
|
||||||
ARM9Write16(0x027FFC30, 0xFFFF);
|
|
||||||
ARM9Write16(0x027FFC40, 0x0001);
|
|
||||||
|
|
||||||
ARM9->CP15Write(0x910, 0x0300000A);
|
ARM9->CP15Write(0x910, 0x0300000A);
|
||||||
ARM9->CP15Write(0x911, 0x00000020);
|
ARM9->CP15Write(0x911, 0x00000020);
|
||||||
ARM9->CP15Write(0x100, ARM9->CP15Read(0x100) | 0x00050000);
|
ARM9->CP15Write(0x100, ARM9->CP15Read(0x100) | 0x00050000);
|
||||||
|
|
||||||
ARM9->R[12] = bootparams[1];
|
ARM9->R[12] = NDSCart::Header.ARM9EntryAddress;
|
||||||
ARM9->R[13] = 0x03002F7C;
|
ARM9->R[13] = 0x03002F7C;
|
||||||
ARM9->R[14] = bootparams[1];
|
ARM9->R[14] = NDSCart::Header.ARM9EntryAddress;
|
||||||
ARM9->R_IRQ[0] = 0x03003F80;
|
ARM9->R_IRQ[0] = 0x03003F80;
|
||||||
ARM9->R_SVC[0] = 0x03003FC0;
|
ARM9->R_SVC[0] = 0x03003FC0;
|
||||||
|
|
||||||
ARM7->R[12] = bootparams[5];
|
ARM7->R[12] = NDSCart::Header.ARM7EntryAddress;
|
||||||
ARM7->R[13] = 0x0380FD80;
|
ARM7->R[13] = 0x0380FD80;
|
||||||
ARM7->R[14] = bootparams[5];
|
ARM7->R[14] = NDSCart::Header.ARM7EntryAddress;
|
||||||
ARM7->R_IRQ[0] = 0x0380FF80;
|
ARM7->R_IRQ[0] = 0x0380FF80;
|
||||||
ARM7->R_SVC[0] = 0x0380FFC0;
|
ARM7->R_SVC[0] = 0x0380FFC0;
|
||||||
|
|
||||||
ARM9->JumpTo(bootparams[1]);
|
ARM9->JumpTo(NDSCart::Header.ARM9EntryAddress);
|
||||||
ARM7->JumpTo(bootparams[5]);
|
ARM7->JumpTo(NDSCart::Header.ARM7EntryAddress);
|
||||||
|
|
||||||
PostFlag9 = 0x01;
|
PostFlag9 = 0x01;
|
||||||
PostFlag7 = 0x01;
|
PostFlag7 = 0x01;
|
||||||
|
@ -444,10 +436,6 @@ void SetupDirectBoot()
|
||||||
SPU::SetBias(0x200);
|
SPU::SetBias(0x200);
|
||||||
|
|
||||||
SetWifiWaitCnt(0x0030);
|
SetWifiWaitCnt(0x0030);
|
||||||
|
|
||||||
ARM7BIOSProt = 0x1204;
|
|
||||||
|
|
||||||
SPI_Firmware::SetupDirectBoot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
@ -1522,7 +1510,7 @@ void MonitorARM9Jump(u32 addr)
|
||||||
if ((!RunningGame) && NDSCart::CartROM)
|
if ((!RunningGame) && NDSCart::CartROM)
|
||||||
{
|
{
|
||||||
if (addr == *(u32*)&NDSCart::CartROM[0x24])
|
if (addr == *(u32*)&NDSCart::CartROM[0x24])
|
||||||
{
|
{debug(0);
|
||||||
printf("Game is now booting\n");
|
printf("Game is now booting\n");
|
||||||
RunningGame = true;
|
RunningGame = true;
|
||||||
}
|
}
|
||||||
|
@ -1880,7 +1868,7 @@ void debug(u32 param)
|
||||||
//for (int i = 0; i < 9; i++)
|
//for (int i = 0; i < 9; i++)
|
||||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||||
|
|
||||||
FILE*
|
/*FILE*
|
||||||
shit = fopen("debug/construct.bin", "wb");
|
shit = fopen("debug/construct.bin", "wb");
|
||||||
fwrite(ARM9->ITCM, 0x8000, 1, shit);
|
fwrite(ARM9->ITCM, 0x8000, 1, shit);
|
||||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||||
|
@ -1893,23 +1881,23 @@ void debug(u32 param)
|
||||||
u32 val = ARM7Read32(i);
|
u32 val = ARM7Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);
|
fclose(shit);*/
|
||||||
|
|
||||||
/*FILE*
|
FILE*
|
||||||
shit = fopen("debug/power9.bin", "wb");
|
shit = fopen("debug/directboot9.bin", "wb");
|
||||||
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
||||||
{
|
{
|
||||||
u32 val = DSi::ARM9Read32(i);
|
u32 val = DSi::ARM9Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);
|
fclose(shit);
|
||||||
shit = fopen("debug/power7.bin", "wb");
|
shit = fopen("debug/directboot7.bin", "wb");
|
||||||
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
||||||
{
|
{
|
||||||
u32 val = DSi::ARM7Read32(i);
|
u32 val = DSi::ARM7Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);*/
|
fclose(shit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -176,15 +176,6 @@ 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CartCommon::CartCommon(u8* rom, u32 len, u32 chipid)
|
CartCommon::CartCommon(u8* rom, u32 len, u32 chipid)
|
||||||
{
|
{
|
||||||
ROM = rom;
|
ROM = rom;
|
||||||
|
|
|
@ -105,7 +105,7 @@ struct NDSHeader
|
||||||
u8 DSiWRAMCntSetting; // global WRAMCNT setting
|
u8 DSiWRAMCntSetting; // global WRAMCNT setting
|
||||||
|
|
||||||
u32 DSiRegionMask;
|
u32 DSiRegionMask;
|
||||||
u32 DSiPermissions;
|
u32 DSiPermissions[2];
|
||||||
u8 Reserved6[3];
|
u8 Reserved6[3];
|
||||||
u8 AppFlags; // flags at 1BF
|
u8 AppFlags; // flags at 1BF
|
||||||
|
|
||||||
|
|
80
src/SPI.cpp
80
src/SPI.cpp
|
@ -21,6 +21,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
|
#include "DSi.h"
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
#include "DSi_SPI_TSC.h"
|
#include "DSi_SPI_TSC.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
@ -167,35 +168,32 @@ void Reset()
|
||||||
|
|
||||||
UserSettings = userdata;
|
UserSettings = userdata;
|
||||||
|
|
||||||
if (NDS::ConsoleType == 0)
|
// fix touchscreen coords
|
||||||
|
*(u16*)&Firmware[userdata+0x58] = 0;
|
||||||
|
*(u16*)&Firmware[userdata+0x5A] = 0;
|
||||||
|
Firmware[userdata+0x5C] = 0;
|
||||||
|
Firmware[userdata+0x5D] = 0;
|
||||||
|
*(u16*)&Firmware[userdata+0x5E] = 255<<4;
|
||||||
|
*(u16*)&Firmware[userdata+0x60] = 191<<4;
|
||||||
|
Firmware[userdata+0x62] = 255;
|
||||||
|
Firmware[userdata+0x63] = 191;
|
||||||
|
|
||||||
|
// disable autoboot
|
||||||
|
//Firmware[userdata+0x64] &= 0xBF;
|
||||||
|
|
||||||
|
*(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
|
||||||
|
|
||||||
|
if (Config::RandomizeMAC)
|
||||||
{
|
{
|
||||||
// fix touchscreen coords
|
// replace MAC address with random address
|
||||||
*(u16*)&Firmware[userdata+0x58] = 0;
|
Firmware[0x36] = 0x00;
|
||||||
*(u16*)&Firmware[userdata+0x5A] = 0;
|
Firmware[0x37] = 0x09;
|
||||||
Firmware[userdata+0x5C] = 0;
|
Firmware[0x38] = 0xBF;
|
||||||
Firmware[userdata+0x5D] = 0;
|
Firmware[0x39] = rand()&0xFF;
|
||||||
*(u16*)&Firmware[userdata+0x5E] = 255<<4;
|
Firmware[0x3A] = rand()&0xFF;
|
||||||
*(u16*)&Firmware[userdata+0x60] = 191<<4;
|
Firmware[0x3B] = rand()&0xFF;
|
||||||
Firmware[userdata+0x62] = 255;
|
|
||||||
Firmware[userdata+0x63] = 191;
|
|
||||||
|
|
||||||
// disable autoboot
|
*(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000);
|
||||||
//Firmware[userdata+0x64] &= 0xBF;
|
|
||||||
|
|
||||||
*(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
|
|
||||||
|
|
||||||
if (Config::RandomizeMAC)
|
|
||||||
{
|
|
||||||
// replace MAC address with random address
|
|
||||||
Firmware[0x36] = 0x00;
|
|
||||||
Firmware[0x37] = 0x09;
|
|
||||||
Firmware[0x38] = 0xBF;
|
|
||||||
Firmware[0x39] = rand()&0xFF;
|
|
||||||
Firmware[0x3A] = rand()&0xFF;
|
|
||||||
Firmware[0x3B] = rand()&0xFF;
|
|
||||||
|
|
||||||
*(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
@ -232,16 +230,30 @@ void DoSavestate(Savestate* file)
|
||||||
file->Var32(&Addr);
|
file->Var32(&Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirectBoot()
|
void SetupDirectBoot(bool dsi)
|
||||||
{
|
{
|
||||||
NDS::ARM9Write32(0x027FF864, 0);
|
if (dsi)
|
||||||
NDS::ARM9Write32(0x027FF868, *(u16*)&Firmware[0x20] << 3);
|
{
|
||||||
|
for (u32 i = 0; i < 6; i += 2)
|
||||||
|
DSi::ARM9Write16(0x02FFFCF4, *(u16*)&Firmware[0x36+i]); // MAC address
|
||||||
|
|
||||||
NDS::ARM9Write16(0x027FF874, *(u16*)&Firmware[0x26]);
|
// checkme
|
||||||
NDS::ARM9Write16(0x027FF876, *(u16*)&Firmware[0x04]);
|
DSi::ARM9Write16(0x02FFFCFA, *(u16*)&Firmware[0x3C]); // enabled channels
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x70; i += 4)
|
for (u32 i = 0; i < 0x70; i += 4)
|
||||||
NDS::ARM9Write32(0x027FFC80+i, *(u32*)&Firmware[UserSettings+i]);
|
DSi::ARM9Write32(0x02FFFC80+i, *(u32*)&Firmware[UserSettings+i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NDS::ARM9Write32(0x027FF864, 0);
|
||||||
|
NDS::ARM9Write32(0x027FF868, *(u16*)&Firmware[0x20] << 3); // user settings offset
|
||||||
|
|
||||||
|
NDS::ARM9Write16(0x027FF874, *(u16*)&Firmware[0x26]); // CRC16 for data/gfx
|
||||||
|
NDS::ARM9Write16(0x027FF876, *(u16*)&Firmware[0x04]); // CRC16 for GUI/wifi code
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 0x70; i += 4)
|
||||||
|
NDS::ARM9Write32(0x027FFC80+i, *(u32*)&Firmware[UserSettings+i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 GetConsoleType() { return Firmware[0x1D]; }
|
u8 GetConsoleType() { return Firmware[0x1D]; }
|
||||||
|
|
Loading…
Reference in New Issue