diff --git a/desmume/src/emufile.cpp b/desmume/src/emufile.cpp index a4ee0d76c..131f5a2ce 100644 --- a/desmume/src/emufile.cpp +++ b/desmume/src/emufile.cpp @@ -1,7 +1,7 @@ /* The MIT License -Copyright (C) 2009-2014 DeSmuME team +Copyright (C) 2009-2015 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 @@ -141,13 +141,15 @@ void EMUFILE_FILE::EnablePositionCache() mFilePosition = ::ftell(fp); } -void EMUFILE_FILE::fwrite(const void *ptr, size_t bytes) +size_t 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; + + return ret; } diff --git a/desmume/src/emufile.h b/desmume/src/emufile.h index e6740d8b2..b2b3474cc 100644 --- a/desmume/src/emufile.h +++ b/desmume/src/emufile.h @@ -1,7 +1,7 @@ /* The MIT License -Copyright (C) 2009-2014 DeSmuME team +Copyright (C) 2009-2015 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 @@ -84,11 +84,7 @@ public: virtual int fputc(int c) = 0; virtual size_t _fread(const void *ptr, size_t bytes) = 0; - - //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) = 0; + virtual size_t fwrite(const void *ptr, size_t bytes) = 0; void write64le(u64* val); void write64le(u64 val); @@ -221,15 +217,13 @@ public: } 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 size_t fwrite(const void *ptr, size_t bytes){ reserve(pos+(s32)bytes); memcpy(buf()+pos,ptr,bytes); pos += (s32)bytes; len = std::max(pos,len); + + return bytes; } virtual int fseek(int offset, int origin){ @@ -333,10 +327,7 @@ public: } 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 size_t fwrite(const void *ptr, size_t bytes); virtual int fseek(int offset, int origin); diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index 4a7ee655b..3778407cd 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -2210,7 +2210,7 @@ public: std::vector differences; - virtual void fwrite(const void *ptr, size_t bytes) + virtual size_t fwrite(const void *ptr, size_t bytes) { if(!failbit) { @@ -2243,6 +2243,8 @@ public: } pos += bytes; + + return bytes; } }; diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index 41865ae26..7310d1efe 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -123,7 +123,7 @@ bool BackupDevice::save_state(EMUFILE* os) std::vector data(fsize); fpMC->fseek(0, SEEK_SET); if(data.size()!=0) - fread((char*)&data[0], 1, fsize, fpMC->get_fp()); + fpMC->fwrite((char *)&data[0], fsize); u32 version = 5; //v0 @@ -195,7 +195,7 @@ bool BackupDevice::load_state(EMUFILE* is) #ifndef _DONT_SAVE_BACKUP fpMC->fseek(0, SEEK_SET); if(data.size()!=0) - fwrite((char*)&data[0], 1, fsize, fpMC->get_fp()); + fpMC->fwrite((char *)&data[0], fsize); ensure(data.size(), fpMC); #endif @@ -249,19 +249,29 @@ BackupDevice::BackupDevice() if (!out->fail()) { u8 *data = new u8[sz]; - fread(data, 1, sz, in->get_fp()); - fwrite(data, 1, sz, out->get_fp()); + in->fread(data, sz); + out->fwrite(data, sz); delete [] data; } + else + { + printf("BackupDevice: Could not create the backup save file.\n"); + } + delete out; } } + else + { + printf("BackupDevice: Could not read the save file for creating a backup.\n"); + } + delete in; } if (!fexists) { - printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); + printf("BackupDevice: DeSmuME .dsv save file not found. Trying to load a .sav file.\n"); std::string tmp_fsav = std::string(buf) + ".sav"; EMUFILE_FILE *fpTmp = new EMUFILE_FILE(tmp_fsav, "rb"); @@ -275,14 +285,19 @@ BackupDevice::BackupDevice() if (!fpOut->fail()) { u8 *buf = new u8[sz + 1]; - if ((buf) && (fread(buf, 1, sz, fpTmp->get_fp()) == sz)) + if ((buf) && (fpTmp->fread(buf, sz) == sz)) { if (no_gba_unpack(buf, sz)) - printf("Converted from no$gba save.\n"); + { + printf("BackupDevice: Converting no$gba .sav file.\n"); + } else + { + printf("BackupDevice: Converting old raw .sav file.\n"); sz = trim(buf, sz); + } - if (fwrite(buf, 1, sz, fpOut->get_fp()) == sz) + if (fpOut->fwrite(buf, sz) == sz) { u8 res = searchFileSaveType(sz); if (res != 0xFF) @@ -297,6 +312,10 @@ BackupDevice::BackupDevice() info.type = 0; fexists = true; } + else + { + printf("BackupDevice: Error converting .sav file.\n"); + } } delete [] buf; } @@ -307,6 +326,14 @@ BackupDevice::BackupDevice() } fpMC = new EMUFILE_FILE(filename, fexists?"rb+":"wb+"); + const bool fileCanReadWrite = (fpMC->get_fp() != NULL); + if (!fileCanReadWrite) + { + delete fpMC; + fpMC = new EMUFILE_MEMORY(); + printf("BackupDevice: WARNING! Failed to get read/write access to the save file! Will operate in RAM instead.\n"); + } + if (!fpMC->fail()) { fsize = fpMC->size(); @@ -372,7 +399,7 @@ BackupDevice::BackupDevice() } if (ss > 0) - printf("Backup size: %u %cbit\n", ss, _Mbit?'M':'K'); + printf("BackupDevice: size = %u %cbit\n", ss, _Mbit?'M':'K'); } state = (fsize > 0)?RUNNING:DETECTING; @@ -491,7 +518,7 @@ bool BackupDevice::write(u8 val) //never use save files if we are in movie mode if (isMovieMode) return true; - return fwrite(&val, 1, 1, fpMC->get_fp())?true:false; + return (fpMC->fwrite(&val, 1) == 1); } void BackupDevice::writeByte(u32 addr, u8 val) @@ -548,7 +575,7 @@ bool BackupDevice::saveBuffer(u8 *data, u32 size, bool _rewind, bool _truncate) fpMC->truncate(0); } fsize = size; - fwrite(data, 1, size, fpMC->get_fp()); + fpMC->fwrite(data, size); ensure(size, fpMC); return true; } @@ -886,16 +913,16 @@ u8 BackupDevice::data_command(u8 val, u8 PROCNUM) } //guarantees that the data buffer has room enough for the specified number of bytes -void BackupDevice::ensure(u32 addr, EMUFILE_FILE *fpOut) +void BackupDevice::ensure(u32 addr, EMUFILE *fpOut) { ensure(addr, uninitializedValue, fpOut); } -void BackupDevice::ensure(u32 addr, u8 val, EMUFILE_FILE *fpOut) +void BackupDevice::ensure(u32 addr, u8 val, EMUFILE *fpOut) { if (!fpOut && (addr < fsize)) return; - EMUFILE_FILE *fp = fpOut?fpOut:fpMC; + EMUFILE *fp = fpOut?fpOut:fpMC; #ifndef _DONT_SAVE_BACKUP fp->fseek(fsize, SEEK_SET); @@ -912,7 +939,7 @@ void BackupDevice::ensure(u32 addr, u8 val, EMUFILE_FILE *fpOut) { u8 *tmp = new u8[size]; memset(tmp, val, size); - fwrite(tmp, 1, size, fp->get_fp()); + fp->fwrite(tmp, size); delete [] tmp; } @@ -1297,7 +1324,7 @@ bool BackupDevice::export_no_gba(const char* fname) std::vector data(fsize); u32 pos = fpMC->ftell(); fpMC->fseek(0, SEEK_SET); - fread((char*)&data[0], 1, fsize, fpMC->get_fp()); + fpMC->fread((char *)&data[0], fsize); fpMC->fseek(pos, SEEK_SET); FILE* outf = fopen(fname,"wb"); @@ -1326,7 +1353,7 @@ bool BackupDevice::export_raw(const char* filename) std::vector data(fsize); u32 pos = fpMC->ftell(); fpMC->fseek(0, SEEK_SET); - fread((char*)&data[0], 1, fsize, fpMC->get_fp()); + fpMC->fread((char *)&data[0], fsize); fpMC->fseek(pos, SEEK_SET); FILE* outf = fopen(filename,"wb"); @@ -1525,7 +1552,7 @@ bool BackupDevice::load_movie(EMUFILE* is) { is->fread((char*)&info.mem_size,4); is->fseek(0, SEEK_SET); - fpMC = (EMUFILE_FILE*)&is; + fpMC = (EMUFILE*)&is; state = RUNNING; addr_size = info.addr_size; diff --git a/desmume/src/mc.h b/desmume/src/mc.h index e569c55e1..602e5cc66 100644 --- a/desmume/src/mc.h +++ b/desmume/src/mc.h @@ -49,7 +49,6 @@ #define MC_SIZE_512MBITS 0x4000000 class EMUFILE; -class EMUFILE_FILE; //This "backup device" represents a typical retail NDS save memory accessible via AUXSPI. //It is managed as a core emulator service for historical reasons which are bad, @@ -104,8 +103,8 @@ public: u32 addr_size; } savedInfo; - void ensure(u32 addr, EMUFILE_FILE *fpOut = NULL); - void ensure(u32 addr, u8 val, EMUFILE_FILE *fpOut = NULL); + void ensure(u32 addr, EMUFILE *fpOut = NULL); + void ensure(u32 addr, u8 val, EMUFILE *fpOut = NULL); //and these are used by old savestates void load_old_state(u32 addr_size, u8* data, u32 datasize); @@ -145,7 +144,7 @@ public: u8 uninitializedValue; private: - EMUFILE_FILE *fpMC; + EMUFILE *fpMC; std::string filename; u32 fsize; int readFooter(); diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 6008f4d82..9e88dc481 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -3937,6 +3937,23 @@ static BOOL OpenCore(const char* filename) MainWindowToolbar->EnableButton(IDM_RESET, true); MainWindowToolbar->ChangeButtonBitmap(IDM_PAUSE, IDB_PAUSE); + // Warn the user if the battery save won't be written to an actual file on disk. + char batteryPath[MAX_PATH] = {0}; + memset(batteryPath, 0, MAX_PATH); + path.getpathnoext(path.BATTERY, batteryPath); + std::string batteryPathString = std::string(batteryPath) + ".dsv"; + FILE *testFs = fopen(batteryPathString.c_str(), "rb+"); + if (testFs == NULL) + { + msgbox->warn("\ +Could not get read/write access to the battery save file! The file will not be saved in this current session.\n\n\ +Choose Config > Path Settings and ensure that the SaveRam directory exists and is available for read/write access."); + } + else + { + fclose(testFs); + } + return TRUE; } else return FALSE;