Page 143 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 通常モードに戻る ┃ INDEX ┃ ≪前へ │ 次へ≫ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ▼IPS Patching Feather 03/11/9(日) 3:13 ─────────────────────────────────────── ■題名 : IPS Patching ■名前 : Feather ■日付 : 03/11/9(日) 3:13 -------------------------------------------------------------------------
Info: Patches 0.86a to apply IPS patches dynamically. Works only for *.nes,*.fds,*.zip files. Adds functionality to class CPathlib. Note: (Sorry for the long patches) Usage: 1. *.nes,*.fds Ex. ips/Test (JUE).ips 2. *.zip Ex. ips/Test (JUE).ips Ex. Test (JUE).ips [inside "Test (JUE).zip"] Patch: [IPS.cpp] #include "Typedef.h" #include "Pathlib.h" #include "unzip.h" #include "ips.h" #include <string> using namespace std; INT fileType; // file fileType: *.ips, *.zip, *.nes, ... INT GetFileType( const char* fname ) { string ext = CPathlib::SplitExt( fname ); if( ext==".ips" ) return 0; if( ext==".nes" ) return 1; if( ext==".fds" ) return 1; if( ext==".zip" ) return 2; return -1; } static INT readMSB( void *fp, INT nbytes ) { INT value = 0; while ( nbytes-- ) { INT ch; switch ( fileType ) { case 1: ch = fgetc( (FILE *) fp ); if( ch == EOF ) return -1; break; case 2: unzReadCurrentFile( (unzFile) fp,&ch,1 ); if( unzeof( (unzFile) fp ) ) return -1; break; } value = (value << 8) | (ch & 0xFF); } return value; } static INT IPSPatch( void* fp, UBYTE* rom, LONG& size ) { char buffer[5]; INT length; INT offset; switch( fileType ) { case 1: if( fread( buffer, 1, 5, (FILE *) fp ) != 5) return -1; break; case 2: if( unzReadCurrentFile( (unzFile) fp,buffer,5 ) <= 0) return -1; break; } // check magic header if( strncmp( buffer, "PATCH", 5 ) != 0 ) return -1; // IPS 1.0 Format while( 1 ) { offset = readMSB( fp, 3 ); if( offset == -1 ) return -1; // IPS end: ascii value of "EOF" if( offset == 0x454f46 ) break; length = readMSB( fp, 2 ); if( length == -1 ) return -1; // direct patch block if( length ) { INT ch; // expand rom if necessary if( offset+length > size ) { size = offset+length; rom = (UBYTE *) realloc( rom, size ); } while( length-- ) { ch = readMSB( fp, 1 ); if( ch == EOF ) return -1; rom[ offset++ ] = (UBYTE) ch; } } else { INT ch; // run-length encoded (RLE) block length = readMSB( fp, 2 ); if( length == -1 ) return -1; ch = readMSB( fp, 1 ); if( ch == EOF ) return -1; // expand rom if necessary if( offset+length > size ) { size = offset+length; rom = (UBYTE *) realloc( rom, size ); } while( length-- ) rom[ offset++ ] = (UBYTE) ch; } } // IPS 2.0 Format // resize rom if needed length = readMSB( fp,3 ); if( length != -1 && length != size ) { size = length; rom = (UBYTE *) realloc( rom,size ); } return 0; } void ApplyIPS( const char* fullname, UBYTE* rom, LONG& size ) { FILE* fp=NULL; INT success=0; string fname = CPathlib::SplitFname( fullname ); string ipsname = CPathlib::MakePathExt( "ips/", fname.c_str(), "ips" ); // First try the non-archived ips fileType=1; if(( fp = fopen( ipsname.c_str(), "rb" ))) { if( IPSPatch( fp, rom, size )) { // patch successful fclose( fp ); return; } // non-success fclose( fp ); } // Next try searching the archives fileType = GetFileType( fullname ); ipsname = CPathlib::MakePathExt( "", fname.c_str(), "ips" ); // Search the zip next if( fileType==2 ) { char buffer[2048]; INT filesize; // Problems will be caught with unzGetCurrentFileInfo unz_file_info info; unzFile unz = unzOpen( fullname ); unzGoToFirstFile( unz ); // search zip for the matching ips file while( 1 ) { if( unzGetCurrentFileInfo( unz, &info, buffer, sizeof( buffer ), NULL, 0, NULL, 0 ) != UNZ_OK ) break; if( GetFileType( buffer ) == 0 && stricmp( buffer,ipsname.c_str() ) == 0 ) { // patch rom and stop looking unzOpenCurrentFile( unz ); IPSPatch( unz, rom, size ); unzCloseCurrentFile( unz ); break; } else { // skip to the next file if( unzGoToNextFile( unz ) != UNZ_OK ) break; } } // end while unzClose( unz ); } } -------------------------------------------------------------------------- [IPS.h] void ApplyIPS( const char* fullname, UCHAR* rom, LONG& size ); -------------------------------------------------------------------------- [Pathlib.cpp] (line 39) string CPathlib::SplitExt( LPCSTR lpszPath ) { CHAR szExt [ _MAX_EXT ]; CHAR szTemp [ _MAX_PATH+1 ]; string fname; ::_splitpath( lpszPath, NULL, NULL, NULL, szExt ); fname = szExt; return fname; } -------------------------------------------------------------------------- [Pathlib.h] (line 26) static string SplitExt( LPCSTR lpszPath ); -------------------------------------------------------------------------- [Nes/Rom.cpp] (line 113) // Since the zip/fds/nes is defrosted and raw, now apply the patch //if( Config.misc.bAutoIps ) { ApplyIPS( fname, temp, FileSize ); ::memcpy( &header, temp, sizeof(NESHEADER) ); //} |