From 517d31bae984dfd2195ad8ef3c039a5c64f234e5 Mon Sep 17 00:00:00 2001 From: mtabachenko Date: Thu, 30 Jul 2009 14:47:54 +0000 Subject: [PATCH] - add loading saves from No$GBA ;) --- desmume/src/mc.cpp | 176 ++++++++++++++++++++++++++++++++++++++++++++- desmume/src/mc.h | 1 + 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index f3ab326d6..e8c29ccce 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -548,6 +548,176 @@ void BackupDevice::load_old_state(u32 addr_size, u8* data, u32 datasize) flush(); } +//======================================================================= no$GBA +//======================================================================= +//======================================================================= + +s32 unpackSAV(void *in_buf, u32 fsize, void *out_buf) +{ + const char no_GBA_HEADER_ID[] = "NocashGbaBackupMediaSavDataFile"; + const char no_GBA_HEADER_SRAM_ID[] = "SRAM"; + u8 *src = (u8 *)in_buf; + u8 *dst = (u8 *)out_buf; + u32 src_pos = 0; + u32 dst_pos = 0; + u8 cc = 0; + u32 size_unpacked = 0; + u32 size_packed = 0; + u32 compressMethod = 0; + char buf[128] = { 0 }; + + if (fsize < 0x50) return (-1); + + for (int i = 0; i < 0x1F; i++) + { + if (src[i] != no_GBA_HEADER_ID[i]) return (-2); + } + if (src[0x1F] != 0x1A) return (-3); + for (int i = 0; i < 0x4; i++) + { + if (src[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) return (-2); + } + + + compressMethod = *((u32*)(src+0x44)); + + if (compressMethod == 0) // unpacked + { + size_unpacked = *((u32*)(src+0x4C)); + src_pos = 0x4C; + for (int i = 0; i < size_unpacked; i++) + { + dst[dst_pos++] = src[src_pos++]; + } + return (dst_pos); + } + + if (compressMethod == 1) // packed (method 1) + { + size_packed = *((u32*)(src+0x48)); + size_unpacked = *((u32*)(src+0x4C)); + + src_pos = 0x50; + while (true) + { + cc = src[src_pos++]; + + if (cc == 0) return (dst_pos); + + if (cc == 0x80) + { + u16 tsize = *((u16*)(src+src_pos+1)); + for (int t = 0; t < tsize; t++) + dst[dst_pos++] = src[src_pos]; + src_pos += 3; + continue; + } + + if (cc > 0x80) // repeat + { + cc -= 0x80; + for (int t = 0; t < cc; t++) + dst[dst_pos++] = src[src_pos]; + src_pos++; + continue; + } + // copy + for (int t = 0; t < cc; t++) + dst[dst_pos++] = src[src_pos++]; + } + return (dst_pos); + } + return (-200); +} + +u32 savTrim(void *buf, u32 size) +{ + u32 rows = size / 16; + u32 pos = (size - 16); + u8 *src = (u8*)buf; + + for (unsigned int i = 0; i < rows; i++, pos -= 16) + { + if (src[pos] == 0xFF) + { + for (int t = 0; t < 16; t++) + { + if (src[pos+t] != 0xFF) return (pos+16); + } + } + else + { + return (pos+16); + } + } + return (size); +} + +u32 fillLeft(u32 size) +{ + for (int i = 1; i < ARRAY_SIZE(save_types); i++) + { + if (size < save_types[i][1]) + return (size + (save_types[i][1] - size)); + } + return size; +} + +bool BackupDevice::load_no_gba(const char *fname) +{ + FILE *fsrc = fopen(fname, "rb"); + u8 *in_buf = NULL; + u8 *out_buf = NULL; + + if (fsrc) + { + u32 fsize = 0; + fseek(fsrc, 0, SEEK_END); + fsize = ftell(fsrc); + fseek(fsrc, 0, SEEK_SET); + //printf("Open %s file (size %i bytes)\n", fname, fsize); + + in_buf = new u8 [fsize]; + + if (fread(in_buf, 1, fsize, fsrc) == fsize) + { + out_buf = new u8 [8 * 1024 * 1024 / 8]; + for (int jj = 0; jj < 8 * 1024 * 1024 / 8; jj++) + { + out_buf[jj] = 0xFF; + } + + s32 size = unpackSAV(in_buf, fsize, out_buf); + if (size > 0) + { + //printf("New size %i byte(s)\n", size); + size = savTrim(out_buf, size); + //printf("--- new size after trim %i byte(s)\n", size); + size = fillLeft(size); + //printf("--- new size after fill %i byte(s)\n", size); + data.resize(size); + for (int tt = 0; tt < size; tt++) + data[tt] = out_buf[tt]; + + //dump back out as a dsv, just to keep things sane + flush(); + printf("Loaded no$GBA save\n"); + + if (in_buf) delete [] in_buf; + if (out_buf) delete [] out_buf; + return true; + } + if (out_buf) delete [] out_buf; + } + if (in_buf) delete [] in_buf; + } + + return false; +} +//======================================================================= end +//======================================================================= +//======================================================================= no$GBA + void BackupDevice::loadfile() { @@ -575,7 +745,8 @@ void BackupDevice::loadfile() } fclose(inf); - load_raw(tmp); + if (!load_no_gba(tmp)) + load_raw(tmp); } else { @@ -591,7 +762,8 @@ void BackupDevice::loadfile() //maybe it is a misnamed raw save file. try loading it that way printf("Not a DeSmuME .dsv save file. Trying to load as raw.\n"); fclose(inf); - load_raw(filename.c_str()); + if (!load_no_gba(filename.c_str())) + load_raw(filename.c_str()); return; } //desmume format diff --git a/desmume/src/mc.h b/desmume/src/mc.h index 8cdc4f580..66598121e 100644 --- a/desmume/src/mc.h +++ b/desmume/src/mc.h @@ -98,6 +98,7 @@ public: void raw_applyUserSettings(u32& size); bool load_duc(const char* filename); + bool load_no_gba(const char *fname); bool load_raw(const char* filename); bool save_raw(const char* filename); bool load_movie(std::istream* is);