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
This commit is contained in:
zeromus 2014-05-26 06:23:56 +00:00
parent fc6930c2e1
commit 262fc4f14a
3 changed files with 144 additions and 56 deletions

View File

@ -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<currPct;i++)
{
if(i%10==0)
printf(" %d%%\n",i/10*10);
else printf(".");
lastpct = currPct;
}
if (readed < 4)
break;
if(pos >= 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;
}
}

View File

@ -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()
{

View File

@ -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();