From 262fc4f14aa45cfabcd8c00f811359abc72da8ac Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 26 May 2014 06:23:56 +0000 Subject: [PATCH] apply alvinhochun's gbagame patches --- add system in EMUFILE_FILE to switch correctly between read/write modes; add system in EMUFILE_FILE to (optionally) track current file position and avoid redundant fseeks - this code is UNTESTED. --- add better console feedback when gbagame .sav is being scanned, to make developers less likely to think the emulator is frozen --- desmume/src/addons/slot2_gbagame.cpp | 84 ++++++++++++++++------------ desmume/src/emufile.cpp | 76 ++++++++++++++++++++++++- desmume/src/emufile.h | 40 ++++++------- 3 files changed, 144 insertions(+), 56 deletions(-) diff --git a/desmume/src/addons/slot2_gbagame.cpp b/desmume/src/addons/slot2_gbagame.cpp index d08a4d38d..024575c52 100644 --- a/desmume/src/addons/slot2_gbagame.cpp +++ b/desmume/src/addons/slot2_gbagame.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2009 CrazyMax - Copyright (C) 2009-2013 DeSmuME team + Copyright (C) 2009-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,9 +44,7 @@ private: EMUFILE* fROM; EMUFILE* fSRAM; u32 romSize; - u32 currentROMPos; u32 sramSize; - u32 currentSRAMPos; u32 saveType; struct @@ -63,12 +61,8 @@ private: { if (!fROM) return 0xFFFFFFFF; - if (currentROMPos != pos) - fROM->fseek(pos, SEEK_SET); - u32 data = 0xFFFFFFFF; u32 readed = fROM->fread(&data, size); - currentROMPos = (pos + readed); return data; } @@ -77,14 +71,11 @@ private: if (!fSRAM) return 0xFFFFFFFF; - if (currentSRAMPos != pos) - fSRAM->fseek(pos, SEEK_SET); + fSRAM->fseek(pos, SEEK_SET); u32 data = 0xFFFFFFFF; u32 readed = fSRAM->fread(&data, size); - currentSRAMPos = (pos + readed); return data; - return 0xFFFFFFFF; } void writeSRAM(const u32 pos, const u8 *data, u32 size) @@ -92,40 +83,59 @@ private: if (!fSRAM) return; - if (currentSRAMPos != pos) - fSRAM->fseek(pos, SEEK_SET); + fSRAM->fseek(pos, SEEK_SET); u32 writed = size; - fSRAM->fwrite(&data, size); - currentSRAMPos = (pos + writed); + fSRAM->fwrite(data, size); + fSRAM->fflush(); } - u32 getSaveTypeGBA() + u32 scanSaveTypeGBA() { if (!fROM) return 0xFF; - u32 saveROMPos = currentROMPos; - u32 tmp = 0; - fROM->fseek(0, SEEK_SET); + int size = fROM->size(); - while (!fROM->eof()) + int lastpct=1; + + int len = fROM->size(); + for(;;) { + u32 tmp; u32 readed = fROM->fread(&tmp, 4); - if (readed < 4) break; + + int pos = fROM->ftell(); + int currPct = pos*100/(size-1); + for(int i=lastpct;i= len) + break; + switch (tmp) { - case EEPROM: fROM->fseek(saveROMPos, SEEK_SET); return 1; - case SRAM_: fROM->fseek(saveROMPos, SEEK_SET); return 2; + case EEPROM: + return 1; + case SRAM_: + return 2; case FLASH: { - fROM->fread(&tmp, 4); - fROM->fseek(saveROMPos, SEEK_SET); + u32 tmp = fROM->read32le(); return ((tmp == FLASH1M_)?3:5); } - case SIIRTC_V: fROM->fseek(saveROMPos, SEEK_SET); return 4; + case SIIRTC_V: + return 4; } } @@ -223,7 +233,7 @@ private: case 0x82: if (val == 0x30) { - u32 ofs = (adr & 0x0000F000); + u32 ofs = (adr & 0x0000F000) + (0x10000 * gbaFlash.bank); //INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000); u8 *tmp = new u8[0x1000]; memset(tmp, 0xFF, 0x1000); @@ -305,9 +315,7 @@ private: delete fROM; fROM = NULL; delete fSRAM; fSRAM = NULL; romSize = 0; - currentROMPos = 0; sramSize = 0; - currentSRAMPos = 0; } public: @@ -328,9 +336,7 @@ public: { Close(); romSize = 0; - currentROMPos = 0; sramSize = 0; - currentSRAMPos = 0; if (gameInfo.romsize == 0) { @@ -348,8 +354,10 @@ public: GBACartridge_SRAMPath = Path::GetFileNameWithoutExt(GBACartridge_RomPath) + "." + GBA_SRAM_FILE_EXT; } - printf("GBASlot opening ROM: %s", GBACartridge_RomPath.c_str()); - fROM = new EMUFILE_FILE(GBACartridge_RomPath, "rb"); + printf("GBASlot opening ROM: %s\n", GBACartridge_RomPath.c_str()); + EMUFILE_FILE *inf = new EMUFILE_FILE(GBACartridge_RomPath, "rb"); + inf->EnablePositionCache(); + fROM = inf; if (fROM->fail()) { printf(" - Failed\n"); @@ -362,7 +370,9 @@ public: printf(" - Success (%u bytes)\n", romSize); // Load the GBA cartridge SRAM. - fSRAM = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+"); + inf = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+"); + inf->EnablePositionCache(); + fSRAM = inf; if(fSRAM->fail()) { delete fSRAM; @@ -372,8 +382,9 @@ public: else { sramSize = fSRAM->size(); - saveType = getSaveTypeGBA(); - printf("GBASlot found SRAM %s (%s - %u bytes)\n", GBACartridge_SRAMPath.c_str(), (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize); + printf("Scanning GBA rom to ID save type\n"); + saveType = scanSaveTypeGBA(); + printf("\nGBASlot found SRAM (%s - %u bytes) at:\n%s\n", (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize, GBACartridge_SRAMPath.c_str()); gbaFlash.size = sramSize; if (gbaFlash.size <= (64 * 1024)) { @@ -385,6 +396,7 @@ public: gbaFlash.idDevice = 0x09; gbaFlash.idManufacturer = 0xC2; } + gbaFlash.state = 0; } } diff --git a/desmume/src/emufile.cpp b/desmume/src/emufile.cpp index 6105b9967..624d1dc26 100644 --- a/desmume/src/emufile.cpp +++ b/desmume/src/emufile.cpp @@ -1,7 +1,7 @@ /* The MIT License -Copyright (C) 2009-2010 DeSmuME team +Copyright (C) 2009-2014 DeSmuME team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -74,6 +74,80 @@ void EMUFILE_FILE::truncate(s32 length) open(fname.c_str(),mode); } +int EMUFILE_FILE::fseek(int offset, int origin) +{ + //if the position cache is enabled, and the seek offset matches the known current position, then early exit. + if(mPositionCacheEnabled) + { + if(origin == SEEK_SET) + { + if(mFilePosition == offset) + { + return mFilePosition; + } + } + } + + mCondition = eCondition_Clean; + + int pos = ::fseek(fp, offset, origin); + mPositionCacheEnabled = pos; + + return pos; +} + + +int EMUFILE_FILE::ftell() +{ + if(mPositionCacheEnabled) + return (int)mFilePosition; + return (u32)::ftell(fp); +} + +void EMUFILE_FILE::DemandCondition(eCondition cond) +{ + //allows switching between reading and writing; an fseek is required, under the circumstances + + if(mCondition == eCondition_Clean) + goto CONCLUDE; + if(mCondition == eCondition_Unknown) + goto RESET; + if(mCondition != cond) + goto RESET; + + return; + +RESET: + ::fseek(fp,::ftell(fp),SEEK_SET); +CONCLUDE: + mCondition = cond; +} + +size_t EMUFILE_FILE::_fread(const void *ptr, size_t bytes) +{ + DemandCondition(eCondition_Read); + size_t ret = ::fread((void*)ptr, 1, bytes, fp); + mFilePosition += ret; + if(ret < bytes) + failbit = true; + return ret; +} + +void EMUFILE_FILE::EnablePositionCache() +{ + mPositionCacheEnabled = true; + mFilePosition = ::ftell(fp); +} + +void EMUFILE_FILE::fwrite(const void *ptr, size_t bytes) +{ + DemandCondition(eCondition_Write); + size_t ret = ::fwrite((void*)ptr, 1, bytes, fp); + mFilePosition += ret; + if(ret < bytes) + failbit = true; +} + EMUFILE* EMUFILE_FILE::memwrap() { diff --git a/desmume/src/emufile.h b/desmume/src/emufile.h index 52bdfa44f..e6740d8b2 100644 --- a/desmume/src/emufile.h +++ b/desmume/src/emufile.h @@ -1,7 +1,7 @@ /* The MIT License -Copyright (C) 2009-2012 DeSmuME team +Copyright (C) 2009-2014 DeSmuME team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -270,10 +270,22 @@ protected: FILE* fp; std::string fname; char mode[16]; + long mFilePosition; + bool mPositionCacheEnabled; + + enum eCondition + { + eCondition_Clean, + eCondition_Unknown, + eCondition_Read, + eCondition_Write + } mCondition; private: void open(const char* fname, const char* mode) { + mPositionCacheEnabled = false; + mCondition = eCondition_Clean; fp = fopen(fname,mode); if(!fp) failbit = true; @@ -286,6 +298,8 @@ public: EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); } EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); } + void EnablePositionCache(); + virtual ~EMUFILE_FILE() { if(NULL != fp) fclose(fp); @@ -299,6 +313,8 @@ public: bool is_open() { return fp != NULL; } + void DemandCondition(eCondition cond); + virtual void truncate(s32 length); virtual int fprintf(const char *format, ...) { @@ -316,29 +332,15 @@ public: return ::fputc(c, fp); } - virtual size_t _fread(const void *ptr, size_t bytes){ - size_t ret = ::fread((void*)ptr, 1, bytes, fp); - if(ret < bytes) - failbit = true; - return ret; - } + virtual size_t _fread(const void *ptr, size_t bytes); //removing these return values for now so we can find any code that might be using them and make sure //they handle the return values correctly + virtual void fwrite(const void *ptr, size_t bytes); - virtual void fwrite(const void *ptr, size_t bytes){ - size_t ret = ::fwrite((void*)ptr, 1, bytes, fp); - if(ret < bytes) - failbit = true; - } + virtual int fseek(int offset, int origin); - virtual int fseek(int offset, int origin) { - return ::fseek(fp, offset, origin); - } - - virtual int ftell() { - return (u32)::ftell(fp); - } + virtual int ftell(); virtual int size() { int oldpos = ftell();