aboutsummaryrefslogtreecommitdiff
path: root/NDSCart.cpp
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-02-03 16:57:31 +0100
committerStapleButter <thetotalworm@gmail.com>2017-02-03 16:57:31 +0100
commitf4335b92927ec3ba0eb3675eb1c4a5c80bb0a05d (patch)
treec38d271abf37386fcf872f11c81b9d254e247804 /NDSCart.cpp
parent7e9972e0378ca7a5499d16511f3a3b169d6a62e1 (diff)
better save support. not hardcoded filename, support for non-tiny EEPROM and Flash, attempt at autodetecting the right memory type.
Diffstat (limited to 'NDSCart.cpp')
-rw-r--r--NDSCart.cpp344
1 files changed, 311 insertions, 33 deletions
diff --git a/NDSCart.cpp b/NDSCart.cpp
index 145f627..9a2e094 100644
--- a/NDSCart.cpp
+++ b/NDSCart.cpp
@@ -28,7 +28,14 @@ namespace NDSCart_SRAM
u8* SRAM;
u32 SRAMLength;
-u32 AddrLength;
+char SRAMPath[256];
+
+void (*WriteFunc)(u8 val, bool islast);
+
+u32 Discover_MemoryType;
+u32 Discover_Likeliness;
+u8* Discover_Buffer;
+u32 Discover_DataPos;
u32 Hold;
u8 CurCmd;
@@ -39,6 +46,13 @@ 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);
+void Write_Discover(u8 val, bool islast);
+
+
void Init()
{
SRAM = NULL;
@@ -46,9 +60,17 @@ void Init()
void Reset()
{
+ //
+}
+
+void LoadSave(char* path)
+{
if (SRAM) delete[] SRAM;
- FILE* f = fopen("rom/nsmb.sav", "rb"); // TODO: NOT HARDCODE THE FILENAME!!!
+ strncpy(SRAMPath, path, 255);
+ SRAMPath[255] = '\0';
+
+ FILE* f = fopen(path, "rb");
if (f)
{
fseek(f, 0, SEEK_END);
@@ -62,17 +84,29 @@ void Reset()
switch (SRAMLength)
{
- case 8192: AddrLength = 2; break;
+ case 512: WriteFunc = Write_EEPROMTiny; break;
+ case 8192:
+ case 65536: WriteFunc = Write_EEPROM; break;
+ case 256*1024:
+ case 512*1024:
+ case 1024*1024:
+ case 8192*1024: WriteFunc = Write_Flash; break;
default:
printf("!! BAD SAVE LENGTH %d\n", SRAMLength);
- AddrLength = 2;
+ WriteFunc = Write_Null;
break;
}
}
else
{
- // TODO: autodetect save type
SRAMLength = 0;
+ WriteFunc = Write_Discover;
+ Discover_MemoryType = 2;
+ Discover_Likeliness = 0;
+
+ Discover_DataPos = 0;
+ Discover_Buffer = new u8[256*1024];
+ memset(Discover_Buffer, 0, 256*1024);
}
Hold = 0;
@@ -86,10 +120,250 @@ u8 Read()
return Data;
}
+void SetMemoryType()
+{
+ switch (Discover_MemoryType)
+ {
+ case 1:
+ printf("Save memory type: EEPROM 4k\n");
+ WriteFunc = Write_EEPROMTiny;
+ SRAMLength = 512;
+ break;
+
+ case 2:
+ printf("Save memory type: EEPROM 64k\n");
+ WriteFunc = Write_EEPROM;
+ SRAMLength = 8192;
+ break;
+
+ case 3:
+ printf("Save memory type: EEPROM 512k\n");
+ WriteFunc = Write_EEPROM;
+ SRAMLength = 65536;
+ break;
+
+ case 4:
+ printf("Save memory type: Flash. Hope the size is 256K.\n");
+ WriteFunc = Write_Flash;
+ SRAMLength = 256*1024;
+ break;
+
+ case 5:
+ printf("Save memory type: ...something else\n");
+ WriteFunc = Write_Null;
+ SRAMLength = 0;
+ break;
+ }
+
+ if (!SRAMLength)
+ return;
+
+ SRAM = new u8[SRAMLength];
+
+ // replay writes that occured during discovery
+ u8 prev_cmd = CurCmd;
+ u32 pos = 0;
+ while (pos < 256*1024)
+ {
+ u32 len = *(u32*)&Discover_Buffer[pos];
+ pos += 4;
+ if (len == 0) break;
+
+ CurCmd = Discover_Buffer[pos++];
+ DataPos = 0;
+ Addr = 0;
+ Data = 0;
+ for (u32 i = 1; i < len; i++)
+ {
+ WriteFunc(Discover_Buffer[pos++], (i==(len-1)));
+ DataPos++;
+ }
+ }
+
+ CurCmd = prev_cmd;
+}
+
+void Write_Discover(u8 val, bool islast)
+{
+ // attempt at autodetecting the type of save memory.
+ // we basically hope the game will be nice and clear whole pages of memory.
+
+ if (CurCmd == 0x03 || CurCmd == 0x0B)
+ {
+ if (Discover_Likeliness)
+ {
+ // apply. and pray.
+ SetMemoryType();
+
+ DataPos = 0;
+ Addr = 0;
+ Data = 0;
+ return WriteFunc(val, islast);
+ }
+ else
+ {
+ Data = 0;
+ return;
+ }
+ }
+
+ if (CurCmd == 0x02 || CurCmd == 0x0A)
+ {
+ if (DataPos == 0)
+ Discover_Buffer[Discover_DataPos + 4] = CurCmd;
+
+ Discover_Buffer[Discover_DataPos + 5 + DataPos] = val;
+
+ if (islast)
+ {
+ u32 len = DataPos+1;
+
+ *(u32*)&Discover_Buffer[Discover_DataPos] = len+1;
+ Discover_DataPos += 5+len;
+
+ if (Discover_Likeliness <= len)
+ {
+ Discover_Likeliness = len;
+
+ if (len > 3+256) // bigger Flash, FRAM, whatever
+ {
+ Discover_MemoryType = 5;
+ }
+ else if (len > 2+128) // Flash
+ {
+ Discover_MemoryType = 4;
+ }
+ else if (len > 2+32) // EEPROM 512k
+ {
+ Discover_MemoryType = 3;
+ }
+ else if (len > 1+16 || (len != 1+16 && CurCmd != 0x0A)) // EEPROM 64k
+ {
+ Discover_MemoryType = 2;
+ }
+ else // EEPROM 4k
+ {
+ Discover_MemoryType = 1;
+ }
+ }
+
+ printf("discover: type=%d likeliness=%d\n", Discover_MemoryType, Discover_Likeliness);
+ }
+ }
+}
+
+void Write_Null(u8 val, bool islast) {}
+
+void Write_EEPROMTiny(u8 val, bool islast)
+{
+ // TODO
+}
+
+void Write_EEPROM(u8 val, bool islast)
+{
+ switch (CurCmd)
+ {
+ case 0x02:
+ if (DataPos < 2)
+ {
+ Addr <<= 8;
+ Addr |= val;
+ Data = 0;
+ }
+ else
+ {
+ if (Addr < SRAMLength)
+ SRAM[Addr] = val;
+
+ Addr++;
+ }
+ break;
+
+ case 0x03:
+ if (DataPos < 2)
+ {
+ Addr <<= 8;
+ Addr |= val;
+ Data = 0;
+ }
+ else
+ {
+ if (Addr >= SRAMLength)
+ Data = 0;
+ else
+ Data = SRAM[Addr];
+
+ 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 0x03:
+ if (DataPos < 3)
+ {
+ Addr <<= 8;
+ Addr |= val;
+ Data = 0;
+ }
+ else
+ {
+ if (Addr >= SRAMLength)
+ Data = 0;
+ else
+ Data = SRAM[Addr];
+
+ Addr++;
+ }
+ break;
+
+ case 0x0A:
+ if (DataPos < 3)
+ {
+ Addr <<= 8;
+ Addr |= val;
+ Data = 0;
+ }
+ else
+ {
+ if (Addr < SRAMLength)
+ SRAM[Addr] = val;
+
+ Addr++;
+ }
+ break;
+
+ case 0x9F:
+ Data = 0xFF;
+ 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;
Hold = 0;
}
@@ -98,7 +372,7 @@ void Write(u8 val, u32 hold)
CurCmd = val;
Hold = 1;
Data = 0;
- DataPos = 1;
+ DataPos = 0;
Addr = 0;
//printf("save SPI command %02X\n", CurCmd);
return;
@@ -106,28 +380,13 @@ void Write(u8 val, u32 hold)
switch (CurCmd)
{
- case 0x03: // read
- {
- if (DataPos < AddrLength+1)
- {
- Addr <<= 8;
- Addr |= val;
- Data = 0;
-
- //if (DataPos == AddrLength) printf("save SPI read %08X\n", Addr);
- }
- else
- {
- if (Addr >= SRAMLength)
- Data = 0;
- else
- Data = SRAM[Addr];
-
- Addr++;
- }
-
- DataPos++;
- }
+ case 0x02:
+ case 0x03:
+ case 0x0A:
+ case 0x0B:
+ case 0x9F:
+ WriteFunc(val, islast);
+ DataPos++;
break;
case 0x04: // write disable
@@ -144,14 +403,21 @@ void Write(u8 val, u32 hold)
Data = 0;
break;
- case 0x9F: // read JEDEC ID
- Data = 0xFF;
- break;
-
default:
- printf("unknown save SPI command %02X\n", CurCmd);
+ if (DataPos==0)
+ printf("unknown save SPI command %02X\n", CurCmd);
break;
}
+
+ if (islast && (CurCmd == 0x02 || CurCmd == 0x0A))
+ {
+ FILE* f = fopen(SRAMPath, "wb");
+ if (f)
+ {
+ fwrite(SRAM, SRAMLength, 1, f);
+ fclose(f);
+ }
+ }
}
}
@@ -347,6 +613,9 @@ void LoadROM(char* path)
fclose(f);
//CartROM = f;
+ // temp. TODO: later make this user selectable
+ // calling this sets up shit for booting from the cart directly.
+ // normal behavior is booting from the BIOS.
NDS::SetupDirectBoot();
CartInserted = true;
@@ -382,6 +651,15 @@ void LoadROM(char* path)
// encryption
Key1_InitKeycode(gamecode, 2, 2);
+
+
+ // save
+ char savepath[256];
+ strncpy(savepath, path, 255);
+ savepath[255] = '\0';
+ strncpy(savepath + strlen(path) - 3, "sav", 3);
+ printf("Save file: %s\n", savepath);
+ NDSCart_SRAM::LoadSave(savepath);
}
void ReadROM(u32 addr, u32 len, u32 offset)