From 109fc776da68438cd2e2bc80e94ea998896f9481 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 14 Apr 2021 19:26:58 +0200 Subject: [PATCH] begin work on the NAND thing --- src/NDS.h | 2 +- src/NDSCart.cpp | 119 ++++++++++++++++++++++++++++++++++++++---------- src/NDSCart.h | 3 ++ 3 files changed, 99 insertions(+), 25 deletions(-) diff --git a/src/NDS.h b/src/NDS.h index c73a2ca4..8aa1397a 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -82,7 +82,7 @@ enum IRQ_IPCSync, IRQ_IPCSendDone, IRQ_IPCRecv, - IRQ_CartSendDone, // TODO: less misleading name + IRQ_CartXferDone, IRQ_CartIREQMC, // IRQ triggered by game cart (example: Pokémon Typing Adventure, BT controller) IRQ_GXFIFO, IRQ_LidOpen, diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 688cd2e4..a32a3581 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -740,7 +740,7 @@ void CartCommon::ROMCommandFinish(u8* cmd) u8 CartCommon::SPIWrite(u8 val, u32 pos, bool last) { - return val; + return 0xFF; } void CartCommon::ReadROM(u32 addr, u32 len, u32 offset) @@ -1159,6 +1159,7 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last) CartRetailNAND::CartRetailNAND(u8* rom, u32 len) : CartRetail(rom, len) { + printf("ohai I am a NAND cart\n"); } CartRetailNAND::~CartRetailNAND() @@ -1167,6 +1168,9 @@ CartRetailNAND::~CartRetailNAND() void CartRetailNAND::Reset() { + SRAMAddr = 0; + SRAMStatus = 0x20; + SRAMReadWindow = 0; } void CartRetailNAND::DoSavestate(Savestate* file) @@ -1176,44 +1180,103 @@ void CartRetailNAND::DoSavestate(Savestate* file) void CartRetailNAND::ROMCommandStart(u8* cmd) { + // ROM header 94/96 = save addr start / 0x20000 + switch (cmd[0]) { + case 0x85: // write enable? + SRAMStatus |= (1<<4); + break; + + case 0x8B: // revert to ROM read mode + SRAMReadWindow = 0; + break; + + case 0x94: // return ID data + { + // TODO: check what the data really is. probably the NAND chip's ID. + // also, might be different between different games or even between different carts. + // this was taken from a Jam with the Band cart. + // not that the game seems to really use this for anything. + u8 iddata[0x30] = + { + 0xEC, 0xF1, 0x00, 0x95, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x9E, 0xA1, 0x51, 0x65, 0x34, 0x35, + 0x30, 0x35, 0x30, 0x31, 0x19, 0x19, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memset(TransferData, 0, TransferLen); + memcpy(TransferData, iddata, std::min(TransferLen, 0x30u)); + } + break; + + case 0xB2: // set window for reading SRAM + { + u32 addr = (cmd[1]<<24) | ((cmd[2]&0xFE)<<16); + + // window is 0x20000 bytes, address is aligned to that boundary + // NAND remains stuck 'busy' forever if this is less than the starting SRAM address + // TODO. + + SRAMReadWindow = addr; + } + break; + case 0xB7: { u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4]; - memset(TransferData, 0, TransferLen); - if (((addr + TransferLen - 1) >> 12) != (addr >> 12)) + if (SRAMReadWindow == 0) { - u32 len1 = 0x1000 - (addr & 0xFFF); - ReadROM_B7(addr, len1, 0); - ReadROM_B7(addr+len1, TransferLen-len1, len1); + memset(TransferData, 0, TransferLen); + + if (((addr + TransferLen - 1) >> 12) != (addr >> 12)) + { + u32 len1 = 0x1000 - (addr & 0xFFF); + ReadROM_B7(addr, len1, 0); + ReadROM_B7(addr+len1, TransferLen-len1, len1); + } + else + ReadROM_B7(addr, TransferLen, 0); } else - ReadROM_B7(addr, TransferLen, 0); - } - break; - - case 0xC0: // SD read - { - u32 sector = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4]; - u64 addr = sector * 0x200ULL; - - if (CartSD) { - fseek(CartSD, addr, SEEK_SET); - fread(TransferData, TransferLen, 1, CartSD); + memset(TransferData, 0xFF, TransferLen); + + u32 sramstart = *(u16*)&ROM[0x96] << 17; + u32 sramend = sramstart + 0x800000; // CHECKME + if (SRAMReadWindow >= sramstart && SRAMReadWindow < sramend && + addr >= SRAMReadWindow && addr < (SRAMReadWindow+0x20000)) + { + // TODO!! + + if (addr == (sramstart+0x7FF800)) + { + u8 iddata[0x10] = {0xEC, 0x00, 0x9E, 0xA1, 0x51, 0x65, 0x34, 0x35, 0x30, 0x35, 0x30, 0x31, 0x19, 0x19, 0x02, 0x0A}; + memcpy(TransferData, iddata, std::min(TransferLen, 0x10u)); + printf("READING ID BLOCK @ %08X\n", addr); + } + } } } break; - case 0xC1: // SD write + case 0xD6: // read NAND status { - TransferDir = 1; + // status bits + // bit5: ready + // bit4: write enable +printf("NAND STATUS %02X\n", SRAMStatus); + for (u32 i = 0; i < TransferLen; i+=4) + *(u32*)&TransferData[i] = SRAMStatus * 0x01010101; } break; default: + /*if (cmd[0] != 0xB8) + printf("shitty command %02X %02X %02X %02X %02X %02X %02X %02X - %08X\n", + cmd[0], cmd[1], cmd[2], cmd[3], + cmd[4], cmd[5], cmd[6], cmd[7], TransferLen);*/ return CartRetail::ROMCommandStart(cmd); } } @@ -1231,7 +1294,7 @@ void CartRetailNAND::ROMCommandFinish(u8* cmd) u8 CartRetailNAND::SPIWrite(u8 val, u32 pos, bool last) { - return val; + return 0xFF; } @@ -1653,6 +1716,11 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct) if (CartIsDSi) CartID |= 0x40000000; + // cart ID for Jam with the Band + // TODO: this kind of ID triggers different KEY1 phase + // (repeats commands a bunch of times) + //CartID = 0x88017FEC; + printf("Cart ID: %08X\n", CartID); u32 arm9base = *(u32*)&CartROM[0x20]; @@ -1712,6 +1780,8 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct) else Cart = new CartRetail(CartROM, CartROMSize); + if (Cart) Cart->Reset(); + // encryption Key1_InitKeycode(false, gamecode, 2, 2); @@ -1864,7 +1934,7 @@ void ROMEndTransfer(u32 param) ROMCnt &= ~(1<<31); if (SPICnt & (1<<14)) - NDS::SetIRQ((NDS::ExMemCnt[0]>>11)&0x1, NDS::IRQ_CartSendDone); + NDS::SetIRQ((NDS::ExMemCnt[0]>>11)&0x1, NDS::IRQ_CartXferDone); /*if (TransferDir == 1) { @@ -2095,11 +2165,11 @@ void WriteROMCnt(u32 val) *(u32*)&TransferCmd[4] = *(u32*)&ROMCommand[4]; } - /*printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", + printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", SPICnt, ROMCnt, TransferCmd[0], TransferCmd[1], TransferCmd[2], TransferCmd[3], TransferCmd[4], TransferCmd[5], TransferCmd[6], TransferCmd[7], - datasize);*/ + datasize); // default is read // commands that do writes will change this @@ -2195,6 +2265,7 @@ void WriteROMCnt(u32 val) u32 cmddelay = 8; // delays are only applied when the WR bit is cleared + // CHECKME: do the delays apply at the end (instead of start) when WR is set? if (!(ROMCnt & (1<<30))) { cmddelay += (ROMCnt & 0x1FFF); diff --git a/src/NDSCart.h b/src/NDSCart.h index e57ed946..cf769f89 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -148,6 +148,9 @@ public: void ROMCommandFinish(u8* cmd); u8 SPIWrite(u8 val, u32 pos, bool last); + +private: + u32 SRAMReadWindow; }; // CartRetailIR -- SPI IR device and SRAM