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:
parent
fc6930c2e1
commit
262fc4f14a
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue