fceugx/source/fceultra/ines.cpp

1560 lines
38 KiB
C++
Raw Normal View History

2012-12-14 18:18:20 +01:00
/* 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 "types.h"
#include "x6502.h"
#include "fceu.h"
#include "cart.h"
#include "ppu.h"
#define INESPRIV
#include "ines.h"
#include "unif.h"
#include "state.h"
#include "file.h"
#include "utils/general.h"
#include "utils/memory.h"
#include "utils/crc32.h"
#include "utils/md5.h"
#include "utils/xstring.h"
#include "cheat.h"
#include "vsuni.h"
#include "driver.h"
extern SFORMAT FCEUVSUNI_STATEINFO[];
//mbg merge 6/29/06 - these need to be global
uint8 *trainerpoo=0;
uint8 *ROM = NULL;
uint8 *VROM = NULL;
iNES_HEADER head ;
CartInfo iNESCart;
uint8 iNESMirroring=0;
uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0};
int32 iNESIRQLatch=0,iNESIRQCount=0;
uint8 iNESIRQa=0;
uint32 ROM_size=0;
uint32 VROM_size=0;
char LoadedRomFName[2048]; //mbg merge 7/17/06 added
static int CHRRAMSize = -1;
static void iNESPower(void);
static int NewiNES_Init(int num);
void (*MapClose)(void);
void (*MapperReset)(void);
static int MapperNo=0;
/* MapperReset() is called when the NES is reset(with the reset button).
Mapperxxx_init is called when the NES has been powered on.
*/
static DECLFR(TrainerRead)
{
return(trainerpoo[A&0x1FF]);
}
static void iNES_ExecPower()
{
if(CHRRAMSize != -1)
FCEU_MemoryRand(VROM,CHRRAMSize);
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;
}
}
}
}
void iNESGI(GI h) //bbit edited: removed static keyword
{
switch(h)
{
case GI_RESETSAVE:
FCEU_ClearGameSave(&iNESCart);
break;
case GI_RESETM2:
if(MapperReset)
MapperReset();
if(iNESCart.Reset)
iNESCart.Reset();
break;
case GI_POWER:
iNES_ExecPower();
break;
case GI_CLOSE:
{
#ifndef GEKKO
FCEU_SaveGameSave(&iNESCart);
#endif
if(iNESCart.Close) iNESCart.Close();
if(ROM) {free(ROM); ROM = NULL;}
if(VROM) {free(VROM); VROM = NULL;}
if(MapClose) MapClose();
if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;}
}
break;
}
}
uint32 iNESGameCRC32=0;
struct CRCMATCH {
uint32 crc;
char *name;
};
struct INPSEL {
uint32 crc32;
ESI input1;
ESI input2;
ESIFC inputfc;
};
2009-07-17 19:27:04 +02:00
static void SetInput(void)
{
static struct INPSEL moo[]=
{
2012-12-14 18:18:20 +01:00
{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 }
2009-07-17 19:27:04 +02:00
};
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++;
}
2012-12-14 18:18:20 +01:00
}
#define INESB_INCOMPLETE 1
#define INESB_CORRUPT 2
#define INESB_HACKED 4
struct BADINF {
uint64 md5partial;
char *name;
uint32 type;
};
static struct BADINF BadROMImages[]=
{
#include "ines-bad.h"
};
void CheckBad(uint64 md5partial)
{
int x;
x=0;
//printf("0x%llx\n",md5partial);
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 FCEUX.", BadROMImages[x].name);
return;
}
x++;
}
}
struct CHINF {
uint32 crc32;
int32 mapper;
int32 mirror;
const char* params;
};
void MapperInit()
{
if(NewiNES_Init(MapperNo))
{
}
else
{
iNESCart.Power=iNESPower;
if(head.ROM_type&2)
{
iNESCart.SaveGame[0]=WRAM;
iNESCart.SaveGameLen[0]=8192;
}
}
}
static const TMasterRomInfo sMasterRomInfo[] = {
{ 0x62b51b108a01d2beLL, "bonus=0" }, //4-in-1 (FK23C8021)[p1][!].nes
{ 0x8bb48490d8d22711LL, "bonus=0" }, //4-in-1 (FK23C8033)[p1][!].nes
{ 0xc75888d7b48cd378LL, "bonus=0" }, //4-in-1 (FK23C8043)[p1][!].nes
{ 0xf81a376fa54fdd69LL, "bonus=0" }, //4-in-1 (FK23Cxxxx, S-0210A PCB)[p1][!].nes
{ 0xa37eb9163e001a46LL, "bonus=0" }, //4-in-1 (FK23C8026) [p1][!].nes
{ 0xde5ce25860233f7eLL, "bonus=0" }, //4-in-1 (FK23C8045) [p1][!].nes
{ 0x5b3aa4cdc484a088LL, "bonus=0" }, //4-in-1 (FK23C8056) [p1][!].nes
{ 0x9342bf9bae1c798aLL, "bonus=0" }, //4-in-1 (FK23C8079) [p1][!].nes
{ 0x164eea6097a1e313LL, "busc=1" }, //Cybernoid - The Fighting Machine (U)[!].nes -- needs bus conflict emulation
};
const TMasterRomInfo* MasterRomInfo;
TMasterRomInfoParams MasterRomInfoParams;
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"
};
int tofix=0;
int x;
uint64 partialmd5=0;
for(x=0;x<8;x++)
{
partialmd5 |= (uint64)iNESCart.MD5[15-x] << (x*8);
//printf("%16llx\n",partialmd5);
}
CheckBad(partialmd5);
MasterRomInfo = NULL;
for(int i=0;i<ARRAY_SIZE(sMasterRomInfo);i++)
{
const TMasterRomInfo& info = sMasterRomInfo[i];
if(info.md5lower != partialmd5)
continue;
MasterRomInfo = &info;
if(!info.params) break;
std::vector<std::string> toks = tokenize_str(info.params,",");
for(int j=0;j<(int)toks.size();j++)
{
std::vector<std::string> parts = tokenize_str(toks[j],"=");
MasterRomInfoParams[parts[0]] = parts[1];
}
break;
}
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)
{
char *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 {
int mapper;
void (*init)(CartInfo *);
} NewMI;
//this is for games that is not the a power of 2
//mapper based for now...
//not really accurate but this works since games
//that are not in the power of 2 tends to come
//in obscure mappers themselves which supports such
//size
static int not_power2[] =
{
228
};
typedef struct {
char* name;
int 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},
// {"", 6, Mapper6_Init},
{"ANROM", 7, ANROM_Init},
{"", 8, Mapper8_Init}, // Nogaems, it's worthless
// {"", 9, Mapper9_Init},
// {"", 10, Mapper10_Init},
{"Color Dreams", 11, Mapper11_Init},
{"", 12, Mapper12_Init},
{"CPROM", 13, CPROM_Init},
// {"", 14, Mapper14_Init},
{"100-in-1", 15, Mapper15_Init},
{"Bandai", 16, Mapper16_Init},
{"", 17, Mapper17_Init},
{"", 18, Mapper18_Init},
{"Namcot 106", 19, Mapper19_Init},
// {"", 20, Mapper20_Init},
{"Konami VRC2/VRC4", 21, Mapper21_Init},
{"Konami VRC2/VRC4", 22, Mapper22_Init},
{"Konami VRC2/VRC4", 23, Mapper23_Init},
// {"", 24, Mapper24_Init},
{"Konami VRC2/VRC4", 25, Mapper25_Init},
// {"", 26, Mapper26_Init},
// {"", 27, Mapper27_Init}, // Deprecated, dupe for VRC2/VRC4 mapper
// {"", 28, Mapper28_Init},
// {"", 29, Mapper29_Init},
// {"", 30, Mapper30_Init},
// {"", 31, Mapper31_Init},
{"IREM G-101", 32, Mapper32_Init},
{"TC0190FMC/TC0350FMR", 33, Mapper33_Init},
{"", 34, Mapper34_Init},
{"Wario Land 2", 35, UNLSC127_Init},
{"TXC Policeman", 36, Mapper36_Init},
{"", 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},
{"", 43, Mapper43_Init},
{"", 44, Mapper44_Init},
{"", 45, Mapper45_Init},
{"RUMBLESTATION 15-in-1",46, Mapper46_Init},
{"", 47, Mapper47_Init},
{"TAITO TCxxx", 48, Mapper48_Init},
{"", 49, Mapper49_Init},
{"SMB2j FDS REV A", 50, Mapper50_Init},
{"11-in-1 BALL SERIES", 51, Mapper51_Init}, // 1993 year version
{"", 52, Mapper52_Init},
// {"", 53, Mapper53_Init}, // iNES version of complex UNIF board, can't emulate properly as iNES
// {"", 54, Mapper54_Init},
// {"", 55, Mapper55_Init},
// {"", 56, Mapper56_Init},
{"", 57, Mapper57_Init},
{"", 58, BMCGK192_Init},
{"", 59, Mapper59_Init}, // Check this out
{"", 60, BMCD1038_Init},
{"20-in-1 KAISER REV A", 61, Mapper61_Init},
{"700-in-1", 62, Mapper62_Init},
// {"", 63, Mapper63_Init},
// {"", 64, Mapper64_Init},
// {"", 65, Mapper65_Init},
{"MHOM", 66, MHROM_Init},
// {"", 67, Mapper67_Init},
{"Sunsoft Mapper #4", 68, Mapper68_Init},
// {"", 69, Mapper69_Init},
{"", 70, Mapper70_Init},
{"CAMERICA BF9093", 71, Mapper71_Init},
{"JALECO JF-17", 72, Mapper72_Init},
{"KONAMI VRC3", 73, Mapper73_Init},
{"", 74, Mapper74_Init},
{"KONAMI VRC1", 75, Mapper75_Init},
{"NAMCOT 108 VER. 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 VER. A", 80, Mapper80_Init},
// {"", 81, Mapper81_Init},
{"", 82, Mapper82_Init},
{"", 83, Mapper83_Init},
// {"", 84, Mapper84_Init},
// {"", 85, Mapper85_Init},
{"", 86, Mapper86_Init},
{"", 87, Mapper87_Init},
{"", 88, Mapper88_Init},
{"", 89, Mapper89_Init},
{"", 90, Mapper90_Init},
{"", 91, Mapper91_Init},
{"", 92, Mapper92_Init},
{"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init},
{"", 94, Mapper94_Init},
{"NAMCOT 108 VER. B", 95, Mapper95_Init},
{"", 96, Mapper96_Init},
{"", 97, Mapper97_Init},
// {"", 98, Mapper98_Init},
{"", 99, Mapper99_Init},
// {"", 100, Mapper100_Init},
{"", 101, Mapper101_Init},
// {"", 102, Mapper102_Init},
{"", 103, Mapper103_Init},
// {"", 104, Mapper104_Init},
2010-03-11 07:30:34 +01:00
{"", 105, Mapper105_Init},
2012-12-14 18:18:20 +01:00
{"", 106, Mapper106_Init},
2010-03-11 07:30:34 +01:00
{"", 107, Mapper107_Init},
2012-12-14 18:18:20 +01:00
{"", 108, Mapper108_Init},
// {"", 109, Mapper109_Init},
// {"", 110, Mapper110_Init},
// {"", 111, Mapper111_Init},
2010-03-11 07:30:34 +01:00
{"", 112, Mapper112_Init},
{"", 113, Mapper113_Init},
{"", 114, Mapper114_Init},
{"", 115, Mapper115_Init},
2012-12-14 18:18:20 +01:00
{"", 116, UNLSL12_Init},
2010-03-11 07:30:34 +01:00
{"", 117, Mapper117_Init},
{"TSKROM", 118, TKSROM_Init},
{"", 119, Mapper119_Init},
2012-12-14 18:18:20 +01:00
{"", 120, Mapper120_Init},
{"", 121, Mapper121_Init},
// {"", 122, Mapper122_Init},
{"UNLH2288", 123, UNLH2288_Init},
// {"", 124, Mapper124_Init},
{"", 125, LH32_Init},
// {"", 126, Mapper126_Init},
// {"", 127, Mapper127_Init},
// {"", 128, Mapper128_Init},
// {"", 129, Mapper129_Init},
// {"", 130, Mapper130_Init},
// {"", 131, Mapper131_Init},
2010-03-11 07:30:34 +01:00
{"UNL22211", 132, UNL22211_Init},
{"SA72008", 133, SA72008_Init},
2012-12-14 18:18:20 +01:00
{"", 134, Mapper134_Init},
// {"", 135, Mapper135_Init},
{"TCU02", 136, TCU02_Init},
2010-03-11 07:30:34 +01:00
{"S8259D", 137, S8259D_Init},
{"S8259B", 138, S8259B_Init},
{"S8259C", 139, S8259C_Init},
{"", 140, Mapper140_Init},
{"S8259A", 141, S8259A_Init},
2012-12-14 18:18:20 +01:00
{"UNLKS7032", 142, UNLKS7032_Init},
2010-03-11 07:30:34 +01:00
{"TCA01", 143, TCA01_Init},
{"", 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},
2012-12-14 18:18:20 +01:00
{"", 151, Mapper151_Init},
2010-03-11 07:30:34 +01:00
{"", 152, Mapper152_Init},
2012-12-14 18:18:20 +01:00
{"", 153, Mapper153_Init},
2010-03-11 07:30:34 +01:00
{"", 154, Mapper154_Init},
{"", 155, Mapper155_Init},
2012-12-14 18:18:20 +01:00
{"", 156, Mapper156_Init},
{"", 157, Mapper157_Init},
// {"", 158, Mapper158_Init},
// {"", 159, Mapper159_Init},
{"SA009", 160, SA009_Init},
// {"", 161, Mapper161_Init},
{"", 162, UNLFS304_Init},
2010-03-11 07:30:34 +01:00
{"", 163, Mapper163_Init},
{"", 164, Mapper164_Init},
{"", 165, Mapper165_Init},
2012-12-14 18:18:20 +01:00
// {"", 166, Mapper166_Init},
// {"", 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},
2010-03-11 07:30:34 +01:00
{"", 180, Mapper180_Init},
{"", 181, Mapper181_Init},
2012-12-14 18:18:20 +01:00
// {"", 182, Mapper182_Init}, // Deprecated, dupe
2010-03-11 07:30:34 +01:00
{"", 183, Mapper183_Init},
{"", 184, Mapper184_Init},
{"", 185, Mapper185_Init},
{"", 186, Mapper186_Init},
{"", 187, Mapper187_Init},
{"", 188, Mapper188_Init},
{"", 189, Mapper189_Init},
2012-12-14 18:18:20 +01:00
// {"", 190, Mapper190_Init},
2010-03-11 07:30:34 +01:00
{"", 191, Mapper191_Init},
{"", 192, Mapper192_Init},
2012-12-14 18:18:20 +01:00
{"", 193, Mapper193_Init},
2010-03-11 07:30:34 +01:00
{"", 194, Mapper194_Init},
{"", 195, Mapper195_Init},
2012-12-14 18:18:20 +01:00
{"", 196, Mapper196_Init},
{"", 197, Mapper197_Init},
2010-03-11 07:30:34 +01:00
{"", 198, Mapper198_Init},
{"", 199, Mapper199_Init},
{"", 200, Mapper200_Init},
2012-12-14 18:18:20 +01:00
{"", 201, Mapper201_Init},
{"", 202, Mapper202_Init},
{"", 203, Mapper203_Init},
{"", 204, Mapper204_Init},
2010-03-11 07:30:34 +01:00
{"", 205, Mapper205_Init},
2012-12-14 18:18:20 +01:00
{"NAMCOT 108 VER. C", 206, Mapper206_Init}, // Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3
{"TAITO X1-005 VER. B", 207, Mapper207_Init},
2010-03-11 07:30:34 +01:00
{"", 208, Mapper208_Init},
{"", 209, Mapper209_Init},
{"", 210, Mapper210_Init},
{"", 211, Mapper211_Init},
2012-12-14 18:18:20 +01:00
{"", 212, Mapper212_Init},
{"", 213, Mapper213_Init},
{"", 214, Mapper214_Init},
2012-01-09 02:59:06 +01:00
{"", 215, UNL8237_Init},
2010-03-11 07:30:34 +01:00
{"", 216, Mapper216_Init},
2012-12-14 18:18:20 +01:00
{"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper
// {"", 218, Mapper218_Init},
2010-12-06 03:46:57 +01:00
{"UNLA9746", 219, UNLA9746_Init},
2012-12-14 18:18:20 +01:00
{"Debug Mapper", 220, UNLKS7057_Init},
{"UNLN625092", 221, UNLN625092_Init},
2010-03-11 07:30:34 +01:00
{"", 222, Mapper222_Init},
2012-12-14 18:18:20 +01:00
// {"", 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 22-in-1+Contra", 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},
2010-03-11 07:30:34 +01:00
{"", 235, Mapper235_Init},
2012-12-14 18:18:20 +01:00
// {"", 236, Mapper236_Init},
// {"", 237, Mapper237_Init},
{"UNL6035052", 238, UNL6035052_Init},
// {"", 239, Mapper239_Init},
2010-03-11 07:30:34 +01:00
{"", 240, Mapper240_Init},
2012-12-14 18:18:20 +01:00
{"", 241, Mapper241_Init},
{"", 242, Mapper242_Init},
2010-03-11 07:30:34 +01:00
{"S74LS374NA", 243, S74LS374NA_Init},
2012-12-14 18:18:20 +01:00
{"DECATHLON", 244, Mapper244_Init},
2010-03-11 07:30:34 +01:00
{"", 245, Mapper245_Init},
2012-12-14 18:18:20 +01:00
{"FONG SHEN BANG", 246, Mapper246_Init},
// {"", 247, Mapper247_Init},
// {"", 248, Mapper248_Init},
2010-03-11 07:30:34 +01:00
{"", 249, Mapper249_Init},
{"", 250, Mapper250_Init},
2012-12-14 18:18:20 +01:00
// {"", 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},
2010-03-11 07:30:34 +01:00
{"", 254, Mapper254_Init},
2012-12-14 18:18:20 +01:00
// {"", 255, Mapper255_Init}, // No good dumps for this mapper
{"", 0, NULL}
};
int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode)
{
struct md5_context md5;
if(FCEU_fread(&head,1,16,fp)!=16)
return 0;
if(memcmp(&head,"NES\x1a",4))
return 0;
head.cleanup();
memset(&iNESCart,0,sizeof(iNESCart));
MapperNo = (head.ROM_type>>4);
MapperNo|=(head.ROM_type2&0xF0);
Mirroring = (head.ROM_type&1);
// int ROM_size=0;
if(!head.ROM_size)
{
// FCEU_PrintError("No PRG ROM!");
// return(0);
ROM_size=256;
//head.ROM_size++;
}
else
ROM_size=uppow2(head.ROM_size);
// ROM_size = head.ROM_size;
VROM_size = head.VROM_size;
int round = true;
for (int i = 0; i != sizeof(not_power2)/sizeof(not_power2[0]); ++i)
{
//for games not to the power of 2, so we just read enough
//prg rom from it, but we have to keep ROM_size to the power of 2
//since PRGCartMapping wants ROM_size to be to the power of 2
//so instead if not to power of 2, we just use head.ROM_size when
//we use FCEU_read
if (not_power2[i] == MapperNo)
{
round = false;
break;
}
}
if(VROM_size)
VROM_size=uppow2(VROM_size);
if(head.ROM_type&8) Mirroring=2;
if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;
if(VROM_size)
{
if((VROM = (uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)
{
free(ROM);
ROM = NULL;
return 0;
}
}
memset(ROM,0xFF,ROM_size<<14);
if(VROM_size) 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*0x4000,0);
// SetupCartPRGMapping(1,WRAM,8192,1);
FCEU_fread(ROM,0x4000,(round) ? ROM_size : head.ROM_size,fp);
if(VROM_size)
FCEU_fread(VROM,0x2000,head.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 CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08lx\n",
(round) ? ROM_size : head.ROM_size, head.VROM_size,iNESGameCRC32);
{
int x;
FCEU_printf(" ROM MD5: 0x");
for(x=0;x<16;x++)
FCEU_printf("%02x",iNESCart.MD5[x]);
FCEU_printf("\n");
}
char* mappername = "Not Listed";
for(int 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 Mapper name: %s\n Mirroring: %s\n",
MapperNo, mappername, 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");
// (head.ROM_type&8) = Mirroring: None(Four-screen)
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)
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(MapperNo != 18) {
// if(ROM) free(ROM);
// if(VROM) free(VROM);
// ROM=VROM=0;
// return(0);
// }
GameInfo->mappernum = MapperNo;
MapperInit();
#ifndef GEKKO
FCEU_LoadGameSave(&iNESCart);
#endif
strcpy(LoadedRomFName,name); //bbit edited: line added
// Extract Filename only. Should account for Windows/Unix this way.
if (strrchr(name, '/')) {
name = strrchr(name, '/') + 1;
} else if(strrchr(name, '\\')) {
name = strrchr(name, '\\') + 1;
}
GameInterface=iNESGI;
FCEU_printf("\n");
// since apparently the iNES format doesn't store this information,
// guess if the settings should be PAL or NTSC from the ROM name
// TODO: MD5 check against a list of all known PAL games instead?
if(OverwriteVidMode)
{
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)"))
FCEUI_SetVidSystem(1);
else
FCEUI_SetVidSystem(0);
}
return 1;
}
// bbit edited: the whole function below was added
int iNesSave(){
FILE *fp;
char name[2048];
if(GameInfo->type != GIT_CART)return 0;
if(GameInterface!=iNESGI)return 0;
strcpy(name,LoadedRomFName);
if (strcmp(name+strlen(name)-4,".nes") != 0) { //para edit
strcat(name,".nes");
}
fp = fopen(name,"wb");
if(fwrite(&head,1,16,fp)!=16)
{
fclose(fp);
return 0;
}
if(head.ROM_type&4) /* Trainer */
{
fwrite(trainerpoo,512,1,fp);
}
fwrite(ROM,0x4000,ROM_size,fp);
if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);
fclose(fp);
return 1;
}
int iNesSaveAs(char* name)
{
//adelikat: TODO: iNesSave() and this have pretty much the same code, outsource the common code to a single function
FILE *fp;
if(GameInfo->type != GIT_CART)return 0;
if(GameInterface != iNESGI)return 0;
fp = fopen(name,"wb");
if(fwrite(&head,1,16,fp)!=16)
{
fclose(fp);
return 0;
}
if(head.ROM_type&4) /* Trainer */
{
fwrite(trainerpoo,512,1,fp);
}
fwrite(ROM,0x4000,ROM_size,fp);
if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);
fclose(fp);
return 1;
}
//para edit: added function below
char *iNesShortFName() {
char *ret;
if (!(ret = strrchr(LoadedRomFName,'\\'))) {
if (!(ret = strrchr(LoadedRomFName,'/'))) return 0;
}
return ret+1;
}
void VRAM_BANK1(uint32 A, uint8 V)
{
V&=7;
PPUCHRRAM|=(1<<(A>>10));
CHRBankList[(A)>>10]=V;
VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
}
void VRAM_BANK4(uint32 A, uint32 V)
{
V&=1;
PPUCHRRAM|=(0xF<<(A>>10));
CHRBankList[(A)>>10]=(V<<2);
CHRBankList[((A)>>10)+1]=(V<<2)+1;
CHRBankList[((A)>>10)+2]=(V<<2)+2;
CHRBankList[((A)>>10)+3]=(V<<2)+3;
VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
}
void VROM_BANK1(uint32 A,uint32 V)
{
setchr1(A,V);
CHRBankList[(A)>>10]=V;
}
void VROM_BANK2(uint32 A,uint32 V)
{
setchr2(A,V);
CHRBankList[(A)>>10]=(V<<1);
CHRBankList[((A)>>10)+1]=(V<<1)+1;
}
void VROM_BANK4(uint32 A, uint32 V)
{
setchr4(A,V);
CHRBankList[(A)>>10]=(V<<2);
CHRBankList[((A)>>10)+1]=(V<<2)+1;
CHRBankList[((A)>>10)+2]=(V<<2)+2;
CHRBankList[((A)>>10)+3]=(V<<2)+3;
}
void VROM_BANK8(uint32 V)
{
setchr8(V);
CHRBankList[0]=(V<<3);
CHRBankList[1]=(V<<3)+1;
CHRBankList[2]=(V<<3)+2;
CHRBankList[3]=(V<<3)+3;
CHRBankList[4]=(V<<3)+4;
CHRBankList[5]=(V<<3)+5;
CHRBankList[6]=(V<<3)+6;
CHRBankList[7]=(V<<3)+7;
}
void ROM_BANK8(uint32 A, uint32 V)
{
setprg8(A,V);
if(A>=0x8000)
PRGBankList[((A-0x8000)>>13)]=V;
}
void ROM_BANK16(uint32 A, uint32 V)
{
setprg16(A,V);
if(A>=0x8000)
{
PRGBankList[((A-0x8000)>>13)]=V<<1;
PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1;
}
}
void ROM_BANK32(uint32 V)
{
setprg32(0x8000,V);
PRGBankList[0]=V<<2;
PRGBankList[1]=(V<<2)+1;
PRGBankList[2]=(V<<2)+2;
PRGBankList[3]=(V<<2)+3;
}
void onemir(uint8 V)
{
if(Mirroring==2) return;
if(V>1)
V=1;
Mirroring=0x10|V;
setmirror(MI_0+V);
}
void MIRROR_SET2(uint8 V)
{
if(Mirroring==2) return;
Mirroring=V;
setmirror(V);
}
void MIRROR_SET(uint8 V)
{
if(Mirroring==2) return;
V^=1;
Mirroring=V;
setmirror(V);
}
static void NONE_init(void)
{
ROM_BANK16(0x8000,0);
ROM_BANK16(0xC000,~0);
if(VROM_size)
VROM_BANK8(0);
else
setvram8(CHRRAM);
}
void (*MapInitTab[256])(void)=
{
2009-07-17 19:27:04 +02:00
0,
0,
0, //Mapper2_init,
0, //Mapper3_init,
0,
0,
Mapper6_init,
2012-12-14 18:18:20 +01:00
0, //Mapper7_init,
0, //Mapper8_init,
2009-07-17 19:27:04 +02:00
Mapper9_init,
Mapper10_init,
0, //Mapper11_init,
2009-11-10 23:13:41 +01:00
0,
2009-07-17 19:27:04 +02:00
0, //Mapper13_init,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper15_init,
0, //Mapper16_init,
0, //Mapper17_init,
0, //Mapper18_init,
2009-07-17 19:27:04 +02:00
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper21_init,
0, //Mapper22_init,
0, //Mapper23_init,
2009-07-17 19:27:04 +02:00
Mapper24_init,
2012-12-14 18:18:20 +01:00
0, //Mapper25_init,
2009-07-17 19:27:04 +02:00
Mapper26_init,
2012-12-14 18:18:20 +01:00
0, //Mapper27_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper32_init,
0, //Mapper33_init,
0, //Mapper34_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper40_init,
0, //Mapper41_init,
0, //Mapper42_init,
2009-07-17 19:27:04 +02:00
0, //Mapper43_init,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper46_init,
2009-07-17 19:27:04 +02:00
0,
2012-12-14 18:18:20 +01:00
0, //Mapper48_init,
2009-07-17 19:27:04 +02:00
0,
2012-12-14 18:18:20 +01:00
0, //Mapper50_init,
0, //Mapper51_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper57_init,
0, //Mapper58_init,
0, //Mapper59_init,
0, //Mapper60_init,
0, //Mapper61_init,
0, //Mapper62_init,
2009-07-17 19:27:04 +02:00
0,
Mapper64_init,
Mapper65_init,
2012-12-14 18:18:20 +01:00
0, //Mapper66_init,
2009-07-17 19:27:04 +02:00
Mapper67_init,
2012-12-14 18:18:20 +01:00
0, //Mapper68_init,
2009-07-17 19:27:04 +02:00
Mapper69_init,
2012-12-14 18:18:20 +01:00
0, //Mapper70_init,
0, //Mapper71_init,
0, //Mapper72_init,
0, //Mapper73_init,
0,
0, //Mapper75_init,
0, //Mapper76_init,
0, //Mapper77_init,
2009-07-17 19:27:04 +02:00
0, //Mapper78_init,
2012-12-14 18:18:20 +01:00
0, //Mapper79_init,
0, //Mapper80_init,
2009-07-17 19:27:04 +02:00
0,
2012-12-14 18:18:20 +01:00
0, //Mapper82_init,
0, //Mapper83_init,
2009-07-17 19:27:04 +02:00
0,
Mapper85_init,
2012-12-14 18:18:20 +01:00
0, //Mapper86_init,
2009-07-17 19:27:04 +02:00
0, //Mapper87_init,
0, //Mapper88_init,
2012-12-14 18:18:20 +01:00
0, //Mapper89_init,
2009-07-17 19:27:04 +02:00
0,
2012-12-14 18:18:20 +01:00
0, //Mapper91_init,
0, //Mapper92_init,
2009-07-17 19:27:04 +02:00
0, //Mapper93_init,
0, //Mapper94_init,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper96_init,
0, //Mapper97_init,
2009-07-17 19:27:04 +02:00
0,
2012-12-14 18:18:20 +01:00
0, //Mapper99_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
0,
0,
0,
0, //Mapper107_init,
0,
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper113_init,
2009-07-17 19:27:04 +02:00
0,
0,
0, //Mapper116_init,
0, //Mapper117_init,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, //Mapper140_init,
0,
0,
0,
0, //Mapper144_init,
0,
0,
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper151_init,
2009-07-17 19:27:04 +02:00
0, //Mapper152_init,
2012-12-14 18:18:20 +01:00
0, //Mapper153_init,
2009-07-17 19:27:04 +02:00
0, //Mapper154_init,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper156_init,
0, //Mapper157_init,
2009-07-17 19:27:04 +02:00
0, //Mapper158_init, removed
0,
0,
0,
0,
0,
0,
0,
Mapper166_init,
Mapper167_init,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, //Mapper180_init,
0,
0,
0,
0, //Mapper184_init,
0, //Mapper185_init,
0,
0,
0,
0, //Mapper189_init,
0,
0, //Mapper191_init,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper193_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
0,
0,
0, //Mapper200_init,
2012-12-14 18:18:20 +01:00
0, //Mapper201_init,
0, //Mapper202_init,
0, //Mapper203_init,
0, //Mapper204_init,
2009-07-17 19:27:04 +02:00
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper207_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0, //Mapper211_init,
2012-12-14 18:18:20 +01:00
0, //Mapper212_init,
0, //Mapper213_init,
0, //Mapper214_init,
2009-07-17 19:27:04 +02:00
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2012-12-14 18:18:20 +01:00
0, //Mapper225_init,
2009-07-17 19:27:04 +02:00
0, //Mapper226_init,
2012-12-14 18:18:20 +01:00
0, //Mapper227_init,
0, //Mapper228_init,
0, //Mapper229_init,
0, //Mapper230_init,
0, //Mapper231_init,
0, //Mapper232_init,
0,
0, //Mapper234_init,
2009-07-17 19:27:04 +02:00
0, //Mapper235_init,
0,
0,
0,
0,
0, //Mapper240_init,
2012-12-14 18:18:20 +01:00
0, //Mapper241_init,
0, //Mapper242_init,
0,
0, //Mapper244_init,
0,
0, //Mapper246_init,
0,
0,
0,
0,
0,
0,
0,
0,
0, //Mapper255_init
};
static DECLFW(BWRAM)
{
WRAM[A-0x6000]=V;
}
static DECLFR(AWRAM)
{
return WRAM[A-0x6000];
}
void (*MapStateRestore)(int version);
void iNESStateRestore(int version)
{
int x;
if(!MapperNo) return;
for(x=0;x<4;x++)
setprg8(0x8000+x*8192,PRGBankList[x]);
if(VROM_size)
for(x=0;x<8;x++)
setchr1(0x400*x,CHRBankList[x]);
if(0) switch(Mirroring)
{
case 0:setmirror(MI_H);break;
case 1:setmirror(MI_V);break;
case 0x12:
case 0x10:setmirror(MI_0);break;
case 0x13:
case 0x11:setmirror(MI_1);break;
}
if(MapStateRestore) MapStateRestore(version);
}
static void iNESPower(void)
{
int x;
int type=MapperNo;
SetReadHandler(0x8000,0xFFFF,CartBR);
GameStateRestore=iNESStateRestore;
MapClose=0;
MapperReset=0;
MapStateRestore=0;
setprg8r(1,0x6000,0);
SetReadHandler(0x6000,0x7FFF,AWRAM);
SetWriteHandler(0x6000,0x7FFF,BWRAM);
FCEU_CheatAddRAM(8,0x6000,WRAM);
/* This statement represents atrocious code. I need to rewrite
all of the iNES mapper code... */
IRQCount=IRQLatch=IRQa=0;
if(head.ROM_type&2)
memset(GameMemBlock+8192,0,GAME_MEM_BLOCK_SIZE-8192);
else
memset(GameMemBlock,0,GAME_MEM_BLOCK_SIZE);
NONE_init();
ResetExState(0,0);
if(GameInfo->type == GIT_VSUNI)
AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
AddExState(WRAM, 8192, 0, "WRAM");
if(type==19 || type==6 || type==69 || type==85 || type==96)
AddExState(MapperExRAM, 32768, 0, "MEXR");
if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96))
AddExState(CHRRAM, 8192, 0, "CHRR");
if(head.ROM_type&8)
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
/* Exclude some mappers whose emulation code handle save state stuff
themselves. */
if(type && type!=13 && type!=96)
{
AddExState(mapbyte1, 32, 0, "MPBY");
AddExState(&Mirroring, 1, 0, "MIRR");
AddExState(&IRQCount, 4, 1, "IRQC");
AddExState(&IRQLatch, 4, 1, "IQL1");
AddExState(&IRQa, 1, 0, "IRQA");
AddExState(PRGBankList, 4, 0, "PBL");
for(x=0;x<8;x++)
{
char tak[8];
sprintf(tak,"CBL%d",x);
AddExState(&CHRBankList[x], 2, 1,tak);
}
}
if(MapInitTab[type]) MapInitTab[type]();
else if(type)
{
FCEU_PrintError("iNES mapper #%d is not supported at all.",type);
}
}
static int NewiNES_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)
{
if(num==13)
{
CHRRAMSize=16384;
}
else
{
CHRRAMSize=8192;
}
if((VROM = (uint8 *)FCEU_dmalloc(CHRRAMSize)) == NULL) return 0;
FCEU_MemoryRand(VROM,CHRRAMSize);
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;
}