aboutsummaryrefslogtreecommitdiff
path: root/src/NDSCart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/NDSCart.cpp')
-rw-r--r--src/NDSCart.cpp460
1 files changed, 209 insertions, 251 deletions
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 3d231ac..940827f 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -22,11 +22,11 @@
#include "DSi.h"
#include "NDSCart.h"
#include "ARM.h"
+#include "CRC32.h"
#include "DSi_AES.h"
#include "Platform.h"
#include "ROMList.h"
#include "melonDLDI.h"
-#include "NDSCart_SRAMManager.h"
namespace NDSCart
@@ -51,12 +51,9 @@ u32 TransferDir;
u8 TransferCmd[8];
bool CartInserted;
-char CartName[256];
u8* CartROM;
u32 CartROMSize;
u32 CartID;
-bool CartIsHomebrew;
-bool CartIsDSi;
NDSHeader Header;
NDSBanner Banner;
@@ -135,13 +132,24 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod)
}
}
+void Key1_LoadKeyBuf(bool dsi)
+{
+ // it is possible that this gets called before the BIOSes are loaded
+ // so we will read from the BIOS files directly
+
+ std::string path = Platform::GetConfigString(dsi ? Platform::DSi_BIOS7Path : Platform::BIOS7Path);
+ FILE* f = Platform::OpenLocalFile(path, "rb");
+ if (f)
+ {
+ fseek(f, dsi ? 0xC6D0 : 0x0030, SEEK_SET);
+ fread(Key1_KeyBuf, 0x1048, 1, f);
+ fclose(f);
+ }
+}
+
void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod)
{
- // TODO: source the key data from different possible places
- if (dsi && NDS::ConsoleType==1)
- memcpy(Key1_KeyBuf, &DSi::ARM7iBIOS[0xC6D0], 0x1048); // hax
- else
- memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax
+ Key1_LoadKeyBuf(dsi);
u32 keycode[3] = {idcode, idcode>>1, idcode<<1};
if (level >= 1) Key1_ApplyKeycode(keycode, mod);
@@ -191,6 +199,22 @@ CartCommon::~CartCommon()
{
}
+u32 CartCommon::Checksum()
+{
+ u32 crc = CRC32(ROM, 0x40);
+
+ crc = CRC32(&ROM[Header.ARM9ROMOffset], Header.ARM9Size, crc);
+ crc = CRC32(&ROM[Header.ARM7ROMOffset], Header.ARM7Size, crc);
+
+ if (IsDSi)
+ {
+ crc = CRC32(&ROM[Header.DSiARM9iROMOffset], Header.DSiARM9iSize, crc);
+ crc = CRC32(&ROM[Header.DSiARM7iROMOffset], Header.DSiARM7iSize, crc);
+ }
+
+ return crc;
+}
+
void CartCommon::Reset()
{
CmdEncMode = 0;
@@ -198,11 +222,11 @@ void CartCommon::Reset()
DSiMode = false;
}
-void CartCommon::SetupDirectBoot()
+void CartCommon::SetupDirectBoot(std::string romname)
{
CmdEncMode = 2;
DataEncMode = 2;
- DSiMode = IsDSi && NDS::ConsoleType==1;
+ DSiMode = IsDSi && (NDS::ConsoleType==1);
}
void CartCommon::DoSavestate(Savestate* file)
@@ -214,20 +238,11 @@ void CartCommon::DoSavestate(Savestate* file)
file->Bool32(&DSiMode);
}
-void CartCommon::LoadSave(const char* path, u32 type)
+void CartCommon::SetupSave(u32 type)
{
}
-void CartCommon::RelocateSave(const char* path, bool write)
-{
-}
-
-int CartCommon::ImportSRAM(const u8* data, u32 length)
-{
- return 0;
-}
-
-void CartCommon::FlushSRAMFile()
+void CartCommon::LoadSave(const u8* savedata, u32 savelen)
{
}
@@ -392,11 +407,7 @@ void CartRetail::DoSavestate(Savestate* file)
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;
+ // it should be the same file, but the contents may change
u32 oldlen = SRAMLength;
@@ -407,13 +418,11 @@ void CartRetail::DoSavestate(Savestate* file)
printf("oh well. loading it anyway. adsfgdsf\n");
if (oldlen) delete[] SRAM;
+ SRAM = nullptr;
if (SRAMLength) SRAM = new u8[SRAMLength];
}
if (SRAMLength)
{
- //if (!file->Saving)
- // SRAM = new u8[SRAMLength];
-
file->VarArray(SRAM, SRAMLength);
}
@@ -423,20 +432,14 @@ void CartRetail::DoSavestate(Savestate* file)
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();
- }
+ if ((!file->Saving) && SRAM)
+ Platform::WriteNDSSave(SRAM, SRAMLength, 0, SRAMLength);
}
-void CartRetail::LoadSave(const char* path, u32 type)
+void CartRetail::SetupSave(u32 type)
{
if (SRAM) delete[] SRAM;
-
- strncpy(SRAMPath, path, 1023);
- SRAMPath[1023] = '\0';
+ SRAM = nullptr;
if (type > 10) type = 0;
int sramlen[] =
@@ -455,18 +458,6 @@ void CartRetail::LoadSave(const char* path, u32 type)
memset(SRAM, 0xFF, SRAMLength);
}
- FILE* f = Platform::OpenFile(path, "rb");
- if (f)
- {
- fseek(f, 0, SEEK_SET);
- fread(SRAM, 1, SRAMLength, f);
-
- fclose(f);
- }
-
- SRAMFileDirty = false;
- NDSCart_SRAMManager::Setup(path, SRAM, SRAMLength);
-
switch (type)
{
case 1: SRAMType = 1; break; // EEPROM, small
@@ -483,47 +474,13 @@ void CartRetail::LoadSave(const char* path, u32 type)
}
}
-void CartRetail::RelocateSave(const char* path, bool write)
+void CartRetail::LoadSave(const u8* savedata, u32 savelen)
{
- 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;
- }
+ if (!SRAM) return;
- fwrite(SRAM, SRAMLength, 1, f);
- 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;
-
- SRAMFileDirty = false;
- NDSCart_SRAMManager::RequestFlush();
+ u32 len = std::min(savelen, SRAMLength);
+ memcpy(SRAM, savedata, len);
+ Platform::WriteNDSSave(savedata, len, 0, len);
}
int CartRetail::ROMCommandStart(u8* cmd, u8* data, u32 len)
@@ -624,6 +581,7 @@ u8 CartRetail::SRAMWrite_EEPROMTiny(u8 val, u32 pos, bool last)
if (pos < 2)
{
SRAMAddr = val;
+ SRAMFirstAddr = SRAMAddr;
}
else
{
@@ -631,11 +589,15 @@ u8 CartRetail::SRAMWrite_EEPROMTiny(u8 val, u32 pos, bool last)
if (SRAMStatus & (1<<1))
{
SRAM[(SRAMAddr + ((SRAMCmd==0x0A)?0x100:0)) & 0x1FF] = val;
- SRAMFileDirty |= last;
}
SRAMAddr++;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ (SRAMFirstAddr + ((SRAMCmd==0x0A)?0x100:0)) & 0x1FF, SRAMAddr-SRAMFirstAddr);
+ }
return 0;
case 0x03: // read low
@@ -683,6 +645,7 @@ u8 CartRetail::SRAMWrite_EEPROM(u8 val, u32 pos, bool last)
{
SRAMAddr <<= 8;
SRAMAddr |= val;
+ SRAMFirstAddr = SRAMAddr;
}
else
{
@@ -690,11 +653,15 @@ u8 CartRetail::SRAMWrite_EEPROM(u8 val, u32 pos, bool last)
if (SRAMStatus & (1<<1))
{
SRAM[SRAMAddr & (SRAMLength-1)] = val;
- SRAMFileDirty |= last;
}
SRAMAddr++;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ SRAMFirstAddr & (SRAMLength-1), SRAMAddr-SRAMFirstAddr);
+ }
return 0;
case 0x03: // read
@@ -735,6 +702,7 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
{
SRAMAddr <<= 8;
SRAMAddr |= val;
+ SRAMFirstAddr = SRAMAddr;
}
else
{
@@ -742,11 +710,15 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
{
// CHECKME: should it be &=~val ??
SRAM[SRAMAddr & (SRAMLength-1)] = 0;
- SRAMFileDirty |= last;
}
SRAMAddr++;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ SRAMFirstAddr & (SRAMLength-1), SRAMAddr-SRAMFirstAddr);
+ }
return 0;
case 0x03: // read
@@ -768,17 +740,22 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
{
SRAMAddr <<= 8;
SRAMAddr |= val;
+ SRAMFirstAddr = SRAMAddr;
}
else
{
if (SRAMStatus & (1<<1))
{
SRAM[SRAMAddr & (SRAMLength-1)] = val;
- SRAMFileDirty |= last;
}
SRAMAddr++;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ SRAMFirstAddr & (SRAMLength-1), SRAMAddr-SRAMFirstAddr);
+ }
return 0;
case 0x0B: // fast read
@@ -809,6 +786,7 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
{
SRAMAddr <<= 8;
SRAMAddr |= val;
+ SRAMFirstAddr = SRAMAddr;
}
if ((pos == 3) && (SRAMStatus & (1<<1)))
{
@@ -817,9 +795,13 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
SRAM[SRAMAddr & (SRAMLength-1)] = 0;
SRAMAddr++;
}
- SRAMFileDirty = true;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ SRAMFirstAddr & (SRAMLength-1), SRAMAddr-SRAMFirstAddr);
+ }
return 0;
case 0xDB: // page erase
@@ -827,6 +809,7 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
{
SRAMAddr <<= 8;
SRAMAddr |= val;
+ SRAMFirstAddr = SRAMAddr;
}
if ((pos == 3) && (SRAMStatus & (1<<1)))
{
@@ -835,9 +818,13 @@ u8 CartRetail::SRAMWrite_FLASH(u8 val, u32 pos, bool last)
SRAM[SRAMAddr & (SRAMLength-1)] = 0;
SRAMAddr++;
}
- SRAMFileDirty = true;
}
- if (last) SRAMStatus &= ~(1<<1);
+ if (last)
+ {
+ SRAMStatus &= ~(1<<1);
+ Platform::WriteNDSSave(SRAM, SRAMLength,
+ SRAMFirstAddr & (SRAMLength-1), SRAMAddr-SRAMFirstAddr);
+ }
return 0;
default:
@@ -884,19 +871,12 @@ void CartRetailNAND::DoSavestate(Savestate* file)
BuildSRAMID();
}
-void CartRetailNAND::LoadSave(const char* path, u32 type)
+void CartRetailNAND::LoadSave(const u8* savedata, u32 savelen)
{
- CartRetail::LoadSave(path, type);
+ CartRetail::LoadSave(savedata, savelen);
BuildSRAMID();
}
-int CartRetailNAND::ImportSRAM(const u8* data, u32 length)
-{
- int ret = CartRetail::ImportSRAM(data, length);
- BuildSRAMID();
- return ret;
-}
-
int CartRetailNAND::ROMCommandStart(u8* cmd, u8* data, u32 len)
{
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(cmd, data, len);
@@ -926,7 +906,7 @@ int CartRetailNAND::ROMCommandStart(u8* cmd, u8* data, u32 len)
if (SRAMLength && SRAMAddr < (SRAMBase+SRAMLength-0x20000))
{
memcpy(&SRAM[SRAMAddr - SRAMBase], SRAMWriteBuffer, 0x800);
- SRAMFileDirty = true;
+ Platform::WriteNDSSave(SRAM, SRAMLength, SRAMAddr - SRAMBase, 0x800);
}
SRAMAddr = 0;
@@ -1164,8 +1144,30 @@ u8 CartRetailBT::SPIWrite(u8 val, u32 pos, bool last)
CartHomebrew::CartHomebrew(u8* rom, u32 len, u32 chipid) : CartCommon(rom, len, chipid)
{
+ SD = nullptr;
+}
+
+CartHomebrew::~CartHomebrew()
+{
+ if (SD)
+ {
+ SD->Close();
+ delete SD;
+ }
+}
+
+void CartHomebrew::Reset()
+{
+ CartCommon::Reset();
+
ReadOnly = Platform::GetConfigBool(Platform::DLDI_ReadOnly);
+ if (SD)
+ {
+ SD->Close();
+ delete SD;
+ }
+
if (Platform::GetConfigBool(Platform::DLDI_Enable))
{
std::string folderpath;
@@ -1185,29 +1187,15 @@ CartHomebrew::CartHomebrew(u8* rom, u32 len, u32 chipid) : CartCommon(rom, len,
SD = nullptr;
}
-CartHomebrew::~CartHomebrew()
+void CartHomebrew::SetupDirectBoot(std::string romname)
{
- if (SD)
- {
- SD->Close();
- delete SD;
- }
-}
-
-void CartHomebrew::Reset()
-{
- CartCommon::Reset();
-}
-
-void CartHomebrew::SetupDirectBoot()
-{
- CartCommon::SetupDirectBoot();
+ CartCommon::SetupDirectBoot(romname);
if (SD)
{
// add the ROM to the SD volume
- if (!SD->InjectFile(CartName, CartROM, CartROMSize))
+ if (!SD->InjectFile(romname, CartROM, CartROMSize))
return;
// setup argv command line
@@ -1216,7 +1204,7 @@ void CartHomebrew::SetupDirectBoot()
int argvlen;
strncpy(argv, "fat:/", 511);
- strncat(argv, CartName, 511);
+ strncat(argv, romname.c_str(), 511);
argvlen = strlen(argv);
void (*writefn)(u32,u32) = (NDS::ConsoleType==1) ? DSi::ARM9Write32 : NDS::ARM9Write32;
@@ -1441,6 +1429,7 @@ void CartHomebrew::ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset)
bool Init()
{
+ CartInserted = false;
CartROM = nullptr;
Cart = nullptr;
@@ -1455,17 +1444,6 @@ void DeInit()
void Reset()
{
- CartInserted = false;
- if (CartROM) delete[] CartROM;
- CartROM = nullptr;
- CartROMSize = 0;
- CartID = 0;
- CartIsHomebrew = false;
- CartIsDSi = false;
-
- if (Cart) delete Cart;
- Cart = nullptr;
-
ResetCart();
}
@@ -1494,6 +1472,30 @@ void DoSavestate(Savestate* file)
// (TODO: system to verify that indeed the right ROM is loaded)
// (what to CRC? whole ROM? code binaries? latter would be more convenient for ie. romhaxing)
+ u32 carttype = 0;
+ u32 cartchk = 0;
+ if (Cart)
+ {
+ carttype = Cart->Type();
+ cartchk = Cart->Checksum();
+ }
+
+ if (file->Saving)
+ {
+ file->Var32(&carttype);
+ file->Var32(&cartchk);
+ }
+ else
+ {
+ u32 savetype;
+ file->Var32(&savetype);
+ if (savetype != carttype) return;
+
+ u32 savechk;
+ file->Var32(&savechk);
+ if (savechk != cartchk) return;
+ }
+
if (Cart) Cart->DoSavestate(file);
}
@@ -1542,11 +1544,6 @@ bool ReadROMParams(u32 gamecode, ROMListEntry* params)
void DecryptSecureArea(u8* out)
{
- // TODO: source decryption data from different possible sources
- // * original DS-mode ARM7 BIOS has the key data at 0x30
- // * .srl ROMs (VC dumps) have encrypted secure areas but have precomputed
- // decryption data at 0x1000 (and at the beginning of the DSi region if any)
-
u32 gamecode = (u32)Header.GameCode[3] << 24 |
(u32)Header.GameCode[2] << 16 |
(u32)Header.GameCode[1] << 8 |
@@ -1576,8 +1573,28 @@ void DecryptSecureArea(u8* out)
}
}
-bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
+bool LoadROM(const u8* romdata, u32 romlen)
{
+ if (CartInserted)
+ EjectCart();
+
+ CartROMSize = 0x200;
+ while (CartROMSize < romlen)
+ CartROMSize <<= 1;
+
+ try
+ {
+ CartROM = new u8[CartROMSize];
+ }
+ catch (const std::bad_alloc& e)
+ {
+ printf("NDSCart: failed to allocate memory for ROM (%d bytes)\n", CartROMSize);
+ return false;
+ }
+
+ memset(CartROM, 0, CartROMSize);
+ memcpy(CartROM, romdata, romlen);
+
memcpy(&Header, CartROM, sizeof(Header));
memcpy(&Banner, CartROM + Header.BannerOffset, sizeof(Banner));
@@ -1589,7 +1606,10 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
(u32)Header.GameCode[0];
u8 unitcode = Header.UnitCode;
- CartIsDSi = (unitcode & 0x02) != 0;
+ bool dsi = (unitcode & 0x02) != 0;
+
+ u32 arm9base = Header.ARM9ROMOffset;
+ bool homebrew = (arm9base < 0x4000) || (gamecode == 0x23232323);
ROMListEntry romparams;
if (!ReadROMParams(gamecode, &romparams))
@@ -1599,7 +1619,7 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
romparams.GameCode = gamecode;
romparams.ROMSize = CartROMSize;
- if (*(u32*)&CartROM[0x20] < 0x4000)
+ if (homebrew)
romparams.SaveMemType = 0; // no saveRAM for homebrew
else
romparams.SaveMemType = 2; // assume EEPROM 64k (TODO FIXME)
@@ -1607,7 +1627,8 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
else
printf("ROM entry: %08X %08X\n", romparams.ROMSize, romparams.SaveMemType);
- if (romparams.ROMSize != filelength) printf("!! bad ROM size %d (expected %d) rounded to %d\n", filelength, romparams.ROMSize, CartROMSize);
+ if (romparams.ROMSize != romlen)
+ printf("!! bad ROM size %d (expected %d) rounded to %d\n", romlen, romparams.ROMSize, CartROMSize);
// generate a ROM ID
// note: most games don't check the actual value
@@ -1622,7 +1643,7 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
if (romparams.SaveMemType >= 8 && romparams.SaveMemType <= 10)
CartID |= 0x08000000; // NAND flag
- if (CartIsDSi)
+ if (dsi)
CartID |= 0x40000000;
// cart ID for Jam with the Band
@@ -1633,34 +1654,24 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
printf("Cart ID: %08X\n", CartID);
- u32 arm9base = *(u32*)&CartROM[0x20];
-
- if (arm9base < 0x8000)
+ if (arm9base >= 0x4000 && arm9base < 0x8000)
{
- if (arm9base >= 0x4000)
+ // reencrypt secure area if needed
+ if (*(u32*)&CartROM[arm9base] == 0xE7FFDEFF && *(u32*)&CartROM[arm9base+0x10] != 0xE7FFDEFF)
{
- // reencrypt secure area if needed
- if (*(u32*)&CartROM[arm9base] == 0xE7FFDEFF && *(u32*)&CartROM[arm9base+0x10] != 0xE7FFDEFF)
- {
- printf("Re-encrypting cart secure area\n");
+ printf("Re-encrypting cart secure area\n");
- strncpy((char*)&CartROM[arm9base], "encryObj", 8);
+ strncpy((char*)&CartROM[arm9base], "encryObj", 8);
- Key1_InitKeycode(false, gamecode, 3, 2);
- for (u32 i = 0; i < 0x800; i += 8)
- Key1_Encrypt((u32*)&CartROM[arm9base + i]);
+ Key1_InitKeycode(false, gamecode, 3, 2);
+ for (u32 i = 0; i < 0x800; i += 8)
+ Key1_Encrypt((u32*)&CartROM[arm9base + i]);
- Key1_InitKeycode(false, gamecode, 2, 2);
- Key1_Encrypt((u32*)&CartROM[arm9base]);
- }
+ Key1_InitKeycode(false, gamecode, 2, 2);
+ Key1_Encrypt((u32*)&CartROM[arm9base]);
}
}
- if ((arm9base < 0x4000) || (gamecode == 0x23232323))
- {
- CartIsHomebrew = true;
- }
-
CartInserted = true;
u32 irversion = 0;
@@ -1672,7 +1683,7 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
irversion = 2; // Pokémon HG/SS, B/W, B2/W2
}
- if (CartIsHomebrew)
+ if (homebrew)
Cart = new CartHomebrew(CartROM, CartROMSize, CartID);
else if (CartID & 0x08000000)
Cart = new CartRetailNAND(CartROM, CartROMSize, CartID);
@@ -1684,99 +1695,44 @@ bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
Cart = new CartRetail(CartROM, CartROMSize, CartID);
if (Cart)
- {
Cart->Reset();
- if (direct)
- {
- NDS::SetupDirectBoot();
- Cart->SetupDirectBoot();
- }
- }
- // encryption
- Key1_InitKeycode(false, gamecode, 2, 2);
-
- // save
- printf("Save file: %s\n", sram);
- if (Cart) Cart->LoadSave(sram, romparams.SaveMemType);
+ if (Cart && romparams.SaveMemType > 0)
+ Cart->SetupSave(romparams.SaveMemType);
return true;
}
-bool LoadROM(const char* path, const char* sram, bool direct)
+void LoadSave(const u8* savedata, u32 savelen)
{
- // TODO: streaming mode? for really big ROMs or systems with limited RAM
- // for now we're lazy
- // also TODO: validate what we're loading!!
-
- FILE* f = Platform::OpenFile(path, "rb");
- if (!f)
- {
- return false;
- }
-
- NDS::Reset();
-
- char* romname = strrchr((char*)path, '/');
- if (!romname)
- {
- romname = strrchr((char*)path, '\\');
- if (!romname)
- romname = (char*)&path[-1];
- }
- romname++;
- strncpy(CartName, romname, 255); CartName[255] = '\0';
-
- fseek(f, 0, SEEK_END);
- u32 len = (u32)ftell(f);
-
- CartROMSize = 0x200;
- while (CartROMSize < len)
- CartROMSize <<= 1;
-
- CartROM = new u8[CartROMSize];
- memset(CartROM, 0, CartROMSize);
- fseek(f, 0, SEEK_SET);
- fread(CartROM, 1, len, f);
-
- fclose(f);
-
- return LoadROMCommon(len, sram, direct);
+ if (Cart)
+ Cart->LoadSave(savedata, savelen);
}
-bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct)
+void SetupDirectBoot(std::string romname)
{
- NDS::Reset();
-
- // TODO: make it more meaningful?
- strncpy(CartName, "rom.nds", 256);
-
- u32 len = filelength;
- CartROMSize = 0x200;
- while (CartROMSize < len)
- CartROMSize <<= 1;
-
- CartROM = new u8[CartROMSize];
- memset(CartROM, 0, CartROMSize);
- memcpy(CartROM, romdata, filelength);
-
- return LoadROMCommon(filelength, sram, direct);
+ if (Cart)
+ Cart->SetupDirectBoot(romname);
}
-void RelocateSave(const char* path, bool write)
+void EjectCart()
{
- if (Cart) Cart->RelocateSave(path, write);
-}
+ if (!CartInserted) return;
-void FlushSRAMFile()
-{
- if (Cart) Cart->FlushSRAMFile();
-}
+ // ejecting the cart triggers the gamecard IRQ
+ NDS::SetIRQ(0, NDS::IRQ_CartIREQMC);
+ NDS::SetIRQ(1, NDS::IRQ_CartIREQMC);
-int ImportSRAM(const u8* data, u32 length)
-{
- if (Cart) return Cart->ImportSRAM(data, length);
- return 0;
+ if (Cart) delete Cart;
+ Cart = nullptr;
+
+ CartInserted = false;
+ if (CartROM) delete[] CartROM;
+ CartROM = nullptr;
+ CartROMSize = 0;
+ CartID = 0;
+
+ // CHECKME: does an eject imply anything for the ROM/SPI transfer registers?
}
void ResetCart()
@@ -1880,6 +1836,8 @@ void WriteROMCnt(u32 val)
*(u32*)&TransferCmd[0] = *(u32*)&ROMCommand[0];
*(u32*)&TransferCmd[4] = *(u32*)&ROMCommand[4];
+ memset(TransferData, 0xFF, TransferLen);
+
/*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],