#include "Typedef.h" #include "App.h" #include "Pathlib.h" #include "Config.h" #include "Debugout.h" #include "unzip.h" #include "ips.h" #include 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 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; }