2887 lines
67 KiB
C
2887 lines
67 KiB
C
/*
|
|
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
|
|
|
http://www.zsnes.com
|
|
http://sourceforge.net/projects/zsnes
|
|
https://zsnes.bountysource.com
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
version 2 as published by the Free Software Foundation.
|
|
|
|
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 __UNIXSDL__
|
|
#include "gblhdr.h"
|
|
#include "linux/audio.h"
|
|
#define DIR_SLASH "/"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#define DIR_SLASH "\\"
|
|
#endif
|
|
#include "asm_call.h"
|
|
#include "cfg.h"
|
|
#include "input.h"
|
|
#include "zpath.h"
|
|
#include "cpu/memtable.h"
|
|
|
|
#define NUMCONV_FR4
|
|
#include "numconv.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
|
|
|
|
//NSRT Goodness
|
|
#define Lo 0x7FC0
|
|
#define Hi 0xFFC0
|
|
#define EHi 0x40FFC0
|
|
|
|
#define MB_bytes 0x100000
|
|
#define Mbit_bytes 0x20000
|
|
|
|
//Offsets to add to infoloc start to reach particular variable
|
|
#define BankOffset 21 //Contains Speed as well
|
|
#define TypeOffset 22
|
|
#define ROMSizeOffset 23
|
|
#define SRAMSizeOffset 24
|
|
#define CountryOffset 25
|
|
#define CompanyOffset 26
|
|
#define VersionOffset 27
|
|
#define InvCSLowOffset 28
|
|
#define InvCSHiOffset 29
|
|
#define CSLowOffset 30
|
|
#define CSHiOffset 31
|
|
//Additional defines for the BS header
|
|
#define BSYearOffset 21 //Not sure how to calculate year yet
|
|
#define BSMonthOffset 22
|
|
#define BSDayOffset 23
|
|
#define BSBankOffset 24
|
|
#define BSSizeOffset 25 //Contains Type as well
|
|
//26 - 31 is the same
|
|
#define ResetLoOffset 60
|
|
#define ResetHiOffset 61
|
|
|
|
|
|
// Some archaic code from an unfinished Dynarec
|
|
extern unsigned int curexecstate;
|
|
extern unsigned char spcon;
|
|
|
|
void procexecloop()
|
|
{
|
|
curexecstate &= 0xFFFFFF00;
|
|
|
|
if (spcon) { curexecstate += 3; }
|
|
else { curexecstate += 1; }
|
|
}
|
|
|
|
void Debug_WriteString(char *str)
|
|
{
|
|
FILE *fp = 0;
|
|
fp = fopen_dir(ZCfgPath, "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;
|
|
unsigned int ramsize;
|
|
unsigned int ramsizeand;
|
|
|
|
bool SplittedROM;
|
|
unsigned int addOnStart;
|
|
unsigned int addOnSize;
|
|
|
|
|
|
//Deinterleave functions
|
|
bool validChecksum(unsigned char *ROM, int BankLoc)
|
|
{
|
|
if (ROM[BankLoc + InvCSLowOffset] + (ROM[BankLoc + InvCSHiOffset] << 8) +
|
|
ROM[BankLoc + CSLowOffset] + (ROM[BankLoc + CSHiOffset] << 8) == 0xFFFF)
|
|
{
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
bool valid_normal_bank(unsigned char bankbyte)
|
|
{
|
|
switch (bankbyte)
|
|
{
|
|
case 32: case 33: case 48: case 49:
|
|
return(true);
|
|
break;
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
bool EHiHeader(unsigned char *ROM, int BankLoc)
|
|
{
|
|
if (validChecksum(ROM, BankLoc) && (ROM[BankLoc+BankOffset] == 53 || ROM[BankLoc+BankOffset] == 37))
|
|
{
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
void SwapData(unsigned int *loc1, unsigned int *loc2, unsigned int amount)
|
|
{
|
|
unsigned int temp;
|
|
while (amount--)
|
|
{
|
|
temp = *loc1;
|
|
*loc1++ = *loc2;
|
|
*loc2++ = temp;
|
|
}
|
|
}
|
|
|
|
void swapBlocks(char *blocks)
|
|
{
|
|
unsigned int i, j;
|
|
for (i = 0; i < NumofBanks; i++)
|
|
{
|
|
for (j = 0; j < NumofBanks; j++)
|
|
{
|
|
if (blocks[j] == (char)i)
|
|
{
|
|
char b;
|
|
SwapData(romdata + blocks[i]*0x2000, romdata + blocks[j]*0x2000, 0x2000);
|
|
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+CountryOffset] < 14) //Country Code
|
|
{
|
|
deintlv1();
|
|
Interleaved = true;
|
|
}
|
|
else if (validChecksum(ROM, Lo) && !validChecksum(ROM, Hi) &&
|
|
ROM[Lo+CountryOffset] < 14 && //Country code
|
|
//Rom make up
|
|
(ROM[Lo+BankOffset] == 33 || ROM[Lo+BankOffset] == 49 ||
|
|
ROM[Lo+BankOffset] == 53 || ROM[Lo+BankOffset] == 58))
|
|
{
|
|
if (ROM[Lo+20] == 32 ||//Check that Header name did not overflow
|
|
!(ROM[Lo+BankOffset] == ROM[Lo+20] || ROM[Lo+BankOffset] == ROM[Lo+19] ||
|
|
ROM[Lo+BankOffset] == ROM[Lo+18] || ROM[Lo+BankOffset] == ROM[Lo+17]))
|
|
{
|
|
deintlv1();
|
|
Interleaved = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CheckIntlEHi(unsigned char *ROM)
|
|
{
|
|
if (EHiHeader(ROM, Lo))
|
|
{
|
|
unsigned int oldNumBanks = NumofBanks;
|
|
|
|
//Swap 4MB ROM with the other one
|
|
SwapData(romdata, romdata+((NumofBytes-0x400000)/4), 0x100000);
|
|
|
|
//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] && (b[i] < 32 || b[i] > 126))
|
|
{
|
|
return(false);
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
//Code to detect if opcode sequence is a valid and popular one for an SNES ROM
|
|
//Code by Cowering
|
|
static bool valid_start_sequence(unsigned char opcode1, unsigned char opcode2, unsigned char opcode3)
|
|
{
|
|
switch (opcode1)
|
|
{
|
|
case 0x78: case 0x5c: case 0x18: case 0xad:
|
|
return(true);
|
|
break;
|
|
case 0x4b:
|
|
if (opcode2 == 0xab && (opcode3 == 0x18 || opcode3 == 0x20))
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0x4c:
|
|
if ((opcode2 == 0x00 || opcode2 == 0xc0) && opcode3 == 0x84)
|
|
{
|
|
return(true);
|
|
}
|
|
if (opcode2 == 0x6d && opcode3 == 0x86)
|
|
{
|
|
return(true);
|
|
}
|
|
if (opcode2 == 0x00 && opcode3 == 0x80)
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0xc2:
|
|
if (opcode2 == 0x30 && opcode3 == 0xa9)
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0x20:
|
|
if ((opcode2 == 0x16 || opcode2 == 0x06) && opcode3 == 0x80)
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0x80:
|
|
if ((opcode2 == 0x16 && opcode3 == 0x4c) ||
|
|
(opcode2 == 0x07 && opcode3 == 0x82))
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0x9c:
|
|
if (opcode2 == 0x00 && opcode3 == 0x21)
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0xa2:
|
|
if (opcode2 == 0xff && opcode3 == 0x86)
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
case 0xa9:
|
|
if ((opcode2 == 0x00 && (opcode3 = 0x48 || opcode3 == 0x4b)) ||
|
|
(opcode2 == 0x8f && opcode3 == 0x8d) ||
|
|
(opcode2 == 0x20 && opcode3 == 0x4b) ||
|
|
(opcode2 == 0x1f && opcode3 == 0x4b))
|
|
{
|
|
return(true);
|
|
}
|
|
break;
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
static int valid_reset(unsigned char *Buffer)
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
unsigned short Reset = Buffer[ResetLoOffset] | ((unsigned short)Buffer[ResetHiOffset] << 8);
|
|
if ((Reset != 0xFFFF) && (Reset & 0x8000))
|
|
{
|
|
unsigned char opcode1 = ROM[(Reset+0) & 0x7FFF];
|
|
unsigned char opcode2 = ROM[(Reset+1) & 0x7FFF];
|
|
unsigned char opcode3 = ROM[(Reset+2) & 0x7FFF];
|
|
|
|
if (valid_start_sequence(opcode1, opcode2, opcode3))
|
|
{
|
|
return(10);
|
|
}
|
|
return(2);
|
|
}
|
|
return(-4);
|
|
}
|
|
|
|
int InfoScore(unsigned char *Buffer)
|
|
{
|
|
int score = valid_reset(Buffer);
|
|
if (validChecksum(Buffer, 0)) { score += 5; }
|
|
if (Buffer[CompanyOffset] == 0x33) { score += 3; }
|
|
if (!Buffer[ROMSizeOffset]) { score += 2; }
|
|
if ((1 << (Buffer[ROMSizeOffset] - 7)) > 48) { score -= 2; }
|
|
if ((8 << Buffer[SRAMSizeOffset]) > 1024) { score -= 2; }
|
|
if (Buffer[CountryOffset] < 14) { score += 2; }
|
|
if (!AllASCII(Buffer, 20)) { score -= 2; }
|
|
if (valid_normal_bank(Buffer[BSBankOffset])) { score += 2; }
|
|
return(score);
|
|
}
|
|
|
|
extern unsigned char ForceHiLoROM;
|
|
extern unsigned char forceromtype;
|
|
|
|
void BankCheck()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
infoloc = 0;
|
|
Interleaved = false;
|
|
|
|
if (NumofBytes < Lo)
|
|
{
|
|
romtype = 1;
|
|
infoloc = 1; //Whatever, we just need a valid location
|
|
}
|
|
|
|
if (NumofBytes < Hi)
|
|
{
|
|
romtype = 1;
|
|
infoloc = Lo;
|
|
}
|
|
|
|
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 + BankOffset])
|
|
{
|
|
case 32: case 35: case 48: case 50:
|
|
loscore += 3;
|
|
break;
|
|
}
|
|
switch(ROM[Hi + BankOffset])
|
|
{
|
|
case 33: case 49: case 53: case 58:
|
|
hiscore += 3;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Chip detection functions
|
|
bool CHIPBATT, BSEnable, C4Enable, DSP1Enable, DSP2Enable, DSP3Enable;
|
|
bool DSP4Enable, OBCEnable, RTCEnable, SA1Enable, SDD1Enable, SFXEnable;
|
|
bool SETAEnable; //ST010 & 11
|
|
bool SGBEnable, SPC7110Enable, ST18Enable;
|
|
|
|
void chip_detect()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
C4Enable = RTCEnable = SA1Enable = SDD1Enable = OBCEnable = CHIPBATT = false;
|
|
SGBEnable = ST18Enable = DSP1Enable = DSP2Enable = DSP3Enable = false;
|
|
DSP4Enable = SPC7110Enable = BSEnable = SFXEnable = SETAEnable = false;
|
|
|
|
//DSP Family
|
|
if (ROM[infoloc+TypeOffset] == 3)
|
|
{
|
|
if (ROM[infoloc+BankOffset] == 48) { DSP4Enable = true; }
|
|
else { DSP1Enable = true; }
|
|
return;
|
|
}
|
|
|
|
if (ROM[infoloc+TypeOffset] == 5)
|
|
{
|
|
CHIPBATT = true;
|
|
if (ROM[infoloc+BankOffset] == 32) { DSP2Enable = true; }
|
|
else if (ROM[infoloc+BankOffset] == 48 && ROM[infoloc+CompanyOffset] == 0xB2) //Bandai
|
|
{ DSP3Enable = true; }
|
|
else { DSP1Enable = true; }
|
|
return;
|
|
}
|
|
|
|
switch((unsigned short)ROM[infoloc+BankOffset] | (ROM[infoloc+TypeOffset] << 8))
|
|
{
|
|
case 0x1320: //Mario Chip 1
|
|
case 0x1420: //GSU-x
|
|
SFXEnable = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x1520: //GSU-x + Battery
|
|
case 0x1A20: //GSU-1 + Battery + Start in 21MHz
|
|
SFXEnable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x2530:
|
|
OBCEnable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x3423:
|
|
SA1Enable = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x3223: //One sample game seems to use this for some reason
|
|
case 0x3523:
|
|
SA1Enable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x4332:
|
|
SDD1Enable = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x4532:
|
|
SDD1Enable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0x5535:
|
|
RTCEnable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0xE320:
|
|
SGBEnable = true;
|
|
return;
|
|
break;
|
|
|
|
case 0xF320:
|
|
C4Enable = true;
|
|
return;
|
|
break;
|
|
|
|
case 0xF530:
|
|
ST18Enable = true;
|
|
CHIPBATT = true; //Check later if this should be removed
|
|
return;
|
|
break;
|
|
|
|
case 0xF53A:
|
|
SPC7110Enable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0xF630:
|
|
SETAEnable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
|
|
case 0xF93A:
|
|
SPC7110Enable = true;
|
|
RTCEnable = true;
|
|
CHIPBATT = true;
|
|
return;
|
|
break;
|
|
}
|
|
|
|
//BS Dump
|
|
if ((ROM[infoloc+CompanyOffset] == 0x33 || ROM[infoloc+CompanyOffset] == 0xFF) &&
|
|
(!ROM[infoloc+BSYearOffset] || (ROM[infoloc+BSYearOffset] & 131) == 128) &&
|
|
valid_normal_bank(ROM[infoloc+BSBankOffset]))
|
|
{
|
|
unsigned char m = ROM[infoloc+BSMonthOffset];
|
|
if (!m && !ROM[infoloc+BSDayOffset])
|
|
{
|
|
//BS Add-on cart
|
|
return;
|
|
}
|
|
if ((m == 0xFF && ROM[infoloc+BSDayOffset] == 0xFF) ||
|
|
(!(m & 0xF) && ((m >> 4) - 1 < 12)))
|
|
{
|
|
BSEnable = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//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);
|
|
}
|
|
|
|
static 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, curromspace);
|
|
}
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
static void rom_memcpy(unsigned char *dest, unsigned char *src, size_t len)
|
|
{
|
|
unsigned char *endrom = (unsigned char *)romdata+maxromspace;
|
|
while (len-- && (dest < endrom) && (src < endrom))
|
|
{
|
|
*dest++ = *src++;
|
|
}
|
|
}
|
|
|
|
//This will mirror up non power of two ROMs to powers of two
|
|
static unsigned int mirror_rom(unsigned char *start, unsigned int length)
|
|
{
|
|
unsigned int mask = 0x800000;
|
|
while (!(length & mask)) { mask >>= 1; }
|
|
|
|
length -= mask;
|
|
if (length)
|
|
{
|
|
start += mask;
|
|
length = mirror_rom(start, length);
|
|
|
|
while (length != mask)
|
|
{
|
|
rom_memcpy(start+length, start, length);
|
|
length += length;
|
|
}
|
|
}
|
|
|
|
return(length+mask);
|
|
}
|
|
|
|
//Misc functions
|
|
void MirrorROM(unsigned char *ROM)
|
|
{
|
|
unsigned int ROMSize, StartMirror = 0;
|
|
if (!SPC7110Enable)
|
|
{
|
|
curromspace = mirror_rom((unsigned char *)romdata, curromspace);
|
|
}
|
|
else if (curromspace == 0x300000)
|
|
{
|
|
memcpy((unsigned char *)romdata+curromspace, romdata, curromspace);
|
|
curromspace += curromspace;
|
|
}
|
|
|
|
if (curromspace > maxromspace)
|
|
{
|
|
curromspace = maxromspace;
|
|
}
|
|
NumofBanks = curromspace >> 15;
|
|
|
|
//This will mirror (now) full sized ROMs through the ROM buffer
|
|
ROMSize = curromspace;
|
|
while (ROMSize < maxromspace)
|
|
{
|
|
ROM[ROMSize++] = ROM[StartMirror++];
|
|
}
|
|
|
|
//If ROM was too small before, but now decent size with mirroring, adjust location
|
|
if (infoloc < Lo)
|
|
{
|
|
infoloc = Lo;
|
|
}
|
|
}
|
|
|
|
|
|
void SetupSramSize()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
if (BSEnable)
|
|
{
|
|
ramsize = 0;
|
|
}
|
|
else if (SFXEnable)
|
|
{
|
|
if (ROM[infoloc+CompanyOffset] == 0x33) //Extended header
|
|
{
|
|
ramsize = 8 << ((unsigned int)ROM[infoloc-3]);
|
|
}
|
|
else
|
|
{
|
|
ramsize = 256;
|
|
}
|
|
}
|
|
else if (SETAEnable)
|
|
{
|
|
ramsize = 32;
|
|
}
|
|
else if (!strncmp((char *)ROM, "BANDAI SFC-ADX", 14))
|
|
{ // For the Sufami Turbo
|
|
ramsize = 8 << ((unsigned int)ROM[0x100032]);
|
|
}
|
|
else
|
|
{
|
|
ramsize = ((ROM[infoloc+SRAMSizeOffset]) ? (8 << ((unsigned int)ROM[infoloc+SRAMSizeOffset])) : 0);
|
|
}
|
|
|
|
//Fix if some ROM goes nuts on size
|
|
if (ramsize > 1024)
|
|
{
|
|
ramsize = 1024;
|
|
}
|
|
|
|
//Convert from Kb to bytes;
|
|
ramsize *= 128;
|
|
ramsizeand = ramsize-1;
|
|
}
|
|
|
|
//File loading code
|
|
bool Header512;
|
|
|
|
char CSStatus[41], CSStatus2[41], CSStatus3[41], CSStatus4[41];
|
|
|
|
void DumpROMLoadInfo()
|
|
{
|
|
FILE *fp = 0;
|
|
|
|
if (RomInfo) //rominfo.txt info dumping enabled?
|
|
{
|
|
fp = fopen_dir(ZCfgPath, "rominfo.txt", "w");
|
|
if (!fp) { return; }
|
|
fputs("This is the info for the last game you ran.\n\nFile: ", fp);
|
|
fputs(ZCartName, 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);
|
|
fputs(CSStatus4, 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_dir(ZRomPath, filename, &stat_results);
|
|
|
|
if ((unsigned int)stat_results.st_size <= maxromspace+512-curromspace)
|
|
{
|
|
FILE *fp = 0;
|
|
fp = fopen_dir(ZRomPath, 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)
|
|
{
|
|
//Open file for size reading
|
|
FILE *fp = fopen_dir(ZRomPath, filename, "rb");
|
|
if (fp)
|
|
{
|
|
int fsize, gzsize;
|
|
gzFile GZipFile;
|
|
|
|
fseek(fp, -4, SEEK_END);
|
|
gzsize = fread4(fp);
|
|
fsize = ftell(fp);
|
|
rewind(fp);
|
|
|
|
//Open GZip file for decompression, use existing file handle
|
|
if ((GZipFile = gzdopen(fileno(fp), "rb")))
|
|
{
|
|
int len = gzdirect(GZipFile) ? fsize : gzsize;
|
|
if (len && ((unsigned int)len <= maxromspace+512) && (gzread(GZipFile, romdata, len) == len))
|
|
{
|
|
curromspace = len; //Success
|
|
}
|
|
gzclose(GZipFile);
|
|
}
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void loadZipFile(char *filename)
|
|
{
|
|
int err, fileSize;
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
bool multifile = false, NSS = false;
|
|
char *incrementer = 0;
|
|
|
|
unzFile zipfile = unzopen_dir(ZRomPath, 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 load_file_fs(char *path)
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
if (isextension(path, "jma"))
|
|
{
|
|
#ifdef NO_JMA
|
|
puts("This binary was built without JMA support.");
|
|
#else
|
|
load_jma_file_dir(ZRomPath, path);
|
|
#endif
|
|
}
|
|
if (isextension(path, "zip"))
|
|
{
|
|
loadZipFile(path);
|
|
}
|
|
if (isextension(path, "gz"))
|
|
{
|
|
loadGZipFile(path);
|
|
}
|
|
else
|
|
{
|
|
loadFile(path);
|
|
}
|
|
|
|
if ((curromspace & 0x7FFF) == 512)
|
|
{
|
|
memmove(ROM, ROM+512, addOnStart);
|
|
curromspace -= 512;
|
|
}
|
|
}
|
|
|
|
char *STCart2 = 0;
|
|
unsigned char *sram2;
|
|
extern unsigned char *sram;
|
|
|
|
void SplitSetup(char *basepath, char *basefile, unsigned int MirrorSystem)
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
curromspace = 0;
|
|
if (maxromspace < addOnStart+addOnSize) { return; }
|
|
memmove(ROM+addOnStart, ROM, addOnSize);
|
|
|
|
if (!*basepath)
|
|
{
|
|
load_file_fs(basefile);
|
|
}
|
|
else
|
|
{
|
|
load_file_fs(basepath);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void SplitSupport()
|
|
{
|
|
char *ROM = (char *)romdata;
|
|
SplittedROM = false;
|
|
|
|
//Same Game add on
|
|
if (curromspace == 0x80000 && ROM[Hi+CompanyOffset] == 0x33 &&
|
|
!ROM[Hi+BankOffset] && !ROM[Hi+BSMonthOffset] && !ROM[Hi+BSDayOffset])
|
|
{
|
|
addOnStart = 0x200000;
|
|
addOnSize = 0x80000;
|
|
SplitSetup(SGPath, "SAMEGAME.ZIP", 1);
|
|
}
|
|
|
|
//SD Gundam G-Next add on
|
|
if (curromspace == 0x80000 && ROM[Lo+CompanyOffset] == 0x33 &&
|
|
!ROM[Lo+BankOffset] && !ROM[Lo+BSMonthOffset] && !ROM[Lo+BSDayOffset] && !strncmp(ROM+Lo, "GNEXT", 5))
|
|
{
|
|
addOnStart = 0x400000;
|
|
addOnSize = 0x80000;
|
|
SplitSetup(GNextPath, "G-NEXT.ZIP", 2);
|
|
addOnStart = 0x200000; //Correct for checksum calc
|
|
}
|
|
|
|
//Sufami Turbo
|
|
if (!strncmp(ROM, "BANDAI SFC-ADX", 14))
|
|
{
|
|
if (!STCart2)
|
|
{
|
|
addOnStart = 0x100000;
|
|
addOnSize = curromspace;
|
|
SplitSetup(STPath, "STBIOS.ZIP", 3);
|
|
}
|
|
else if (maxromspace >= (curromspace<<2)+0x100000)
|
|
{
|
|
memcpy(ROM+curromspace+curromspace, ROM, curromspace);
|
|
memcpy(ROM+curromspace*3, ROM, curromspace);
|
|
curromspace = 0;
|
|
load_file_fs(STCart2);
|
|
memcpy(ROM+curromspace, ROM, curromspace);
|
|
SwapData(romdata, romdata+(curromspace>>1), curromspace>>1);
|
|
addOnSize = curromspace<<2;
|
|
addOnStart = 0x100000;
|
|
SplitSetup(STPath, "STBIOS.ZIP", 3);
|
|
addOnSize = (curromspace-addOnStart) >> 2; //Correct for checksum calc
|
|
sram2 = sram+65536;
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
void calculate_state_sizes(), InitRewindVars(), zst_init();
|
|
bool findZipIPS(char *, char *);
|
|
extern bool EMUPause;
|
|
extern unsigned char device1, device2;
|
|
unsigned char lorommapmode2, curromsize, snesinputdefault1, snesinputdefault2;
|
|
bool input1gp, input1mouse, input2gp, input2mouse, input2scope, input2just;
|
|
|
|
void loadROM()
|
|
{
|
|
bool isCompressed = false, isZip = false;
|
|
|
|
zst_init();
|
|
|
|
EMUPause = false;
|
|
curromspace = 0;
|
|
|
|
if (isextension(ZCartName, "jma"))
|
|
{
|
|
#ifdef NO_JMA
|
|
puts("This binary was built without JMA support.");
|
|
#else
|
|
isCompressed = true;
|
|
load_jma_file_dir(ZRomPath, ZCartName);
|
|
#endif
|
|
}
|
|
else if (isextension(ZCartName, "zip"))
|
|
{
|
|
isCompressed = true;
|
|
isZip = true;
|
|
loadZipFile(ZCartName);
|
|
}
|
|
else if (isextension(ZCartName, "gz"))
|
|
{
|
|
isCompressed = true;
|
|
loadGZipFile(ZCartName);
|
|
}
|
|
|
|
if (!isCompressed) { loadFile(ZCartName); }
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
device1 = 0;
|
|
device2 = 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] & 0xF0) //Port 1
|
|
{
|
|
case 0x00: //Gamepad
|
|
input1mouse = false;
|
|
break;
|
|
|
|
case 0x10: //Mouse port 1
|
|
device1 = 1;
|
|
input1gp = false;
|
|
break;
|
|
|
|
case 0x20: //Mouse or Gamepad port 1
|
|
device1 = 1;
|
|
break;
|
|
|
|
case 0x90: //Lasabirdie - not yet supported
|
|
input1gp = false;
|
|
input1mouse = false;
|
|
break;
|
|
}
|
|
|
|
switch (ROM[0x1ED] & 0x0F) //Port 1
|
|
{
|
|
case 0x00: //Gamepad
|
|
input2mouse = false;
|
|
input2scope = false;
|
|
input2just = false;
|
|
break;
|
|
|
|
case 0x01: //Mouse port 2
|
|
device2 = 1;
|
|
input2gp = false;
|
|
input2scope = false;
|
|
input2just = false;
|
|
break;
|
|
|
|
case 0x02: //Mouse or Gamepad port 2
|
|
device1 = 2;
|
|
input2just = false;
|
|
input2scope = false;
|
|
break;
|
|
|
|
case 0x03: //Super Scope port 2
|
|
device2 = 2;
|
|
input2gp = false;
|
|
input2mouse = false;
|
|
input2just = false;
|
|
break;
|
|
|
|
case 0x04: //Super Scope or Gamepad port 2
|
|
device2 = 2;
|
|
input2mouse = false;
|
|
input2just = false;
|
|
break;
|
|
|
|
case 0x05: //Justifier (Lethal Enforcer gun) port 2
|
|
device2 = 3;
|
|
input2mouse = false;
|
|
input2scope = false;
|
|
break;
|
|
|
|
case 0x06: //Multitap port 2
|
|
input2gp = false;
|
|
input2mouse = false;
|
|
input2just = false;
|
|
input2scope = false;
|
|
break;
|
|
|
|
case 0x07: //Mouse or Gamepad port 1, Mouse, Super Scope, or Gamepad port 2
|
|
input2just = false;
|
|
break;
|
|
|
|
case 0x08: //Mouse or Multitap port 2
|
|
device2 = 1;
|
|
input2just = false;
|
|
input2scope = false;
|
|
break;
|
|
|
|
case 0x09: //Lasabirdie - not yet supported
|
|
input2gp = false;
|
|
input2mouse = false;
|
|
input2just = false;
|
|
input2scope = false;
|
|
break;
|
|
|
|
case 0x0A: //Barcode Battler - not yet supported
|
|
input2gp = false;
|
|
input2mouse = false;
|
|
input2just = false;
|
|
input2scope = false;
|
|
break;
|
|
}
|
|
}
|
|
curromspace -= 512;
|
|
memmove((unsigned char *)romdata, ((unsigned char *)romdata)+512, curromspace);
|
|
}
|
|
|
|
snesinputdefault1 = device1;
|
|
snesinputdefault2 = device2;
|
|
|
|
SplitSupport();
|
|
|
|
if (isZip)
|
|
{
|
|
int i;
|
|
char ext[4];
|
|
|
|
strcpy(ext, "ips");
|
|
for (i = 0; findZipIPS(ZCartName, ext); i++)
|
|
{
|
|
if (i > 9) { break; }
|
|
ext[2] = i+'0';
|
|
}
|
|
}
|
|
|
|
if (curromspace)
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
NumofBytes = curromspace;
|
|
NumofBanks = curromspace >> 15;
|
|
BankCheck();
|
|
curromsize = ROM[infoloc+ROMSizeOffset];
|
|
chip_detect();
|
|
SetupSramSize();
|
|
calculate_state_sizes();
|
|
InitRewindVars();
|
|
}
|
|
}
|
|
|
|
//Memory Setup functions
|
|
extern unsigned char wramdataa[65536];
|
|
extern unsigned char ram7fa[65536];
|
|
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;
|
|
#ifdef OLD_DEBUGGER
|
|
extern unsigned char *debugbuf;
|
|
#endif
|
|
extern unsigned char *sram;
|
|
|
|
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, 65536);
|
|
clearSPCRAM();
|
|
}
|
|
|
|
void clearmem()
|
|
{
|
|
int i;
|
|
|
|
memset(vidbuffer, 0, 131072);
|
|
memset(wramdataa, 0, 65536);
|
|
memset(ram7fa, 0, 65536);
|
|
memset(vram, 0, 65536);
|
|
memset(sram, 0, 65536*2);
|
|
#ifdef OLD_DEBUGGER
|
|
memset(debugbuf, 0, 80000);
|
|
#endif
|
|
memset(regptra, 0, 49152);
|
|
memset(regptwa, 0, 49152);
|
|
memset(vcache2b, 0, 262144+256);
|
|
memset(vcache4b, 0, 131072+256);
|
|
memset(vcache8b, 0, 65536+256);
|
|
memset(vidmemch2, 0, 4096);
|
|
memset(vidmemch4, 0, 4096);
|
|
memset(vidmemch8, 0, 4096);
|
|
memset(pal16b, 0, 1024);
|
|
memset(pal16bcl, 0, 1024);
|
|
memset(pal16bclha, 0, 1024);
|
|
for (i=0 ; i<1024 ; i+=4)
|
|
{
|
|
memset(pal16bxcl+i, 255, 2);
|
|
memset(pal16bxcl+i+2, 0, 2);
|
|
}
|
|
memset(romdata, 0xFF, maxromspace+32768);
|
|
clearmem2();
|
|
}
|
|
|
|
extern unsigned char BRRBuffer[32];
|
|
extern unsigned char echoon0;
|
|
extern unsigned int PHdspsave;
|
|
extern unsigned int PHdspsave2;
|
|
unsigned char echobuf[90000];
|
|
extern unsigned char *spcBuffera;
|
|
extern unsigned char DSPMem[256];
|
|
|
|
void clearvidsound()
|
|
{
|
|
memset(vram, 0, 65536);
|
|
memset(vidmemch2, 0, 4096);
|
|
memset(vidmemch4, 0, 4096);
|
|
memset(vidmemch8, 0, 4096);
|
|
memset(BRRBuffer, 0, PHdspsave);
|
|
memset(&echoon0, 0, PHdspsave2);
|
|
memset(echobuf, 0, 90000);
|
|
memset(spcBuffera, 0, 65536*4+4096);
|
|
memset(DSPMem, 0, 256);
|
|
}
|
|
|
|
/*
|
|
|
|
--------------Caution Hack City--------------
|
|
|
|
Would be nice to trash this section in the future
|
|
*/
|
|
|
|
extern unsigned char ENVDisable, cycpb268, cycpb358, cycpbl2, cycpblt2, cycpbl;
|
|
extern unsigned char cycpblt, opexec268, opexec358, opexec268b, opexec358b;
|
|
extern unsigned char opexec268cph, opexec358cph, opexec268cphb, opexec358cphb;
|
|
bool HacksDisable;
|
|
|
|
void headerhack()
|
|
{
|
|
char *RomData = (char *)romdata;
|
|
ENVDisable = 0;
|
|
|
|
if (curromspace < Lo || HacksDisable) { return; }
|
|
|
|
//Super Famista (J)
|
|
//Shows black screen after one screen.
|
|
if (!strncmp((RomData+Lo),"\xbd\xb0\xca\xdf\xb0\xcc\xa7\xd0\xbd\xc0 ", 12))
|
|
{
|
|
RomData[0x2762F] = 0xEA;
|
|
RomData[0x27630] = 0xEA;
|
|
}
|
|
|
|
//Super Famista 2 (J)
|
|
//Shows black screen after loading the ROM.
|
|
if (!strncmp((RomData+Lo),"\xbd\xb0\xca\xdf\xb0\xcc\xa7\xd0\xbd\xc0 2", 12))
|
|
{
|
|
//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;
|
|
}
|
|
|
|
//Deae Tonosama Appare Ichiban (J)
|
|
//Shows some screen and hangs there.
|
|
if (!strncmp((RomData+Lo),"\xc3\xde\xb1\xb4\xc4\xc9\xbb\xcf", 8))
|
|
{
|
|
RomData[0x17837C] = 0xEA;
|
|
RomData[0x17837D] = 0xEA;
|
|
}
|
|
|
|
//Human Grand Prix III - F1 Triple Battle (J)
|
|
//Shows black screen after loading the ROM.
|
|
if (!strncmp((RomData+Lo),"HUMAN GRANDPRIX 3 ", 20))
|
|
{
|
|
cycpb268 = 135;
|
|
cycpb358 = 157;
|
|
cycpbl2 = 125;
|
|
cycpblt2 = 125;
|
|
cycpbl = 125;
|
|
cycpblt = 125;
|
|
}
|
|
|
|
//Accele Brid (J)
|
|
//Hangs after some time in the first level.
|
|
if (!strncmp((RomData+Lo),"ACCELEBRID ", 12))
|
|
{
|
|
RomData[0x34DA2] = 0;
|
|
RomData[0x34DA3] = 0;
|
|
}
|
|
|
|
//Home Alone (J/E/U)
|
|
//Hangs after starting a new game.
|
|
if (!strncmp((RomData+Lo),"HOME ALONE ", 12))
|
|
{
|
|
RomData[0x666B] = 0xEE;
|
|
RomData[0x666C] = 0xBC;
|
|
}
|
|
|
|
//Emerald Dragon (J)
|
|
//Hangs while drawing the logo after loading the ROM.
|
|
if (!strncmp((RomData+Hi),"EMERALD DRAG", 12))
|
|
{
|
|
ENVDisable = true;
|
|
}
|
|
|
|
//Rendering Ranger R2
|
|
//Shows black screen after loading the ROM.
|
|
if (!strncmp((RomData+Lo),"REND", 4))
|
|
{
|
|
cycpb268 = 157;
|
|
cycpb358 = 157;
|
|
cycpbl2 = 157;
|
|
cycpblt2 = 157;
|
|
cycpbl = 157;
|
|
cycpblt = 157;
|
|
}
|
|
|
|
//Tuff E Nuff (U/E), Dead Dance (J),
|
|
//Cyber Knight II - Tikyu Teikoku no Yabou (J)
|
|
//Shows black screen after loading the ROM. (Tuff E Nuff, Dead Dance)
|
|
//Shows black screen after two screens. (Cyber Knight II)
|
|
if (!strncmp((RomData+Lo),"CYBER KNIGHT 2 ", 16) ||
|
|
!strncmp((RomData+Lo),"DEAD", 4) ||
|
|
!strncmp((RomData+Lo),"TUFF", 4))
|
|
{
|
|
cycpb268 = 75;
|
|
cycpb358 = 77;
|
|
cycpbl2 = 75;
|
|
cycpblt2 = 75;
|
|
cycpbl = 75;
|
|
cycpblt = 75;
|
|
}
|
|
|
|
//Addams Family Values (U/E)
|
|
//Restarts or shows a black screen after starting a new game.
|
|
if (!strncmp((RomData+Lo), "ADDAMS FAMILY VALUES", 20))
|
|
{
|
|
opexec268 = 120;
|
|
opexec358 = 100;
|
|
}
|
|
|
|
//Front Mission
|
|
//Flickering worldmap and statusbar.
|
|
if (!strncmp((RomData+Hi), "\xcc\xdb\xdd\xc4\xd0\xaf\xbc\xae", 8) ||
|
|
!strncmp((RomData+Hi), "FRONT MI", 8))
|
|
{
|
|
opexec268 = 226;
|
|
opexec358 = 226;
|
|
opexec268cph = 80;
|
|
opexec358cph = 80;
|
|
}
|
|
}
|
|
|
|
void Setper2exec()
|
|
{
|
|
if (per2exec != 100)
|
|
{ // Decrease standard % of execution by 5% to replace branch and 16bit
|
|
// cycle deductions
|
|
opexec268b = (unsigned char)((opexec268 * 95 * per2exec) / 10000);
|
|
opexec358b = (unsigned char)((opexec358 * 87 * per2exec) / 10000); // 82
|
|
opexec268cphb = (unsigned char)((opexec268cph * 95 * per2exec) / 10000);
|
|
opexec358cphb = (unsigned char)((opexec358cph * 87 * per2exec) / 10000); // 82
|
|
}
|
|
}
|
|
|
|
extern unsigned int SPC7110TempPosition, SPC7110TempLength, SPCDecmPtr;
|
|
static char *SPC7110path, SPC7110fname[8+1+6+4+1]; //dir / 12345 .bin
|
|
char *SPC7110filep;
|
|
extern unsigned char *SPC7110IndexPtr, *SPC7110PackPtr;
|
|
unsigned int SPC7110IndexSize;
|
|
|
|
static void SPC7PathSetup(char *PathVar, const char *Default)
|
|
{
|
|
if (*PathVar)
|
|
{
|
|
SPC7110path = PathVar;
|
|
strcatslash(SPC7110path);
|
|
*SPC7110fname = 0;
|
|
}
|
|
else
|
|
{
|
|
SPC7110path = ZSramPath;
|
|
strcpy(SPC7110fname, Default);
|
|
strcatslash(SPC7110fname);
|
|
}
|
|
}
|
|
|
|
extern unsigned int MsgCount, MessageOn;
|
|
extern char *Msgptr;
|
|
unsigned int SPC7110Entries, CRC32;
|
|
|
|
void SPC7PackIndexLoad()
|
|
{
|
|
char *ROM = (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))
|
|
{ SPC7PathSetup(FEOEZPath, "FEOEZSP7"); }
|
|
else if (!strncmp(ROM+infoloc, "JUMP TENGAIMAKYO ZERO", 21))
|
|
{ SPC7PathSetup(SJNSPath, "SJNS-SP7"); }
|
|
else if (!strncmp(ROM+infoloc, "MOMOTETSU HAPPY ", 21))
|
|
{ SPC7PathSetup(MDHPath, "MDH-SP7"); }
|
|
else if (!strncmp(ROM+infoloc, "SUPER POWER LEAG 4 ", 21))
|
|
{ SPC7PathSetup(SPL4Path, "SPL4-SP7"); }
|
|
else
|
|
{
|
|
Msgptr = "DECOMPRESSED PACK NOT FOUND";
|
|
MessageOn = 360;
|
|
return;
|
|
}
|
|
|
|
//Set the pointer to after the slash - needed for the case converters
|
|
SPC7110filep = SPC7110fname+strlen(SPC7110fname);
|
|
|
|
//Index file;
|
|
strcat(SPC7110fname, "index.bin");
|
|
|
|
//Load the index
|
|
fp = fopen_dir(SPC7110path, SPC7110fname, "rb");
|
|
if (fp)
|
|
{
|
|
SPC7110IndexSize = fread(SPC7110IndexPtr, 1, 12*4608, fp);
|
|
fclose(fp);
|
|
|
|
//Get file pointer ready for individual pack files
|
|
strcpy(SPC7110filep, "123456.bin"); //Extension Lower Case
|
|
}
|
|
|
|
SPC7110Entries = 0;
|
|
|
|
if (!SPC7110IndexSize)
|
|
{
|
|
Msgptr = "DECOMPRESSED PACK NOT FOUND";
|
|
MessageOn = 360;
|
|
}
|
|
}
|
|
|
|
void SPC7_Convert_Upper()
|
|
{
|
|
char *i = SPC7110filep;
|
|
while (*i)
|
|
{
|
|
*i = toupper(*i); //To make extension Upper case
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void SPC7_Convert_Lower()
|
|
{
|
|
char *i = SPC7110filep;
|
|
while (*i)
|
|
{
|
|
*i = tolower(*i); //To make everything Lower case
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void SPC7_Data_Load()
|
|
{
|
|
FILE *fp = fopen_dir(SPC7110path, SPC7110fname, "rb");
|
|
if (!fp)
|
|
{
|
|
SPC7_Convert_Upper();
|
|
fp = fopen_dir(SPC7110path, SPC7110fname, "rb");
|
|
|
|
if (!fp)
|
|
{
|
|
SPC7_Convert_Lower();
|
|
fp = fopen_dir(SPC7110path, SPC7110fname, "rb");
|
|
}
|
|
}
|
|
|
|
if (fp)
|
|
{
|
|
fseek(fp, SPC7110TempPosition, SEEK_SET);
|
|
fread(SPC7110PackPtr, 1, SPC7110TempLength, fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
extern unsigned char IPSPatched;
|
|
|
|
unsigned int showinfogui()
|
|
{
|
|
unsigned int i;
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
strcpy(CSStatus, " TYPE: ");
|
|
strcpy(CSStatus2, "INTERLEAVED: CHKSUM: ");
|
|
strcpy(CSStatus3, "VIDEO: BANK: CRC32: ");
|
|
strcpy(CSStatus4, " ");
|
|
|
|
for (i=0 ; i<21 ; i++)
|
|
{ CSStatus[i] = (ROM[infoloc + i]) ? ROM[infoloc + i] : 32; }
|
|
|
|
if (Interleaved)
|
|
{
|
|
memcpy(CSStatus2+12, "Yes ", 4);
|
|
memcpy(CSStatus4+10, "PLEASE DEINTERLEAVE ROM", 23);
|
|
}
|
|
else
|
|
{
|
|
memcpy(CSStatus2+12, "No ", 4);
|
|
memset(CSStatus4+10, ' ', 23);
|
|
}
|
|
|
|
memcpy(CSStatus2+20, (IPSPatched) ? "IPS ":" ", 4);
|
|
memcpy(CSStatus3+6, (ROM[infoloc + 25] < 2 || ROM[infoloc + 25] > 12) ? "NTSC":"PAL ", 4);
|
|
|
|
if (infoloc == EHi) { memcpy(CSStatus3+19, "EHi ", 4); }
|
|
else { memcpy(CSStatus3+19, (romtype == 2) ? "Hi ":"Lo ", 4); }
|
|
|
|
memcpy(CSStatus+31, "NORMAL ", 9);
|
|
if (SA1Enable) { memcpy(CSStatus+31, "SA-1 ", 9); }
|
|
if (RTCEnable) { memcpy(CSStatus+31, "RTC ", 9); }
|
|
if (SPC7110Enable) { memcpy(CSStatus+31, "SPC7110 ", 9); }
|
|
if (SFXEnable) { memcpy(CSStatus+31, "SUPER FX ", 9); }
|
|
if (C4Enable) { memcpy(CSStatus+31, "C4 ", 9); }
|
|
if (DSP1Enable) { memcpy(CSStatus+31, "DSP-1 ", 9); }
|
|
if (DSP2Enable) { memcpy(CSStatus+31, "DSP-2 ", 9); }
|
|
if (DSP3Enable) { memcpy(CSStatus+31, "DSP-3 ", 9); }
|
|
if (DSP4Enable) { memcpy(CSStatus+31, "DSP-4 ", 9); }
|
|
if (SDD1Enable) { memcpy(CSStatus+31, "S-DD1 ", 9); }
|
|
if (OBCEnable) { memcpy(CSStatus+31, "OBC1 ", 9); }
|
|
if (SETAEnable) { memcpy(CSStatus+31, "SETA DSP ", 9); }
|
|
if (ST18Enable) { memcpy(CSStatus+31, "ST018 ", 9); }
|
|
if (SGBEnable) { memcpy(CSStatus+31, "SGB ", 9); }
|
|
if (BSEnable) { memcpy(CSStatus+31, "BROADCAST", 9);
|
|
// dummy out date so CRC32 matches
|
|
ROM[infoloc+BSMonthOffset] = 0x42;
|
|
ROM[infoloc+BSDayOffset] = 0x00; }
|
|
// 42 is the answer, and the uCONSRT standard
|
|
|
|
// calculate CRC32 for the whole ROM, or Add-on ROM only
|
|
CRC32 = (SplittedROM) ? crc32(0, ROM+addOnStart, addOnSize) : crc32(0, ROM, NumofBytes);
|
|
// place CRC32 on line
|
|
sprintf(CSStatus3+32, "%08X", CRC32);
|
|
|
|
i = (SplittedROM) ? infoloc + 0x1E + addOnStart: infoloc + 0x1E;
|
|
|
|
if ((ROM[i] == (Checksumvalue & 0xFF)) && (ROM[i+1] == (Checksumvalue >> 8)))
|
|
{ memcpy(CSStatus2+36, "OK ", 4); }
|
|
else
|
|
{
|
|
memcpy(CSStatus2+36, "FAIL", 4);
|
|
if (!IPSPatched) { memcpy(CSStatus4, "BAD ROM ",8); }
|
|
else { memset(CSStatus4, ' ', 7); }
|
|
}
|
|
|
|
DumpROMLoadInfo();
|
|
|
|
MessageOn = 300;
|
|
Msgptr = CSStatus;
|
|
return (MsgCount);
|
|
}
|
|
|
|
extern unsigned int nmiprevaddrl, nmiprevaddrh, nmirept, nmiprevline, nmistatus;
|
|
extern unsigned char spcnumread, yesoutofmemory;
|
|
extern unsigned char NextLineCache, sramsavedis, sndrot, regsbackup[3019];
|
|
extern unsigned int Voice0Freq, Voice1Freq, Voice2Freq, Voice3Freq;
|
|
extern unsigned int Voice4Freq, Voice5Freq, Voice6Freq, Voice7Freq;
|
|
extern unsigned int dspPAdj;
|
|
extern unsigned short Voice0Pitch, Voice1Pitch, Voice2Pitch, Voice3Pitch;
|
|
extern unsigned short Voice4Pitch, Voice5Pitch, Voice6Pitch, Voice7Pitch;
|
|
void outofmemfix(), GUIDoReset();
|
|
|
|
void initpitch()
|
|
{
|
|
Voice0Pitch = DSPMem[2+0*0x10];
|
|
Voice0Freq = ((((Voice0Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice1Pitch = DSPMem[2+1*0x10];
|
|
Voice1Freq = ((((Voice1Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice2Pitch = DSPMem[2+2*0x10];
|
|
Voice2Freq = ((((Voice2Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice3Pitch = DSPMem[2+3*0x10];
|
|
Voice3Freq = ((((Voice3Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice4Pitch = DSPMem[2+4*0x10];
|
|
Voice4Freq = ((((Voice4Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice5Pitch = DSPMem[2+5*0x10];
|
|
Voice5Freq = ((((Voice5Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice6Pitch = DSPMem[2+6*0x10];
|
|
Voice6Freq = ((((Voice6Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
Voice7Pitch = DSPMem[2+7*0x10];
|
|
Voice7Freq = ((((Voice7Pitch & 0x3FFF) * dspPAdj) >> 8) & 0xFFFFFFFF);
|
|
}
|
|
|
|
extern unsigned int SfxR1, SfxR2, SetaCmdEnable, SfxSFR, SfxSCMR;
|
|
extern unsigned char disablespcclr, *sfxramdata, SramExists;
|
|
extern unsigned char *setaramdata, *wramdata, *SA1RAMArea, cbitmode;
|
|
extern unsigned char ForcePal, ForceROMTiming, romispal, MovieWaiting, DSP1Type;
|
|
extern unsigned short totlines;
|
|
void SetAddressingModes(), GenerateBank0Table();
|
|
void SetAddressingModesSA1(), GenerateBank0TableSA1();
|
|
void InitDSP(), InitDSP2(), InitDSP3(), InitDSP4(), InitOBC1(), InitFxTables();
|
|
void initregr(), initregw();
|
|
|
|
#ifdef __MSDOS__
|
|
void dosmakepal();
|
|
#endif
|
|
|
|
void CheckROMType()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
if (!MovieWaiting)
|
|
{
|
|
MirrorROM((unsigned char *)romdata);
|
|
CalcChecksum();
|
|
}
|
|
|
|
lorommapmode2 = 0;
|
|
if (!strncmp((char *)ROM+0x207FC0, "DERBY STALLION 96", 17) ||
|
|
!strncmp((char *)ROM+Lo, "SOUND NOVEL-TCOOL", 17))
|
|
{ lorommapmode2 = 1; }
|
|
|
|
// Setup memmapping
|
|
SetAddressingModes();
|
|
GenerateBank0Table();
|
|
|
|
disablespcclr = (memcmp(ROM+Hi, "BS Z", 4)) ? 0 : 1;
|
|
|
|
if (!strncmp((char *)ROM, "BANDAI SFC-ADX", 14))
|
|
{
|
|
map_mem(0x60, &stbanka, 0x08);
|
|
if (STCart2)
|
|
{
|
|
map_mem(0x70, &stbankb, 0x08);
|
|
}
|
|
}
|
|
else if (romtype == 1) // LoROM SRAM mapping
|
|
{ // banks 70 - 77
|
|
map_mem(0x70, &srambank, 0x08);
|
|
|
|
if (!BSEnable)
|
|
{ // banks 78 - 7D (not for BS)
|
|
map_mem(0x78, &srambank, 0x06);
|
|
}
|
|
|
|
if (!SDD1Enable)
|
|
{ // banks F0 - FF (not for S-DD1)
|
|
map_mem(0xF0, &srambank, 0x10);
|
|
}
|
|
}
|
|
|
|
// Setup DSP-X stuff
|
|
DSP1Type = 0;
|
|
|
|
if (DSP1Enable)
|
|
{
|
|
InitDSP();
|
|
|
|
if (romtype == 1)
|
|
{
|
|
DSP1Type = 1;
|
|
map_mem(0x30, &dsp1bank, 0x10);
|
|
map_mem(0xB0, &dsp1bank, 0x10);
|
|
map_mem(0xE0, &dsp1bank, 0x10);
|
|
}
|
|
else
|
|
{
|
|
DSP1Type = 2;
|
|
}
|
|
}
|
|
|
|
if (DSP2Enable)
|
|
{
|
|
asm_call(InitDSP2);
|
|
map_mem(0x3F, &dsp2bank, 1);
|
|
}
|
|
|
|
if (DSP3Enable)
|
|
{
|
|
InitDSP3();
|
|
|
|
// DSP-3 mapping, banks 20 - 3F
|
|
map_mem(0x20, &dsp3bank, 0x20);
|
|
}
|
|
|
|
if (DSP4Enable)
|
|
{
|
|
InitDSP4();
|
|
|
|
// DSP-4 mapping, banks 30 - 3F
|
|
map_mem(0x30, &dsp4bank, 0x10);
|
|
}
|
|
|
|
if (OBCEnable)
|
|
{
|
|
InitOBC1();
|
|
|
|
map_mem(0x00, &obc1bank, 0x40);
|
|
map_mem(0x80, &obc1bank, 0x40);
|
|
}
|
|
|
|
if (C4Enable)
|
|
{
|
|
map_mem(0x00, &c4bank, 0x40);
|
|
map_mem(0x80, &c4bank, 0x40);
|
|
}
|
|
|
|
if (SFXEnable)
|
|
{
|
|
// Setup SuperFX stuff
|
|
if (maxromspace >= 0x600000)
|
|
{
|
|
//SuperFX mapping, banks 70 - 73
|
|
map_mem(0x70, &sfxbank, 1);
|
|
map_mem(0x71, &sfxbankb, 1);
|
|
map_mem(0x72, &sfxbankc, 1);
|
|
map_mem(0x73, &sfxbankd, 1);
|
|
|
|
//SRAM mapping, banks 78 - 79
|
|
map_mem(0x78, &sramsbank, 2);
|
|
|
|
SfxR1 = 0;
|
|
SfxR2 = 0;
|
|
memset(sfxramdata, 0, 262144); // clear 256kB SFX ram
|
|
|
|
if (SramExists)
|
|
{
|
|
memcpy(sfxramdata, sram, 65536); // proper SFX sram area
|
|
}
|
|
|
|
asm_call(InitFxTables);
|
|
}
|
|
else
|
|
{
|
|
yesoutofmemory = 1;
|
|
}
|
|
}
|
|
|
|
if (SETAEnable)
|
|
{
|
|
if (strncmp((char *)ROM+Lo, "2DAN MORITA SHOUGI", 18))
|
|
{
|
|
//Setup Seta 10 stuff
|
|
|
|
//Really banks 68h-6Fh:0000-7FFF are all mapped the same by the chip but
|
|
//F1 ROC II only uses bank 68h
|
|
map_mem(0x68, &setabank, 1);
|
|
|
|
//Control register (and some status?) is in banks 60h-67h:0000-3FFF
|
|
map_mem(0x60, &setabanka, 1);
|
|
|
|
SetaCmdEnable = 0x00000080; // 60:0000
|
|
}
|
|
else
|
|
{
|
|
void ST011_Reset();
|
|
ST011_Reset();
|
|
map_mem(0x68, &seta11bank, 1);
|
|
map_mem(0x60, &seta11banka, 1);
|
|
}
|
|
memset(setaramdata, 0, 4096); // clear 4kB SETA ram
|
|
|
|
// proper SETA sram area
|
|
if (SramExists)
|
|
{
|
|
memcpy(setaramdata, sram, 4096);
|
|
}
|
|
}
|
|
|
|
// General stuff all mixed together [... wouldn't it be cool to clean that]
|
|
SfxSFR = 0;
|
|
SfxSCMR &= 0xFFFFFF00;
|
|
asm_call(initregr);
|
|
asm_call(initregw);
|
|
|
|
if (SA1Enable)
|
|
{
|
|
SA1RAMArea = ROM + 4096*1024;
|
|
|
|
GenerateBank0TableSA1();
|
|
SetAddressingModesSA1();
|
|
|
|
if (CHIPBATT) // proper SA-1 sram area
|
|
{
|
|
memset(SA1RAMArea, 0, 131072);
|
|
if (SramExists) { memcpy(SA1RAMArea, sram, 131072); }
|
|
}
|
|
}
|
|
|
|
wramdata = wramdataa;
|
|
}
|
|
|
|
extern unsigned short copv, brkv, abortv, nmiv, nmiv2, irqv, irqv2, resetv;
|
|
extern unsigned short copv8, brkv8, abortv8, nmiv8, irqv8;
|
|
|
|
void SetIRQVectors()
|
|
{ // get vectors (NMI & reset)
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
if (!memcmp(ROM+infoloc+36+24, "\0xFF\0xFF", 2)) // if reset error
|
|
{
|
|
memcpy(ROM+infoloc+36+6, "\0x9C\0xFF", 2);
|
|
memcpy(ROM+infoloc+36+24, "\0x80\0xFF", 2);
|
|
}
|
|
|
|
memcpy(&copv, ROM+infoloc+0x24, 2);
|
|
memcpy(&brkv, ROM+infoloc+0x26, 2);
|
|
memcpy(&abortv, ROM+infoloc+0x28, 2);
|
|
memcpy(&nmiv, ROM+infoloc+0x2A, 2);
|
|
memcpy(&nmiv2, ROM+infoloc+0x2A, 2);
|
|
memcpy(&irqv, ROM+infoloc+0x2E, 2);
|
|
memcpy(&irqv2, ROM+infoloc+0x2E, 2);
|
|
|
|
// 8-bit and reset
|
|
memcpy(&copv8, ROM+infoloc+0x34, 2);
|
|
memcpy(&abortv8, ROM+infoloc+0x38, 2);
|
|
memcpy(&nmiv8, ROM+infoloc+0x3A, 2);
|
|
memcpy(&resetv, ROM+infoloc+0x3C, 2);
|
|
memcpy(&brkv8, ROM+infoloc+0x3E, 2);
|
|
memcpy(&irqv8, ROM+infoloc+0x3E, 2);
|
|
|
|
if (yesoutofmemory) // failed ?
|
|
{
|
|
resetv = 0x8000;
|
|
memcpy(ROM+0x0000, "\0x80\0xFE", 2);
|
|
memcpy(ROM+0x8000, "\0x80\0xFE", 2);
|
|
}
|
|
}
|
|
|
|
void SetupROM()
|
|
{
|
|
static bool CLforce = false;
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
CheckROMType();
|
|
SetIRQVectors();
|
|
|
|
#ifdef __MSDOS__
|
|
if (!cbitmode) // 8-bit mode uses a palette
|
|
{
|
|
asm_call(dosmakepal);
|
|
}
|
|
#endif
|
|
|
|
/* get timing (pal/ntsc)
|
|
ForceROMTiming is from the GUI.
|
|
ForcePal 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 (ForcePal && !CLforce) { CLforce = true; }
|
|
else { ForcePal = ForceROMTiming; }
|
|
|
|
switch (ForcePal)
|
|
{
|
|
case 1:
|
|
romispal = 0;
|
|
break;
|
|
case 2:
|
|
romispal = (!BSEnable);
|
|
break;
|
|
default:
|
|
romispal = ((!BSEnable) && (ROM[infoloc+CountryOffset] > 1) && (ROM[infoloc+CountryOffset] < 0xD));
|
|
}
|
|
|
|
#ifdef __UNIXSDL__
|
|
InitSampleControl();
|
|
#endif
|
|
|
|
if (romispal)
|
|
{
|
|
totlines = 314;
|
|
MsgCount = 100;
|
|
}
|
|
else
|
|
{
|
|
totlines = 263;
|
|
MsgCount = 120;
|
|
}
|
|
}
|
|
|
|
extern int NumComboLocl;
|
|
extern unsigned char ComboHeader[23];
|
|
extern char CombinDataLocl[3300];
|
|
extern bool romloadskip;
|
|
|
|
void SaveCombFile()
|
|
{
|
|
if (!romloadskip)
|
|
{
|
|
FILE *fp;
|
|
|
|
setextension(ZSaveName, "cmb");
|
|
|
|
if (NumComboLocl)
|
|
{
|
|
ComboHeader[22] = NumComboLocl;
|
|
|
|
if ((fp = fopen_dir(ZSramPath, ZSaveName, "wb")))
|
|
{
|
|
fwrite(ComboHeader, 1, 23, fp);
|
|
fwrite(CombinDataLocl, 1, NumComboLocl*66, fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenCombFile()
|
|
{
|
|
FILE *fp;
|
|
|
|
setextension(ZSaveName, "cmb");
|
|
NumComboLocl = 0;
|
|
|
|
if ((fp = fopen_dir(ZSramPath, ZSaveName, "rb")))
|
|
{
|
|
fread(ComboHeader, 1, 23, fp);
|
|
NumComboLocl = ComboHeader[22];
|
|
|
|
if (NumComboLocl)
|
|
{
|
|
fread(CombinDataLocl, 1, NumComboLocl*66, fp);
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
unsigned char SFXCounter, SfxAC, ForceNewGfxOff;
|
|
|
|
void preparesfx()
|
|
{
|
|
char *ROM = (char *)romdata, i;
|
|
|
|
SFXCounter = SfxAC = 0;
|
|
|
|
if (!strncmp(ROM+Lo, "FX S", 4) ||
|
|
!strncmp(ROM+Lo, "DIRT", 4))
|
|
{
|
|
SFXCounter = 1;
|
|
}
|
|
else if (!strncmp(ROM+Lo, "Stun", 4))
|
|
{
|
|
ForceNewGfxOff=1;
|
|
}
|
|
|
|
for (i=63;i>=0;i--)
|
|
{
|
|
memcpy(romdata+i*0x4000 ,romdata+i*0x2000,0x8000);
|
|
memcpy(romdata+i*0x4000+0x2000,romdata+i*0x2000,0x8000);
|
|
}
|
|
}
|
|
|
|
void map_set(void **dest, unsigned char *src, size_t count, size_t step)
|
|
{
|
|
while (count--)
|
|
{
|
|
*dest = src;
|
|
dest++;
|
|
src += step;
|
|
}
|
|
}
|
|
|
|
extern unsigned char MultiType;
|
|
extern void *snesmmap[256];
|
|
extern void *snesmap2[256];
|
|
|
|
unsigned int cromptradd;
|
|
extern unsigned char MultiTap;
|
|
extern unsigned int SfxR0, SfxR1, SfxR2, SfxR3, SfxR4, SfxR5, SfxR6, SfxR7,
|
|
SfxR8, SfxR9, SfxR10, SfxR11, SfxR12, SfxR13, SfxR14, SfxR15;
|
|
extern void *ram7f;
|
|
|
|
void map_lorom()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
int x;
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-7F (80h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap,ROM-0x8000,0x80,0x8000);
|
|
|
|
// set banks 80-FF (80h x 32KB ROM banks @ 8000h)
|
|
if (lorommapmode2)
|
|
{
|
|
map_set(snesmmap+0x80,ROM+0x1F8000,0x20,0x8000);
|
|
map_set(snesmmap+0xA0,ROM+0x0F8000,0x60,0x8000);
|
|
}
|
|
else
|
|
{
|
|
map_set(snesmmap+0x80,ROM-0x8000,0x80,0x8000);
|
|
}
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmap2+0x40,ROM+0x200000,0x40,0x8000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmap2+0xC0,ROM+0x200000,0x40,0x8000);
|
|
|
|
// set banks 70-77 (07h x SRAM)
|
|
for (x = 0x70; x <= 0x77; x++) { snesmap2[x] = sram; }
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void map_hirom()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
int x;
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-3F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap,ROM,0x40,0x10000);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0x80,ROM,0x40,0x10000);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set banks 70-77 (07h x SRAM)
|
|
for (x = 0x70; x <= 0x77; x++) { snesmap2[x] = sram; }
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void map_ehirom()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
int x;
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-3F (40h x 32KB ROM banks @ 10000h)
|
|
map_set(snesmmap,ROM+0x400000,0x20,0x10000);
|
|
map_set(snesmmap+0x20,ROM+0x400000,0x20,0x10000);
|
|
|
|
// set banks 40-7F (40h x 32KB ROM banks @ 10000h)
|
|
map_set(snesmmap+0x40,ROM+0x400000,0x20,0x10000);
|
|
map_set(snesmmap+0x60,ROM+0x400000,0x20,0x10000);
|
|
|
|
// set banks 80-BF (40h x 32KB ROM banks @10000h)
|
|
map_set(snesmmap+0x80,ROM+0x400000,0x20,0x10000);
|
|
map_set(snesmmap+0xA0,ROM+0x400000,0x20,0x10000);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmap2+0x40,ROM+0x400000,0x20,0x10000);
|
|
map_set(snesmap2+0x60,ROM+0x400000,0x20,0x10000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set banks 70-77 (07h x SRAM)
|
|
for(x = 0x70; x <= 0x77; x++) { snesmap2[x] = sram; }
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void map_sfx()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
|
|
// Clear SFX registers
|
|
SfxR0 = SfxR1 = SfxR2 = SfxR3 = SfxR4 = SfxR5 = SfxR6 = SfxR7 = 0;
|
|
SfxR8 = SfxR9 = SfxR10 = SfxR11 = SfxR12 = SfxR13 = SfxR14 = SfxR15 = 0;
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-3F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap,ROM,0x40,0x10000);
|
|
|
|
// set banks 40-7F (40h x128KB ROM banks @20000h)
|
|
map_set(snesmmap+0x40,ROM+0x8000,0x30,0x20000);
|
|
map_set(snesmmap+0x70,ROM+0x8000,0x10,0x20000);
|
|
|
|
// set banks 80-BF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0x80,ROM,0x40,0x10000);
|
|
|
|
// set banks C0-FF (40h x128KB ROM banks @20000h)
|
|
map_set(snesmmap+0xC0,ROM+0x8000,0x30,0x20000);
|
|
map_set(snesmmap+0xF0,ROM+0x8000,0x10,0x20000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x128KB ROM banks @20000h)
|
|
map_set(snesmap2+0x40,ROM+0x8000,0x30,0x20000);
|
|
map_set(snesmap2+0x70,ROM+0x8000,0x10,0x20000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x128KB ROM banks @20000h)
|
|
map_set(snesmap2+0xC0,ROM+0x8000,0x30,0x20000);
|
|
map_set(snesmap2+0xF0,ROM+0x8000,0x10,0x20000);
|
|
|
|
// set banks 70-73/78/79 (SFXRAM & SRAM)
|
|
map_set(snesmap2+0x70,sfxramdata,4,0x10000);
|
|
snesmap2[0x78] = snesmap2[0x79] = sram;
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
|
|
preparesfx();
|
|
}
|
|
|
|
void map_sa1()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
unsigned char test[] = { 0xA9, 0x10, 0xCF, 0xAD };
|
|
|
|
if(!memcmp(ROM+0xB95, test, 4)) { ROM[0xB96] = 0; }
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-3F (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap,ROM-0x8000,0x40,0x8000);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap+0x80,ROM+0x1F8000,0x40,0x8000);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void map_sdd1()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
unsigned char test[] = { 0xA9, 0x10, 0xCF, 0xAD };
|
|
|
|
if(!memcmp(ROM+0xB95, test, 4)) { ROM[0xB96] = 0; }
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-3F (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap,ROM-0x8000,0x40,0x8000);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap+0x80,ROM-0x8000,0x40,0x8000);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmmap+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0x40,ROM,0x40,0x10000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 64KB ROM banks @10000h)
|
|
map_set(snesmap2+0xC0,ROM,0x40,0x10000);
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void map_bsx()
|
|
{
|
|
unsigned char *ROM = (unsigned char *)romdata;
|
|
int x;
|
|
|
|
// set addresses 8000-FFFF
|
|
// set banks 00-7F (80h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap,ROM-0x8000,0x80,0x8000);
|
|
|
|
// set banks 80-BF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap+0x80,ROM-0x8000,0x40,0x8000);
|
|
|
|
// set banks C0-FF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmmap+0xC0,ROM+0x8000,0x40,0x8000);
|
|
|
|
// set addresses 0000-7FFF
|
|
// set banks 00-3F (40h x WRAM)
|
|
map_set(snesmap2,wramdata,0x40,0);
|
|
|
|
// set banks 40-7F (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmap2+0x40,ROM+0x200000,0x40,0x8000);
|
|
|
|
// set banks 80-BF (40h x WRAM)
|
|
map_set(snesmap2+0x80,wramdata,0x40,0);
|
|
|
|
// set banks C0-FF (40h x 32KB ROM banks @ 8000h)
|
|
map_set(snesmap2+0xC0,ROM+0x8000,0x40,0x8000);
|
|
|
|
// set banks 70-77 (07h x SRAM)
|
|
for (x = 0x70; x <= 0x77; x++) { snesmap2[x] = sram; }
|
|
|
|
// set banks 7E/7F (WRAM)
|
|
snesmmap[0x7E] = snesmap2[0x7E] = wramdata;
|
|
snesmmap[0x7F] = snesmap2[0x7F] = ram7f;
|
|
}
|
|
|
|
void initsnes()
|
|
{
|
|
ForceNewGfxOff = 0;
|
|
|
|
if (!BSEnable)
|
|
{
|
|
MultiTap = pl12s34 ? 0 : (pl3contrl || pl4contrl || pl5contrl);
|
|
|
|
if (SFXEnable) { map_sfx(); }
|
|
else if (SA1Enable) { map_sa1(); }
|
|
else if (SDD1Enable) { map_sdd1(); }
|
|
else if (SPC7110Enable) { map_hirom(); }
|
|
else if (curromsize == 13) { map_ehirom(); }
|
|
else if (romtype == 2) { map_hirom(); }
|
|
else { map_lorom(); }
|
|
}
|
|
else
|
|
{
|
|
map_bsx();
|
|
}
|
|
}
|
|
|
|
bool PatchUsingIPS(char *);
|
|
void DosExit(), OpenSramFile(), CheatCodeLoad(), LoadSecondState(), LoadGameSpecificInput();
|
|
extern unsigned char GUIOn, GUIOn2;
|
|
|
|
bool loadfileGUI()
|
|
{
|
|
bool result = true;
|
|
|
|
spcon = !SPCDisable;
|
|
MessageOn = yesoutofmemory = IPSPatched = 0;
|
|
|
|
loadROM();
|
|
|
|
if (curromspace)
|
|
{
|
|
SramExists = 0;
|
|
OpenSramFile();
|
|
OpenCombFile();
|
|
LoadGameSpecificInput();
|
|
|
|
if (!(GUIOn || GUIOn2))
|
|
{
|
|
puts("File opened successfully !");
|
|
}
|
|
if (!IPSPatched)
|
|
{
|
|
int i;
|
|
char ext[4];
|
|
|
|
strcpy(ext, "ips");
|
|
for (i = 0; PatchUsingIPS(ext); i++)
|
|
{
|
|
if (i > 9) { break; }
|
|
ext[2] = i+'0';
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GUIOn || GUIOn2) { result = false; }
|
|
else
|
|
{
|
|
puts("Error opening file!\n");
|
|
asm_call(DosExit);
|
|
}
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
extern unsigned int CheatOn, NumCheats;
|
|
extern unsigned char CheatWinMode, CheatSearchStatus;
|
|
void GUIQuickLoadUpdate();
|
|
|
|
void powercycle(bool sramload, bool romload)
|
|
{
|
|
clearmem2();
|
|
|
|
nmiprevaddrl = 0;
|
|
nmiprevaddrh = 0;
|
|
nmirept = 0;
|
|
nmiprevline = 224;
|
|
nmistatus = 0;
|
|
spcnumread = 0;
|
|
NextLineCache = 0;
|
|
curexecstate = 1;
|
|
|
|
if (sramload) { OpenSramFile(); }
|
|
if (romload) { romloadskip = 1; }
|
|
|
|
if (!romload || (loadfileGUI()))
|
|
{
|
|
if (romload)
|
|
{ CheatOn = NumCheats = CheatWinMode = CheatSearchStatus = 0; }
|
|
|
|
SetupROM();
|
|
|
|
if (romload)
|
|
{
|
|
if (DisplayInfo) { showinfogui(); }
|
|
initsnes();
|
|
}
|
|
|
|
sramsavedis = 0;
|
|
memcpy(&sndrot, regsbackup, 3019);
|
|
|
|
if (yesoutofmemory) { asm_call(outofmemfix); }
|
|
asm_call(GUIDoReset);
|
|
|
|
if (romload)
|
|
{
|
|
GUIQuickLoadUpdate();
|
|
|
|
if (AutoLoadCht) { CheatCodeLoad(); }
|
|
if (AutoState) { LoadSecondState(); }
|
|
}
|
|
}
|
|
}
|
|
|
|
extern unsigned char osm2dis, ReturnFromSPCStall, SPCStallSetting, prevoamptr;
|
|
extern unsigned char reg1read, reg2read, reg3read, reg4read, NMIEnab, INTEnab;
|
|
extern unsigned char doirqnext, vidbright, forceblnk, timeron, spcP, JoyAPos, JoyBPos;
|
|
extern unsigned char coladdr, coladdg, coladdb;
|
|
extern unsigned char SDD1BankA,SDD1BankB, SDD1BankC, SDD1BankD;
|
|
extern unsigned char intrset, curcyc, cycpl, GUIReset;
|
|
extern unsigned int numspcvblleft, SPC700read, SPC700write, spc700idle;
|
|
extern unsigned int FIRTAPVal0, FIRTAPVal1, FIRTAPVal2, FIRTAPVal3, FIRTAPVal4, FIRTAPVal5, FIRTAPVal6, FIRTAPVal7;
|
|
extern unsigned int xa, xdb, xpb, xs, xd, xx, xy, scrndis;
|
|
extern unsigned short VIRQLoc, resolutn, xpc;
|
|
extern unsigned char spcextraram[64], SPCROM[64];
|
|
extern unsigned int tableD[256];
|
|
unsigned char SPCSkipXtraROM, bgfixer2 = 0, disableeffects = 0;
|
|
//This is saved in states
|
|
unsigned char cycpl = 0; // cycles per scanline
|
|
unsigned char cycphb = 0; // cycles per hblank
|
|
unsigned char intrset = 0; // interrupt set
|
|
unsigned short curypos = 0; // current y position
|
|
unsigned short stackand = 0x01FF; // value to and stack to keep it from going to the wrong area
|
|
unsigned short stackor = 0x0100; // value to or stack to keep it from going to the wrong area
|
|
|
|
// 65816 registers
|
|
unsigned char xp = 0;
|
|
unsigned char xe = 0;
|
|
unsigned char xirqb = 0; // which bank the irqs start at
|
|
unsigned int Curtableaddr = 0; // Current table address
|
|
|
|
void SA1Reset();
|
|
void InitC4();
|
|
void RTCinit();
|
|
void SPC7110init();
|
|
|
|
void init65816()
|
|
{
|
|
unsigned int i;
|
|
osm2dis = 0;
|
|
bgfixer2 = 0;
|
|
if(SA1Enable)
|
|
{
|
|
SA1Reset();
|
|
SetAddressingModesSA1();
|
|
}
|
|
|
|
if(C4Enable)
|
|
{
|
|
osm2dis = 1;
|
|
bgfixer2 = 1;
|
|
InitC4();
|
|
}
|
|
|
|
if(RTCEnable)
|
|
RTCinit();
|
|
|
|
if(SPC7110Enable)
|
|
{
|
|
if (!SPC7110IndexPtr) SPC7110IndexPtr = malloc(12*4608);
|
|
if (!SPC7110PackPtr) SPC7110PackPtr = malloc(65536);
|
|
|
|
if (SPC7110IndexPtr && SPC7110PackPtr)
|
|
{
|
|
SPC7PackIndexLoad();
|
|
|
|
SPC7110init();
|
|
map_mem(0x50, &SPC7110bank, 1);
|
|
map_mem(0x00, &SPC7110SRAMBank, 1);
|
|
map_mem(0x30, &SPC7110SRAMBank, 1);
|
|
snesmmap[0x50] = SPC7110PackPtr;
|
|
snesmap2[0x50] = SPC7110PackPtr;
|
|
memset(SPC7110PackPtr, 0, 0x10000);
|
|
}
|
|
else
|
|
{
|
|
puts("You don't have enough memory to run SPC7110 games!");
|
|
Msgptr = "MEMORY ERROR!";
|
|
MessageOn = 360;
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SPC7110IndexPtr) free(SPC7110IndexPtr);
|
|
if (SPC7110PackPtr) free(SPC7110PackPtr);
|
|
}
|
|
|
|
cycpb268 = 117;
|
|
cycpb358 = 127;
|
|
cycpbl2 = 117;
|
|
cycpblt2 = 117;
|
|
cycpbl = 117;
|
|
cycpblt = 117;
|
|
|
|
SPCSkipXtraROM = 0;
|
|
if(ReturnFromSPCStall)
|
|
{
|
|
cycpb268 = 69;
|
|
cycpb358 = 81;
|
|
cycpbl2 = 69;
|
|
cycpblt2 = 69;
|
|
cycpbl = 69;
|
|
cycpblt = 69;
|
|
SPCSkipXtraROM = 1;
|
|
if(SPCStallSetting == 2)
|
|
{
|
|
cycpb268 = 240;
|
|
cycpb358 = 240;
|
|
cycpbl = 240;
|
|
cycpblt = 240;
|
|
cycpbl2 = 240;
|
|
cycpblt2 = 240;
|
|
SPCSkipXtraROM = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SPCStallSetting = 0;
|
|
}
|
|
|
|
numspcvblleft = 480;
|
|
SPC700write = 0;
|
|
SPC700read = 0;
|
|
spc700idle = 0;
|
|
|
|
for(i = 0;i<0x40;i++)
|
|
{
|
|
spcextraram[i] = 0xFF;
|
|
SPCRAM[0xFFC0+i] = SPCROM[i];
|
|
}
|
|
|
|
// Clear SPC Memory
|
|
clearSPCRAM();
|
|
clearvidsound();
|
|
|
|
prevoamptr = 0xFF;
|
|
disableeffects = 0;
|
|
opexec268 = opexec268b;
|
|
opexec358 = opexec358b;
|
|
opexec268cph = opexec268cphb;
|
|
opexec358cph = opexec358cphb;
|
|
|
|
if (!(((unsigned char *)romdata)[infoloc+BankOffset] & 0xF0)) // if not fastrom
|
|
{
|
|
opexec358 = opexec268;
|
|
opexec358cph = opexec268cph;
|
|
cycpb358 = cycpb268;
|
|
}
|
|
|
|
FIRTAPVal0 = 0x7F;
|
|
FIRTAPVal1 = 0;
|
|
FIRTAPVal2 = 0;
|
|
FIRTAPVal3 = 0;
|
|
FIRTAPVal4 = 0;
|
|
FIRTAPVal5 = 0;
|
|
FIRTAPVal6 = 0;
|
|
FIRTAPVal7 = 0;
|
|
|
|
// Check Headers
|
|
headerhack();
|
|
|
|
SPCRAM[0xF4] = 0;
|
|
SPCRAM[0xF5] = 0;
|
|
SPCRAM[0xF6] = 0;
|
|
SPCRAM[0xF7] = 0;
|
|
reg1read = 0;
|
|
reg2read = 0;
|
|
reg3read = 0;
|
|
reg4read = 0;
|
|
cycpbl = 0;
|
|
spcnumread = 0;
|
|
NMIEnab = 1;
|
|
VIRQLoc = 0;
|
|
doirqnext = 0;
|
|
resolutn = 224;
|
|
vidbright = 0;
|
|
forceblnk = 0;
|
|
spcP = 0;
|
|
timeron = 0;
|
|
JoyAPos = 0;
|
|
JoyBPos = 0;
|
|
coladdr = 0;
|
|
coladdg = 0;
|
|
coladdb = 0;
|
|
INTEnab = 0;
|
|
xa = 0;
|
|
xdb = 0;
|
|
xpb = 0;
|
|
xs = 0x01FF;
|
|
xd = 0;
|
|
xx = 0;
|
|
xy = 0;
|
|
SDD1BankA = 0;
|
|
SDD1BankB = 0x01;
|
|
SDD1BankC = 0x02;
|
|
SDD1BankD = 0x03;
|
|
xirqb = 0;
|
|
xp = 52; // NVMXDIZC
|
|
xe = 1; // E
|
|
xpc = resetv;
|
|
|
|
intrset = 0;
|
|
|
|
if (xpc < 0x8000)
|
|
{
|
|
xpc += 0x8000;
|
|
//xpb = 0x40;
|
|
}
|
|
|
|
// 2.68 Mhz / 3.58 Mhz = 228
|
|
curcyc = cycpl = opexec268;
|
|
cycphb = opexec268cph; // 2.68 Mhz / 3.58 Mhz = 56
|
|
cycpbl = 110; // 3.58Mhz = 175
|
|
cycpblt = 110;
|
|
curypos = 0;
|
|
Curtableaddr = *tableD;
|
|
scrndis = 0;
|
|
stackand = 0x01FF;
|
|
stackor = 0x0100;
|
|
|
|
nmiprevaddrl = 0;
|
|
nmiprevaddrh = 0;
|
|
nmirept = 0;
|
|
nmiprevline = 224;
|
|
nmistatus = 0;
|
|
|
|
if(GUIReset)
|
|
{
|
|
GUIReset = 0;
|
|
}
|
|
|
|
else
|
|
{
|
|
memset(wramdataa,0x55,0x10000);
|
|
memset(ram7fa, 0x55,0x10000);
|
|
}
|
|
|
|
if(BSEnable)
|
|
{
|
|
memset(wramdataa,0xFF,0x10000);
|
|
memset(ram7fa,0xFF,0x10000);
|
|
if(romtype == 1)
|
|
memset(ram7fa+65528, 0x01, 8);
|
|
}
|
|
}
|
|
|
|
void zexit()
|
|
{
|
|
exit(0);
|
|
}
|
|
|