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 *);