restore IPS patching capability which was lost when archive support was added

This commit is contained in:
zeromus 2008-08-12 04:57:15 +00:00
parent c8473ffadb
commit f73de3b31e
5 changed files with 163 additions and 152 deletions

View File

@ -1,11 +1,11 @@
---version 2.0.2 released--- ---version 2.0.2 released---
10-aug-2008 - punkrockguy318 - SDL: cleaned up the SConsruct
11-aug-2008 - zeromus - restore IPS patching capability which was lost when archive support was added
11-aug-2008 - zeromus - SF [ 2011550 ] Buffer overflow (change vsprintf to vsnprintf) 11-aug-2008 - zeromus - SF [ 2011550 ] Buffer overflow (change vsprintf to vsnprintf)
11-aug-2008 - zeromus - SF [ 2047004 ] Moviefilenames without extension don't automatically get fm2 11-aug-2008 - zeromus - SF [ 2047004 ] Moviefilenames without extension don't automatically get fm2
10-aug-2008 - zeromus - upgrade to cah4e3's latest mapper 163&164 code to fix a crash in a game 10-aug-2008 - zeromus - upgrade to cah4e3's latest mapper 163&164 code to fix a crash in a game
10-aug-2008 - zeromus - remove cnrom chr rom size limit for homebrew roms 10-aug-2008 - zeromus - remove cnrom chr rom size limit for homebrew roms
10-aug-2008 - punkrockguy318 - SDL: cleaned up the SConsruct
10-aug-2008 - punkrockguy318 - SDL: fixed issue where fceu would lock up when file dialogs were opened during fullscreen 10-aug-2008 - punkrockguy318 - SDL: fixed issue where fceu would lock up when file dialogs were opened during fullscreen
10-aug-2008 - punkrockguy318 - SDL: fixed bug where fceux would close when file dialogs were closed 10-aug-2008 - punkrockguy318 - SDL: fixed bug where fceux would close when file dialogs were closed
10-aug-2008 - punkrockguy318 - SDL: File open dialog is now used to movie playback 10-aug-2008 - punkrockguy318 - SDL: File open dialog is now used to movie playback

View File

@ -59,6 +59,7 @@
#include "drivers/sdl/sdl.h" #include "drivers/sdl/sdl.h"
#endif #endif
int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings
bool justLagged = false; bool justLagged = false;
bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1) bool frameAdvanceLagSkip = false; //If this is true, frame advance will skip over lag frame (i.e. it will emulate 2 frames instead of 1)
@ -339,8 +340,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
FCEU_printf("Loading %s...\n\n",name); FCEU_printf("Loading %s...\n\n",name);
ipsfn=strdup(FCEU_MakeFName(FCEUMKF_IPS,0,0).c_str()); fp=FCEU_fopen(name,0,"rb",0);
fp=FCEU_fopen(name,ipsfn,"rb",0);
if(!fp) if(!fp)
{ {
return 0; return 0;
@ -348,7 +348,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
GetFileBase(fp->filename.c_str()); GetFileBase(fp->filename.c_str());
free(ipsfn); //free(ipsfn);
if(!fp) { if(!fp) {
FCEU_PrintError("Error opening \"%s\"!",name); FCEU_PrintError("Error opening \"%s\"!",name);
@ -657,6 +657,9 @@ void hand(X6502 *X, int type, unsigned int A)
int suppressAddPowerCommand=0; // hack... yeah, I know... int suppressAddPowerCommand=0; // hack... yeah, I know...
void PowerNES(void) void PowerNES(void)
{ {
/*void MapperInit();
MapperInit();*/
if(!suppressAddPowerCommand) if(!suppressAddPowerCommand)
FCEUMOV_AddCommand(FCEUNPCMD_POWER); FCEUMOV_AddCommand(FCEUNPCMD_POWER);
if(!GameInfo) return; if(!GameInfo) return;

View File

@ -47,30 +47,36 @@
#include "movie.h" #include "movie.h"
#include "driver.h" #include "driver.h"
#include "utils/xstring.h" #include "utils/xstring.h"
#include "utils/memorystream.h"
using namespace std; using namespace std;
typedef struct {
uint8 *data;
uint32 size;
uint32 location;
} MEMWRAP;
void ApplyIPS(FILE *ips, MEMWRAP *dest) static std::string BaseDirectory;
static char FileExt[2048]; //Includes the . character, as in ".nes"
char FileBase[2048];
static char FileBaseDirectory[2048];
void ApplyIPS(FILE *ips, FCEUFILE* fp)
{ {
uint8 header[5]; uint8 header[5];
uint32 count=0; uint32 count=0;
if(!ips) return;
char* buf = (char*)malloc(fp->size);
memcpy(buf,fp->EnsureMemorystream()->buf(),fp->size);
FCEU_printf(" Applying IPS...\n"); FCEU_printf(" Applying IPS...\n");
if(fread(header,1,5,ips)!=5) if(fread(header,1,5,ips)!=5)
{ {
fclose(ips); goto end;
return;
} }
if(memcmp(header,"PATCH",5)) if(memcmp(header,"PATCH",5))
{ {
fclose(ips); goto end;
return;
} }
while(fread(header,1,3,ips)==3) while(fread(header,1,3,ips)==3)
@ -81,39 +87,34 @@ void ApplyIPS(FILE *ips, MEMWRAP *dest)
if(!memcmp(header,"EOF",3)) if(!memcmp(header,"EOF",3))
{ {
FCEU_printf(" IPS EOF: Did %d patches\n\n",count); FCEU_printf(" IPS EOF: Did %d patches\n\n",count);
fclose(ips); goto end;
return;
} }
size=fgetc(ips)<<8; size=fgetc(ips)<<8;
size|=fgetc(ips); size|=fgetc(ips);
if(!size) /* RLE */ if(!size) /* RLE */
{ {
uint8 *start; char *start;
uint8 b; char b;
size=fgetc(ips)<<8; size=fgetc(ips)<<8;
size|=fgetc(ips); size|=fgetc(ips);
//FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size); //FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size);
if((offset+size)>dest->size) if((offset+size)>(uint32)fp->size)
{ {
uint8 *tmp;
// Probably a little slow. // Probably a little slow.
tmp=(uint8 *)realloc(dest->data,offset+size); buf=(char *)realloc(buf,offset+size);
if(!tmp) if(!buf)
{ {
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count); FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
fclose(ips); goto end;
return;
} }
dest->size=offset+size; memset(buf+fp->size,0,offset+size-fp->size);
dest->data=tmp; fp->size=offset+size;
memset(dest->data+dest->size,0,offset+size-dest->size);
} }
b=fgetc(ips); b=fgetc(ips);
start=dest->data+offset; start=buf+offset;
do do
{ {
*start=b; *start=b;
@ -123,94 +124,33 @@ void ApplyIPS(FILE *ips, MEMWRAP *dest)
else /* Normal patch */ else /* Normal patch */
{ {
//FCEU_printf(" Offset: %8d Size: %5d\n",offset,size); //FCEU_printf(" Offset: %8d Size: %5d\n",offset,size);
if((offset+size)>dest->size) if((offset+size)>(uint32)fp->size)
{ {
uint8 *tmp;
// Probably a little slow. // Probably a little slow.
tmp=(uint8 *)realloc(dest->data,offset+size); buf=(char *)realloc(buf,offset+size);
if(!tmp) if(!buf)
{ {
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count); FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
fclose(ips); goto end;
return;
} }
dest->data=tmp; memset(buf+fp->size,0,offset+size-fp->size);
memset(dest->data+dest->size,0,offset+size-dest->size);
} }
fread(dest->data+offset,1,size,ips); fread(buf+offset,1,size,ips);
} }
count++; count++;
} }
fclose(ips);
FCEU_printf(" Hard IPS end!\n"); FCEU_printf(" Hard IPS end!\n");
end:
fclose(ips);
memorystream* ms = new memorystream(buf,fp->size);
ms->giveBuf();
fp->SetStream(ms);
} }
static MEMWRAP *MakeMemWrap(void *tz, int type) std::string FCEU_MakeIpsFilename(FileBaseInfo fbi) {
{ char ret[FILENAME_MAX] = "";
MEMWRAP *tmp; sprintf(ret,"%s"PSS"%s%s.ips",fbi.filebasedirectory.c_str(),fbi.filebase.c_str(),fbi.ext.c_str());
return ret;
if(!(tmp=(MEMWRAP *)FCEU_malloc(sizeof(MEMWRAP))))
goto doret;
tmp->location=0;
if(type==0)
{
fseek((FILE *)tz,0,SEEK_END);
tmp->size=ftell((FILE *)tz);
fseek((FILE *)tz,0,SEEK_SET);
if(!(tmp->data=(uint8*)FCEU_malloc(tmp->size)))
{
free(tmp);
tmp=0;
goto doret;
}
fread(tmp->data,1,tmp->size,(FILE *)tz);
}
else if(type==1)
{
/* Bleck. The gzip file format has the size of the uncompressed data,
but I can't get to the info with the zlib interface(?). */
for(tmp->size=0; gzgetc(tz) != EOF; tmp->size++);
gzseek(tz,0,SEEK_SET);
if(!(tmp->data=(uint8 *)FCEU_malloc(tmp->size)))
{
free(tmp);
tmp=0;
goto doret;
}
gzread(tz,tmp->data,tmp->size);
}
else if(type==2)
{
unz_file_info ufo;
unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
tmp->size=ufo.uncompressed_size;
if(!(tmp->data=(uint8 *)FCEU_malloc(ufo.uncompressed_size)))
{
free(tmp);
tmp=0;
goto doret;
}
unzReadCurrentFile(tz,tmp->data,ufo.uncompressed_size);
}
doret:
if(type==0)
{
fclose((FILE *)tz);
}
else if(type==1)
{
gzclose(tz);
}
else if(type==2)
{
unzCloseCurrentFile(tz);
unzClose(tz);
}
return tmp;
} }
void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::string& file, std::string& fileToOpen) void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::string& file, std::string& fileToOpen)
@ -230,6 +170,56 @@ void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::strin
} }
} }
FileBaseInfo CurrentFileBase() {
return FileBaseInfo(FileBaseDirectory,FileBase,FileExt);
}
FileBaseInfo DetermineFileBase(const char *f) {
const char *tp1,*tp3;
char FileBase[2048];
char FileBaseDirectory[2048];
char FileExt[2048];
#if PSS_STYLE==4
tp1=((char *)strrchr(f,':'));
#elif PSS_STYLE==1
tp1=((char *)strrchr(f,'/'));
#else
tp1=((char *)strrchr(f,'\\'));
#if PSS_STYLE!=3
tp3=((char *)strrchr(f,'/'));
if(tp1<tp3) tp1=tp3;
#endif
#endif
if(!tp1)
{
tp1=f;
strcpy(FileBaseDirectory,".");
}
else
{
memcpy(FileBaseDirectory,f,tp1-f);
FileBaseDirectory[tp1-f]=0;
tp1++;
}
if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
{
memcpy(FileBase,tp1,tp3-tp1);
FileBase[tp3-tp1]=0;
strcpy(FileExt,tp3);
}
else
{
strcpy(FileBase,tp1);
FileExt[0]=0;
}
return FileBaseInfo(FileBaseDirectory,FileBase,FileExt);
}
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index) FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index)
{ {
FILE *ipsfile=0; FILE *ipsfile=0;
@ -246,6 +236,8 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
std::string archive,fname,fileToOpen; std::string archive,fname,fileToOpen;
FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen); FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen);
if(!ipsfn) {
}
//try to setup the ips file //try to setup the ips file
if(ipsfn && read) if(ipsfn && read)
@ -270,7 +262,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
FCEU_fseek(fceufp,0,SEEK_END); FCEU_fseek(fceufp,0,SEEK_END);
fceufp->size = FCEU_ftell(fceufp); fceufp->size = FCEU_ftell(fceufp);
FCEU_fseek(fceufp,0,SEEK_SET); FCEU_fseek(fceufp,0,SEEK_SET);
return fceufp; goto applyips;
} }
else else
{ {
@ -282,8 +274,15 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0); fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
else else
fceufp = FCEUD_OpenArchive(asr, archive, &fname); fceufp = FCEUD_OpenArchive(asr, archive, &fname);
return fceufp; goto applyips;
} }
applyips:
//try to open the ips file
if(!ipsfile && !ipsfn)
ipsfile=FCEUD_UTF8fopen(FCEU_MakeIpsFilename(DetermineFileBase(fceufp->filename.c_str())),"rb");
ApplyIPS(ipsfile,fceufp);
return fceufp;
} }
#else #else
std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode); std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode);
@ -405,12 +404,6 @@ std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for a
return movieFilenamePart; return movieFilenamePart;
} }
static std::string BaseDirectory;
char FileBase[2048];
static char FileExt[2048]; //Includes the . character, as in ".nes"
static char FileBaseDirectory[2048];
/// Updates the base directory /// Updates the base directory
void FCEUI_SetBaseDirectory(std::string const & dir) void FCEUI_SetBaseDirectory(std::string const & dir)
{ {
@ -615,7 +608,9 @@ std::string FCEU_MakeFName(int type, int id1, const char *cd1)
else else
sprintf(ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory.c_str(),FileBase); sprintf(ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory.c_str(),FileBase);
break; break;
case FCEUMKF_IPS:sprintf(ret,"%s"PSS"%s%s.ips",FileBaseDirectory,FileBase,FileExt);break; case FCEUMKF_IPS:
strcpy(ret,FCEU_MakeIpsFilename(CurrentFileBase()).c_str());
break;
case FCEUMKF_GGROM:sprintf(ret,"%s"PSS"gg.rom",BaseDirectory.c_str());break; case FCEUMKF_GGROM:sprintf(ret,"%s"PSS"gg.rom",BaseDirectory.c_str());break;
case FCEUMKF_FDSROM: case FCEUMKF_FDSROM:
if(odirs[FCEUIOD_FDSROM]) if(odirs[FCEUIOD_FDSROM])
@ -646,42 +641,9 @@ std::string FCEU_MakeFName(int type, int id1, const char *cd1)
void GetFileBase(const char *f) void GetFileBase(const char *f)
{ {
const char *tp1,*tp3; FileBaseInfo fbi = DetermineFileBase(f);
strcpy(FileBase,fbi.filebase.c_str());
#if PSS_STYLE==4 strcpy(FileBaseDirectory,fbi.filebasedirectory.c_str());
tp1=((char *)strrchr(f,':'));
#elif PSS_STYLE==1
tp1=((char *)strrchr(f,'/'));
#else
tp1=((char *)strrchr(f,'\\'));
#if PSS_STYLE!=3
tp3=((char *)strrchr(f,'/'));
if(tp1<tp3) tp1=tp3;
#endif
#endif
if(!tp1)
{
tp1=f;
strcpy(FileBaseDirectory,".");
}
else
{
memcpy(FileBaseDirectory,f,tp1-f);
FileBaseDirectory[tp1-f]=0;
tp1++;
}
if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
{
memcpy(FileBase,tp1,tp3-tp1);
FileBase[tp3-tp1]=0;
strcpy(FileExt,tp3);
}
else
{
strcpy(FileBase,tp1);
FileExt[0]=0;
}
} }
bool FCEU_isFileInArchive(const char *path) bool FCEU_isFileInArchive(const char *path)

View File

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include "types.h" #include "types.h"
#include "utils/memorystream.h"
struct FCEUFILE { struct FCEUFILE {
//the stream you can use to access the data //the stream you can use to access the data
@ -43,6 +44,38 @@ struct FCEUFILE {
enum { enum {
READ, WRITE, READWRITE READ, WRITE, READWRITE
} mode; } mode;
//guarantees that the file contains a memorystream, and returns it for your convenience
memorystream* EnsureMemorystream() {
memorystream* ret = dynamic_cast<memorystream*>(stream);
if(ret) return ret;
//nope, we need to create it: copy the contents
ret = new memorystream(size);
stream->read(ret->buf(),size);
delete stream;
stream = ret;
return ret;
}
void SetStream(std::iostream *newstream) {
if(stream) delete stream;
stream = newstream;
//get the size of the stream
stream->seekg(0,std::ios::end);
size = stream->tellg();
stream->seekg(0,std::ios::beg);
}
};
struct FileBaseInfo {
FileBaseInfo() {}
FileBaseInfo(std::string fbd, std::string fb, std::string ext)
: filebasedirectory(fbd)
, filebase(fb)
, ext(ext)
{}
std::string filebase, filebasedirectory, ext;
}; };
struct ArchiveScanRecord struct ArchiveScanRecord

View File

@ -1,3 +1,6 @@
#ifndef _memorystream_h_
#define _memorystream_h_
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <sstream> #include <sstream>
@ -145,6 +148,11 @@ public:
return buf; return buf;
} }
//if we were provided a buffer, then calling this gives us ownership of it
void giveBuf() {
myBuf = true;
}
private: private:
void dosync(int c) void dosync(int c)
@ -285,4 +293,9 @@ public:
//if the memorystream wraps a vector, the vector will be trimmed to the correct size,. //if the memorystream wraps a vector, the vector will be trimmed to the correct size,.
//you probably need to use this if you are using the vector wrapper //you probably need to use this if you are using the vector wrapper
void trim() { streambuf.trim(); } void trim() { streambuf.trim(); }
void giveBuf() { streambuf.giveBuf(); }
}; };
#endif