finish buttoning up the new NDSCart. kiss NDSCart_SRAM goodbye.

This commit is contained in:
Arisotura 2021-04-23 23:44:03 +02:00
parent 5f0e119e34
commit 76e8933a05
3 changed files with 118 additions and 515 deletions

View File

@ -31,443 +31,6 @@
// SRAM TODO: emulate write delays???
namespace NDSCart_SRAM
{
u8* SRAM;
u32 SRAMLength;
char SRAMPath[1024];
bool SRAMFileDirty;
void (*WriteFunc)(u8 val, bool islast);
u32 Hold;
u8 CurCmd;
u32 DataPos;
u8 Data;
u8 StatusReg;
u32 Addr;
void Write_Null(u8 val, bool islast);
void Write_EEPROMTiny(u8 val, bool islast);
void Write_EEPROM(u8 val, bool islast);
void Write_Flash(u8 val, bool islast);
bool Init()
{
SRAM = NULL;
return true;
}
void DeInit()
{
if (SRAM) delete[] SRAM;
}
void Reset()
{
if (SRAM) delete[] SRAM;
SRAM = NULL;
}
void DoSavestate(Savestate* file)
{
file->Section("NDCS");
// we reload the SRAM contents.
// it should be the same file (as it should be the same ROM, duh)
// but the contents may change
//if (!file->Saving && SRAMLength)
// delete[] SRAM;
u32 oldlen = SRAMLength;
file->Var32(&SRAMLength);
if (SRAMLength != oldlen)
{
printf("savestate: VERY BAD!!!! SRAM LENGTH DIFFERENT. %d -> %d\n", oldlen, SRAMLength);
printf("oh well. loading it anyway. adsfgdsf\n");
if (oldlen) delete[] SRAM;
if (SRAMLength) SRAM = new u8[SRAMLength];
}
if (SRAMLength)
{
//if (!file->Saving)
// SRAM = new u8[SRAMLength];
file->VarArray(SRAM, SRAMLength);
}
// SPI status shito
file->Var32(&Hold);
file->Var8(&CurCmd);
file->Var32(&DataPos);
file->Var8(&Data);
file->Var8(&StatusReg);
file->Var32(&Addr);
// SRAMManager might now have an old buffer (or one from the future or alternate timeline!)
if (!file->Saving)
NDSCart_SRAMManager::RequestFlush();
}
void LoadSave(const char* path, u32 type)
{
if (SRAM) delete[] SRAM;
strncpy(SRAMPath, path, 1023);
SRAMPath[1023] = '\0';
FILE* f = Platform::OpenFile(path, "rb");
if (f)
{
fseek(f, 0, SEEK_END);
SRAMLength = (u32)ftell(f);
SRAM = new u8[SRAMLength];
fseek(f, 0, SEEK_SET);
fread(SRAM, SRAMLength, 1, f);
fclose(f);
}
else
{
if (type > 9) type = 0;
int sramlen[] = {0, 512, 8192, 65536, 128*1024, 256*1024, 512*1024, 1024*1024, 8192*1024, 32768*1024};
SRAMLength = sramlen[type];
if (SRAMLength)
{
SRAM = new u8[SRAMLength];
memset(SRAM, 0xFF, SRAMLength);
}
}
SRAMFileDirty = false;
NDSCart_SRAMManager::Setup(path, SRAM, SRAMLength);
switch (SRAMLength)
{
case 512: WriteFunc = Write_EEPROMTiny; break;
case 8192:
case 65536:
case 128*1024: WriteFunc = Write_EEPROM; break;
case 256*1024:
case 512*1024:
case 1024*1024:
case 8192*1024: WriteFunc = Write_Flash; break;
case 32768*1024: WriteFunc = Write_Null; break; // NAND FLASH, handled differently
default:
printf("!! BAD SAVE LENGTH %d\n", SRAMLength);
case 0:
WriteFunc = Write_Null;
break;
}
Hold = 0;
CurCmd = 0;
Data = 0;
StatusReg = 0x00;
}
void RelocateSave(const char* path, bool write)
{
if (!write)
{
LoadSave(path, 0); // lazy
return;
}
strncpy(SRAMPath, path, 1023);
SRAMPath[1023] = '\0';
FILE* f = Platform::OpenFile(path, "wb");
if (!f)
{
printf("NDSCart_SRAM::RelocateSave: failed to create new file. fuck\n");
return;
}
fwrite(SRAM, SRAMLength, 1, f);
fclose(f);
}
u8 Read()
{
return Data;
}
void Write_Null(u8 val, bool islast) {}
void Write_EEPROMTiny(u8 val, bool islast)
{
switch (CurCmd)
{
case 0x02:
case 0x0A:
if (DataPos < 1)
{
Addr = val;
Data = 0;
}
else
{
SRAM[(Addr + ((CurCmd==0x0A)?0x100:0)) & 0x1FF] = val;
Addr++;
}
break;
case 0x03:
case 0x0B:
if (DataPos < 1)
{
Addr = val;
Data = 0;
}
else
{
Data = SRAM[(Addr + ((CurCmd==0x0B)?0x100:0)) & 0x1FF];
Addr++;
}
break;
case 0x9F:
Data = 0xFF;
break;
default:
if (DataPos==0)
printf("unknown tiny EEPROM save command %02X\n", CurCmd);
break;
}
}
void Write_EEPROM(u8 val, bool islast)
{
u32 addrsize = 2;
if (SRAMLength > 65536) addrsize++;
switch (CurCmd)
{
case 0x02:
if (DataPos < addrsize)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
else
{
SRAM[Addr & (SRAMLength-1)] = val;
Addr++;
}
break;
case 0x03:
if (DataPos < addrsize)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
else
{
Data = SRAM[Addr & (SRAMLength-1)];
Addr++;
}
break;
case 0x9F:
Data = 0xFF;
break;
default:
if (DataPos==0)
printf("unknown EEPROM save command %02X\n", CurCmd);
break;
}
}
void Write_Flash(u8 val, bool islast)
{
switch (CurCmd)
{
case 0x02:
if (DataPos < 3)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
else
{
SRAM[Addr & (SRAMLength-1)] = 0;
Addr++;
}
break;
case 0x03:
if (DataPos < 3)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
else
{
Data = SRAM[Addr & (SRAMLength-1)];
Addr++;
}
break;
case 0x0A:
if (DataPos < 3)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
else
{
SRAM[Addr & (SRAMLength-1)] = val;
Addr++;
}
break;
case 0x9F:
Data = 0xFF;
break;
case 0xD8:
if (DataPos < 3)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
if (DataPos == 2)
{
for (u32 i = 0; i < 0x10000; i++)
{
SRAM[Addr & (SRAMLength-1)] = 0;
Addr++;
}
}
break;
case 0xDB:
if (DataPos < 3)
{
Addr <<= 8;
Addr |= val;
Data = 0;
}
if (DataPos == 2)
{
for (u32 i = 0; i < 0x100; i++)
{
SRAM[Addr & (SRAMLength-1)] = 0;
Addr++;
}
}
break;
default:
if (DataPos==0)
printf("unknown Flash save command %02X\n", CurCmd);
break;
}
}
void Write(u8 val, u32 hold)
{
bool islast = false;
if (!hold)
{
if (Hold) islast = true;
else CurCmd = val;
Hold = 0;
}
if (hold && (!Hold))
{
CurCmd = val;
Hold = 1;
Data = 0;
DataPos = 0;
Addr = 0;
//printf("save SPI command %02X\n", CurCmd);
return;
}
switch (CurCmd)
{
case 0x00:
// Pokémon carts have an IR transceiver thing, and send this
// to bypass it and access SRAM.
// TODO: design better
CurCmd = val;
break;
case 0x08:
// see above
// TODO: work out how the IR thing works. emulate it.
Data = 0xAA;
break;
case 0x02:
case 0x03:
case 0x0A:
case 0x0B:
case 0x9F:
case 0xD8:
case 0xDB:
WriteFunc(val, islast);
DataPos++;
break;
case 0x04: // write disable
StatusReg &= ~(1<<1);
Data = 0;
break;
case 0x05: // read status reg
Data = StatusReg;
break;
case 0x06: // write enable
StatusReg |= (1<<1);
Data = 0;
break;
default:
if (DataPos==0)
printf("unknown save SPI command %02X %02X %d\n", CurCmd, val, islast);
break;
}
SRAMFileDirty |= islast && (CurCmd == 0x02 || CurCmd == 0x0A) && (SRAMLength > 0);
}
void FlushSRAMFile()
{
if (!SRAMFileDirty) return;
SRAMFileDirty = false;
NDSCart_SRAMManager::RequestFlush();
}
}
namespace NDSCart
{
@ -646,7 +209,10 @@ void CartCommon::SetupDirectBoot()
void CartCommon::DoSavestate(Savestate* file)
{
// TODO?
file->Section("NDCS");
file->Var32(&CmdEncMode);
file->Var32(&DataEncMode);
}
void CartCommon::LoadSave(const char* path, u32 type)
@ -657,6 +223,11 @@ void CartCommon::RelocateSave(const char* path, bool write)
{
}
int CartCommon::ImportSRAM(const u8* data, u32 length)
{
return 0;
}
void CartCommon::FlushSRAMFile()
{
}
@ -798,7 +369,46 @@ void CartRetail::Reset()
void CartRetail::DoSavestate(Savestate* file)
{
// TODO?
CartCommon::DoSavestate(file);
// we reload the SRAM contents.
// it should be the same file (as it should be the same ROM, duh)
// but the contents may change
//if (!file->Saving && SRAMLength)
// delete[] SRAM;
u32 oldlen = SRAMLength;
file->Var32(&SRAMLength);
if (SRAMLength != oldlen)
{
printf("savestate: VERY BAD!!!! SRAM LENGTH DIFFERENT. %d -> %d\n", oldlen, SRAMLength);
printf("oh well. loading it anyway. adsfgdsf\n");
if (oldlen) delete[] SRAM;
if (SRAMLength) SRAM = new u8[SRAMLength];
}
if (SRAMLength)
{
//if (!file->Saving)
// SRAM = new u8[SRAMLength];
file->VarArray(SRAM, SRAMLength);
}
// SPI status shito
file->Var8(&SRAMCmd);
file->Var32(&SRAMAddr);
file->Var8(&SRAMStatus);
// SRAMManager might now have an old buffer (or one from the future or alternate timeline!)
if (!file->Saving)
{
SRAMFileDirty = false;
NDSCart_SRAMManager::RequestFlush();
}
}
void CartRetail::LoadSave(const char* path, u32 type)
@ -874,6 +484,19 @@ void CartRetail::RelocateSave(const char* path, bool write)
fclose(f);
}
int CartRetail::ImportSRAM(const u8* data, u32 length)
{
memcpy(SRAM, data, std::min(length, SRAMLength));
FILE* f = Platform::OpenFile(SRAMPath, "wb");
if (f)
{
fwrite(SRAM, SRAMLength, 1, f);
fclose(f);
}
return length - SRAMLength;
}
void CartRetail::FlushSRAMFile()
{
if (!SRAMFileDirty) return;
@ -1201,30 +824,28 @@ void CartRetailNAND::Reset()
void CartRetailNAND::DoSavestate(Savestate* file)
{
// TODO?
CartRetail::DoSavestate(file);
file->Var32(&SRAMBase);
file->Var32(&SRAMWindow);
file->VarArray(SRAMWriteBuffer, 0x800);
file->Var32(&SRAMWritePos);
if (!file->Saving)
BuildSRAMID();
}
void CartRetailNAND::LoadSave(const char* path, u32 type)
{
CartRetail::LoadSave(path, type);
BuildSRAMID();
}
// the last 128K of the SRAM are read-only.
// most of it is FF, except for the NAND ID at the beginning
// of the last 0x800 bytes.
if (SRAMLength > 0x20000)
{
memset(&SRAM[SRAMLength - 0x20000], 0xFF, 0x20000);
// TODO: check what the data is all about!
// this was pulled from a Jam with the Band cart. may be different on other carts.
// WarioWare DIY may have different data or not have this at all.
// the ID data is also found in the response to command 94, and JwtB checks it.
// WarioWare doesn't seem to care.
// there is also more data here, but JwtB doesn't seem to care.
u8 iddata[0x10] = {0xEC, 0x00, 0x9E, 0xA1, 0x51, 0x65, 0x34, 0x35, 0x30, 0x35, 0x30, 0x31, 0x19, 0x19, 0x02, 0x0A};
memcpy(&SRAM[SRAMLength - 0x800], iddata, 16);
}
int CartRetailNAND::ImportSRAM(const u8* data, u32 length)
{
CartRetail::ImportSRAM(data, length);
BuildSRAMID();
}
int CartRetailNAND::ROMCommandStart(u8* cmd, u8* data, u32 len)
@ -1386,6 +1007,27 @@ u8 CartRetailNAND::SPIWrite(u8 val, u32 pos, bool last)
return 0xFF;
}
void CartRetailNAND::BuildSRAMID()
{
// the last 128K of the SRAM are read-only.
// most of it is FF, except for the NAND ID at the beginning
// of the last 0x800 bytes.
if (SRAMLength > 0x20000)
{
memset(&SRAM[SRAMLength - 0x20000], 0xFF, 0x20000);
// TODO: check what the data is all about!
// this was pulled from a Jam with the Band cart. may be different on other carts.
// WarioWare DIY may have different data or not have this at all.
// the ID data is also found in the response to command 94, and JwtB checks it.
// WarioWare doesn't seem to care.
// there is also more data here, but JwtB doesn't seem to care.
u8 iddata[0x10] = {0xEC, 0x00, 0x9E, 0xA1, 0x51, 0x65, 0x34, 0x35, 0x30, 0x35, 0x30, 0x31, 0x19, 0x19, 0x02, 0x0A};
memcpy(&SRAM[SRAMLength - 0x800], iddata, 16);
}
}
CartRetailIR::CartRetailIR(u8* rom, u32 len, u32 chipid, u32 irversion) : CartRetail(rom, len, chipid)
{
@ -1405,7 +1047,9 @@ void CartRetailIR::Reset()
void CartRetailIR::DoSavestate(Savestate* file)
{
// TODO?
CartRetail::DoSavestate(file);
file->Var8(&IRCmd);
}
u8 CartRetailIR::SPIWrite(u8 val, u32 pos, bool last)
@ -1445,7 +1089,7 @@ void CartRetailBT::Reset()
void CartRetailBT::DoSavestate(Savestate* file)
{
// TODO?
CartRetail::DoSavestate(file);
}
u8 CartRetailBT::SPIWrite(u8 val, u32 pos, bool last)
@ -1493,7 +1137,7 @@ void CartHomebrew::Reset()
void CartHomebrew::DoSavestate(Savestate* file)
{
// TODO?
CartCommon::DoSavestate(file);
}
int CartHomebrew::ROMCommandStart(u8* cmd, u8* data, u32 len)
@ -1729,6 +1373,10 @@ void DoSavestate(Savestate* file)
file->Var16(&SPICnt);
file->Var32(&ROMCnt);
file->Var8(&SPIData);
file->Var32(&SPIDataPos);
file->Bool32(&SPIHold);
file->VarArray(ROMCommand, 8);
file->Var32(&ROMData);
@ -2002,16 +1650,7 @@ void FlushSRAMFile()
int ImportSRAM(const u8* data, u32 length)
{
/*memcpy(NDSCart_SRAM::SRAM, data, std::min(length, NDSCart_SRAM::SRAMLength));
FILE* f = Platform::OpenFile(NDSCart_SRAM::SRAMPath, "wb");
if (f)
{
fwrite(NDSCart_SRAM::SRAM, NDSCart_SRAM::SRAMLength, 1, f);
fclose(f);
}
return length - NDSCart_SRAM::SRAMLength;*/
// TODO!!!!
if (Cart) return Cart->ImportSRAM(data, length);
return 0;
}

View File

@ -21,47 +21,6 @@
#include "types.h"
// required class design
// * interface bits (init/reset/writeregs) static
// * cart-specific bits in class
// * responding to cart commands
// * forwarding response data
// * forwarding cart IRQ (for ie. pokémon typing cart, or when ejecting cart)
// * responding to SPI commands
// * saveRAM management (interface between emulated SRAM interface and save file)
// * DLDI shito (for homebrew)
/*class NDSCart
{
public:
static bool Init();
static void DeInit();
static void Reset;
static void DoSavestate(Savestate* file);
static bool LoadROM(const char* path, const char* sram, bool direct);
static bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct);
// direct boot support
static void DecryptSecureArea(u8* out);
static u16 SPICnt;
static u32 ROMCnt;
static u8 ROMCommand[8];
static bool CartInserted;
static u8* CartROM;
static u32 CartROMSize;
static u32 CartID;
//
private:
// private parts go here
};*/
namespace NDSCart
{
@ -79,6 +38,7 @@ public:
virtual void LoadSave(const char* path, u32 type);
virtual void RelocateSave(const char* path, bool write);
virtual int ImportSRAM(const u8* data, u32 length);
virtual void FlushSRAMFile();
virtual int ROMCommandStart(u8* cmd, u8* data, u32 len);
@ -96,8 +56,8 @@ protected:
u32 ChipID;
bool IsDSi;
int CmdEncMode;
int DataEncMode;
u32 CmdEncMode;
u32 DataEncMode;
};
// CartRetail -- regular retail cart (ROM, SPI SRAM)
@ -113,6 +73,7 @@ public:
virtual void LoadSave(const char* path, u32 type) override;
virtual void RelocateSave(const char* path, bool write) override;
virtual int ImportSRAM(const u8* data, u32 length) override;
virtual void FlushSRAMFile() override;
virtual int ROMCommandStart(u8* cmd, u8* data, u32 len) override;
@ -150,6 +111,7 @@ public:
void DoSavestate(Savestate* file);
void LoadSave(const char* path, u32 type) override;
int ImportSRAM(const u8* data, u32 length) override;
int ROMCommandStart(u8* cmd, u8* data, u32 len) override;
void ROMCommandFinish(u8* cmd, u8* data, u32 len) override;
@ -157,6 +119,8 @@ public:
u8 SPIWrite(u8 val, u32 pos, bool last) override;
private:
void BuildSRAMID();
u32 SRAMBase;
u32 SRAMWindow;

View File

@ -22,8 +22,8 @@
#include <stdio.h>
#include "types.h"
#define SAVESTATE_MAJOR 7
#define SAVESTATE_MINOR 1
#define SAVESTATE_MAJOR 8
#define SAVESTATE_MINOR 0
class Savestate
{