From 9a0bf912d9f3886cb96d02dfb1f2d182d3b57643 Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 11 Dec 2018 20:39:07 +0100 Subject: [PATCH] (finally) axe trainwreck savetype-autodetect code. pull that from ROM database. for now, assume EEPROM 64k if not found, or null for homebrew. --- romlist.bin | Bin 0 -> 114560 bytes src/NDSCart.cpp | 326 +++++------------------------------------------- 2 files changed, 34 insertions(+), 292 deletions(-) create mode 100644 romlist.bin diff --git a/romlist.bin b/romlist.bin new file mode 100644 index 0000000000000000000000000000000000000000..f8705dc27449e294d6352ce599382a51be600317 GIT binary patch literal 114560 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 J_27qs{{r>_76SkP literal 0 HcmV?d00001 diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 730d3202..c7ce0db0 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -29,11 +29,6 @@ namespace NDSCart_SRAM { -// BIG SRAM TODO!!!! -// USE A DATABASE TO IDENTIFY SAVE MEMORY TYPE -// (and maybe keep autodetect as a last resort??) -// AUTODETECT IS BLARGY AND IS A MESS - u8* SRAM; u32 SRAMLength; @@ -41,15 +36,6 @@ char SRAMPath[1024]; void (*WriteFunc)(u8 val, bool islast); -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; u32 DataPos; @@ -69,37 +55,25 @@ void Write_Discover(u8 val, bool islast); bool Init() { SRAM = NULL; - Discover_Buffer = NULL; return true; } void DeInit() { if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; } void Reset() { if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; SRAM = NULL; - Discover_Buffer = NULL; } void DoSavestate(Savestate* file) { file->Section("NDCS"); - // CHECKME/TODO/whatever - // should the autodetect status shit go in the savestate??? - // I don't think so. - // worst case is that the savestate was taken before autodetect took place completely - // and that causes it to yield a different result, fucking things up - // but that is unlikely - // and we should just use a goddamn database anyway, this is a trainwreck - - // we reload the SRAM contents, tho. + // we reload the SRAM contents. // it should be the same file (as it should be the same ROM, duh) // but the contents may change // TODO maybe: possibility to save to a separate file when using savestates???? @@ -139,15 +113,9 @@ void DoSavestate(Savestate* file) file->Var32(&Addr); } -void LoadSave(const char* path) +void LoadSave(const char* path, u32 type) { if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; - - Discover_Buffer = NULL; - Discover_LastPC = 0; - Discover_AddrLength = 0x7FFFFFFF; - Discover_LikelySize = 0; strncpy(SRAMPath, path, 1023); SRAMPath[1023] = '\0'; @@ -163,32 +131,34 @@ void LoadSave(const char* path) fread(SRAM, SRAMLength, 1, f); fclose(f); - - switch (SRAMLength) - { - 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); - WriteFunc = Write_Null; - break; - } } else { - SRAMLength = 0; - WriteFunc = Write_Discover; - Discover_MemoryType = 2; - Discover_Likeliness = 0; + int sramlen[] = {0, 512, 8192, 65536, 256*1024, 512*1024, 1024*1024, 8192*1024, 32768*1024}; + SRAMLength = sramlen[type]; - Discover_DataPos = 0; - Discover_Buffer = new u8[256*1024]; - memset(Discover_Buffer, 0, 256*1024); + if (SRAMLength) + { + SRAM = new u8[SRAMLength]; + memset(SRAM, 0, SRAMLength); + } + } + + switch (SRAMLength) + { + 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: + case 32768*1024: WriteFunc = Write_Flash; break; + default: + printf("!! BAD SAVE LENGTH %d\n", SRAMLength); + case 0: + WriteFunc = Write_Null; + break; } Hold = 0; @@ -201,7 +171,7 @@ void RelocateSave(const char* path, bool write) { if (!write) { - LoadSave(path); // lazy + LoadSave(path, 0); // lazy return; } @@ -224,240 +194,6 @@ u8 Read() return Data; } -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_LikelySize); - Discover_MemoryType = 2; - } - } - - 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: - if (!SRAMLength) SRAMLength = 256*1024; - printf("Save memory type: Flash %dk\n", SRAMLength/1024); - WriteFunc = Write_Flash; - 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; - - delete[] Discover_Buffer; - Discover_Buffer = NULL; -} - -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) // writes have occured before this read - { - // apply. and pray. - SetMemoryType(); - - DataPos = 0; - Addr = 0; - Data = 0; - return WriteFunc(val, 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; - } - } - - 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) || (len > 1+16 && CurCmd == 0xA)) // 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) @@ -1161,6 +897,12 @@ bool LoadROM(const char* path, const char* sram, bool direct) { // set defaults printf("ROM entry not found\n"); + + romparams[0] = CartROMSize; + if (*(u32*)&CartROM[0x20] < 0x4000) + romparams[1] = 0; // no saveRAM for homebrew + else + romparams[1] = 2; // assume EEPROM 64k (TODO FIXME) } else printf("ROM entry: %08X %08X %08X\n", romparams[0], romparams[1], romparams[2]); @@ -1215,7 +957,7 @@ bool LoadROM(const char* path, const char* sram, bool direct) // save printf("Save file: %s\n", sram); - NDSCart_SRAM::LoadSave(sram); + NDSCart_SRAM::LoadSave(sram, romparams[1]); return true; }