mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 21:14:21 +01:00
add IPS/UPS/PPF patch support
This commit is contained in:
parent
6d4bab0809
commit
fb54f957e1
@ -9,3 +9,5 @@
|
||||
***************************************************************************/
|
||||
|
||||
void SetupCheats();
|
||||
|
||||
extern SCheatData Cheat;
|
||||
|
131
source/ngc/memfile.cpp
Normal file
131
source/ngc/memfile.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/****************************************************************************
|
||||
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||
*
|
||||
* Tantric October 2008
|
||||
*
|
||||
* memfile.cpp
|
||||
*
|
||||
* Memory-based replacement for standard C file functions
|
||||
* This allows standard file calls to be replaced by memory based ones
|
||||
* With little modification required to the code
|
||||
***************************************************************************/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "memfile.h"
|
||||
|
||||
/****************************************************************************
|
||||
* memfopen
|
||||
* memory replacement for fopen
|
||||
*
|
||||
* Creates a memory-based file
|
||||
***************************************************************************/
|
||||
MFILE * memfopen(char * buffer, int size)
|
||||
{
|
||||
MFILE *f = (MFILE *)malloc(sizeof(MFILE));
|
||||
|
||||
f->buffer = buffer;
|
||||
f->offset = 0;
|
||||
f->size = size;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* memfclose
|
||||
* memory replacement for fclose
|
||||
*
|
||||
* 'Closes' the memory file specified
|
||||
***************************************************************************/
|
||||
int memfclose(MFILE * src)
|
||||
{
|
||||
free(src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* memfseek
|
||||
* memory replacement for fseek
|
||||
*
|
||||
* Sets the position indicator associated with the stream to a new position
|
||||
* defined by adding offset to a reference position specified by origin.
|
||||
***************************************************************************/
|
||||
int memfseek ( MFILE * m, long int offset, int origin )
|
||||
{
|
||||
int success = 0; // 0 indicates success
|
||||
|
||||
switch(origin)
|
||||
{
|
||||
case MSEEK_SET:
|
||||
if(offset >= 0 && offset <= m->size)
|
||||
m->offset = offset;
|
||||
else
|
||||
success = 1; // failure
|
||||
break;
|
||||
case MSEEK_CUR:
|
||||
if((m->offset + offset) >= 0 && (m->offset + offset) <= m->size)
|
||||
m->offset += offset;
|
||||
else
|
||||
success = 1; // failure
|
||||
break;
|
||||
case MSEEK_END:
|
||||
if((m->size + offset) >= 0 && (m->size + offset) <= m->size)
|
||||
m->offset = m->size + offset;
|
||||
else
|
||||
success = 1; // failure
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* memftell
|
||||
* memory replacement for ftell
|
||||
*
|
||||
* Get current position in stream (offset + 1)
|
||||
***************************************************************************/
|
||||
long int memftell (MFILE * stream)
|
||||
{
|
||||
return stream->offset; // to emulate ftell behavior
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* memfread
|
||||
* memory replacement for fread
|
||||
*
|
||||
* Reads an array of count elements, each one with a size of size bytes, from
|
||||
* the buffer and stores them in the block of memory specified by ptr. The
|
||||
* postion indicator of the buffer is advanced by the total amount of bytes
|
||||
* read. The total amount of bytes read if successful is (size * count).
|
||||
***************************************************************************/
|
||||
size_t memfread(void * dst, size_t size, size_t count, MFILE * src)
|
||||
{
|
||||
if(src->offset >= src->size) // reached end of buffer
|
||||
return 0;
|
||||
|
||||
int numbytes = size*count;
|
||||
|
||||
if((src->offset + numbytes) > src->size) // can't read full # requested
|
||||
numbytes = src->size - src->offset; // do a partial read
|
||||
|
||||
if(numbytes > 0)
|
||||
memcpy(dst, src->buffer+src->offset, numbytes);
|
||||
|
||||
src->offset += numbytes;
|
||||
return numbytes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* memfgetc
|
||||
* memory replacement for fgetc
|
||||
*
|
||||
* Returns the next character in the buffer specified, and advances the
|
||||
* postion indicator of the buffer by 1.
|
||||
***************************************************************************/
|
||||
int memfgetc(MFILE * src)
|
||||
{
|
||||
if(src->offset >= src->size) // reached end of buffer
|
||||
return MEOF;
|
||||
else
|
||||
return src->buffer[src->offset++];
|
||||
}
|
34
source/ngc/memfile.h
Normal file
34
source/ngc/memfile.h
Normal file
@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||
*
|
||||
* Tantric October 2008
|
||||
*
|
||||
* memfile.h
|
||||
*
|
||||
* Memory-based replacement for standard C file functions
|
||||
* This allows standard file calls to be replaced by memory based ones
|
||||
* With little modification required to the code
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _MEMFILE_H_
|
||||
#define _MEMFILE_H_
|
||||
|
||||
typedef struct MFile {
|
||||
char *buffer; // pointer to buffer memory
|
||||
long int offset; // current position indicator in buffer
|
||||
long int size; // total file (buffer) size
|
||||
} MFILE;
|
||||
|
||||
#define MSEEK_SET 0
|
||||
#define MSEEK_CUR 1
|
||||
#define MSEEK_END 2
|
||||
#define MEOF (-1)
|
||||
|
||||
MFILE * memfopen(char * buffer, int size);
|
||||
int memfclose(MFILE * src);
|
||||
int memfseek ( MFILE * m, long int offset, int origin );
|
||||
long int memftell (MFILE * stream);
|
||||
size_t memfread(void * dst, size_t size, size_t count, MFILE * src);
|
||||
int memfgetc(MFILE * src);
|
||||
|
||||
#endif
|
@ -54,23 +54,16 @@ extern "C" {
|
||||
#include "menudraw.h"
|
||||
#include "cheatmgr.h"
|
||||
#include "input.h"
|
||||
|
||||
extern void DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize);
|
||||
|
||||
extern SCheatData Cheat;
|
||||
|
||||
extern int menu;
|
||||
|
||||
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
|
||||
#include "patch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Reboot / Exit
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HW_RVL
|
||||
#define PSOSDLOADID 0x7c6000a6
|
||||
int *psoid = (int *) 0x80001800;
|
||||
void (*PSOReload) () = (void (*)()) 0x80001800;
|
||||
#ifdef HW_DOL
|
||||
#define PSOSDLOADID 0x7c6000a6
|
||||
int *psoid = (int *) 0x80001800;
|
||||
void (*PSOReload) () = (void (*)()) 0x80001800;
|
||||
#endif
|
||||
|
||||
void Reboot()
|
||||
@ -78,8 +71,8 @@ void Reboot()
|
||||
#ifdef HW_RVL
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
#else
|
||||
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
|
||||
*SOFTRESET_ADR = 0x00000000;
|
||||
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
|
||||
*SOFTRESET_ADR = 0x00000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -106,11 +99,12 @@ LoadManager ()
|
||||
{
|
||||
int loadROM = OpenROM(GCSettings.LoadMethod);
|
||||
|
||||
/***
|
||||
* check for autoloadsram / freeze
|
||||
***/
|
||||
if ( loadROM == 1 ) // if ROM was loaded, load the SRAM & settings
|
||||
if (loadROM)
|
||||
{
|
||||
// load UPS/IPS/PPF patch
|
||||
LoadPatch(GCSettings.LoadMethod);
|
||||
|
||||
// load SRAM or snapshot
|
||||
if ( GCSettings.AutoLoad == 1 )
|
||||
LoadSRAM(GCSettings.SaveMethod, SILENT);
|
||||
else if ( GCSettings.AutoLoad == 2 )
|
||||
|
@ -44,4 +44,6 @@ void ShowProgress (char *msg, int done, int total);
|
||||
void DrawPolygon (int vertices, int *varray, u8 r, u8 g, u8 b);
|
||||
void DrawLineFast( int startx, int endx, int y, u8 r, u8 g, u8 b );
|
||||
|
||||
extern int menu;
|
||||
|
||||
#endif
|
||||
|
475
source/ngc/patch.cpp
Normal file
475
source/ngc/patch.cpp
Normal file
@ -0,0 +1,475 @@
|
||||
/****************************************************************************
|
||||
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||
*
|
||||
* Tantric October 2008
|
||||
*
|
||||
* patch.cpp
|
||||
*
|
||||
* IPS/UPS/PPF patch support
|
||||
***************************************************************************/
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "memmap.h"
|
||||
|
||||
#include "snes9xGX.h"
|
||||
#include "menudraw.h"
|
||||
#include "fileop.h"
|
||||
#include "dvd.h"
|
||||
#include "smbop.h"
|
||||
#include "memfile.h"
|
||||
#include "filesel.h"
|
||||
|
||||
static int readInt2(MFILE *f) {
|
||||
int res = 0;
|
||||
int c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
res = c;
|
||||
c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
return c + (res << 8);
|
||||
}
|
||||
|
||||
static int readInt3(MFILE *f) {
|
||||
int res = 0;
|
||||
int c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
res = c;
|
||||
c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
res = c + (res << 8);
|
||||
c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
return c + (res << 8);
|
||||
}
|
||||
|
||||
static s64 readInt4(MFILE *f) {
|
||||
s64 tmp, res = 0;
|
||||
int c;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
tmp = c;
|
||||
res = res + (tmp << (i * 8));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static s64 readInt8(MFILE *f) {
|
||||
s64 tmp, res = 0;
|
||||
int c;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return -1;
|
||||
tmp = c;
|
||||
res = res + (tmp << (i * 8));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static s64 readVarPtr(MFILE *f) {
|
||||
s64 offset = 0, shift = 1;
|
||||
for (;;) {
|
||||
int c = memfgetc(f);
|
||||
if (c == MEOF)
|
||||
return 0;
|
||||
offset += (c & 0x7F) * shift;
|
||||
if (c & 0x80)
|
||||
break;
|
||||
shift <<= 7;
|
||||
offset += shift;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
static uLong computePatchCRC(MFILE *f, unsigned int size) {
|
||||
Bytef buf[4096];
|
||||
long readed;
|
||||
|
||||
uLong crc = crc32(0L, Z_NULL, 0);
|
||||
do {
|
||||
readed = memfread(buf, 1, MIN(size, sizeof(buf)), f);
|
||||
crc = crc32(crc, buf, readed);
|
||||
size -= readed;
|
||||
} while (readed > 0);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
bool patchApplyIPS(MFILE * f, u8 **r, int *s) {
|
||||
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
||||
|
||||
bool result = false;
|
||||
|
||||
u8 *rom = *r;
|
||||
int size = *s;
|
||||
if (memfgetc(f) == 'P' && memfgetc(f) == 'A' && memfgetc(f) == 'T'
|
||||
&& memfgetc(f) == 'C' && memfgetc(f) == 'H') {
|
||||
int b;
|
||||
int offset;
|
||||
int len;
|
||||
|
||||
result = true;
|
||||
|
||||
for (;;) {
|
||||
// read offset
|
||||
offset = readInt3(f);
|
||||
// if offset == MEOF, end of patch
|
||||
if (offset == 0x454f46 || offset == -1)
|
||||
break;
|
||||
// read length
|
||||
len = readInt2(f);
|
||||
if (!len) {
|
||||
// len == 0, RLE block
|
||||
len = readInt2(f);
|
||||
// byte to fill
|
||||
int c = memfgetc(f);
|
||||
if (c == -1)
|
||||
break;
|
||||
b = (u8) c;
|
||||
} else
|
||||
b = -1;
|
||||
// check if we need to reallocate our ROM
|
||||
if ((offset + len) >= size) {
|
||||
#ifdef NGC
|
||||
size = offset + len;
|
||||
#else
|
||||
size *= 2;
|
||||
rom = (u8 *) realloc(rom, size);
|
||||
#endif
|
||||
*r = rom;
|
||||
*s = size;
|
||||
}
|
||||
if (b == -1) {
|
||||
// normal block, just read the data
|
||||
if (memfread(&rom[offset], 1, len, f) != (size_t) len)
|
||||
break;
|
||||
} else {
|
||||
// fill the region with the given byte
|
||||
while (len--) {
|
||||
rom[offset++] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool patchApplyUPS(MFILE * f, u8 **rom, int *size) {
|
||||
|
||||
s64 srcCRC, dstCRC, patchCRC;
|
||||
|
||||
memfseek(f, 0, MSEEK_END);
|
||||
long int patchSize = memftell(f);
|
||||
if (patchSize < 20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memfseek(f, 0, MSEEK_SET);
|
||||
|
||||
if (memfgetc(f) != 'U' || memfgetc(f) != 'P' || memfgetc(f) != 'S'
|
||||
|| memfgetc(f) != '1') {
|
||||
return false;
|
||||
}
|
||||
|
||||
memfseek(f, -12, MSEEK_END);
|
||||
srcCRC = readInt4(f);
|
||||
dstCRC = readInt4(f);
|
||||
patchCRC = readInt4(f);
|
||||
if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memfseek(f, 0, MSEEK_SET);
|
||||
u32 crc = computePatchCRC(f, patchSize - 4);
|
||||
|
||||
if (crc != patchCRC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
crc = crc32(0L, Z_NULL, 0);
|
||||
crc = crc32(crc, *rom, *size);
|
||||
|
||||
memfseek(f, 4, MSEEK_SET);
|
||||
s64 dataSize;
|
||||
s64 srcSize = readVarPtr(f);
|
||||
s64 dstSize = readVarPtr(f);
|
||||
|
||||
if (crc == srcCRC) {
|
||||
dataSize = srcSize;
|
||||
} else if (crc == dstCRC) {
|
||||
dataSize = dstSize;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (dataSize != *size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
s64 relative = 0;
|
||||
u8 *mem;
|
||||
while (memftell(f) < patchSize - 12) {
|
||||
relative += readVarPtr(f);
|
||||
if (relative > dataSize)
|
||||
continue;
|
||||
mem = *rom + relative;
|
||||
for (s64 i = relative; i < dataSize; i++) {
|
||||
int x = memfgetc(f);
|
||||
relative++;
|
||||
if (!x)
|
||||
break;
|
||||
if (i < dataSize) {
|
||||
*mem++ ^= x;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ppfVersion(MFILE *f) {
|
||||
memfseek(f, 0, MSEEK_SET);
|
||||
if (memfgetc(f) != 'P' || memfgetc(f) != 'P' || memfgetc(f) != 'F')
|
||||
return 0;
|
||||
switch (memfgetc(f)) {
|
||||
case '1':
|
||||
return 1;
|
||||
case '2':
|
||||
return 2;
|
||||
case '3':
|
||||
return 3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ppfFileIdLen(MFILE *f, int version) {
|
||||
if (version == 2) {
|
||||
memfseek(f, -8, MSEEK_END);
|
||||
} else {
|
||||
memfseek(f, -6, MSEEK_END);
|
||||
}
|
||||
|
||||
if (memfgetc(f) != '.' || memfgetc(f) != 'D' || memfgetc(f) != 'I'
|
||||
|| memfgetc(f) != 'Z')
|
||||
return 0;
|
||||
|
||||
return (version == 2) ? readInt4(f) : readInt2(f);
|
||||
}
|
||||
|
||||
static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size) {
|
||||
memfseek(f, 0, MSEEK_END);
|
||||
int count = memftell(f);
|
||||
if (count < 56)
|
||||
return false;
|
||||
count -= 56;
|
||||
|
||||
memfseek(f, 56, MSEEK_SET);
|
||||
|
||||
u8 *mem = *rom;
|
||||
|
||||
while (count > 0) {
|
||||
int offset = readInt4(f);
|
||||
if (offset == -1)
|
||||
break;
|
||||
int len = memfgetc(f);
|
||||
if (len == MEOF)
|
||||
break;
|
||||
if (offset + len > *size)
|
||||
break;
|
||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
||||
break;
|
||||
count -= 4 + 1 + len;
|
||||
}
|
||||
|
||||
return (count == 0);
|
||||
}
|
||||
|
||||
static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) {
|
||||
memfseek(f, 0, MSEEK_END);
|
||||
int count = memftell(f);
|
||||
if (count < 56 + 4 + 1024)
|
||||
return false;
|
||||
count -= 56 + 4 + 1024;
|
||||
|
||||
memfseek(f, 56, MSEEK_SET);
|
||||
|
||||
int datalen = readInt4(f);
|
||||
if (datalen != *size)
|
||||
return false;
|
||||
|
||||
u8 *mem = *rom;
|
||||
|
||||
u8 block[1024];
|
||||
memfread(&block, 1, 1024, f);
|
||||
if (memcmp(&mem[0x9320], &block, 1024) != 0)
|
||||
return false;
|
||||
|
||||
int idlen = ppfFileIdLen(f, 2);
|
||||
if (idlen > 0)
|
||||
count -= 16 + 16 + idlen;
|
||||
|
||||
memfseek(f, 56 + 4 + 1024, MSEEK_SET);
|
||||
|
||||
while (count > 0) {
|
||||
int offset = readInt4(f);
|
||||
if (offset == -1)
|
||||
break;
|
||||
int len = memfgetc(f);
|
||||
if (len == MEOF)
|
||||
break;
|
||||
if (offset + len > *size)
|
||||
break;
|
||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
||||
break;
|
||||
count -= 4 + 1 + len;
|
||||
}
|
||||
|
||||
return (count == 0);
|
||||
}
|
||||
|
||||
static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) {
|
||||
memfseek(f, 0, MSEEK_END);
|
||||
int count = memftell(f);
|
||||
if (count < 56 + 4 + 1024)
|
||||
return false;
|
||||
count -= 56 + 4;
|
||||
|
||||
memfseek(f, 56, MSEEK_SET);
|
||||
|
||||
int imagetype = memfgetc(f);
|
||||
int blockcheck = memfgetc(f);
|
||||
int undo = memfgetc(f);
|
||||
memfgetc(f);
|
||||
|
||||
u8 *mem = *rom;
|
||||
|
||||
if (blockcheck) {
|
||||
u8 block[1024];
|
||||
memfread(&block, 1, 1024, f);
|
||||
if (memcmp(&mem[(imagetype == 0) ? 0x9320 : 0x80A0], &block, 1024) != 0)
|
||||
return false;
|
||||
count -= 1024;
|
||||
}
|
||||
|
||||
int idlen = ppfFileIdLen(f, 2);
|
||||
if (idlen > 0)
|
||||
count -= 16 + 16 + idlen;
|
||||
|
||||
memfseek(f, 56 + 4 + (blockcheck ? 1024 : 0), MSEEK_SET);
|
||||
|
||||
while (count > 0) {
|
||||
s64 offset = readInt8(f);
|
||||
if (offset == -1)
|
||||
break;
|
||||
int len = memfgetc(f);
|
||||
if (len == MEOF)
|
||||
break;
|
||||
if (offset + len > *size)
|
||||
break;
|
||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
||||
break;
|
||||
if (undo)
|
||||
memfseek(f, len, MSEEK_CUR);
|
||||
count -= 8 + 1 + len;
|
||||
if (undo)
|
||||
count -= len;
|
||||
}
|
||||
|
||||
return (count == 0);
|
||||
}
|
||||
|
||||
bool patchApplyPPF(MFILE *f, u8 **rom, int *size)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
int version = ppfVersion(f);
|
||||
switch (version)
|
||||
{
|
||||
case 1: res = patchApplyPPF1(f, rom, size); break;
|
||||
case 2: res = patchApplyPPF2(f, rom, size); break;
|
||||
case 3: res = patchApplyPPF3(f, rom, size); break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void LoadPatch(int method)
|
||||
{
|
||||
int patchsize = 0;
|
||||
int patchtype = -1;
|
||||
|
||||
AllocSaveBuffer ();
|
||||
|
||||
char patchpath[3][512];
|
||||
memset(patchpath, 0, sizeof(patchpath));
|
||||
sprintf(patchpath[0], "%s/%s.ips", currentdir, Memory.ROMFilename);
|
||||
sprintf(patchpath[1], "%s/%s.ups", currentdir, Memory.ROMFilename);
|
||||
sprintf(patchpath[2], "%s/%s.ppf", currentdir, Memory.ROMFilename);
|
||||
|
||||
ShowAction((char *)"Loading patch...");
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case METHOD_SD:
|
||||
case METHOD_USB:
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
patchsize = LoadBufferFromFAT (patchpath[i], SILENT);
|
||||
|
||||
if(patchsize)
|
||||
{
|
||||
patchtype = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case METHOD_SMB:
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
patchsize = LoadBufferFromSMB (patchpath[i], SILENT);
|
||||
|
||||
if(patchsize)
|
||||
{
|
||||
patchtype = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(patchsize > 0)
|
||||
{
|
||||
// create memory file
|
||||
MFILE * mf = memfopen((char *)savebuffer, patchsize);
|
||||
|
||||
int tmpSize = SNESROMSize;
|
||||
|
||||
if(patchtype == 0)
|
||||
patchApplyIPS(mf, &Memory.ROM, &tmpSize);
|
||||
else if(patchtype == 1)
|
||||
patchApplyUPS(mf, &Memory.ROM, &tmpSize);
|
||||
else
|
||||
patchApplyPPF(mf, &Memory.ROM, &tmpSize);
|
||||
|
||||
SNESROMSize = tmpSize;
|
||||
|
||||
memfclose(mf); // close memory file
|
||||
}
|
||||
|
||||
FreeSaveBuffer ();
|
||||
}
|
18
source/ngc/patch.h
Normal file
18
source/ngc/patch.h
Normal file
@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||
*
|
||||
* Tantric October 2008
|
||||
*
|
||||
* patch.h
|
||||
*
|
||||
* IPS/UPS/PPF patch support
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PATCH_H
|
||||
#define PATCH_H
|
||||
|
||||
#include "memfile.h"
|
||||
|
||||
void LoadPatch(int method);
|
||||
|
||||
#endif
|
@ -180,6 +180,9 @@ emulate ()
|
||||
|
||||
MainMenu (2); // go to game menu
|
||||
|
||||
// save zoom level
|
||||
SavePrefs(GCSettings.SaveMethod, SILENT);
|
||||
|
||||
FrameTimer = 0;
|
||||
setFrameTimerMethod (); // set frametimer method every time a ROM is loaded
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user