過去ログ

                                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) );
        //}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━    通常モードに戻る  ┃  INDEX  ┃  ≪前へ  │  次へ≫    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                 Page 143