From 181278b136b64f4c7b8e93e0f08921560862be7a Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 6 Jun 2012 17:15:06 +0000 Subject: [PATCH] apply changes made during brief timespan in new (abandoned) svn repository: * support mapper 176. mapper 176 no longer maps to BMCFK23C. BMCFK23C is still accessible through crc or unif? test case would be welcome. it is unclear to me why mapper 176 control was removed from 176.cpp and given to BMCFK23C * fix malformed ines.cpp file format * gtk: bump about date to 2012 * Taseditor: fixed silly bug with JumpToFrame * Taseditor: autosave works only when project has a filename * Taseditor: small fixes --- src/boards/176.cpp | 93 +- src/drivers/sdl/gui.cpp | 2 +- src/drivers/win/res.rc | 2 +- src/drivers/win/taseditor/playback.cpp | 4 +- src/drivers/win/taseditor/taseditor_config.h | 4 +- .../win/taseditor/taseditor_project.cpp | 7 +- .../win/taseditor/taseditor_window.cpp | 4 +- src/drivers/win/taseditor/taseditor_window.h | 2 +- src/ines.cpp | 2861 +++++++++-------- src/ines.h | 1 + 10 files changed, 1527 insertions(+), 1453 deletions(-) diff --git a/src/boards/176.cpp b/src/boards/176.cpp index 1d7b5d19..ccd2a625 100644 --- a/src/boards/176.cpp +++ b/src/boards/176.cpp @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2012 FCEUX team * * 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 @@ -20,44 +21,116 @@ #include "mapinc.h" -static uint8 prg, chr; +extern uint32 ROM_size; + +static uint8 prg[4], chr, sbw, we_sram; static uint8 *WRAM=NULL; static uint32 WRAMSIZE; static SFORMAT StateRegs[]= { - {&prg, 1, "PRG"}, + {prg, 4, "PRG"}, {&chr, 1, "CHR"}, + {&sbw, 1, "SBW"}, {0} }; static void Sync(void) { setprg8r(0x10,0x6000,0); - setprg32(0x8000,prg>>1); + setprg8(0x8000,prg[0]); + setprg8(0xA000,prg[1]); + setprg8(0xC000,prg[2]); + setprg8(0xE000,prg[3]); + setchr8(chr); } -static DECLFW(M176Write1) +static DECLFW(M176Write_5001) { - prg = V; + if(sbw) + { + prg[0] = V*4; + prg[1] = V*4+1; + prg[2] = V*4+2; + prg[3] = V*4+3; + } Sync(); } -static DECLFW(M176Write2) +static DECLFW(M176Write_5010) +{ + if(V == 0x24) sbw = 1; + Sync(); +} + +static DECLFW(M176Write_5011) +{ + V >>= 1; + if(sbw) + { + prg[0] = V*4; + prg[1] = V*4+1; + prg[2] = V*4+2; + prg[3] = V*4+3; + } + Sync(); +} + +static DECLFW(M176Write_5FF1) +{ + V >>= 1; + prg[0] = V*4; + prg[1] = V*4+1; + prg[2] = V*4+2; + prg[3] = V*4+3; + Sync(); +} + +static DECLFW(M176Write_5FF2) { chr = V; Sync(); } +static DECLFW(M176Write_A001) +{ + we_sram = V & 0x03; +} + +static DECLFW(M176Write_WriteSRAM) +{ +// if(we_sram) + CartBW(A,V); +} + static void M176Power(void) { - prg = ~0; SetReadHandler(0x6000,0x7fff,CartBR); - SetWriteHandler(0x6000,0x7fff,CartBW); + SetWriteHandler(0x6000,0x7fff,M176Write_WriteSRAM); SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x5ff1,0x5ff1,M176Write1); - SetWriteHandler(0x5ff2,0x5ff2,M176Write2); + SetWriteHandler(0xA001,0xA001,M176Write_A001); + SetWriteHandler(0x5001,0x5001,M176Write_5001); + SetWriteHandler(0x5010,0x5010,M176Write_5010); + SetWriteHandler(0x5011,0x5011,M176Write_5011); + SetWriteHandler(0x5ff1,0x5ff1,M176Write_5FF1); + SetWriteHandler(0x5ff2,0x5ff2,M176Write_5FF2); + + we_sram = 0; + sbw = 0; + prg[0] = 0; + prg[1] = 1; + if(ROM_size > 32) + { + prg[2] = ROM_size-2; + prg[3] = ROM_size-1; + } + else + { + prg[2] = ROM_size*2-2; + prg[3] = ROM_size*2-1; + } + Sync(); } diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 2f768dbe..226493c1 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -1201,7 +1201,7 @@ void openAbout () gtk_show_about_dialog(GTK_WINDOW(MainWindow), "program-name", "fceuX", "version", FCEU_VERSION_STRING, - "copyright", "© 2011 FceuX development team", + "copyright", "© 2012 FceuX development team", "license", "GPL-2; See COPYING", //"license-type", GTK_LICENSE_GPL_2_0, "website", "http://fceux.com", diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index b2431350..c3888f24 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -1479,7 +1479,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Save",IDOK,7,114,50,14 PUSHBUTTON "Cancel",IDCANCEL,65,114,50,14 - CONTROL " Binary Format of Input",IDC_CHECK_BINARY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,7,87,10 + CONTROL " Binary format of Input",IDC_CHECK_BINARY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,7,87,10 CONTROL " Markers",IDC_CHECK_MARKERS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,22,67,10 CONTROL " Bookmarks",IDC_CHECK_BOOKMARKS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,37,67,10 CONTROL " Greenzone",IDC_CHECK_GREENZONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,35,52,67,10 diff --git a/src/drivers/win/taseditor/playback.cpp b/src/drivers/win/taseditor/playback.cpp index 67c50ab7..0c55d3df 100644 --- a/src/drivers/win/taseditor/playback.cpp +++ b/src/drivers/win/taseditor/playback.cpp @@ -465,9 +465,9 @@ bool PLAYBACK::JumpToFrame(int index) } // search for an earlier frame with savestate int i = (index > 0) ? index-1 : 0; - for (; i > 0; i--) + for (; i >= 0; i--) if (greenzone.loadTasSavestate(i)) break; - if (i > 0) + if (i < 0) StartFromZero(); // couldn't find a savestate // continue from the frame if (index != currFrameCounter) diff --git a/src/drivers/win/taseditor/taseditor_config.h b/src/drivers/win/taseditor/taseditor_config.h index 0c5dc0b5..9afeaf62 100644 --- a/src/drivers/win/taseditor/taseditor_config.h +++ b/src/drivers/win/taseditor/taseditor_config.h @@ -5,8 +5,8 @@ #define GREENZONE_CAPACITY_DEFAULT 10000 #define UNDO_LEVELS_MIN 1 -#define UNDO_LEVELS_MAX 999 -#define UNDO_LEVELS_DEFAULT 99 +#define UNDO_LEVELS_MAX 1000 +#define UNDO_LEVELS_DEFAULT 100 #define AUTOSAVE_PERIOD_MIN 0 // 0 = no autosave #define AUTOSAVE_PERIOD_MAX 1440 // 24 hours diff --git a/src/drivers/win/taseditor/taseditor_project.cpp b/src/drivers/win/taseditor/taseditor_project.cpp index e310a2f7..92e3d397 100644 --- a/src/drivers/win/taseditor/taseditor_project.cpp +++ b/src/drivers/win/taseditor/taseditor_project.cpp @@ -60,7 +60,7 @@ void TASEDITOR_PROJECT::reset() void TASEDITOR_PROJECT::update() { // if it's time to autosave - pop Save As dialog - if (changed && taseditor_window.TASEditor_focus && taseditor_config.autosave_period && clock() >= next_save_shedule && piano_roll.drag_mode == DRAG_MODE_NONE) + if (changed && taseditor_window.TASEditor_focus && taseditor_config.autosave_period && !projectFile.empty() && clock() >= next_save_shedule && piano_roll.drag_mode == DRAG_MODE_NONE) { if (taseditor_config.silent_autosave) SaveProject(); @@ -69,7 +69,6 @@ void TASEDITOR_PROJECT::update() // in case user pressed Cancel, postpone saving to next time SheduleNextAutosave(); } - } bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_piano_roll, bool save_selection) @@ -148,9 +147,9 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool selection.save(ofs, save_selection); delete ofs; playback.updateProgressbar(); - // also reset autosave period if we saved the project to its current filename + // also set project.changed to false, unless it was SaveCompact if (!different_name) - this->reset(); + reset(); // restore cursor taseditor_window.must_update_mouse_cursor = true; return true; diff --git a/src/drivers/win/taseditor/taseditor_window.cpp b/src/drivers/win/taseditor/taseditor_window.cpp index 9089015c..c5bddac7 100644 --- a/src/drivers/win/taseditor/taseditor_window.cpp +++ b/src/drivers/win/taseditor/taseditor_window.cpp @@ -131,7 +131,7 @@ char taseditor_help_filename[] = "\\taseditor.chm"; // all items of the window (used for resising) and their default x,y,w,h // actual x,y,w,h are calculated at the beginning from screen Window_items_struct window_items[TASEDITOR_WINDOW_TOTAL_ITEMS] = { - IDC_PROGRESS_BUTTON, -1, 0, 0, 0, "Click here whenever you want to abort seeking", "", false, EMUCMD_TASEDITOR_CANCEL_SEEKING, 0, + IDC_PROGRESS_BUTTON, -1, 0, 0, 0, "Click here when you want to abort seeking", "", false, EMUCMD_TASEDITOR_CANCEL_SEEKING, 0, IDC_BRANCHES_BUTTON, -1, 0, 0, 0, "Click here to switch between Bookmarks List and Branches Tree", "", false, 0, 0, IDC_LIST1, 0, 0, -1, -1, "", "", false, 0, 0, IDC_PLAYBACK_BOX, -1, 0, 0, 0, "", "", false, 0, 0, @@ -147,7 +147,7 @@ Window_items_struct window_items[TASEDITOR_WINDOW_TOTAL_ITEMS] = { TASEDITOR_FORWARD_FULL, -1, 0, 0, 0, "Send Playback to next Marker (mouse: Shift+Wheel down) (hotkey: Shift+PageDown)", "", false, 0, 0, IDC_PROGRESS1, -1, 0, 0, 0, "", "", false, 0, 0, CHECK_FOLLOW_CURSOR, -1, 0, 0, 0, "The Piano Roll will follow Playback cursor movements", "", false, 0, 0, - CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0, "When you change input above Playback cursor, the cursor returns to where it was before the change", "", false, 0, 0, + CHECK_AUTORESTORE_PLAYBACK, -1, 0, 0, 0, "Whenever you change input above Playback cursor, the cursor returns to where it was before the change (hotkey: Ctrl+Spacebar)", "", false, 0, 0, IDC_BOOKMARKSLIST, -1, 0, 0, 0, "Right click = set Bookmark, Left click = jump to Bookmark or load Branch", "", false, 0, 0, IDC_HISTORYLIST, -1, 0, 0, -1, "Click to revert the project back to that time", "", false, 0, 0, IDC_RADIO_ALL, -1, 0, 0, 0, "", "", false, 0, 0, diff --git a/src/drivers/win/taseditor/taseditor_window.h b/src/drivers/win/taseditor/taseditor_window.h index 833e2b85..2d7d84b2 100644 --- a/src/drivers/win/taseditor/taseditor_window.h +++ b/src/drivers/win/taseditor/taseditor_window.h @@ -3,7 +3,7 @@ #define TASEDITOR_WINDOW_TOTAL_ITEMS 43 #define PIANOROLL_IN_WINDOWITEMS 2 -#define TOOLTIP_TEXT_MAX_LEN 100 +#define TOOLTIP_TEXT_MAX_LEN 127 #define TOOLTIPS_AUTOPOP_TIMEOUT 30000 #define PATTERNS_MENU_POS 5 diff --git a/src/ines.cpp b/src/ines.cpp index beb948b4..a910e23c 100644 --- a/src/ines.cpp +++ b/src/ines.cpp @@ -1,1430 +1,1431 @@ -/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include - -#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 "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 ; - - - -static 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: - { - FCEU_SaveGameSave(&iNESCart); - - 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; -}; - -static void SetInput(void) -{ - static struct INPSEL moo[]= - { - {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, // Nekketsu Kakutou Densetsu - - {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, // The two "Oeka Kids" games - {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, // - - {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // World Class Track Meet - {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Super Team Games - {0x61d86167,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Street Cop - {0x6435c095,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Short Order/Eggsplode - - - {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, // Top Rider - - {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, // Barcode World - {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Super Mogura Tataki!! - Pokkun Moguraa - {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Rairai Kyonshizu - {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Jogging Race - {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Athletic World - - {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Totsugeki Fuuun Takeshi Jou - {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Running Stadium - {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Meiro Dai Sakusen - // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Fuun Takeshi Jou 2 - {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Dai Undoukai - {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Aerobics Studio - {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Manhattan Police - {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Running Stadium - - {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ... - {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ... 2 - - {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong 2 - {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong - - {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic - {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic (Gentei Ban) - {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Sports - {0xad9c63e2,SI_GAMEPAD,SI_UNSET,SIFC_SHADOW}, // Space Shadow - - {0x24598791,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Duck Hunt - {0xff24d794,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Hogan's Alley - {0xbeb8ab01,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gumshoe - {0xde8fd935,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // To the Earth - {0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf - {0x2a6559a1,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf (J) - {0x4e959173,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gotcha! - The Sport! - - {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // The Lone Ranger - {0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman - {0x5112dc21,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman - {0x4318a2f8,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Barker Bill's Trick Shooting - {0x5ee6008e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Mechanized Attack - {0x3e58a87e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Freedom Force - {0xe9a7fe9e,SI_UNSET,SI_MOUSE,SIFC_NONE}, // Educational Computer 2000 //mbg merge 7/17/06 added -- appears to be from newer MM build - {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Shooting Range - {0x74bea652,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Supergun 3-in-1 - {0x32fb0583,SI_UNSET,SI_ARKANOID,SIFC_NONE}, // Arkanoid(NES) - {0xd89e5a67,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid (J) - {0x0f141525,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid 2(J) - - {0x912989dc,SI_UNSET,SI_UNSET,SIFC_FKB}, // Playbox BASIC - {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 - {0x82f1fb96,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Subor 1.0 Russian - {0xabb2f974,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Study and Game 32-in-1 - {0xd5d6eac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Edu (As) - {0x589b6b0d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV20 - {0x5e073a1b,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Supor English (Chinese) - {0x8b265862,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, - {0x41401c6d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV40 - {0x41ef9ac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, - {0x368c19a8,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Study Cartridge - {0x543ab532,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Color Lines - {0,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; - 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; -}; - -void MapperInit() -{ - if(NewiNES_Init(MapperNo)) - { - - } - else - { - iNESCart.Power=iNESPower; - if(head.ROM_type&2) - { - iNESCart.SaveGame[0]=WRAM; - iNESCart.SaveGameLen[0]=8192; - } - } -} - - -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[]= - { - 0x498c10dc463cfe95LL, /* Battle Fleet */ - 0x6917ffcaca2d8466LL, /* Famista '90 */ - - 0xd63dcc68c2b20adcLL, /* Final Fantasy J */ - 0x012df596e2b31174LL, /* Final Fantasy 1+2 */ - 0xf6b359a720549ecdLL, /* Final Fantasy 2 */ - 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */ - - 0x2ee3417ba8b69706LL, /* Hydlide 3*/ - - 0xebbce5a54cf3ecc0LL, /* Justbreed */ - - 0x6a858da551ba239eLL, /* Kaijuu Monogatari */ - 0xa40666740b7d22feLL, /* Mindseeker */ - - 0x77b811b2760104b9LL, /* Mouryou Senki Madara */ - - 0x11b69122efe86e8cLL, /* RPG Jinsei Game */ - - 0xa70b495314f4d075LL, /* Ys 3 */ - - - 0xc04361e499748382LL, /* AD&D Heroes of the Lance */ - 0xb72ee2337ced5792LL, /* AD&D Hillsfar */ - 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */ - - 0x854d7947a3177f57LL, /* Crystalis */ - - 0xb0bcc02c843c1b79LL, /* DW */ - 0x4a1f5336b86851b6LL, /* DW */ - - 0x2dcf3a98c7937c22LL, /* DW 2 */ - 0x733026b6b72f2470LL, /* Dw 3 */ - 0x98e55e09dfcc7533LL, /* DW 4*/ - 0x8da46db592a1fcf4LL, /* Faria */ - 0x91a6846d3202e3d6LL, /* Final Fantasy */ - 0xedba17a2c4608d20LL, /* "" */ - - 0x94b9484862a26cbaLL, /* Legend of Zelda */ - 0x04a31647de80fdabLL, /* "" */ - - 0x9aa1dc16c05e7de5LL, /* Startropics */ - 0x1b084107d0878bd0LL, /* Startropics 2*/ - - 0x836c0ff4f3e06e45LL, /* Zelda 2 */ - - 0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */ - - 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); - - 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}, - {"ANROM", 7, ANROM_Init}, - {"Color Dreams", 11, Mapper11_Init}, - {"", 12, Mapper12_Init}, - {"CPROM", 13, CPROM_Init}, - {"100-in1", 15, Mapper15_Init}, - {"Bandai", 16, Mapper16_Init}, - {"Namcot 106", 19, Mapper19_Init}, - {"Konami VRC2 type B", 23, Mapper23_Init}, - {"Wario Land 2", 35, UNLSC127_Init}, // Wario Land 2 - {"TXC Policeman", 36, Mapper36_Init}, // TXC Policeman - {"", 37, Mapper37_Init}, - {"Bit Corp. Crime Busters", 38, Mapper38_Init}, // Bit Corp. Crime Busters - {"", 43, Mapper43_Init}, - {"", 44, Mapper44_Init}, - {"", 45, Mapper45_Init}, - {"", 47, Mapper47_Init}, - {"", 49, Mapper49_Init}, - {"", 52, Mapper52_Init}, - {"", 57, Mapper57_Init}, - {"", 58, BMCGK192_Init}, - {"", 60, BMCD1038_Init}, - {"MHROM", 66, MHROM_Init}, - {"Sunsoft Mapper #4", 68, Mapper68_Init}, - {"", 70, Mapper70_Init}, - {"", 74, Mapper74_Init}, - {"Irem 74HC161/32", 78, Mapper78_Init}, - {"", 87, Mapper87_Init}, - {"", 88, Mapper88_Init}, - {"", 90, Mapper90_Init}, - {"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init}, - {"", 94, Mapper94_Init}, - {"", 95, Mapper95_Init}, - {"", 101, Mapper101_Init}, - {"", 103, Mapper103_Init}, - {"", 105, Mapper105_Init}, - {"", 106, Mapper106_Init}, - {"", 107, Mapper107_Init}, - {"", 108, Mapper108_Init}, - {"", 112, Mapper112_Init}, - {"", 113, Mapper113_Init}, - {"", 114, Mapper114_Init}, - {"", 115, Mapper115_Init}, - {"", 116, Mapper116_Init}, -// {116, UNLSL1632_Init}, - {"", 117, Mapper117_Init}, - {"TSKROM", 118, TKSROM_Init}, - {"", 119, Mapper119_Init}, - {"", 120, Mapper120_Init}, - {"", 121, Mapper121_Init}, - {"UNLH2288", 123, UNLH2288_Init}, - {"UNL22211", 132, UNL22211_Init}, - {"SA72008", 133, SA72008_Init}, - {"", 134, Mapper134_Init}, - {"TCU02", 136, TCU02_Init}, - {"S8259D", 137, S8259D_Init}, - {"S8259B", 138, S8259B_Init}, - {"S8259C", 139, S8259C_Init}, - {"", 140, Mapper140_Init}, - {"S8259A", 141, S8259A_Init}, - {"UNLKS7032", 142, UNLKS7032_Init}, - {"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}, - {"", 152, Mapper152_Init}, - {"", 153, Mapper153_Init}, - {"", 154, Mapper154_Init}, - {"", 155, Mapper155_Init}, - {"", 159, Mapper159_Init}, - {"SA009", 160, SA009_Init}, - {"", 163, Mapper163_Init}, - {"", 164, Mapper164_Init}, - {"", 165, Mapper165_Init}, -// {169, Mapper169_Init}, - {"", 171, Mapper171_Init}, - {"", 172, Mapper172_Init}, - {"", 173, Mapper173_Init}, - {"", 175, Mapper175_Init}, - {"BMCFK23C", 176, BMCFK23C_Init}, - {"", 177, Mapper177_Init}, - {"", 178, Mapper178_Init}, - {"", 180, Mapper180_Init}, - {"", 181, Mapper181_Init}, -// {"", 182, Mapper182_Init}, // identical to 114 - {"", 183, Mapper183_Init}, - {"", 184, Mapper184_Init}, - {"", 185, Mapper185_Init}, - {"", 186, Mapper186_Init}, - {"", 187, Mapper187_Init}, - {"", 188, Mapper188_Init}, - {"", 189, Mapper189_Init}, - {"", 191, Mapper191_Init}, - {"", 192, Mapper192_Init}, - {"", 194, Mapper194_Init}, - {"", 195, Mapper195_Init}, - {"", 196, Mapper196_Init}, - {"", 197, Mapper197_Init}, - {"", 198, Mapper198_Init}, - {"", 199, Mapper199_Init}, - {"", 200, Mapper200_Init}, - {"", 205, Mapper205_Init}, - {"DEIROM", 206, DEIROM_Init}, - {"", 208, Mapper208_Init}, - {"", 209, Mapper209_Init}, - {"", 210, Mapper210_Init}, - {"", 211, Mapper211_Init}, - {"", 215, UNL8237_Init}, - {"", 216, Mapper216_Init}, -// {"", 217, Mapper217_Init}, - {"UNLA9746", 219, UNLA9746_Init}, - {"OneBus", 220, UNLOneBus_Init}, - -// {220, BMCFK23C_Init}, -// {220, UNL3DBlock_Init}, -// {220, UNLTF1201_Init}, -// {220, TCU02_Init}, -// {220, UNLCN22M_Init}, -// {220, BMCT2271_Init}, -// {220, UNLDANCE_Init}, - - {"UNLN625092", 221, UNLN625092_Init}, - {"", 222, Mapper222_Init}, - {"", 226, Mapper226_Init}, - {"", 235, Mapper235_Init}, - {"UNL6035052", 238, UNL6035052_Init}, - {"", 240, Mapper240_Init}, - {"S74LS374NA", 243, S74LS374NA_Init}, - {"", 245, Mapper245_Init}, - {"", 249, Mapper249_Init}, - {"", 250, Mapper250_Init}, - {"", 253, Mapper253_Init}, - {"", 254, Mapper254_Init}, - {"", 0, 0} -}; - - -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(); - FCEU_LoadGameSave(&iNESCart); - - 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,"(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)= -{ - 0, - 0, - 0, //Mapper2_init, - 0, //Mapper3_init, - 0, - 0, - Mapper6_init, - 0,//Mapper7_init, - Mapper8_init, - Mapper9_init, - Mapper10_init, - 0, //Mapper11_init, - 0, - 0, //Mapper13_init, - 0, - 0, //Mapper15_init, - 0, //Mapper16_init, - Mapper17_init, - Mapper18_init, - 0, - 0, - Mapper21_init, - Mapper22_init, - 0, //Mapper23_init, - Mapper24_init, - Mapper25_init, - Mapper26_init, - Mapper27_init, - 0, - 0, - 0, - 0, - Mapper32_init, - Mapper33_init, - Mapper34_init, - 0, - 0, - 0, - 0, - 0, - Mapper40_init, - Mapper41_init, - Mapper42_init, - 0, //Mapper43_init, - 0, - 0, - Mapper46_init, - 0, - Mapper48_init, - 0, - Mapper50_init, - Mapper51_init, - 0, - 0, - 0, - 0, - 0, - 0,// Mapper57_init, - 0,// Mapper58_init, - Mapper59_init, - 0,// Mapper60_init, - Mapper61_init, - Mapper62_init, - 0, - Mapper64_init, - Mapper65_init, - 0,//Mapper66_init, - Mapper67_init, - 0,//Mapper68_init, - Mapper69_init, - 0,//Mapper70_init, - Mapper71_init, - Mapper72_init, - Mapper73_init, - 0, - Mapper75_init, - Mapper76_init, - Mapper77_init, - 0, //Mapper78_init, - Mapper79_init, - Mapper80_init, - 0, - Mapper82_init, - Mapper83_init, - 0, - Mapper85_init, - Mapper86_init, - 0, //Mapper87_init, - 0, //Mapper88_init, - Mapper89_init, - 0, - Mapper91_init, - Mapper92_init, - 0, //Mapper93_init, - 0, //Mapper94_init, - 0, - Mapper96_init, - Mapper97_init, - 0, - Mapper99_init, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, //Mapper107_init, - 0, - 0, - 0, - 0, - 0, - 0, // Mapper113_init, - 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, - Mapper151_init, - 0, //Mapper152_init, - 0, //Mapper153_init, - 0, //Mapper154_init, - 0, - Mapper156_init, - Mapper157_init, - 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, - Mapper193_init, - 0, - 0, - 0, - 0, - 0, - 0, - 0, //Mapper200_init, - Mapper201_init, - Mapper202_init, - Mapper203_init, - Mapper204_init, - 0, - 0, - Mapper207_init, - 0, - 0, - 0, - 0, //Mapper211_init, - Mapper212_init, - Mapper213_init, - Mapper214_init, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - Mapper225_init, - 0, //Mapper226_init, - Mapper227_init, - Mapper228_init, - Mapper229_init, - Mapper230_init, - Mapper231_init, - Mapper232_init, - 0, - Mapper234_init, - 0, //Mapper235_init, - 0, - 0, - 0, - 0, - 0, //Mapper240_init, - Mapper241_init, - Mapper242_init, - 0, - Mapper244_init, - 0, - Mapper246_init, - 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; -} +/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#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 "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 ; + + + +static 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: + { + FCEU_SaveGameSave(&iNESCart); + + 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; +}; + +static void SetInput(void) +{ + static struct INPSEL moo[]= + { + {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, // Nekketsu Kakutou Densetsu + + {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, // The two "Oeka Kids" games + {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, // + + {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // World Class Track Meet + {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Super Team Games + {0x61d86167,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Street Cop + {0x6435c095,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Short Order/Eggsplode + + + {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, // Top Rider + + {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, // Barcode World + {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Super Mogura Tataki!! - Pokkun Moguraa + {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Rairai Kyonshizu + {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Jogging Race + {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Athletic World + + {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Totsugeki Fuuun Takeshi Jou + {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Running Stadium + {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Meiro Dai Sakusen + // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Fuun Takeshi Jou 2 + {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Dai Undoukai + {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Aerobics Studio + {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Manhattan Police + {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Running Stadium + + {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ... + {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ... 2 + + {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong 2 + {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong + + {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic + {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic (Gentei Ban) + {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Sports + {0xad9c63e2,SI_GAMEPAD,SI_UNSET,SIFC_SHADOW}, // Space Shadow + + {0x24598791,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Duck Hunt + {0xff24d794,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Hogan's Alley + {0xbeb8ab01,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gumshoe + {0xde8fd935,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // To the Earth + {0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf + {0x2a6559a1,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf (J) + {0x4e959173,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gotcha! - The Sport! + + {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // The Lone Ranger + {0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman + {0x5112dc21,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman + {0x4318a2f8,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Barker Bill's Trick Shooting + {0x5ee6008e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Mechanized Attack + {0x3e58a87e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Freedom Force + {0xe9a7fe9e,SI_UNSET,SI_MOUSE,SIFC_NONE}, // Educational Computer 2000 //mbg merge 7/17/06 added -- appears to be from newer MM build + {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Shooting Range + {0x74bea652,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Supergun 3-in-1 + {0x32fb0583,SI_UNSET,SI_ARKANOID,SIFC_NONE}, // Arkanoid(NES) + {0xd89e5a67,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid (J) + {0x0f141525,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid 2(J) + + {0x912989dc,SI_UNSET,SI_UNSET,SIFC_FKB}, // Playbox BASIC + {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 + {0x82f1fb96,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Subor 1.0 Russian + {0xabb2f974,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Study and Game 32-in-1 + {0xd5d6eac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Edu (As) + {0x589b6b0d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV20 + {0x5e073a1b,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Supor English (Chinese) + {0x8b265862,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, + {0x41401c6d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV40 + {0x41ef9ac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, + {0x368c19a8,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Study Cartridge + {0x543ab532,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Color Lines + {0,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; + 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; +}; + +void MapperInit() +{ + if(NewiNES_Init(MapperNo)) + { + + } + else + { + iNESCart.Power=iNESPower; + if(head.ROM_type&2) + { + iNESCart.SaveGame[0]=WRAM; + iNESCart.SaveGameLen[0]=8192; + } + } +} + + +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[]= + { + 0x498c10dc463cfe95LL, /* Battle Fleet */ + 0x6917ffcaca2d8466LL, /* Famista '90 */ + + 0xd63dcc68c2b20adcLL, /* Final Fantasy J */ + 0x012df596e2b31174LL, /* Final Fantasy 1+2 */ + 0xf6b359a720549ecdLL, /* Final Fantasy 2 */ + 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */ + + 0x2ee3417ba8b69706LL, /* Hydlide 3*/ + + 0xebbce5a54cf3ecc0LL, /* Justbreed */ + + 0x6a858da551ba239eLL, /* Kaijuu Monogatari */ + 0xa40666740b7d22feLL, /* Mindseeker */ + + 0x77b811b2760104b9LL, /* Mouryou Senki Madara */ + + 0x11b69122efe86e8cLL, /* RPG Jinsei Game */ + + 0xa70b495314f4d075LL, /* Ys 3 */ + + + 0xc04361e499748382LL, /* AD&D Heroes of the Lance */ + 0xb72ee2337ced5792LL, /* AD&D Hillsfar */ + 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */ + + 0x854d7947a3177f57LL, /* Crystalis */ + + 0xb0bcc02c843c1b79LL, /* DW */ + 0x4a1f5336b86851b6LL, /* DW */ + + 0x2dcf3a98c7937c22LL, /* DW 2 */ + 0x733026b6b72f2470LL, /* Dw 3 */ + 0x98e55e09dfcc7533LL, /* DW 4*/ + 0x8da46db592a1fcf4LL, /* Faria */ + 0x91a6846d3202e3d6LL, /* Final Fantasy */ + 0xedba17a2c4608d20LL, /* "" */ + + 0x94b9484862a26cbaLL, /* Legend of Zelda */ + 0x04a31647de80fdabLL, /* "" */ + + 0x9aa1dc16c05e7de5LL, /* Startropics */ + 0x1b084107d0878bd0LL, /* Startropics 2*/ + + 0x836c0ff4f3e06e45LL, /* Zelda 2 */ + + 0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */ + + 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); + + 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}, + {"ANROM", 7, ANROM_Init}, + {"Color Dreams", 11, Mapper11_Init}, + {"", 12, Mapper12_Init}, + {"CPROM", 13, CPROM_Init}, + {"100-in1", 15, Mapper15_Init}, + {"Bandai", 16, Mapper16_Init}, + {"Namcot 106", 19, Mapper19_Init}, + {"Konami VRC2 type B", 23, Mapper23_Init}, + {"Wario Land 2", 35, UNLSC127_Init}, // Wario Land 2 + {"TXC Policeman", 36, Mapper36_Init}, // TXC Policeman + {"", 37, Mapper37_Init}, + {"Bit Corp. Crime Busters", 38, Mapper38_Init}, // Bit Corp. Crime Busters + {"", 43, Mapper43_Init}, + {"", 44, Mapper44_Init}, + {"", 45, Mapper45_Init}, + {"", 47, Mapper47_Init}, + {"", 49, Mapper49_Init}, + {"", 52, Mapper52_Init}, + {"", 57, Mapper57_Init}, + {"", 58, BMCGK192_Init}, + {"", 60, BMCD1038_Init}, + {"MHROM", 66, MHROM_Init}, + {"Sunsoft Mapper #4", 68, Mapper68_Init}, + {"", 70, Mapper70_Init}, + {"", 74, Mapper74_Init}, + {"Irem 74HC161/32", 78, Mapper78_Init}, + {"", 87, Mapper87_Init}, + {"", 88, Mapper88_Init}, + {"", 90, Mapper90_Init}, + {"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init}, + {"", 94, Mapper94_Init}, + {"", 95, Mapper95_Init}, + {"", 101, Mapper101_Init}, + {"", 103, Mapper103_Init}, + {"", 105, Mapper105_Init}, + {"", 106, Mapper106_Init}, + {"", 107, Mapper107_Init}, + {"", 108, Mapper108_Init}, + {"", 112, Mapper112_Init}, + {"", 113, Mapper113_Init}, + {"", 114, Mapper114_Init}, + {"", 115, Mapper115_Init}, + {"", 116, Mapper116_Init}, +// {116, UNLSL1632_Init}, + {"", 117, Mapper117_Init}, + {"TSKROM", 118, TKSROM_Init}, + {"", 119, Mapper119_Init}, + {"", 120, Mapper120_Init}, + {"", 121, Mapper121_Init}, + {"UNLH2288", 123, UNLH2288_Init}, + {"UNL22211", 132, UNL22211_Init}, + {"SA72008", 133, SA72008_Init}, + {"", 134, Mapper134_Init}, + {"TCU02", 136, TCU02_Init}, + {"S8259D", 137, S8259D_Init}, + {"S8259B", 138, S8259B_Init}, + {"S8259C", 139, S8259C_Init}, + {"", 140, Mapper140_Init}, + {"S8259A", 141, S8259A_Init}, + {"UNLKS7032", 142, UNLKS7032_Init}, + {"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}, + {"", 152, Mapper152_Init}, + {"", 153, Mapper153_Init}, + {"", 154, Mapper154_Init}, + {"", 155, Mapper155_Init}, + {"", 159, Mapper159_Init}, + {"SA009", 160, SA009_Init}, + {"", 163, Mapper163_Init}, + {"", 164, Mapper164_Init}, + {"", 165, Mapper165_Init}, +// {169, Mapper169_Init}, + {"", 171, Mapper171_Init}, + {"", 172, Mapper172_Init}, + {"", 173, Mapper173_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. + {"BMCFK23C", 176, Mapper176_Init}, + {"", 177, Mapper177_Init}, + {"", 178, Mapper178_Init}, + {"", 180, Mapper180_Init}, + {"", 181, Mapper181_Init}, +// {"", 182, Mapper182_Init}, // identical to 114 + {"", 183, Mapper183_Init}, + {"", 184, Mapper184_Init}, + {"", 185, Mapper185_Init}, + {"", 186, Mapper186_Init}, + {"", 187, Mapper187_Init}, + {"", 188, Mapper188_Init}, + {"", 189, Mapper189_Init}, + {"", 191, Mapper191_Init}, + {"", 192, Mapper192_Init}, + {"", 194, Mapper194_Init}, + {"", 195, Mapper195_Init}, + {"", 196, Mapper196_Init}, + {"", 197, Mapper197_Init}, + {"", 198, Mapper198_Init}, + {"", 199, Mapper199_Init}, + {"", 200, Mapper200_Init}, + {"", 205, Mapper205_Init}, + {"DEIROM", 206, DEIROM_Init}, + {"", 208, Mapper208_Init}, + {"", 209, Mapper209_Init}, + {"", 210, Mapper210_Init}, + {"", 211, Mapper211_Init}, + {"", 215, UNL8237_Init}, + {"", 216, Mapper216_Init}, +// {"", 217, Mapper217_Init}, + {"UNLA9746", 219, UNLA9746_Init}, + {"OneBus", 220, UNLOneBus_Init}, + +// {220, BMCFK23C_Init}, +// {220, UNL3DBlock_Init}, +// {220, UNLTF1201_Init}, +// {220, TCU02_Init}, +// {220, UNLCN22M_Init}, +// {220, BMCT2271_Init}, +// {220, UNLDANCE_Init}, + + {"UNLN625092", 221, UNLN625092_Init}, + {"", 222, Mapper222_Init}, + {"", 226, Mapper226_Init}, + {"", 235, Mapper235_Init}, + {"UNL6035052", 238, UNL6035052_Init}, + {"", 240, Mapper240_Init}, + {"S74LS374NA", 243, S74LS374NA_Init}, + {"", 245, Mapper245_Init}, + {"", 249, Mapper249_Init}, + {"", 250, Mapper250_Init}, + {"", 253, Mapper253_Init}, + {"", 254, Mapper254_Init}, + {"", 0, 0} +}; + + +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(); + FCEU_LoadGameSave(&iNESCart); + + 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,"(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)= +{ + 0, + 0, + 0, //Mapper2_init, + 0, //Mapper3_init, + 0, + 0, + Mapper6_init, + 0,//Mapper7_init, + Mapper8_init, + Mapper9_init, + Mapper10_init, + 0, //Mapper11_init, + 0, + 0, //Mapper13_init, + 0, + 0, //Mapper15_init, + 0, //Mapper16_init, + Mapper17_init, + Mapper18_init, + 0, + 0, + Mapper21_init, + Mapper22_init, + 0, //Mapper23_init, + Mapper24_init, + Mapper25_init, + Mapper26_init, + Mapper27_init, + 0, + 0, + 0, + 0, + Mapper32_init, + Mapper33_init, + Mapper34_init, + 0, + 0, + 0, + 0, + 0, + Mapper40_init, + Mapper41_init, + Mapper42_init, + 0, //Mapper43_init, + 0, + 0, + Mapper46_init, + 0, + Mapper48_init, + 0, + Mapper50_init, + Mapper51_init, + 0, + 0, + 0, + 0, + 0, + 0,// Mapper57_init, + 0,// Mapper58_init, + Mapper59_init, + 0,// Mapper60_init, + Mapper61_init, + Mapper62_init, + 0, + Mapper64_init, + Mapper65_init, + 0,//Mapper66_init, + Mapper67_init, + 0,//Mapper68_init, + Mapper69_init, + 0,//Mapper70_init, + Mapper71_init, + Mapper72_init, + Mapper73_init, + 0, + Mapper75_init, + Mapper76_init, + Mapper77_init, + 0, //Mapper78_init, + Mapper79_init, + Mapper80_init, + 0, + Mapper82_init, + Mapper83_init, + 0, + Mapper85_init, + Mapper86_init, + 0, //Mapper87_init, + 0, //Mapper88_init, + Mapper89_init, + 0, + Mapper91_init, + Mapper92_init, + 0, //Mapper93_init, + 0, //Mapper94_init, + 0, + Mapper96_init, + Mapper97_init, + 0, + Mapper99_init, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, //Mapper107_init, + 0, + 0, + 0, + 0, + 0, + 0, // Mapper113_init, + 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, + Mapper151_init, + 0, //Mapper152_init, + 0, //Mapper153_init, + 0, //Mapper154_init, + 0, + Mapper156_init, + Mapper157_init, + 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, + Mapper193_init, + 0, + 0, + 0, + 0, + 0, + 0, + 0, //Mapper200_init, + Mapper201_init, + Mapper202_init, + Mapper203_init, + Mapper204_init, + 0, + 0, + Mapper207_init, + 0, + 0, + 0, + 0, //Mapper211_init, + Mapper212_init, + Mapper213_init, + Mapper214_init, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Mapper225_init, + 0, //Mapper226_init, + Mapper227_init, + Mapper228_init, + Mapper229_init, + Mapper230_init, + Mapper231_init, + Mapper232_init, + 0, + Mapper234_init, + 0, //Mapper235_init, + 0, + 0, + 0, + 0, + 0, //Mapper240_init, + Mapper241_init, + Mapper242_init, + 0, + Mapper244_init, + 0, + Mapper246_init, + 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; +} diff --git a/src/ines.h b/src/ines.h index a8a1033b..98eccc0f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -415,6 +415,7 @@ void Mapper171_Init(CartInfo *); void Mapper172_Init(CartInfo *); void Mapper173_Init(CartInfo *); void Mapper175_Init(CartInfo *); +void Mapper176_Init(CartInfo *); void Mapper177_Init(CartInfo *); void Mapper178_Init(CartInfo *); void Mapper180_Init(CartInfo *);