AxibugEmuOnline/virtuanessrc097-master/NES/IPS.cpp

177 lines
7.7 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Typedef.h"
#include "App.h"
#include "Pathlib.h"
#include "Config.h"
#include "Debugout.h"
#include "unzip.h"
#include "ips.h"
#include <vector>
using namespace std;
static BOOL PatchIPS( LPBYTE pIPS, LPBYTE pROM, LONG imagesize, LONG ipssize )
{
INT index = 0;
// IPS patch?
if( ::strncmp( (const char *)pIPS, "PATCH", 5 ) != 0 ) {
return FALSE;
}
index += 5;
INT offset, length;
while( TRUE ) {
// read patch address offset
if( index+3 > ipssize ) {
return FALSE;
}
offset = ((INT)pIPS[index]<<16)|((INT)pIPS[index+1]<<8)|((INT)pIPS[index+2]);
index += 3;
// END?
if( offset == 0x00454f46 ) {
break;
}
// read patch length
if( index+2 > ipssize ) {
return FALSE;
}
length = ((INT)pIPS[index]<<8)|((INT)pIPS[index+1]);
index += 2;
if( length ) {
while( length-- ) {
if( offset < imagesize ) {
pROM[ offset++ ] = pIPS[ index ];
}
if( ++index > ipssize ) {
return FALSE;
}
}
} else {
if( index+2 > ipssize ) {
return FALSE;
}
length = ((INT)pIPS[index]<<8)|((INT)pIPS[index+1]);
index += 2;
BYTE data = pIPS[ index ];
if( ++index > ipssize ) {
return FALSE;
}
while( length-- ) {
if( offset < imagesize ) {
pROM[ offset++ ] = data;
}
}
}
}
return TRUE;
}
BOOL ApplyIPS( const char* filename, LPBYTE pROM, LONG imagesize )
{
string pathstr, tempstr;
if( Config.path.bIpsPath ) {
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szIpsPath );
} else {
pathstr = CPathlib::SplitPath( filename );
}
string fname = CPathlib::SplitFname( filename );
tempstr = CPathlib::MakePathExt( pathstr.c_str(), fname.c_str(), "ips" );
DEBUGOUT( "IPS name:%s\n", tempstr.c_str() );
FILE* fp = NULL;
vector<BYTE> tempbuf;
LONG ipssize = 0;
DEBUGOUT( "Open ips\n" );
if( (fp = ::fopen( tempstr.c_str(), "rb" )) ) {
LONG ipssize;
::fseek( fp, 0, SEEK_END );
ipssize = ::ftell( fp );
::fseek( fp, 0, SEEK_SET );
tempbuf.reserve( ipssize );
// load IPS file
if( ::fread( (void*)&tempbuf[0], ipssize, 1, fp ) != 1 ) {
DEBUGOUT( "IPS load error.\n" );
FCLOSE( fp );
return FALSE;
}
FCLOSE( fp );
DEBUGOUT( "IPS patching.\n" );
return PatchIPS( (LPBYTE)&tempbuf[0], pROM, imagesize, ipssize );
}
string ext = CPathlib::SplitExt( filename );
if( ext != ".zip" ) {
DEBUGOUT( "Not zip\n" );
return FALSE;
}
DEBUGOUT( "Open zip\n" );
unzFile unzipFile = NULL;
unz_global_info unzipGlobalInfo;
unz_file_info unzipFileInfo;
char fname_buf[256];
if( !(unzipFile = unzOpen( (const char*)filename )) )
return FALSE;
if( unzGetGlobalInfo( unzipFile, &unzipGlobalInfo ) != UNZ_OK ) {
unzClose( unzipFile );
return FALSE;
}
for( uLong i = 0; i < unzipGlobalInfo.number_entry; i++ ) {
if( unzGetCurrentFileInfo( unzipFile, &unzipFileInfo, fname_buf, sizeof(fname_buf), NULL, 0, NULL, 0 ) != UNZ_OK )
break;
char* pExt = ::PathFindExtension( fname_buf );
if( _stricmp( pExt, ".ips" ) == 0 ) {
if( unzipFileInfo.uncompressed_size ) {
if( unzOpenCurrentFile( unzipFile ) != UNZ_OK )
break;
if( unzipFileInfo.uncompressed_size > 0 ) {
tempbuf.reserve( unzipFileInfo.uncompressed_size );
uInt size = unzReadCurrentFile( unzipFile, &tempbuf[0], unzipFileInfo.uncompressed_size );
if( size != unzipFileInfo.uncompressed_size )
break;
}
ipssize = unzipFileInfo.uncompressed_size;
if( unzCloseCurrentFile( unzipFile ) != UNZ_OK )
break;
unzClose( unzipFile );
return PatchIPS( (LPBYTE)&tempbuf[0], pROM, imagesize, ipssize );
}
}
// Next file
if( (i+1) < unzipGlobalInfo.number_entry ) {
if( unzGoToNextFile( unzipFile ) != UNZ_OK ) {
break;
}
}
}
unzClose( unzipFile );
return FALSE;
}