Patches by chrono:
[CORE] Add UPS/PPF patch support [SDL] Add UPS/PPF patch support [SDL] Fix memory leak
This commit is contained in:
parent
dcc2f30119
commit
89c0a7b049
|
@ -134,6 +134,7 @@ SET(SRC_MAIN
|
||||||
src/Mode3.cpp
|
src/Mode3.cpp
|
||||||
src/Mode4.cpp
|
src/Mode4.cpp
|
||||||
src/Mode5.cpp
|
src/Mode5.cpp
|
||||||
|
src/Patch.cpp
|
||||||
src/pixel.cpp
|
src/pixel.cpp
|
||||||
src/RTC.cpp
|
src/RTC.cpp
|
||||||
src/scanline.cpp
|
src/scanline.cpp
|
||||||
|
|
|
@ -0,0 +1,464 @@
|
||||||
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
||||||
|
// Copyright (C) 1999-2003 Forgotten
|
||||||
|
// Copyright (C) 2004-2006 Forgotten and the VBA development team
|
||||||
|
// Copyright (C) 2007-2008 VBA-M development team and Shay Green
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2, or(at your option)
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
|
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "System.h"
|
||||||
|
// #include "NLS.h"
|
||||||
|
// #include "Util.h"
|
||||||
|
// #include "Flash.h"
|
||||||
|
// #include "agb/GBA.h"
|
||||||
|
// #include "Globals.h"
|
||||||
|
// #include "RTC.h"
|
||||||
|
// #include "Port.h"
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#define _stricmp strcasecmp
|
||||||
|
#endif // ! _MSC_VER
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined (MACOSX)
|
||||||
|
#define fseeko64 fseeko
|
||||||
|
#define ftello64 ftello
|
||||||
|
typedef off_t __off64_t;
|
||||||
|
#endif /* __APPLE__ || MACOSX */
|
||||||
|
|
||||||
|
static int readInt2(FILE *f)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
int c = fgetc(f);
|
||||||
|
if(c == EOF)
|
||||||
|
return -1;
|
||||||
|
res = c;
|
||||||
|
c = fgetc(f);
|
||||||
|
if(c == EOF)
|
||||||
|
return -1;
|
||||||
|
return c + (res<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readInt3(FILE *f)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
int c = fgetc(f);
|
||||||
|
if(c == EOF)
|
||||||
|
return -1;
|
||||||
|
res = c;
|
||||||
|
c = fgetc(f);
|
||||||
|
if(c == EOF)
|
||||||
|
return -1;
|
||||||
|
res = c + (res<<8);
|
||||||
|
c = fgetc(f);
|
||||||
|
if(c == EOF)
|
||||||
|
return -1;
|
||||||
|
return c + (res<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s64 readInt4(FILE *f)
|
||||||
|
{
|
||||||
|
s64 tmp, res = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
return -1;
|
||||||
|
tmp = c;
|
||||||
|
res = res + (tmp << (i*8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s64 readInt8(FILE *f)
|
||||||
|
{
|
||||||
|
s64 tmp, res = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
return -1;
|
||||||
|
tmp = c;
|
||||||
|
res = res + (tmp << (i*8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s64 readVarPtr(FILE *f)
|
||||||
|
{
|
||||||
|
s64 offset = 0, shift = 1;
|
||||||
|
for (;;) {
|
||||||
|
int c = fgetc(f);
|
||||||
|
if (c == EOF) 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(FILE *f, unsigned int size)
|
||||||
|
{
|
||||||
|
Bytef buf[4096];
|
||||||
|
long readed;
|
||||||
|
|
||||||
|
uLong crc = crc32(0L, Z_NULL, 0);
|
||||||
|
do {
|
||||||
|
readed = fread(buf, 1, MIN(size, sizeof(buf)), f);
|
||||||
|
crc = crc32(crc, buf, readed);
|
||||||
|
size -= readed;
|
||||||
|
} while (readed > 0);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyIPS(const char *patchname, u8 **r, int *s)
|
||||||
|
{
|
||||||
|
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
||||||
|
FILE *f = fopen(patchname, "rb");
|
||||||
|
if(!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
u8 *rom = *r;
|
||||||
|
int size = *s;
|
||||||
|
if(fgetc(f) == 'P' &&
|
||||||
|
fgetc(f) == 'A' &&
|
||||||
|
fgetc(f) == 'T' &&
|
||||||
|
fgetc(f) == 'C' &&
|
||||||
|
fgetc(f) == 'H') {
|
||||||
|
int b;
|
||||||
|
int offset;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
// read offset
|
||||||
|
offset = readInt3(f);
|
||||||
|
// if offset == EOF, 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 = fgetc(f);
|
||||||
|
if(c == -1)
|
||||||
|
break;
|
||||||
|
b = (u8)c;
|
||||||
|
} else
|
||||||
|
b= -1;
|
||||||
|
// check if we need to reallocate our ROM
|
||||||
|
if((offset + len) >= size) {
|
||||||
|
size *= 2;
|
||||||
|
rom = (u8 *)realloc(rom, size);
|
||||||
|
*r = rom;
|
||||||
|
*s = size;
|
||||||
|
}
|
||||||
|
if(b == -1) {
|
||||||
|
// normal block, just read the data
|
||||||
|
if(fread(&rom[offset], 1, len, f) != (size_t)len)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// fill the region with the given byte
|
||||||
|
while(len--) {
|
||||||
|
rom[offset++] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// close the file
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyUPS(const char *patchname, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
s64 srcCRC, dstCRC, patchCRC;
|
||||||
|
|
||||||
|
FILE *f = fopen(patchname, "rb");
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fseeko64(f, 0, SEEK_END);
|
||||||
|
__off64_t patchSize = ftello64(f);
|
||||||
|
if (patchSize < 20) {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseeko64(f, 0, SEEK_SET);
|
||||||
|
if(fgetc(f) != 'U' || fgetc(f) != 'P' || fgetc(f) != 'S' || fgetc(f) != '1') {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseeko64(f, -12, SEEK_END);
|
||||||
|
srcCRC = readInt4(f);
|
||||||
|
dstCRC = readInt4(f);
|
||||||
|
patchCRC = readInt4(f);
|
||||||
|
if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseeko64(f, 0, SEEK_SET);
|
||||||
|
u32 crc = computePatchCRC(f, patchSize-4);
|
||||||
|
|
||||||
|
if (crc != patchCRC) {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = crc32(0L, Z_NULL, 0);
|
||||||
|
crc = crc32(crc, *rom, *size);
|
||||||
|
|
||||||
|
fseeko64(f, 4, SEEK_SET);
|
||||||
|
s64 dataSize;
|
||||||
|
s64 srcSize = readVarPtr(f);
|
||||||
|
s64 dstSize = readVarPtr(f);
|
||||||
|
|
||||||
|
if (crc == srcCRC) {
|
||||||
|
dataSize = srcSize;
|
||||||
|
} else if (crc == dstCRC) {
|
||||||
|
dataSize = dstSize;
|
||||||
|
} else {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dataSize != *size) {
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 relative = 0;
|
||||||
|
u8 *mem;
|
||||||
|
while(ftello64(f) < patchSize - 12) {
|
||||||
|
relative += readVarPtr(f);
|
||||||
|
if (relative > dataSize) continue;
|
||||||
|
mem = *rom + relative;
|
||||||
|
for(s64 i = relative; i < dataSize; i++) {
|
||||||
|
int x = fgetc(f);
|
||||||
|
relative++;
|
||||||
|
if (!x) break;
|
||||||
|
if (i < dataSize) {
|
||||||
|
*mem++ ^= x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ppfVersion(FILE *f)
|
||||||
|
{
|
||||||
|
fseeko64(f, 0, SEEK_SET);
|
||||||
|
if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F')
|
||||||
|
return 0;
|
||||||
|
switch(fgetc(f)){
|
||||||
|
case '1': return 1;
|
||||||
|
case '2': return 2;
|
||||||
|
case '3': return 3;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppfFileIdLen(FILE *f, int version)
|
||||||
|
{
|
||||||
|
if (version == 2) {
|
||||||
|
fseeko64(f, -8, SEEK_END);
|
||||||
|
} else {
|
||||||
|
fseeko64(f, -6, SEEK_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fgetc(f) != '.' || fgetc(f) != 'D' || fgetc(f) != 'I' || fgetc(f) != 'Z')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (version == 2) ? readInt4(f) : readInt2(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyPPF1(FILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
int count = ftell(f);
|
||||||
|
if (count < 56)
|
||||||
|
return false;
|
||||||
|
count -= 56;
|
||||||
|
|
||||||
|
fseek(f, 56, SEEK_SET);
|
||||||
|
|
||||||
|
u8 *mem = *rom;
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
int offset = readInt4(f);
|
||||||
|
if (offset == -1)
|
||||||
|
break;
|
||||||
|
int len = fgetc(f);
|
||||||
|
if (len == EOF)
|
||||||
|
break;
|
||||||
|
if (offset+len > *size)
|
||||||
|
break;
|
||||||
|
if (fread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
|
break;
|
||||||
|
count -= 4 + 1 + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyPPF2(FILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
int count = ftell(f);
|
||||||
|
if (count < 56+4+1024)
|
||||||
|
return false;
|
||||||
|
count -= 56+4+1024;
|
||||||
|
|
||||||
|
fseek(f, 56, SEEK_SET);
|
||||||
|
|
||||||
|
int datalen = readInt4(f);
|
||||||
|
if (datalen != *size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u8 *mem = *rom;
|
||||||
|
|
||||||
|
u8 block[1024];
|
||||||
|
fread(&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;
|
||||||
|
|
||||||
|
fseek(f, 56+4+1024, SEEK_SET);
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
int offset = readInt4(f);
|
||||||
|
if (offset == -1)
|
||||||
|
break;
|
||||||
|
int len = fgetc(f);
|
||||||
|
if (len == EOF)
|
||||||
|
break;
|
||||||
|
if (offset+len > *size)
|
||||||
|
break;
|
||||||
|
if (fread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
|
break;
|
||||||
|
count -= 4 + 1 + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyPPF3(FILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
int count = ftell(f);
|
||||||
|
if (count < 56+4+1024)
|
||||||
|
return false;
|
||||||
|
count -= 56+4;
|
||||||
|
|
||||||
|
fseek(f, 56, SEEK_SET);
|
||||||
|
|
||||||
|
int imagetype = fgetc(f);
|
||||||
|
int blockcheck = fgetc(f);
|
||||||
|
int undo = fgetc(f);
|
||||||
|
fgetc(f);
|
||||||
|
|
||||||
|
u8 *mem = *rom;
|
||||||
|
|
||||||
|
if (blockcheck) {
|
||||||
|
u8 block[1024];
|
||||||
|
fread(&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;
|
||||||
|
|
||||||
|
fseek(f, 56+4+(blockcheck ? 1024 : 0), SEEK_SET);
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
__off64_t offset = readInt8(f);
|
||||||
|
if (offset == -1)
|
||||||
|
break;
|
||||||
|
int len = fgetc(f);
|
||||||
|
if (len == EOF)
|
||||||
|
break;
|
||||||
|
if (offset+len > *size)
|
||||||
|
break;
|
||||||
|
if (fread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
|
break;
|
||||||
|
if (undo) fseeko64(f, len, SEEK_CUR);
|
||||||
|
count -= 8 + 1 + len;
|
||||||
|
if (undo) count -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patchApplyPPF(const char *patchname, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(patchname, "rb");
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool applyPatch(const char *patchname, u8 **rom, int *size)
|
||||||
|
{
|
||||||
|
if (strlen(patchname) < 5)
|
||||||
|
return false;
|
||||||
|
const char * p = strrchr(patchname, '.');
|
||||||
|
if (p == NULL)
|
||||||
|
return false;
|
||||||
|
if (_stricmp(p, ".ips") == 0)
|
||||||
|
return patchApplyIPS(patchname, rom, size);
|
||||||
|
if (_stricmp(p, ".ups") == 0)
|
||||||
|
return patchApplyUPS(patchname, rom, size);
|
||||||
|
if (_stricmp(p, ".ppf") == 0)
|
||||||
|
return patchApplyPPF(patchname, rom, size);
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
||||||
|
// Copyright (C) 1999-2003 Forgotten
|
||||||
|
// Copyright (C) 2004 Forgotten and the VBA development team
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2, or(at your option)
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
|
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef VBA_PATCH_H
|
||||||
|
#define VBA_PATCH_H
|
||||||
|
|
||||||
|
#include "System.h"
|
||||||
|
|
||||||
|
bool applyPatch(const char *patchname, u8 **rom, int *size);
|
||||||
|
|
||||||
|
#endif
|
92
src/Util.cpp
92
src/Util.cpp
|
@ -34,6 +34,7 @@ extern "C" {
|
||||||
#include "agb/GBA.h"
|
#include "agb/GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
#include "Patch.h"
|
||||||
#include "Port.h"
|
#include "Port.h"
|
||||||
|
|
||||||
#include "fex.h"
|
#include "fex.h"
|
||||||
|
@ -330,96 +331,9 @@ bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int utilReadInt2(FILE *f)
|
void utilApplyIPS(const char *ips, u8 **rom, int *size)
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
int c = fgetc(f);
|
|
||||||
if(c == EOF)
|
|
||||||
return -1;
|
|
||||||
res = c;
|
|
||||||
c = fgetc(f);
|
|
||||||
if(c == EOF)
|
|
||||||
return -1;
|
|
||||||
return c + (res<<8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int utilReadInt3(FILE *f)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
int c = fgetc(f);
|
|
||||||
if(c == EOF)
|
|
||||||
return -1;
|
|
||||||
res = c;
|
|
||||||
c = fgetc(f);
|
|
||||||
if(c == EOF)
|
|
||||||
return -1;
|
|
||||||
res = c + (res<<8);
|
|
||||||
c = fgetc(f);
|
|
||||||
if(c == EOF)
|
|
||||||
return -1;
|
|
||||||
return c + (res<<8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void utilApplyIPS(const char *ips, u8 **r, int *s)
|
|
||||||
{
|
|
||||||
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
|
||||||
FILE *f = fopen(ips, "rb");
|
|
||||||
if(!f)
|
|
||||||
return;
|
|
||||||
u8 *rom = *r;
|
|
||||||
int size = *s;
|
|
||||||
if(fgetc(f) == 'P' &&
|
|
||||||
fgetc(f) == 'A' &&
|
|
||||||
fgetc(f) == 'T' &&
|
|
||||||
fgetc(f) == 'C' &&
|
|
||||||
fgetc(f) == 'H') {
|
|
||||||
int b;
|
|
||||||
int offset;
|
|
||||||
int len;
|
|
||||||
for(;;) {
|
|
||||||
// read offset
|
|
||||||
offset = utilReadInt3(f);
|
|
||||||
// if offset == EOF, end of patch
|
|
||||||
if(offset == 0x454f46)
|
|
||||||
break;
|
|
||||||
// read length
|
|
||||||
len = utilReadInt2(f);
|
|
||||||
if(!len) {
|
|
||||||
// len == 0, RLE block
|
|
||||||
len = utilReadInt2(f);
|
|
||||||
// byte to fill
|
|
||||||
int c = fgetc(f);
|
|
||||||
if(c == -1)
|
|
||||||
break;
|
|
||||||
b = (u8)c;
|
|
||||||
} else
|
|
||||||
b= -1;
|
|
||||||
// check if we need to reallocate our ROM
|
|
||||||
if((offset + len) >= size) {
|
|
||||||
size *= 2;
|
|
||||||
rom = (u8 *)realloc(rom, size);
|
|
||||||
*r = rom;
|
|
||||||
*s = size;
|
|
||||||
}
|
|
||||||
if(b == -1) {
|
|
||||||
// normal block, just read the data
|
|
||||||
if(fread(&rom[offset], 1, len, f) != (size_t)len)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// fill the region with the given byte
|
|
||||||
while(len--) {
|
|
||||||
rom[offset++] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close the file
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Modify ZSNES code for this
|
|
||||||
void utilApplyUPS(const char *ips, u8 **r, int *s)
|
|
||||||
{
|
{
|
||||||
|
applyPatch(ips, rom, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool cpuIsMultiBoot;
|
extern bool cpuIsMultiBoot;
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "../agb/GBA.h"
|
#include "../agb/GBA.h"
|
||||||
#include "../agb/agbprint.h"
|
#include "../agb/agbprint.h"
|
||||||
#include "../Flash.h"
|
#include "../Flash.h"
|
||||||
|
#include "../Patch.h"
|
||||||
#include "../RTC.h"
|
#include "../RTC.h"
|
||||||
#include "../Sound.h"
|
#include "../Sound.h"
|
||||||
#include "../Util.h"
|
#include "../Util.h"
|
||||||
|
@ -150,7 +151,6 @@ FilterFunc filterFunction = 0;
|
||||||
IFBFilterFunc ifbFunction = 0;
|
IFBFilterFunc ifbFunction = 0;
|
||||||
IFBFilter ifbType = kIFBNone;
|
IFBFilter ifbType = kIFBNone;
|
||||||
char filename[2048];
|
char filename[2048];
|
||||||
char ipsname[2048];
|
|
||||||
char biosFileName[2048];
|
char biosFileName[2048];
|
||||||
char gbBiosFileName[2048];
|
char gbBiosFileName[2048];
|
||||||
char captureDir[2048];
|
char captureDir[2048];
|
||||||
|
@ -185,10 +185,10 @@ static int saveSlotPosition = 0; // default is the slot from normal F1
|
||||||
static int sdlOpenglScale = 1;
|
static int sdlOpenglScale = 1;
|
||||||
// will scale window on init by this much
|
// will scale window on init by this much
|
||||||
static int sdlSoundToggledOff = 0;
|
static int sdlSoundToggledOff = 0;
|
||||||
// allow up to 100 IPS patches given on commandline
|
// allow up to 100 IPS/UPS/PPF patches given on commandline
|
||||||
#define IPS_MAX_NUM 100
|
#define PATCH_MAX_NUM 100
|
||||||
int sdl_ips_num = 0;
|
int sdl_patch_num = 0;
|
||||||
char * (sdl_ips_names[IPS_MAX_NUM]) = { NULL }; // and so on
|
char * (sdl_patch_names[PATCH_MAX_NUM]) = { NULL }; // and so on
|
||||||
|
|
||||||
#define REWIND_NUM 8
|
#define REWIND_NUM 8
|
||||||
#define REWIND_SIZE 400000
|
#define REWIND_SIZE 400000
|
||||||
|
@ -214,7 +214,7 @@ bool debugger = false;
|
||||||
bool debuggerStub = false;
|
bool debuggerStub = false;
|
||||||
int fullscreen = 0;
|
int fullscreen = 0;
|
||||||
int sdlFlashSize = 0;
|
int sdlFlashSize = 0;
|
||||||
int sdlAutoIPS = 1;
|
int sdlAutoPatch = 1;
|
||||||
int sdlRtcEnable = 0;
|
int sdlRtcEnable = 0;
|
||||||
int sdlAgbPrint = 0;
|
int sdlAgbPrint = 0;
|
||||||
int sdlMirroringEnable = 0;
|
int sdlMirroringEnable = 0;
|
||||||
|
@ -259,11 +259,11 @@ struct option sdlOptions[] = {
|
||||||
{ "fullscreen", no_argument, &fullscreen, 1 },
|
{ "fullscreen", no_argument, &fullscreen, 1 },
|
||||||
{ "gdb", required_argument, 0, 'G' },
|
{ "gdb", required_argument, 0, 'G' },
|
||||||
{ "help", no_argument, &sdlPrintUsage, 1 },
|
{ "help", no_argument, &sdlPrintUsage, 1 },
|
||||||
{ "ips", required_argument, 0, 'i' },
|
{ "patch", required_argument, 0, 'i' },
|
||||||
{ "no-agb-print", no_argument, &sdlAgbPrint, 0 },
|
{ "no-agb-print", no_argument, &sdlAgbPrint, 0 },
|
||||||
{ "no-auto-frameskip", no_argument, &autoFrameSkip, 0 },
|
{ "no-auto-frameskip", no_argument, &autoFrameSkip, 0 },
|
||||||
{ "no-debug", no_argument, 0, 'N' },
|
{ "no-debug", no_argument, 0, 'N' },
|
||||||
{ "no-ips", no_argument, &sdlAutoIPS, 0 },
|
{ "no-patch", no_argument, &sdlAutoPatch, 0 },
|
||||||
{ "no-opengl", no_argument, &openGL, 0 },
|
{ "no-opengl", no_argument, &openGL, 0 },
|
||||||
{ "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 },
|
{ "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 },
|
||||||
{ "no-rtc", no_argument, &sdlRtcEnable, 0 },
|
{ "no-rtc", no_argument, &sdlRtcEnable, 0 },
|
||||||
|
@ -1760,7 +1760,7 @@ Options:\n\
|
||||||
printf(" %d - %s\n", i, getFilterName((Filter)i));
|
printf(" %d - %s\n", i, getFilterName((Filter)i));
|
||||||
printf("\
|
printf("\
|
||||||
-h, --help Print this help\n\
|
-h, --help Print this help\n\
|
||||||
-i, --ips=PATCH Apply given IPS patch\n\
|
-i, --patch=PATCH Apply given patch\n\
|
||||||
-p, --profile=[HERTZ] Enable profiling\n\
|
-p, --profile=[HERTZ] Enable profiling\n\
|
||||||
-s, --frameskip=FRAMESKIP Set frame skip (0...9)\n\
|
-s, --frameskip=FRAMESKIP Set frame skip (0...9)\n\
|
||||||
-t, --save-type=TYPE Set the available save type\n\
|
-t, --save-type=TYPE Set the available save type\n\
|
||||||
|
@ -1787,7 +1787,7 @@ Long options only:\n\
|
||||||
--auto-frameskip Enable auto frameskipping\n\
|
--auto-frameskip Enable auto frameskipping\n\
|
||||||
--no-agb-print Disable AGBPrint support\n\
|
--no-agb-print Disable AGBPrint support\n\
|
||||||
--no-auto-frameskip Disable auto frameskipping\n\
|
--no-auto-frameskip Disable auto frameskipping\n\
|
||||||
--no-ips Do not apply IPS patch\n\
|
--no-patch Do not automatically apply patch\n\
|
||||||
--no-pause-when-inactive Don't pause when inactive\n\
|
--no-pause-when-inactive Don't pause when inactive\n\
|
||||||
--no-rtc Disable RTC support\n\
|
--no-rtc Disable RTC support\n\
|
||||||
--no-show-speed Don't show emulation speed\n\
|
--no-show-speed Don't show emulation speed\n\
|
||||||
|
@ -1796,7 +1796,7 @@ Long options only:\n\
|
||||||
--rtc Enable RTC support\n\
|
--rtc Enable RTC support\n\
|
||||||
--show-speed-normal Show emulation speed\n\
|
--show-speed-normal Show emulation speed\n\
|
||||||
--show-speed-detailed Show detailed speed data\n\
|
--show-speed-detailed Show detailed speed data\n\
|
||||||
--cheat 'CHEAT' add a cheat\n\
|
--cheat 'CHEAT' Add a cheat\n\
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1848,7 +1848,6 @@ int main(int argc, char **argv)
|
||||||
captureDir[0] = 0;
|
captureDir[0] = 0;
|
||||||
saveDir[0] = 0;
|
saveDir[0] = 0;
|
||||||
batteryDir[0] = 0;
|
batteryDir[0] = 0;
|
||||||
ipsname[0] = 0;
|
|
||||||
|
|
||||||
int op = -1;
|
int op = -1;
|
||||||
|
|
||||||
|
@ -1933,16 +1932,15 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if(optarg == NULL) {
|
if(optarg == NULL) {
|
||||||
fprintf(stderr, "Missing IPS name\n");
|
fprintf(stderr, "Missing patch name\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
// strcpy(ipsname, optarg);
|
if (sdl_patch_num >= PATCH_MAX_NUM) {
|
||||||
if (sdl_ips_num >= IPS_MAX_NUM) {
|
fprintf(stderr, "Too many patches given at %s (max is %d). Ignoring.\n", optarg, PATCH_MAX_NUM);
|
||||||
fprintf(stderr, "Too many IPS patches given at %s (max is %d). Ignoring.\n", optarg, IPS_MAX_NUM);
|
|
||||||
} else {
|
} else {
|
||||||
sdl_ips_names[sdl_ips_num] = (char *)malloc(1 + strlen(optarg));
|
sdl_patch_names[sdl_patch_num] = (char *)malloc(1 + strlen(optarg));
|
||||||
strcpy(sdl_ips_names[sdl_ips_num], optarg);
|
strcpy(sdl_patch_names[sdl_patch_num], optarg);
|
||||||
sdl_ips_num++;
|
sdl_patch_num++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
|
@ -2110,14 +2108,26 @@ int main(int argc, char **argv)
|
||||||
if(p)
|
if(p)
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
// if(ipsname[0] == 0)
|
if (sdlAutoPatch && sdl_patch_num == 0)
|
||||||
// sprintf(ipsname, "%s.ips", filename);
|
|
||||||
if (sdl_ips_num == 0)
|
|
||||||
{
|
{
|
||||||
|
char * tmp;
|
||||||
// no patch given yet - look for ROMBASENAME.ips
|
// no patch given yet - look for ROMBASENAME.ips
|
||||||
sprintf(ipsname, "%s.ips", filename);
|
tmp = (char *)malloc(strlen(filename) + 4 + 1);
|
||||||
sdl_ips_names[0] = ipsname;
|
sprintf(tmp, "%s.ips", filename);
|
||||||
sdl_ips_num++;
|
sdl_patch_names[sdl_patch_num] = tmp;
|
||||||
|
sdl_patch_num++;
|
||||||
|
|
||||||
|
// no patch given yet - look for ROMBASENAME.ups
|
||||||
|
tmp = (char *)malloc(strlen(filename) + 4 + 1);
|
||||||
|
sprintf(tmp, "%s.ups", filename);
|
||||||
|
sdl_patch_names[sdl_patch_num] = tmp;
|
||||||
|
sdl_patch_num++;
|
||||||
|
|
||||||
|
// no patch given yet - look for ROMBASENAME.ppf
|
||||||
|
tmp = (char *)malloc(strlen(filename) + 4 + 1);
|
||||||
|
sprintf(tmp, "%s.ppf", filename);
|
||||||
|
sdl_patch_names[sdl_patch_num] = tmp;
|
||||||
|
sdl_patch_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
@ -2139,22 +2149,19 @@ int main(int argc, char **argv)
|
||||||
if (gbHardware & 5)
|
if (gbHardware & 5)
|
||||||
gbCPUInit(gbBiosFileName, useBios);
|
gbCPUInit(gbBiosFileName, useBios);
|
||||||
|
|
||||||
gbReset();
|
|
||||||
cartridgeType = IMAGE_GB;
|
cartridgeType = IMAGE_GB;
|
||||||
emulator = GBSystem;
|
emulator = GBSystem;
|
||||||
if(sdlAutoIPS) {
|
|
||||||
int size = gbRomSize, patchnum;
|
int size = gbRomSize, patchnum;
|
||||||
// utilApplyIPS(ipsname, &gbRom, &size);
|
for (patchnum = 0; patchnum < sdl_patch_num; patchnum++) {
|
||||||
for (patchnum = 0; patchnum < sdl_ips_num; patchnum++) {
|
fprintf(stdout, "Trying patch %s%s\n", sdl_patch_names[patchnum],
|
||||||
fprintf(stdout, "Trying IPS patch %s.\n", sdl_ips_names[patchnum]);
|
applyPatch(sdl_patch_names[patchnum], &gbRom, &size) ? " [success]" : "");
|
||||||
utilApplyIPS(sdl_ips_names[patchnum], &gbRom, &size);
|
|
||||||
}
|
}
|
||||||
if(size != gbRomSize) {
|
if(size != gbRomSize) {
|
||||||
extern bool gbUpdateSizes();
|
extern bool gbUpdateSizes();
|
||||||
gbUpdateSizes();
|
gbUpdateSizes();
|
||||||
gbReset();
|
gbReset();
|
||||||
}
|
}
|
||||||
}
|
gbReset();
|
||||||
}
|
}
|
||||||
} else if(type == IMAGE_GBA) {
|
} else if(type == IMAGE_GBA) {
|
||||||
int size = CPULoadRom(szFile);
|
int size = CPULoadRom(szFile);
|
||||||
|
@ -2168,18 +2175,12 @@ int main(int argc, char **argv)
|
||||||
emulator = GBASystem;
|
emulator = GBASystem;
|
||||||
|
|
||||||
CPUInit(biosFileName, useBios);
|
CPUInit(biosFileName, useBios);
|
||||||
|
int patchnum;
|
||||||
|
for (patchnum = 0; patchnum < sdl_patch_num; patchnum++) {
|
||||||
|
fprintf(stdout, "Trying patch %s%s\n", sdl_patch_names[patchnum],
|
||||||
|
applyPatch(sdl_patch_names[patchnum], &rom, &size) ? " [success]" : "");
|
||||||
|
}
|
||||||
CPUReset();
|
CPUReset();
|
||||||
if(sdlAutoIPS) {
|
|
||||||
int size = 0x2000000, patchnum;
|
|
||||||
// utilApplyIPS(ipsname, &rom, &size);
|
|
||||||
for (patchnum = 0; patchnum < sdl_ips_num; patchnum++) {
|
|
||||||
fprintf(stdout, "Trying IPS patch %s.\n", sdl_ips_names[patchnum]);
|
|
||||||
utilApplyIPS(sdl_ips_names[patchnum], &rom, &size);
|
|
||||||
}
|
|
||||||
if(size != 0x2000000) {
|
|
||||||
CPUReset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2361,6 +2362,10 @@ int main(int argc, char **argv)
|
||||||
filterPix = NULL;
|
filterPix = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sdl_patch_num; i++) {
|
||||||
|
free(sdl_patch_names[i]);
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_LIRC
|
#if WITH_LIRC
|
||||||
StopLirc();
|
StopLirc();
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue