aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-06-25 17:35:45 +0200
committerStapleButter <thetotalworm@gmail.com>2017-06-25 17:35:45 +0200
commit39fbc415f67b3ffd27982e31af57314487daf9cb (patch)
tree247534a957ab632a63b784aa58a0bae94e1afb74
parent4ffb2177913ed97c1e0705f040002acff8e0efc0 (diff)
new save heuristic. atleast Scribblenauts doesn't lose its shit now.
shut up shibs
-rw-r--r--src/NDS.cpp5
-rw-r--r--src/NDS.h2
-rw-r--r--src/NDSCart.cpp115
3 files changed, 118 insertions, 4 deletions
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 234ed0c..66e5a47 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -586,6 +586,11 @@ void ResumeCPU(u32 cpu, u32 mask)
CPUStop &= ~mask;
}
+u32 GetPC(u32 cpu)
+{
+ return cpu ? ARM7->R[15] : ARM9->R[15];
+}
+
void HandleTimerOverflow(u32 tid)
diff --git a/src/NDS.h b/src/NDS.h
index 38f2b89..bb2d210 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -126,6 +126,8 @@ bool HaltInterrupted(u32 cpu);
void StopCPU(u32 cpu, u32 mask);
void ResumeCPU(u32 cpu, u32 mask);
+u32 GetPC(u32 cpu);
+
void CheckDMAs(u32 cpu, u32 mode);
void StopDMAs(u32 cpu, u32 mode);
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 696666b..78b7af5 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -20,6 +20,7 @@
#include <string.h>
#include "NDS.h"
#include "NDSCart.h"
+#include "ARM.h"
namespace NDSCart_SRAM
@@ -36,6 +37,10 @@ u32 Discover_MemoryType;
u32 Discover_Likeliness;
u8* Discover_Buffer;
u32 Discover_DataPos;
+u32 Discover_LastPC;
+u32 Discover_AddrLength;
+u32 Discover_Addr;
+u32 Discover_LikelySize;
u32 Hold;
u8 CurCmd;
@@ -80,6 +85,9 @@ void LoadSave(char* path)
if (Discover_Buffer) delete[] Discover_Buffer;
Discover_Buffer = NULL;
+ Discover_LastPC = 0;
+ Discover_AddrLength = 0x7FFFFFFF;
+ Discover_LikelySize = 0;
strncpy(SRAMPath, path, 255);
SRAMPath[255] = '\0';
@@ -136,6 +144,43 @@ u8 Read()
void SetMemoryType()
{
+ SRAMLength = 0;
+
+ if (Discover_LikelySize)
+ {
+ if (Discover_LikelySize >= 0x40000)
+ {
+ Discover_MemoryType = 4; // FLASH
+ SRAMLength = Discover_LikelySize;
+ }
+ else if (Discover_LikelySize == 0x10000 || Discover_MemoryType == 3)
+ {
+ if (Discover_MemoryType > 3)
+ printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize);
+
+ Discover_MemoryType = 3;
+ }
+ else if (Discover_LikelySize == 0x2000)
+ {
+ if (Discover_MemoryType > 3)
+ printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize);
+
+ Discover_MemoryType = 2;
+ }
+ else if (Discover_LikelySize == 0x200 || Discover_MemoryType == 1)
+ {
+ if (Discover_MemoryType > 1)
+ printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize);
+
+ Discover_MemoryType = 1;
+ }
+ else
+ {
+ printf("bad save size %X. assuming EEPROM 64K\n");
+ Discover_MemoryType = 2;
+ }
+ }
+
switch (Discover_MemoryType)
{
case 1:
@@ -157,9 +202,9 @@ void SetMemoryType()
break;
case 4:
- printf("Save memory type: Flash. Hope the size is 256K.\n");
+ if (!SRAMLength) SRAMLength = 256*1024;
+ printf("Save memory type: Flash %dk\n", SRAMLength/1024);
WriteFunc = Write_Flash;
- SRAMLength = 256*1024;
break;
case 5:
@@ -207,7 +252,7 @@ void Write_Discover(u8 val, bool islast)
if (CurCmd == 0x03 || CurCmd == 0x0B)
{
- if (Discover_Likeliness)
+ if (Discover_Likeliness) // writes have occured before this read
{
// apply. and pray.
SetMemoryType();
@@ -219,6 +264,68 @@ void Write_Discover(u8 val, bool islast)
}
else
{
+ if (DataPos == 0)
+ {
+ Discover_LastPC = NDS::GetPC((NDS::ExMemCnt[0] >> 11) & 0x1);
+ Discover_Addr = val;
+ }
+ else
+ {
+ bool addrlenchange = false;
+
+ Discover_Addr <<= 8;
+ Discover_Addr |= val;
+
+ u32 pc = NDS::GetPC((NDS::ExMemCnt[0] >> 11) & 0x1);
+ if ((pc != Discover_LastPC) || islast)
+ {
+ if (DataPos < Discover_AddrLength)
+ {
+ Discover_AddrLength = DataPos;
+ addrlenchange = true;
+ }
+ }
+
+ if (DataPos == Discover_AddrLength)
+ {
+ Discover_Addr >>= 8;
+
+ // determine the address for this read
+ // the idea is to see how far the game reads
+ // but we need margins for games that have antipiracy
+ // as those will generally read just past the limit
+ // and expect it to wrap to zero
+
+ u32 likelysize = 0;
+
+ if (DataPos == 3) // FLASH
+ {
+ if (Discover_Addr >= 0x101000)
+ likelysize = 0x800000; // 8M
+ else if (Discover_Addr >= 0x81000)
+ likelysize = 0x100000; // 1M
+ else if (Discover_Addr >= 0x41000)
+ likelysize = 0x80000; // 512K
+ else
+ likelysize = 0x40000; // 256K
+ }
+ else if (DataPos == 2) // EEPROM
+ {
+ if (Discover_Addr >= 0x3000)
+ likelysize = 0x10000; // 64K
+ else
+ likelysize = 0x2000; // 8K
+ }
+ else if (DataPos == 1) // tiny EEPROM
+ {
+ likelysize = 0x200; // always 4K
+ }
+
+ if ((likelysize > Discover_LikelySize) || addrlenchange)
+ Discover_LikelySize = likelysize;
+ }
+ }
+
Data = 0;
return;
}
@@ -505,7 +612,7 @@ void Write(u8 val, u32 hold)
default:
if (DataPos==0)
- printf("unknown save SPI command %02X %08X\n", CurCmd);
+ printf("unknown save SPI command %02X %02X\n", CurCmd, val);
break;
}