Files
ZSNES/zsnes/src/initc.c
2004-07-15 21:48:30 +00:00

1381 lines
31 KiB
C
Executable File

/*
Copyright (C) 2003 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __LINUX__
#include "gblhdr.h"
#define DIR_SLASH "/"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#define DIR_SLASH "\\"
#endif
#include "zip/zunzip.h"
#ifndef __GNUC__
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
//C++ style code in C
#define bool unsigned char
#define true 1
#define false 0
#define Lo 0x7FC0
#define Hi 0xFFC0
#define EHi 0x40FFC0
#define MB_bytes 0x100000
#define Mbit_bytes 0x20000
void Debug_WriteString(char *str)
{
FILE *fp = 0;
fp = fopen("zsnes.dbg", "w");
if (!fp) { return; }
fputs(str, fp);
fclose(fp);
}
//I want to port over the more complicated
//functions from init.asm, or replace with
//better versions from NSRT. -Nach
//init.asm goodness
extern unsigned int NumofBanks;
extern unsigned int NumofBytes;
extern unsigned int *romdata;
extern unsigned char romtype;
extern unsigned char Interleaved;
unsigned int maxromspace;
unsigned int curromspace;
unsigned int infoloc;
bool SplittedROM;
unsigned int addOnStart;
unsigned int addOnSize;
//Deinterleave functions
bool validChecksum(unsigned char *ROM, int BankLoc)
{
if (ROM[BankLoc + 28] + (ROM[BankLoc + 29] << 8) +
ROM[BankLoc + 30] + (ROM[BankLoc + 31] << 8) == 0xFFFF)
{
return(true);
}
return(false);
}
bool EHiHeader(unsigned char *ROM, int BankLoc)
{
if (validChecksum(ROM, BankLoc) && ROM[BankLoc+21] == 53)
{
return(true);
}
return(false);
}
void swapBlocks(char *blocks)
{
unsigned int i,j,k;
for (i = 0; i < NumofBanks; i++)
{
for (j = 0; j < NumofBanks; j++)
{
if (blocks[j] == (char)i)
{
char b;
unsigned int temp,
*loc1 = romdata + blocks[i]*0x2000,
*loc2 = romdata + blocks[j]*0x2000;
for (k = 0; k < 0x2000; k++)
{
temp = loc1[k];
loc1[k] = loc2[k];
loc2[k] = temp;
}
b = blocks[j];
blocks[j] = blocks[i];
blocks[i] = b;
break;
}
}
}
}
void deintlv1()
{
char blocks[256];
int i, numblocks = NumofBanks/2;
for (i = 0; i < numblocks; i++)
{
blocks[i * 2] = i + numblocks;
blocks[i * 2 + 1] = i;
}
swapBlocks(blocks);
}
void CheckIntl1(unsigned char *ROM)
{
unsigned int ROMmidPoint = NumofBytes / 2;
if (validChecksum(ROM, ROMmidPoint + Lo) &&
!validChecksum(ROM, Lo) &&
ROM[ROMmidPoint+Lo+25] < 14) //Country Code
{
deintlv1();
Interleaved = true;
}
else if (validChecksum(ROM, Lo) && !validChecksum(ROM, Hi) &&
ROM[Lo+25] < 14 && //Country code
//Rom make up
(ROM[Lo+21] == 33 || ROM[Lo+21] == 49 ||
ROM[Lo+21] == 53 || ROM[Lo+21] == 58))
{
if (ROM[Lo+20] == 32 ||//Check that Header name did not overflow
!(ROM[Lo+21] == ROM[Lo+20] || ROM[Lo+21] == ROM[Lo+19] ||
ROM[Lo+21] == ROM[Lo+18] || ROM[Lo+21] == ROM[Lo+17]))
{
deintlv1();
Interleaved = true;
}
}
}
void CheckIntlEHi(unsigned char *ROM)
{
if (EHiHeader(ROM, Lo))
{
unsigned int temp, i, oldNumBanks = NumofBanks,
*loc1 = romdata,
*loc2 = romdata + ((NumofBytes - 0x400000)/4);
//Swap 4MB ROM with the other one
for (i = 0; i < 0x100000; i++)
{
temp = loc1[i];
loc1[i] = loc2[i];
loc2[i] = temp;
}
//Deinterleave the 4MB ROM first
NumofBanks = 128;
deintlv1();
//Now the other one
NumofBanks = oldNumBanks - 128;
romdata += 0x100000; //Ofset pointer
deintlv1();
//Now fix the data and we're done
NumofBanks = oldNumBanks;
romdata -= 0x100000;
Interleaved = true;
}
}
//ROM loading functions, which some strangly enough were in guiload.inc
bool AllASCII(unsigned char *b, int size)
{
int i;
for (i = 0; i < size; i++)
{
if (b[i] < 32 || b[i] > 126)
{
return(false);
}
}
return(true);
}
int InfoScore(unsigned char *Buffer)
{
int score = 0;
if (validChecksum(Buffer, 0)) { score += 4; }
if (Buffer[26] == 0x33) { score += 2; }
if (!(Buffer[61] & 0x80)) { score -= 4; }
if ((1 << (Buffer[23] - 7)) > 48) { score -= 1; }
if (Buffer[25] < 14) { score += 1; }
if (!AllASCII(Buffer, 20)) { score -= 1; }
return(score);
}
extern unsigned char ForceHiLoROM;
extern unsigned char forceromtype;
void BankCheck()
{
unsigned char *ROM = (unsigned char *)romdata;
infoloc = 0;
Interleaved = false;
if (NumofBytes >= 0x500000)
{
//Deinterleave if neccesary
CheckIntlEHi(ROM);
if (EHiHeader(ROM, EHi))
{
romtype = 2;
infoloc = EHi;
}
}
if (!infoloc)
{
static bool CommandLineForce2 = false;
int loscore, hiscore;
//Deinterleave if neccesary
CheckIntl1(ROM);
loscore = InfoScore(ROM+Lo);
hiscore = InfoScore(ROM+Hi);
switch(ROM[Lo + 21])
{
case 32: case 35: case 48: case 50:
loscore += 2;
case 128: case 156: case 176: case 188: case 252: //BS
loscore += 1;
break;
}
switch(ROM[Hi + 21])
{
case 33: case 49: case 53: case 58:
hiscore += 2;
case 128: case 156: case 176: case 188: case 252: //BS
hiscore += 1;
break;
}
/*
Force code.
ForceHiLoROM is from the GUI.
forceromtype is from Command line, we have a static var
to prevent forcing a secong game loaded from the GUI when
the first was loaded from the command line with forcing.
*/
if (ForceHiLoROM == 1 ||
(forceromtype == 1 && !CommandLineForce2))
{
CommandLineForce2 = true;
loscore += 50;
}
else if (ForceHiLoROM == 2 ||
(forceromtype == 2 && !CommandLineForce2))
{
CommandLineForce2 = true;
hiscore += 50;
}
if (hiscore > loscore)
{
romtype = 2;
infoloc = Hi;
}
else
{
romtype = 1;
infoloc = Lo;
}
}
}
//Checksum functions
unsigned short sum(unsigned char *array, unsigned int size)
{
unsigned short theSum = 0;
unsigned int i;
//Prevent crashing by reading too far (needed for messed up ROMs)
if (array + size > (unsigned char *)romdata + maxromspace)
{
return(0xFFFF);
}
for (i = 0; i < size; i++)
{
theSum += array[i];
}
return(theSum);
}
extern unsigned char SPC7110Enable;
extern unsigned char BSEnable;
extern unsigned short Checksumvalue;
void CalcChecksum()
{
unsigned char *ROM = (unsigned char *)romdata;
if (SplittedROM)
{
Checksumvalue = sum(ROM+addOnStart, addOnSize);
Checksumvalue -= sum(ROM+infoloc+addOnStart-16, 48);
}
else if (SPC7110Enable)
{
Checksumvalue = sum(ROM, NumofBytes);
if (NumofBytes == 0x300000) //Fix for 24Mb SPC7110 ROMs
{
Checksumvalue += Checksumvalue;
}
}
else
{
Checksumvalue = sum(ROM, curromspace);
if (NumofBanks > 128 && maxromspace == 6*MB_bytes)
{
Checksumvalue += sum(ROM+4*MB_bytes, 2*MB_bytes);
}
if (BSEnable)
{
Checksumvalue -= sum(&ROM[infoloc - 16], 48); //Fix for BS Dumps
}
}
}
//Misc functions
void MirrorROM()
{
unsigned char *ROM = (unsigned char *)romdata;
unsigned int size, StartMirror = 0, ROMSize = curromspace;
//This will mirror up non power of two ROMs to powers of two
for (size = 1; size <= 64; size +=size)
{
unsigned int fullSize = size * Mbit_bytes,
halfSize = fullSize >> 1;
if ((ROMSize > halfSize) && (ROMSize < fullSize))
{
for (StartMirror = halfSize;
ROMSize < fullSize && ROMSize < maxromspace;)
{
ROM[ROMSize++] = ROM[StartMirror++];
}
curromspace = ROMSize;
break;
}
}
//This will mirror (now) full sized ROMs through the ROM buffer
for (StartMirror = 0; ROMSize < maxromspace;)
{
ROM[ROMSize++] = ROM[StartMirror++];
}
NumofBanks = curromspace >> 15;
}
//File loading code
extern char *ZOpenFileName;
bool Header512;
extern char CSStatus[41];
extern char CSStatus2[41];
extern char CSStatus3[41];
char *lastROMFileName;
void DumpROMLoadInfo()
{
FILE *fp = 0;
fp = fopen("rominfo.txt", "w");
if (!fp) { return; }
fputs("This is the info for the last game you ran.\n\nFile: ", fp);
fputs(lastROMFileName, fp);
fputs(" Header: ", fp);
fputs(Header512 ? "Yes\n" : "No\n", fp);
fputs(CSStatus, fp);
fputs("\n", fp);
fputs(CSStatus2, fp);
fputs("\n", fp);
fputs(CSStatus3, fp);
fputs("\n", fp);
fclose(fp);
}
void loadFile(char *filename)
{
bool multifile = false;
char *incrementer = 0;
unsigned char *ROM = (unsigned char *)romdata;
if (strlen(filename) >= 3) //Char + ".1"
{
char *ext = filename+strlen(filename)-2;
if (!strcmp(ext, ".1") || !strcasecmp(ext, ".A"))
{
incrementer = ext + 1;
multifile = true;
}
}
for (;;)
{
struct stat stat_results;
stat(filename, &stat_results);
if ((unsigned int)stat_results.st_size <= maxromspace+512-curromspace)
{
FILE *fp = 0;
fp = fopen(filename, "rb");
if (!fp) { return; }
if (curromspace && ((stat_results.st_size & 0x7FFF) == 512))
{
stat_results.st_size -= 512;
fseek(fp, 512, SEEK_SET);
}
fread(ROM+curromspace, stat_results.st_size, 1, fp);
fclose(fp);
curromspace += stat_results.st_size;
if (!multifile) { return; }
(*incrementer)++;
}
else
{
return;
}
}
}
void loadGZipFile(char *filename)
{
int size, err;
gzFile GZipFile;
FILE *fp = 0;
fp = fopen(filename, "rb");
if (!fp) { return; }
fseek(fp, -4, SEEK_END);
//Size is read like this due to VC screwing up with optimizations
size = fgetc(fp);
size |= fgetc(fp) << 8;
size |= fgetc(fp) << 16;
size |= fgetc(fp) << 24;
fclose(fp);
if ((unsigned int)size > maxromspace+512) { return; }
//Open GZip file for decompression
GZipFile = gzopen(filename, "rb");
//Decompress file into memory
err = gzread(GZipFile, romdata, size);
//Close compressed file
gzclose(GZipFile);
if (err != size) { return; }
curromspace = size;
}
//void Output_Text();
//asm volatile("movl _ZOpenFileName, %edx \n"
// "movb $9, %ah \n"
// "call _Output_Text \n");
//system("pause");
void loadZipFile(char *filename)
{
int err, fileSize;
unsigned char *ROM = (unsigned char *)romdata;
bool multifile = false, NSS = false;
char *incrementer = 0;
unzFile zipfile = unzOpen(filename); //Open zip file
int cFile = unzGoToFirstFile(zipfile); //Set cFile to first compressed file
unz_file_info cFileInfo; //Create variable to hold info for a compressed file
int LargestGoodFile = 0; //To keep track of largest file
//Variables for the file we pick
char ourFile[256];
ourFile[0] = '\n';
while(cFile == UNZ_OK) //While not at end of compressed file list
{
//Temporary char array for file name
char cFileName[256];
//Gets info on current file, and places it in cFileInfo
unzGetCurrentFileInfo(zipfile, &cFileInfo, cFileName, 256, NULL, 0, NULL, 0);
//Get the file's size
fileSize = cFileInfo.uncompressed_size;
//Find split files
if (strlen(cFileName) >= 3) //Char + ".1"
{
char *ext = cFileName+strlen(cFileName)-2;
if (!strcmp(ext, ".1") || !strcasecmp(ext, ".A"))
{
strcpy(ourFile, cFileName);
incrementer = ourFile+strlen(ourFile)-1;
multifile = true;
break;
}
}
//Find Nintendo Super System ROMs
if (strlen(cFileName) >= 5) //Char + ".IC2"
{
char *ext = cFileName+strlen(cFileName)-4;
if (!strncasecmp(ext, ".IC", 3))
{
strcpy(ourFile, cFileName);
incrementer = ourFile+strlen(ourFile)-1;
*incrementer = '7';
NSS = true;
break;
}
}
//Check for valid ROM based on size
if (((unsigned int)fileSize <= maxromspace+512) &&
(fileSize > LargestGoodFile))
{
strcpy(ourFile, cFileName);
LargestGoodFile = fileSize;
}
//Go to next file in zip file
cFile = unzGoToNextFile(zipfile);
}
//No files found
if (ourFile[0] == '\n')
{
unzClose(zipfile);
return;
}
for (;;)
{
//Sets current file to the file we liked before
if (unzLocateFile(zipfile, ourFile, 1) != UNZ_OK)
{
if (NSS)
{
(*incrementer)--;
continue;
}
unzClose(zipfile);
return;
}
//Gets info on current file, and places it in cFileInfo
unzGetCurrentFileInfo(zipfile, &cFileInfo, ourFile, 256, NULL, 0, NULL, 0);
//Get the file's size
fileSize = cFileInfo.uncompressed_size;
//Too big?
if (curromspace + fileSize > maxromspace+512)
{
unzClose(zipfile);
return;
}
//Open file
unzOpenCurrentFile(zipfile);
//Read file into memory
err = unzReadCurrentFile(zipfile, ROM+curromspace, fileSize);
//Close file
unzCloseCurrentFile(zipfile);
//Encountered error?
if (err != fileSize)
{
unzClose(zipfile);
return;
}
if (curromspace && ((fileSize & 0x7FFF) == 512))
{
fileSize -= 512;
memmove(ROM+curromspace, ROM+curromspace+512, fileSize);
}
curromspace += fileSize;
if (NSS)
{
if (!*incrementer) { return; }
(*incrementer)--;
continue;
}
if (!multifile)
{
unzClose(zipfile);
return;
}
(*incrementer)++;
}
}
void SplitSetup(char *basepath, char *basefile, unsigned int MirrorSystem)
{
unsigned char *ROM = (unsigned char *)romdata;
curromspace = 0;
if (maxromspace < addOnStart+addOnSize) { return; }
memcpy(ROM+addOnStart, ROM, addOnSize);
if (*basepath == 0)
{
loadZipFile(basefile);
}
else
{
unsigned int pathlen = strlen(basepath);
char *ext = basepath+pathlen-4;
if (pathlen >= 5 && !strcasecmp(ext, ".zip"))
{
loadZipFile(basepath);
}
else if (pathlen >= 4 && !strcasecmp(ext+1, ".gz"))
{
loadGZipFile(basepath);
}
else
{
loadFile(basepath);
}
}
if ((curromspace & 0x7FFF) == 512)
{
memmove(ROM, ROM+512, addOnStart);
curromspace -= 512;
}
if (!curromspace) { return; }
switch (MirrorSystem)
{
case 1:
memcpy(ROM+0x100000, ROM, 0x100000); //Mirror 8 to 16
break;
case 2:
memcpy(ROM+0x180000, ROM+0x100000, 0x80000); //Mirrors 12 to 16
memcpy(ROM+0x200000, ROM+0x400000, 0x80000); //Copy base over
memset(ROM+0x280000, 0, 0x180000); //Blank out rest
break;
case 3:
memcpy(ROM+0x40000, ROM, 0x40000);
memcpy(ROM+0x80000, ROM, 0x80000);
break;
}
curromspace = addOnStart+addOnSize;
SplittedROM = true;
}
extern char STPath[1024];
extern char GNextPath[1024];
extern char SGPath[1024];
void SplitSupport()
{
unsigned char *ROM = (unsigned char *)romdata;
SplittedROM = false;
//Same Game add on
if (ROM[Hi+26] == 0x33 && curromspace == 0x80000 &&
!ROM[Hi+21] && !ROM[Hi+22] && !ROM[Hi+23])
{
addOnStart = 0x200000;
addOnSize = 0x80000;
SplitSetup(SGPath, "SAMEGAME.ZIP", 1);
}
//SD Gundam G-Next add on
if (ROM[Lo+26] == 0x33 && curromspace == 0x80000 &&
!ROM[Lo+21] && !ROM[Lo+22] && !ROM[Lo+23] && !strncmp(ROM+Lo, "GNEXT", 5))
{
addOnStart = 0x400000;
addOnSize = 0x80000;
SplitSetup(GNextPath, "G-NEXT.ZIP", 2);
addOnStart = 0x200000;
}
//Sufami Turbo
if (!strncmp(ROM, "BANDAI SFC-ADX", 14))
{
addOnStart = 0x100000;
addOnSize = curromspace;
SplitSetup(STPath, "STBIOS.ZIP", 3);
}
}
bool NSRTHead(unsigned char *ROM)
{
unsigned char *NSRTHead = ROM + 0x1D0; //NSRT Header Location
if (!strncmp("NSRT", (char*)&NSRTHead[24],4) && NSRTHead[28] == 22)
{
if ((sum(NSRTHead, 32) & 0xFF) != NSRTHead[30] ||
NSRTHead[30] + NSRTHead[31] != 255 ||
(NSRTHead[0] & 0x0F) > 13 ||
((NSRTHead[0] & 0xF0) >> 4) > 3 ||
((NSRTHead[0] & 0xF0) >> 4) == 0)
{
return(false); //Corrupt
}
return(true); //NSRT header
}
return(false); //None
}
extern bool Sup48mbit;
extern bool Sup16mbit;
extern unsigned char snesmouse;
unsigned char snesinputdefault;
bool input1gp;
bool input1mouse;
bool input2gp;
bool input2mouse;
bool input2scope;
bool input2just;
void findZipIPS(char *);
void loadROM()
{
bool isCompressed = false, isZip = false;
curromspace = 0;
maxromspace = 4194304;
if (Sup48mbit) { maxromspace += 2097152; }
if (Sup16mbit) { maxromspace -= 2097152; } //I don't get it either
lastROMFileName = ZOpenFileName;
if (strlen(ZOpenFileName) >= 5) //Char + ".zip"
{
char *ext = ZOpenFileName+strlen(ZOpenFileName)-4;
if (!strcasecmp(ext, ".zip"))
{
isCompressed = true;
isZip = true;
loadZipFile(ZOpenFileName);
}
}
if (strlen(ZOpenFileName) >= 4) //Char + ".gz"
{
char *ext = ZOpenFileName+strlen(ZOpenFileName)-3;
if (!strcasecmp(ext, ".gz"))
{
isCompressed = true;
loadGZipFile(ZOpenFileName);
}
}
if (!isCompressed) { loadFile(ZOpenFileName); }
Header512 = false;
if (!curromspace) { return; }
if (!strncmp("GAME DOCTOR SF 3", (char *)romdata, 16) ||
!strncmp("SUPERUFO", (char *)romdata+8, 8))
{
Header512 = true;
}
else
{
int HeadRemain = (curromspace & 0x7FFF);
switch(HeadRemain)
{
case 0:
break;
case 512:
Header512 = true;
break;
default:
{
unsigned char *ROM = (unsigned char *)romdata;
//SMC/SWC header
if (ROM[8] == 0xAA && ROM[9]==0xBB && ROM[10]== 4)
{
Header512 = true;
}
//FIG header
else if ((ROM[4] == 0x77 && ROM[5] == 0x83) ||
(ROM[4] == 0xDD && ROM[5] == 0x82) ||
(ROM[4] == 0xDD && ROM[5] == 2) ||
(ROM[4] == 0xF7 && ROM[5] == 0x83) ||
(ROM[4] == 0xFD && ROM[5] == 0x82) ||
(ROM[4] == 0x00 && ROM[5] == 0x80) ||
(ROM[4] == 0x47 && ROM[5] == 0x83) ||
(ROM[4] == 0x11 && ROM[5] == 2))
{
Header512 = true;
}
break;
}
}
}
snesmouse = 0;
input1gp = true;
input1mouse = true;
input2gp = true;
input2mouse = true;
input2scope = true;
input2just = true;
if (Header512)
{
unsigned char *ROM = (unsigned char *)romdata;
if (NSRTHead(ROM))
{
switch (ROM[0x1ED])
{
default: break;
case 0:
input1mouse = false;
input2mouse = false;
input2scope = false;
input2just = false;
break;
case 0x01: //Mouse port 2
snesmouse = 2;
input2gp = false;
input2scope = false;
input2just = false;
input1mouse = false;
break;
case 0x03: //Super Scope port 2
snesmouse = 3;
input2gp = false;
input2mouse = false;
input2just = false;
input1mouse = false;
break;
case 0x04: //Super Scope or Gamepad port 2
snesmouse = 3;
input2mouse = false;
input2just = false;
input1mouse = false;
break;
case 0x05: //Justifier (Lethal Enforcer gun) port 2
snesmouse = 4;
input2mouse = false;
input2scope = false;
input1mouse = false;
break;
case 0x06: //Multitap port 2
input2gp = false;
input2mouse = false;
input2just = false;
input2scope = false;
input1mouse = false;
break;
case 0x08: //Mouse or Multitap port 2
snesmouse = 2;
input2just = false;
input2scope = false;
input1mouse = false;
break;
case 0x10: //Mouse port 1
snesmouse = 1;
input2mouse = false;
input2just = false;
input2scope = false;
input1gp = false;
break;
case 0x20: //Mouse or Gamepad port 1
snesmouse = 1;
input2mouse = false;
input2just = false;
input2scope = false;
break;
case 0x22: //Mouse or Gamepad port 1 and port 2
snesmouse = 1;
input2just = false;
input2scope = false;
break;
case 0x27: //Mouse or Gamepad port 1, Mouse, Super Scope, or Gamepad port 2
input2just = false;
break;
case 0x99: break; //Lasabirdie
case 0x0A: break; //Barcode Battler
}
}
curromspace -= 512;
memmove((unsigned char *)romdata, ((unsigned char *)romdata)+512, curromspace);
}
snesinputdefault = snesmouse;
SplitSupport();
if (isZip) { findZipIPS(ZOpenFileName); }
}
//Memory Setup functions
extern unsigned char wramdataa[65536];
extern unsigned char ram7fa[65536];
extern unsigned char srama[65536];
extern unsigned char debugbufa[80000];
extern unsigned char regptra[49152];
extern unsigned char regptwa[49152];
extern unsigned char vidmemch2[4096];
extern unsigned char vidmemch4[4096];
extern unsigned char vidmemch8[4096];
extern unsigned char pal16b[1024];
extern unsigned char pal16bcl[1024];
extern unsigned char pal16bclha[1024];
extern unsigned char pal16bxcl[256];
extern unsigned char spcRam[65472];
extern unsigned char *sram;
extern unsigned char *vidbuffer;
extern unsigned char *vram;
extern unsigned char *vcache2b;
extern unsigned char *vcache4b;
extern unsigned char *vcache8b;
void clearmem2();
void clearmem()
{
memset(vidbuffer, 0, 131072);
memset(wramdataa, 0, 65536);
memset(ram7fa, 0, 65536);
memset(vram, 0, 65536);
memset(srama, 0, 65536);
memset(debugbufa, 0, 80000);
memset(regptra, 0, 49152);
memset(regptwa, 0, 49152);
memset(vcache2b, 0, 262144);
memset(vcache4b, 0, 131072);
memset(vcache8b, 0, 65536);
memset(vidmemch2, 0, 4096);
memset(vidmemch4, 0, 4096);
memset(vidmemch8, 0, 4096);
memset(pal16b, 0, 1024);
memset(pal16bcl, 0, 1024);
memset(pal16bclha, 0, 1024);
memset(pal16bxcl, 0xFF, 256);
memset(romdata, 0xFF, maxromspace+32768);
clearmem2();
}
void clearSPCRAM()
{
/*
SPC RAM is filled with alternating 0x00 and 0xFF for 0x20 bytes.
Basically the SPCRAM is initialized as follows:
xx00 - xx1f: $00
xx20 - xx3f: $ff
xx40 - xx5f: $00
xx60 - xx7f: $ff
xx80 - xx9f: $00
xxa0 - xxbf: $ff
xxc0 - xxdf: $00
xxe0 - xxff: $ff
*/
unsigned int i;
for (i = 0; i < 65472; i += 0x40)
{
memset(spcRam+i, 0, 0x20);
memset(spcRam+i+0x20, 0xFF, 0x20);
}
}
void clearmem2()
{
memset(sram, 0xFF, 16384);
clearSPCRAM();
}
/*
--------------Caution Hack City--------------
Would be nice to trash this section in the future
*/
extern unsigned char disablehdma;
extern unsigned char hdmaearlstart;
extern unsigned int WindowDisables;
extern unsigned char ClearScreenSkip;
extern unsigned char ENVDisable;
extern unsigned char latchyr;
extern unsigned char cycpb268;
extern unsigned char cycpb358;
extern unsigned char cycpbl2;
extern unsigned char cycpblt2;
extern unsigned char cycpbl;
extern unsigned char cycpblt;
extern unsigned char opexec268;
extern unsigned char opexec358;
extern unsigned char opexec268cph;
extern unsigned char opexec358cph;
extern unsigned char DSP1Type;
extern unsigned int ewj2hack;
extern unsigned char cycpl;
void headerhack()
{
char *RomData = (char *)romdata;
disablehdma = 0;
hdmaearlstart = 0;
WindowDisables = 0;
ClearScreenSkip = 0;
ENVDisable = 0;
//These next fiew look like RAM init hacks, should be looked into
//Should be Super Famista (J), uses non-standard characters
if (!strncmp((RomData+Lo),"\x0bd\x0b0\x0ca\x0df\x0b0\x0cc\x0a7\x0d0\x0bd\x0c0 " ,16))
{
RomData[0x2762F] = 0xEA;
RomData[0x27630] = 0xEA;
}
//Should be Super Famista 2 (J), uses non-standard characters
if (!strncmp((RomData+Lo),"\x0bd\x0b0\x0ca\x0df\x0b0\x0cc\x0a7\x0d0\x0bd\x0c0 \x032 " ,16))
{
//Skip a check for value FF at 2140 when spc not initialized yet?!?
RomData[0x6CED] = 0xEA;
RomData[0x6CEE] = 0xEA;
//Skip a check for value FF at 2140 when spc not initialized yet?!?
RomData[0x6CF9] = 0xEA;
RomData[0x6CFA] = 0xEA;
}
//Kamen Rider (J)
if (!strncmp((RomData+Lo),"SFC \x0b6\x0d2\x0dd\x0d7\x0b2\x0c0\x0de\x0b0 " ,16))
{
latchyr = 2;
}
//Deae Tonosama Appare Ichiban (J)
if (!strncmp((RomData+Lo),"\x0c3\x0de\x0b1\x0b4\x0c4\x0c9\x0bb\x0cf \x0b1\x0af\x0ca" ,12))
{
RomData[0x17837] = 0xEA;
RomData[0x17838] = 0xEA;
}
/*
The asm indicates the hack is for HGP3, but all of these are affected
Human Grand Prix (J), Human Grand Prix II (J),
Human Grand Prix III - F1 Triple Battle (J).
Human Grand Prix IV is a HiROM and is not affected
*/
if (!strncmp((RomData+Lo),"HUMAN GRANDP" ,12))
{
cycpb268 = 135;
cycpb358 = 157;
cycpbl2 = 125;
cycpblt2 = 125;
cycpbl = 125;
cycpblt = 125;
}
//Accele Brid (J)
if (!strncmp((RomData+Lo),"ACCELEBRID " ,12))
{
RomData[0x34DA2] = 0;
RomData[0x34DA3] = 0;
}
//Battle Grand Prix (J)
if (!strncmp((RomData+Lo),"BATTLE GRAND" ,12))
{
RomData[0x18089] = 0xFB;
RomData[0x6C95] = 0xFB;
}
//Neugier (J), and it's English translation
if (!strncmp((RomData+Lo),"NEUGIER " ,12) ||
!strncmp((RomData+Lo),"Neugier (tr." ,12))
{
RomData[0xD4150] = 0xF9;
}
//Home Alone (J/E/U)
if (!strncmp((RomData+Lo),"HOME ALO" ,8))
{
RomData[0x666B] = 0xEE;
RomData[0x666C] = 0xBC;
}
//Emerald Dragon (J)
if (!strncmp((RomData+Hi),"EMERALD DRAG" ,12))
{
ENVDisable = true;
}
/*
Super Mario World 2 - Yoshi's Island (U/E),
Super Mario - Yossy Island (J), and variants
*/
if (!strncmp((RomData+Lo),"YOSSY'S ISLA" ,12) ||
!strncmp((RomData+Lo),"YOSHI'S ISLA" ,12))
{
hdmaearlstart = 2;
opexec268 = 116;
opexec358 = 126;
}
//Bubsy II (U/E)
if (!strncmp((RomData+Hi),"BUBSY II" ,8))
{
cycpb268 = 125;
cycpb358 = 147;
cycpbl2 = 125;
cycpblt2 = 125;
cycpbl = 125;
cycpblt = 125;
}
/*
Marvelous (J) has this hack in the asm, but disabled
Alternate if for Marvelous-inclusive version
if (!strncmp((RomData+Lo),"\x0cf\x0bo\x0b3\x0de", 4) ||
!strncmp((RomData+Lo),"REND", 4))
*/
//Rendering Ranger R2
if (!strncmp((RomData+Lo),"REND", 4))
{
cycpb268 = 157;
cycpb358 = 157;
cycpbl2 = 157;
cycpblt2 = 157;
cycpbl = 157;
cycpblt = 157;
}
//Clay Fighter (U), other versions are CLAYFIGHTER with no space
if (!strncmp((RomData+Hi),"CLAY FIGHTER " ,16))
{
//Intro
RomData[0x1A10B9] = 0xDE;
//In Game
RomData[0x1A1996] = 0xDE;
RomData[0x1AE563] = 0xDE;
RomData[0x1AE600] = 0xDE;
}
//Bahamut Lagoon (J) and all known translations
if (!strncmp((RomData+Hi),"Bahamut Lago" ,12))
{
RomData[0x10254] = 0xEE;
}
//Mortal Kombat (J/U/E), Super Punch-Out, Dragon Quest 5 (J)
if (!strncmp((RomData+Lo),"DRAGONQUEST5" ,12) ||
!strncmp((RomData+Lo),"MORTAL KOMBAT " ,16) ||
!strncmp((RomData+Lo),"Super Punch-Out!! ", 20))
{
disablehdma = true;
}
//Super Final Match Tennis (J)
if (!strncmp((RomData+Lo),"SP F", 4))
{
cycpb268 = 145;
cycpb358 = 147;
cycpbl2 = 145;
cycpblt2 = 145;
cycpbl = 145;
cycpblt = 145;
}
//Okaaay...
if(DSP1Type) { disablehdma = true; }
//Final Fantasy 3 (extent unknown!)
if (romdata[0x26AC] == 0xF00F2908)
{
//asm volatile("int $3");
opexec268 = 163;
opexec358 = 157;
opexec268cph = 39;
opexec358cph = 39;
}
//Earthworm Jim 2 (all regions?)
if (!strncmp((RomData+Lo),"EARTHWORM JIM 2 " ,20))
{
RomData[0x2A9C1A] = 0;
RomData[0x2A9C1B] = 0;
RomData[0x2A9C1F] = 0;
RomData[0x2A9C20] = 0;
ewj2hack = true;
}
//Lamborghini - American Challenge (U/E)
if (!strncmp((RomData+Lo), "LAMBORGHINI AMERICAN", 20))
{
opexec268 = 187;
opexec358 = 187;
}
//Addams Family Values (U/E)
if (!strncmp((RomData+Lo), "ADDAMS FAMILY VALUES", 20))
{
opexec268 = 120;
opexec358 = 100;
}
//Front Mission
if (!strncmp((RomData+Hi), "\x0cc\x0db\x0dd\x0c4\x0d0\x0af\x0bc\x0ae", 8) ||
!strncmp((RomData+Hi), "FRONT MI", 8))
{
opexec268 = 226;
opexec358 = 226;
opexec268cph = 80;
opexec358cph = 80;
}
return;
}
extern unsigned char per2exec;
void Setper2exec()
{
opexec268 = (unsigned char)(opexec268*(per2exec*0.01));
opexec358 = (unsigned char)(opexec358*(per2exec*0.01));
opexec268cph = (unsigned char)(opexec268cph*(per2exec*0.01));
opexec358cph = (unsigned char)(opexec358cph*(per2exec*0.01));
}
extern char FEOEZPath[1024];
extern char SJNSPath[1024];
extern char MDHPath[1024];
extern char SPL4Path[1024];
char *SPC7110filep;
char SPC7110nfname[1024+12]; //12 is / plus 6.3
unsigned int SPC7110IndexSize;
extern unsigned int SPC7110Entries;
void SPC7PackIndexLoad()
{
unsigned char *ROM = (unsigned char *)romdata;
FILE *fp = 0;
SPC7110IndexSize = 0;
//Get correct path for the ROM we just loaded
if (!strncmp(ROM+infoloc, "HU TENGAI MAKYO ZERO ", 21))
{
strcpy(SPC7110nfname, *FEOEZPath ? FEOEZPath : "FEOEZSP7");
}
else if (!strncmp(ROM+infoloc, "JUMP TENGAIMAKYO ZERO", 21))
{
strcpy(SPC7110nfname, *SJNSPath ? SJNSPath : "SJNS-SP7");
}
else if (!strncmp(ROM+infoloc, "MOMOTETSU HAPPY ", 21))
{
strcpy(SPC7110nfname, *MDHPath ? MDHPath : "MDH-SP7");
}
else if (!strncmp(ROM+infoloc, "SUPER POWER LEAG 4 ", 21))
{
strcpy(SPC7110nfname, *SPL4Path ? SPL4Path : "SPL4-SP7");
}
//Add a slash if needed
if (SPC7110nfname[strlen(SPC7110nfname)-1] != *DIR_SLASH)
{
strcat(SPC7110nfname, DIR_SLASH);
}
//Set the pointer to after the slash - needed for sa1regs.asm
SPC7110filep = SPC7110nfname+strlen(SPC7110nfname);
//Index file;
strcat(SPC7110nfname, "index.bin");
//Load the index
fp = fopen(SPC7110nfname, "rb");
if (!fp) { return; }
SPC7110IndexSize = fread(ROM+0x580000, 1, 12*32768, fp);
fclose(fp);
SPC7110Entries = 0;
//Get file pointer ready for individual pack files
strcpy(SPC7110filep, "123456.bin"); //Extension Lower Case
}
void SPC7_Convert_Upper()
{
char *i = SPC7110filep;
while (*i)
{
if (islower(*i)) { *i = toupper(*i); } //To make extension Upper case
i++;
}
}
void SPC7_Convert_Lower()
{
char *i = SPC7110filep;
while (*i)
{
if (isupper(*i)) { *i = tolower(*i); } //To make everything Lower case
i++;
}
}