Make local versions of fds/ines/unif.c
This commit is contained in:
@@ -2,4 +2,4 @@ INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(CORE_DIR) -I$(CORE_DIR)/input -I$
|
||||
|
||||
FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers
|
||||
SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
SOURCES_C += $(CORE_DIR)/drivers/libretro/griffin.c $(CORE_DIR)/ines.c $(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c
|
||||
SOURCES_C += $(CORE_DIR)/drivers/libretro/griffin.c $(CORE_DIR)/drivers/libretro/fceu/ines.c $(CORE_DIR)/drivers/libretro/fceu/unif.c $(CORE_DIR)/x6502.c
|
||||
|
||||
772
src/drivers/libretro/fceu/fds.c
Normal file
772
src/drivers/libretro/fceu/fds.c
Normal file
@@ -0,0 +1,772 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fceu-types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "fds.h"
|
||||
#include "sound.h"
|
||||
#include "general.h"
|
||||
#include "state.h"
|
||||
#include "file.h"
|
||||
#include "fceu-memory.h"
|
||||
#include "cart.h"
|
||||
#include "md5.h"
|
||||
#include "netplay.h"
|
||||
|
||||
// TODO: Add code to put a delay in between the time a disk is inserted
|
||||
// and the when it can be successfully read/written to. This should
|
||||
// prevent writes to wrong places OR add code to prevent disk ejects
|
||||
// when the virtual motor is on(mmm...virtual motor).
|
||||
|
||||
static DECLFR(FDSRead4030);
|
||||
static DECLFR(FDSRead4031);
|
||||
static DECLFR(FDSRead4032);
|
||||
static DECLFR(FDSRead4033);
|
||||
|
||||
static DECLFW(FDSWrite);
|
||||
|
||||
static DECLFW(FDSWaveWrite);
|
||||
static DECLFR(FDSWaveRead);
|
||||
|
||||
static DECLFR(FDSSRead);
|
||||
static DECLFW(FDSSWrite);
|
||||
|
||||
static void FDSInit(void);
|
||||
static void FDSClose(void);
|
||||
|
||||
static void FP_FASTAPASS(1) FDSFix(int a);
|
||||
|
||||
static uint8 FDSRegs[6];
|
||||
static int32 IRQLatch, IRQCount;
|
||||
static uint8 IRQa;
|
||||
|
||||
static uint8 *FDSRAM = NULL;
|
||||
static uint32 FDSRAMSize;
|
||||
static uint8 *FDSBIOS = NULL;
|
||||
static uint32 FDSBIOSsize;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint32 CHRRAMSize;
|
||||
|
||||
/* Original disk data backup, to help in creating save states. */
|
||||
static uint8 *diskdatao[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static uint8 *diskdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static uint32 TotalSides;
|
||||
static uint8 DiskWritten = 0; /* Set to 1 if disk was written to. */
|
||||
static uint8 writeskip;
|
||||
static int32 DiskPtr;
|
||||
static int32 DiskSeekIRQ;
|
||||
static uint8 SelectDisk, InDisk;
|
||||
|
||||
uint32 lastDiskPtrRead, lastDiskPtrWrite;
|
||||
|
||||
#define DC_INC 1
|
||||
|
||||
void FDSGI(int h) {
|
||||
switch (h) {
|
||||
case GI_CLOSE: FDSClose(); break;
|
||||
case GI_POWER: FDSInit(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FDSStateRestore(int version) {
|
||||
int x;
|
||||
|
||||
setmirror(((FDSRegs[5] & 8) >> 3) ^ 1);
|
||||
|
||||
if (version >= 9810)
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
int b;
|
||||
for (b = 0; b < 65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
}
|
||||
|
||||
void FDSSound();
|
||||
void FDSSoundReset(void);
|
||||
void FDSSoundStateAdd(void);
|
||||
static void RenderSound(void);
|
||||
static void RenderSoundHQ(void);
|
||||
|
||||
static void FDSInit(void) {
|
||||
memset(FDSRegs, 0, sizeof(FDSRegs));
|
||||
lastDiskPtrRead = lastDiskPtrWrite = writeskip = DiskPtr = DiskSeekIRQ = 0;
|
||||
|
||||
setmirror(1);
|
||||
setprg8(0xE000, 0); // BIOS
|
||||
setprg32r(1, 0x6000, 0); // 32KB RAM
|
||||
setchr8(0); // 8KB CHR RAM
|
||||
|
||||
MapIRQHook = FDSFix;
|
||||
GameStateRestore = FDSStateRestore;
|
||||
|
||||
SetReadHandler(0x4030, 0x4030, FDSRead4030);
|
||||
SetReadHandler(0x4031, 0x4031, FDSRead4031);
|
||||
SetReadHandler(0x4032, 0x4032, FDSRead4032);
|
||||
SetReadHandler(0x4033, 0x4033, FDSRead4033);
|
||||
|
||||
SetWriteHandler(0x4020, 0x4025, FDSWrite);
|
||||
|
||||
SetWriteHandler(0x6000, 0xDFFF, CartBW);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
|
||||
IRQCount = IRQLatch = IRQa = 0;
|
||||
|
||||
FDSSoundReset();
|
||||
InDisk = 0;
|
||||
SelectDisk = 0;
|
||||
}
|
||||
|
||||
void FCEU_FDSInsert(int oride) {
|
||||
if (InDisk == 255) {
|
||||
FCEU_DispMessage("Disk %d Side %s Inserted", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = SelectDisk;
|
||||
} else {
|
||||
FCEU_DispMessage("Disk %d Side %s Ejected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = 255;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_FDSEject(void) {
|
||||
InDisk = 255;
|
||||
}
|
||||
|
||||
void FCEU_FDSSelect(void) {
|
||||
if (InDisk != 255) {
|
||||
FCEU_DispMessage("Eject disk before selecting.");
|
||||
return;
|
||||
}
|
||||
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
|
||||
FCEU_DispMessage("Disk %d Side %s Selected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) FDSFix(int a) {
|
||||
if ((IRQa & 2) && IRQCount) {
|
||||
IRQCount -= a;
|
||||
if (IRQCount <= 0) {
|
||||
if (!(IRQa & 1)) {
|
||||
IRQa &= ~2;
|
||||
IRQCount = IRQLatch = 0;
|
||||
} else
|
||||
IRQCount = IRQLatch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
if (DiskSeekIRQ > 0) {
|
||||
DiskSeekIRQ -= a;
|
||||
if (DiskSeekIRQ <= 0) {
|
||||
if (FDSRegs[5] & 0x80) {
|
||||
X6502_IRQBegin(FCEU_IQEXT2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4030) {
|
||||
uint8 ret = 0;
|
||||
|
||||
/* Cheap hack. */
|
||||
if (X.IRQlow & FCEU_IQEXT) ret |= 1;
|
||||
if (X.IRQlow & FCEU_IQEXT2) ret |= 2;
|
||||
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg)
|
||||
#endif
|
||||
{
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4031) {
|
||||
static uint8 z = 0;
|
||||
if (InDisk != 255) {
|
||||
z = diskdata[InDisk][DiskPtr];
|
||||
lastDiskPtrRead = DiskPtr;
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg)
|
||||
#endif
|
||||
{
|
||||
if (DiskPtr < 64999) DiskPtr++;
|
||||
DiskSeekIRQ = 150;
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
static DECLFR(FDSRead4032) {
|
||||
uint8 ret;
|
||||
|
||||
ret = X.DB & ~7;
|
||||
if (InDisk == 255)
|
||||
ret |= 5;
|
||||
|
||||
if (InDisk == 255 || !(FDSRegs[5] & 1) || (FDSRegs[5] & 2))
|
||||
ret |= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4033) {
|
||||
return 0x80; // battery
|
||||
}
|
||||
|
||||
/* Begin FDS sound */
|
||||
|
||||
#define FDSClock (1789772.7272727272727272 / 2)
|
||||
|
||||
typedef struct {
|
||||
int64 cycles; // Cycles per PCM sample
|
||||
int64 count; // Cycle counter
|
||||
int64 envcount; // Envelope cycle counter
|
||||
uint32 b19shiftreg60;
|
||||
uint32 b24adder66;
|
||||
uint32 b24latch68;
|
||||
uint32 b17latch76;
|
||||
int32 clockcount; // Counter to divide frequency by 8.
|
||||
uint8 b8shiftreg88; // Modulation register.
|
||||
uint8 amplitude[2]; // Current amplitudes.
|
||||
uint8 speedo[2];
|
||||
uint8 mwcount;
|
||||
uint8 mwstart;
|
||||
uint8 mwave[0x20]; // Modulation waveform
|
||||
uint8 cwave[0x40]; // Game-defined waveform(carrier)
|
||||
uint8 SPSG[0xB];
|
||||
} FDSSOUND;
|
||||
|
||||
static FDSSOUND fdso;
|
||||
|
||||
#define SPSG fdso.SPSG
|
||||
#define b19shiftreg60 fdso.b19shiftreg60
|
||||
#define b24adder66 fdso.b24adder66
|
||||
#define b24latch68 fdso.b24latch68
|
||||
#define b17latch76 fdso.b17latch76
|
||||
#define b8shiftreg88 fdso.b8shiftreg88
|
||||
#define clockcount fdso.clockcount
|
||||
#define amplitude fdso.amplitude
|
||||
#define speedo fdso.speedo
|
||||
|
||||
void FDSSoundStateAdd(void) {
|
||||
AddExState(fdso.cwave, 64, 0, "WAVE");
|
||||
AddExState(fdso.mwave, 32, 0, "MWAV");
|
||||
AddExState(amplitude, 2, 0, "AMPL");
|
||||
AddExState(SPSG, 0xB, 0, "SPSG");
|
||||
|
||||
AddExState(&b8shiftreg88, 1, 0, "B88");
|
||||
|
||||
AddExState(&clockcount, 4, 1, "CLOC");
|
||||
AddExState(&b19shiftreg60, 4, 1, "B60");
|
||||
AddExState(&b24adder66, 4, 1, "B66");
|
||||
AddExState(&b24latch68, 4, 1, "B68");
|
||||
AddExState(&b17latch76, 4, 1, "B76");
|
||||
}
|
||||
|
||||
static DECLFR(FDSSRead) {
|
||||
switch (A & 0xF) {
|
||||
case 0x0: return(amplitude[0] | (X.DB & 0xC0));
|
||||
case 0x2: return(amplitude[1] | (X.DB & 0xC0));
|
||||
}
|
||||
return(X.DB);
|
||||
}
|
||||
|
||||
static DECLFW(FDSSWrite) {
|
||||
if (FSettings.SndRate) {
|
||||
if (FSettings.soundq >= 1)
|
||||
RenderSoundHQ();
|
||||
else
|
||||
RenderSound();
|
||||
}
|
||||
A -= 0x4080;
|
||||
switch (A) {
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
if (V & 0x80)
|
||||
amplitude[(A & 0xF) >> 2] = V & 0x3F;
|
||||
break;
|
||||
case 0x7:
|
||||
b17latch76 = 0;
|
||||
SPSG[0x5] = 0;
|
||||
break;
|
||||
case 0x8:
|
||||
b17latch76 = 0;
|
||||
fdso.mwave[SPSG[0x5] & 0x1F] = V & 0x7;
|
||||
SPSG[0x5] = (SPSG[0x5] + 1) & 0x1F;
|
||||
break;
|
||||
}
|
||||
SPSG[A] = V;
|
||||
}
|
||||
|
||||
// $4080 - Fundamental wave amplitude data register 92
|
||||
// $4082 - Fundamental wave frequency data register 58
|
||||
// $4083 - Same as $4082($4083 is the upper 4 bits).
|
||||
|
||||
// $4084 - Modulation amplitude data register 78
|
||||
// $4086 - Modulation frequency data register 72
|
||||
// $4087 - Same as $4086($4087 is the upper 4 bits)
|
||||
|
||||
|
||||
static void DoEnv() {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 2; x++)
|
||||
if (!(SPSG[x << 2] & 0x80) && !(SPSG[0x3] & 0x40)) {
|
||||
static int counto[2] = { 0, 0 };
|
||||
|
||||
if (counto[x] <= 0) {
|
||||
if (!(SPSG[x << 2] & 0x80)) {
|
||||
if (SPSG[x << 2] & 0x40) {
|
||||
if (amplitude[x] < 0x3F)
|
||||
amplitude[x]++;
|
||||
} else {
|
||||
if (amplitude[x] > 0)
|
||||
amplitude[x]--;
|
||||
}
|
||||
}
|
||||
counto[x] = (SPSG[x << 2] & 0x3F);
|
||||
} else
|
||||
counto[x]--;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FDSWaveRead) {
|
||||
return(fdso.cwave[A & 0x3f] | (X.DB & 0xC0));
|
||||
}
|
||||
|
||||
static DECLFW(FDSWaveWrite) {
|
||||
if (SPSG[0x9] & 0x80)
|
||||
fdso.cwave[A & 0x3f] = V & 0x3F;
|
||||
}
|
||||
|
||||
static int ta;
|
||||
static INLINE void ClockRise(void) {
|
||||
if (!clockcount) {
|
||||
ta++;
|
||||
|
||||
b19shiftreg60 = (SPSG[0x2] | ((SPSG[0x3] & 0xF) << 8));
|
||||
b17latch76 = (SPSG[0x6] | ((SPSG[0x07] & 0xF) << 8)) + b17latch76;
|
||||
|
||||
if (!(SPSG[0x7] & 0x80)) {
|
||||
int t = fdso.mwave[(b17latch76 >> 13) & 0x1F] & 7;
|
||||
int t2 = amplitude[1];
|
||||
int adj = 0;
|
||||
|
||||
if ((t & 3)) {
|
||||
if ((t & 4))
|
||||
adj -= (t2 * ((4 - (t & 3))));
|
||||
else
|
||||
adj += (t2 * ((t & 3)));
|
||||
}
|
||||
adj *= 2;
|
||||
if (adj > 0x7F) adj = 0x7F;
|
||||
if (adj < -0x80) adj = -0x80;
|
||||
b8shiftreg88 = 0x80 + adj;
|
||||
} else {
|
||||
b8shiftreg88 = 0x80;
|
||||
}
|
||||
} else {
|
||||
b19shiftreg60 <<= 1;
|
||||
b8shiftreg88 >>= 1;
|
||||
}
|
||||
b24adder66 = (b24latch68 + b19shiftreg60) & 0x1FFFFFF;
|
||||
}
|
||||
|
||||
static INLINE void ClockFall(void) {
|
||||
if ((b8shiftreg88 & 1))
|
||||
b24latch68 = b24adder66;
|
||||
clockcount = (clockcount + 1) & 7;
|
||||
}
|
||||
|
||||
static INLINE int32 FDSDoSound(void) {
|
||||
fdso.count += fdso.cycles;
|
||||
if (fdso.count >= ((int64)1 << 40)) {
|
||||
dogk:
|
||||
fdso.count -= (int64)1 << 40;
|
||||
ClockRise();
|
||||
ClockFall();
|
||||
fdso.envcount--;
|
||||
if (fdso.envcount <= 0) {
|
||||
fdso.envcount += SPSG[0xA] * 3;
|
||||
DoEnv();
|
||||
}
|
||||
}
|
||||
if (fdso.count >= 32768) goto dogk;
|
||||
|
||||
// Might need to emulate applying the amplitude to the waveform a bit better...
|
||||
{
|
||||
int k = amplitude[0];
|
||||
if (k > 0x20) k = 0x20;
|
||||
return (fdso.cwave[b24latch68 >> 19] * k) * 4 / ((SPSG[0x9] & 0x3) + 2);
|
||||
}
|
||||
}
|
||||
|
||||
static int32 FBC = 0;
|
||||
|
||||
static void RenderSound(void) {
|
||||
int32 end, start;
|
||||
int32 x;
|
||||
|
||||
start = FBC;
|
||||
end = (SOUNDTS << 16) / soundtsinc;
|
||||
if (end <= start)
|
||||
return;
|
||||
FBC = end;
|
||||
|
||||
if (!(SPSG[0x9] & 0x80))
|
||||
for (x = start; x < end; x++) {
|
||||
uint32 t = FDSDoSound();
|
||||
t += t >> 1;
|
||||
t >>= 4;
|
||||
Wave[x >> 4] += t; //(t>>2)-(t>>3); //>>3;
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderSoundHQ(void) {
|
||||
uint32 x;
|
||||
|
||||
if (!(SPSG[0x9] & 0x80))
|
||||
for (x = FBC; x < SOUNDTS; x++) {
|
||||
uint32 t = FDSDoSound();
|
||||
t += t >> 1;
|
||||
WaveHi[x] += t; //(t<<2)-(t<<1);
|
||||
}
|
||||
FBC = SOUNDTS;
|
||||
}
|
||||
|
||||
static void HQSync(int32 ts) {
|
||||
FBC = ts;
|
||||
}
|
||||
|
||||
void FDSSound(int c) {
|
||||
RenderSound();
|
||||
FBC = c;
|
||||
}
|
||||
|
||||
static void FDS_ESI(void) {
|
||||
if (FSettings.SndRate) {
|
||||
if (FSettings.soundq >= 1) {
|
||||
fdso.cycles = (int64)1 << 39;
|
||||
} else {
|
||||
fdso.cycles = ((int64)1 << 40) * FDSClock;
|
||||
fdso.cycles /= FSettings.SndRate * 16;
|
||||
}
|
||||
}
|
||||
SetReadHandler(0x4040, 0x407f, FDSWaveRead);
|
||||
SetWriteHandler(0x4040, 0x407f, FDSWaveWrite);
|
||||
SetWriteHandler(0x4080, 0x408A, FDSSWrite);
|
||||
SetReadHandler(0x4090, 0x4092, FDSSRead);
|
||||
}
|
||||
|
||||
void FDSSoundReset(void) {
|
||||
memset(&fdso, 0, sizeof(fdso));
|
||||
FDS_ESI();
|
||||
GameExpSound.HiSync = HQSync;
|
||||
GameExpSound.HiFill = RenderSoundHQ;
|
||||
GameExpSound.Fill = FDSSound;
|
||||
GameExpSound.RChange = FDS_ESI;
|
||||
}
|
||||
|
||||
static DECLFW(FDSWrite) {
|
||||
switch (A) {
|
||||
case 0x4020:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch &= 0xFF00;
|
||||
IRQLatch |= V;
|
||||
break;
|
||||
case 0x4021:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch &= 0xFF;
|
||||
IRQLatch |= V << 8;
|
||||
break;
|
||||
case 0x4022:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQCount = IRQLatch;
|
||||
IRQa = V & 3;
|
||||
break;
|
||||
case 0x4024:
|
||||
if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) {
|
||||
if (DiskPtr >= 0 && DiskPtr < 65500) {
|
||||
if (writeskip)
|
||||
writeskip--;
|
||||
else if (DiskPtr >= 2) {
|
||||
DiskWritten = 1;
|
||||
diskdata[InDisk][DiskPtr - 2] = V;
|
||||
lastDiskPtrWrite = DiskPtr - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x4025:
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
if (InDisk != 255) {
|
||||
if (!(V & 0x40)) {
|
||||
if ((FDSRegs[5] & 0x40) && !(V & 0x10)) {
|
||||
DiskSeekIRQ = 200;
|
||||
DiskPtr -= 2;
|
||||
}
|
||||
if (DiskPtr < 0) DiskPtr = 0;
|
||||
}
|
||||
if (!(V & 0x4)) writeskip = 2;
|
||||
if (V & 2) {
|
||||
DiskPtr = 0; DiskSeekIRQ = 200;
|
||||
}
|
||||
if (V & 0x40) DiskSeekIRQ = 200;
|
||||
}
|
||||
setmirror(((V >> 3) & 1) ^ 1);
|
||||
break;
|
||||
}
|
||||
FDSRegs[A & 7] = V;
|
||||
}
|
||||
|
||||
static void FreeFDSMemory(void) {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < TotalSides; x++)
|
||||
if (diskdata[x]) {
|
||||
free(diskdata[x]);
|
||||
diskdata[x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int SubLoad(FCEUFILE *fp) {
|
||||
struct md5_context md5;
|
||||
uint8 header[16];
|
||||
int x;
|
||||
|
||||
FCEU_fread(header, 16, 1, fp);
|
||||
|
||||
if (memcmp(header, "FDS\x1a", 4)) {
|
||||
if (!(memcmp(header + 1, "*NINTENDO-HVC*", 14))) {
|
||||
long t;
|
||||
t = FCEU_fgetsize(fp);
|
||||
if (t < 65500)
|
||||
t = 65500;
|
||||
TotalSides = t / 65500;
|
||||
FCEU_fseek(fp, 0, SEEK_SET);
|
||||
} else
|
||||
return(0);
|
||||
} else
|
||||
TotalSides = header[4];
|
||||
|
||||
md5_starts(&md5);
|
||||
|
||||
if (TotalSides > 8) TotalSides = 8;
|
||||
if (TotalSides < 1) TotalSides = 1;
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
diskdata[x] = (uint8*)FCEU_malloc(65500);
|
||||
if (!diskdata[x]) {
|
||||
int zol;
|
||||
for (zol = 0; zol < x; zol++)
|
||||
free(diskdata[zol]);
|
||||
return 0;
|
||||
}
|
||||
FCEU_fread(diskdata[x], 1, 65500, fp);
|
||||
md5_update(&md5, diskdata[x], 65500);
|
||||
}
|
||||
md5_finish(&md5, GameInfo->MD5);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void PreSave(void) {
|
||||
int x;
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
int b;
|
||||
for (b = 0; b < 65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
}
|
||||
|
||||
static void PostSave(void) {
|
||||
int x;
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
int b;
|
||||
for (b = 0; b < 65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
}
|
||||
|
||||
int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
FILE *zp;
|
||||
int x;
|
||||
|
||||
char *fn = FCEU_MakeFName(FCEUMKF_FDSROM, 0, 0);
|
||||
|
||||
if (!(zp = FCEUD_UTF8fopen(fn, "rb"))) {
|
||||
FCEU_PrintError("FDS BIOS ROM image missing!");
|
||||
free(fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(fn);
|
||||
|
||||
ResetCartMapping();
|
||||
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
if (FDSRAM)
|
||||
free(FDSRAM);
|
||||
FDSRAM = NULL;
|
||||
if (CHRRAM)
|
||||
free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
|
||||
FDSBIOSsize = 8192;
|
||||
FDSBIOS = (uint8*)FCEU_gmalloc(FDSBIOSsize);
|
||||
SetupCartPRGMapping(0, FDSBIOS, FDSBIOSsize, 0);
|
||||
|
||||
if (fread(FDSBIOS, 1, FDSBIOSsize, zp) != FDSBIOSsize) {
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
fclose(zp);
|
||||
FCEU_PrintError("Error reading FDS BIOS ROM image.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(zp);
|
||||
|
||||
FCEU_fseek(fp, 0, SEEK_SET);
|
||||
|
||||
FreeFDSMemory();
|
||||
if (!SubLoad(fp)) {
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
{
|
||||
FCEUFILE *tp;
|
||||
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
|
||||
|
||||
int x;
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
diskdatao[x] = (uint8*)FCEU_malloc(65500);
|
||||
memcpy(diskdatao[x], diskdata[x], 65500);
|
||||
}
|
||||
|
||||
if ((tp = FCEU_fopen(fn, 0, "rb", 0))) {
|
||||
FCEU_printf("Disk was written. Auxillary FDS file open \"%s\".\n", fn);
|
||||
FreeFDSMemory();
|
||||
if (!SubLoad(tp)) {
|
||||
FCEU_PrintError("Error reading auxillary FDS file.");
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
free(fn);
|
||||
return(0);
|
||||
}
|
||||
FCEU_fclose(tp);
|
||||
DiskWritten = 1; /* For save state handling. */
|
||||
}
|
||||
free(fn);
|
||||
}
|
||||
|
||||
GameInfo->type = GIT_FDS;
|
||||
GameInterface = FDSGI;
|
||||
|
||||
SelectDisk = 0;
|
||||
InDisk = 255;
|
||||
|
||||
ResetExState(PreSave, PostSave);
|
||||
FDSSoundStateAdd();
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
char temp[5];
|
||||
sprintf(temp, "DDT%d", x);
|
||||
AddExState(diskdata[x], 65500, 0, temp);
|
||||
}
|
||||
|
||||
AddExState(FDSRegs, sizeof(FDSRegs), 0, "FREG");
|
||||
AddExState(&IRQCount, 4, 1, "IRQC");
|
||||
AddExState(&IRQLatch, 4, 1, "IQL1");
|
||||
AddExState(&IRQa, 1, 0, "IRQA");
|
||||
AddExState(&writeskip, 1, 0, "WSKI");
|
||||
AddExState(&DiskPtr, 4, 1, "DPTR");
|
||||
AddExState(&DiskSeekIRQ, 4, 1, "DSIR");
|
||||
AddExState(&SelectDisk, 1, 0, "SELD");
|
||||
AddExState(&InDisk, 1, 0, "INDI");
|
||||
AddExState(&DiskWritten, 1, 0, "DSKW");
|
||||
|
||||
CHRRAMSize = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
memset(CHRRAM, 0, CHRRAMSize);
|
||||
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||
|
||||
FDSRAMSize = 32768;
|
||||
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
|
||||
memset(FDSRAM, 0, FDSRAMSize);
|
||||
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
|
||||
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
|
||||
|
||||
SetupCartMirroring(0, 0, 0);
|
||||
|
||||
FCEU_printf(" Sides: %d\n\n", TotalSides);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FDSClose(void) {
|
||||
FILE *fp;
|
||||
int x;
|
||||
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
|
||||
|
||||
if (!DiskWritten) return;
|
||||
|
||||
if (!(fp = FCEUD_UTF8fopen(fn, "wb"))) {
|
||||
free(fn);
|
||||
return;
|
||||
}
|
||||
FCEU_printf("FDS Save \"%s\"\n", fn);
|
||||
free(fn);
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
if (fwrite(diskdata[x], 1, 65500, fp) != 65500) {
|
||||
FCEU_PrintError("Error saving FDS image!");
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < TotalSides; x++)
|
||||
if (diskdatao[x]) {
|
||||
free(diskdatao[x]);
|
||||
diskdatao[x] = 0;
|
||||
}
|
||||
|
||||
FreeFDSMemory();
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
if (FDSRAM)
|
||||
free(FDSRAM);
|
||||
FDSRAM = NULL;
|
||||
if (CHRRAM)
|
||||
free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
fclose(fp);
|
||||
}
|
||||
839
src/drivers/libretro/fceu/ines.c
Normal file
839
src/drivers/libretro/fceu/ines.c
Normal file
@@ -0,0 +1,839 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 1998 BERO
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fceu-types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "cart.h"
|
||||
#include "ppu.h"
|
||||
|
||||
#include "ines.h"
|
||||
#include "unif.h"
|
||||
#include "state.h"
|
||||
#include "file.h"
|
||||
#include "general.h"
|
||||
#include "fceu-memory.h"
|
||||
#include "crc32.h"
|
||||
#include "md5.h"
|
||||
#include "cheat.h"
|
||||
#include "vsuni.h"
|
||||
|
||||
extern SFORMAT FCEUVSUNI_STATEINFO[];
|
||||
|
||||
uint8 *trainerpoo = NULL;
|
||||
uint8 *ROM = NULL;
|
||||
uint8 *VROM = NULL;
|
||||
uint8 *ExtraNTARAM = NULL;
|
||||
iNES_HEADER head;
|
||||
|
||||
CartInfo iNESCart;
|
||||
|
||||
uint8 Mirroring = 0;
|
||||
uint32 ROM_size = 0;
|
||||
uint32 VROM_size = 0;
|
||||
|
||||
static int CHRRAMSize = -1;
|
||||
static int iNES_Init(int num);
|
||||
|
||||
static int MapperNo = 0;
|
||||
|
||||
static DECLFR(TrainerRead) {
|
||||
return(trainerpoo[A & 0x1FF]);
|
||||
}
|
||||
|
||||
static void iNES_ExecPower() {
|
||||
if (iNESCart.Power)
|
||||
iNESCart.Power();
|
||||
|
||||
if (trainerpoo) {
|
||||
int x;
|
||||
for (x = 0; x < 512; x++) {
|
||||
X6502_DMW(0x7000 + x, trainerpoo[x]);
|
||||
if (X6502_DMR(0x7000 + x) != trainerpoo[x]) {
|
||||
SetReadHandler(0x7000, 0x71FF, TrainerRead);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iNESGI(int h) {
|
||||
switch (h) {
|
||||
case GI_RESETM2:
|
||||
if (iNESCart.Reset)
|
||||
iNESCart.Reset();
|
||||
break;
|
||||
case GI_POWER:
|
||||
iNES_ExecPower();
|
||||
break;
|
||||
case GI_CLOSE:
|
||||
{
|
||||
FCEU_SaveGameSave(&iNESCart);
|
||||
if (iNESCart.Close)
|
||||
iNESCart.Close();
|
||||
if (ROM) {
|
||||
free(ROM);
|
||||
ROM = NULL;
|
||||
}
|
||||
if (VROM) {
|
||||
free(VROM);
|
||||
VROM = NULL;
|
||||
}
|
||||
if (trainerpoo) {
|
||||
free(trainerpoo);
|
||||
trainerpoo = NULL;
|
||||
}
|
||||
if (ExtraNTARAM) {
|
||||
free(ExtraNTARAM);
|
||||
ExtraNTARAM = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 iNESGameCRC32 = 0;
|
||||
|
||||
struct CRCMATCH {
|
||||
uint32 crc;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct INPSEL {
|
||||
uint32 crc32;
|
||||
int input1;
|
||||
int input2;
|
||||
int inputfc;
|
||||
};
|
||||
|
||||
static void SetInput(void) {
|
||||
static struct INPSEL moo[] =
|
||||
{
|
||||
{0x19b0a9f1, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // 6-in-1 (MGC-023)(Unl)[!]
|
||||
{0x29de87af, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Aerobics Studio
|
||||
{0xd89e5a67, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid (J)
|
||||
{0x0f141525, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid 2(J)
|
||||
{0x32fb0583, SI_UNSET, SI_ARKANOID, SIFC_NONE }, // Arkanoid(NES)
|
||||
{0x60ad090a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Athletic World
|
||||
{0x48ca0ee1, SI_GAMEPAD, SI_GAMEPAD, SIFC_BWORLD }, // Barcode World
|
||||
{0x4318a2f8, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Barker Bill's Trick Shooting
|
||||
{0x6cca1c1f, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Dai Undoukai
|
||||
{0x24598791, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
|
||||
{0xd5d6eac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Edu (As)
|
||||
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Educational Computer 2000
|
||||
{0x8f7b1669, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // FP BASIC 3.3 by maxzhou88
|
||||
{0xf7606810, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.0A
|
||||
{0x895037bc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.1a
|
||||
{0xb2530afc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 3.0
|
||||
{0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Running Stadium
|
||||
{0xbba58be5, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Manhattan Police
|
||||
{0x3e58a87e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Freedom Force
|
||||
{0xd9f45be9, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ...
|
||||
{0x1545bd13, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ... 2
|
||||
{0x4e959173, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gotcha! - The Sport!
|
||||
{0xbeb8ab01, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gumshoe
|
||||
{0xff24d794, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Hogan's Alley
|
||||
{0x21f85681, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic (Gentei Ban)
|
||||
{0x980be936, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic
|
||||
{0x915a53a7, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Sports
|
||||
{0x9fae4d46, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong
|
||||
{0x7b44fb2a, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong 2
|
||||
{0x2f128512, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Jogging Race
|
||||
{0xbb33196f, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer
|
||||
{0x8587ee00, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer
|
||||
{0x543ab532, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Color Lines
|
||||
{0x368c19a8, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Study Cartridge
|
||||
{0x5ee6008e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Mechanized Attack
|
||||
{0x370ceb65, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Meiro Dai Sakusen
|
||||
{0x3a1694f9, SI_GAMEPAD, SI_GAMEPAD, SIFC_4PLAYER }, // Nekketsu Kakutou Densetsu
|
||||
{0x9d048ea4, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // Oeka Kids
|
||||
{0x2a6559a1, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf (J)
|
||||
{0xedc3662b, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf
|
||||
{0x912989dc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Playbox BASIC
|
||||
{0x9044550e, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Rairai Kyonshizu
|
||||
{0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Running Stadium
|
||||
{0x851eb9be, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Shooting Range
|
||||
{0x6435c095, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Short Order/Eggsplode
|
||||
{0xc043a8df, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Shu Xue Xiao Zhuan Yuan (Ch)
|
||||
{0x2cf5db05, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Zhi Li Xiao Zhuan Yuan (Ch)
|
||||
{0xad9c63e2, SI_GAMEPAD, SI_UNSET, SIFC_SHADOW }, // Space Shadow
|
||||
{0x61d86167, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Street Cop
|
||||
{0xabb2f974, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Study and Game 32-in-1
|
||||
{0x41ef9ac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor
|
||||
{0x8b265862, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor
|
||||
{0x82f1fb96, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor 1.0 Russian
|
||||
{0x9f8f200a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Super Mogura Tataki!! - Pokkun Moguraa
|
||||
{0xd74b2719, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Super Team Games
|
||||
{0x74bea652, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Supergun 3-in-1
|
||||
{0x5e073a1b, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Supor English (Chinese)
|
||||
{0x589b6b0d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV20
|
||||
{0x41401c6d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV40
|
||||
{0x23d17f5e, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // The Lone Ranger
|
||||
{0xc3c0811d, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // The two "Oeka Kids" games
|
||||
{0xde8fd935, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // To the Earth
|
||||
{0x47232739, SI_GAMEPAD, SI_GAMEPAD, SIFC_TOPRIDER }, // Top Rider
|
||||
{0x8a12a7d9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Totsugeki Fuuun Takeshi Jou
|
||||
{0xb8b9aca3, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
|
||||
{0x5112dc21, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
|
||||
{0xaf4010ea, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // World Class Track Meet
|
||||
{0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET }
|
||||
};
|
||||
int x = 0;
|
||||
|
||||
while (moo[x].input1 >= 0 || moo[x].input2 >= 0 || moo[x].inputfc >= 0) {
|
||||
if (moo[x].crc32 == iNESGameCRC32) {
|
||||
GameInfo->input[0] = moo[x].input1;
|
||||
GameInfo->input[1] = moo[x].input2;
|
||||
GameInfo->inputfc = moo[x].inputfc;
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
#define INESB_INCOMPLETE 1
|
||||
#define INESB_CORRUPT 2
|
||||
#define INESB_HACKED 4
|
||||
|
||||
struct BADINF {
|
||||
uint64 md5partial;
|
||||
uint8 *name;
|
||||
uint32 type;
|
||||
};
|
||||
|
||||
static struct BADINF BadROMImages[] =
|
||||
{
|
||||
#include "ines-bad.h"
|
||||
};
|
||||
|
||||
void CheckBad(uint64 md5partial) {
|
||||
int32 x = 0;
|
||||
while (BadROMImages[x].name) {
|
||||
if (BadROMImages[x].md5partial == md5partial) {
|
||||
FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly in FCE Ultra.", BadROMImages[x].name);
|
||||
return;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct CHINF {
|
||||
uint32 crc32;
|
||||
int32 mapper;
|
||||
int32 mirror;
|
||||
};
|
||||
|
||||
static void CheckHInfo(void) {
|
||||
/* ROM images that have the battery-backed bit set in the header that really
|
||||
don't have battery-backed RAM is not that big of a problem, so I'll
|
||||
treat this differently by only listing games that should have battery-backed RAM.
|
||||
|
||||
Lower 64 bits of the MD5 hash.
|
||||
*/
|
||||
|
||||
static uint64 savie[] =
|
||||
{
|
||||
0xc04361e499748382LL, /* AD&D Heroes of the Lance */
|
||||
0xb72ee2337ced5792LL, /* AD&D Hillsfar */
|
||||
0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */
|
||||
0x498c10dc463cfe95LL, /* Battle Fleet */
|
||||
0x854d7947a3177f57LL, /* Crystalis */
|
||||
0x4a1f5336b86851b6LL, /* DW */
|
||||
0xb0bcc02c843c1b79LL, /* DW */
|
||||
0x2dcf3a98c7937c22LL, /* DW 2 */
|
||||
0x98e55e09dfcc7533LL, /* DW 4*/
|
||||
0x733026b6b72f2470LL, /* Dw 3 */
|
||||
0x6917ffcaca2d8466LL, /* Famista '90 */
|
||||
0x8da46db592a1fcf4LL, /* Faria */
|
||||
0xedba17a2c4608d20LL, /* Final Fantasy */
|
||||
0x91a6846d3202e3d6LL, /* Final Fantasy */
|
||||
0x012df596e2b31174LL, /* Final Fantasy 1+2 */
|
||||
0xf6b359a720549ecdLL, /* Final Fantasy 2 */
|
||||
0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */
|
||||
0xd63dcc68c2b20adcLL, /* Final Fantasy J */
|
||||
0x2ee3417ba8b69706LL, /* Hydlide 3*/
|
||||
0xebbce5a54cf3ecc0LL, /* Justbreed */
|
||||
0x6a858da551ba239eLL, /* Kaijuu Monogatari */
|
||||
0x2db8f5d16c10b925LL, /* Kyonshiizu 2 */
|
||||
0x04a31647de80fdabLL, /* Legend of Zelda */
|
||||
0x94b9484862a26cbaLL, /* Legend of Zelda */
|
||||
0xa40666740b7d22feLL, /* Mindseeker */
|
||||
0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */
|
||||
0x77b811b2760104b9LL, /* Mouryou Senki Madara */
|
||||
0x11b69122efe86e8cLL, /* RPG Jinsei Game */
|
||||
0x9aa1dc16c05e7de5LL, /* Startropics */
|
||||
0x1b084107d0878bd0LL, /* Startropics 2*/
|
||||
0xa70b495314f4d075LL, /* Ys 3 */
|
||||
0x836c0ff4f3e06e45LL, /* Zelda 2 */
|
||||
0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */
|
||||
};
|
||||
|
||||
static struct CHINF moo[] =
|
||||
{
|
||||
#include "ines-correct.h"
|
||||
};
|
||||
int32 tofix = 0, x;
|
||||
uint64 partialmd5 = 0;
|
||||
|
||||
for (x = 0; x < 8; x++)
|
||||
partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8);
|
||||
CheckBad(partialmd5);
|
||||
|
||||
x = 0;
|
||||
do {
|
||||
if (moo[x].crc32 == iNESGameCRC32) {
|
||||
if (moo[x].mapper >= 0) {
|
||||
if (moo[x].mapper & 0x800 && VROM_size) {
|
||||
VROM_size = 0;
|
||||
free(VROM);
|
||||
VROM = NULL;
|
||||
tofix |= 8;
|
||||
}
|
||||
if (MapperNo != (moo[x].mapper & 0xFF)) {
|
||||
tofix |= 1;
|
||||
MapperNo = moo[x].mapper & 0xFF;
|
||||
}
|
||||
}
|
||||
if (moo[x].mirror >= 0) {
|
||||
if (moo[x].mirror == 8) {
|
||||
if (Mirroring == 2) { /* Anything but hard-wired(four screen). */
|
||||
tofix |= 2;
|
||||
Mirroring = 0;
|
||||
}
|
||||
} else if (Mirroring != moo[x].mirror) {
|
||||
if (Mirroring != (moo[x].mirror & ~4))
|
||||
if ((moo[x].mirror & ~4) <= 2) /* Don't complain if one-screen mirroring
|
||||
needs to be set(the iNES header can't
|
||||
hold this information).
|
||||
*/
|
||||
tofix |= 2;
|
||||
Mirroring = moo[x].mirror;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
} while (moo[x].mirror >= 0 || moo[x].mapper >= 0);
|
||||
|
||||
x = 0;
|
||||
while (savie[x] != 0) {
|
||||
if (savie[x] == partialmd5) {
|
||||
if (!(head.ROM_type & 2)) {
|
||||
tofix |= 4;
|
||||
head.ROM_type |= 2;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
/* Games that use these iNES mappers tend to have the four-screen bit set
|
||||
when it should not be.
|
||||
*/
|
||||
if ((MapperNo == 118 || MapperNo == 24 || MapperNo == 26) && (Mirroring == 2)) {
|
||||
Mirroring = 0;
|
||||
tofix |= 2;
|
||||
}
|
||||
|
||||
/* Four-screen mirroring implicitly set. */
|
||||
if (MapperNo == 99)
|
||||
Mirroring = 2;
|
||||
|
||||
if (tofix) {
|
||||
char gigastr[768];
|
||||
strcpy(gigastr, "The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
|
||||
if (tofix & 1)
|
||||
sprintf(gigastr + strlen(gigastr), "The mapper number should be set to %d. ", MapperNo);
|
||||
if (tofix & 2) {
|
||||
uint8 *mstr[3] = { "Horizontal", "Vertical", "Four-screen" };
|
||||
sprintf(gigastr + strlen(gigastr), "Mirroring should be set to \"%s\". ", mstr[Mirroring & 3]);
|
||||
}
|
||||
if (tofix & 4)
|
||||
strcat(gigastr, "The battery-backed bit should be set. ");
|
||||
if (tofix & 8)
|
||||
strcat(gigastr, "This game should not have any CHR ROM. ");
|
||||
strcat(gigastr, "\n");
|
||||
FCEU_printf("%s", gigastr);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32 mapper;
|
||||
void (*init)(CartInfo *);
|
||||
} NewMI;
|
||||
|
||||
typedef struct {
|
||||
uint8 *name;
|
||||
int32 number;
|
||||
void (*init)(CartInfo *);
|
||||
} BMAPPINGLocal;
|
||||
|
||||
static BMAPPINGLocal bmap[] = {
|
||||
{"NROM", 0, NROM_Init},
|
||||
{"MMC1", 1, Mapper1_Init},
|
||||
{"UNROM", 2, UNROM_Init},
|
||||
{"CNROM", 3, CNROM_Init},
|
||||
{"MMC3", 4, Mapper4_Init},
|
||||
{"MMC5", 5, Mapper5_Init},
|
||||
{"FFE Rev. A", 6, Mapper6_Init},
|
||||
{"ANROM", 7, ANROM_Init},
|
||||
{"", 8, Mapper8_Init}, // Nogaems, it's worthless
|
||||
{"MMC2", 9, Mapper9_Init},
|
||||
{"MMC4", 10, Mapper10_Init},
|
||||
{"Color Dreams", 11, Mapper11_Init},
|
||||
{"REX DBZ 5", 12, Mapper12_Init},
|
||||
{"CPROM", 13, CPROM_Init},
|
||||
{"REX SL-1632", 14, UNLSL1632_Init},
|
||||
{"100-in-1", 15, Mapper15_Init},
|
||||
{"BANDAI 24C02", 16, Mapper16_Init},
|
||||
{"FFE Rev. B", 17, Mapper17_Init},
|
||||
{"JALECO SS880006", 18, Mapper18_Init}, // JF-NNX (EB89018-30007) boards
|
||||
{"Namcot 106", 19, Mapper19_Init},
|
||||
// {"", 20, Mapper20_Init},
|
||||
{"Konami VRC2/VRC4 A", 21, Mapper21_Init},
|
||||
{"Konami VRC2/VRC4 B", 22, Mapper22_Init},
|
||||
{"Konami VRC2/VRC4 C", 23, Mapper23_Init},
|
||||
{"Konami VRC6 Rev. A", 24, Mapper24_Init},
|
||||
{"Konami VRC2/VRC4 D", 25, Mapper25_Init},
|
||||
{"Konami VRC6 Rev. B", 26, Mapper26_Init},
|
||||
{"CC-21 MI HUN CHE", 27, UNLCC21_Init}, // Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards
|
||||
// {"", 28, Mapper28_Init}, // Custom Multidiscrete mapper for PDs
|
||||
// {"", 29, Mapper29_Init},
|
||||
// {"", 30, Mapper30_Init},
|
||||
// {"", 31, Mapper31_Init},
|
||||
{"IREM G-101", 32, Mapper32_Init},
|
||||
{"TC0190FMC/TC0350FMR", 33, Mapper33_Init},
|
||||
{"IREM I-IM/BNROM", 34, Mapper34_Init},
|
||||
{"Wario Land 2", 35, UNLSC127_Init},
|
||||
{"TXC Policeman", 36, Mapper36_Init},
|
||||
{"PAL-ZZ SMB/TETRIS/NWC",37, Mapper37_Init},
|
||||
{"Bit Corp.", 38, Mapper38_Init}, // Crime Busters
|
||||
// {"", 39, Mapper39_Init},
|
||||
{"SMB2j FDS", 40, Mapper40_Init},
|
||||
{"CALTRON 6-in-1", 41, Mapper41_Init},
|
||||
{"BIO MIRACLE FDS", 42, Mapper42_Init},
|
||||
{"FDS SMB2j LF36", 43, Mapper43_Init},
|
||||
{"MMC3 BMC PIRATE A", 44, Mapper44_Init},
|
||||
{"MMC3 BMC PIRATE B", 45, Mapper45_Init},
|
||||
{"RUMBLESTATION 15-in-1",46, Mapper46_Init},
|
||||
{"NES-QJ SSVB/NWC", 47, Mapper47_Init},
|
||||
{"TAITO TCxxx", 48, Mapper48_Init},
|
||||
{"MMC3 BMC PIRATE C", 49, Mapper49_Init},
|
||||
{"SMB2j FDS Rev. A", 50, Mapper50_Init},
|
||||
{"11-in-1 BALL SERIES", 51, Mapper51_Init}, // 1993 year version
|
||||
{"MMC3 BMC PIRATE D", 52, Mapper52_Init},
|
||||
{"SUPERVISION 16-in-1", 53, Supervision16_Init},
|
||||
// {"", 54, Mapper54_Init},
|
||||
// {"", 55, Mapper55_Init},
|
||||
// {"", 56, Mapper56_Init},
|
||||
{"SIMBPLE BMC PIRATE A", 57, Mapper57_Init},
|
||||
{"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init},
|
||||
{"", 59, Mapper59_Init}, // Check this out
|
||||
{"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init},
|
||||
{"20-in-1 KAISER Rev. A",61, Mapper61_Init},
|
||||
{"700-in-1", 62, Mapper62_Init},
|
||||
// {"", 63, Mapper63_Init},
|
||||
{"TENGEN RAMBO1", 64, Mapper64_Init},
|
||||
{"IREM-H3001", 65, Mapper65_Init},
|
||||
{"MHROM", 66, MHROM_Init},
|
||||
{"SUNSOFT-FZII", 67, Mapper67_Init},
|
||||
{"Sunsoft Mapper #4", 68, Mapper68_Init},
|
||||
{"SUNSOFT-5/FME-7", 69, Mapper69_Init},
|
||||
{"BA KAMEN DISCRETE", 70, Mapper70_Init},
|
||||
{"CAMERICA BF9093", 71, Mapper71_Init},
|
||||
{"JALECO JF-17", 72, Mapper72_Init},
|
||||
{"KONAMI VRC3", 73, Mapper73_Init},
|
||||
{"TW MMC3+VRAM Rev. A", 74, Mapper74_Init},
|
||||
{"KONAMI VRC1", 75, Mapper75_Init},
|
||||
{"NAMCOT 108 Rev. A", 76, Mapper76_Init},
|
||||
{"IREM LROG017", 77, Mapper77_Init},
|
||||
{"Irem 74HC161/32", 78, Mapper78_Init},
|
||||
{"AVE/C&E/TXC BOARD", 79, Mapper79_Init},
|
||||
{"TAITO X1-005 Rev. A", 80, Mapper80_Init},
|
||||
// {"", 81, Mapper81_Init},
|
||||
{"TAITO X1-017", 82, Mapper82_Init},
|
||||
{"YOKO VRC Rev. B", 83, Mapper83_Init},
|
||||
// {"", 84, Mapper84_Init},
|
||||
{"KONAMI VRC7", 85, Mapper85_Init},
|
||||
{"JALECO JF-13", 86, Mapper86_Init},
|
||||
{"74*139/74 DISCRETE", 87, Mapper87_Init},
|
||||
{"NAMCO 3433", 88, Mapper88_Init},
|
||||
{"SUNSOFT-3", 89, Mapper89_Init}, // SUNSOFT-2 mapper
|
||||
{"HUMMER/JY BOARD", 90, Mapper90_Init},
|
||||
{"EARLY HUMMER/JY BOARD",91, Mapper91_Init},
|
||||
{"JALECO JF-19", 92, Mapper92_Init},
|
||||
{"SUNSOFT-3R", 93, SUNSOFT_UNROM_Init},// SUNSOFT-2 mapper with VRAM, different wiring
|
||||
{"HVC-UN1ROM", 94, Mapper94_Init},
|
||||
{"NAMCOT 108 Rev. B", 95, Mapper95_Init},
|
||||
{"BANDAI OEKAKIDS", 96, Mapper96_Init},
|
||||
{"IREM TAM-S1", 97, Mapper97_Init},
|
||||
// {"", 98, Mapper98_Init},
|
||||
{"VS Uni/Dual- system", 99, Mapper99_Init},
|
||||
// {"", 100, Mapper100_Init},
|
||||
{"", 101, Mapper101_Init},
|
||||
// {"", 102, Mapper102_Init},
|
||||
{"FDS DOKIDOKI FULL", 103, Mapper103_Init},
|
||||
// {"", 104, Mapper104_Init},
|
||||
{"NES-EVENT NWC1990", 105, Mapper105_Init},
|
||||
{"SMB3 PIRATE A", 106, Mapper106_Init},
|
||||
{"MAGIC CORP A", 107, Mapper107_Init},
|
||||
{"FDS UNROM BOARD", 108, Mapper108_Init},
|
||||
// {"", 109, Mapper109_Init},
|
||||
// {"", 110, Mapper110_Init},
|
||||
// {"", 111, Mapper111_Init},
|
||||
{"ASDER/NTDEC BOARD", 112, Mapper112_Init},
|
||||
{"HACKER/SACHEN BOARD", 113, Mapper113_Init},
|
||||
{"MMC3 SG PROT. A", 114, Mapper114_Init},
|
||||
{"MMC3 PIRATE A", 115, Mapper115_Init},
|
||||
{"MMC1/MMC3/VRC PIRATE",116, UNLSL12_Init},
|
||||
{"FUTURE MEDIA BOARD", 117, Mapper117_Init},
|
||||
{"TSKROM", 118, TKSROM_Init},
|
||||
{"NES-TQROM", 119, Mapper119_Init},
|
||||
{"FDS TOBIDASE", 120, Mapper120_Init},
|
||||
{"MMC3 PIRATE PROT. A", 121, Mapper121_Init},
|
||||
// {"", 122, Mapper122_Init},
|
||||
{"MMC3 PIRATE H2288", 123, UNLH2288_Init},
|
||||
// {"", 124, Mapper124_Init},
|
||||
{"FDS LH32", 125, LH32_Init},
|
||||
// {"", 126, Mapper126_Init},
|
||||
// {"", 127, Mapper127_Init},
|
||||
// {"", 128, Mapper128_Init},
|
||||
// {"", 129, Mapper129_Init},
|
||||
// {"", 130, Mapper130_Init},
|
||||
// {"", 131, Mapper131_Init},
|
||||
{"TXC/MGENIUS 22111", 132, UNL22211_Init},
|
||||
{"SA72008", 133, SA72008_Init},
|
||||
{"MMC3 BMC PIRATE", 134, Mapper134_Init},
|
||||
// {"", 135, Mapper135_Init},
|
||||
{"TCU02", 136, TCU02_Init},
|
||||
{"S8259D", 137, S8259D_Init},
|
||||
{"S8259B", 138, S8259B_Init},
|
||||
{"S8259C", 139, S8259C_Init},
|
||||
{"JALECO JF-11/14", 140, Mapper140_Init},
|
||||
{"S8259A", 141, S8259A_Init},
|
||||
{"UNLKS7032", 142, UNLKS7032_Init},
|
||||
{"TCA01", 143, TCA01_Init},
|
||||
{"AGCI 50282", 144, Mapper144_Init},
|
||||
{"SA72007", 145, SA72007_Init},
|
||||
{"SA0161M", 146, SA0161M_Init},
|
||||
{"TCU01", 147, TCU01_Init},
|
||||
{"SA0037", 148, SA0037_Init},
|
||||
{"SA0036", 149, SA0036_Init},
|
||||
{"S74LS374N", 150, S74LS374N_Init},
|
||||
{"", 151, Mapper151_Init},
|
||||
{"", 152, Mapper152_Init},
|
||||
{"BANDAI SRAM", 153, Mapper153_Init}, // Bandai board 16 with SRAM instead of EEPROM
|
||||
{"", 154, Mapper154_Init},
|
||||
{"", 155, Mapper155_Init},
|
||||
{"", 156, Mapper156_Init},
|
||||
{"BANDAI BARCODE", 157, Mapper157_Init},
|
||||
// {"", 158, Mapper158_Init},
|
||||
{"BANDAI 24C01", 159, Mapper159_Init}, // Different type of EEPROM on the bandai board
|
||||
{"SA009", 160, SA009_Init},
|
||||
// {"", 161, Mapper161_Init},
|
||||
{"", 162, UNLFS304_Init},
|
||||
{"", 163, Mapper163_Init},
|
||||
{"", 164, Mapper164_Init},
|
||||
{"", 165, Mapper165_Init},
|
||||
{"SUBOR Rev. A", 166, Mapper166_Init},
|
||||
{"SUBOR Rev. B", 167, Mapper167_Init},
|
||||
{"", 168, Mapper168_Init},
|
||||
// {"", 169, Mapper169_Init},
|
||||
{"", 170, Mapper170_Init},
|
||||
{"", 171, Mapper171_Init},
|
||||
{"", 172, Mapper172_Init},
|
||||
{"", 173, Mapper173_Init},
|
||||
// {"", 174, Mapper174_Init},
|
||||
{"", 175, Mapper175_Init},
|
||||
{"BMCFK23C", 176, BMCFK23C_Init}, // zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance ????. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it.
|
||||
{"", 177, Mapper177_Init},
|
||||
{"", 178, Mapper178_Init},
|
||||
// {"", 179, Mapper179_Init},
|
||||
{"", 180, Mapper180_Init},
|
||||
{"", 181, Mapper181_Init},
|
||||
// {"", 182, Mapper182_Init}, // Deprecated, dupe
|
||||
{"", 183, Mapper183_Init},
|
||||
{"", 184, Mapper184_Init},
|
||||
{"", 185, Mapper185_Init},
|
||||
{"", 186, Mapper186_Init},
|
||||
{"", 187, Mapper187_Init},
|
||||
{"", 188, Mapper188_Init},
|
||||
{"", 189, Mapper189_Init},
|
||||
// {"", 190, Mapper190_Init},
|
||||
{"", 191, Mapper191_Init},
|
||||
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
|
||||
{"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf
|
||||
{"TW MMC3+VRAM Rev. C", 194, Mapper194_Init},
|
||||
{"TW MMC3+VRAM Rev. D", 195, Mapper195_Init},
|
||||
{"", 196, Mapper196_Init},
|
||||
{"", 197, Mapper197_Init},
|
||||
{"TW MMC3+VRAM Rev. E", 198, Mapper198_Init},
|
||||
{"", 199, Mapper199_Init},
|
||||
{"", 200, Mapper200_Init},
|
||||
{"", 201, Mapper201_Init},
|
||||
{"", 202, Mapper202_Init},
|
||||
{"", 203, Mapper203_Init},
|
||||
{"", 204, Mapper204_Init},
|
||||
{"", 205, Mapper205_Init},
|
||||
{"NAMCOT 108 Rev. C", 206, Mapper206_Init}, // Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3
|
||||
{"TAITO X1-005 Rev. B", 207, Mapper207_Init},
|
||||
{"", 208, Mapper208_Init},
|
||||
{"", 209, Mapper209_Init},
|
||||
{"", 210, Mapper210_Init},
|
||||
{"", 211, Mapper211_Init},
|
||||
{"", 212, Mapper212_Init},
|
||||
{"", 213, Mapper213_Init},
|
||||
{"", 214, Mapper214_Init},
|
||||
{"", 215, UNL8237_Init},
|
||||
{"", 216, Mapper216_Init},
|
||||
{"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper
|
||||
// {"", 218, Mapper218_Init},
|
||||
{"UNLA9746", 219, UNLA9746_Init},
|
||||
{"Debug Mapper", 220, UNLPEC586Init}, // UNLKS7057_Init},
|
||||
{"UNLN625092", 221, UNLN625092_Init},
|
||||
{"", 222, Mapper222_Init},
|
||||
// {"", 223, Mapper223_Init},
|
||||
// {"", 224, Mapper224_Init},
|
||||
{"", 225, Mapper225_Init},
|
||||
{"BMC 22+20-in-1", 226, Mapper226_Init},
|
||||
{"", 227, Mapper227_Init},
|
||||
{"", 228, Mapper228_Init},
|
||||
{"", 229, Mapper229_Init},
|
||||
{"BMC Contra+22-in-1", 230, Mapper230_Init},
|
||||
{"", 231, Mapper231_Init},
|
||||
{"BMC QUATTRO", 232, Mapper232_Init},
|
||||
{"BMC 22+20-in-1 RST", 233, Mapper233_Init},
|
||||
{"BMC MAXI", 234, Mapper234_Init},
|
||||
{"", 235, Mapper235_Init},
|
||||
// {"", 236, Mapper236_Init},
|
||||
// {"", 237, Mapper237_Init},
|
||||
{"UNL6035052", 238, UNL6035052_Init},
|
||||
// {"", 239, Mapper239_Init},
|
||||
{"", 240, Mapper240_Init},
|
||||
{"", 241, Mapper241_Init},
|
||||
{"", 242, Mapper242_Init},
|
||||
{"S74LS374NA", 243, S74LS374NA_Init},
|
||||
{"DECATHLON", 244, Mapper244_Init},
|
||||
{"", 245, Mapper245_Init},
|
||||
{"FONG SHEN BANG", 246, Mapper246_Init},
|
||||
// {"", 247, Mapper247_Init},
|
||||
// {"", 248, Mapper248_Init},
|
||||
{"", 249, Mapper249_Init},
|
||||
{"", 250, Mapper250_Init},
|
||||
// {"", 251, Mapper251_Init}, // No good dumps for this mapper, use UNIF version
|
||||
{"SAN GUO ZHI PIRATE", 252, Mapper252_Init},
|
||||
{"DRAGON BALL PIRATE", 253, Mapper253_Init},
|
||||
{"", 254, Mapper254_Init},
|
||||
// {"", 255, Mapper255_Init}, // No good dumps for this mapper
|
||||
{"", 0, NULL}
|
||||
};
|
||||
|
||||
int iNESLoad(const char *name, FCEUFILE *fp) {
|
||||
struct md5_context md5;
|
||||
char* mappername;
|
||||
uint32 mappertest;
|
||||
|
||||
if (FCEU_fread(&head, 1, 16, fp) != 16)
|
||||
return 0;
|
||||
|
||||
if (memcmp(&head, "NES\x1a", 4))
|
||||
return 0;
|
||||
|
||||
memset(&iNESCart, 0, sizeof(iNESCart));
|
||||
|
||||
if (!memcmp((char*)(&head) + 0x7, "DiskDude", 8)) {
|
||||
memset((char*)(&head) + 0x7, 0, 0x9);
|
||||
}
|
||||
|
||||
if (!memcmp((char*)(&head) + 0x7, "demiforce", 9)) {
|
||||
memset((char*)(&head) + 0x7, 0, 0x9);
|
||||
}
|
||||
|
||||
if (!memcmp((char*)(&head) + 0xA, "Ni03", 4)) {
|
||||
if (!memcmp((char*)(&head) + 0x7, "Dis", 3))
|
||||
memset((char*)(&head) + 0x7, 0, 0x9);
|
||||
else
|
||||
memset((char*)(&head) + 0xA, 0, 0x6);
|
||||
}
|
||||
|
||||
MapperNo = (head.ROM_type >> 4);
|
||||
MapperNo |= (head.ROM_type2 & 0xF0);
|
||||
if (head.ROM_type & 8) {
|
||||
Mirroring = 2;
|
||||
} else
|
||||
Mirroring = (head.ROM_type & 1);
|
||||
|
||||
if (!head.ROM_size)
|
||||
ROM_size = 256;
|
||||
else
|
||||
ROM_size = uppow2(head.ROM_size);
|
||||
|
||||
VROM_size = uppow2(head.VROM_size);
|
||||
|
||||
|
||||
if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL)
|
||||
return 0;
|
||||
memset(ROM, 0xFF, ROM_size << 14);
|
||||
|
||||
if (VROM_size) {
|
||||
if ((VROM = (uint8*)FCEU_malloc(VROM_size << 13)) == NULL) {
|
||||
free(ROM);
|
||||
ROM = NULL;
|
||||
return 0;
|
||||
}
|
||||
memset(VROM, 0xFF, VROM_size << 13);
|
||||
}
|
||||
|
||||
if (head.ROM_type & 4) { /* Trainer */
|
||||
trainerpoo = (uint8*)FCEU_gmalloc(512);
|
||||
FCEU_fread(trainerpoo, 512, 1, fp);
|
||||
}
|
||||
|
||||
ResetCartMapping();
|
||||
ResetExState(0, 0);
|
||||
|
||||
SetupCartPRGMapping(0, ROM, ROM_size << 14, 0);
|
||||
|
||||
if (head.ROM_size)
|
||||
FCEU_fread(ROM, 0x4000, head.ROM_size, fp);
|
||||
else
|
||||
FCEU_fread(ROM, 0x4000, ROM_size, fp);
|
||||
|
||||
if (VROM_size)
|
||||
FCEU_fread(VROM, 0x2000, VROM_size, fp);
|
||||
|
||||
md5_starts(&md5);
|
||||
md5_update(&md5, ROM, ROM_size << 14);
|
||||
|
||||
iNESGameCRC32 = CalcCRC32(0, ROM, ROM_size << 14);
|
||||
|
||||
if (VROM_size) {
|
||||
iNESGameCRC32 = CalcCRC32(iNESGameCRC32, VROM, VROM_size << 13);
|
||||
md5_update(&md5, VROM, VROM_size << 13);
|
||||
}
|
||||
md5_finish(&md5, iNESCart.MD5);
|
||||
memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5));
|
||||
|
||||
iNESCart.CRC32 = iNESGameCRC32;
|
||||
|
||||
FCEU_printf(" PRG ROM: %3d x 16KiB\n", ROM_size);
|
||||
FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size);
|
||||
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
|
||||
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5));
|
||||
mappername = "Not Listed";
|
||||
|
||||
for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
|
||||
if (bmap[mappertest].number == MapperNo) {
|
||||
mappername = bmap[mappertest].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FCEU_printf(" Mapper #: %d\n", MapperNo);
|
||||
FCEU_printf(" Mapper name: %s\n", mappername);
|
||||
FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal");
|
||||
FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No");
|
||||
FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No");
|
||||
|
||||
SetInput();
|
||||
CheckHInfo();
|
||||
{
|
||||
int x;
|
||||
uint64 partialmd5 = 0;
|
||||
|
||||
for (x = 0; x < 8; x++) {
|
||||
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
|
||||
}
|
||||
|
||||
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
|
||||
}
|
||||
/* Must remain here because above functions might change value of
|
||||
VROM_size and free(VROM).
|
||||
*/
|
||||
if (VROM_size)
|
||||
SetupCartCHRMapping(0, VROM, VROM_size * 0x2000, 0);
|
||||
|
||||
if (Mirroring == 2) {
|
||||
ExtraNTARAM = (uint8*)FCEU_gmalloc(2048);
|
||||
SetupCartMirroring(4, 1, ExtraNTARAM);
|
||||
} else if (Mirroring >= 0x10)
|
||||
SetupCartMirroring(2 + (Mirroring & 1), 1, 0);
|
||||
else
|
||||
SetupCartMirroring(Mirroring & 1, (Mirroring & 4) >> 2, 0);
|
||||
|
||||
iNESCart.battery = (head.ROM_type & 2) ? 1 : 0;
|
||||
iNESCart.mirror = Mirroring;
|
||||
|
||||
if (!iNES_Init(MapperNo))
|
||||
FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo);
|
||||
|
||||
FCEU_LoadGameSave(&iNESCart);
|
||||
|
||||
GameInterface = iNESGI;
|
||||
FCEU_printf("\n");
|
||||
|
||||
if (strstr(name, "(E)") || strstr(name, "(e)")
|
||||
|| strstr(name, "(Europe)") || strstr(name, "(PAL)")
|
||||
|| strstr(name, "(F)") || strstr(name, "(f)")
|
||||
|| strstr(name, "(G)") || strstr(name, "(g)")
|
||||
|| strstr(name, "(I)") || strstr(name, "(i)"))
|
||||
GameInfo->vidsys = GIV_PAL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int iNES_Init(int num) {
|
||||
BMAPPINGLocal *tmp = bmap;
|
||||
|
||||
CHRRAMSize = -1;
|
||||
|
||||
if (GameInfo->type == GIT_VSUNI)
|
||||
AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
|
||||
|
||||
while (tmp->init) {
|
||||
if (num == tmp->number) {
|
||||
UNIFchrrama = 0; // need here for compatibility with UNIF mapper code
|
||||
if (!VROM_size) {
|
||||
switch (num) { // FIXME, mapper or game data base with the board parameters and ROM/RAM sizes
|
||||
case 13: CHRRAMSize = 16 * 1024; break;
|
||||
case 6:
|
||||
case 96: CHRRAMSize = 32 * 1024; break;
|
||||
case 176: CHRRAMSize = 256 * 1024; break;
|
||||
default: CHRRAMSize = 8 * 1024; break;
|
||||
}
|
||||
if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0;
|
||||
UNIFchrrama = VROM;
|
||||
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
|
||||
AddExState(VROM, CHRRAMSize, 0, "CHRR");
|
||||
}
|
||||
if (head.ROM_type & 8)
|
||||
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
|
||||
tmp->init(&iNESCart);
|
||||
return 1;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
618
src/drivers/libretro/fceu/unif.c
Normal file
618
src/drivers/libretro/fceu/unif.c
Normal file
@@ -0,0 +1,618 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* TODO: Battery backup file saving, mirror force */
|
||||
/* **INCOMPLETE** */
|
||||
/* Override stuff: CHR RAM instead of CHR ROM, mirroring. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "fceu-types.h"
|
||||
#include "fceu.h"
|
||||
#include "cart.h"
|
||||
#include "unif.h"
|
||||
#include "ines.h"
|
||||
#include "general.h"
|
||||
#include "state.h"
|
||||
#include "fceu-endian.h"
|
||||
#include "file.h"
|
||||
#include "fceu-memory.h"
|
||||
#include "input.h"
|
||||
#include "md5.h"
|
||||
|
||||
typedef struct {
|
||||
char ID[4];
|
||||
uint32 info;
|
||||
} UNIF_HEADER;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
void (*init)(CartInfo *);
|
||||
int flags;
|
||||
} BMAPPING;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*init)(FCEUFILE *fp);
|
||||
} BFMAPPING;
|
||||
|
||||
CartInfo UNIFCart;
|
||||
|
||||
static int vramo;
|
||||
static int mirrortodo;
|
||||
static uint8 *boardname;
|
||||
static uint8 *sboardname;
|
||||
|
||||
static uint32 CHRRAMSize;
|
||||
uint8 *UNIFchrrama = 0;
|
||||
|
||||
static UNIF_HEADER unhead;
|
||||
static UNIF_HEADER uchead;
|
||||
|
||||
|
||||
static uint8 *malloced[32];
|
||||
static uint32 mallocedsizes[32];
|
||||
|
||||
static int FixRomSize(uint32 size, uint32 minimum) {
|
||||
uint32 x = 1;
|
||||
|
||||
if (size < minimum)
|
||||
return minimum;
|
||||
while (x < size)
|
||||
x <<= 1;
|
||||
return x;
|
||||
}
|
||||
|
||||
static void FreeUNIF(void) {
|
||||
int x;
|
||||
if (UNIFchrrama) {
|
||||
free(UNIFchrrama); UNIFchrrama = 0;
|
||||
}
|
||||
if (boardname) {
|
||||
free(boardname); boardname = 0;
|
||||
}
|
||||
for (x = 0; x < 32; x++) {
|
||||
if (malloced[x]) {
|
||||
free(malloced[x]); malloced[x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetUNIF(void) {
|
||||
int x;
|
||||
for (x = 0; x < 32; x++)
|
||||
malloced[x] = 0;
|
||||
vramo = 0;
|
||||
boardname = 0;
|
||||
mirrortodo = 0;
|
||||
memset(&UNIFCart, 0, sizeof(UNIFCart));
|
||||
UNIFchrrama = 0;
|
||||
}
|
||||
|
||||
static uint8 exntar[2048];
|
||||
|
||||
static void MooMirroring(void) {
|
||||
if (mirrortodo < 0x4)
|
||||
SetupCartMirroring(mirrortodo, 1, 0);
|
||||
else if (mirrortodo == 0x4) {
|
||||
SetupCartMirroring(4, 1, exntar);
|
||||
AddExState(exntar, 2048, 0, "EXNR");
|
||||
} else
|
||||
SetupCartMirroring(0, 0, 0);
|
||||
}
|
||||
|
||||
static int DoMirroring(FCEUFILE *fp) {
|
||||
int t;
|
||||
uint32 i;
|
||||
if (uchead.info == 1) {
|
||||
if ((t = FCEU_fgetc(fp)) == EOF)
|
||||
return(0);
|
||||
mirrortodo = t;
|
||||
{
|
||||
static char *stuffo[6] = { "Horizontal", "Vertical", "$2000", "$2400", "\"Four-screen\"", "Controlled by Mapper Hardware" };
|
||||
if (t < 6)
|
||||
FCEU_printf(" Name/Attribute Table Mirroring: %s\n", stuffo[t]);
|
||||
}
|
||||
} else {
|
||||
FCEU_printf(" Incorrect Mirroring Chunk Size (%d). Data is:", uchead.info);
|
||||
for (i = 0; i < uchead.info; i++) {
|
||||
if ((t = FCEU_fgetc(fp)) == EOF)
|
||||
return(0);
|
||||
FCEU_printf(" %02x", t);
|
||||
}
|
||||
FCEU_printf("\n Default Name/Attribute Table Mirroring: Horizontal\n", uchead.info);
|
||||
mirrortodo = 0;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int NAME(FCEUFILE *fp) {
|
||||
char namebuf[100];
|
||||
int index;
|
||||
int t;
|
||||
|
||||
FCEU_printf(" Name: ");
|
||||
index = 0;
|
||||
|
||||
while ((t = FCEU_fgetc(fp)) > 0)
|
||||
if (index < 99)
|
||||
namebuf[index++] = t;
|
||||
|
||||
namebuf[index] = 0;
|
||||
FCEU_printf("%s\n", namebuf);
|
||||
|
||||
if (!GameInfo->name) {
|
||||
GameInfo->name = malloc(strlen(namebuf) + 1);
|
||||
strcpy(GameInfo->name, namebuf);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int DINF(FCEUFILE *fp) {
|
||||
char name[100], method[100];
|
||||
uint8 d, m;
|
||||
uint16 y;
|
||||
int t;
|
||||
|
||||
if (FCEU_fread(name, 1, 100, fp) != 100)
|
||||
return(0);
|
||||
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
|
||||
d = t;
|
||||
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
|
||||
m = t;
|
||||
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
|
||||
y = t;
|
||||
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
|
||||
y |= t << 8;
|
||||
if (FCEU_fread(method, 1, 100, fp) != 100)
|
||||
return(0);
|
||||
name[99] = method[99] = 0;
|
||||
FCEU_printf(" Dumped by: %s\n", name);
|
||||
FCEU_printf(" Dumped with: %s\n", method);
|
||||
{
|
||||
char *months[12] = {
|
||||
"January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"
|
||||
};
|
||||
FCEU_printf(" Dumped on: %s %d, %d\n", months[(m - 1) % 12], d, y);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int CTRL(FCEUFILE *fp) {
|
||||
int t;
|
||||
uint32 i;
|
||||
if (uchead.info == 1) {
|
||||
if ((t = FCEU_fgetc(fp)) == EOF)
|
||||
return(0);
|
||||
/* The information stored in this byte isn't very helpful, but it's
|
||||
better than nothing...maybe.
|
||||
*/
|
||||
|
||||
if (t & 1)
|
||||
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
|
||||
else
|
||||
GameInfo->input[0] = GameInfo->input[1] = SI_NONE;
|
||||
if (t & 2)
|
||||
GameInfo->input[1] = SI_ZAPPER;
|
||||
} else {
|
||||
FCEU_printf(" Incorrect Control Chunk Size (%d). Data is:", uchead.info);
|
||||
for (i = 0; i < uchead.info; i++) {
|
||||
t = FCEU_fgetc(fp);
|
||||
FCEU_printf(" %02x", t);
|
||||
}
|
||||
FCEU_printf("\n");
|
||||
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int TVCI(FCEUFILE *fp) {
|
||||
int t;
|
||||
if ((t = FCEU_fgetc(fp)) == EOF)
|
||||
return(0);
|
||||
if (t <= 2) {
|
||||
char *stuffo[3] = { "NTSC", "PAL", "NTSC and PAL" };
|
||||
if (t == 0)
|
||||
GameInfo->vidsys = GIV_NTSC;
|
||||
else if (t == 1)
|
||||
GameInfo->vidsys = GIV_PAL;
|
||||
FCEU_printf(" TV Standard Compatibility: %s\n", stuffo[t]);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int EnableBattery(FCEUFILE *fp) {
|
||||
FCEU_printf(" Battery-backed.\n");
|
||||
if (FCEU_fgetc(fp) == EOF)
|
||||
return(0);
|
||||
UNIFCart.battery = 1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int LoadPRG(FCEUFILE *fp) {
|
||||
int z, t;
|
||||
z = uchead.ID[3] - '0';
|
||||
|
||||
if (z < 0 || z > 15)
|
||||
return(0);
|
||||
FCEU_printf(" PRG ROM %d size: %d", z, (int)uchead.info);
|
||||
if (malloced[z])
|
||||
free(malloced[z]);
|
||||
t = FixRomSize(uchead.info, 2048);
|
||||
if (!(malloced[z] = (uint8*)FCEU_malloc(t)))
|
||||
return(0);
|
||||
mallocedsizes[z] = t;
|
||||
memset(malloced[z] + uchead.info, 0xFF, t - uchead.info);
|
||||
if (FCEU_fread(malloced[z], 1, uchead.info, fp) != uchead.info) {
|
||||
FCEU_printf("Read Error!\n");
|
||||
return(0);
|
||||
} else
|
||||
FCEU_printf("\n");
|
||||
|
||||
SetupCartPRGMapping(z, malloced[z], t, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int SetBoardName(FCEUFILE *fp) {
|
||||
if (!(boardname = (uint8*)FCEU_malloc(uchead.info + 1)))
|
||||
return(0);
|
||||
FCEU_fread(boardname, 1, uchead.info, fp);
|
||||
boardname[uchead.info] = 0;
|
||||
FCEU_printf(" Board name: %s\n", boardname);
|
||||
sboardname = boardname;
|
||||
if (!memcmp(boardname, "NES-", 4) || !memcmp(boardname, "UNL-", 4) || !memcmp(boardname, "HVC-", 4) || !memcmp(boardname, "BTL-", 4) || !memcmp(boardname, "BMC-", 4))
|
||||
sboardname += 4;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int LoadCHR(FCEUFILE *fp) {
|
||||
int z, t;
|
||||
z = uchead.ID[3] - '0';
|
||||
if (z < 0 || z > 15)
|
||||
return(0);
|
||||
FCEU_printf(" CHR ROM %d size: %d", z, (int)uchead.info);
|
||||
if (malloced[16 + z])
|
||||
free(malloced[16 + z]);
|
||||
t = FixRomSize(uchead.info, 8192);
|
||||
if (!(malloced[16 + z] = (uint8*)FCEU_malloc(t)))
|
||||
return(0);
|
||||
mallocedsizes[16 + z] = t;
|
||||
memset(malloced[16 + z] + uchead.info, 0xFF, t - uchead.info);
|
||||
if (FCEU_fread(malloced[16 + z], 1, uchead.info, fp) != uchead.info) {
|
||||
FCEU_printf("Read Error!\n");
|
||||
return(0);
|
||||
} else
|
||||
FCEU_printf("\n");
|
||||
|
||||
SetupCartCHRMapping(z, malloced[16 + z], t, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define BMCFLAG_FORCE4 1
|
||||
#define BMCFLAG_16KCHRR 2
|
||||
#define BMCFLAG_32KCHRR 4
|
||||
#define BMCFLAG_EXPCHRR 8
|
||||
|
||||
static BMAPPING bmap[] = {
|
||||
{ "11160", BMC11160_Init, 0 },
|
||||
{ "12-IN-1", BMC12IN1_Init, 0 },
|
||||
{ "13in1JY110", BMC13in1JY110_Init, 0 },
|
||||
{ "190in1", BMC190in1_Init, 0 },
|
||||
{ "22211", UNL22211_Init, 0 },
|
||||
{ "3D-BLOCK", UNL3DBlock_Init, 0 },
|
||||
{ "411120-C", BMC411120C_Init, 0 },
|
||||
{ "42in1ResetSwitch", Mapper226_Init, 0 },
|
||||
{ "43272", UNL43272_Init, 0 },
|
||||
{ "603-5052", UNL6035052_Init, 0 },
|
||||
{ "64in1NoRepeat", BMC64in1nr_Init, 0 },
|
||||
{ "70in1", BMC70in1_Init, 0 },
|
||||
{ "70in1B", BMC70in1B_Init, 0 },
|
||||
{ "810544-C-A1", BMC810544CA1_Init, 0 },
|
||||
{ "8157", UNL8157_Init, 0 },
|
||||
{ "8237", UNL8237_Init, 0 },
|
||||
{ "8237A", UNL8237A_Init, 0 },
|
||||
{ "830118C", BMC830118C_Init, 0 },
|
||||
{ "A65AS", BMCA65AS_Init, 0 },
|
||||
{ "AC08", AC08_Init, 0 },
|
||||
{ "ANROM", ANROM_Init, 0 },
|
||||
{ "AX5705", UNLAX5705_Init, 0 },
|
||||
{ "BB", UNLBB_Init, 0 },
|
||||
{ "BS-5", BMCBS5_Init, 0 },
|
||||
{ "CC-21", UNLCC21_Init, 0 },
|
||||
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
|
||||
{ "CNROM", CNROM_Init, 0 },
|
||||
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
|
||||
{ "D1038", BMCD1038_Init, 0 },
|
||||
{ "DANCE", UNLOneBus_Init, 0 }, // redundant
|
||||
{ "DANCE2000", UNLD2000_Init, 0 },
|
||||
{ "DREAMTECH01", DreamTech01_Init, 0 },
|
||||
{ "EDU2000", UNLEDU2000_Init, 0 },
|
||||
{ "EKROM", EKROM_Init, 0 },
|
||||
{ "ELROM", ELROM_Init, 0 },
|
||||
{ "ETROM", ETROM_Init, 0 },
|
||||
{ "EWROM", EWROM_Init, 0 },
|
||||
{ "FK23C", BMCFK23C_Init, BMCFLAG_EXPCHRR },
|
||||
{ "FK23CA", BMCFK23CA_Init, BMCFLAG_EXPCHRR },
|
||||
{ "FS304", UNLFS304_Init, 0 },
|
||||
{ "G-146", BMCG146_Init, 0 },
|
||||
{ "GK-192", BMCGK192_Init, 0 },
|
||||
{ "GS-2004", BMCGS2004_Init, 0 },
|
||||
{ "GS-2013", BMCGS2013_Init, 0 },
|
||||
{ "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0 },
|
||||
{ "H2288", UNLH2288_Init, 0 },
|
||||
{ "HKROM", HKROM_Init, 0 },
|
||||
{ "KOF97", UNLKOF97_Init, 0 },
|
||||
{ "KONAMI-QTAI", Mapper190_Init, 0 },
|
||||
{ "KS7012", UNLKS7012_Init, 0 },
|
||||
{ "KS7013B", UNLKS7013B_Init, 0 },
|
||||
{ "KS7017", UNLKS7017_Init, 0 },
|
||||
{ "KS7030", UNLKS7030_Init, 0 },
|
||||
{ "KS7031", UNLKS7031_Init, 0 },
|
||||
{ "KS7032", UNLKS7032_Init, 0 },
|
||||
{ "KS7037", UNLKS7037_Init, 0 },
|
||||
{ "KS7057", UNLKS7057_Init, 0 },
|
||||
{ "LE05", LE05_Init, 0 },
|
||||
{ "LH10", LH10_Init, 0 },
|
||||
{ "LH32", LH32_Init, 0 },
|
||||
{ "LH53", LH53_Init, 0 },
|
||||
{ "MALISB", UNLMaliSB_Init, 0 },
|
||||
{ "MARIO1-MALEE2", MALEE_Init, 0 },
|
||||
{ "MHROM", MHROM_Init, 0 },
|
||||
{ "N625092", UNLN625092_Init, 0 },
|
||||
{ "NROM", NROM_Init, 0 },
|
||||
{ "NROM-128", NROM_Init, 0 },
|
||||
{ "NROM-256", NROM_Init, 0 },
|
||||
{ "NTBROM", Mapper68_Init, 0 },
|
||||
{ "NTD-03", BMCNTD03_Init, 0 },
|
||||
{ "NovelDiamond9999999in1", Novel_Init, 0 },
|
||||
{ "OneBus", UNLOneBus_Init, 0 },
|
||||
{ "PEC-586", UNLPEC586Init, 0 },
|
||||
{ "RROM", NROM_Init, 0 },
|
||||
{ "RROM-128", NROM_Init, 0 },
|
||||
{ "SA-002", TCU02_Init, 0 },
|
||||
{ "SA-0036", SA0036_Init, 0 },
|
||||
{ "SA-0037", SA0037_Init, 0 },
|
||||
{ "SA-009", SA009_Init, 0 },
|
||||
{ "SA-016-1M", SA0161M_Init, 0 },
|
||||
{ "SA-72007", SA72007_Init, 0 },
|
||||
{ "SA-72008", SA72008_Init, 0 },
|
||||
{ "SA-9602B", SA9602B_Init, BMCFLAG_32KCHRR },
|
||||
{ "SA-NROM", TCA01_Init, 0 },
|
||||
{ "SAROM", SAROM_Init, 0 },
|
||||
{ "SBROM", SBROM_Init, 0 },
|
||||
{ "SC-127", UNLSC127_Init, 0 },
|
||||
{ "SCROM", SCROM_Init, 0 },
|
||||
{ "SEROM", SEROM_Init, 0 },
|
||||
{ "SGROM", SGROM_Init, 0 },
|
||||
{ "SHERO", UNLSHeroes_Init, 0 },
|
||||
{ "SKROM", SKROM_Init, 0 },
|
||||
{ "SL12", UNLSL12_Init, 0 },
|
||||
{ "SL1632", UNLSL1632_Init, 0 },
|
||||
{ "SL1ROM", SL1ROM_Init, 0 },
|
||||
{ "SLROM", SLROM_Init, 0 },
|
||||
{ "SMB2J", UNLSMB2J_Init, 0 },
|
||||
{ "SNROM", SNROM_Init, 0 },
|
||||
{ "SOROM", SOROM_Init, 0 },
|
||||
{ "SSS-NROM-256", SSSNROM_Init, 0 },
|
||||
{ "SUNSOFT_UNROM", SUNSOFT_UNROM_Init, 0 }, // fix me, real pcb name, real pcb type
|
||||
{ "Sachen-74LS374N", S74LS374N_Init, 0 },
|
||||
{ "Sachen-74LS374NA", S74LS374NA_Init, 0 }, //seems to be custom mapper
|
||||
{ "Sachen-8259A", S8259A_Init, 0 },
|
||||
{ "Sachen-8259B", S8259B_Init, 0 },
|
||||
{ "Sachen-8259C", S8259C_Init, 0 },
|
||||
{ "Sachen-8259D", S8259D_Init, 0 },
|
||||
{ "Super24in1SC03", Super24_Init, 0 },
|
||||
{ "SuperHIK8in1", Mapper45_Init, 0 },
|
||||
{ "Supervision16in1", Supervision16_Init, 0 },
|
||||
{ "T-227-1", BMCT2271_Init, 0 },
|
||||
{ "T-230", UNLT230_Init, 0 },
|
||||
{ "T-262", BMCT262_Init, 0 },
|
||||
{ "TBROM", TBROM_Init, 0 },
|
||||
{ "TC-U01-1.5M", TCU01_Init, 0 },
|
||||
{ "TEK90", Mapper90_Init, 0 },
|
||||
{ "TEROM", TEROM_Init, 0 },
|
||||
{ "TF1201", UNLTF1201_Init, 0 },
|
||||
{ "TFROM", TFROM_Init, 0 },
|
||||
{ "TGROM", TGROM_Init, 0 },
|
||||
{ "TKROM", TKROM_Init, 0 },
|
||||
{ "TKSROM", TKSROM_Init, 0 },
|
||||
{ "TLROM", TLROM_Init, 0 },
|
||||
{ "TLSROM", TLSROM_Init, 0 },
|
||||
{ "TQROM", TQROM_Init, 0 },
|
||||
{ "TR1ROM", TFROM_Init, BMCFLAG_FORCE4 },
|
||||
{ "TSROM", TSROM_Init, 0 },
|
||||
{ "TVROM", TLROM_Init, BMCFLAG_FORCE4 },
|
||||
{ "Transformer", Transformer_Init, 0 },
|
||||
{ "UNROM", UNROM_Init, 0 },
|
||||
{ "UOROM", UNROM_Init, 0 },
|
||||
{ "VRC7", UNLVRC7_Init, 0 },
|
||||
{ "YOKO", UNLYOKO_Init, 0 },
|
||||
|
||||
#ifdef COPYFAMI
|
||||
{ "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 },
|
||||
{ "COPYFAMI", MapperCopyFami_Init, 0 },
|
||||
#endif
|
||||
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static BFMAPPING bfunc[] = {
|
||||
{ "CTRL", CTRL },
|
||||
{ "TVCI", TVCI },
|
||||
{ "BATR", EnableBattery },
|
||||
{ "MIRR", DoMirroring },
|
||||
{ "PRG", LoadPRG },
|
||||
{ "CHR", LoadCHR },
|
||||
{ "NAME", NAME },
|
||||
{ "MAPR", SetBoardName },
|
||||
{ "DINF", DINF },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int LoadUNIFChunks(FCEUFILE *fp) {
|
||||
int x;
|
||||
int t;
|
||||
for (;; ) {
|
||||
t = FCEU_fread(&uchead, 1, 4, fp);
|
||||
if (t < 4) {
|
||||
if (t > 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (!(FCEU_read32le(&uchead.info, fp)))
|
||||
return 0;
|
||||
t = 0;
|
||||
x = 0;
|
||||
while (bfunc[x].name) {
|
||||
if (!memcmp(&uchead, bfunc[x].name, strlen(bfunc[x].name))) {
|
||||
if (!bfunc[x].init(fp))
|
||||
return 0;
|
||||
t = 1;
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (!t)
|
||||
if (FCEU_fseek(fp, uchead.info, SEEK_CUR))
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int InitializeBoard(void) {
|
||||
int x = 0;
|
||||
|
||||
if (!sboardname) return(0);
|
||||
|
||||
while (bmap[x].name) {
|
||||
if (!strcmp((char*)sboardname, (char*)bmap[x].name)) {
|
||||
if (!malloced[16]) {
|
||||
if (bmap[x].flags & BMCFLAG_16KCHRR)
|
||||
CHRRAMSize = 16384;
|
||||
else if (bmap[x].flags & BMCFLAG_32KCHRR)
|
||||
CHRRAMSize = 32768;
|
||||
else if (bmap[x].flags & BMCFLAG_EXPCHRR)
|
||||
CHRRAMSize = 256 * 1024;
|
||||
else
|
||||
CHRRAMSize = 8192;
|
||||
if ((UNIFchrrama = (uint8*)FCEU_malloc(CHRRAMSize))) {
|
||||
SetupCartCHRMapping(0, UNIFchrrama, CHRRAMSize, 1);
|
||||
AddExState(UNIFchrrama, CHRRAMSize, 0, "CHRR");
|
||||
} else
|
||||
return(-1);
|
||||
}
|
||||
if (bmap[x].flags & BMCFLAG_FORCE4)
|
||||
mirrortodo = 4;
|
||||
MooMirroring();
|
||||
bmap[x].init(&UNIFCart);
|
||||
return(1);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
FCEU_PrintError("Board type not supported.");
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void UNIFGI(int h) {
|
||||
switch (h) {
|
||||
case GI_RESETM2:
|
||||
if (UNIFCart.Reset)
|
||||
UNIFCart.Reset();
|
||||
break;
|
||||
case GI_POWER:
|
||||
if (UNIFCart.Power)
|
||||
UNIFCart.Power();
|
||||
if (UNIFchrrama) memset(UNIFchrrama, 0, 8192);
|
||||
break;
|
||||
case GI_CLOSE:
|
||||
FCEU_SaveGameSave(&UNIFCart);
|
||||
if (UNIFCart.Close)
|
||||
UNIFCart.Close();
|
||||
FreeUNIF();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int UNIFLoad(const char *name, FCEUFILE *fp) {
|
||||
FCEU_fseek(fp, 0, SEEK_SET);
|
||||
FCEU_fread(&unhead, 1, 4, fp);
|
||||
if (memcmp(&unhead, "UNIF", 4))
|
||||
return 0;
|
||||
|
||||
ResetCartMapping();
|
||||
|
||||
ResetExState(0, 0);
|
||||
ResetUNIF();
|
||||
if (!FCEU_read32le(&unhead.info, fp))
|
||||
goto aborto;
|
||||
if (FCEU_fseek(fp, 0x20, SEEK_SET) < 0)
|
||||
goto aborto;
|
||||
if (!LoadUNIFChunks(fp))
|
||||
goto aborto;
|
||||
{
|
||||
int x;
|
||||
struct md5_context md5;
|
||||
|
||||
md5_starts(&md5);
|
||||
|
||||
for (x = 0; x < 32; x++)
|
||||
if (malloced[x]) {
|
||||
md5_update(&md5, malloced[x], mallocedsizes[x]);
|
||||
}
|
||||
md5_finish(&md5, UNIFCart.MD5);
|
||||
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(UNIFCart.MD5));
|
||||
memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5));
|
||||
}
|
||||
|
||||
if (!InitializeBoard())
|
||||
goto aborto;
|
||||
|
||||
FCEU_LoadGameSave(&UNIFCart);
|
||||
GameInterface = UNIFGI;
|
||||
return 1;
|
||||
|
||||
aborto:
|
||||
|
||||
FreeUNIF();
|
||||
ResetUNIF();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CopyFamiLoad() {
|
||||
ResetCartMapping();
|
||||
ResetExState(0, 0);
|
||||
|
||||
sboardname = "COPYFAMI";
|
||||
if (!InitializeBoard())
|
||||
goto aborto;
|
||||
|
||||
FCEU_LoadGameSave(&UNIFCart);
|
||||
GameInterface = UNIFGI;
|
||||
return 1;
|
||||
|
||||
aborto:
|
||||
|
||||
FreeUNIF();
|
||||
ResetUNIF();
|
||||
return 0;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "drivers/libretro/fceu/misc.c"
|
||||
#include "drivers/libretro/fceu/fceu.c"
|
||||
//#include "fceustr.c"
|
||||
#include "fds.c"
|
||||
#include "drivers/libretro/fceu/fds.c"
|
||||
#include "drivers/libretro/fceu/file.c"
|
||||
#include "filter.c"
|
||||
#include "drivers/libretro/fceu/general.c"
|
||||
|
||||
@@ -48,11 +48,7 @@ uint8 *VROM = NULL;
|
||||
uint8 *ExtraNTARAM = NULL;
|
||||
iNES_HEADER head;
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
CartInfo iNESCart;
|
||||
#else
|
||||
static CartInfo iNESCart;
|
||||
#endif
|
||||
|
||||
uint8 Mirroring = 0;
|
||||
uint32 ROM_size = 0;
|
||||
|
||||
@@ -56,11 +56,7 @@ typedef struct {
|
||||
int (*init)(FCEUFILE *fp);
|
||||
} BFMAPPING;
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
CartInfo UNIFCart;
|
||||
#else
|
||||
static CartInfo UNIFCart;
|
||||
#endif
|
||||
|
||||
static int vramo;
|
||||
static int mirrortodo;
|
||||
|
||||
Reference in New Issue
Block a user