MCUME/MCUME_teensy41/teensysnes/memory.cpp

1062 wiersze
21 KiB
C++

/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include <Arduino.h>
#include "snes9x.h"
#include "memory.h"
#include "apu.h"
#include "controls.h"
#include "hacks.h"
CMemory Memory;
uint32 OpenBus = 0;
#define match_nn(str) (strncmp(Memory.ROMName, (str), strlen((str))) == 0)
static int First512BytesCountZeroes(void)
{
int zeroCount = 0;
for (int i = 0; i < 512; i++)
{
if (Memory.ROM[i] == 0)
zeroCount++;
}
return zeroCount;
}
static void sanitize(char *b, int size)
{
for (int pos = 0; pos < size; pos++)
{
if (b[pos] == 0)
continue;
if (b[pos] < 32 || b[pos] > 126)
b[pos] = '_';
}
b[size - 1] = 0;
}
static bool8 allASCII (uint8 *b, int size)
{
for (int i = 0; i < size; i++)
{
if (b[i] < 32 || b[i] > 126)
return (FALSE);
}
return (TRUE);
}
static void ShowInfoString (void)
{
const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" };
char contentstr[20], sizestr[20], sramstr[20];
bool8 isChecksumOK = (Memory.ROMChecksum + Memory.ROMComplementChecksum == 0xffff) &
(Memory.ROMChecksum == Memory.CalculatedChecksum);
if (!isChecksumOK || ((uint32) Memory.CalculatedSize > (uint32) (((1 << (Memory.ROMSize - 7)) * 128) * 1024)))
{
// Use yellow tint to indicate corrupted ROM.
Settings.DisplayColor = BUILD_PIXEL(31, 31, 0);
}
else if (Memory.ROMIsPatched)
{
// Use slight blue tint to indicate ROM was patched.
Settings.DisplayColor = BUILD_PIXEL(26, 26, 31);
}
else
{
Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
}
strcpy(contentstr, contents[(Memory.ROMType & 0xf) % 3]);
if (Settings.DSP == 1)
strcat(contentstr, "+DSP-1");
else if (Settings.DSP == 2)
strcat(contentstr, "+DSP-2");
if (Memory.ROMSize < 7 || Memory.ROMSize - 7 > 23)
strcpy(sizestr, "Corrupt");
else
sprintf(sizestr, "%dMbits", 1 << (Memory.ROMSize - 7));
if (Memory.SRAMSize > 16)
strcpy(sramstr, "Corrupt");
else
sprintf(sramstr, "%dKbits", 8 * (Memory.SRAMMask + 1) / 1024);
sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X",
Memory.ROMName,
isChecksumOK ? "checksum ok" : "bad checksum",
Memory.HiROM ? "HiROM" : "LoROM",
sizestr,
contentstr,
(Settings.Region == S9X_PAL) ? "PAL" : "NTSC",
sramstr,
Memory.ROMId,
Memory.ROMCRC32);
S9xMessage(S9X_INFO, S9X_ROM_INFO, String);
}
static uint32 map_mirror (uint32 size, uint32 pos)
{
// from bsnes
if (size == 0)
return (0);
if (pos < size)
return (pos);
uint32 mask = 1 << 31;
while (!(pos & mask))
mask >>= 1;
if (size <= (pos & mask))
return (map_mirror(size, pos - mask));
else
return (mask + map_mirror(size - mask, pos - mask));
}
static void map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size)
{
uint32 c, i, p, addr;
for (c = bank_s; c <= bank_e; c++)
{
for (i = addr_s; i <= addr_e; i += 0x1000)
{
p = (c << 4) | (i >> 12);
addr = (c & 0x7f) * 0x8000;
Memory.ReadMap[p] = Memory.ROM + map_mirror(size, addr) - (i & 0x8000);
}
}
}
static void map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size)
{
uint32 c, i, p, addr;
for (c = bank_s; c <= bank_e; c++)
{
for (i = addr_s; i <= addr_e; i += 0x1000)
{
p = (c << 4) | (i >> 12);
addr = c << 16;
Memory.ReadMap[p] = Memory.ROM + map_mirror(size, addr);
}
}
}
static void map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data)
{
uint32 c, i, p;
for (c = bank_s; c <= bank_e; c++)
{
for (i = addr_s; i <= addr_e; i += 0x1000)
{
p = (c << 4) | (i >> 12);
Memory.ReadMap[p] = data;
Memory.WriteMap[p] = data;
}
}
}
static void map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type)
{
uint32 c, i, p;
for (c = bank_s; c <= bank_e; c++)
{
for (i = addr_s; i <= addr_e; i += 0x1000)
{
p = (c << 4) | (i >> 12);
Memory.ReadMap[p] = (uint8 *) (pint) index;
Memory.WriteMap[p] = (uint8 *) (pint) index;
}
}
}
static void Map_Initialize (void)
{
for (int c = 0; c < MEMMAP_NUM_BLOCKS; c++)
{
Memory.ReadMap[c] = (uint8 *) MAP_NONE;
Memory.WriteMap[c] = (uint8 *) MAP_NONE;
}
// will be overwritten
map_space(0x00, 0x3f, 0x0000, 0x1fff, Memory.RAM);
map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
map_space(0x80, 0xbf, 0x0000, 0x1fff, Memory.RAM);
map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
}
static void Map_Finalize (void)
{
// Map Work RAM
map_space(0x7e, 0x7e, 0x0000, 0xffff, Memory.RAM);
map_space(0x7f, 0x7f, 0x0000, 0xffff, Memory.RAM + 0x10000);
}
static void Map_DSP (void)
{
switch (DSP0.maptype)
{
case M_DSP1_LOROM_S:
map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
break;
case M_DSP1_LOROM_L:
map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
break;
case M_DSP1_HIROM:
map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
break;
case M_DSP2_LOROM:
map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
break;
}
}
static void Map_LoROMMap (void)
{
Map_Initialize();
map_lorom(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize);
map_lorom(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize);
map_lorom(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize);
map_lorom(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize);
if (Settings.DSP)
Map_DSP();
if (Memory.SRAMSize > 0)
{
uint32 hi = (Memory.ROMSize > 11 || Memory.SRAMSize > 5) ? 0x7fff : 0xffff;
map_index(0x70, 0x7d, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0xf0, 0xff, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
}
Map_Finalize();
}
static void Map_HiROMMap (void)
{
Map_Initialize();
map_hirom(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize);
map_hirom(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize);
map_hirom(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize);
map_hirom(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize);
if (Settings.DSP)
Map_DSP();
map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
Map_Finalize();
}
static uint16 checksum_calc_sum (uint8 *data, uint32 length)
{
uint16 sum = 0;
for (size_t i = 0; i < length; i++)
sum += data[i];
return (sum);
}
static uint16 checksum_mirror_sum (uint8 *start, uint32 *length, uint32 mask)
{
// from NSRT
while (!(*length & mask) && mask)
mask >>= 1;
uint16 part1 = checksum_calc_sum(start, mask);
uint16 part2 = 0;
uint32 next_length = *length - mask;
if (next_length)
{
part2 = checksum_mirror_sum(start + mask, &next_length, mask >> 1);
while (next_length < mask)
{
next_length += next_length;
part2 += part2;
}
*length = mask + mask;
}
return (part1 + part2);
}
static uint16 CalcChecksum (uint8 *data, uint32 length)
{
if (length & 0x7fff)
return checksum_calc_sum(data, length);
else
return checksum_mirror_sum(data, &length, 0x800000);
}
static int ScoreHiROM (void)
{
uint8 *buf = Memory.ROM + 0xff00;
int score = 0;
if (buf[0xd5] & 0x1)
score += 2;
// Mode23 is SA-1
if (buf[0xd5] == 0x23)
score -= 2;
if (buf[0xd4] == 0x20)
score += 2;
if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
{
score += 2;
if (0 != (buf[0xde] + (buf[0xdf] << 8)))
score++;
}
if (buf[0xda] == 0x33)
score += 2;
if ((buf[0xd5] & 0xf) < 4)
score += 2;
if (!(buf[0xfd] & 0x80))
score -= 6;
if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
score -= 2; // reduced after looking at a scan by Cowering
if (Memory.CalculatedSize > 1024 * 1024 * 3)
score += 4;
if ((1 << (buf[0xd7] - 7)) > 48)
score -= 1;
if (!allASCII(&buf[0xb0], 6))
score -= 1;
if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
score -= 1;
return (score);
}
static int ScoreLoROM (void)
{
uint8 *buf = Memory.ROM + 0x7f00;
int score = 0;
if (!(buf[0xd5] & 0x1))
score += 3;
// Mode23 is SA-1
if (buf[0xd5] == 0x23)
score += 2;
if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
{
score += 2;
if (0 != (buf[0xde] + (buf[0xdf] << 8)))
score++;
}
if (buf[0xda] == 0x33)
score += 2;
if ((buf[0xd5] & 0xf) < 4)
score += 2;
if (!(buf[0xfd] & 0x80))
score -= 6;
if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
score -= 2; // reduced per Cowering suggestion
if (Memory.CalculatedSize <= 1024 * 1024 * 16)
score += 2;
if ((1 << (buf[0xd7] - 7)) > 48)
score -= 1;
if (!allASCII(&buf[0xb0], 6))
score -= 1;
if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
score -= 1;
return (score);
}
int ApplyGameSpecificHacks (void)
{
int applied = 0;
for (const s9x_hack_t *hack = &GameHacks[0]; hack->checksum; hack++)
{
if (hack->checksum == Memory.ROMCRC32)
{
printf("Applying patch %s: '%s'\n", hack->name, hack->patch);
char *ptr = (char*)hack->patch;
while (ptr && *ptr)
{
int offset = strtol(ptr, &ptr, 16);
int value = strtol(ptr + 1, &ptr, 16);
if ((ptr = strchr(ptr, ',')))
ptr++;
// We only care about opcode 0x42 for now
if ((value != 0x42) && ((value >> 8) != 0x42))
{
printf(" - Warning: Ignoring patch %X=%X...\n", offset, value);
}
else if (offset < 1 || offset >= Memory.CalculatedSize)
{
printf(" - Warning: Offset %d (%X) is out of range...\n", offset, offset);
}
else if (value & 0xFF00) // 16 bit replacement
{
printf(" - Applying 16bit patch %X=%X\n", offset, value);
// Memory.ROM[offset] = (value >> 8) & 0xFF;
// Memory.ROM[offset + 1] = value & 0xFF;
applied++;
}
else // 8 bit replacement
{
printf(" - Applying 8bit patch %X=%X\n", offset, value);
// Memory.ROM[offset] = value;
applied++;
}
}
}
}
return applied;
}
static bool8 InitROM ()
{
if (!Memory.ROM || Memory.ROM_SIZE < 0x200)
return (FALSE);
if ((Memory.ROM_SIZE & 0x7FF) == 512 || First512BytesCountZeroes() > 400)
{
emu_printf("Found ROM file header (and ignored it).\n");
memmove(Memory.ROM, Memory.ROM + 512, Memory.ROM_SIZE - 512);
Memory.ROM_SIZE -= 512;
}
Memory.CalculatedSize = ((Memory.ROM_SIZE + 0x1fff) / 0x2000) * 0x2000;
//// these two games fail to be detected
if (strncmp((char *) &Memory.ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
(strncmp((char *) &Memory.ROM[0xffc0], "BATMAN--REVENGE JOKER", 21) == 0))
{
Memory.LoROM = TRUE;
Memory.HiROM = FALSE;
}
else
{
Memory.LoROM = (ScoreLoROM() >= ScoreHiROM());
Memory.HiROM = !Memory.LoROM;
}
//// Parse ROM header and read ROM informatoin
uint8 *RomHeader = Memory.ROM + (Memory.HiROM ? 0xFFB0 : 0x7FB0);
strncpy(Memory.ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1);
sanitize(Memory.ROMName, ROM_NAME_LEN);
Memory.ROMName[ROM_NAME_LEN - 1] = 0;
if (strlen(Memory.ROMName))
{
char *p = Memory.ROMName + strlen(Memory.ROMName);
if (p > Memory.ROMName + 21 && Memory.ROMName[20] == ' ')
p = Memory.ROMName + 21;
while (p > Memory.ROMName && *(p - 1) == ' ')
p--;
*p = 0;
}
Memory.ROMSize = RomHeader[0x27];
Memory.SRAMSize = RomHeader[0x28];
Memory.ROMSpeed = RomHeader[0x25];
Memory.ROMType = RomHeader[0x26];
Memory.ROMRegion = RomHeader[0x29];
Memory.ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8);
Memory.ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8);
memmove(Memory.ROMId, &RomHeader[0x02], 4);
sanitize(Memory.ROMId, 4);
//// Detect DSP 1 & 2
if (Memory.ROMType == 0x03 || (Memory.ROMType == 0x05 && Memory.ROMSpeed != 0x20))
{
Settings.DSP = 1;
if (Memory.HiROM)
{
DSP0.boundary = 0x7000;
DSP0.maptype = M_DSP1_HIROM;
}
else
if (Memory.CalculatedSize > 0x100000)
{
DSP0.boundary = 0x4000;
DSP0.maptype = M_DSP1_LOROM_L;
}
else
{
DSP0.boundary = 0xc000;
DSP0.maptype = M_DSP1_LOROM_S;
}
SetDSP = &DSP1SetByte;
GetDSP = &DSP1GetByte;
}
else
if (Memory.ROMType == 0x05 && Memory.ROMSpeed == 0x20)
{
Settings.DSP = 2;
DSP0.boundary = 0x10000;
DSP0.maptype = M_DSP2_LOROM;
SetDSP = &DSP2SetByte;
GetDSP = &DSP2GetByte;
}
else
{
Settings.DSP = 0;
SetDSP = NULL;
GetDSP = NULL;
}
//// SRAM size
if (strncmp("HITOMI3 ", Memory.ROMName, 8) == 0)
{
Memory.SRAMSize = 1;
}
Memory.SRAMMask = Memory.SRAMSize ? ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
Memory.SRAMBytes = Memory.SRAMSize ? ((1 << (Memory.SRAMSize + 3)) * 128) : 0;
if (Memory.SRAMBytes > 0x8000)
{
emu_printf("\n\nWARNING: Default SRAM size too small!, need bytes");
emu_printi(Memory.SRAMBytes);
}
//// Map memory
if (Memory.HiROM)
{
Map_HiROMMap();
}
else
{
Map_LoROMMap();
}
//// Checksums
Memory.ROMCRC32 = crc32_le(0, Memory.ROM, Memory.CalculatedSize);
Memory.CalculatedChecksum = CalcChecksum(Memory.ROM, Memory.CalculatedSize);
//// ROM Region
if ((Memory.ROMRegion >= 2) && (Memory.ROMRegion <= 12))
{
Settings.Region = S9X_PAL;
Settings.FrameRate = 50;
}
else
{
Settings.Region = S9X_NTSC;
Settings.FrameRate = 60;
}
// Setup APU timings
S9xAPUTimingSetSpeedup(0);
//// Apply Game hacks
if (!Settings.DisableGameSpecificHacks)
{
ApplyGameSpecificHacks();
}
//// Show ROM information
ShowInfoString();
//// Reset system, then we're ready
S9xReset();
return (TRUE);
}
// Public functions
bool8 S9xMemoryInit (void)
{
memset(&Memory, 0, sizeof(Memory));
Memory.RAM = (uint8 *) emu_Malloc(0x20000); // calloc(1, 0x20000); // 128k
Memory.VRAM = (uint8 *) emu_Malloc(0x10000); //calloc(1, 0x10000); // 64k
Memory.SRAM = (uint8 *) emu_Malloc(0x8000); //calloc(1, 0x8000); // 32k
Memory.ROM_MAX_SIZE = 0x500000;
//Memory.ROM = (uint8 *) calloc(1, Memory.ROM_MAX_SIZE);
// Note: we don't care if ROM alloc fails. It's just to grab a large heap block
// before it gets fragmented. The actual useful alloc is done in S9xLoadROM()
if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM)
{
S9xMemoryDeinit();
return (FALSE);
}
return (TRUE);
}
void S9xMemoryDeinit (void)
{
emu_Free(Memory.RAM); //free(Memory.RAM);
emu_Free(Memory.SRAM); //free(Memory.SRAM);
emu_Free(Memory.VRAM); // free(Memory.VRAM);
emu_SFree(Memory.ROM); //free(Memory.ROM);
Memory.RAM = NULL;
Memory.SRAM = NULL;
Memory.VRAM = NULL;
Memory.ROM = NULL;
}
bool8 S9xLoadROM (const char *filename)
{
//FILE *stream = fopen(filename, "rb");
//if (!stream)
// return (FALSE);
//fseek(stream, 0, SEEK_END);
//Memory.ROM_SIZE = ftell(stream);
Memory.ROM_SIZE = emu_FileSize((char*)filename);
Memory.ROM = (uint8 *) emu_SMalloc(Memory.ROM_SIZE);
// We shrink if possible because we need all the memory we can get for savestates and buffers
//uint8 *temp = (uint8 *)realloc(Memory.ROM, Memory.ROM_SIZE);
//if (temp)
//{
// Memory.ROM_MAX_SIZE = Memory.ROM_SIZE;
// Memory.ROM = temp;
//}
if (!Memory.ROM || Memory.ROM_MAX_SIZE < Memory.ROM_SIZE)
{
//fclose(stream);
return (FALSE);
}
//fseek(stream, 0, SEEK_SET);
//fread(Memory.ROM, Memory.ROM_SIZE, 1, stream);
//fclose(stream);
emu_LoadFile((char*)filename, (char*)Memory.ROM, Memory.ROM_SIZE);
emu_printf("loaded");
return InitROM();
}
// BPS % UPS % IPS
#if 0
static long ReadInt (Stream *r, unsigned nbytes)
{
long v = 0;
while (nbytes--)
{
int c = r->get_char();
if (c == EOF)
return (-1);
v = (v << 8) | (c & 0xFF);
}
return (v);
}
static bool8 ReadIPSPatch (Stream *r, long offset, int32 &rom_size)
{
const int32 IPS_EOF = 0x00454F46l;
int32 ofs;
char fname[6];
fname[5] = 0;
for (int i = 0; i < 5; i++)
{
int c = r->get_char();
if (c == EOF)
return (0);
fname[i] = (char) c;
}
if (strncmp(fname, "PATCH", 5))
return (0);
for (;;)
{
long len, rlen;
int rchar;
ofs = ReadInt(r, 3);
if (ofs == -1)
return (0);
if (ofs == IPS_EOF)
break;
ofs -= offset;
len = ReadInt(r, 2);
if (len == -1)
return (0);
if (len)
{
if (ofs + len > Memory.ROM_SIZE)
return (0);
while (len--)
{
rchar = r->get_char();
if (rchar == EOF)
return (0);
Memory.ROM[ofs++] = (uint8) rchar;
}
if (ofs > rom_size)
rom_size = ofs;
}
else
{
rlen = ReadInt(r, 2);
if (rlen == -1)
return (0);
rchar = r->get_char();
if (rchar == EOF)
return (0);
if (ofs + rlen > Memory.ROM_SIZE)
return (0);
while (rlen--)
Memory.ROM[ofs++] = (uint8) rchar;
if (ofs > rom_size)
rom_size = ofs;
}
}
ofs = ReadInt(r, 3);
if (ofs != -1 && ofs - offset < rom_size)
rom_size = ofs - offset;
ROMIsPatched = 1;
return (1);
}
/*
void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &rom_size)
{
ROMIsPatched = false;
FSTREAM patch_file = NULL;
uint32 i;
long offset = header ? 512 : 0;
int ret;
bool flag;
char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1];
const char *n;
_splitpath(rom_filename, drive, dir, name, ext);
// IPS
_makepath(fname, drive, dir, name, "ips");
if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL)
{
printf("Using IPS patch %s", fname);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
return;
}
else
printf(" failed!\n");
}
if (_MAX_EXT > 6)
{
i = 0;
flag = false;
do
{
snprintf(ips, 8, "%03d.ips", i);
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i < 1000);
if (flag)
return;
}
if (_MAX_EXT > 3)
{
i = 0;
flag = false;
do
{
snprintf(ips, _MAX_EXT + 2, "ips%d", i);
if (strlen(ips) > _MAX_EXT)
break;
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i != 0);
if (flag)
return;
}
if (_MAX_EXT > 2)
{
i = 0;
flag = false;
do
{
snprintf(ips, 4, "ip%d", i);
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i < 10);
if (flag)
return;
}
n = S9xGetFilename(".ips", PATCH_DIR);
if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL)
{
printf("Using IPS patch %s", n);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
return;
}
else
printf(" failed!\n");
}
if (_MAX_EXT > 6)
{
i = 0;
flag = false;
do
{
snprintf(ips, 9, ".%03d.ips", i);
n = S9xGetFilename(ips, PATCH_DIR);
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i < 1000);
if (flag)
return;
}
if (_MAX_EXT > 3)
{
i = 0;
flag = false;
do
{
snprintf(ips, _MAX_EXT + 3, ".ips%d", i);
if (strlen(ips) > _MAX_EXT + 1)
break;
n = S9xGetFilename(ips, PATCH_DIR);
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i != 0);
if (flag)
return;
}
if (_MAX_EXT > 2)
{
i = 0;
flag = false;
do
{
snprintf(ips, 5, ".ip%d", i);
n = S9xGetFilename(ips, PATCH_DIR);
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
Stream *s = new fStream(patch_file);
ret = ReadIPSPatch(s, offset, rom_size);
s->closeStream();
if (ret)
{
printf("!\n");
flag = true;
}
else
{
printf(" failed!\n");
break;
}
} while (++i < 10);
if (flag)
return;
}
}
*/
#endif