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---
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 [ 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 - 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 bug where fceux would close when file dialogs were closed
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"
#endif
int AFon = 1, AFoff = 1, AutoFireOffset = 0; //For keeping track of autofire settings
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)
@ -339,8 +340,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
FCEU_printf("Loading %s...\n\n",name);
ipsfn=strdup(FCEU_MakeFName(FCEUMKF_IPS,0,0).c_str());
fp=FCEU_fopen(name,ipsfn,"rb",0);
fp=FCEU_fopen(name,0,"rb",0);
if(!fp)
{
return 0;
@ -348,7 +348,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
GetFileBase(fp->filename.c_str());
free(ipsfn);
//free(ipsfn);
if(!fp) {
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...
void PowerNES(void)
{
/*void MapperInit();
MapperInit();*/
if(!suppressAddPowerCommand)
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
if(!GameInfo) return;

View File

@ -47,30 +47,36 @@
#include "movie.h"
#include "driver.h"
#include "utils/xstring.h"
#include "utils/memorystream.h"
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];
uint32 count=0;
if(!ips) return;
char* buf = (char*)malloc(fp->size);
memcpy(buf,fp->EnsureMemorystream()->buf(),fp->size);
FCEU_printf(" Applying IPS...\n");
if(fread(header,1,5,ips)!=5)
{
fclose(ips);
return;
goto end;
}
if(memcmp(header,"PATCH",5))
{
fclose(ips);
return;
goto end;
}
while(fread(header,1,3,ips)==3)
@ -81,39 +87,34 @@ void ApplyIPS(FILE *ips, MEMWRAP *dest)
if(!memcmp(header,"EOF",3))
{
FCEU_printf(" IPS EOF: Did %d patches\n\n",count);
fclose(ips);
return;
goto end;
}
size=fgetc(ips)<<8;
size|=fgetc(ips);
if(!size) /* RLE */
{
uint8 *start;
uint8 b;
char *start;
char b;
size=fgetc(ips)<<8;
size|=fgetc(ips);
//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.
tmp=(uint8 *)realloc(dest->data,offset+size);
if(!tmp)
buf=(char *)realloc(buf,offset+size);
if(!buf)
{
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
fclose(ips);
return;
goto end;
}
dest->size=offset+size;
dest->data=tmp;
memset(dest->data+dest->size,0,offset+size-dest->size);
memset(buf+fp->size,0,offset+size-fp->size);
fp->size=offset+size;
}
b=fgetc(ips);
start=dest->data+offset;
start=buf+offset;
do
{
*start=b;
@ -123,94 +124,33 @@ void ApplyIPS(FILE *ips, MEMWRAP *dest)
else /* Normal patch */
{
//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.
tmp=(uint8 *)realloc(dest->data,offset+size);
if(!tmp)
buf=(char *)realloc(buf,offset+size);
if(!buf)
{
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
fclose(ips);
return;
goto end;
}
dest->data=tmp;
memset(dest->data+dest->size,0,offset+size-dest->size);
memset(buf+fp->size,0,offset+size-fp->size);
}
fread(dest->data+offset,1,size,ips);
fread(buf+offset,1,size,ips);
}
count++;
}
fclose(ips);
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)
{
MEMWRAP *tmp;
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;
std::string FCEU_MakeIpsFilename(FileBaseInfo fbi) {
char ret[FILENAME_MAX] = "";
sprintf(ret,"%s"PSS"%s%s.ips",fbi.filebasedirectory.c_str(),fbi.filebase.c_str(),fbi.ext.c_str());
return ret;
}
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)
{
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;
FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen);
if(!ipsfn) {
}
//try to setup the ips file
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);
fceufp->size = FCEU_ftell(fceufp);
FCEU_fseek(fceufp,0,SEEK_SET);
return fceufp;
goto applyips;
}
else
{
@ -282,8 +274,15 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
else
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
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;
}
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
void FCEUI_SetBaseDirectory(std::string const & dir)
{
@ -615,7 +608,9 @@ std::string FCEU_MakeFName(int type, int id1, const char *cd1)
else
sprintf(ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory.c_str(),FileBase);
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_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)
{
const char *tp1,*tp3;
#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;
}
FileBaseInfo fbi = DetermineFileBase(f);
strcpy(FileBase,fbi.filebase.c_str());
strcpy(FileBaseDirectory,fbi.filebasedirectory.c_str());
}
bool FCEU_isFileInArchive(const char *path)

View File

@ -4,6 +4,7 @@
#include <string>
#include <iostream>
#include "types.h"
#include "utils/memorystream.h"
struct FCEUFILE {
//the stream you can use to access the data
@ -43,6 +44,38 @@ struct FCEUFILE {
enum {
READ, WRITE, READWRITE
} 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

View File

@ -1,3 +1,6 @@
#ifndef _memorystream_h_
#define _memorystream_h_
#include <iostream>
#include <vector>
#include <sstream>
@ -145,6 +148,11 @@ public:
return buf;
}
//if we were provided a buffer, then calling this gives us ownership of it
void giveBuf() {
myBuf = true;
}
private:
void dosync(int c)
@ -285,4 +293,9 @@ public:
//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
void trim() { streambuf.trim(); }
void giveBuf() { streambuf.giveBuf(); }
};
#endif