forked from sin365/AxibugEmuOnline
177 lines
7.7 KiB
C++
177 lines
7.7 KiB
C++
#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;
|
||
}
|