From d164ea7470657a2ab0f2673cb6035f879b7c85e3 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 11 Mar 2019 15:39:57 +0800 Subject: [PATCH 01/74] Move some startup variables into retro_load_game --- src/drivers/libretro/libretro.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 28e1796..618fb92 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -875,20 +875,6 @@ void retro_init(void) if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) log_cb.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); #endif - - /* initialize some of the default variables */ -#ifdef GEKKO - sndsamplerate = 32000; -#else - sndsamplerate = 48000; -#endif - sndquality = 0; - sndvolume = 150; - swapDuty = 0; - - /* Wii: initialize this or else last variable is passed through - * when loading another rom causing save state size change. */ - serialize_size = 0; } static void retro_set_custom_palette(void) @@ -2053,6 +2039,20 @@ bool retro_load_game(const struct retro_game_info *game) if (!game) return false; + /* initialize some of the default variables */ +#ifdef GEKKO + sndsamplerate = 32000; +#else + sndsamplerate = 48000; +#endif + sndquality = 0; + sndvolume = 150; + swapDuty = 0; + + /* Wii: initialize this or else last variable is passed through + * when loading another rom causing save state size change. */ + serialize_size = 0; + var.value = 0; var.key = "fceumm_ramstate"; From 5c1ddf45d452b1842e797312c18b047f42a23b7c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 27 Mar 2019 18:00:47 +0800 Subject: [PATCH 02/74] VRC7: Update instrument patch dumped by Nuke.YKT https://wiki.nesdev.com/w/index.php/VRC7_audio#cite_note-2 --- src/boards/emu2413.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/boards/emu2413.c b/src/boards/emu2413.c index 5350695..a9fabb3 100644 --- a/src/boards/emu2413.c +++ b/src/boards/emu2413.c @@ -49,22 +49,23 @@ #include "emu2413.h" static const unsigned char default_inst[15][8] = { - /* VRC7 instruments, January 17, 2004 update -Xodnizel */ - { 0x03, 0x21, 0x04, 0x06, 0x8D, 0xF2, 0x42, 0x17 }, - { 0x13, 0x41, 0x05, 0x0E, 0x99, 0x96, 0x63, 0x12 }, - { 0x31, 0x11, 0x10, 0x0A, 0xF0, 0x9C, 0x32, 0x02 }, - { 0x21, 0x61, 0x1D, 0x07, 0x9F, 0x64, 0x20, 0x27 }, - { 0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28 }, - { 0x02, 0x01, 0x06, 0x00, 0xF0, 0xF2, 0x03, 0x95 }, - { 0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x16, 0x07 }, - { 0x23, 0x21, 0x1A, 0x17, 0xEF, 0x82, 0x25, 0x15 }, - { 0x25, 0x11, 0x1F, 0x00, 0x86, 0x41, 0x20, 0x11 }, - { 0x85, 0x01, 0x1F, 0x0F, 0xE4, 0xA2, 0x11, 0x12 }, - { 0x07, 0xC1, 0x2B, 0x45, 0xB4, 0xF1, 0x24, 0xF4 }, - { 0x61, 0x23, 0x11, 0x06, 0x96, 0x96, 0x13, 0x16 }, - { 0x01, 0x02, 0xD3, 0x05, 0x82, 0xA2, 0x31, 0x51 }, - { 0x61, 0x22, 0x0D, 0x02, 0xC3, 0x7F, 0x24, 0x05 }, - { 0x21, 0x62, 0x0E, 0x00, 0xA1, 0xA0, 0x44, 0x17 }, + /* 2019-03-19 VRC7 instrument patchset dumped by Nuke.YKT */ + /* https://wiki.nesdev.com/w/index.php/VRC7_audio */ + { 0x03, 0x21, 0x05, 0x06, 0xE8, 0x81, 0x42, 0x27 }, + { 0x13, 0x41, 0x14, 0x0D, 0xD8, 0xF6, 0x23, 0x12 }, + { 0x11, 0x11, 0x08, 0x08, 0xFA, 0xB2, 0x20, 0x12 }, + { 0x31, 0x61, 0x0C, 0x07, 0xA8, 0x64, 0x61, 0x27 }, + { 0x32, 0x21, 0x1E, 0x06, 0xE1, 0x76, 0x01, 0x28 }, + { 0x02, 0x01, 0x06, 0x00, 0xA3, 0xE2, 0xF4, 0xF4 }, + { 0x21, 0x61, 0x1D, 0x07, 0x82, 0x81, 0x11, 0x07 }, + { 0x23, 0x21, 0x22, 0x17, 0xA2, 0x72, 0x01, 0x17 }, + { 0x35, 0x11, 0x25, 0x00, 0x40, 0x73, 0x72, 0x01 }, + { 0xB5, 0x01, 0x0F, 0x0F, 0xA8, 0xA5, 0x51, 0x02 }, + { 0x17, 0xC1, 0x24, 0x07, 0xF8, 0xF8, 0x22, 0x12 }, + { 0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16 }, + { 0x01, 0x02, 0xD3, 0x05, 0xC9, 0x95, 0x03, 0x02 }, + { 0x61, 0x63, 0x0C, 0x00, 0x94, 0xC0, 0x33, 0xF6 }, + { 0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06 } }; /* Size of Sintable ( 8 -- 18 can be used. 9 recommended.)*/ From f9aa5e54621031ab46c303fa3b4c1573c0b4de4a Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 11 May 2019 23:11:55 +0800 Subject: [PATCH 03/74] Add dipswitch for VS games and Mapper105 (NWC) --- Makefile.common | 3 +- src/boards/mmc1.c | 10 +- src/cart.h | 1 + src/drivers/libretro/dipswitch.c | 1525 ++++++++++++++++++++++++++++++ src/drivers/libretro/dipswitch.h | 11 + src/drivers/libretro/libretro.c | 83 +- src/git.h | 1 + src/ines.c | 1 + src/vsuni.c | 82 +- src/vsuni.h | 33 + 10 files changed, 1677 insertions(+), 73 deletions(-) create mode 100644 src/drivers/libretro/dipswitch.c create mode 100644 src/drivers/libretro/dipswitch.h diff --git a/Makefile.common b/Makefile.common index 9ee013b..37f20d9 100644 --- a/Makefile.common +++ b/Makefile.common @@ -63,4 +63,5 @@ endif SOURCES_C += \ $(CORE_DIR)/ines.c \ - $(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c + $(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c \ + $(CORE_DIR)/drivers/libretro/dipswitch.c diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index d05b29a..5a4d343 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -201,12 +201,12 @@ static int DetectMMC1WRAMSize(uint32 crc32) { static uint32 NWCIRQCount; static uint8 NWCRec; -#define NWCDIP 0xE +static int32 nwcdip = 0x4; static void NWCIRQHook(int a) { if (!(NWCRec & 0x10)) { NWCIRQCount += a; - if ((NWCIRQCount | (NWCDIP << 25)) >= 0x3e000000) { + if (NWCIRQCount >= (0x20000000 | (nwcdip << 25))) { NWCIRQCount = 0; X6502_IRQBegin(FCEU_IQEXT); } @@ -236,6 +236,11 @@ static void NWCPRGHook(uint32 A, uint8 V) { static void NWCPower(void) { GenMMC1Power(); setchr8r(0, 0); + nwcdip = (int32)GameInfo->cspecial; +} + +static void NWCReset(void) { + nwcdip = (int32)GameInfo->cspecial; } void Mapper105_Init(CartInfo *info) { @@ -244,6 +249,7 @@ void Mapper105_Init(CartInfo *info) { MMC1PRGHook16 = NWCPRGHook; MapIRQHook = NWCIRQHook; info->Power = NWCPower; + info->Reset = NWCReset; } static void GenMMC1Power(void) { diff --git a/src/cart.h b/src/cart.h index 7a7c2c4..37eca2c 100644 --- a/src/cart.h +++ b/src/cart.h @@ -10,6 +10,7 @@ typedef struct { uint32 SaveGameLen[4]; /* How much memory to save/load. */ /* Set by iNES/UNIF loading code. */ + int mapper; /* mapper used */ int mirror; /* As set in the header or chunk. * iNES/UNIF specific. Intended * to help support games like "Karnov" diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/dipswitch.c new file mode 100644 index 0000000..fabc26b --- /dev/null +++ b/src/drivers/libretro/dipswitch.c @@ -0,0 +1,1525 @@ +#include +#include + +#include "../../fceu.h" +#include "../../fceu-types.h" +#include "../../vsuni.h" +#include "../../git.h" +#include "../../driver.h" +#include "../../cart.h" + +#include "dipswitch.h" + +extern CartInfo iNESCart; + +/* VSUNI */ + +typedef struct { + char name[20]; + uint8 value; +} SETTING; + +typedef struct { + char var_name[50]; + char var_value[150]; + unsigned settings_size; + uint8 mask; + SETTING settings[8]; +} DIPSWITCH; + +typedef struct { + unsigned gameid; + char romname[100]; + unsigned dipswitch_size; + DIPSWITCH dipswitch_core_options[8]; +} VSUNIGAME; + +static VSUNIGAME dipswitch_battlecity = { + VS_BATTLECITY, + "VS. Battle City", + 3, + { + { "fceumm_dipswitch_battlecity_credits", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 2, + 0x01, + { + { "2", 0x01 }, + { "1", 0x00 } + } + }, + { "fceumm_dipswitch_battlecity_lives", + "Lives; 3|5", + 2, + 0x02, + { + { "5", 0x02 }, + { "3", 0x00 } + } + }, + { "fceumm_dipswitch_battlecity_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x04, + { + { "disabled", 0x04 }, + { "enabled", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_castlevania = { + VS_CASTLEVANIA, + "VS. Castlevania", + 4, + { + { "fceumm_dipswitch_castlevania_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_castlevania_lives", + "Lives; 3|2", + 2, + 0x08, + { + { "2", 0x08 }, + { "3", 0x00 } + } + }, + { "fceumm_dipswitch_castlevania_bonus", + "Bonus; 100k|200k|300k|400k", + 4, + 0x30, + { + { "100k", 0x00 }, + { "200k", 0x20 }, + { "300k", 0x10 }, + { "400k", 0x30 } + } + }, + { "fceumm_dipswitch_castlevania_difficulty", + "Difficulty; Normal|Hard", + 2, + 0x40, + { + { "Hard", 0x40 }, + { "Normal", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_clucluland = { + VS_CLUCLULAND, + "VS. Clu Clu Land", + 2, + { + { "fceumm_dipswitch_clucluland_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_clucluland_lives", + "Lives; 3|4|5|2", + 4, + 0x60, + { + { "2", 0x60 }, + { "3", 0x00 }, + { "4", 0x40 }, + { "5", 0x20 } + } + } + } +}; + +static VSUNIGAME dipswitch_drmario = { + VS_DRMARIO, + "VS. Dr. Mario", + 5, + { + { "fceumm_dipswitch_drmario_droprateinc", + "Drop Rate Increase After; 7 Pills|8 Pills|9 Pills|10 Pills", + 4, + 0x03, + { + { "7 Pills", 0x00 }, + { "8 Pills", 0x01 }, + { "9 Pills", 0x02 }, + { "10 Pills", 0x03 } + }, + }, + { "fceumm_dipswitch_drmario_viruslevel", + "Virus Level; 1|3|5|7", + 4, + 0x0c, + { + { "1", 0x00 }, + { "3", 0x04 }, + { "5", 0x08 }, + { "7", 0x0c } + }, + }, + { "fceumm_dipswitch_drmario_dropspeedup", + "Drop Speed Up; Slow|Medium|Fast|Fastest", + 4, + 0x30, + { + { "Slow", 0x00 }, + { "Medium", 0x10 }, + { "Fast", 0x20 }, + { "Fastest", 0x30 } + }, + }, + { "fceumm_dipswitch_drmario_freeplay", + "Free Play; disabled|enabled", + 2, + 0x40, + { + { "disabled", 0x00 }, + { "enabled", 0x40 } + }, + }, + { "fceumm_dipswitch_drmario_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x80, + { + { "disabled", 0x00 }, + { "enabled", 0x80 } + } + } + } +}; + +static VSUNIGAME dipswitch_duckhunt = { + VS_DUCKHUNT, + "VS. Duck Hunt", + 4, + { + { "fceumm_dipswitch_duckhunt_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|5 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_duckhunt_difficulty", + "Difficulty; Normal|Easy|Hard|Medium", + 4, + 0x18, + { + { "Easy", 0x00 }, + { "Normal", 0x08 }, + { "Medium", 0x10 }, + { "Hard", 0x18 } + } + }, + { "fceumm_dipswitch_duckhunt_misspergame", + "Miss per game; 5|3", + 2, + 0x20, + { + { "3", 0x00 }, + { "5", 0x20 } + } + }, + { "fceumm_dipswitch_duckhunt_bonus", + "Bonus Life; 30000|50000|80000|100000", + 4, + 0xc0, + { + { "30000", 0x00 }, + { "50000", 0x40 }, + { "80000", 0x80 }, + { "100000", 0xc0 } + } + } + } +}; + +static VSUNIGAME dipswitch_excitebike = { + VS_EXITEBIKE, + "VS. Excite Bike", + 4, + { + { "fceumm_dipswitch_excitebike_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_excitebike_bonusbike", + "Bonus Bike; 100k and Every 50k|100k Only|Every 100k|None", + 4, + 0x18, + { + { "100k and Every 50k", 0x00 }, + { "100k Only", 0x08 }, + { "Every 100k", 0x10 }, + { "None", 0x18 } + } + }, + { "fceumm_dipswitch_excitebike_1stqtime", + "1st Qualifying Time; Easy|Hard", + 2, + 0x20, + { + { "Easy", 0x00 }, + { "Hard", 0x20 } + } + }, + { "fceumm_dipswitch_excitebike_2ndqtime", + "2st Qualifying Time; Easy|Hard", + 2, + 0x40, + { + { "Easy", 0x00 }, + { "Hard", 0x40 } + } + } + } +}; + +static VSUNIGAME dipswitch_freedomforce = { + VS_FREEDOMFORCE, + "VS. Freedom Force", + 4, + { + { "fceumm_dipswitch_freedomforce_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|5 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_freedomforce_healthawd", + "Health Awarded At; 10k 50k|10k 50k Every 50k|50k 60k|20k 60k Every 60k", + 4, + 0x18, + { + { "10k 50k", 0x10 }, + { "20k 60k", 0x00 }, + { "20k 60k Every 60k", 0x08 }, + { "10k 50k Every 50k", 0x18 } + } + }, + { "fceumm_dipswitch_freedomforce_damage", + "Difficulty (Damage); Normal|Easy|Hard|Hardest", + 4, + 0x60, + { + { "Normal", 0x00 }, + { "Easy", 0x40 }, + { "Hard", 0x20 }, + { "Hardest", 0x60 } + } + }, + { "fceumm_dipswitch_freedomforce_enemy", + "Difficulty (Enemy); Normal|Hard", + 2, + 0x80, + { + { "Normal", 0x80 }, + { "Hard", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_goonies = { + VS_GOONIES, + "VS. Goonies", + 5, + { + { "fceumm_dipswitch_goonies_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_goonies_lives", + "Lives; 4|3", + 2, + 0x08, + { + { "3", 0x08 }, + { "4", 0x00 } + } + }, + { "fceumm_dipswitch_goonies_bonus", + "Bonus; 40000|50000|60000|70000", + 4, + 0x30, + { + { "40000", 0x00 }, + { "50000", 0x20 }, + { "60000", 0x10 }, + { "70000", 0x30 } + } + }, + { "fceumm_dipswitch_goonies_timer", + "Timer; Slow|Fast", + 2, + 0x40, + { + { "Slow", 0x00 }, + { "Fast", 0x40 } + } + }, + { "fceumm_dipswitch_goonies_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x80, + { + { "enabled", 0x80 }, + { "disabled", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_gradius = { + VS_GRADIUS, + "VS. Gradius", + 5, + { + { "fceumm_dipswitch_gradius_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_gradius_lives", + "Lives; 3|4", + 2, + 0x08, + { + { "3", 0x08 }, + { "4", 0x00 } + } + }, + { "fceumm_dipswitch_gradius_bonus", + "Bonus; 100k|200k|300k|400k", + 4, + 0x30, + { + { "100k", 0x00 }, + { "200k", 0x20 }, + { "300k", 0x10 }, + { "400k", 0x30 } + } + }, + { "fceumm_dipswitch_gradius_difficulty", + "Difficulty; Normal|Hard", + 2, + 0x40, + { + { "Hard", 0x40 }, + { "Normal", 0x00 } + } + }, + { "fceumm_dipswitch_gradius_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x80, + { + { "enabled", 0x80 }, + { "disabled", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_gumshoe = { + VS_GUMSHOE, + "VS. Gumshoe", + 5, + { + { "fceumm_dipswitch_gumshoe_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_gumshoe_difficulty", + "Difficulty; Normal|Easy|Hard|Hardest", + 4, + 0x18, + { + { "Normal", 0x08 }, + { "Easy", 0x00 }, + { "Hard", 0x10 }, + { "Hardest", 0x18 } + } + }, + { "fceumm_dipswitch_gumshoe_lives", + "Lives; 3|5", + 2, + 0x20, + { + { "3", 0x20 }, + { "5", 0x00 } + } + }, + { "fceumm_dipswitch_gumshoe_bullets", + "Bullets per Balloon; 3|2", + 2, + 0x40, + { + { "3", 0x00 }, + { "2", 0x40 } + } + }, + { "fceumm_dipswitch_gumshoe_bonus", + "Bonus Man Awarded; At 50000|None", + 2, + 0x80, + { + { "At 50000", 0x00 }, + { "None", 0x80 } + } + } + } +}; + +static VSUNIGAME dipswitch_hogansalley = { + VS_HOGANSALLEY, + "VS. Hogan Alley", + 4, + { + { "fceumm_dipswitch_hogansalley_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_hogansalley_difficulty", + "Difficulty; Normal|Easy|Hard|Hardest", + 4, + 0x18, + { + { "Normal", 0x08 }, + { "Easy", 0x00 }, + { "Hard", 0x10 }, + { "Hardest", 0x18 } + } + }, + { "fceumm_dipswitch_hogansalley_misspergame", + "Misses Per Game; 5|3", + 2, + 0x20, + { + { "3", 0x00 }, + { "5", 0x20 } + } + }, + { "fceumm_dipswitch_hogansalley_bonuslife", + "Bonus Life; 30000|50000|80000|100000", + 4, + 0xc0, + { + { "30000", 0x00 }, + { "50000", 0x40 }, + { "80000", 0x80 }, + { "100000", 0xc0 } + } + } + } +}; + +static VSUNIGAME dipswitch_iceclimber = { + VS_ICECLIMBER, + "VS. Ice Climber", + 4, + { + { "fceumm_dipswitch_iceclimber_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_iceclimber_lives", + "Lives; 3|4|5|7", + 4, + 0x18, + { + { "3", 0x00 }, + { "4", 0x10 }, + { "5", 0x08 }, + { "7", 0x18 } + } + }, + { "fceumm_dipswitch_iceclimber_difficulty", + "Difficulty; Easy|Hard", + 2, + 0x20, + { + { "Easy", 0x00 }, + { "Hard", 0x20 } + } + }, + { "fceumm_dipswitch_iceclimber_time", + "Time before bear appears; Long|Short", + 2, + 0x40, + { + { "Long", 0x00 }, + { "Short", 0x40 } + } + } + } +}; + +static VSUNIGAME dipswitch_jajamaru = { + VS_JAJAMARU, + "VS. Jajamaru", + 3, + { + { "fceumm_dipswitch_jajamaru_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_jajamaru_lives", + "Lives; 3|4|5", + 3, + 0x18, + { + { "3", 0x00 }, + { "4", 0x10 }, + { "5", 0x08 } + } + }, + { "fceumm_dipswitch_jajamaru_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x80, + { + { "enabled", 0x80 }, + { "disabled", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_mightybj = { + VS_MIGHTYBOMBJACK, + "VS. Mighty Bomb Jack", + 2, + { + { "fceumm_dipswitch_mightybj_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "5 Coins 1 Credit", 0x07 } + } + }, + { "fceumm_dipswitch_mightybj_lives", + "Lives; 3|4|5|2", + 4, + 0x18, + { + { "2", 0x10 }, + { "3", 0x00 }, + { "4", 0x08 }, + { "5", 0x18 } + } + } + } +}; + +static VSUNIGAME dipswitch_pinball = { + VS_PINBALL, + "VS. Pinball", + 5, + { + { "fceumm_dipswitch_pinball_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x01 }, + { "1 Coin 2 Credits", 0x06 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x04 }, + { "2 Coins 1 Credit", 0x05 }, + { "3 Coins 1 Credit", 0x03 }, + { "4 Coins 1 Credit", 0x07 }, + { "Free Play", 0x00 } + } + }, + { "fceumm_dipswitch_pinball_sidedrainwalls", + "Side Drain Walls; High|Low", + 2, + 0x08, + { + { "High", 0x00 }, + { "Low", 0x08 } + } + }, + { "fceumm_dipswitch_pinball_bonus", + "Bonus Life; 50000|70000", + 2, + 0x10, + { + { "50000", 0x00 }, + { "70000", 0x10 } + } + }, + { "fceumm_dipswitch_pinball_balls", + "Balls; 3|4|5|2", + 4, + 0x60, + { + { "2", 0x60 }, + { "3", 0x00 }, + { "4", 0x40 }, + { "5", 0x20 } + } + }, + { "fceumm_dipswitch_pinball_ballspeed", + "Ball Speed; Slow|Fast", + 2, + 0x80, + { + { "Slow", 0x00 }, + { "Fast", 0x80 } + } + } + } +}; + +static VSUNIGAME dipswitch_platoon = { + VS_PLATOON, + "VS. Platoon", + 3, + { + { "fceumm_dipswitch_platoon_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x04, + { + { "enabled", 0x00 }, + { "disabled", 0x04 } + } + }, + { "fceumm_dipswitch_platoon_difficulty", + "Difficulty; Normal|Medium|Hard|Easy", + 4, + 0x18, + { + { "Easy",0x00 }, + { "Normal", 0x08 }, + { "Medium", 0x10 }, + { "Hard",0x18 } + } + }, + { "fceumm_dipswitch_platoon_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0xe0, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x20 }, + { "1 Coin 3 Credits", 0x40 }, + { "2 Coins 1 Credit", 0x60 }, + { "3 Coins 1 Credit", 0x80 }, + { "4 Coins 1 Credit", 0xa0 }, + { "5 Coins 1 Credit", 0xc0 }, + { "Free Play", 0xe0 } + } + } + } +}; + +static VSUNIGAME dipswitch_rbibaseball = { + VS_RBIBASEBALL, + "VS. Atari R.B.I. Baseball", + 3, + { + { "fceumm_dipswitch_rbibaseball_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", + 4, + 0x03, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x01 }, + { "2 Coins 1 Credit", 0x02 }, + { "3 Coins 1 Credit", 0x03 } + } + }, + { "fceumm_dipswitch_rbibaseball_inn", + "1p-inn 2p-inn time-min; 2 2 4|3 2 6|4 3 7|2 1 3", + 4, + 0x0c, + { + { "2 1 3", 0x04 }, + { "2 2 4", 0x0c }, + { "3 2 6", 0x00 }, + { "4 3 7", 0x08 } + } + }, + { "fceumm_dipswitch_rbibaseball_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x10, + { + { "enabled", 0x00 }, + { "disabled", 0x10 } + } + } + } +}; + +static VSUNIGAME dipswitch_slalom = { + VS_SLALOM, + "VS. Slalom", + 5, + { + { "fceumm_dipswitch_slalom_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x06 }, + { "3 Coins 1 Credit", 0x01 }, + { "4 Coins 1 Credit", 0x05 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_slalom_freestylepts", + "Freestyle Points; Hold Time|Left Right", + 2, + 0x08, + { + { "Hold Time", 0x08 }, + { "Left Right", 0x00 } + } + }, + { "fceumm_dipswitch_slalom_difficulty", + "Difficulty; Normal|Medium|Hard|Easy", + 4, + 0x30, + { + { "Easy", 0x00 }, + { "Normal", 0x10 }, + { "Medium", 0x20 }, + { "Hard", 0x30 } + } + }, + { "fceumm_dipswitch_slalom_allowcontinue", + "Allow Continue; enabled|disabled", + 2, + 0x40, + { + { "enabled", 0x00 }, + { "disabled", 0x40 } + } + }, + { "fceumm_dipswitch_slalom_inverted_input", + "Inverted Input; disabled|enabled", + 2, + 0x80, + { + { "enabled", 0x80 }, + { "disabled", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_smb = { + VS_SMB, + "VS. Super Mario Bros.", + 5, + { + { "fceumm_dipswitch_smb_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|1 Coin 5 Credits|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x06 }, + { "1 Coin 3 Credits", 0x01 }, + { "1 Coin 4 Credits", 0x05 }, + { "1 Coin 5 Credits", 0x03 }, + { "2 Coins 1 Credit", 0x04 }, + { "3 Coins 1 Credit", 0x02 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_smb_lives", + "Lives; 3|2", + 2, + 0x08, + { + { "2", 0x08 }, + { "3", 0x00 } + } + }, + { "fceumm_dipswitch_smb_bonuslife", + "Bonus Life (coins); 100|150|200|250", + 4, + 0x30, + { + { "100", 0x00 }, + { "150", 0x20 }, + { "200", 0x10 }, + { "250", 0x30 } + } + }, + { "fceumm_dipswitch_smb_timer", + "Timer; Slow|Fast", + 2, + 0x40, + { + { "Slow", 0x00 }, + { "Fast", 0x40 } + } + }, + { "fceumm_dipswitch_smb_continuelives", + "Continue Lives; 3|4", + 2, + 0x80, + { + { "3", 0x80 }, + { "4", 0x00 } + } + } + } +}; + +static VSUNIGAME dipswitch_soccer = { + VS_SOCCER, + "VS. Soccer", + 3, + { + { "fceumm_dipswitch_soccer_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_soccer_pts_timer", + "Points Timer; 1000 Pts|1200 Pts|600 Pts|800 Pts", + 4, + 0x18, + { + { "600 Pts", 0x00 }, + { "800 Pts", 0x10 }, + { "1000 Pts", 0x08 }, + { "1200 Pts", 0x18 } + } + }, + { "fceumm_dipswitch_soccer_difficulty", + "Difficulty; Normal|Medium|Hard|Easy", + 4, + 0x60, + { + { "Easy",0x00 }, + { "Normal", 0x40 }, + { "Medium", 0x20 }, + { "Hard",0x60 } + } + } + } +}; + +static VSUNIGAME dipswitch_starluster = { + VS_STARLUSTER, + "VS. Star Luster", + 1, + { + { "fceumm_dipswitch_starluster_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", + 4, + 0x03, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x03 } + } + } + } +}; + +static VSUNIGAME dipswitch_superskykid = { + VS_SUPERSKYKID, + "VS. Super Sky Kid", + 3, + { + { "fceumm_dipswitch_superskykid_difficulty", + "Difficulty; Normal|Medium|Hard|Easy", + 4, + 0x03, + { + { "Easy",0x00 }, + { "Normal", 0x01 }, + { "Medium", 0x02 }, + { "Hard",0x03 } + } + }, + { "fceumm_dipswitch_superskykid_lives", + "Lives; 3|2", + 2, + 0x04, + { + { "2", 0x00 }, + { "3", 0x04 } + } + }, + { "fceumm_dipswitch_superskykid_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", + 4, + 0x18, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x08 }, + { "2 Coins 1 Credit", 0x10 }, + { "3 Coins 1 Credit", 0x18 } + } + } + } +}; + +static VSUNIGAME dipswitch_superxevious = { + VS_SUPERXEVIOUS, + "VS. Super Xevious", + 1, + { + { "fceumm_dipswitch_superxevious_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", + 4, + 0x30, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x10 }, + { "2 Coins 1 Credit", 0x20 }, + { "3 Coins 1 Credit", 0x30 } + } + } + } +}; + +static VSUNIGAME dipswitch_tetris = { + VS_TETRIS, + "VS. Tetris", + 1, + { + { "fceumm_dipswitch_tetris_difficulty", + "Difficulty; Normal|Medium|Hard|Easy", + 4, + 0x0c, + { + { "Easy",0x00 }, + { "Normal", 0x04 }, + { "Medium", 0x08 }, + { "Hard",0x0c } + } + } + } +}; + +static VSUNIGAME dipswitch_tkoboxing = { + VS_TKOBOXING, + "VS. T.K.O. Boxing", + 2, + { + { "fceumm_dipswitch_tkoboxing_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", + 4, + 0x03, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x01 }, + { "2 Coins 1 Credit", 0x02 }, + { "3 Coins 1 Credit", 0x03 } + } + }, + { "fceumm_dipswitch_tkoboxing_difficulty", + "Difficulty; Easy|Normal|Hard|Very Hard", + 4, + 0x0c, + { + { "Easy",0x00 }, + { "Normal", 0x04 }, + { "Hard",0x08 }, + { "Very Hard", 0x0c } + } + } + } +}; + +static VSUNIGAME dipswitch_topgun = { + VS_TOPGUN, + "VS. Top Gun", + 5, + { + { "fceumm_dipswitch_topgun_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x06 }, + { "5 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_topgun_livespercoin", + "Live per Coin; 3-12 Max|2-9 Max", + 2, + 0x08, + { + { "3-12 Max", 0x00 }, + { "2-9 Max", 0x08 } + } + }, + { "fceumm_dipswitch_topgun_bonuslife", + "Bonus Life; 30k and Every 50k|50k and Every 100k|100k and Every 150k|200k and Every 200k", + 4, + 0x30, + { + { "30k and Every 50k", 0x00 }, + { "50k and Every 100k", 0x20 }, + { "100k and Every 150k", 0x10 }, + { "200k and Every 200k", 0x30 } + } + }, + { "fceumm_dipswitch_topgun_difficulty", + "Difficulty; Easy|Hard", + 2, + 0x40, + { + { "Easy", 0x00 }, + { "Hard", 0x40 } + } + }, + { "fceumm_dipswitch_topgun_demosounds", + "Demo Sounds; enabled|disabled", + 2, + 0x80, + { + { "disabled", 0x00 }, + { "enabled", 0x80 } + } + } + } +}; + +static VSUNIGAME dipswitch_machrider = { + VS_MACHRIDER, + "VS. Mach Rider", + 3, + { + { "fceumm_dipswitch_machrider_coinage", + "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + 8, + 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "fceumm_dipswitch_machrider_time", + "Time; 280 (Easy)|250|220|200 (Hard)", + 4, + 0x18, + { + { "280 (Easy)", 0x00 }, + { "250", 0x10 }, + { "220", 0x08 }, + { "200 (Hard)", 0x18 } + } + }, + { "fceumm_dipswitch_machrider_enemies", + "Enemies; Less|More", + 2, + 0x40, + { + { "Less", 0x00 }, + { "More", 0x40 } + } + } + } +}; + +static struct retro_variable var_empty = { NULL, NULL }; +static struct retro_variable dipswitch_vsuni[8]; +static VSUNIGAME *vsgame = NULL; + +static int make_core_options(VSUNIGAME *tmp) +{ + unsigned ret = 0; + VSUNIGAME *vs = tmp; + + if (vs->gameid != GameInfo->gameid) + return 0; + + for (ret = 0; ret < vs->dipswitch_size; ret++) { + DIPSWITCH *coreoptions = &vs->dipswitch_core_options[ret]; + dipswitch_vsuni[ret].key = coreoptions->var_name; + dipswitch_vsuni[ret].value = coreoptions->var_value; + } + + dipswitch_vsuni[ret] = var_empty; + vsgame = vs; + + return (ret); +} + +static int get_vsuni_dipswitch(unsigned id) +{ + unsigned ret = 0; + + if (id == 0) + return 0; + + switch (id) { + case VS_BATTLECITY: + ret = make_core_options(&dipswitch_battlecity); + break; + case VS_CASTLEVANIA: + ret = make_core_options(&dipswitch_castlevania); + break; + case VS_CLUCLULAND: + ret = make_core_options(&dipswitch_clucluland); + break; + case VS_DRMARIO: + ret = make_core_options(&dipswitch_drmario); + break; + case VS_DUCKHUNT: + ret = make_core_options(&dipswitch_duckhunt); + break; + case VS_EXITEBIKE: + ret = make_core_options(&dipswitch_excitebike); + break; + case VS_FREEDOMFORCE: + ret = make_core_options(&dipswitch_freedomforce); + break; + case VS_GOONIES: + ret = make_core_options(&dipswitch_goonies); + break; + case VS_GRADIUS: + ret = make_core_options(&dipswitch_gradius); + break; + case VS_GUMSHOE: + ret = make_core_options(&dipswitch_gumshoe); + break; + case VS_HOGANSALLEY: + ret = make_core_options(&dipswitch_hogansalley); + break; + case VS_ICECLIMBER: + ret = make_core_options(&dipswitch_iceclimber); + break; + case VS_JAJAMARU: + ret = make_core_options(&dipswitch_jajamaru); + break; + /* case VS_LADIESGOLF: */ + /* case VS_STROKEANDMATCHGOLF: */ + case VS_MACHRIDER: + ret = make_core_options(&dipswitch_machrider); + break; + case VS_MIGHTYBOMBJACK: + ret = make_core_options(&dipswitch_mightybj); + break; + case VS_PINBALL: + ret = make_core_options(&dipswitch_pinball); + break; + case VS_PLATOON: + ret = make_core_options(&dipswitch_platoon); + break; + case VS_RBIBASEBALL: + ret = make_core_options(&dipswitch_rbibaseball); + break; + case VS_SLALOM: + ret = make_core_options(&dipswitch_slalom); + break; + case VS_SMB: + ret = make_core_options(&dipswitch_smb); + break; + case VS_SOCCER: + ret = make_core_options(&dipswitch_soccer); + break; + case VS_STARLUSTER: + ret = make_core_options(&dipswitch_starluster); + break; + case VS_SUPERSKYKID: + ret = make_core_options(&dipswitch_superskykid); + break; + case VS_SUPERXEVIOUS: + ret = make_core_options(&dipswitch_superxevious); + break; + case VS_TETRIS: + ret = make_core_options(&dipswitch_tetris); + break; + case VS_TKOBOXING: + ret = make_core_options(&dipswitch_tkoboxing); + break; + case VS_TOPGUN: + ret = make_core_options(&dipswitch_topgun); + break; + default: + FCEU_printf("No dipsettings found. %d\n", id); + break; + } + + return (ret); +} + +void update_dipswitch_vsuni(void) +{ + struct retro_variable var = {0}; + unsigned idx_dips, idx_var; + uint8 vsdip_new = 0x00; + + if (GameInfo->type != GIT_VSUNI) + return; + + if (vsgame == NULL) + return; + + vsdip_new = FCEUI_VSUniGetDIPs(); + for (idx_dips = 0; idx_dips < vsgame->dipswitch_size; idx_dips++) + { + DIPSWITCH *core_option = &vsgame->dipswitch_core_options[idx_dips]; + var.key = core_option->var_name; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) + continue; + for (idx_var = 0; idx_var < core_option->settings_size; idx_var++) + { + SETTING *vs_settings = &core_option->settings[idx_var]; + if (strcmp(var.value, vs_settings->name) != 0) + continue; + vsdip_new &= ~core_option->mask; + vsdip_new |= vs_settings->value; + } + } + + if (FCEUI_VSUniGetDIPs() != (uint8)vsdip_new) + { + vsdip = (uint8)vsdip_new; +#ifdef DEBUG + FCEU_printf("Dipswitch changed %d%d%d%d%d%d%d%d\n", + (vsdip >> 0) & 1, (vsdip >> 1) & 1, (vsdip >> 2) & 1, (vsdip >> 3) & 1, + (vsdip >> 4) & 1, (vsdip >> 5) & 1, (vsdip >> 6) & 1, (vsdip >> 7) & 1); +#endif + } +} + +/* Nintendo World Championship */ +static struct retro_variable dipswitch_nwc[] = { + { "fceumm_dipswitch_nwc_swa", "Dipswitch SW1 (18.7s); disabled|enabled" }, + { "fceumm_dipswitch_nwc_swb", "Dipswitch SW2 (37.5s); disabled|enabled" }, + { "fceumm_dipswitch_nwc_swc", "Dipswitch SW3 (1m 15s); enabled|disabled" }, + { "fceumm_dipswitch_nwc_swd", "Dipswitch SW4 (2m 30s); disabled|enabled" }, + { NULL, NULL } +}; + +static void update_dipswitch_nwc(void) +{ + struct retro_variable var = {0}; + unsigned dips = 0x00; + unsigned index; + + if (iNESCart.mapper != 105) + return; + + for (index = 0; index < 4; index++) + { + struct retro_variable *nwc = &dipswitch_nwc[index]; + var.key = nwc->key; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "enabled") == 0) + dips |= (1 << index); + } + } + + if (GameInfo->cspecial != dips) + { + GameInfo->cspecial = dips; +#ifdef DEBUG + FCEU_printf("Dipswitch changed = %d%d%d%d\n", (dips >> 0) & 1, + (dips >> 1) & 1, (dips >> 2) & 1, (dips >> 3) & 1); +#endif + } +} + +void set_dipswitch_variables(unsigned *index, struct retro_variable vars[]) +{ + unsigned i, idx = *index; + + /* VSUNI Dipswitch */ + if (GameInfo->type == GIT_VSUNI) + { + unsigned size = 0; + size = get_vsuni_dipswitch(GameInfo->gameid); + if (size) + { + i = 0; + while (dipswitch_vsuni[i].key) { + vars[idx] = dipswitch_vsuni[i]; + idx++; + i++; + } + } + } + + /* Nintendo World Championship cart (Mapper 105)*/ + if (iNESCart.mapper == 105) + { + i = 0; + while (dipswitch_nwc[i].key) { + vars[idx] = dipswitch_nwc[i]; + idx++; + i++; + } + } + + *index = idx; +} + +void update_dipswitch(void) +{ + if (iNESCart.mapper == 105) + update_dipswitch_nwc(); + + if (GameInfo->type == GIT_VSUNI) + update_dipswitch_vsuni(); +} diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/dipswitch.h new file mode 100644 index 0000000..6ad2bc1 --- /dev/null +++ b/src/drivers/libretro/dipswitch.h @@ -0,0 +1,11 @@ +#ifndef __VSUNI_DIPSWITCH__ +#define __VSUNI_DIPSWITCH__ + +#include + +void set_dipswitch_variables(unsigned *index, struct retro_variable vars[]); +void update_dipswitch(void); + +extern retro_environment_t environ_cb; + +#endif /* __VSUNI_DIPSWITCH__ */ diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 618fb92..98e87b1 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -29,6 +29,7 @@ #endif #include "libretro-common/include/streams/memory_stream.h" +#include "dipswitch.h" #define MAX_PLAYERS 4 /* max supported players */ #define MAX_PORTS 2 /* max controller ports, @@ -63,7 +64,7 @@ static retro_video_refresh_t video_cb = NULL; static retro_input_poll_t poll_cb = NULL; static retro_input_state_t input_cb = NULL; static retro_audio_sample_batch_t audio_batch_cb = NULL; -static retro_environment_t environ_cb = NULL; +retro_environment_t environ_cb = NULL; #ifdef PSP static bool use_overscan; #else @@ -133,6 +134,7 @@ extern uint8 *XBuf; extern CartInfo iNESCart; extern CartInfo UNIFCart; extern int show_crosshair; +extern int option_ramstate; /* emulator-specific callback functions */ @@ -737,7 +739,7 @@ void retro_set_controller_port_device(unsigned port, unsigned device) } } -void retro_set_environment(retro_environment_t cb) +static void set_variables(void) { static const struct retro_variable vars[] = { { "fceumm_region", "Region Override; Auto|NTSC|PAL|Dendy" }, @@ -767,9 +769,39 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, - { NULL, NULL }, + { NULL, NULL } }; + static struct retro_variable vars_empty = { NULL, NULL }; + static struct retro_variable retro_vars[32]; + unsigned i = 0, index_core = 0; + + while (vars[index_core].key != NULL) + { + retro_vars[index_core].key = vars[index_core].key; + retro_vars[index_core].value = vars[index_core].value; + index_core++; + } + + /* append dipswitches to core options if available */ + set_dipswitch_variables(&index_core, &retro_vars[0]); + + /* NULL terminate */ + retro_vars[index_core] = vars_empty; + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)retro_vars); + +#ifdef DEBUG + /* list core options */ + i = 0; + while (retro_vars[i].key) { + FCEU_printf(" { '%s', '%s' }\n", retro_vars[i].key, retro_vars[i].value); + i++; + } +#endif +} + +void retro_set_environment(retro_environment_t cb) +{ static const struct retro_controller_description pads1[] = { { "Auto", RETRO_DEVICE_AUTO }, { "Gamepad", RETRO_DEVICE_GAMEPAD }, @@ -816,8 +848,7 @@ void retro_set_environment(retro_environment_t cb) }; environ_cb = cb; - cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); - cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); + environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); } void retro_get_system_info(struct retro_system_info *info) @@ -1035,6 +1066,18 @@ static void check_variables(bool startup) char key[256]; int i, enable_apu; + var.key = "fceumm_ramstate"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "random")) + option_ramstate = 2; + else if (!strcmp(var.value, "fill $00")) + option_ramstate = 1; + else + option_ramstate = 0; + } + var.key = "fceumm_palette"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -1202,8 +1245,6 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - unsigned i; - turbo_enabler[0] = 0; turbo_enabler[1] = 0; @@ -1319,6 +1360,7 @@ static void check_variables(bool startup) set_apu_channels(0xff); #endif + update_dipswitch(); } static int mzx = 0, mzy = 0; @@ -1573,7 +1615,7 @@ static void retro_run_blit(uint8_t *gfx) } if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) { - printf("HW render interface mismatch, expected %u, got %u!\n", + printf("HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version); return; } @@ -1583,9 +1625,9 @@ static void retro_run_blit(uint8_t *gfx) ps2->coreTexture->PSM = GS_PSM_T8; ps2->coreTexture->ClutPSM = GS_PSM_CT16; ps2->coreTexture->Filter = GS_FILTER_LINEAR; - ps2->padding = (struct retro_hw_ps2_insets){ overscan_v ? 8.0f : 0.0f, - overscan_h ? 8.0f : 0.0f, - overscan_v ? 8.0f : 0.0f, + ps2->padding = (struct retro_hw_ps2_insets){ overscan_v ? 8.0f : 0.0f, + overscan_h ? 8.0f : 0.0f, + overscan_v ? 8.0f : 0.0f, overscan_h ? 8.0f : 0.0f}; } @@ -1971,7 +2013,6 @@ static char slash = '/'; #endif extern uint32_t iNESGameCRC32; -extern int option_ramstate; bool retro_load_game(const struct retro_game_info *game) { @@ -2034,7 +2075,6 @@ bool retro_load_game(const struct retro_game_info *game) struct retro_memory_descriptor descs[64]; struct retro_memory_map mmaps; - struct retro_variable var = {0}; if (!game) return false; @@ -2053,20 +2093,6 @@ bool retro_load_game(const struct retro_game_info *game) * when loading another rom causing save state size change. */ serialize_size = 0; - var.value = 0; - var.key = "fceumm_ramstate"; - - /* set this variable before calling PowerNES() */ - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (!strcmp(var.value, "random")) - option_ramstate = 2; - else if (!strcmp(var.value, "fill $00")) - option_ramstate = 1; - else - option_ramstate = 0; - } - PowerNES(); check_system_specs(); #if defined(_3DS) @@ -2113,9 +2139,10 @@ bool retro_load_game(const struct retro_game_info *game) is_PAL = retro_get_region(); /* Save current loaded region info */ retro_set_custom_palette(); - FCEUD_SoundToggle(); + set_variables(); check_variables(true); + PowerNES(); FCEUI_DisableFourScore(1); diff --git a/src/git.h b/src/git.h index 3645168..913ac60 100644 --- a/src/git.h +++ b/src/git.h @@ -25,6 +25,7 @@ typedef struct { uint8 MD5[16]; int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */ int soundchan; /* Number of sound channels. */ + int gameid; /* VS game id for per-game settings e.g. dip switches */ } FCEUGI; #endif diff --git a/src/ines.c b/src/ines.c index 9bb3ef7..83591df 100644 --- a/src/ines.c +++ b/src/ines.c @@ -792,6 +792,7 @@ int iNESLoad(const char *name, FCEUFILE *fp) { if (!iNES_Init(MapperNo)) FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo); + iNESCart.mapper = MapperNo; GameInterface = iNESGI; FCEU_printf("\n"); diff --git a/src/vsuni.c b/src/vsuni.c index 2da1562..b7b4134 100644 --- a/src/vsuni.c +++ b/src/vsuni.c @@ -34,6 +34,7 @@ typedef struct { char *name; + int gameid; uint64 md5partial; int mapper; int mirroring; @@ -245,48 +246,44 @@ RC2C05-04: VSUNIENTRY VSUniGames[] = { - { "Baseball", 0x691d4200ea42be45LL, 99, 2, RP2C04_0001, 0 }, - { "Battle City", 0x8540949d74c4d0ebLL, 99, 2, RP2C04_0001, 0 }, - { "Battle City(Bootleg)", 0x8093cbe7137ac031LL, 99, 2, RP2C04_0001, 0 }, - - { "Clu Clu Land", 0x1b8123218f62b1eeLL, 99, 2, RP2C04_0004, IOPTION_SWAPDIRAB }, - { "Dr Mario", 0xe1af09c477dc0081LL, 1, 0, RP2C04_0003, IOPTION_SWAPDIRAB }, - { "Duck Hunt", 0x47735d1e5f1205bbLL, 99, 2, RCP2C03B, IOPTION_GUN }, - { "Excitebike", 0x3dcd1401bcafde77LL, 99, 2, RP2C04_0003, 0 }, - { "Excitebike (J)", 0x7ea51c9d007375f0LL, 99, 2, RP2C04_0004, 0 }, - { "Freedom Force", 0xed96436bd1b5e688LL, 4, 0, RP2C04_0001, IOPTION_GUN }, /* Wrong color in game select screen? */ - { "Stroke and Match Golf", 0x612325606e82bc66LL, 99, 2, RP2C04_0002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x01 }, - - { "Goonies", 0xb4032d694e1d2733LL, 151, 1, RP2C04_0003, 0 }, - { "Gradius", 0x50687ae63bdad976LL, 151, 1, RP2C04_0001, IOPTION_SWAPDIRAB }, - { "Gumshoe", 0x87161f8ee37758d3LL, 99, 2, RC2C05_03, IOPTION_GUN }, - { "Gumshoe", 0xb8500780bf69ce29LL, 99, 2, RC2C05_03, IOPTION_GUN }, - { "Gumshoe", 0xa6bf132ba11d0a8cLL, 99, 2, RC2C05_03, IOPTION_GUN }, /* Gumshoe (VS).nes added: 2017-9-5*/ - { "Hogan's Alley", 0xd78b7f0bb621fb45LL, 99, 2, RP2C04_0001, IOPTION_GUN }, - { "Ice Climber", 0xd21e999513435e2aLL, 99, 2, RP2C04_0004, IOPTION_SWAPDIRAB }, - { "Ladies Golf", 0x781b24be57ef6785LL, 99, 2, RP2C04_0002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 }, - - { "Mach Rider", 0x015672618af06441LL, 99, 2, RP2C04_0002, 0 }, - { "Mach Rider (J)", 0xa625afb399811a8aLL, 99, 2, RP2C04_0001, 0 }, - { "Mighty Bomb Jack", 0xe6a89f4873fac37bLL, 0, 2, RC2C05_02, 0 }, - { "Ninja Jajamaru Kun", 0xb26a2c31474099c0LL, 99, 2, RC2C05_01, IOPTION_SWAPDIRAB }, - { "Pinball", 0xc5f49d3de7f2e9b8LL, 99, 2, RP2C04_0001, IOPTION_PREDIP, 0x01 }, - { "Pinball (J)", 0x66ab1a3828cc901cLL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x1 }, - { "Platoon", 0x160f237351c19f1fLL, 68, 1, RP2C04_0001, 0 }, - { "RBI Baseball", 0x6a02d345812938afLL, 4, 1, RP2C04_0001, IOPTION_SWAPDIRAB }, - { "Soccer", 0xd4e7a9058780eda3LL, 99, 2, RP2C04_0003, IOPTION_SWAPDIRAB }, - { "Star Luster", 0x8360e134b316d94cLL, 99, 2, RCP2C03B, 0 }, - { "Stroke and Match Golf (J)", 0x869bb83e02509747LL, 99, 2, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 }, - { "Super Sky Kid", 0x78d04c1dd4ec0101LL, 4, 1, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x20 }, - - { "Super Xevious", 0x2d396247cf58f9faLL, 206, 0, RP2C04_0001, 0 }, - { "Tetris", 0x531a5e8eea4ce157LL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x20 }, - { "Top Gun", 0xf1dea36e6a7b531dLL, 2, 0, RC2C05_04, 0 }, - { "VS Castlevania", 0x92fd6909c81305b9LL, 2, 1, RP2C04_0002, 0 }, - { "VS Slalom", 0x4889b5a50a623215LL, 0, 1, RP2C04_0002, 0 }, - { "VS Super Mario Bros", 0x39d8cfa788e20b6cLL, 99, 2, RP2C04_0004, 0 }, - { "VS Super Mario Bros [a1]", 0xfc182e5aefbce14dLL, 99, 2, RP2C04_0004, 0 }, - { "VS TKO Boxing", 0x6e1ee06171d8ce3aLL, 4, 1, RP2C04_0003, IOPTION_PREDIP, 0x00 }, + { "Baseball", VS_BASEBALL, 0x691d4200ea42be45LL, 99, 2, RP2C04_0001, 0 }, + { "Battle City", VS_BATTLECITY, 0x8540949d74c4d0ebLL, 99, 2, RP2C04_0001, 0 }, + { "Battle City(Bootleg)", VS_BATTLECITY, 0x8093cbe7137ac031LL, 99, 2, RP2C04_0001, 0 }, + { "Clu Clu Land", VS_CLUCLULAND, 0x1b8123218f62b1eeLL, 99, 2, RP2C04_0004, IOPTION_SWAPDIRAB }, + { "Dr Mario", VS_DRMARIO, 0xe1af09c477dc0081LL, 1, 0, RP2C04_0003, IOPTION_SWAPDIRAB }, + { "Duck Hunt", VS_DUCKHUNT, 0x47735d1e5f1205bbLL, 99, 2, RCP2C03B, IOPTION_GUN }, + { "Excitebike", VS_EXITEBIKE, 0x3dcd1401bcafde77LL, 99, 2, RP2C04_0003, 0 }, + { "Excitebike (J)", VS_EXITEBIKE, 0x7ea51c9d007375f0LL, 99, 2, RP2C04_0004, 0 }, + { "Freedom Force", VS_FREEDOMFORCE, 0xed96436bd1b5e688LL, 4, 0, RP2C04_0001, IOPTION_GUN }, /* Wrong color in game select screen? */ + { "Stroke and Match Golf", VS_STROKEANDMATCHGOLF, 0x612325606e82bc66LL, 99, 2, RP2C04_0002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x01 }, + { "Goonies", VS_GOONIES, 0xb4032d694e1d2733LL, 151, 1, RP2C04_0003, 0 }, + { "Gradius", VS_GRADIUS, 0x50687ae63bdad976LL, 151, 1, RP2C04_0001, IOPTION_SWAPDIRAB }, + { "Gumshoe", VS_GUMSHOE, 0x87161f8ee37758d3LL, 99, 2, RC2C05_03, IOPTION_GUN }, + { "Gumshoe", VS_GUMSHOE, 0xb8500780bf69ce29LL, 99, 2, RC2C05_03, IOPTION_GUN }, + { "Gumshoe", VS_GUMSHOE, 0xa6bf132ba11d0a8cLL, 99, 2, RC2C05_03, IOPTION_GUN }, /* Gumshoe (VS).nes added: 2017-9-5*/ + { "Hogan's Alley", VS_HOGANSALLEY, 0xd78b7f0bb621fb45LL, 99, 2, RP2C04_0001, IOPTION_GUN }, + { "Ice Climber", VS_ICECLIMBER, 0xd21e999513435e2aLL, 99, 2, RP2C04_0004, IOPTION_SWAPDIRAB }, + { "Ladies Golf", VS_LADIESGOLF, 0x781b24be57ef6785LL, 99, 2, RP2C04_0002, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 }, + { "Mach Rider", VS_MACHRIDER, 0x015672618af06441LL, 99, 2, RP2C04_0002, 0 }, + { "Mach Rider (J)", VS_MACHRIDER, 0xa625afb399811a8aLL, 99, 2, RP2C04_0001, 0 }, + { "Mighty Bomb Jack", VS_MIGHTYBOMBJACK, 0xe6a89f4873fac37bLL, 0, 2, RC2C05_02, 0 }, + { "Ninja Jajamaru Kun", VS_JAJAMARU, 0xb26a2c31474099c0LL, 99, 2, RC2C05_01, IOPTION_SWAPDIRAB }, + { "Pinball", VS_PINBALL, 0xc5f49d3de7f2e9b8LL, 99, 2, RP2C04_0001, IOPTION_PREDIP, 0x01 }, + { "Pinball (J)", VS_PINBALL, 0x66ab1a3828cc901cLL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x1 }, + { "Platoon", VS_PLATOON, 0x160f237351c19f1fLL, 68, 1, RP2C04_0001, 0 }, + { "RBI Baseball", VS_RBIBASEBALL, 0x6a02d345812938afLL, 4, 1, RP2C04_0001, IOPTION_SWAPDIRAB }, + { "Soccer", VS_SOCCER, 0xd4e7a9058780eda3LL, 99, 2, RP2C04_0003, IOPTION_SWAPDIRAB }, + { "Star Luster", VS_STARLUSTER, 0x8360e134b316d94cLL, 99, 2, RCP2C03B, 0 }, + { "Stroke and Match Golf (J)", VS_STROKEANDMATCHGOLF, 0x869bb83e02509747LL, 99, 2, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x1 }, + { "Super Sky Kid", VS_SUPERSKYKID, 0x78d04c1dd4ec0101LL, 4, 1, RCP2C03B, IOPTION_SWAPDIRAB | IOPTION_PREDIP, 0x20 }, + { "Super Xevious", VS_SUPERXEVIOUS, 0x2d396247cf58f9faLL, 206, 0, RP2C04_0001, 0 }, + { "Tetris", VS_TETRIS, 0x531a5e8eea4ce157LL, 99, 2, RCP2C03B, IOPTION_PREDIP, 0x20 }, + { "Top Gun", VS_TOPGUN, 0xf1dea36e6a7b531dLL, 2, 0, RC2C05_04, 0 }, + { "VS Castlevania", VS_CASTLEVANIA, 0x92fd6909c81305b9LL, 2, 1, RP2C04_0002, 0 }, + { "VS Slalom", VS_SLALOM, 0x4889b5a50a623215LL, 0, 1, RP2C04_0002, 0 }, + { "VS Super Mario Bros", VS_SMB, 0x39d8cfa788e20b6cLL, 99, 2, RP2C04_0004, 0 }, + { "VS Super Mario Bros [a1]", VS_SMB, 0xfc182e5aefbce14dLL, 99, 2, RP2C04_0004, 0 }, + { "VS TKO Boxing", VS_TKOBOXING, 0x6e1ee06171d8ce3aLL, 4, 1, RP2C04_0003, IOPTION_PREDIP, 0x00 }, { 0 } }; @@ -302,6 +299,7 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) { GameInfo->type = GIT_VSUNI; GameInfo->cspecial = SIS_VSUNISYSTEM; GameInfo->inputfc = SIFC_NONE; + GameInfo->gameid = vs->gameid; curppu = vs->ppu; curmd5 = md5partial; diff --git a/src/vsuni.h b/src/vsuni.h index 8457bb7..8248885 100644 --- a/src/vsuni.h +++ b/src/vsuni.h @@ -9,4 +9,37 @@ void FCEU_VSUniToggleDIP(int); /* For movies and netplay */ void FCEU_VSUniCoin(void); void FCEU_VSUniSwap(uint8 *j0, uint8 *j1); +enum { + VS_BASEBALL = 1, + VS_BATTLECITY, + VS_CASTLEVANIA, + VS_CLUCLULAND, + VS_DRMARIO, + VS_DUCKHUNT, + VS_EXITEBIKE, + VS_FREEDOMFORCE, + VS_GOONIES, + VS_GRADIUS, + VS_GUMSHOE, + VS_HOGANSALLEY, + VS_ICECLIMBER, + VS_JAJAMARU, + VS_LADIESGOLF, + VS_MACHRIDER, + VS_MIGHTYBOMBJACK, + VS_PINBALL, + VS_PLATOON, + VS_RBIBASEBALL, + VS_SLALOM, + VS_SMB, + VS_SOCCER, + VS_STARLUSTER, + VS_STROKEANDMATCHGOLF, + VS_SUPERSKYKID, + VS_SUPERXEVIOUS, + VS_TETRIS, + VS_TKOBOXING, + VS_TOPGUN +}; + #endif From 16b689f7e03ac2dfdd8d193f56d64d3c942135d3 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 18 May 2019 22:39:23 +0800 Subject: [PATCH 04/74] Fix other input types not working on startup when type is set to auto --- src/drivers/libretro/libretro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 98e87b1..521f50d 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -689,7 +689,7 @@ static unsigned fc_to_libretro(int d) void retro_set_controller_port_device(unsigned port, unsigned device) { - if ((port < 5) && (input_type[port] != device)) + if (port < 5) { if (port < 2) /* player 1-2 */ { @@ -2129,7 +2129,7 @@ bool retro_load_game(const struct retro_game_info *game) for (i = 0; i < MAX_PORTS; i++) { FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0); - input_type[i] == RETRO_DEVICE_JOYPAD; + input_type[i] = RETRO_DEVICE_JOYPAD; } external_palette_exist = ipalette; From b868d519aba01931fc059667e49d9c7f4ed8325e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 18 May 2019 22:43:28 +0800 Subject: [PATCH 05/74] Remove duplicates in Makefile.libretro --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 140b874..abf874b 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -693,7 +693,7 @@ else WARNING_DEFINES = -Wno-write-strings endif -CFLAGS += $(COREDEFINES) $(fpic) $(WARNING_DEFINES) $(DEFINES) $(ENDIANNESS_DEFINES) +CFLAGS += $(fpic) $(WARNING_DEFINES) $(DEFINES) $(ENDIANNESS_DEFINES) LDFLAGS += $(LIBM) ifeq ($(platform), psp1) From a3a16a68e750b4ba61355d2e515a120163e298c1 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 18 May 2019 23:10:00 +0800 Subject: [PATCH 06/74] vsuni: Add "VS TKO Boxing [a1]" to supported games --- src/vsuni.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vsuni.c b/src/vsuni.c index b7b4134..6c7dc1c 100644 --- a/src/vsuni.c +++ b/src/vsuni.c @@ -283,7 +283,8 @@ VSUNIENTRY VSUniGames[] = { "VS Slalom", VS_SLALOM, 0x4889b5a50a623215LL, 0, 1, RP2C04_0002, 0 }, { "VS Super Mario Bros", VS_SMB, 0x39d8cfa788e20b6cLL, 99, 2, RP2C04_0004, 0 }, { "VS Super Mario Bros [a1]", VS_SMB, 0xfc182e5aefbce14dLL, 99, 2, RP2C04_0004, 0 }, - { "VS TKO Boxing", VS_TKOBOXING, 0x6e1ee06171d8ce3aLL, 4, 1, RP2C04_0003, IOPTION_PREDIP, 0x00 }, + { "VS TKO Boxing", VS_TKOBOXING, 0x6e1ee06171d8ce3aLL, 206, 1, RP2C04_0003, IOPTION_PREDIP, 0x00 }, + { "VS TKO Boxing [a1]", VS_TKOBOXING, 0xa1c694ce147bc1edLL, 206, 1, RP2C04_0003, IOPTION_PREDIP, 0x00 }, { 0 } }; @@ -303,11 +304,14 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) { curppu = vs->ppu; curmd5 = md5partial; + FCEU_printf(" System: VS-UniSystem\n"); + FCEU_printf(" Name: %s\n", vs->name); + secptr = 0; { static int64 tko = 0x6e1ee06171d8ce3aULL, rbi = 0x6a02d345812938afULL; - if (md5partial == tko) + if (vs->gameid & VS_TKOBOXING) secptr = secdata[0]; if (md5partial == rbi) secptr = secdata[1]; From e654ed305c7b48d393ab359ba33e73718425c318 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 21 May 2019 20:29:53 +0800 Subject: [PATCH 07/74] vsuni: simplify game database and other fixes - simplify game database - remove pre-configured core options. they are now created on a per-game basis on rom load. - some minor data type changes --- src/drivers/libretro/dipswitch.c | 931 ++++++++++--------------------- src/drivers/libretro/dipswitch.h | 2 +- src/drivers/libretro/libretro.c | 2 +- 3 files changed, 294 insertions(+), 641 deletions(-) diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/dipswitch.c index fabc26b..610dde2 100644 --- a/src/drivers/libretro/dipswitch.c +++ b/src/drivers/libretro/dipswitch.c @@ -12,16 +12,13 @@ extern CartInfo iNESCart; -/* VSUNI */ - typedef struct { - char name[20]; + char *name; uint8 value; } SETTING; typedef struct { - char var_name[50]; - char var_value[150]; + const char *option_name; unsigned settings_size; uint8 mask; SETTING settings[8]; @@ -29,38 +26,27 @@ typedef struct { typedef struct { unsigned gameid; - char romname[100]; + char *romname_short; unsigned dipswitch_size; - DIPSWITCH dipswitch_core_options[8]; + DIPSWITCH dipswitch_core_options[5]; } VSUNIGAME; static VSUNIGAME dipswitch_battlecity = { - VS_BATTLECITY, - "VS. Battle City", - 3, + VS_BATTLECITY, "battlecity", 3, { - { "fceumm_dipswitch_battlecity_credits", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 2, - 0x01, + { "Credits for 2 Players", 2, 0x01, { { "2", 0x01 }, { "1", 0x00 } } }, - { "fceumm_dipswitch_battlecity_lives", - "Lives; 3|5", - 2, - 0x02, + { "Lives", 2, 0x02, { { "5", 0x02 }, { "3", 0x00 } } }, - { "fceumm_dipswitch_battlecity_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x04, + { "Demo Sounds", 2, 0x04, { { "disabled", 0x04 }, { "enabled", 0x00 } @@ -70,12 +56,9 @@ static VSUNIGAME dipswitch_battlecity = { }; static VSUNIGAME dipswitch_castlevania = { - VS_CASTLEVANIA, - "VS. Castlevania", - 4, + VS_CASTLEVANIA, "castlevania", 4, { - { "fceumm_dipswitch_castlevania_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", + { "Coinage", 8, 0x07, { @@ -89,19 +72,14 @@ static VSUNIGAME dipswitch_castlevania = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_castlevania_lives", - "Lives; 3|2", - 2, - 0x08, + { "Lives", 2, 0x08, { - { "2", 0x08 }, - { "3", 0x00 } + { "3", 0x00 }, + { "2", 0x08 } + } }, - { "fceumm_dipswitch_castlevania_bonus", - "Bonus; 100k|200k|300k|400k", - 4, - 0x30, + { "Bonus", 4, 0x30, { { "100k", 0x00 }, { "200k", 0x20 }, @@ -109,27 +87,19 @@ static VSUNIGAME dipswitch_castlevania = { { "400k", 0x30 } } }, - { "fceumm_dipswitch_castlevania_difficulty", - "Difficulty; Normal|Hard", - 2, - 0x40, + { "Difficulty", 2, 0x40, { - { "Hard", 0x40 }, - { "Normal", 0x00 } + { "Normal", 0x00 }, + { "Hard", 0x40 } } } } }; static VSUNIGAME dipswitch_clucluland = { - VS_CLUCLULAND, - "VS. Clu Clu Land", - 2, + VS_CLUCLULAND, "clucluland", 2, { - { "fceumm_dipswitch_clucluland_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -141,29 +111,21 @@ static VSUNIGAME dipswitch_clucluland = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_clucluland_lives", - "Lives; 3|4|5|2", - 4, - 0x60, + { "Lives", 4, 0x60, { - { "2", 0x60 }, { "3", 0x00 }, { "4", 0x40 }, - { "5", 0x20 } + { "5", 0x20 }, + { "2", 0x60 } } } } }; static VSUNIGAME dipswitch_drmario = { - VS_DRMARIO, - "VS. Dr. Mario", - 5, + VS_DRMARIO, "drmario", 5, { - { "fceumm_dipswitch_drmario_droprateinc", - "Drop Rate Increase After; 7 Pills|8 Pills|9 Pills|10 Pills", - 4, - 0x03, + { "Drop Rate Increase After", 4, 0x03, { { "7 Pills", 0x00 }, { "8 Pills", 0x01 }, @@ -171,10 +133,7 @@ static VSUNIGAME dipswitch_drmario = { { "10 Pills", 0x03 } }, }, - { "fceumm_dipswitch_drmario_viruslevel", - "Virus Level; 1|3|5|7", - 4, - 0x0c, + { "Virus Level", 4, 0x0c, { { "1", 0x00 }, { "3", 0x04 }, @@ -182,10 +141,7 @@ static VSUNIGAME dipswitch_drmario = { { "7", 0x0c } }, }, - { "fceumm_dipswitch_drmario_dropspeedup", - "Drop Speed Up; Slow|Medium|Fast|Fastest", - 4, - 0x30, + { "Drop Speed Up", 4, 0x30, { { "Slow", 0x00 }, { "Medium", 0x10 }, @@ -193,36 +149,25 @@ static VSUNIGAME dipswitch_drmario = { { "Fastest", 0x30 } }, }, - { "fceumm_dipswitch_drmario_freeplay", - "Free Play; disabled|enabled", - 2, - 0x40, + { "Free Play", 2, 0x40, { { "disabled", 0x00 }, { "enabled", 0x40 } }, }, - { "fceumm_dipswitch_drmario_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x80, + { "Demo Sounds", 2, 0x80, { - { "disabled", 0x00 }, - { "enabled", 0x80 } + { "enabled", 0x80 }, + { "disabled", 0x00 } } } } }; static VSUNIGAME dipswitch_duckhunt = { - VS_DUCKHUNT, - "VS. Duck Hunt", - 4, + VS_DUCKHUNT, "duckhunt", 4, { - { "fceumm_dipswitch_duckhunt_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|5 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -234,30 +179,21 @@ static VSUNIGAME dipswitch_duckhunt = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_duckhunt_difficulty", - "Difficulty; Normal|Easy|Hard|Medium", - 4, - 0x18, + { "Difficulty", 4, 0x18, { - { "Easy", 0x00 }, { "Normal", 0x08 }, { "Medium", 0x10 }, - { "Hard", 0x18 } + { "Hard", 0x18 }, + { "Easy", 0x00 } } }, - { "fceumm_dipswitch_duckhunt_misspergame", - "Miss per game; 5|3", - 2, - 0x20, + { "Miss per game", 2, 0x20, { - { "3", 0x00 }, - { "5", 0x20 } + { "5", 0x20 }, + { "3", 0x00 } } }, - { "fceumm_dipswitch_duckhunt_bonus", - "Bonus Life; 30000|50000|80000|100000", - 4, - 0xc0, + { "Bonus Life", 4, 0xc0, { { "30000", 0x00 }, { "50000", 0x40 }, @@ -269,14 +205,9 @@ static VSUNIGAME dipswitch_duckhunt = { }; static VSUNIGAME dipswitch_excitebike = { - VS_EXITEBIKE, - "VS. Excite Bike", - 4, + VS_EXITEBIKE, "excitebike", 4, { - { "fceumm_dipswitch_excitebike_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -288,10 +219,7 @@ static VSUNIGAME dipswitch_excitebike = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_excitebike_bonusbike", - "Bonus Bike; 100k and Every 50k|100k Only|Every 100k|None", - 4, - 0x18, + { "Bonus Bike", 4, 0x18, { { "100k and Every 50k", 0x00 }, { "100k Only", 0x08 }, @@ -299,19 +227,13 @@ static VSUNIGAME dipswitch_excitebike = { { "None", 0x18 } } }, - { "fceumm_dipswitch_excitebike_1stqtime", - "1st Qualifying Time; Easy|Hard", - 2, - 0x20, + { "1st Qualifying Time", 2, 0x20, { { "Easy", 0x00 }, { "Hard", 0x20 } } }, - { "fceumm_dipswitch_excitebike_2ndqtime", - "2st Qualifying Time; Easy|Hard", - 2, - 0x40, + { "2nd Qualifying Time", 2, 0x40, { { "Easy", 0x00 }, { "Hard", 0x40 } @@ -321,14 +243,9 @@ static VSUNIGAME dipswitch_excitebike = { }; static VSUNIGAME dipswitch_freedomforce = { - VS_FREEDOMFORCE, - "VS. Freedom Force", - 4, + VS_FREEDOMFORCE, "freedomforce", 4, { - { "fceumm_dipswitch_freedomforce_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|2 Coins 1 Credit|3 Coins 1 Credit|4 Coins 1 Credit|5 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -340,10 +257,7 @@ static VSUNIGAME dipswitch_freedomforce = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_freedomforce_healthawd", - "Health Awarded At; 10k 50k|10k 50k Every 50k|50k 60k|20k 60k Every 60k", - 4, - 0x18, + { "Health Awarded At", 4, 0x18, { { "10k 50k", 0x10 }, { "20k 60k", 0x00 }, @@ -351,10 +265,7 @@ static VSUNIGAME dipswitch_freedomforce = { { "10k 50k Every 50k", 0x18 } } }, - { "fceumm_dipswitch_freedomforce_damage", - "Difficulty (Damage); Normal|Easy|Hard|Hardest", - 4, - 0x60, + { "Difficulty (Damage)", 4, 0x60, { { "Normal", 0x00 }, { "Easy", 0x40 }, @@ -362,10 +273,7 @@ static VSUNIGAME dipswitch_freedomforce = { { "Hardest", 0x60 } } }, - { "fceumm_dipswitch_freedomforce_enemy", - "Difficulty (Enemy); Normal|Hard", - 2, - 0x80, + { "Difficulty (Enemy)", 2, 0x80, { { "Normal", 0x80 }, { "Hard", 0x00 } @@ -375,14 +283,9 @@ static VSUNIGAME dipswitch_freedomforce = { }; static VSUNIGAME dipswitch_goonies = { - VS_GOONIES, - "VS. Goonies", - 5, + VS_GOONIES, "goonies", 5, { - { "fceumm_dipswitch_goonies_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -394,19 +297,13 @@ static VSUNIGAME dipswitch_goonies = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_goonies_lives", - "Lives; 4|3", - 2, - 0x08, + { "Lives", 2, 0x08, { { "3", 0x08 }, { "4", 0x00 } } }, - { "fceumm_dipswitch_goonies_bonus", - "Bonus; 40000|50000|60000|70000", - 4, - 0x30, + { "Bonus", 4, 0x30, { { "40000", 0x00 }, { "50000", 0x20 }, @@ -414,19 +311,13 @@ static VSUNIGAME dipswitch_goonies = { { "70000", 0x30 } } }, - { "fceumm_dipswitch_goonies_timer", - "Timer; Slow|Fast", - 2, - 0x40, + { "Timer", 2, 0x40, { { "Slow", 0x00 }, { "Fast", 0x40 } } }, - { "fceumm_dipswitch_goonies_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x80, + { "Demo Sounds", 2, 0x80, { { "enabled", 0x80 }, { "disabled", 0x00 } @@ -436,14 +327,9 @@ static VSUNIGAME dipswitch_goonies = { }; static VSUNIGAME dipswitch_gradius = { - VS_GRADIUS, - "VS. Gradius", - 5, + VS_GRADIUS, "gradius", 5, { - { "fceumm_dipswitch_gradius_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -455,19 +341,13 @@ static VSUNIGAME dipswitch_gradius = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_gradius_lives", - "Lives; 3|4", - 2, - 0x08, + { "Lives", 2, 0x08, { { "3", 0x08 }, { "4", 0x00 } } }, - { "fceumm_dipswitch_gradius_bonus", - "Bonus; 100k|200k|300k|400k", - 4, - 0x30, + { "Bonus", 4, 0x30, { { "100k", 0x00 }, { "200k", 0x20 }, @@ -475,19 +355,13 @@ static VSUNIGAME dipswitch_gradius = { { "400k", 0x30 } } }, - { "fceumm_dipswitch_gradius_difficulty", - "Difficulty; Normal|Hard", - 2, - 0x40, + { "Difficulty", 2, 0x40, { - { "Hard", 0x40 }, - { "Normal", 0x00 } + { "Normal", 0x00 }, + { "Hard", 0x40 } } }, - { "fceumm_dipswitch_gradius_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x80, + { "Demo Sounds", 2, 0x80, { { "enabled", 0x80 }, { "disabled", 0x00 } @@ -497,14 +371,9 @@ static VSUNIGAME dipswitch_gradius = { }; static VSUNIGAME dipswitch_gumshoe = { - VS_GUMSHOE, - "VS. Gumshoe", - 5, + VS_GUMSHOE, "gumshoe", 5, { - { "fceumm_dipswitch_gumshoe_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -516,10 +385,7 @@ static VSUNIGAME dipswitch_gumshoe = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_gumshoe_difficulty", - "Difficulty; Normal|Easy|Hard|Hardest", - 4, - 0x18, + { "Difficulty", 4, 0x18, { { "Normal", 0x08 }, { "Easy", 0x00 }, @@ -527,28 +393,19 @@ static VSUNIGAME dipswitch_gumshoe = { { "Hardest", 0x18 } } }, - { "fceumm_dipswitch_gumshoe_lives", - "Lives; 3|5", - 2, - 0x20, + { "Lives", 2, 0x20, { { "3", 0x20 }, { "5", 0x00 } } }, - { "fceumm_dipswitch_gumshoe_bullets", - "Bullets per Balloon; 3|2", - 2, - 0x40, + { "Bullets per Balloon", 2, 0x40, { { "3", 0x00 }, { "2", 0x40 } } }, - { "fceumm_dipswitch_gumshoe_bonus", - "Bonus Man Awarded; At 50000|None", - 2, - 0x80, + { "Bonus Man Awarded", 2, 0x80, { { "At 50000", 0x00 }, { "None", 0x80 } @@ -558,14 +415,9 @@ static VSUNIGAME dipswitch_gumshoe = { }; static VSUNIGAME dipswitch_hogansalley = { - VS_HOGANSALLEY, - "VS. Hogan Alley", - 4, + VS_HOGANSALLEY, "hogansalley", 4, { - { "fceumm_dipswitch_hogansalley_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -577,10 +429,7 @@ static VSUNIGAME dipswitch_hogansalley = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_hogansalley_difficulty", - "Difficulty; Normal|Easy|Hard|Hardest", - 4, - 0x18, + { "Difficulty", 4, 0x18, { { "Normal", 0x08 }, { "Easy", 0x00 }, @@ -588,19 +437,13 @@ static VSUNIGAME dipswitch_hogansalley = { { "Hardest", 0x18 } } }, - { "fceumm_dipswitch_hogansalley_misspergame", - "Misses Per Game; 5|3", - 2, - 0x20, + { "Misses Per Game", 2, 0x20, { - { "3", 0x00 }, - { "5", 0x20 } + { "5", 0x20 }, + { "3", 0x00 } } }, - { "fceumm_dipswitch_hogansalley_bonuslife", - "Bonus Life; 30000|50000|80000|100000", - 4, - 0xc0, + { "Bonus Life", 4, 0xc0, { { "30000", 0x00 }, { "50000", 0x40 }, @@ -612,14 +455,9 @@ static VSUNIGAME dipswitch_hogansalley = { }; static VSUNIGAME dipswitch_iceclimber = { - VS_ICECLIMBER, - "VS. Ice Climber", - 4, + VS_ICECLIMBER, "iceclimber", 4, { - { "fceumm_dipswitch_iceclimber_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -631,10 +469,7 @@ static VSUNIGAME dipswitch_iceclimber = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_iceclimber_lives", - "Lives; 3|4|5|7", - 4, - 0x18, + { "Lives", 4, 0x18, { { "3", 0x00 }, { "4", 0x10 }, @@ -642,19 +477,13 @@ static VSUNIGAME dipswitch_iceclimber = { { "7", 0x18 } } }, - { "fceumm_dipswitch_iceclimber_difficulty", - "Difficulty; Easy|Hard", - 2, - 0x20, + { "Difficulty", 2, 0x20, { { "Easy", 0x00 }, { "Hard", 0x20 } } }, - { "fceumm_dipswitch_iceclimber_time", - "Time before bear appears; Long|Short", - 2, - 0x40, + { "Time before bear appears", 2, 0x40, { { "Long", 0x00 }, { "Short", 0x40 } @@ -664,14 +493,9 @@ static VSUNIGAME dipswitch_iceclimber = { }; static VSUNIGAME dipswitch_jajamaru = { - VS_JAJAMARU, - "VS. Jajamaru", - 3, + VS_JAJAMARU, "jajamaru", 3, { - { "fceumm_dipswitch_jajamaru_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -683,20 +507,14 @@ static VSUNIGAME dipswitch_jajamaru = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_jajamaru_lives", - "Lives; 3|4|5", - 3, - 0x18, + { "Lives", 3, 0x18, { { "3", 0x00 }, { "4", 0x10 }, { "5", 0x08 } } }, - { "fceumm_dipswitch_jajamaru_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x80, + { "Demo Sounds", 2, 0x80, { { "enabled", 0x80 }, { "disabled", 0x00 } @@ -705,15 +523,42 @@ static VSUNIGAME dipswitch_jajamaru = { } }; -static VSUNIGAME dipswitch_mightybj = { - VS_MIGHTYBOMBJACK, - "VS. Mighty Bomb Jack", - 2, +static VSUNIGAME dipswitch_machrider = { + VS_MACHRIDER, "machrider", 3, { - { "fceumm_dipswitch_mightybj_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit", - 8, - 0x07, + { "Coinage", 8, 0x07, + { + { "1 Coin 1 Credit", 0x00 }, + { "1 Coin 2 Credits", 0x04 }, + { "1 Coin 3 Credits", 0x02 }, + { "1 Coin 4 Credits", 0x06 }, + { "2 Coins 1 Credit", 0x01 }, + { "3 Coins 1 Credit", 0x05 }, + { "4 Coins 1 Credit", 0x03 }, + { "Free Play", 0x07 } + } + }, + { "Time", 4, 0x18, + { + { "280 (Easy)", 0x00 }, + { "250", 0x10 }, + { "220", 0x08 }, + { "200 (Hard)", 0x18 } + } + }, + { "Enemies", 2, 0x40, + { + { "Less", 0x00 }, + { "More", 0x40 } + } + } + } +}; + +static VSUNIGAME dipswitch_mightybj = { + VS_MIGHTYBOMBJACK, "mightybj", 2, + { + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -725,29 +570,21 @@ static VSUNIGAME dipswitch_mightybj = { { "5 Coins 1 Credit", 0x07 } } }, - { "fceumm_dipswitch_mightybj_lives", - "Lives; 3|4|5|2", - 4, - 0x18, + { "Lives", 4, 0x18, { - { "2", 0x10 }, { "3", 0x00 }, { "4", 0x08 }, - { "5", 0x18 } + { "5", 0x18 }, + { "2", 0x10 }, } } } }; static VSUNIGAME dipswitch_pinball = { - VS_PINBALL, - "VS. Pinball", - 5, + VS_PINBALL, "pinball", 5, { - { "fceumm_dipswitch_pinball_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x01 }, { "1 Coin 2 Credits", 0x06 }, @@ -759,39 +596,27 @@ static VSUNIGAME dipswitch_pinball = { { "Free Play", 0x00 } } }, - { "fceumm_dipswitch_pinball_sidedrainwalls", - "Side Drain Walls; High|Low", - 2, - 0x08, + { "Side Drain Walls", 2, 0x08, { { "High", 0x00 }, { "Low", 0x08 } } }, - { "fceumm_dipswitch_pinball_bonus", - "Bonus Life; 50000|70000", - 2, - 0x10, + { "Bonus Life", 2, 0x10, { { "50000", 0x00 }, { "70000", 0x10 } } }, - { "fceumm_dipswitch_pinball_balls", - "Balls; 3|4|5|2", - 4, - 0x60, + { "Balls", 4, 0x60, { - { "2", 0x60 }, { "3", 0x00 }, { "4", 0x40 }, - { "5", 0x20 } + { "5", 0x20 }, + { "2", 0x60 }, } }, - { "fceumm_dipswitch_pinball_ballspeed", - "Ball Speed; Slow|Fast", - 2, - 0x80, + { "Ball Speed", 2, 0x80, { { "Slow", 0x00 }, { "Fast", 0x80 } @@ -801,34 +626,23 @@ static VSUNIGAME dipswitch_pinball = { }; static VSUNIGAME dipswitch_platoon = { - VS_PLATOON, - "VS. Platoon", - 3, + VS_PLATOON, "platoon", 3, { - { "fceumm_dipswitch_platoon_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x04, + { "Demo Sounds", 2, 0x04, { { "enabled", 0x00 }, { "disabled", 0x04 } } }, - { "fceumm_dipswitch_platoon_difficulty", - "Difficulty; Normal|Medium|Hard|Easy", - 4, - 0x18, + { "Difficulty", 4, 0x18, { - { "Easy",0x00 }, { "Normal", 0x08 }, { "Medium", 0x10 }, - { "Hard",0x18 } + { "Hard", 0x18 }, + { "Easy", 0x00 }, } }, - { "fceumm_dipswitch_platoon_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0xe0, + { "Coinage", 8, 0xe0, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x20 }, @@ -844,14 +658,9 @@ static VSUNIGAME dipswitch_platoon = { }; static VSUNIGAME dipswitch_rbibaseball = { - VS_RBIBASEBALL, - "VS. Atari R.B.I. Baseball", - 3, + VS_RBIBASEBALL, "atari_rbibb", 3, { - { "fceumm_dipswitch_rbibaseball_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", - 4, - 0x03, + { "Coinage", 4, 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, @@ -859,21 +668,15 @@ static VSUNIGAME dipswitch_rbibaseball = { { "3 Coins 1 Credit", 0x03 } } }, - { "fceumm_dipswitch_rbibaseball_inn", - "1p-inn 2p-inn time-min; 2 2 4|3 2 6|4 3 7|2 1 3", - 4, - 0x0c, + { "1p-inn 2p-inn time-min", 4, 0x0c, { - { "2 1 3", 0x04 }, { "2 2 4", 0x0c }, { "3 2 6", 0x00 }, - { "4 3 7", 0x08 } + { "4 3 7", 0x08 }, + { "2 1 3", 0x04 }, } }, - { "fceumm_dipswitch_rbibaseball_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x10, + { "Demo Sounds", 2, 0x10, { { "enabled", 0x00 }, { "disabled", 0x10 } @@ -883,14 +686,9 @@ static VSUNIGAME dipswitch_rbibaseball = { }; static VSUNIGAME dipswitch_slalom = { - VS_SLALOM, - "VS. Slalom", - 5, + VS_SLALOM, "slalom", 5, { - { "fceumm_dipswitch_slalom_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -902,56 +700,39 @@ static VSUNIGAME dipswitch_slalom = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_slalom_freestylepts", - "Freestyle Points; Hold Time|Left Right", - 2, - 0x08, + { "Freestyle Points", 2, 0x08, { { "Hold Time", 0x08 }, { "Left Right", 0x00 } } }, - { "fceumm_dipswitch_slalom_difficulty", - "Difficulty; Normal|Medium|Hard|Easy", - 4, - 0x30, + { "Difficulty", 4, 0x30, { - { "Easy", 0x00 }, { "Normal", 0x10 }, { "Medium", 0x20 }, - { "Hard", 0x30 } + { "Hard", 0x30 }, + { "Easy", 0x00 } } }, - { "fceumm_dipswitch_slalom_allowcontinue", - "Allow Continue; enabled|disabled", - 2, - 0x40, + { "Allow Continue", 2, 0x40, { { "enabled", 0x00 }, { "disabled", 0x40 } } }, - { "fceumm_dipswitch_slalom_inverted_input", - "Inverted Input; disabled|enabled", - 2, - 0x80, + { "Inverted Input", 2, 0x80, { - { "enabled", 0x80 }, - { "disabled", 0x00 } + { "disabled", 0x00 }, + { "enabled", 0x80 } } } } }; static VSUNIGAME dipswitch_smb = { - VS_SMB, - "VS. Super Mario Bros.", - 5, + VS_SMB, "smb", 5, { - { "fceumm_dipswitch_smb_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|1 Coin 5 Credits|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x06 }, @@ -963,39 +744,27 @@ static VSUNIGAME dipswitch_smb = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_smb_lives", - "Lives; 3|2", - 2, - 0x08, + { "Lives", 2, 0x08, { - { "2", 0x08 }, - { "3", 0x00 } + { "3", 0x00 }, + { "2", 0x08 } } }, - { "fceumm_dipswitch_smb_bonuslife", - "Bonus Life (coins); 100|150|200|250", - 4, - 0x30, + { "Bonus Life", 4, 0x30, { - { "100", 0x00 }, - { "150", 0x20 }, - { "200", 0x10 }, - { "250", 0x30 } + { "100 coins", 0x00 }, + { "150 coins", 0x20 }, + { "200 coins", 0x10 }, + { "250 coins", 0x30 } } }, - { "fceumm_dipswitch_smb_timer", - "Timer; Slow|Fast", - 2, - 0x40, + { "Timer", 2, 0x40, { { "Slow", 0x00 }, { "Fast", 0x40 } } }, - { "fceumm_dipswitch_smb_continuelives", - "Continue Lives; 3|4", - 2, - 0x80, + { "Continue Lives", 2, 0x80, { { "3", 0x80 }, { "4", 0x00 } @@ -1005,14 +774,9 @@ static VSUNIGAME dipswitch_smb = { }; static VSUNIGAME dipswitch_soccer = { - VS_SOCCER, - "VS. Soccer", - 3, + VS_SOCCER, "soccer", 3, { - { "fceumm_dipswitch_soccer_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -1024,40 +788,29 @@ static VSUNIGAME dipswitch_soccer = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_soccer_pts_timer", - "Points Timer; 1000 Pts|1200 Pts|600 Pts|800 Pts", - 4, - 0x18, + { "Points Timer", 4, 0x18, { - { "600 Pts", 0x00 }, - { "800 Pts", 0x10 }, { "1000 Pts", 0x08 }, - { "1200 Pts", 0x18 } + { "1200 Pts", 0x18 }, + { "600 Pts", 0x00 }, + { "800 Pts", 0x10 } } }, - { "fceumm_dipswitch_soccer_difficulty", - "Difficulty; Normal|Medium|Hard|Easy", - 4, - 0x60, + { "Difficulty", 4, 0x60, { - { "Easy",0x00 }, { "Normal", 0x40 }, { "Medium", 0x20 }, - { "Hard",0x60 } + { "Hard", 0x60 }, + { "Easy", 0x00 } } } } }; static VSUNIGAME dipswitch_starluster = { - VS_STARLUSTER, - "VS. Star Luster", - 1, + VS_STARLUSTER, "starluster", 1, { - { "fceumm_dipswitch_starluster_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", - 4, - 0x03, + { "Coinage", 4, 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x02 }, @@ -1069,34 +822,24 @@ static VSUNIGAME dipswitch_starluster = { }; static VSUNIGAME dipswitch_superskykid = { - VS_SUPERSKYKID, - "VS. Super Sky Kid", - 3, + VS_SUPERSKYKID, "superskykid", 3, { - { "fceumm_dipswitch_superskykid_difficulty", - "Difficulty; Normal|Medium|Hard|Easy", - 4, - 0x03, + { "Difficulty", 4, 0x03, { - { "Easy",0x00 }, + { "Normal", 0x01 }, { "Medium", 0x02 }, - { "Hard",0x03 } + { "Hard", 0x03 }, + { "Easy", 0x00 }, } }, - { "fceumm_dipswitch_superskykid_lives", - "Lives; 3|2", - 2, - 0x04, + { "Lives", 2, 0x04, { - { "2", 0x00 }, - { "3", 0x04 } + { "3", 0x04 }, + { "2", 0x00 } } }, - { "fceumm_dipswitch_superskykid_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", - 4, - 0x18, + { "Coinage", 4, 0x18, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x08 }, @@ -1108,14 +851,9 @@ static VSUNIGAME dipswitch_superskykid = { }; static VSUNIGAME dipswitch_superxevious = { - VS_SUPERXEVIOUS, - "VS. Super Xevious", - 1, + VS_SUPERXEVIOUS, "superxevious", 1, { - { "fceumm_dipswitch_superxevious_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", - 4, - 0x30, + { "Coinage", 4, 0x30, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x10 }, @@ -1127,33 +865,23 @@ static VSUNIGAME dipswitch_superxevious = { }; static VSUNIGAME dipswitch_tetris = { - VS_TETRIS, - "VS. Tetris", - 1, + VS_TETRIS, "tetris", 1, { - { "fceumm_dipswitch_tetris_difficulty", - "Difficulty; Normal|Medium|Hard|Easy", - 4, - 0x0c, + { "Difficulty", 4, 0x0c, { - { "Easy",0x00 }, { "Normal", 0x04 }, { "Medium", 0x08 }, - { "Hard",0x0c } + { "Hard", 0x0c }, + { "Easy", 0x00 }, } } } }; static VSUNIGAME dipswitch_tkoboxing = { - VS_TKOBOXING, - "VS. T.K.O. Boxing", - 2, + VS_TKOBOXING, "tkoboxing", 2, { - { "fceumm_dipswitch_tkoboxing_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|3 Coins 1 Credit|2 Coins 1 Credit", - 4, - 0x03, + { "Coinage", 4, 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, @@ -1161,29 +889,21 @@ static VSUNIGAME dipswitch_tkoboxing = { { "3 Coins 1 Credit", 0x03 } } }, - { "fceumm_dipswitch_tkoboxing_difficulty", - "Difficulty; Easy|Normal|Hard|Very Hard", - 4, - 0x0c, + { "Difficulty", 4, 0x0c, { - { "Easy",0x00 }, - { "Normal", 0x04 }, - { "Hard",0x08 }, - { "Very Hard", 0x0c } + { "Normal", 0x04 }, + { "Hard", 0x08 }, + { "Very Hard", 0x0c }, + { "Easy", 0x00 }, } } } }; static VSUNIGAME dipswitch_topgun = { - VS_TOPGUN, - "VS. Top Gun", - 5, + VS_TOPGUN, "topgun", 5, { - { "fceumm_dipswitch_topgun_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|5 Coins 1 Credit|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, + { "Coinage", 8, 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -1195,19 +915,13 @@ static VSUNIGAME dipswitch_topgun = { { "Free Play", 0x07 } } }, - { "fceumm_dipswitch_topgun_livespercoin", - "Live per Coin; 3-12 Max|2-9 Max", - 2, - 0x08, + { "Lives per Coin", 2, 0x08, { { "3-12 Max", 0x00 }, { "2-9 Max", 0x08 } } }, - { "fceumm_dipswitch_topgun_bonuslife", - "Bonus Life; 30k and Every 50k|50k and Every 100k|100k and Every 150k|200k and Every 200k", - 4, - 0x30, + { "Bonus Life", 4, 0x30, { { "30k and Every 50k", 0x00 }, { "50k and Every 100k", 0x20 }, @@ -1215,202 +929,146 @@ static VSUNIGAME dipswitch_topgun = { { "200k and Every 200k", 0x30 } } }, - { "fceumm_dipswitch_topgun_difficulty", - "Difficulty; Easy|Hard", - 2, - 0x40, + { "Difficulty", 2, 0x40, { { "Easy", 0x00 }, { "Hard", 0x40 } } }, - { "fceumm_dipswitch_topgun_demosounds", - "Demo Sounds; enabled|disabled", - 2, - 0x80, + { "Demo Sounds", 2, 0x80, { - { "disabled", 0x00 }, - { "enabled", 0x80 } + { "enabled", 0x80 }, + { "disabled", 0x00 } } } } }; -static VSUNIGAME dipswitch_machrider = { - VS_MACHRIDER, - "VS. Mach Rider", - 3, - { - { "fceumm_dipswitch_machrider_coinage", - "Coinage; 1 Coin 1 Credit|1 Coin 2 Credits|1 Coin 3 Credits|1 Coin 4 Credits|4 Coins 1 Credit|3 Coins 1 Credit|2 Coins 1 Credit|Free Play", - 8, - 0x07, - { - { "1 Coin 1 Credit", 0x00 }, - { "1 Coin 2 Credits", 0x04 }, - { "1 Coin 3 Credits", 0x02 }, - { "1 Coin 4 Credits", 0x06 }, - { "2 Coins 1 Credit", 0x01 }, - { "3 Coins 1 Credit", 0x05 }, - { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } - }, - { "fceumm_dipswitch_machrider_time", - "Time; 280 (Easy)|250|220|200 (Hard)", - 4, - 0x18, - { - { "280 (Easy)", 0x00 }, - { "250", 0x10 }, - { "220", 0x08 }, - { "200 (Hard)", 0x18 } - } - }, - { "fceumm_dipswitch_machrider_enemies", - "Enemies; Less|More", - 2, - 0x40, - { - { "Less", 0x00 }, - { "More", 0x40 } - } - } - } -}; +typedef struct { + char key[64]; + char val[150]; +} VSUNIGAMEOPT; -static struct retro_variable var_empty = { NULL, NULL }; -static struct retro_variable dipswitch_vsuni[8]; static VSUNIGAME *vsgame = NULL; +static VSUNIGAMEOPT vscoreopt[5]; -static int make_core_options(VSUNIGAME *tmp) +static void str_to_corekey_label(char *str) { - unsigned ret = 0; - VSUNIGAME *vs = tmp; + unsigned i = 0; - if (vs->gameid != GameInfo->gameid) - return 0; - - for (ret = 0; ret < vs->dipswitch_size; ret++) { - DIPSWITCH *coreoptions = &vs->dipswitch_core_options[ret]; - dipswitch_vsuni[ret].key = coreoptions->var_name; - dipswitch_vsuni[ret].value = coreoptions->var_value; + while (str[i] != '\0') + { + if (str[i] == ' ') + str[i] = '_'; + i++; } - - dipswitch_vsuni[ret] = var_empty; - vsgame = vs; - - return (ret); + str[i] = '\0'; } -static int get_vsuni_dipswitch(unsigned id) +static void make_core_options(void) { - unsigned ret = 0; + unsigned i, dipswitch_size; + char core_prefix[32]; - if (id == 0) - return 0; + dipswitch_size = vsgame->dipswitch_size; + sprintf(core_prefix, "fceumm_dipswitch_%s", vsgame->romname_short); + for (i = 0; i < dipswitch_size; i++) + { + unsigned x; + char core_key[64], core_values[150]; + DIPSWITCH *coreoptions = &vsgame->dipswitch_core_options[i]; + /* make var key string from list */ + sprintf(core_key, "%s%c%s", core_prefix, '-', coreoptions->option_name); + str_to_corekey_label(core_key); + + /* make var values string from lists of values */ + sprintf(core_values, "%s; ", coreoptions->option_name); + for (x = 0; x < coreoptions->settings_size; x++) + { + SETTING *corevalues = &coreoptions->settings[x]; + + strcat(core_values, corevalues->name); + if ((coreoptions->settings_size - 1) > x) + strcat(core_values, "|"); + } + + sprintf(vscoreopt[i].key, "%s", core_key); + sprintf(vscoreopt[i].val, "%s", core_values); + } +} + +static VSUNIGAME *get_vsuni_dipswitch(unsigned id) +{ switch (id) { case VS_BATTLECITY: - ret = make_core_options(&dipswitch_battlecity); - break; + return (&dipswitch_battlecity); case VS_CASTLEVANIA: - ret = make_core_options(&dipswitch_castlevania); - break; + return (&dipswitch_castlevania); case VS_CLUCLULAND: - ret = make_core_options(&dipswitch_clucluland); - break; + return (&dipswitch_clucluland); case VS_DRMARIO: - ret = make_core_options(&dipswitch_drmario); - break; + return (&dipswitch_drmario); case VS_DUCKHUNT: - ret = make_core_options(&dipswitch_duckhunt); - break; + return (&dipswitch_duckhunt); case VS_EXITEBIKE: - ret = make_core_options(&dipswitch_excitebike); - break; + return (&dipswitch_excitebike); case VS_FREEDOMFORCE: - ret = make_core_options(&dipswitch_freedomforce); - break; + return (&dipswitch_freedomforce); case VS_GOONIES: - ret = make_core_options(&dipswitch_goonies); - break; + return (&dipswitch_goonies); case VS_GRADIUS: - ret = make_core_options(&dipswitch_gradius); - break; + return (&dipswitch_gradius); case VS_GUMSHOE: - ret = make_core_options(&dipswitch_gumshoe); - break; + return (&dipswitch_gumshoe); case VS_HOGANSALLEY: - ret = make_core_options(&dipswitch_hogansalley); - break; + return (&dipswitch_hogansalley); case VS_ICECLIMBER: - ret = make_core_options(&dipswitch_iceclimber); - break; + return (&dipswitch_iceclimber); case VS_JAJAMARU: - ret = make_core_options(&dipswitch_jajamaru); - break; + return (&dipswitch_jajamaru); /* case VS_LADIESGOLF: */ /* case VS_STROKEANDMATCHGOLF: */ case VS_MACHRIDER: - ret = make_core_options(&dipswitch_machrider); - break; + return (&dipswitch_machrider); case VS_MIGHTYBOMBJACK: - ret = make_core_options(&dipswitch_mightybj); - break; + return (&dipswitch_mightybj); case VS_PINBALL: - ret = make_core_options(&dipswitch_pinball); - break; + return (&dipswitch_pinball); case VS_PLATOON: - ret = make_core_options(&dipswitch_platoon); - break; + return (&dipswitch_platoon); case VS_RBIBASEBALL: - ret = make_core_options(&dipswitch_rbibaseball); - break; + return (&dipswitch_rbibaseball); case VS_SLALOM: - ret = make_core_options(&dipswitch_slalom); - break; + return (&dipswitch_slalom); case VS_SMB: - ret = make_core_options(&dipswitch_smb); - break; + return (&dipswitch_smb); case VS_SOCCER: - ret = make_core_options(&dipswitch_soccer); - break; + return (&dipswitch_soccer); case VS_STARLUSTER: - ret = make_core_options(&dipswitch_starluster); - break; + return (&dipswitch_starluster); case VS_SUPERSKYKID: - ret = make_core_options(&dipswitch_superskykid); - break; + return (&dipswitch_superskykid); case VS_SUPERXEVIOUS: - ret = make_core_options(&dipswitch_superxevious); - break; + return (&dipswitch_superxevious); case VS_TETRIS: - ret = make_core_options(&dipswitch_tetris); - break; + return (&dipswitch_tetris); case VS_TKOBOXING: - ret = make_core_options(&dipswitch_tkoboxing); - break; + return (&dipswitch_tkoboxing); case VS_TOPGUN: - ret = make_core_options(&dipswitch_topgun); - break; - default: - FCEU_printf("No dipsettings found. %d\n", id); - break; + return (&dipswitch_topgun); } - return (ret); + FCEU_printf("No dipsettings found. %d\n", id); + return (NULL); } -void update_dipswitch_vsuni(void) +static void update_dipswitch_vsuni(void) { struct retro_variable var = {0}; unsigned idx_dips, idx_var; uint8 vsdip_new = 0x00; - if (GameInfo->type != GIT_VSUNI) - return; - if (vsgame == NULL) return; @@ -1418,7 +1076,7 @@ void update_dipswitch_vsuni(void) for (idx_dips = 0; idx_dips < vsgame->dipswitch_size; idx_dips++) { DIPSWITCH *core_option = &vsgame->dipswitch_core_options[idx_dips]; - var.key = core_option->var_name; + var.key = vscoreopt[idx_dips].key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) continue; for (idx_var = 0; idx_var < core_option->settings_size; idx_var++) @@ -1431,9 +1089,9 @@ void update_dipswitch_vsuni(void) } } - if (FCEUI_VSUniGetDIPs() != (uint8)vsdip_new) + if (FCEUI_VSUniGetDIPs() != vsdip_new) { - vsdip = (uint8)vsdip_new; + vsdip = vsdip_new; #ifdef DEBUG FCEU_printf("Dipswitch changed %d%d%d%d%d%d%d%d\n", (vsdip >> 0) & 1, (vsdip >> 1) & 1, (vsdip >> 2) & 1, (vsdip >> 3) & 1, @@ -1457,9 +1115,6 @@ static void update_dipswitch_nwc(void) unsigned dips = 0x00; unsigned index; - if (iNESCart.mapper != 105) - return; - for (index = 0; index < 4; index++) { struct retro_variable *nwc = &dipswitch_nwc[index]; @@ -1481,22 +1136,20 @@ static void update_dipswitch_nwc(void) } } -void set_dipswitch_variables(unsigned *index, struct retro_variable vars[]) +void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) { unsigned i, idx = *index; /* VSUNI Dipswitch */ if (GameInfo->type == GIT_VSUNI) { - unsigned size = 0; - size = get_vsuni_dipswitch(GameInfo->gameid); - if (size) + vsgame = get_vsuni_dipswitch(GameInfo->gameid); + if (vsgame) { - i = 0; - while (dipswitch_vsuni[i].key) { - vars[idx] = dipswitch_vsuni[i]; - idx++; - i++; + make_core_options(); + for (i = 0; i < vsgame->dipswitch_size; i++, idx++) { + vars[idx].key = vscoreopt[i].key; + vars[idx].value = vscoreopt[i].val; } } } diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/dipswitch.h index 6ad2bc1..8b03006 100644 --- a/src/drivers/libretro/dipswitch.h +++ b/src/drivers/libretro/dipswitch.h @@ -3,7 +3,7 @@ #include -void set_dipswitch_variables(unsigned *index, struct retro_variable vars[]); +void set_dipswitch_variables(unsigned *index, struct retro_variable *vars); void update_dipswitch(void); extern retro_environment_t environ_cb; diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 521f50d..0b20614 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -784,7 +784,7 @@ static void set_variables(void) } /* append dipswitches to core options if available */ - set_dipswitch_variables(&index_core, &retro_vars[0]); + set_dipswitch_variables(&index_core, retro_vars); /* NULL terminate */ retro_vars[index_core] = vars_empty; From 005eb7bdc31345f05977d2e85e10a5e1ad54c806 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 24 May 2019 06:59:26 +0800 Subject: [PATCH 08/74] Implement mappers 28, 29, 31, 56, 63, 255, BMC-60311C, BMC-WS, BMC-HPxx - Added a few mappers to the list. Tested with roms from goodnes set and some demos - Fix IRQ for Kaiser7032/202 - Issue noticeable with SMB2/3's status status bar --- src/boards/255.c | 79 +++++++++++++ src/boards/28.c | 187 ++++++++++++++++++++++++++++++ src/boards/31.c | 66 +++++++++++ src/boards/{ks7016.c => KS7016.c} | 0 src/boards/KS7032.c | 119 +++++++++++++++---- src/boards/addrlatch.c | 31 +++++ src/boards/bmc60311c.c | 110 ++++++++++++++++++ src/boards/datalatch.c | 16 +++ src/boards/hp10xx_hp20xx.c | 171 +++++++++++++++++++++++++++ src/boards/super40in1.c | 74 ++++++++++++ src/ines-correct.h | 1 - src/ines.c | 40 ++++--- src/ines.h | 6 +- src/unif.c | 5 + src/unif.h | 6 + 15 files changed, 872 insertions(+), 39 deletions(-) create mode 100644 src/boards/255.c create mode 100644 src/boards/28.c create mode 100644 src/boards/31.c rename src/boards/{ks7016.c => KS7016.c} (100%) create mode 100644 src/boards/bmc60311c.c create mode 100644 src/boards/hp10xx_hp20xx.c create mode 100644 src/boards/super40in1.c diff --git a/src/boards/255.c b/src/boards/255.c new file mode 100644 index 0000000..fc7f28c --- /dev/null +++ b/src/boards/255.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * Mapper 255 + * https://wiki.nesdev.com/w/index.php/INES_Mapper_225 + * 115-in-1 [p1][!] CRC32 0xb39d30b4 + * Seems to handle up to last game in the multicarts than m225 but causes + * graphics garbage past it, else games works fine */ + +#include "mapinc.h" + +static uint8 preg, creg, mode, mirr; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PRG0" }, + { &creg, 1, "CHR0" }, + { &mode, 1, "MODE" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, preg & ~mode); + setprg16(0xC000, preg | mode); + setchr8(creg); + setmirror(mirr ^ 1); +} + +static DECLFW(M255Write) { + uint32 bank = (A >> 8 & 0x40); + preg = bank | ((A >> 6) & 0x3F); + creg = bank | (A & 0x3F); + mirr = (A >> 13) & 1; + mode = ((~A) >> 12 & 1); + Sync(); +} + +static void M255Power(void) { + preg = 0; + mode = 1; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M255Write); +} + +static void M255Reset(void) { + preg = 0; + mode = 1; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper255_Init(CartInfo *info) { + info->Reset = M255Reset; + info->Power = M255Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/28.c b/src/boards/28.c new file mode 100644 index 0000000..2cb95f0 --- /dev/null +++ b/src/boards/28.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2012-2017 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +/* added 2019-5-23 + * Mapper 28 - Action 53 + * http://wiki.nesdev.com/w/index.php/INES_Mapper_028 */ + +#include "mapinc.h" + +static uint8 prg_mask_16k; +static uint8 reg, chr, prg, mode, outer; + +static SFORMAT StateRegs[] = { + {®, 1, "REG"}, + {&chr, 1, "CHR"}, + {&prg, 1, "PRG"}, + {&mode, 1, "MODE"}, + {&outer, 1, "OUTR"}, + {0} +}; + +void SyncMirror() { + switch (mode & 3) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + } +} + +void Mirror(uint8 value) +{ + if ((mode & 2) == 0) { + mode &= 0xfe; + mode |= value >> 4 & 1; + } + SyncMirror(); +} + + +static void Sync() { + uint8 prglo; + uint8 prghi; + + uint8 outb = outer << 1; + + /* this can probably be rolled up, but i have no motivation to do so + * until it's been tested */ + switch (mode & 0x3c) { + /* 32K modes */ + case 0x00: + case 0x04: + prglo = outb; + prghi = outb | 1; + break; + case 0x10: + case 0x14: + prglo = outb & ~2 | prg << 1 & 2; + prghi = outb & ~2 | prg << 1 & 2 | 1; + break; + case 0x20: + case 0x24: + prglo = outb & ~6 | prg << 1 & 6; + prghi = outb & ~6 | prg << 1 & 6 | 1; + break; + case 0x30: + case 0x34: + prglo = outb & ~14 | prg << 1 & 14; + prghi = outb & ~14 | prg << 1 & 14 | 1; + break; + /* bottom fixed modes */ + case 0x08: + prglo = outb; + prghi = outb | prg & 1; + break; + case 0x18: + prglo = outb; + prghi = outb & ~2 | prg & 3; + break; + case 0x28: + prglo = outb; + prghi = outb & ~6 | prg & 7; + break; + case 0x38: + prglo = outb; + prghi = outb & ~14 | prg & 15; + break; + /* top fixed modes */ + case 0x0c: + prglo = outb | prg & 1; + prghi = outb | 1; + break; + case 0x1c: + prglo = outb & ~2 | prg & 3; + prghi = outb | 1; + break; + case 0x2c: + prglo = outb & ~6 | prg & 7; + prghi = outb | 1; + break; + case 0x3c: + prglo = outb & ~14 | prg & 15; + prghi = outb | 1; + break; + } + + prglo &= prg_mask_16k; + prghi &= prg_mask_16k; + + setprg16(0x8000, prglo); + setprg16(0xC000, prghi); + setchr8(chr); +} + +static DECLFW(WriteEXP) { + reg = V & 0x81; +} + +static DECLFW(WritePRG) { + switch (reg) { + case 0x00: + chr = V & 3; + Mirror(V); + Sync(); + break; + case 0x01: + prg = V & 15; + Mirror(V); + Sync(); + break; + case 0x80: + mode = V & 63; + SyncMirror(); + Sync(); + break; + case 0x81: + outer = V & 63; + Sync(); + break; + } +} + +static void M28Power(void) { + outer = 63; + prg = 15; + Sync(); + prg_mask_16k = PRGsize[0] - 1; + SetWriteHandler(0x5000,0x5FFF,WriteEXP); + SetWriteHandler(0x8000,0xFFFF,WritePRG); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetReadHandler(0x6000,0x7FFF,CartBR); + SetWriteHandler(0x6000,0x7FFF,CartBW); +} + +static void M28Reset(void) { + outer = 63; + prg = 15; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper28_Init(CartInfo* info) { + info->Power=M28Power; + info->Reset=M28Reset; + GameStateRestore=StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/31.c b/src/boards/31.c new file mode 100644 index 0000000..17777ab --- /dev/null +++ b/src/boards/31.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * Mapper 31 - custom mapper by infiniteneslives + * https://wiki.nesdev.com/w/index.php/INES_Mapper_031 */ + +#include "mapinc.h" + +static uint8 preg[8]; + +static SFORMAT StateRegs[] = +{ + { preg, 8, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x8000, preg[0]); + setprg4(0x9000, preg[1]); + setprg4(0xA000, preg[2]); + setprg4(0xB000, preg[3]); + setprg4(0xC000, preg[4]); + setprg4(0xD000, preg[5]); + setprg4(0xE000, preg[6]); + setprg4(0xF000, preg[7]); + setchr8(0); +} + +static DECLFW(M31Write) { + preg[A & 7] = V; + Sync(); +} + +static void M31Power(void) { + preg[7] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M31Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper31_Init(CartInfo *info) { + info->Power = M31Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/ks7016.c b/src/boards/KS7016.c similarity index 100% rename from src/boards/ks7016.c rename to src/boards/KS7016.c diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 7958a0c..5a5bd53 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2019 Libretro Team (IRQ Update) * * 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 @@ -21,43 +22,99 @@ * */ +/* added 2019-5-23 + * - Mapper 56 - UNL KS202 + * FDS Conversion: Super Mario Bros. 3 (Pirate, Alt) + * similar to M142 but use WRAM instead? $D000 additional IRQ trigger + * - fix IRQ counter, noticeable in status bars of both SMB2J(KS7032) and SMB3J(KS202) + */ + #include "mapinc.h" -static uint8 reg[8], cmd, IRQa = 0, isirqused = 0; -static int32 IRQCount; +static uint8 reg[8], creg[8], mirr, cmd, IRQa = 0, isirqused = 0; +static int32 IRQCount, IRQLatch; +static uint8 KS7032; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; -static SFORMAT StateRegs[] = +static SFORMAT StateRegsKS7032[] = { { &cmd, 1, "CMD" }, { reg, 8, "REGS" }, { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, + { &IRQCount, 4 | FCEUSTATE_RLSB, "IRQC" }, + { 0 } +}; + +static SFORMAT StateRegsKS202[] = +{ + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, { 0 } }; static void Sync(void) { - setprg8(0x6000, reg[4]); - setprg8(0x8000, reg[1]); - setprg8(0xA000, reg[2]); - setprg8(0xC000, reg[3]); + setprg8(0x8000, reg[0]); + setprg8(0xA000, reg[1]); + setprg8(0xC000, reg[2]); setprg8(0xE000, ~0); setchr8(0); + if (KS7032) + setprg8(0x6000, reg[3]); + else { + setprg8r(0x10, 0x6000, 0); + setchr1(0x0000, creg[0]); + setchr1(0x0400, creg[1]); + setchr1(0x0800, creg[2]); + setchr1(0x0C00, creg[3]); + setchr1(0x1000, creg[4]); + setchr1(0x1400, creg[5]); + setchr1(0x1800, creg[6]); + setchr1(0x1C00, creg[7]); + setmirror(mirr); + } } static DECLFW(UNLKS7032Write) { /* FCEU_printf("bs %04x %02x\n",A,V); */ switch (A & 0xF000) { /* case 0x8FFF: reg[4]=V; Sync(); break; */ - case 0x8000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x000F) | (V & 0x0F); isirqused = 1; break; - case 0x9000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x00F0) | ((V & 0x0F) << 4); isirqused = 1; break; - case 0xA000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x0F00) | ((V & 0x0F) << 8); isirqused = 1; break; - case 0xB000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0xF000) | (V << 12); isirqused = 1; break; - case 0xC000: if (isirqused) { - X6502_IRQEnd(FCEU_IQEXT); IRQa = 1; - } - break; + case 0x8000: IRQLatch = (IRQLatch & 0xFFF0) | (V & 0x0F); break; + case 0x9000: IRQLatch = (IRQLatch & 0xFF0F) | ((V & 0x0F) << 4); break; + case 0xA000: IRQLatch = (IRQLatch & 0xF0FF) | ((V & 0x0F) << 8); break; + case 0xB000: IRQLatch = (IRQLatch & 0x0FFF) | (V << 12); break; + case 0xC000: + IRQa = (V & 0xF); + if (IRQa) + IRQCount = IRQLatch; + X6502_IRQEnd(FCEU_IQEXT); break; + case 0xD000: X6502_IRQEnd(FCEU_IQEXT); break; case 0xE000: cmd = V & 7; break; - case 0xF000: reg[cmd] = V; Sync(); break; + case 0xF000: { + uint8 bank = (cmd - 1); + if (bank < 3) + reg[bank] = reg[bank] & 0x10 | V & 0x0F; + else if (bank < 4) + reg[bank] = V; + Sync(); + switch (A & 0xFC00) { + case 0xF000: + A &= 3; + if (A < 3) + reg[bank] = reg[bank] & 0x0F | V & 0x10; + Sync(); + break; + case 0xF800: + mirr = (V & 1); + Sync(); + break; + case 0xFC00: + creg[A & 7] = V; + Sync(); + break; + } + } + break; } } @@ -65,8 +122,7 @@ static void FP_FASTAPASS(1) UNLSMB2JIRQHook(int a) { if (IRQa) { IRQCount += a; if (IRQCount >= 0xFFFF) { - IRQa = 0; - IRQCount = 0; + IRQCount = IRQLatch; X6502_IRQBegin(FCEU_IQEXT); } } @@ -77,6 +133,10 @@ static void UNLKS7032Power(void) { SetReadHandler(0x6000, 0x7FFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x4020, 0xFFFF, UNLKS7032Write); + if (!KS7032) { + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } } static void StateRestore(int version) { @@ -84,8 +144,27 @@ static void StateRestore(int version) { } void UNLKS7032_Init(CartInfo *info) { + KS7032 = 1; info->Power = UNLKS7032Power; MapIRQHook = UNLSMB2JIRQHook; GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); + AddExState(&StateRegsKS7032, ~0, 0, 0); +} + +void UNLKS202_Init(CartInfo *info) { + KS7032 = 0; + info->Power = UNLKS7032Power; + MapIRQHook = UNLSMB2JIRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegsKS7032, ~0, 0, 0); + AddExState(&StateRegsKS202, ~0, 0, 0); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index b9efe6d..ec1a3f1 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -195,6 +195,37 @@ void Mapper61_Init(CartInfo *info) { Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); } +/*------------------ Map 063 ---------------------------*/ +/* added 2019-5-23 + * Mapper 63 NTDEC-Multicart + * http://wiki.nesdev.com/w/index.php/INES_Mapper_063 + * - Powerful 250-in-1 + * - Hello Kitty 255-in-1 */ + +static DECLFR(M63Read) { + if (latche & 0x0300) + return X.DB; + return CartBR(A); +} + +static void M63Sync(void) { + uint16 mode = latche & 2; + uint16 prg_bank = (latche & 0x3F8) >> 1; + uint16 prg16 = (latche & 4) >> 1; + + setprg8(0x8000, (prg_bank | (mode ? 0 : prg16 | 0))); + setprg8(0xA000, (prg_bank | (mode ? 1 : prg16 | 1))); + setprg8(0xC000, (prg_bank | (mode ? 2 : prg16 | 0))); + setprg8(0xE000, ((latche & 0x800) ? ((latche & 0x7C) | ((latche & 6) ? 3 : 1)) : + (prg_bank | (mode ? 3 : (prg16 | 1))))); + setchr8(0); + setmirror((latche & 1) ^ 1); +} + +void Mapper63_Init(CartInfo *info) { + Latch_Init(info, M63Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + /*------------------ Map 092 ---------------------------*/ /* Another two-in-one mapper, two Jaleco carts uses similar * hardware, but with different wiring. diff --git a/src/boards/bmc60311c.c b/src/boards/bmc60311c.c new file mode 100644 index 0000000..8f313ee --- /dev/null +++ b/src/boards/bmc60311c.c @@ -0,0 +1,110 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * UNIF: BMC-60311C: + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_289 + */ + +#include "mapinc.h" + +static uint8 inner_bank, outer_bank, mode; + +static SFORMAT StateRegs[] = +{ + { &inner_bank, 1, "INB0" }, + { &outer_bank, 1, "OUTB" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + uint8 bbank = (mode & 4) ? 0 : (inner_bank & 7); + uint8 bank = outer_bank | bbank; + uint8 preg[2]; + + /* 0: NROM-128: Same inner/outer 16 KiB bank at CPU $8000-$BFFF + * and $C000-$FFFF + * 1: NROM-256: 32 kiB bank at CPU $8000-$FFFF (Selected inner/outer bank SHR 1) + * 2: UNROM: Inner/outer bank at CPU $8000-BFFF, + * fixed inner bank 7 within outer bank at $C000-$FFFF + * 3: Unknown + * + * The combined inner/outer bank is simply the inner bank, selected by the + * latch at $8000-$FFFF (or 0 if the latch is disabled) ORed with the + * outer bank selected by $6001, without any bit shifting. + */ + + preg[0] = bank; + switch (mode & 3) { + case 0x00: + case 0x01: + preg[1] = bank | ((mode & 1) ? 1 : 0); + break; + case 0x02: + preg[1] = outer_bank | 7; + case 0x03: + break; + } + + setchr8(0); + setprg16(0x8000, preg[0]); + setprg16(0xC000, preg[1]); + SetupCartMirroring(((mode & 8) >> 3) ^ 1, 1, NULL); +} + +static DECLFW(Write0) { + mode = V; + Sync(); +} + +static DECLFW(Write1) { + outer_bank = V; + Sync(); +} + +static DECLFW(Write8) { + inner_bank = V; + Sync(); +} + +static void BMC60311CPower(void) { + inner_bank = outer_bank = mode = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6000, Write0); + SetWriteHandler(0x6001, 0x6001, Write1); + SetWriteHandler(0x8000, 0xFFFF, Write8); +} + +static void BMC60311CReset(void) { + inner_bank = outer_bank = mode = 0; + Sync(); +} + +static void BMC60311CRestore(int version) { + Sync(); +} + +void BMC60311C_Init(CartInfo *info) { + info->Power = BMC60311CPower; + info->Reset = BMC60311CReset; + GameStateRestore = BMC60311CRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 3ed37be..c13454b 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -225,6 +225,22 @@ void CPROM_Init(CartInfo *info) { Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); } +/*------------------ Map 29 ---------------------------*/ +/* added 2019-5-23 + * Mapper 28, used by homebrew game Glider + * https://wiki.nesdev.com/w/index.php/INES_Mapper_029 */ + +static void M29Sync(void) { + setprg16(0x8000, (latche >> 2) & 7); + setprg16(0xc000, ~0); + setchr8r(0, latche & 3); + setprg8r(0x10, 0x6000, 0); +} + +void Mapper29_Init(CartInfo *info) { + Latch_Init(info, M29Sync, 0x0000, 0x6000, 0xFFFF, 1, 0); +} + /*------------------ Map 38 ---------------------------*/ static void M38Sync(void) { diff --git a/src/boards/hp10xx_hp20xx.c b/src/boards/hp10xx_hp20xx.c new file mode 100644 index 0000000..c18c9d1 --- /dev/null +++ b/src/boards/hp10xx_hp20xx.c @@ -0,0 +1,171 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "../ines.h" + +/* added on 2019-5-23 - NES 2.0 Mapper 260 + * HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better + * organized banking behaviour. It seems that some 176 mapper assigned game may be + * actually this kind of board instead but in common they aren't compatible at all, + * the games on the regular FK23C boards couldn't run on this mapper and vice versa... + */ + +static uint8 unromchr, lock; +static uint32 dipswitch; + +static void BMCHPxxCW(uint32 A, uint8 V) { + if (EXPREGS[0] & 4) { /* custom banking */ + switch(EXPREGS[0] & 3) { + case 0: + case 1: + setchr8(EXPREGS[2] & 0x3F); +/* FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F); */ + break; + case 2: + setchr8((EXPREGS[2] & 0x3E) | (unromchr & 1)); +/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1)); */ + break; + case 3: + setchr8((EXPREGS[2] & 0x3C) | (unromchr & 3)); +/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3)); */ + break; + } + } else { /* mmc3 banking */ + int base, mask; + if(EXPREGS[0] & 1) { /* 128K mode */ + base = EXPREGS[2] & 0x30; + mask = 0x7F; + } else { /* 256K mode */ + base = EXPREGS[2] & 0x20; + mask = 0xFF; + } +/* FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3)); */ + setchr1(A, (V & mask) | (base << 3)); + } +} + +/* PRG wrapper */ +static void BMCHPxxPW(uint32 A, uint8 V) { + if(EXPREGS[0] & 4) { /* custom banking */ + if((EXPREGS[0] & 0xF) == 4) { /* 16K mode */ +/* FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F); */ + setprg16(0x8000, EXPREGS[1] & 0x1F); + setprg16(0xC000, EXPREGS[1] & 0x1F); + } else { /* 32K modes */ +/* FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1); */ + setprg32(0x8000, (EXPREGS[1] & 0x1F) >> 1); + } + } else { /* mmc3 banking */ + uint8 base, mask; + if(EXPREGS[0] & 2) { /* 128K mode */ + base = EXPREGS[1] & 0x18; + mask = 0x0F; + } else { /* 256K mode */ + base = EXPREGS[1] & 0x10; + mask = 0x1F; + } +/* FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1)); */ + setprg8(A, (V & mask) | (base << 1)); + setprg8r(0x10, 0x6000, A001B & 3); + } +} + +/* MIRROR wrapper */ +static void BMCHPxxMW(uint8 V) { + if(EXPREGS[0] & 4) { /* custom banking */ +/* FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1); */ + setmirror(((unromchr >> 2) & 1) ^ 1); + } else { /* mmc3 banking */ +/* FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1); */ + A000B = V; + setmirror((A000B & 1) ^ 1); + } +} + +/* PRG handler ($8000-$FFFF) */ +static DECLFW(BMCHPxxHiWrite) { +/* FCEU_printf("HI WRITE %04X:%02X\n",A,V); */ + if(EXPREGS[0] & 4) { /* custom banking */ +/* FCEU_printf("CUSTOM\n"); */ + unromchr = V; + FixMMC3CHR(MMC3_cmd); + } else { /* mmc3 banking */ +/* FCEU_printf("MMC3\n"); */ + if(A<0xC000) { + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + MMC3_IRQWrite(A, V); + } + } +} + +/* EXP handler ($5000-$5FFF) */ +static DECLFW(BMCHPxxWrite) { + if (!lock) { +/* FCEU_printf("LO WRITE %04X:%02X\n",A,V); */ + EXPREGS[A & 3] = V; + lock = V & 0x80; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static DECLFR(BMCHPxxRead) { + return dipswitch; +} + +static void BMCHPxxReset(void) { + dipswitch++; + dipswitch &= 0xF; + lock = 0; +/* FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch); */ + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + MMC3RegReset(); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCHPxxPower(void) { + GenMMC3Power(); + dipswitch = lock = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + SetReadHandler(0x5000, 0x5fff, BMCHPxxRead); + SetWriteHandler(0x5000, 0x5fff, BMCHPxxWrite); + SetWriteHandler(0x8000, 0xffff, BMCHPxxHiWrite); +} + +void BMCHPxx_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 8, 0); + cwrap = BMCHPxxCW; + pwrap = BMCHPxxPW; + mwrap = BMCHPxxMW; + info->Power = BMCHPxxPower; + info->Reset = BMCHPxxReset; + AddExState(EXPREGS, 8, 0, "EXPR"); + AddExState(&unromchr, 1, 0, "UCHR"); + AddExState(&dipswitch, 1, 0, "DPSW"); + AddExState(&lock, 1, 0, "LOCK"); +} diff --git a/src/boards/super40in1.c b/src/boards/super40in1.c new file mode 100644 index 0000000..ef5a5e1 --- /dev/null +++ b/src/boards/super40in1.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * BMC-WS Used for Super 40-in-1 multicart + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */ + +#include "mapinc.h" + +static uint8 preg, creg; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &creg, 1, "CREG" }, + { 0 } +}; + +static void Sync(void) { + if (preg & 8) { + setprg16(0x8000, preg & 7); + setprg16(0xc000, preg & 7); + } + else + setprg32(0x8000, (preg & 6) >> 1); + setchr8(creg); + setmirror(((preg >> 4) & 1) ^ 1); +} + +static DECLFW(BMCWSWrite) { + if (preg & 0x20) + return; + + switch (A & 1) { + case 0: preg = V; Sync(); break; + case 1: creg = V; Sync(); break; + } +} + +static void MBMCWSPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6001, BMCWSWrite); +} + +static void BMCWSReset(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCWS_Init(CartInfo *info) { + info->Reset = BMCWSReset; + info->Power = MBMCWSPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index 359c7e9..fde6d54 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -317,7 +317,6 @@ {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ - {0x00000000, -1, -1} #endif diff --git a/src/ines.c b/src/ines.c index 83591df..acec60f 100644 --- a/src/ines.c +++ b/src/ines.c @@ -417,10 +417,10 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"Konami VRC2/VRC4 D", 25, Mapper25_Init}, {(uint8_t*)"Konami VRC6 Rev. B", 26, Mapper26_Init}, {(uint8_t*)"CC-21 MI HUN CHE", 27, UNLCC21_Init}, /* Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards */ -/* {(uint8_t*)"", 28, Mapper28_Init}, */ /* Custom Multidiscrete mapper for PDs */ -/* {(uint8_t*)"", 29, Mapper29_Init}, */ + {(uint8_t*)"Action 53", 28, Mapper28_Init}, + {(uint8_t*)"", 29, Mapper29_Init}, {(uint8_t*)"UNROM 512", 30, UNROM512_Init}, -/* {(uint8_t*)"", 31, Mapper31_Init}, */ + {(uint8_t*)"infineteNesLives-NSF", 31, Mapper31_Init}, {(uint8_t*)"IREM G-101", 32, Mapper32_Init}, {(uint8_t*)"TC0190FMC/TC0350FMR", 33, Mapper33_Init}, {(uint8_t*)"IREM I-IM/BNROM", 34, Mapper34_Init}, @@ -445,14 +445,14 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"SUPERVISION 16-in-1", 53, Supervision16_Init}, /* {(uint8_t*)"", 54, Mapper54_Init}, */ /* {(uint8_t*)"", 55, Mapper55_Init}, */ -/* {(uint8_t*)"", 56, Mapper56_Init}, */ + {(uint8_t*)"UNLKS202", 56, UNLKS202_Init}, {(uint8_t*)"SIMBPLE BMC PIRATE A", 57, Mapper57_Init}, {(uint8_t*)"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init}, {(uint8_t*)"", 59, Mapper59_Init}, /* Check this out */ {(uint8_t*)"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init}, {(uint8_t*)"20-in-1 KAISER Rev. A",61, Mapper61_Init}, {(uint8_t*)"700-in-1", 62, Mapper62_Init}, -/* {(uint8_t*)"", 63, Mapper63_Init}, */ + {(uint8_t*)"", 63, Mapper63_Init}, {(uint8_t*)"TENGEN RAMBO1", 64, Mapper64_Init}, {(uint8_t*)"IREM-H3001", 65, Mapper65_Init}, {(uint8_t*)"MHROM", 66, MHROM_Init}, @@ -571,7 +571,7 @@ static BMAPPINGLocal bmap[] = { /* {(uint8_t*)"", 179, Mapper179_Init}, */ {(uint8_t*)"", 180, Mapper180_Init}, {(uint8_t*)"", 181, Mapper181_Init}, -/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe */ +/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe of Mapper 114 */ {(uint8_t*)"", 183, Mapper183_Init}, {(uint8_t*)"", 184, Mapper184_Init}, {(uint8_t*)"", 185, Mapper185_Init}, @@ -644,7 +644,8 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"SAN GUO ZHI PIRATE", 252, Mapper252_Init}, {(uint8_t*)"DRAGON BALL PIRATE", 253, Mapper253_Init}, {(uint8_t*)"", 254, Mapper254_Init}, -/* {(uint8_t*)"", 255, Mapper255_Init}, */ /* No good dumps for this mapper */ + {(uint8_t*)"", 255, Mapper255_Init}, /* Duplicate of M225? */ + {(uint8_t*)"", 0, NULL} }; @@ -742,10 +743,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) { iNESCart.CRC32 = iNESGameCRC32; - FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256); - FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); - FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); - FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); mappername = "Not Listed"; for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { @@ -755,12 +752,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) { } } - FCEU_printf(" Mapper #: %d\n", MapperNo); - FCEU_printf(" Mapper name: %s\n", mappername); - FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); - FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); - FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); - SetInput(); CheckHInfo(); { @@ -790,10 +781,22 @@ int iNESLoad(const char *name, FCEUFILE *fp) { iNESCart.battery = (head.ROM_type & 2) ? 1 : 0; iNESCart.mirror = Mirroring; + FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); + FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); + FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256); + FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); + if (!iNES_Init(MapperNo)) FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo); iNESCart.mapper = MapperNo; + FCEU_printf(" \n"); + FCEU_printf(" Mapper #: %3d\n", MapperNo); + FCEU_printf(" Mapper name: %s\n", mappername); + FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); + FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); + FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + GameInterface = iNESGI; FCEU_printf("\n"); @@ -831,6 +834,8 @@ static int iNES_Init(int num) { switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */ case 13: CHRRAMSize = 16 * 1024; break; case 6: + case 28: + case 29: case 30: case 45: case 96: CHRRAMSize = 32 * 1024; break; @@ -843,6 +848,7 @@ static int iNES_Init(int num) { UNIFchrrama = VROM; SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); AddExState(VROM, CHRRAMSize, 0, "CHRR"); + FCEU_printf(" CHR RAM: %3d x 1KiB\n", CHRRAMSize / 1024); } if (head.ROM_type & 8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); diff --git a/src/ines.h b/src/ines.h index b3d07ba..61402c2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -63,7 +63,9 @@ void Mapper23_Init(CartInfo *); void Mapper24_Init(CartInfo *); void Mapper25_Init(CartInfo *); void Mapper26_Init(CartInfo *); -void UNROM512_Init(CartInfo *); /* Mapper #30 */ +void Mapper28_Init(CartInfo *); +void Mapper29_Init(CartInfo *); +void Mapper31_Init(CartInfo *); void Mapper32_Init(CartInfo *); void Mapper33_Init(CartInfo *); void Mapper34_Init(CartInfo *); @@ -87,6 +89,7 @@ void Mapper57_Init(CartInfo *); void Mapper59_Init(CartInfo *); void Mapper61_Init(CartInfo *); void Mapper62_Init(CartInfo *); +void Mapper63_Init(CartInfo *); void Mapper64_Init(CartInfo *); void Mapper65_Init(CartInfo *); void Mapper67_Init(CartInfo *); @@ -222,5 +225,6 @@ void Mapper250_Init(CartInfo *); void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); +void Mapper255_Init(CartInfo *); #endif diff --git a/src/unif.c b/src/unif.c index 4622f3a..e0f961b 100644 --- a/src/unif.c +++ b/src/unif.c @@ -463,6 +463,10 @@ static BMAPPING bmap[] = { { "RT-01", UNLRT01_Init, 0 }, { "81-01-31-C", BMC810131C_Init, 0 }, { "8-IN-1", BMC8IN1_Init, 0 }, + { "RET-CUFROM", Mapper29_Init, BMCFLAG_32KCHRR }, + { "60311C", BMC60311C_Init, 0 }, + { "WS", BMCWS_Init, 0 }, + { "HPxx", BMCHPxx_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, @@ -609,6 +613,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { aborto: + FCEU_printf(" Failed to initialize board %s\n", boardname); FreeUNIF(); ResetUNIF(); return 0; diff --git a/src/unif.h b/src/unif.h index f7df71d..8e58113 100644 --- a/src/unif.h +++ b/src/unif.h @@ -158,6 +158,12 @@ void UNLRT01_Init(CartInfo *info); void BMC810131C_Init(CartInfo *info); void BMC8IN1_Init(CartInfo *info); +/* additional boards */ +void BMC60311C_Init(CartInfo *info); /* m289 */ +void BMCWS_Init(CartInfo *info); /* m332 */ +void UNLKS202_Init(CartInfo *info); /* m056 */ +void BMCHPxx_Init(CartInfo *info); /* m260 */ + #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); void MapperCopyFami_Init(CartInfo *info); From 6fd12ed6bf9899f81e96b45f273dce4f1e4b8862 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 27 May 2019 21:35:12 +0800 Subject: [PATCH 09/74] BMC-8157: ignore prg mapping for split rom types - fixes 1 of only 2 CK-001 4-in-1 carts i found so far --- src/boards/8157.c | 9 ++++++--- src/boards/KS7032.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/boards/8157.c b/src/boards/8157.c index 8a95353..f62cb8f 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -36,10 +36,13 @@ static void Sync(void) { uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; uint32 bank = (cmdreg & 0x01C) >> 2; uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); - if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); /* for versions with split ROMs */ + /* this fails to load at least one game, which probably has invalid PRG size in header + * (rom is only 512KB but reported as having 3 prg banks with 128k each) */ + /*if (PRGptr[1]) { + setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs setprg16r(base >> 3, 0xC000, lbank); - } else { + } else*/ + { setprg16(0x8000, base | bank); setprg16(0xC000, base | lbank); } diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 5a5bd53..7a8bdfc 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -2,7 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2019 Libretro Team (IRQ Update) + * Copyright (C) 2019 Libretro 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 From ffef1743d86ea0da149998e4e91d71928bfe7c7c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 27 May 2019 21:39:27 +0800 Subject: [PATCH 10/74] Add Super Donkey Kong (Unl) [o1] to ines-correct --- src/ines-correct.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ines-correct.h b/src/ines-correct.h index fde6d54..3c0a31a 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -317,6 +317,7 @@ {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ + {0xdb9d71b7, 114, -1}, /* Super Donkey Kong (Unl) [o1] */ {0x00000000, -1, -1} #endif From 5dc795233bce0ad437410cf7df2f7a42602069f9 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 29 May 2019 09:02:58 +0800 Subject: [PATCH 11/74] unif: Assign a few boards to ines mappers - CHINA_ER_SAN2 -> Mapper19_Init, http://forums.nesdev.com/viewtopic.php?t=16465&p=216531 - WAIXING-FW01 -> Mapper227_Init, https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 - WAIXING-FS005 -> BMCFK23C_Init, https://wiki.nesdev.com/w/index.php/INES_Mapper_176 --- src/unif.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/unif.c b/src/unif.c index e0f961b..3a4f352 100644 --- a/src/unif.c +++ b/src/unif.c @@ -468,6 +468,10 @@ static BMAPPING bmap[] = { { "WS", BMCWS_Init, 0 }, { "HPxx", BMCHPxx_Init, 0 }, + { "CHINA_ER_SAN2", Mapper19_Init, 0 }, /* http://forums.nesdev.com/viewtopic.php?t=16465&p=216531 */ + { "WAIXING-FW01", Mapper227_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 */ + { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ + #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, { "COPYFAMI", MapperCopyFami_Init, 0 }, From 28e729177ef5024ecc94fe53a6735debb7c497d5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 29 May 2019 19:06:28 +0800 Subject: [PATCH 12/74] Implement mapper 224 (kt-008) and add related games to ines-correct - Most of these games are incorrectly assigned to Mapper 4. so correct it with hash http://wiki.nesdev.com/w/index.php/INES_Mapper_224 --- src/boards/224.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ src/ines-correct.h | 6 ++++++ src/ines.c | 2 +- src/ines.h | 1 + 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/boards/224.c diff --git a/src/boards/224.c b/src/boards/224.c new file mode 100644 index 0000000..8fd7a19 --- /dev/null +++ b/src/boards/224.c @@ -0,0 +1,50 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* 2019-05-29 - Mapper 224, KT-008 + * iNES Mapper 224 is used for the 晶科泰 (Jncota) KT-008 PCB. + * It's an MMC3 clone that supports 1024 KiB of PRG-ROM through an additional + * outer bank register at $5000. + * http://wiki.nesdev.com/w/index.php/INES_Mapper_224 */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M224PW(uint32 A, uint8 V) { + setprg8(A, V & 0x3f | (EXPREGS[0] << 4) & 0x40); +} + +static DECLFW(Mapper224Write) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); +} + +static void M224Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x5000, 0x5000, Mapper224Write); +} + +void Mapper224_Init(CartInfo *info) { + GenMMC3_Init(info, 1024, 0, 8, 0); + pwrap = M224PW; + info->Power = M224Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index 3c0a31a..77c041f 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -318,6 +318,12 @@ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ {0xdb9d71b7, 114, -1}, /* Super Donkey Kong (Unl) [o1] */ + + {0x61fc4d20, 224, 0}, /* Pokemon HeartGold (KT-008 PCB)(Ch)[!] */ + {0x4d735cb1, 224, 0}, /* Pokemon Platinum (KT-008 PCB)(Ch)[!] */ + {0x4f427110, 224, 0}, /* Pokemon Platinum Alt title 1 (KT-008 PCB)(Ch)[!] */ + {0xe001de16, 224, 0}, /* Pokemon Platinum Alt title 2 (KT-008 PCB)(Ch)[!] */ + {0x00000000, -1, -1} #endif diff --git a/src/ines.c b/src/ines.c index acec60f..ee468e6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -613,7 +613,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"UNLN625092", 221, UNLN625092_Init}, {(uint8_t*)"", 222, Mapper222_Init}, /* {(uint8_t*)"", 223, Mapper223_Init}, */ -/* {(uint8_t*)"", 224, Mapper224_Init}, */ + {(uint8_t*)"KT-008", 224, Mapper224_Init}, {(uint8_t*)"", 225, Mapper225_Init}, {(uint8_t*)"BMC 22+20-in-1", 226, Mapper226_Init}, {(uint8_t*)"", 227, Mapper227_Init}, diff --git a/src/ines.h b/src/ines.h index 61402c2..3e44574 100644 --- a/src/ines.h +++ b/src/ines.h @@ -201,6 +201,7 @@ void Mapper216_Init(CartInfo *); void Mapper217_Init(CartInfo *); void Mapper220_Init(CartInfo *); void Mapper222_Init(CartInfo *); +void Mapper224_Init(CartInfo *); void Mapper225_Init(CartInfo *); void Mapper226_Init(CartInfo *); void Mapper227_Init(CartInfo *); From 3d4ebd5b7b5ddc42be5e0149ddb2389383e16caa Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 30 May 2019 22:42:53 +0800 Subject: [PATCH 13/74] Add mapper 126 - supports the game, PowerJoy 84-in-1 Multicart (PJ-008) --- src/boards/126.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 +- src/ines.h | 1 + 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/boards/126.c diff --git a/src/boards/126.c b/src/boards/126.c new file mode 100644 index 0000000..0a93910 --- /dev/null +++ b/src/boards/126.c @@ -0,0 +1,105 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 126, PowerJoy 84-in-1 Multicart (PJ-008*/ +/* reference from nestopia since not available in nesdev */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint16 GetExChrExBank() { + uint16 bank = (uint16)EXPREGS[0]; + return ((~bank << 0 & 0x080 & ((uint16)EXPREGS[2])) | (bank << 4 & 0x080 & bank) | + (bank << 3 & 0x100) | (bank << 5 & 0x200)); +} + +static void UpdateChrBank(void) { + uint16 bank = (uint16)EXPREGS[2] & 0x0F; + bank |= GetExChrExBank() >> 3; + setchr8(bank); +} + +static void M126CW(uint32 A, uint8 V) { + if (!(EXPREGS[3] & 0x10)) { + uint16 bank = (uint16)V & (((uint16)EXPREGS[0] & 0x80) - 1); + bank |= GetExChrExBank(); + setchr1(A, bank); + } +} + +static void M126PW(uint32 A, uint8 V) { + uint16 bank = (uint16)V; + uint16 preg = (uint16)EXPREGS[0]; + bank &= ((~preg >> 2) & 0x10) | 0x0F; + bank |= ((preg & (0x06 | (preg & 0x40) >> 6)) << 4) | ((preg & 0x10) << 3); + if (!(EXPREGS[3] & 0x03)) + setprg8(A, bank); + else if ((A - 0x8000) == ((MMC3_cmd << 8) & 0x4000)) { /* TODO: Clean this */ + if ((EXPREGS[3] & 0x3) == 0x3) + setprg32(0x8000, (bank >> 2)); + else { + setprg16(0x8000, (bank >> 1)); + setprg16(0xc000, (bank >> 1)); + } + } +} + +static DECLFW(M126Write) { + A &= 0x03; + if(A == 0x01 || A == 0x02 || ((A == 0x00 || A == 0x03) && !(EXPREGS[3] & 0x80))) { + if (EXPREGS[A] != V) { + EXPREGS[A] = V; + if (EXPREGS[3] & 0x10) + UpdateChrBank(); + else + FixMMC3CHR(MMC3_cmd); + FixMMC3PRG(MMC3_cmd); + } + } +} + +void M126StateRestore(int v) { + FixMMC3CHR(MMC3_cmd); + FixMMC3PRG(MMC3_cmd); + + if (EXPREGS[3] & 0x10) + UpdateChrBank(); +} + +static void M126Reset(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + MMC3RegReset(); +} + +static void M126Power(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, M126Write); +} + +void Mapper126_Init(CartInfo *info) { + GenMMC3_Init(info, 2048, 1023, 0, 0); + cwrap = M126CW; + pwrap = M126PW; + info->Power = M126Power; + info->Reset = M126Reset; + GameStateRestore = M126StateRestore; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index ee468e6..6ca2069 100644 --- a/src/ines.c +++ b/src/ines.c @@ -515,7 +515,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"MMC3 PIRATE H2288", 123, UNLH2288_Init}, /* {(uint8_t*)"", 124, Mapper124_Init}, */ {(uint8_t*)"FDS LH32", 125, LH32_Init}, -/* {(uint8_t*)"", 126, Mapper126_Init}, */ + {(uint8_t*)"PowerJoy 84-in-1", 126, Mapper126_Init}, /* {(uint8_t*)"", 127, Mapper127_Init}, */ /* {(uint8_t*)"", 128, Mapper128_Init}, */ /* {(uint8_t*)"", 129, Mapper129_Init}, */ diff --git a/src/ines.h b/src/ines.h index 3e44574..75a801d 100644 --- a/src/ines.h +++ b/src/ines.h @@ -139,6 +139,7 @@ void Mapper119_Init(CartInfo *); void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); void Mapper125_Init(CartInfo *); +void Mapper126_Init(CartInfo *); void Mapper134_Init(CartInfo *); void Mapper140_Init(CartInfo *); void Mapper144_Init(CartInfo *); From 897221a50321fd71b129523bb8f0dab3e8b7c8b4 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 30 May 2019 22:56:40 +0800 Subject: [PATCH 14/74] Fix missing openbus read in mapper 63 --- src/boards/addrlatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index ec1a3f1..86a2e72 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -223,7 +223,7 @@ static void M63Sync(void) { } void Mapper63_Init(CartInfo *info) { - Latch_Init(info, M63Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); + Latch_Init(info, M63Sync, M63Read, 0x0000, 0x8000, 0xFFFF, 0); } /*------------------ Map 092 ---------------------------*/ From 1c0d0192d1db77b81e7cd8721a749ab787f29580 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 30 May 2019 23:09:39 +0800 Subject: [PATCH 15/74] Silence clang warnings (-Wbitwise-op-parentheses) --- src/boards/224.c | 2 +- src/boards/28.c | 28 ++++++++++++++-------------- src/boards/KS7032.c | 4 ++-- src/ines.c | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/boards/224.c b/src/boards/224.c index 8fd7a19..7c885b7 100644 --- a/src/boards/224.c +++ b/src/boards/224.c @@ -28,7 +28,7 @@ #include "mmc3.h" static void M224PW(uint32 A, uint8 V) { - setprg8(A, V & 0x3f | (EXPREGS[0] << 4) & 0x40); + setprg8(A, (V & 0x3f) | ((EXPREGS[0] << 4) & 0x40)); } static DECLFW(Mapper224Write) { diff --git a/src/boards/28.c b/src/boards/28.c index 2cb95f0..4fdd088 100644 --- a/src/boards/28.c +++ b/src/boards/28.c @@ -72,51 +72,51 @@ static void Sync() { break; case 0x10: case 0x14: - prglo = outb & ~2 | prg << 1 & 2; - prghi = outb & ~2 | prg << 1 & 2 | 1; + prglo = (outb & ~2) | (prg << 1 & 2); + prghi = (outb & ~2) | (prg << 1 & 2) | 1; break; case 0x20: case 0x24: - prglo = outb & ~6 | prg << 1 & 6; - prghi = outb & ~6 | prg << 1 & 6 | 1; + prglo = (outb & ~6) | (prg << 1 & 6); + prghi = (outb & ~6) | (prg << 1 & 6) | 1; break; case 0x30: case 0x34: - prglo = outb & ~14 | prg << 1 & 14; - prghi = outb & ~14 | prg << 1 & 14 | 1; + prglo = (outb & ~14) | (prg << 1 & 14); + prghi = (outb & ~14) | (prg << 1 & 14) | 1; break; /* bottom fixed modes */ case 0x08: prglo = outb; - prghi = outb | prg & 1; + prghi = outb | (prg & 1); break; case 0x18: prglo = outb; - prghi = outb & ~2 | prg & 3; + prghi = (outb & ~2) | (prg & 3); break; case 0x28: prglo = outb; - prghi = outb & ~6 | prg & 7; + prghi = (outb & ~6) | (prg & 7); break; case 0x38: prglo = outb; - prghi = outb & ~14 | prg & 15; + prghi = (outb & ~14) | (prg & 15); break; /* top fixed modes */ case 0x0c: - prglo = outb | prg & 1; + prglo = outb | (prg & 1); prghi = outb | 1; break; case 0x1c: - prglo = outb & ~2 | prg & 3; + prglo = (outb & ~2) | (prg & 3); prghi = outb | 1; break; case 0x2c: - prglo = outb & ~6 | prg & 7; + prglo = (outb & ~6) | (prg & 7); prghi = outb | 1; break; case 0x3c: - prglo = outb & ~14 | prg & 15; + prglo = (outb & ~14) | (prg & 15); prghi = outb | 1; break; } diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 7a8bdfc..41739af 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -93,7 +93,7 @@ static DECLFW(UNLKS7032Write) { case 0xF000: { uint8 bank = (cmd - 1); if (bank < 3) - reg[bank] = reg[bank] & 0x10 | V & 0x0F; + reg[bank] = (reg[bank] & 0x10) | (V & 0x0F); else if (bank < 4) reg[bank] = V; Sync(); @@ -101,7 +101,7 @@ static DECLFW(UNLKS7032Write) { case 0xF000: A &= 3; if (A < 3) - reg[bank] = reg[bank] & 0x0F | V & 0x10; + reg[bank] = (reg[bank] & 0x0F) | (V & 0x10); Sync(); break; case 0xF800: diff --git a/src/ines.c b/src/ines.c index 6ca2069..94f6087 100644 --- a/src/ines.c +++ b/src/ines.c @@ -515,7 +515,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"MMC3 PIRATE H2288", 123, UNLH2288_Init}, /* {(uint8_t*)"", 124, Mapper124_Init}, */ {(uint8_t*)"FDS LH32", 125, LH32_Init}, - {(uint8_t*)"PowerJoy 84-in-1", 126, Mapper126_Init}, + {(uint8_t*)"PowerJoy 84-in-1 PJ-008", 126, Mapper126_Init}, /* {(uint8_t*)"", 127, Mapper127_Init}, */ /* {(uint8_t*)"", 128, Mapper128_Init}, */ /* {(uint8_t*)"", 129, Mapper129_Init}, */ From 5c4a659b4953776f7732c6b8b241a58bf7bc9e7f Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 31 May 2019 19:45:45 +0800 Subject: [PATCH 16/74] mapper63: try fixing openbus reads again --- src/boards/addrlatch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 86a2e72..7bda0c1 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -202,9 +202,12 @@ void Mapper61_Init(CartInfo *info) { * - Powerful 250-in-1 * - Hello Kitty 255-in-1 */ +static uint16 openBus; + static DECLFR(M63Read) { - if (latche & 0x0300) - return X.DB; + if (A < 0xC000) + if (openBus) + return X.DB; return CartBR(A); } @@ -213,6 +216,7 @@ static void M63Sync(void) { uint16 prg_bank = (latche & 0x3F8) >> 1; uint16 prg16 = (latche & 4) >> 1; + openBus = ((latche & 0x300) == 0x300); setprg8(0x8000, (prg_bank | (mode ? 0 : prg16 | 0))); setprg8(0xA000, (prg_bank | (mode ? 1 : prg16 | 1))); setprg8(0xC000, (prg_bank | (mode ? 2 : prg16 | 0))); From 950479cc7a4b5b9a51857316754925d2743f7f4c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 31 May 2019 20:18:48 +0800 Subject: [PATCH 17/74] NROM: update prg mapping --- src/boards/datalatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index c13454b..be7bd9b 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -94,7 +94,7 @@ static DECLFW(NROMWrite) { static void NROMPower(void) { setprg8r(0x10, 0x6000, 0); /* Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB */ setprg16(0x8000, 0); - setprg16(0xC000, ~0); + setprg16(0xC000, 1); setchr8(0); SetReadHandler(0x6000, 0x7FFF, CartBR); From 74513dd8e4e11f329327ed143518ef60b51f4a2d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 1 Jun 2019 01:35:19 +0800 Subject: [PATCH 18/74] Update bus conflict for some games using mapper 3, add some games to ines-correct.h --- src/boards/datalatch.c | 3 +++ src/ines-correct.h | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index be7bd9b..4a563f3 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -168,6 +168,9 @@ void CNROM_Init(CartInfo *info) { case 0xebd0644d: /* Dao Shuai (Asia) (Unl).nes */ case 0x8f154a0d: /* Pu Ke Jing Ling (China) (Unl).nes */ case 0xd04a40e6: /* Bingo 75 (Asia) (Unl).nes */ + case 0xe41b440f: /* Sidewinder (Joy Van) */ + case 0xb0c871c5: /* Wei Lai Xiao Zi (Joy Van) */ + case 0xb3be2f71: /* Yanshan Chess (Unl) */ _busc = 0; break; } diff --git a/src/ines-correct.h b/src/ines-correct.h index 77c041f..1a0c89d 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -318,12 +318,24 @@ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ {0xdb9d71b7, 114, -1}, /* Super Donkey Kong (Unl) [o1] */ - {0x61fc4d20, 224, 0}, /* Pokemon HeartGold (KT-008 PCB)(Ch)[!] */ {0x4d735cb1, 224, 0}, /* Pokemon Platinum (KT-008 PCB)(Ch)[!] */ {0x4f427110, 224, 0}, /* Pokemon Platinum Alt title 1 (KT-008 PCB)(Ch)[!] */ {0xe001de16, 224, 0}, /* Pokemon Platinum Alt title 2 (KT-008 PCB)(Ch)[!] */ + {0xbdbe3c96, 238, 1}, /* Contra Fighter (Unl) */ + {0xcfe02ada, 1, -1}, /* Darkman (E) [!] */ + {0xcb53c523, 1, -1}, /* King Neptune's Adventure (Color Dreams) [!] */ + {0x6e149729, 189, -1}, /* Master Fighter II (Unl) [a1] */ + {0x60bfeb0c, 90, -1}, /* Mortal Kombat 2 (Unl) [!] */ + {0x247cc73d, 150, -1}, /* Poker II (Sachen) [!] */ + {0xe41b440f, 3, 0}, /* Sidewinder (Joy Van) */ + {0x1f1326d4, 121, 0}, /* Super Sonic 5 (1997) (Unl) [!] */ + {0xb0c871c5, 3, 1}, /* Wei Lai Xiao Zi (Joy Van) */ + {0xb3be2f71, 3, 0}, /* Yanshan Chess (Unl) */ + {0x8dedea07, 3, 1}, /* Shui Guo Li (Ch) [a1] */ + {0x1a71fd06, 1, 1}, /* Kujaku Ou (J) [T+Eng1.1_Snark] */ + {0x00000000, -1, -1} #endif From c447b412fc9963f42570700042ee5031700dbe46 Mon Sep 17 00:00:00 2001 From: hizzlekizzle Date: Fri, 31 May 2019 18:27:04 -0500 Subject: [PATCH 19/74] stop travis building for wii u at least for now this should make the CI plugin a little more informative for this core --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 451cdd7..e652e3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ env: - PLATFORM=linux_x64 - PLATFORM=ngc - PLATFORM=wii - - PLATFORM=wiiu +# - PLATFORM=wiiu before_script: - pwd - mkdir -p ~/bin From 7e745cc5eb55c04799dcb69c93da99c869aeff6b Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 1 Jun 2019 18:29:20 +0800 Subject: [PATCH 20/74] Assign a few more games as mapper 215 - these games were assigned to mapper 217 in goodnes. this mapper is deprecated and the said games are Mapper 215's - Minor adjustment of rom info logs at startup --- src/ines-correct.h | 3 +++ src/ines.c | 17 ++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/ines-correct.h b/src/ines-correct.h index 1a0c89d..e52a69b 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -335,6 +335,9 @@ {0xb3be2f71, 3, 0}, /* Yanshan Chess (Unl) */ {0x8dedea07, 3, 1}, /* Shui Guo Li (Ch) [a1] */ {0x1a71fd06, 1, 1}, /* Kujaku Ou (J) [T+Eng1.1_Snark] */ + {0x99748230, 215, 0}, /* EarthWorm Jim 2 (SuperGame) */ + {0x37876ac7, 215, 0}, /* Golden Card 6-in-1 (Unl) [!] */ + {0x1a3320a3, 215, 0}, /* Mortal Kombat 3 (SuperGame) */ {0x00000000, -1, -1} diff --git a/src/ines.c b/src/ines.c index 94f6087..b14b248 100644 --- a/src/ines.c +++ b/src/ines.c @@ -295,6 +295,8 @@ static void CheckHInfo(void) { }; int32 tofix = 0, x; uint64 partialmd5 = 0; + int current_mapper = 0; + int cur_mirr = 0; for (x = 0; x < 8; x++) partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8); @@ -312,10 +314,12 @@ static void CheckHInfo(void) { } if (MapperNo != (moo[x].mapper & 0xFF)) { tofix |= 1; + current_mapper = MapperNo; MapperNo = moo[x].mapper & 0xFF; } } if (moo[x].mirror >= 0) { + cur_mirr = Mirroring; if (moo[x].mirror == 8) { if (Mirroring == 2) { /* Anything but hard-wired(four screen). */ tofix |= 2; @@ -361,12 +365,12 @@ static void CheckHInfo(void) { if (tofix) { char gigastr[768]; - strcpy(gigastr, "The iNES header contains incorrect information. For now, the information will be corrected in RAM. "); + 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); + sprintf(gigastr + strlen(gigastr), "Current mapper # is %d. The mapper number should be set to %d. ", current_mapper, MapperNo); if (tofix & 2) { uint8 *mstr[3] = { (uint8_t*)"Horizontal", (uint8_t*)"Vertical", (uint8_t*)"Four-screen" }; - sprintf(gigastr + strlen(gigastr), "Mirroring should be set to \"%s\". ", mstr[Mirroring & 3]); + sprintf(gigastr + strlen(gigastr), "Current mirroring is %s. Mirroring should be set to \"%s\". ", mstr[cur_mirr & 3], mstr[Mirroring & 3]); } if (tofix & 4) strcat(gigastr, "The battery-backed bit should be set. "); @@ -604,7 +608,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"", 212, Mapper212_Init}, {(uint8_t*)"", 213, Mapper213_Init}, {(uint8_t*)"", 214, Mapper214_Init}, - {(uint8_t*)"", 215, UNL8237_Init}, + {(uint8_t*)"UNL-8237", 215, UNL8237_Init}, {(uint8_t*)"", 216, Mapper216_Init}, {(uint8_t*)"", 217, Mapper217_Init}, /* Redefined to a new Discrete BMC mapper */ /* {(uint8_t*)"", 218, Mapper218_Init}, */ @@ -743,6 +747,8 @@ int iNESLoad(const char *name, FCEUFILE *fp) { iNESCart.CRC32 = iNESGameCRC32; + SetInput(); + CheckHInfo(); mappername = "Not Listed"; for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { @@ -751,9 +757,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) { break; } } - - SetInput(); - CheckHInfo(); { int x; uint64 partialmd5 = 0; From 38ba67413f95724ce3157fda3965c1d8333d1dac Mon Sep 17 00:00:00 2001 From: Yoshi Sugawara Date: Mon, 10 Jun 2019 17:16:00 -1000 Subject: [PATCH 21/74] Add back support for pointer device (touchscreen) for lightgun input --- src/drivers/libretro/libretro.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 0b20614..8e324a6 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -78,7 +78,8 @@ static bool enable_4player = false; static unsigned turbo_enabler[MAX_PLAYERS] = {0}; static unsigned turbo_delay = 0; static unsigned input_type[MAX_PLAYERS + 1] = {0}; /* 4-players + famicom expansion */ -static unsigned lightgun_enabled = 1; /* 0=mouse 1=lightgun(default) */ +enum RetroZapperInputModes{RetroLightgun, RetroMouse, RetroPointer}; +static enum RetroZapperInputModes zappermode = RetroLightgun; /* emulator-specific variables */ @@ -765,7 +766,7 @@ static void set_variables(void) #endif { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, { "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" }, - { "fceumm_zapper_mode", "Zapper Mode; lightgun|mouse" }, + { "fceumm_zapper_mode", "Zapper Mode; lightgun|touchscreen|mouse" }, { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, @@ -1190,8 +1191,9 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if (!strcmp(var.value, "mouse")) lightgun_enabled = 0; - else lightgun_enabled = 1; /*default setting*/ + if (!strcmp(var.value, "mouse")) zappermode = RetroMouse; + else if (!strcmp(var.value, "touchscreen")) zappermode = RetroPointer; + else zappermode = RetroLightgun; /*default setting*/ } var.key = "fceumm_show_crosshair"; @@ -1381,7 +1383,7 @@ void get_mouse_input(unsigned port, uint32_t *zapdata) max_height = 240; zapdata[2] = 0; /* reset click state */ - if (!lightgun_enabled) /* mouse device */ + if (zappermode == RetroMouse) /* mouse device */ { min_width = (adjx ? 8 : 0) + 1; min_height = (adjy ? 8 : 0) + 1; @@ -1407,6 +1409,27 @@ void get_mouse_input(unsigned port, uint32_t *zapdata) if (input_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT)) zapdata[2] |= 0x2; } + else if (zappermode == RetroPointer) { + int offset_x = (adjx ? 0X8FF : 0); + int offset_y = (adjy ? 0X999 : 0); + + int _x = input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); + int _y = input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); + + if (_x == 0 && _y == 0) + { + zapdata[0] = 0; + zapdata[1] = 0; + } + else + { + zapdata[0] = (_x + (0x7FFF + offset_x)) * max_width / ((0x7FFF + offset_x) * 2); + zapdata[1] = (_y + (0x7FFF + offset_y)) * max_height / ((0x7FFF + offset_y) * 2); + } + + if (input_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) + zapdata[2] |= 0x1; + } else /* lightgun device */ { int offset_x = (adjx ? 0X8FF : 0); From 67ae7663b8ad0e277d3feff58a69faecde8389ff Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 11 Jun 2019 22:10:39 +0800 Subject: [PATCH 22/74] Add m114.1(boogerman), m281, bmc-80013b. Update m205. Disable kt-008 hack on mmc3. Add a few games to ines-correct.h - Support for Boogerman (SuperGame) Mapper 114, submapper 1 - Update Mapper 205 based on nesdev, move previous mapper 205 to separate GN-45 mapper with retained support to emulate OK-411 - Use nes-to-unif wrapper for some games which does not have nes 2.0 header. - add unif board BMC-80013-B - add mapper 281 (JY-052) - disable KT-008 hack on mmc3. KT-008 boards should be assigned as Mapper 224. Fixes Final Fantasy X1/X2 - force-assign a few roms using ines-correct.h --- src/boards/90.c | 101 +++++++++++++++++++------------ src/boards/bmc80013b.c | 77 ++++++++++++++++++++++++ src/boards/mmc3.c | 132 +++++++++++++++++++++++++++++++++-------- src/ines-correct.h | 22 ++++++- src/ines.c | 17 ++++-- src/ines.h | 3 + src/unif.c | 6 +- src/unif.h | 1 + 8 files changed, 288 insertions(+), 71 deletions(-) create mode 100644 src/boards/bmc80013b.c diff --git a/src/boards/90.c b/src/boards/90.c index bdbd3a0..2bc867a 100644 --- a/src/boards/90.c +++ b/src/boards/90.c @@ -3,6 +3,7 @@ * Copyright notice for this file: * Copyright (C) 2002 Xodnizel * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro 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 @@ -25,10 +26,12 @@ /* Mapper 090 is simpliest mapper hardware and have not extended nametable control and latched chr banks in 4k mode * Mapper 209 much compicated hardware with decribed above features disabled by default and switchable by command * Mapper 211 the same mapper 209 but with forced nametable control + * Mapper 281 PRG ($8000-$8FFF) and CHR ($9000-$AFFF) bank select register bits that select 256 KiB banks are masked off. */ static int is209; static int is211; +static int is281; static uint8 IRQMode; /* from $c001 */ static uint8 IRQPre; /* from $c004 */ @@ -73,7 +76,7 @@ static SFORMAT Tek_StateRegs[] = { }; static void mira(void) { - if ((tkcom[0] & 0x20 && is209) || is211) { + if (((tkcom[0] & 0x20) && is209) || is211 || ((tkcom[1] & 0x08) && is281)) { int x; if (tkcom[0] & 0x40) { /* Name tables are ROM-only */ for (x = 0; x < 4; x++) @@ -96,56 +99,64 @@ static void mira(void) { } } +static uint8 invertprg(uint8 bank, uint8 reverse) { + if (reverse) + return ((bank & 0x01) << 6 | (bank & 0x02) << 4 | (bank & 0x04) << 2 | + (bank & 0x10) >> 2 | (bank & 0x20) >> 4 | (bank & 0x40) >> 6); + else + return bank; +} + static void tekprom(void) { - uint32 bankmode = ((tkcom[3] & 6) << 5); - switch (tkcom[0] & 7) { - case 00: + uint8 prgshift = 0, prgmask = 0x3F, outb_sel = 0x06, last_bank = 0x3F; + uint8 prgmode = tkcom[0] & 0x03; + uint8 invert = (tkcom[0] & 0x03) == 0x03 ? 1 : 0; + uint32 bankmode = 0; + + switch (tkcom[0] & 0x03) { + case 0x00: prgshift = 3; prgmask = 0x0F; break; + case 0x01: prgshift = 4; prgmask = 0x1F; break; + default: prgshift = 5; prgmask = 0x3F; break; + } + + if (is281) { + prgmask >>= 1; + outb_sel = 0x01; + } + + bankmode = ((tkcom[3] & outb_sel) << prgshift); + last_bank = (tkcom[0] & 0x04) ? prgb[3] : prgmask; + switch (prgmode) { + case 0x00: if (tkcom[0] & 0x80) setprg8(0x6000, (((prgb[3] << 2) + 3) & 0x3F) | bankmode); - setprg32(0x8000, 0x0F | ((tkcom[3] & 6) << 3)); + setprg32(0x8000, last_bank & prgmask | bankmode); break; - case 01: + case 0x01: if (tkcom[0] & 0x80) setprg8(0x6000, (((prgb[3] << 1) + 1) & 0x3F) | bankmode); - setprg16(0x8000, (prgb[1] & 0x1F) | ((tkcom[3] & 6) << 4)); - setprg16(0xC000, 0x1F | ((tkcom[3] & 6) << 4)); + setprg16(0x8000, (prgb[1] & prgmask) | bankmode); + setprg16(0xC000, last_bank & prgmask | bankmode); break; - case 03: /* bit reversion */ - case 02: + case 0x02: + case 0x03: if (tkcom[0] & 0x80) - setprg8(0x6000, (prgb[3] & 0x3F) | bankmode); - setprg8(0x8000, (prgb[0] & 0x3F) | bankmode); - setprg8(0xa000, (prgb[1] & 0x3F) | bankmode); - setprg8(0xc000, (prgb[2] & 0x3F) | bankmode); - setprg8(0xe000, 0x3F | bankmode); - break; - case 04: - if (tkcom[0] & 0x80) - setprg8(0x6000, (((prgb[3] << 2) + 3) & 0x3F) | bankmode); - setprg32(0x8000, (prgb[3] & 0x0F) | ((tkcom[3] & 6) << 3)); - break; - case 05: - if (tkcom[0] & 0x80) - setprg8(0x6000, (((prgb[3] << 1) + 1) & 0x3F) | bankmode); - setprg16(0x8000, (prgb[1] & 0x1F) | ((tkcom[3] & 6) << 4)); - setprg16(0xC000, (prgb[3] & 0x1F) | ((tkcom[3] & 6) << 4)); - break; - case 07: /* bit reversion */ - case 06: - if (tkcom[0] & 0x80) - setprg8(0x6000, (prgb[3] & 0x3F) | bankmode); - setprg8(0x8000, (prgb[0] & 0x3F) | bankmode); - setprg8(0xa000, (prgb[1] & 0x3F) | bankmode); - setprg8(0xc000, (prgb[2] & 0x3F) | bankmode); - setprg8(0xe000, (prgb[3] & 0x3F) | bankmode); + setprg8(0x6000, (invertprg(prgb[3], invert) & 0x3F) | bankmode); + setprg8(0x8000, (invertprg(prgb[0], invert) & prgmask) | bankmode); + setprg8(0xa000, (invertprg(prgb[1], invert) & prgmask) | bankmode); + setprg8(0xc000, (invertprg(prgb[2], invert) & prgmask) | bankmode); + setprg8(0xe000, (invertprg(last_bank, invert) & prgmask) | bankmode); break; } } static void tekvrom(void) { int x, bank = 0, mask = 0xFFFF; - if (!(tkcom[3] & 0x20)) { - bank = (tkcom[3] & 1) | ((tkcom[3] & 0x18) >> 2); + if (!(tkcom[3] & 0x20) || is281) { + if (is281) + bank = tkcom[3] & 1; + else + bank = (tkcom[3] & 1) | ((tkcom[3] & 0x18) >> 2); switch (tkcom[0] & 0x18) { case 0x00: bank <<= 5; mask = 0x1F; break; case 0x08: bank <<= 6; mask = 0x3F; break; @@ -445,6 +456,7 @@ static void M90Power(void) { void Mapper90_Init(CartInfo *info) { is211 = 0; is209 = 0; + is281 = 0; info->Reset = togglie; info->Power = M90Power; PPU_hook = M90PPU; @@ -457,6 +469,7 @@ void Mapper90_Init(CartInfo *info) { void Mapper209_Init(CartInfo *info) { is211 = 0; is209 = 1; + is281 = 0; info->Reset = togglie; info->Power = M90Power; PPU_hook = M90PPU; @@ -468,6 +481,20 @@ void Mapper209_Init(CartInfo *info) { void Mapper211_Init(CartInfo *info) { is211 = 1; + is281 = 0; + info->Reset = togglie; + info->Power = M90Power; + PPU_hook = M90PPU; + MapIRQHook = CPUWrap; + GameHBIRQHook2 = SLWrap; + GameStateRestore = M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper281_Init(CartInfo *info) { + is211 = 0; + is209 = 0; + is281 = 1; info->Reset = togglie; info->Power = M90Power; PPU_hook = M90PPU; diff --git a/src/boards/bmc80013b.c b/src/boards/bmc80013b.c new file mode 100644 index 0000000..51fb150 --- /dev/null +++ b/src/boards/bmc80013b.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 274 is used for the 90-in-1 Hwang Shinwei multicart. + * Its UNIF board name is BMC-80013-B. + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_274 */ + +#include "mapinc.h" + +static uint8 regs[2], mode; + +static SFORMAT StateRegs[] = +{ + { ®s[0], 1, "REG0" }, + { ®s[1], 1, "REG1" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + if (mode & 0x02) + setprg16(0x8000, regs[0] & 0x0F | regs[1] & 0x70); + else + setprg16r(1, 0x8000, regs[0] & 0x03); + setprg16(0xC000, regs[1]); + SetupCartMirroring(((regs[0] >> 4) & 1) ^ 1, 1, NULL); +} + +static DECLFW(BMC80013BWrite) { + uint8 reg = (A >> 13) & 0x03; + if (!reg) + regs[0] = V & 0x1F; + else { + regs[1] = V & 0x7F; + mode = reg; + } + Sync(); +} + +static void BMC80013BPower(void) { + Sync(); + setchr8(0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BMC80013BWrite); +} + +static void BMC80013BReset(void) { + regs[0] = regs[1] = mode = 0; + Sync(); +} + +static void BMC80013BRestore(int version) { + Sync(); +} + +void BMC80013B_Init(CartInfo *info) { + info->Power = BMC80013BPower; + info->Reset = BMC80013BReset; + GameStateRestore = BMC80013BRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index d2d3369..9ac6f86 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -236,8 +236,9 @@ static void GENPWRAP(uint32 A, uint8 V) { /* [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken * also HengGe BBC-2x boards enables this mode as default board mode at boot up */ - setprg8(A, (V & 0x7F) | ((kt_extra & 4) << 4)); + setprg8(A, (V & 0x7F)/* | ((kt_extra & 4) << 4)*/); /* KT-008 boards hack 2-in-1, TODO assign to new ines mapper, most dump of KT-boards on the net are mapper 4, so need database or goodnes fix support */ + /* KT-008 boards should be assigned to mapper 224 */ } static void GENMWRAP(uint8 V) { @@ -265,7 +266,7 @@ void GenMMC3Power(void) { SetReadHandler(0x8000, 0xFFFF, CartBR); /* KT-008 boards hack 2-in-1, TODO assign to new ines mapper, most dump of KT-boards on the net are mapper 4, so need database or goodnes fix support */ - SetWriteHandler(0x5000,0x5FFF, KT008HackWrite); + /* SetWriteHandler(0x5000,0x5FFF, KT008HackWrite); */ /* KT-008 boards should be assigned to mapper 224 */ A001B = A000B = 0; setmirror(1); @@ -321,6 +322,7 @@ void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery) { } /* KT-008 boards hack 2-in-1, TODO assign to new ines mapper, most dump of KT-boards on the net are mapper 4, so need database or goodnes fix support */ + /* KT-008 boards should be assigned to mapper 224 */ AddExState(&kt_extra, 1, 0, "KTEX"); AddExState(MMC3_StateRegs, ~0, 0, 0); @@ -720,18 +722,24 @@ void Mapper74_Init(CartInfo *info) { /* ---------------------------- Mapper 114 ------------------------------ */ -static uint8 cmdin; +static uint8 cmdin, type_Boogerman = 0; +uint8 boogerman_perm[8] = { 0, 2, 5, 3, 6, 1, 7, 4 }; uint8 m114_perm[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; static void M114PWRAP(uint32 A, uint8 V) { if (EXPREGS[0] & 0x80) { -/* FCEU_printf("8000-C000:%02X\n",EXPREGS[0]&0xF); */ - setprg16(0x8000, EXPREGS[0] & 0xF); - setprg16(0xC000, EXPREGS[0] & 0xF); - } else { -/* FCEU_printf("%04X:%02X\n",A,V&0x3F); */ - setprg8(A, V & 0x3F); - } + if (EXPREGS[0] & 0x20) + setprg32(0x8000, (EXPREGS[0] & 0x0F) >> 1); + else { + setprg16(0x8000, (EXPREGS[0] & 0x0F)); + setprg16(0xC000, (EXPREGS[0] & 0x0F)); + } + } else + setprg8(A, V); +} + +static void M114CWRAP(uint32 A, uint8 V) { + setchr1(A, (uint32)V | ((EXPREGS[1] & 1) << 8)); } static DECLFW(M114Write) { @@ -746,28 +754,52 @@ static DECLFW(M114Write) { } } +static DECLFW(BoogermanWrite) { + switch (A & 0xE001) { + case 0x8001: if (!cmdin) break; MMC3_CMDWrite(0x8001, V); cmdin = 0; break; + case 0xA000: MMC3_CMDWrite(0x8000, (V & 0xC0) | (boogerman_perm[V & 7])); cmdin = 1; break; + case 0xA001: IRQReload = 1; break; + case 0xC000: MMC3_CMDWrite(0xA000, V); break; + case 0xC001: IRQLatch = V; break; + case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; + case 0xE001: IRQa = 1; break; + } +} + static DECLFW(M114ExWrite) { if (A <= 0x7FFF) { - EXPREGS[0] = V; + if (A & 1) + EXPREGS[1] = V; + else + EXPREGS[0] = V; FixMMC3PRG(MMC3_cmd); } } static void M114Power(void) { + EXPREGS[0] = EXPREGS[1] = 0; GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, M114ExWrite); SetWriteHandler(0x8000, 0xFFFF, M114Write); - SetWriteHandler(0x5000, 0x7FFF, M114ExWrite); + if (type_Boogerman) + SetWriteHandler(0x8000, 0xFFFF, BoogermanWrite); } static void M114Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = EXPREGS[1] = 0; MMC3RegReset(); } void Mapper114_Init(CartInfo *info) { isRevB = 0; + type_Boogerman = 0; + if (info->CRC32 == 0x80eb1839 || /* Boogerman (Sugar Softec) (Unl) [!] - submapper 1 */ + info->CRC32 == 0x071e4ee8) /* 114 test-rom https://forums.nesdev.com/viewtopic.php?f=3&t=17391 */ + type_Boogerman = 1; + GenMMC3_Init(info, 256, 256, 0, 0); pwrap = M114PWRAP; + cwrap = M114CWRAP; info->Power = M114Power; info->Reset = M114Reset; AddExState(EXPREGS, 1, 0, "EXPR"); @@ -1137,22 +1169,21 @@ void Mapper198_Init(CartInfo *info) { } /* ---------------------------- Mapper 205 ------------------------------ */ -/* GN-45 BOARD */ +/* https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */ static void M205PW(uint32 A, uint8 V) { -/* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC 1F + \E0\EF\EF\E0\F0\E0\F2\ED\FB\E9 \EF\E5\F0\E5\EA\EB\FE\F7\E0\F2\E5\EB\FC \ED\E0 \F8\E8\ED\E5 \E0\E4\F0\E5\F1\E0 */ - setprg8(A, (V & 0x0f) | EXPREGS[0]); + setprg8(A, EXPREGS[0] & 0x30 | (V & (!(EXPREGS[0] & 0xC0) ? 0x1F : 0x0F))); } static void M205CW(uint32 A, uint8 V) { -/* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC FF */ - setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3)); + uint16 reg = (uint16)EXPREGS[0] & 0x30; + setchr1(A, (reg << 3) | V); } static DECLFW(M205Write0) { - if (EXPREGS[2] == 0) { - EXPREGS[0] = A & 0x30; - EXPREGS[2] = A & 0x80; + if (EXPREGS[1] == 0) { + EXPREGS[0] = (V << 4) & 0x30; + EXPREGS[1] = A & 0x80; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); } else @@ -1160,8 +1191,8 @@ static DECLFW(M205Write0) { } static DECLFW(M205Write1) { - if (EXPREGS[2] == 0) { - EXPREGS[0] = V & 0x30; + if (EXPREGS[1] == 0) { + EXPREGS[0] = V & 0xF0; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); } else @@ -1169,11 +1200,12 @@ static DECLFW(M205Write1) { } static void M205Reset(void) { - EXPREGS[0] = EXPREGS[2] = 0; + EXPREGS[0] = EXPREGS[1] = 0; MMC3RegReset(); } static void M205Power(void) { + EXPREGS[0] = EXPREGS[1] = 0; GenMMC3Power(); SetWriteHandler(0x6000, 0x6fff, M205Write0); SetWriteHandler(0x7000, 0x7fff, M205Write1); /* OK-411 boards, the same logic, but data latched, 2-in-1 frankenstein */ @@ -1188,6 +1220,58 @@ void Mapper205_Init(CartInfo *info) { AddExState(EXPREGS, 1, 0, "EXPR"); } +/* --------------------------- GN-45 BOARD ------------------------------ */ + +/* Mapper 361 and 366, previously assigned as Mapper 205 */ +static void GN45PW(uint32 A, uint8 V) { +/* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC 1F + \E0\EF\EF\E0\F0\E0\F2\ED\FB\E9 \EF\E5\F0\E5\EA\EB\FE\F7\E0\F2\E5\EB\FC \ED\E0 \F8\E8\ED\E5 \E0\E4\F0\E5\F1\E0 */ + setprg8(A, (V & 0x0f) | EXPREGS[0]); +} + +static void GN45CW(uint32 A, uint8 V) { +/* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC FF */ + setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3)); +} + +static DECLFW(GN45Write0) { + if (EXPREGS[2] == 0) { + EXPREGS[0] = A & 0x30; + EXPREGS[2] = A & 0x80; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + CartBW(A, V); +} + +static DECLFW(GN45Write1) { + if (EXPREGS[2] == 0) { + EXPREGS[0] = V & 0x30; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + CartBW(A, V); +} + +static void GN45Reset(void) { + EXPREGS[0] = EXPREGS[2] = 0; + MMC3RegReset(); +} + +static void GN45Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x6fff, GN45Write0); + SetWriteHandler(0x7000, 0x7fff, GN45Write1); /* OK-411 boards, the same logic, but data latched, 2-in-1 frankenstein */ +} + +void GN45_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = GN45PW; + cwrap = GN45CW; + info->Power = GN45Power; + info->Reset = GN45Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + /* ---------------------------- Mapper 245 ------------------------------ */ static void M245CW(uint32 A, uint8 V) { diff --git a/src/ines-correct.h b/src/ines-correct.h index e52a69b..fd6a6c0 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -167,7 +167,7 @@ {0x0d98db53, 114, -1}, /* Pocahontas */ {0x4e7729ff, 114, -1}, /* Super Donkey Kong */ {0xc5e5c5b2, 115, -1}, /* Bao Qing Tian (As).nes */ - {0xa1dc16c0, 116, -1}, /* Street Heroes (Sachen) [b1] */ +/* {0xa1dc16c0, 116, -1}, Street Heroes (Sachen) [b1] */ {0xe40dfb7e, 116, -1}, /* Somari (P conf.) */ {0xc9371ebb, 116, -1}, /* Somari (W conf.) */ {0x78b657ac, 118, -1}, /* Armadillo */ @@ -322,7 +322,6 @@ {0x4d735cb1, 224, 0}, /* Pokemon Platinum (KT-008 PCB)(Ch)[!] */ {0x4f427110, 224, 0}, /* Pokemon Platinum Alt title 1 (KT-008 PCB)(Ch)[!] */ {0xe001de16, 224, 0}, /* Pokemon Platinum Alt title 2 (KT-008 PCB)(Ch)[!] */ - {0xbdbe3c96, 238, 1}, /* Contra Fighter (Unl) */ {0xcfe02ada, 1, -1}, /* Darkman (E) [!] */ {0xcb53c523, 1, -1}, /* King Neptune's Adventure (Color Dreams) [!] */ @@ -338,6 +337,25 @@ {0x99748230, 215, 0}, /* EarthWorm Jim 2 (SuperGame) */ {0x37876ac7, 215, 0}, /* Golden Card 6-in-1 (Unl) [!] */ {0x1a3320a3, 215, 0}, /* Mortal Kombat 3 (SuperGame) */ + {0x80eb1839, 114, 0}, /* Boogerman (Sugar Softec) (Unl) [!] */ + {0x071e4ee8, 114, 0}, /* m114,submapper 1 test rom */ + {0xfe3e03a1, 197, -1}, /* Mortal Kombat III Special (YY-030) (Ch) [!] */ + {0x9151d311, 197, -1}, /* Mortal Kombat III 28 Peoples (NT-328) (Ch) [!] */ + {0xf6bd8e31, 281, 0}, /* 1997 Super HIK 4-in-1 (JY-052) [p1][!] */ + + /* ines mappers that uses iNes 2.0 numbers */ + + {0x5aa23a15, 361, 0}, /* 4-in-1 (OK-411)[p1][!] */ + {0xf6b9d088, 366, 0}, /* 4-in-1 (K-3131GS, GN-45) [p1][!] */ + {0x503566b2, 366, 0}, /* 4-in-1 (K-3131SS, GN-45) [p1][!] */ + + /* ines mappers that uses unif boards */ + + {0x0073dbd8, 260, -1}, /* 2-in-1 - Mortal Kombat V Turbo 30 + Super Aladdin (Unl) [p1][!] */ + {0x4dc6107d, 260, -1}, /* 2-in-1 - Boogerman + Flintstones, The (Unl) [p1][!] */ + {0xb72b2cf4, 260, -1}, /* 2-in-1 - Aladdin + Lion King, The (Unl) [p1][!] */ + {0xa1dc16c0, 262, -1}, /* Street Heroes (Asia) (Ja) (Unl */ + {0xf956fcea, 521, -1}, /* Korean Igo (Korea) (Unl) */ {0x00000000, -1, -1} diff --git a/src/ines.c b/src/ines.c index b14b248..41c4dcf 100644 --- a/src/ines.c +++ b/src/ines.c @@ -295,8 +295,8 @@ static void CheckHInfo(void) { }; int32 tofix = 0, x; uint64 partialmd5 = 0; - int current_mapper = 0; - int cur_mirr = 0; + int32 current_mapper = 0; + int32 cur_mirr = 0; for (x = 0; x < 8; x++) partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8); @@ -312,10 +312,10 @@ static void CheckHInfo(void) { VROM = NULL; tofix |= 8; } - if (MapperNo != (moo[x].mapper & 0xFF)) { + if (MapperNo != (moo[x].mapper & 0xFFF)) { tofix |= 1; current_mapper = MapperNo; - MapperNo = moo[x].mapper & 0xFF; + MapperNo = moo[x].mapper & 0xFFF; } } if (moo[x].mirror >= 0) { @@ -598,7 +598,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"", 202, Mapper202_Init}, {(uint8_t*)"", 203, Mapper203_Init}, {(uint8_t*)"", 204, Mapper204_Init}, - {(uint8_t*)"", 205, Mapper205_Init}, + {(uint8_t*)"BMC 15-in-1/3-in-1", 205, Mapper205_Init}, {(uint8_t*)"NAMCOT 108 Rev. C", 206, Mapper206_Init}, /* Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3 */ {(uint8_t*)"TAITO X1-005 Rev. B", 207, Mapper207_Init}, {(uint8_t*)"", 208, Mapper208_Init}, @@ -650,6 +650,13 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"", 254, Mapper254_Init}, {(uint8_t*)"", 255, Mapper255_Init}, /* Duplicate of M225? */ + {(uint8_t*)"BMC-HPxx", 260, BMCHPxx_Init}, + {(uint8_t*)"UNL-SHERO", 262, UNLSHeroes_Init}, + {(uint8_t*)"OK-411", 361, GN45_Init}, /* OK-411 is emulated together with GN-45 */ + {(uint8_t*)"HUMMER/JY-052", 281, Mapper281_Init}, + {(uint8_t*)"GN-45", 366, GN45_Init}, + {(uint8_t*)"DREAMTECH01", 521, DreamTech01_Init}, + {(uint8_t*)"", 0, NULL} }; diff --git a/src/ines.h b/src/ines.h index 75a801d..1d6dee7 100644 --- a/src/ines.h +++ b/src/ines.h @@ -229,4 +229,7 @@ void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); +void GN45_Init(CartInfo *info); /* m361, m366 */ +void Mapper281_Init(CartInfo *); + #endif diff --git a/src/unif.c b/src/unif.c index 3a4f352..8288a1e 100644 --- a/src/unif.c +++ b/src/unif.c @@ -467,10 +467,11 @@ static BMAPPING bmap[] = { { "60311C", BMC60311C_Init, 0 }, { "WS", BMCWS_Init, 0 }, { "HPxx", BMCHPxx_Init, 0 }, - + { "HP2018-A", BMCHPxx_Init, 0 }, { "CHINA_ER_SAN2", Mapper19_Init, 0 }, /* http://forums.nesdev.com/viewtopic.php?t=16465&p=216531 */ { "WAIXING-FW01", Mapper227_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 */ { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ + { "80013-B", BMC80013B_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, @@ -555,7 +556,7 @@ static int InitializeBoard(void) { } x++; } - FCEU_PrintError("Board type not supported."); + FCEU_PrintError("Board type not supported.", boardname); return(0); } @@ -617,7 +618,6 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { aborto: - FCEU_printf(" Failed to initialize board %s\n", boardname); FreeUNIF(); ResetUNIF(); return 0; diff --git a/src/unif.h b/src/unif.h index 8e58113..5bb8a52 100644 --- a/src/unif.h +++ b/src/unif.h @@ -157,6 +157,7 @@ void BMCF15_Init(CartInfo *info); void UNLRT01_Init(CartInfo *info); void BMC810131C_Init(CartInfo *info); void BMC8IN1_Init(CartInfo *info); +void BMC80013B_Init(CartInfo *info); /* additional boards */ void BMC60311C_Init(CartInfo *info); /* m289 */ From 650bc4579a69c743b2279e1060eef336205966bf Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 16 Jun 2019 16:39:52 +0800 Subject: [PATCH 23/74] Update ines-correct based on latest tests, update m36... - Update exiting game database based on latest changes and testing (reference nesdev for one) - Update mapper 36, supports F-15 City War (Spain) (Gluk Video) (Unl) - add Reset function to m177, fixes games freezing when reset is pressed (might not be a hardware behavior, but its annoying for emulators :D) --- src/boards/177.c | 6 ++++++ src/boards/36.c | 48 +++++++++++++++++++++++++++++++++--------- src/ines-correct.h | 52 ++++++++++++++++++++++++++++------------------ src/ines.c | 1 - 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/boards/177.c b/src/boards/177.c index bc87196..38828f8 100644 --- a/src/boards/177.c +++ b/src/boards/177.c @@ -59,6 +59,11 @@ static void M177Close(void) { WRAM = NULL; } +static void M177Reset(void) { + reg = 0; + Sync(); +} + static void StateRestore(int version) { Sync(); } @@ -66,6 +71,7 @@ static void StateRestore(int version) { void Mapper177_Init(CartInfo *info) { info->Power = M177Power; info->Close = M177Close; + info->Reset = M177Reset; GameStateRestore = StateRestore; WRAMSIZE = 8192; diff --git a/src/boards/36.c b/src/boards/36.c index 9ffed93..afc1c87 100644 --- a/src/boards/36.c +++ b/src/boards/36.c @@ -1,7 +1,8 @@ -/* FCE Ultra - NES/Famicom Emulator +/* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2019 Libretro 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 @@ -18,38 +19,65 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TXC/Micro Genius simplified mapper + * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 + * + * Known games: + * - Strike Wolf (Asia) (Unl) + * - Policeman (Gluk Video) (unl) + * - F-15 City War (Spain) (Gluk Video) (Unl) */ #include "mapinc.h" -static uint8 latche; +static uint8 regs[5]; static SFORMAT StateRegs[] = { - { &latche, 1, "LATC" }, + { regs, 5, "REGS" }, { 0 } }; static void Sync(void) { - setprg32(0x8000, latche >> 4); - setchr8(latche & 0xf); + setprg32(0x8000, regs[0] >> 4); + setchr8(regs[4] & 0x0F); } -static DECLFW(M36Write) { - latche = V; +static DECLFW(M36Write4100) { + switch(A & 0xE103) { + case 0x4100: + if(regs[3] & 0x10) + regs[0]++; + else + regs[0] = regs[2]; + break; + case 0x4101: + case 0x4102: + case 0x4103: + regs[A & 0x03] = V; + break; + } +} + +static DECLFW(M36Write4200) { + regs[4] = V; + Sync(); +} + +static DECLFW(M36WriteHi) { Sync(); } static DECLFR(M36Read) { - return latche; /* Need by Strike Wolf, being simplified mapper, this cart still uses some TCX mapper features andrely on it */ + return ((X.DB & 0xCF) | (regs[0] & 0x30)); } static void M36Power(void) { - latche = 0; Sync(); SetReadHandler(0x4100, 0x4100, M36Read); SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFE, M36Write); /* Actually, BUS conflict there preventing from triggering the wrong banks */ + SetWriteHandler(0x4100, 0x4103, M36Write4100); + SetWriteHandler(0x4200, 0x4200, M36Write4200); + SetWriteHandler(0x8000, 0xFFFF, M36WriteHi); } static void M36Restore(int version) { diff --git a/src/ines-correct.h b/src/ines-correct.h index fd6a6c0..e26aa65 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -49,7 +49,7 @@ {0x52ab2d17, 1, 8}, /* Toukyou Pachi-Slot Adventure (Japan) (Rev 0) */ {0x934db14a, 1, -1},/* All-Pro Basketball */ {0xf74dfc91, 1, -1},/* Win, Lose, or Draw */ - {0xe6a477b2, 2, 0}, /* 3-D WorldRunner (USA) */ + {0xe6a477b2, 2, 1}, /* 3-D WorldRunner (USA) */ {0x9ea1dc76, 2, 0}, /* Rainbow Islands */ {0x6d65cac6, 2, 0}, /* Terra Cresta */ {0xe1b260da, 2, 1}, /* Argos no Senshi */ @@ -79,7 +79,7 @@ {0xbc065fc3, 3, 1}, /* Pipe Dream */ {0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */ {0x97b6cb19, 4, -1},/* Aladdin (SuperGame) (Mapper 4) [!] */ - {0xd97c31b0, 4, 1}, /* Rasaaru Ishii no Childs Quest (J) */ + {0xd97c31b0, 206, 1}, /* Rasaaru Ishii no Childs Quest (J) */ {0x404b2e8b, 4, 2}, /* Rad Racer 2 */ {0x15141401, 4, 8}, /* Asmik Kun Land */ {0x4cccd878, 4, 8}, /* Cat Ninden Teyandee */ @@ -116,24 +116,36 @@ {0x5555fca3, 32, 8}, {0x283ad224, 32, 8}, /* Ai Sensei no Oshiete */ {0x243a8735, 32, 0x10|4}, /* Major League */ - {0xbc7b1d0f, 33, -1}, /* Bakushou!! Jinsei Gekijou 2 (J) [!] */ + {0x8a7d0abe, 33, 8}, /* Akira (J) [!] */ + {0x376138d8, 33, 8}, /* Akira (J) [a1] */ + {0xadf606f6, 33, 8}, /* Bakushou!! Jinsei Gekijou (J) [!] */ + {0xbc7b1d0f, 33, 8}, /* Bakushou!! Jinsei Gekijou 2 (J) [!] */ + {0x7a497ae3, 33, 8}, /* Don Doko Don (J) [!] */ + {0xbaca10a9, 33, 8}, /* Golf Ko Open (J) [!] */ + {0xf80bdc50, 33, 8}, /* Insector X (J) [!] */ + {0x2a6559a1, 33, 8}, /* Operation Wolf (J) [!] */ + {0xaeb7fce9, 33, 8}, /* Power Blazer (J) [!] */ + {0xd920f9df, 33, 8}, /* Takeshi no Sengoku Fuuunji (J) [!] */ + {0x3cd4b420, 33, 8}, /* Takeshi no Sengoku Fuuunji (Japan) (Beta) */ {0x4c7c1af3, 34, 1}, /* Caesar's Palace */ {0x932ff06e, 34, 1}, /* Classic Concentration */ {0xf46ef39a, 37, -1}, /* Super Mario Bros. + Tetris + Nintendo World Cup (E) [!] */ {0x7ccb12a3, 43, -1}, /* SMB2j */ {0x6c71feae, 45, -1}, /* Kunio 8-in-1 */ - {0xe2c94bc2, 48, -1}, /* Super Bros 8 (Unl) [!] */ - {0xaebd6549, 48, 8}, /* Bakushou!! Jinsei Gekijou 3 */ - {0x6cdc0cd9, 48, 8}, /* Bubble Bobble 2 */ - {0x99c395f9, 48, 8}, /* Captain Saver */ - {0xa7b0536c, 48, 8}, /* Don Doko Don 2 */ {0x40c0ad47, 48, 8}, /* Flintstones 2 */ - {0x1500e835, 48, 8}, /* Jetsons (J) */ + {0xaebd6549, 48, 8}, /* Bakushou!! Jinsei Gekijou 3 (J) [!] */ + {0x6cdc0cd9, 48, 8}, /* Bubble Bobble 2 (J) */ + {0x99c395f9, 48, 8}, /* Captain Saver (J) */ + {0xa7b0536c, 48, 8}, /* Don Doko Don 2 (J) [!] */ + {0xb17c828a, 48, 8}, /* Don Doko Don 2 (J) [a1] */ + {0x10e24006, 48, 8}, /* Flintstones, The - The Rescue of Dino & Hoppy (J) */ + {0x1500e835, 48, 8}, /* Jetsons, The - Cogswell's Caper! (J) */ + {0xe2c94bc2, 48, 8}, /* Super Bros 8 (Unl) [!] */ {0xa912b064, 51|0x800, 8}, /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */ {0x39ab0fc7, 64, 8}, /* Hard Drivin' (USA) (Proto) (Unl) */ {0xb19a55dd, 64, 8}, /* Road Runner */ {0xf92be3ec, 64, -1}, /* Rolling Thunder */ - {0xd114f544, 66, 1}, /* AV Super Real Pachinko (Japan) (Unl) */ + {0xd114f544, 66, 0}, /* AV Super Real Pachinko (Japan) (Unl) */ {0xe84274c5, 66, 1}, /* Mississippi Satsujin Jiken (J) [h2] */ {0xbde3ae9b, 66, 1}, /* Doraemon */ {0x9552e8df, 66, 1}, /* Dragon Ball */ @@ -142,7 +154,7 @@ {0xdd8ed0f7, 70, 1}, /* Kamen Rider Club */ {0xbba58be5, 70, -1}, /* Family Trainer - Manhattan Police */ {0x370ceb65, 70, -1}, /* Family Trainer - Meiro Dai Sakusen */ - {0x86be4746, 71, -1}, /* Dooly Bravo Land (Korea) (Unl) */ + {0x86be4746, 2, -1}, /* Dooly Bravo Land (Korea) (Unl) */ {0xe62e3382, 71, -1}, /* Mig-29 Soviet Fighter */ {0xac7b0742, 71, -1}, /* Golden KTV (Ch) [!], not actually 71, but UNROM without BUS conflict */ {0x054bd3e9, 74, -1}, /* Di 4 Ci - Ji Qi Ren Dai Zhan (As) */ @@ -159,7 +171,8 @@ {0xd2699893, 88, 0}, /* Dragon Spirit */ {0xbb7c5f7a, 89, 8}, /* Mito Koumon or something similar */ {0x10119e6b, 93, 8}, /* Fantasy Zone (Japan) */ - {0x0da5e32e, 101, -1}, /* Uruusey Yatsura */ + {0x2b750bf9, 101, 1}, /* Urusei Yatsura - Lum no Wedding Bell (Japan) (Beta) */ + {0x0da5e32e, 101, 1}, /* Urusei Yatsura - Lum no Wedding Bell (Japan) */ {0x6096f84e, 104, 1}, /* Pegasus 5-in-1 (Golden Five) (Unl) */ {0x3d3ff543, 113, 0}, /* Kazama Jun to Asama Yuuko no AV Dragon Mahjong (Japan) (Unl) */ {0x68379fdb, 113, 1}, /* Pipemania (Australia) (HES) (Unl) */ @@ -167,7 +180,6 @@ {0x0d98db53, 114, -1}, /* Pocahontas */ {0x4e7729ff, 114, -1}, /* Super Donkey Kong */ {0xc5e5c5b2, 115, -1}, /* Bao Qing Tian (As).nes */ -/* {0xa1dc16c0, 116, -1}, Street Heroes (Sachen) [b1] */ {0xe40dfb7e, 116, -1}, /* Somari (P conf.) */ {0xc9371ebb, 116, -1}, /* Somari (W conf.) */ {0x78b657ac, 118, -1}, /* Armadillo */ @@ -296,7 +308,7 @@ {0x2447e03b, 210, 1}, /* Top Striker */ {0x1dc0f740, 210, 1}, /* Wagyan Land 2 */ {0xd323b806, 210, 1}, /* Wagyan Land 3 */ - {0xbd523011, 210, 0}, /* Dream Master */ + {0xbd523011, 210, 0}, /* Namco Prism Zone - Dream Master (Japan) */ {0x5daae69a, 211, -1}, /* Aladdin - Return of Jaffar, The (Unl) [!] */ {0x1ec1dfeb, 217, -1}, /* 255-in-1 (Cut version) [p1] */ {0x046d70cc, 217, -1}, /* 500-in-1 (Anim Splash, Alt Mapper)[p1][!] */ @@ -305,15 +317,15 @@ {0x62ef6c79, 232, 8}, /* Quattro Sports -Aladdin */ {0x2705eaeb, 234, -1}, /* Maxi 15 */ {0x6f12afc5, 235, -1}, /* Golden Game 150-in-1 */ - {0xfb2b6b10, 241, -1}, /* Fan Kong Jing Ying (Ch) */ - {0xb5e83c9a, 241, -1}, /* Xing Ji Zheng Ba (Ch) */ {0x2537b3e6, 241, -1}, /* Dance Xtreme - Prima (Unl) */ {0x11611e89, 241, -1}, /* Darkseed (Unl) [p1] */ {0x81a37827, 241, -1}, /* Darkseed (Unl) [p1][b1] */ - {0xc2730c30, 241, -1}, /* Deadly Towers (U) [!] */ - {0xa21e675c, 241, -1}, /* Mashou (J) [!] */ + {0xfb2b6b10, 241, -1}, /* Fan Kong Jing Ying (Ch) */ + {0xb5e83c9a, 241, -1}, /* Xing Ji Zheng Ba (Ch) */ {0x368c19a8, 241, -1}, /* LIKO Study Cartridge 3-in-1 (Unl) [!] */ {0x54d98b79, 241, -1}, /* Titanic 1912 (Unl) */ + {0xc2730c30, 34, 0}, /* Deadly Towers (U) [!] */ + {0xa21e675c, 34, 0}, /* Mashou (J) [!] */ {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ @@ -324,7 +336,7 @@ {0xe001de16, 224, 0}, /* Pokemon Platinum Alt title 2 (KT-008 PCB)(Ch)[!] */ {0xbdbe3c96, 238, 1}, /* Contra Fighter (Unl) */ {0xcfe02ada, 1, -1}, /* Darkman (E) [!] */ - {0xcb53c523, 1, -1}, /* King Neptune's Adventure (Color Dreams) [!] */ + {0xcb53c523, 11, 1}, /* King Neptune's Adventure (Color Dreams) [!] */ {0x6e149729, 189, -1}, /* Master Fighter II (Unl) [a1] */ {0x60bfeb0c, 90, -1}, /* Mortal Kombat 2 (Unl) [!] */ {0x247cc73d, 150, -1}, /* Poker II (Sachen) [!] */ @@ -341,10 +353,10 @@ {0x071e4ee8, 114, 0}, /* m114,submapper 1 test rom */ {0xfe3e03a1, 197, -1}, /* Mortal Kombat III Special (YY-030) (Ch) [!] */ {0x9151d311, 197, -1}, /* Mortal Kombat III 28 Peoples (NT-328) (Ch) [!] */ - {0xf6bd8e31, 281, 0}, /* 1997 Super HIK 4-in-1 (JY-052) [p1][!] */ /* ines mappers that uses iNes 2.0 numbers */ + {0xf6bd8e31, 281, 0}, /* 1997 Super HIK 4-in-1 (JY-052) [p1][!] */ {0x5aa23a15, 361, 0}, /* 4-in-1 (OK-411)[p1][!] */ {0xf6b9d088, 366, 0}, /* 4-in-1 (K-3131GS, GN-45) [p1][!] */ {0x503566b2, 366, 0}, /* 4-in-1 (K-3131SS, GN-45) [p1][!] */ diff --git a/src/ines.c b/src/ines.c index 41c4dcf..8edac57 100644 --- a/src/ines.c +++ b/src/ines.c @@ -237,7 +237,6 @@ void CheckBad(uint64 md5partial) { } } - struct CHINF { uint32 crc32; int32 mapper; From b414ad217688ad2ec124ca3703cb0976c891d68f Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 18 Jun 2019 11:04:27 +0800 Subject: [PATCH 24/74] Add UNIF boards... - Add UNL-TH2131-1, UNL-LH51, BMC-RESETNROM-XIN1, BMC-RESET-TXROM - Add FARID_SLROM_8-IN-1, BMC-830425C-4391T, BMC-TJ-03, BMC-CTC-09 - Add BMC-K-3046, BMC-SA005-A, BMC-K-3006, BMC-K-3036, MINDKIDS - Add UNL-KS7021A, KS106C, BTL-900218 - Cleanup VRC2and4 (unify power function) --- src/boards/addrlatch.c | 33 +++++++++ src/boards/bcmk3006.c | 70 +++++++++++++++++++ src/boards/bmc830425C4391t.c | 101 +++++++++++++++++++++++++++ src/boards/bmcctc09.c | 74 ++++++++++++++++++++ src/boards/bmck3036.c | 75 ++++++++++++++++++++ src/boards/coolboy.c | 28 +++++++- src/boards/datalatch.c | 14 ++++ src/boards/lh51.c | 87 ++++++++++++++++++++++++ src/boards/mmc1.c | 51 +++++++++++++- src/boards/resetnromxin1.c | 86 +++++++++++++++++++++++ src/boards/resettxrom.c | 57 ++++++++++++++++ src/boards/vrc2and4.c | 128 +++++++++++++++++++++++++++++------ src/unif.c | 19 ++++++ src/unif.h | 19 +++++- 14 files changed, 816 insertions(+), 26 deletions(-) create mode 100644 src/boards/bcmk3006.c create mode 100644 src/boards/bmc830425C4391t.c create mode 100644 src/boards/bmcctc09.c create mode 100644 src/boards/bmck3036.c create mode 100644 src/boards/lh51.c create mode 100644 src/boards/resetnromxin1.c create mode 100644 src/boards/resettxrom.c diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 7bda0c1..ee18af9 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -541,3 +541,36 @@ static void BMCG146Sync(void) { void BMCG146_Init(CartInfo *info) { Latch_Init(info, BMCG146Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); } + +/*-------------- BMC-TJ-03 ------------------------*/ +/* NES 2.0 mapper 341 is used for a simple 4-in-1 multicart */ + +static void BMCTJ03Sync(void) { + uint8 mirr = ((latche >> 1) & 1) ^ 1; + uint8 bank = (latche >> 8) & 7; + + setprg32(0x8000, bank); + setchr8(bank); + + if (bank == 3) mirr ^= 1; /* Twin Bee has incorrect mirroring */ + SetupCartMirroring(mirr, 1, NULL); +} + +void BMCTJ03_Init(CartInfo *info) { + Latch_Init(info, BMCTJ03Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +/*-------------- BMC-SA005-A ------------------------*/ +/* NES 2.0 mapper 338 is used for a 16-in-1 and a 200/300/600/1000-in-1 multicart. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_338 */ + +static void BMCSA005ASync(void) { + setprg16(0x8000, latche & 0x0F); + setprg16(0xC000, latche & 0x0F); + setchr8(latche & 0x0F); + SetupCartMirroring((latche >> 3) & 1, 1, NULL); +} + +void BMCSA005A_Init(CartInfo *info) { + Latch_Init(info, BMCSA005ASync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} diff --git a/src/boards/bcmk3006.c b/src/boards/bcmk3006.c new file mode 100644 index 0000000..ab3e539 --- /dev/null +++ b/src/boards/bcmk3006.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 mapper 339 is used for a 21-in-1 multicart. + * Its UNIF board name is BMC-K-3006. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_339 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCK3006CW(uint32 A, uint8 V) { + setchr1(A, (V & 0x7F) | (EXPREGS[0] & 0x18) << 4); +} + +static void BMCK3006PW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x20) { /* MMC3 mode */ + setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0x18) << 1); + } else { + if ((EXPREGS[0] & 0x07) == 0x06) { /* NROM-256 */ + setprg32(0x8000, (EXPREGS[0] >> 1) & 0x0F); + } else { /* NROM-128 */ + setprg16(0x8000, EXPREGS[0] & 0x1F); + setprg16(0xC000, EXPREGS[0] & 0x1F); + } + } +} + +static DECLFW(BMCK3006Write) { + EXPREGS[0] = A & 0x3F; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCK3006Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMCK3006Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCK3006Write); +} + +void BMCK3006_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 512, 8, 0); + pwrap = BMCK3006PW; + cwrap = BMCK3006CW; + info->Power = BMCK3006Power; + info->Reset = BMCK3006Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/bmc830425C4391t.c b/src/boards/bmc830425C4391t.c new file mode 100644 index 0000000..db18618 --- /dev/null +++ b/src/boards/bmc830425C4391t.c @@ -0,0 +1,101 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 320 is used for the Super HiK 6-in-1 A-030 multicart. + * Basically UxROM with an address-latch-based outer bank register. + * UNIF board name is BMC-830425C-4391T. Mirroring is hard-wired. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_320 + */ + +#include "mapinc.h" + +static uint8 regs[2]; +static uint8 isMermaid = 0; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { &isMermaid, 1, "MERM" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank_size = (regs[0] & 0x80) ? 0x07: 0x0F; + uint8 outer_bank = !isMermaid ? (regs[0] & 0x78) : 0x04; + uint8 inner_bank = regs[1]; + uint8 game_block = regs[0] & 0x78; + + /* TODO: Hacky and forced mapping of outer banks(game block)... */ + if (!isMermaid) { + switch(game_block) { + case 0x00: /* botb outerbank=0 */ + case 0x10: /* rocketeer outerbank=1 */ + case 0x20: /* contra outerbank=2 */ + case 0x28: /* ducktales outerbank=3 */ + case 0x38: /* school fight outerbank=5 */ + outer_bank = (game_block >> 4) + ((game_block & 0x08) ? 0x01 : 0x00); + outer_bank |= (game_block >> 3) & 1; + break; + case 0x30: + /* Mermaid game block is tricky (to me at least). Aim here is + * when this register is selected, ignore any other outer bank reg changes */ + isMermaid = 1; + outer_bank = 0x04; + break; + } + } + + setprg16r(outer_bank, 0x8000, (inner_bank & bank_size)); + setprg16r(outer_bank, 0xC000, bank_size); + setchr8(0); +} + +static DECLFW(M320Write) { + if ((A & 0xF0E0) == 0xF0E0) { + regs[0] = (A & 0x1F) << 3; + } + regs[1] = V & 0x0F; + Sync(); +} + +static void M320Power(void) { + regs[0] = regs[1] = 0; + isMermaid = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M320Write); +} + +static void M320Reset(void) { + regs[0] = regs[1] = 0; + isMermaid = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMC830425C4391T_Init(CartInfo *info) { + info->Power = M320Power; + info->Reset = M320Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bmcctc09.c b/src/boards/bmcctc09.c new file mode 100644 index 0000000..185576c --- /dev/null +++ b/src/boards/bmcctc09.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 mapper 335 is used for a 10-in-1 multicart. + * Its UNIF board name is BMC-CTC-09. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_335 */ + +#include "mapinc.h" + +#define PRG 0 +#define CHR 1 + +static uint8 regs[2]; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (regs[PRG] & 0x10) { + setprg16(0x8000, ((regs[PRG] & 0x07) << 1) | ((regs[PRG] >> 3) & 1)); + setprg16(0xC000, ((regs[PRG] & 0x07) << 1) | ((regs[PRG] >> 3) & 1)); + } else + setprg32(0x8000, regs[PRG] & 0x07); + + setchr8(regs[CHR] & 0x0F); + SetupCartMirroring(((regs[PRG] >> 5) & 1) ^ 1, 1, NULL); +} + +static DECLFW(WritePRG) { + regs[PRG] = V; + Sync(); +} + +static DECLFW(WriteCHR) { + regs[CHR] = V; + Sync(); +} + +static void BMCCTC09Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, WriteCHR); + SetWriteHandler(0xC000, 0xFFFF, WritePRG); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCCTC09_Init(CartInfo *info) { + info->Power = BMCCTC09Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c new file mode 100644 index 0000000..2e716e0 --- /dev/null +++ b/src/boards/bmck3036.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 mapper 340 is used for a 35-in-1 multicart. + * Its UNIF board name is BMC-K-3036. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_340 + * TODO: Some games are not working... + */ + +#include "mapinc.h" + +static uint8 regs[2]; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (regs[0] & 0x20) { /* NROM-128 */ + setprg16(0x8000, regs[0] & 0x1F); + setprg16(0xC000, regs[0] & 0x1F); + } else { /* UNROM */ + setprg16(0x8000, regs[0] & 0x1F | regs[1] & 0x07); + setprg16(0xC000, regs[0] & 0x1F | 0x07); + } + setchr8(0); + SetupCartMirroring(((regs[0] & 0x25) == 0x25 ? MI_H : MI_V), 1, NULL); +} + +static DECLFW(M340Write) { + regs[0] = A & 0xFF; + regs[1] = V & 0xFF; + Sync(); +} + +static void BMCK3036Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M340Write); +} + +static void BMCK3036Reset(void) { + regs[0] = regs[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCK3036_Init(CartInfo *info) { + info->Power = BMCK3036Power; + info->Reset = BMCK3036Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/coolboy.c b/src/boards/coolboy.c index b0f8649..5482550 100644 --- a/src/boards/coolboy.c +++ b/src/boards/coolboy.c @@ -42,7 +42,7 @@ static void COOLBOYCW(uint32 A, uint8 V) { } } /* Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise */ - setchr1(A, + setchr1(A, (V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) /* 7th bit */ | ((EXPREGS[2] & 0x0F) << 3) /* 6-3 bits */ | ((A >> 10) & 7) /* 2-0 bits */ @@ -107,7 +107,7 @@ static DECLFW(COOLBOYWrite) { CartBW(A,V); /* Deny any further writes when 7th bit is 1 AND 4th is 0 */ - if ((EXPREGS[3] & 0x90) != 0x80) { + if ((EXPREGS[3] & 0x90) != 0x80) { EXPREGS[A & 3] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); @@ -150,3 +150,27 @@ void COOLBOY_Init(CartInfo *info) { info->Reset = COOLBOYReset; AddExState(EXPREGS, 4, 0, "EXPR"); } + +/*------------------ MINDKIDS ---------------------------*/ +/* A COOLBOY variant that works identically but puts the outer bank registers + * in the $5xxx range instead of the $6xxx range. + * The UNIF board name is MINDKIDS (submapper 1). + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_268 + */ + +static void MINDKIDSPower(void) { + GenMMC3Power(); + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite); +} + +void MINDKIDS_Init(CartInfo *info) { + GenMMC3_Init(info, 2048, 256, 8, info->battery); + pwrap = COOLBOYPW; + cwrap = COOLBOYCW; + info->Power = MINDKIDSPower; + info->Reset = COOLBOYReset; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 4a563f3..1846bb7 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -527,3 +527,17 @@ static void BMC11160Sync(void) { void BMC11160_Init(CartInfo *info) { Latch_Init(info, BMC11160Sync, 0, 0x8000, 0xFFFF, 0, 0); } + +/*------------------ BMC-K-3046 ---------------------------*/ +/* NES 2.0 mapper 336 is used for an 11-in-1 multicart + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_336 */ + +static void BMCK3046Sync(void) { + setprg16(0x8000, latche); + setprg16(0xC000, latche | 0x07); + setchr8(0); +} + +void BMCK3046_Init(CartInfo *info) { + Latch_Init(info, BMCK3046Sync, 0, 0x8000, 0xFFFF, 0, 0); +} diff --git a/src/boards/lh51.c b/src/boards/lh51.c new file mode 100644 index 0000000..3236485 --- /dev/null +++ b/src/boards/lh51.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FDS Conversion + * NES 2.0 Mapper 309 is used for Whirlwind Manu's ROM cartridge conversion + * of game 愛戦士ニコル (Ai Senshi Nicol, cartridge code LH51). + * Its UNIF board name is UNL-LH51. + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_309 + */ + +#include "mapinc.h" + +static uint8 reg, mirr; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, reg & 0x0F); + setprg8(0xA000, 13); + setprg8(0xC000, 14); + setprg8(0xE000, 15); + setmirror(((mirr >> 3) & 1) ^ 1); +} + +static DECLFW(LH51Write) { + switch (A & 0xF000) { + case 0x8000: reg = V; Sync(); break; + case 0xF000: mirr = V; Sync(); break; + } +} + +static void LH51Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, LH51Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void LH51Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void LH51_Init(CartInfo *info) { + info->Power = LH51Power; + info->Close = LH51Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index 5a4d343..4dc4f69 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -36,13 +36,17 @@ static uint8 *WRAM = NULL; static uint8 *CHRRAM = NULL; static int is155, is171; +static uint8 MMC1WRAMEnabled(void) { + return !(DRegs[3] & 0x10); +} + static DECLFW(MBWRAM) { - if (!(DRegs[3] & 0x10) || is155) + if (MMC1WRAMEnabled() || is155) Page[A >> 11][A] = V; /* WRAM is enabled. */ } static DECLFR(MAWRAM) { - if ((DRegs[3] & 0x10) && !is155) + if (!MMC1WRAMEnabled() && !is155) return X.DB; /* WRAM is disabled */ return(Page[A >> 11][A]); } @@ -395,4 +399,47 @@ void SOROM_Init(CartInfo *info) { GenMMC1Init(info, 256, 0, 16, info->battery); } +/* ----------------------- FARID_SLROM_8-IN-1 -----------------------*/ +/* NES 2.0 Mapper 323 - UNIF FARID_SLROM_8-IN-1 */ + +static uint8 reg, lock; + +static void FARIDSLROM8IN1PRGHook(uint32 A, uint8 V) { + setprg16(A, (V & 0x07) | (reg << 3)); +} + +static void FARIDSLROM8IN1CHRHook(uint32 A, uint8 V) { + setchr4(A, (V & 0x1F) | (reg << 5)); +} + +static DECLFW(FARIDSLROM8IN1Write) { + if (MMC1WRAMEnabled() && !lock) { + lock = (V & 0x08) >> 3; + reg = (V & 0xF0) >> 4; + MMC1MIRROR(); + MMC1CHR(); + MMC1PRG(); + } +} + +static void FARIDSLROM8IN1Power(void) { + reg = lock = 0; + GenMMC1Power(); + SetWriteHandler(0x6000, 0x7FFF, FARIDSLROM8IN1Write); +} + +static void FARIDSLROM8IN1Reset(void) { + reg = lock = 0; + MMC1CMReset(); +} + +void FARIDSLROM8IN1_Init(CartInfo *info) { + GenMMC1Init(info, 1024, 256, 8, 0); + MMC1CHRHook4 = FARIDSLROM8IN1CHRHook; + MMC1PRGHook16 = FARIDSLROM8IN1PRGHook; + info->Power = FARIDSLROM8IN1Power; + info->Reset = FARIDSLROM8IN1Reset; + AddExState(lock, 1, 0, "LOCK"); + AddExState(reg, 1, 0, "REG6"); +} diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c new file mode 100644 index 0000000..c97837d --- /dev/null +++ b/src/boards/resetnromxin1.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* BMC-RESETNROM-XIN1 + * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) + * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee + * + * BMC-KS106C + * - Kaiser 4-in-1(Unl,KS106C)[p1] - B-Wings, Kung Fu, 1942, SMB1 (wrong mirroring) + */ + +#include "mapinc.h" + +static uint8 gameblock, limit; + +static SFORMAT StateRegs[] = +{ + { &gameblock, 1, "GAME" }, + { 0 } +}; + +static void Sync(void) { + setchr8r(gameblock, 0); + setprg32r(gameblock, 0x8000, 0); +} + +static void BMCRESETNROMXIN1Power(void) { + gameblock = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void BMCRESETNROMXIN1Reset(void) { + gameblock++; + gameblock &= limit; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCRESETNROMXIN1_Init(CartInfo *info) { + uint8 x; + uint64 partialmd5; + + for (x = 0; x < 8; x++) + partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); + + /* Mirroring override - these boards have incorrect mirroring for some reasons in their headers */ + if (partialmd5 == 0x616851e56946893bLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ + SetupCartMirroring(1, 1, NULL); + else if (partialmd5 == 0x4cd729b5ae23a3cfLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ + SetupCartMirroring(0, 1, NULL); + + limit = 0x01; + info->Power = BMCRESETNROMXIN1Power; + info->Reset = BMCRESETNROMXIN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void BMCKS106C_Init(CartInfo *info) { + limit = 0x03; + info->Power = BMCRESETNROMXIN1Power; + info->Reset = BMCRESETNROMXIN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c new file mode 100644 index 0000000..fdf1d1b --- /dev/null +++ b/src/boards/resettxrom.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 313 is used for MMC3-based multicarts that switch + * between 128 KiB PRG-ROM/128 KiB CHR-ROM-sized games on each reset and + * thus require no additional registers. + * Its UNIF board name is BMC-RESET-TXROM. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M313CW(uint32 A, uint8 V) { + setchr1r(EXPREGS[0], A, V & 0x7F); +} + +static void M313PW(uint32 A, uint8 V) { + setprg8r(EXPREGS[0], A, V & 0x0F); +} + +static void M313Reset(void) { + EXPREGS[0]++; + EXPREGS[0] &= 0x03; + MMC3RegReset(); +} + +static void M313Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); +} + +/* NES 2.0 313, UNIF BMC-RESET-TXROM */ +void BMCRESETTXROM_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 0, 0); + cwrap = M313CW; + pwrap = M313PW; + info->Power = M313Power; + info->Reset = M313Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c index 7ff7ce7..b26d804 100644 --- a/src/boards/vrc2and4.c +++ b/src/boards/vrc2and4.c @@ -158,14 +158,20 @@ static DECLFW(M23Write) { VRC24Write(A, V); } -static void M21Power(void) { +static void VRC24PowerCommon(void (*WRITEFUNC)(uint32 A, uint8 V)) { Sync(); - setprg8r(0x10, 0x6000, 0); + setprg8r(0x10, 0x6000, 0); /* Only two Goemon games are have battery backed RAM, three more shooters + * (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only + */ SetReadHandler(0x6000, 0x7FFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M21Write); + SetWriteHandler(0x8000, 0xFFFF, WRITEFUNC); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M21Power(void) { + VRC24PowerCommon(M21Write); } static void M22Power(void) { @@ -176,26 +182,12 @@ static void M22Power(void) { static void M23Power(void) { big_bank = 0x20; - Sync(); - setprg8r(0x10, 0x6000, 0); /* Only two Goemon games are have battery backed RAM, three more shooters - * (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only - */ - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M23Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + VRC24PowerCommon(M23Write); } static void M25Power(void) { big_bank = 0x20; - Sync(); - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M22Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + VRC24PowerCommon(M22Write); } void FP_FASTAPASS(1) VRC24IRQHook(int a) { @@ -279,3 +271,99 @@ void UNLT230_Init(CartInfo *info) { info->Power = M23Power; VRC24_Init(info); } + +/* -------------------- UNL-TH2131-1 -------------------- */ +/* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_308 + * NES 2.0 Mapper 308 is used for a bootleg version of the Sunsoft game Batman + * similar to Mapper 23 Submapper 3) with custom IRQ functionality. + * UNIF board name is UNL-TH2131-1. + */ + +static DECLFW(TH2131Write) { + switch (A & 0xF003) { + case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; + case 0xF001: IRQa = 1; break; + case 0xF003: IRQLatch = (V & 0xF0) >> 4; break; + } +} + +void FP_FASTAPASS(1) TH2131IRQHook(int a) { + int count; + + if (!IRQa) + return; + + for (count = 0; count < a; count++) { + IRQCount++; + if ((IRQCount & 0x0FFF) == 2048) + IRQLatch--; + if (!IRQLatch && (IRQCount & 0x0FFF) < 2048) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void TH2131Power(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xF000, 0xFFFF, TH2131Write); +} + +void UNLTH21311_Init(CartInfo *info) { + info->Power = TH2131Power; + VRC24_Init(info); + MapIRQHook = TH2131IRQHook; +} + +/* -------------------- UNL-KS7021A -------------------- */ +/* http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_525 + * NES 2.0 Mapper 525 is used for a bootleg version of versions of Contra and 月風魔伝 (Getsu Fūma Den). + * Its similar to Mapper 23 Submapper 3) with non-nibblized CHR-ROM bank registers. + */ + +static DECLFW(KS7021AWrite) { + switch (A & 0xB000) { + case 0xB000: chrreg[A & 0x07] = V; Sync(); break; + } +} + +static void KS7021APower(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xB000, 0xBFFF, KS7021AWrite); +} + +void UNLKS7021A_Init(CartInfo *info) { + info->Power = KS7021APower; + VRC24_Init(info); +} + +/* -------------------- BTL-900218 -------------------- */ +/* http://wiki.nesdev.com/w/index.php/UNIF/900218 + * NES 2.0 Mapper 524 describes the PCB used for the pirate port Lord of King or Axe of Fight. + * UNIF board name is BTL-900218. + */ + +static DECLFW(BTL900218Write) { + switch (A & 0xF00C) { + case 0xF008: IRQa = 1; break; + case 0xF00C: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; + } +} + +void FP_FASTAPASS(1) BTL900218IRQHook(int a) { + if (!IRQa) + return; + + IRQCount += a; + if (IRQCount & 1024) + X6502_IRQBegin(FCEU_IQEXT); +} + +static void BTL900218Power(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xF000, 0xFFFF, BTL900218Write); +} + +void BTL900218_Init(CartInfo *info) { + info->Power = BTL900218Power; + VRC24_Init(info); + MapIRQHook = BTL900218IRQHook; +} diff --git a/src/unif.c b/src/unif.c index 8288a1e..2ff053e 100644 --- a/src/unif.c +++ b/src/unif.c @@ -473,6 +473,25 @@ static BMAPPING bmap[] = { { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ { "80013-B", BMC80013B_Init, 0 }, + { "TH2131-1", UNLTH21311_Init, 0 }, + { "LH51", LH51_Init, 0 }, + { "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 }, + { " BMC-RESET-TXROM", BMCRESETTXROM_Init, 0 }, + { "RESET-TXROM", BMCRESETTXROM_Init, 0 }, + { "K-3088", BMC411120C_Init, 0 }, + { "FARID_SLROM_8-IN-1", FARIDSLROM8IN1_Init, 0 }, + { "830425C-4391T", BMC830425C4391T_Init, 0 }, + { "TJ-03", BMCTJ03_Init, 0 }, + { "CTC-09", BMCCTC09_Init, 0 }, + { "K-3046", BMCK3046_Init, 0 }, + { "SA005-A", BMCSA005A_Init, 0 }, + { "K-3006", BMCK3006_Init, 0 }, + { "K-3036", BMCK3036_Init, 0 }, + { "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR }, + { "KS7021A", UNLKS7021A_Init, 0 }, + { "KS106C", BMCKS106C_Init, 0 }, + { "900218", BTL900218_Init, 0 }, + #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, { "COPYFAMI", MapperCopyFami_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 5bb8a52..93b3df8 100644 --- a/src/unif.h +++ b/src/unif.h @@ -158,13 +158,28 @@ void UNLRT01_Init(CartInfo *info); void BMC810131C_Init(CartInfo *info); void BMC8IN1_Init(CartInfo *info); void BMC80013B_Init(CartInfo *info); - -/* additional boards */ void BMC60311C_Init(CartInfo *info); /* m289 */ void BMCWS_Init(CartInfo *info); /* m332 */ void UNLKS202_Init(CartInfo *info); /* m056 */ void BMCHPxx_Init(CartInfo *info); /* m260 */ +void BMCRESETNROMXIN1_Init(CartInfo *info); +void BMCKS106C_Init(CartInfo *info); +void UNLTH21311_Init(CartInfo *info); /* m308 */ +void LH51_Init(CartInfo *info); /* m309 */ +void BMCRESETTXROM_Init(CartInfo *info); /* m313 */ +void FARIDSLROM8IN1_Init(CartInfo *info); /* m323 */ +void BMC830425C4391T_Init(CartInfo *info); /* m320 */ +void BMCTJ03_Init(CartInfo *info); /* m341 */ +void BMCCTC09_Init(CartInfo *info); /* m335 */ +void BMCK3046_Init(CartInfo *info); /* m336 */ +void BMCSA005A_Init(CartInfo *info); /* m338 */ +void BMCK3006_Init(CartInfo *info); /* m339 */ +void BMCK3036_Init(CartInfo *info); /* m340 */ +void MINDKIDS_Init(CartInfo *info); /* m268 */ +void UNLKS7021A_Init(CartInfo *info); /* m525 */ +void BTL900218_Init(CartInfo *info); /* m524 */ + #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); void MapperCopyFami_Init(CartInfo *info); From dae081ba6df9a028826f7445e1670a14afe4f418 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 21 Jun 2019 11:21:46 +0200 Subject: [PATCH 25/74] Implement new environment callback RETRO_ENVIRONMENT_GET_INPUT_BITMASKS --- .../libretro-common/include/libretro.h | 93 +++++++++++++++++-- src/drivers/libretro/libretro.c | 59 +++++++++--- 2 files changed, 131 insertions(+), 21 deletions(-) diff --git a/src/drivers/libretro/libretro-common/include/libretro.h b/src/drivers/libretro/libretro-common/include/libretro.h index 4e1a978..8daec83 100644 --- a/src/drivers/libretro/libretro-common/include/libretro.h +++ b/src/drivers/libretro/libretro-common/include/libretro.h @@ -202,6 +202,8 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_L3 14 #define RETRO_DEVICE_ID_JOYPAD_R3 15 +#define RETRO_DEVICE_ID_JOYPAD_MASK 256 + /* Index / Id values for ANALOG device. */ #define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 #define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 @@ -248,6 +250,7 @@ extern "C" { #define RETRO_DEVICE_ID_POINTER_X 0 #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 +#define RETRO_DEVICE_ID_POINTER_COUNT 3 /* Returned from retro_get_region(). */ #define RETRO_REGION_NTSC 0 @@ -274,6 +277,7 @@ enum retro_language RETRO_LANGUAGE_VIETNAMESE = 15, RETRO_LANGUAGE_ARABIC = 16, RETRO_LANGUAGE_GREEK = 17, + RETRO_LANGUAGE_TURKISH = 18, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -485,11 +489,13 @@ enum retro_mod /* Environment commands. */ #define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- * Sets screen rotation of graphics. - * Is only implemented if rotation can be accelerated by hardware. * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, * 270 degrees counter-clockwise respectively. */ #define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- + * NOTE: As of 2019 this callback is considered deprecated in favor of + * using core options to manage overscan in a more nuanced, core-specific way. + * * Boolean value whether or not the implementation should use overscan, * or crop away overscan. */ @@ -875,12 +881,12 @@ enum retro_mod * types already defined in the libretro API. * * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the + * is terminated with a blanked out struct. Each element of the * retro_controller_info struct corresponds to the ascending port index * that is passed to retro_set_controller_port_device() when that function * is called to indicate to the core that the frontend has changed the * active device subclass. SEE ALSO: retro_set_controller_port_device() - * + * * The ascending input port indexes provided by the core in the struct * are generally presented by frontends as ascending User # or Player #, * such as Player 1, Player 2, Player 3, etc. Which device subclasses are @@ -892,7 +898,7 @@ enum retro_mod * User or Player, beginning with the generic Libretro device that the * subclasses are derived from. The second inner element of each entry is the * total number of subclasses that are listed in the retro_controller_description. - * + * * NOTE: Even if special device types are set in the libretro core, * libretro should only poll input based on the base input device types. */ @@ -1079,10 +1085,31 @@ enum retro_mod * fastforwarding mode. */ +#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* float * -- + * Float value that lets us know what target refresh rate + * is curently in use by the frontend. + * + * The core can use the returned value to set an ideal + * refresh rate/framerate. + */ + +#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend supports + * input bitmasks being returned by retro_input_state_t. The advantage + * of this is that retro_input_state_t has to be only called once to + * grab all button states instead of multiple times. + * + * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id' + * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD). + * It will return a bitmask of all the digital buttons. + */ + /* VFS functionality */ /* File paths: - * File paths passed as parameters when using this api shall be well formed unix-style, + * File paths passed as parameters when using this API shall be well formed UNIX-style, * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator. * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead). * Other than the directory separator, cores shall not make assumptions about path format: @@ -1100,6 +1127,10 @@ enum retro_mod * Introduced in VFS API v1 */ struct retro_vfs_file_handle; +/* Opaque directory handle + * Introduced in VFS API v3 */ +struct retro_vfs_dir_handle; + /* File open flags * Introduced in VFS API v1 */ #define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ @@ -1119,6 +1150,12 @@ struct retro_vfs_file_handle; #define RETRO_VFS_SEEK_POSITION_CURRENT 1 #define RETRO_VFS_SEEK_POSITION_END 2 +/* stat() result flags + * Introduced in VFS API v3 */ +#define RETRO_VFS_STAT_IS_VALID (1 << 0) +#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1) +#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2) + /* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle * Introduced in VFS API v1 */ typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); @@ -1128,7 +1165,7 @@ typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file * Introduced in VFS API v1 */ typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); -/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on succes, -1 on failure. +/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure. * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. * Introduced in VFS API v1 */ typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); @@ -1141,7 +1178,7 @@ typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle * Introduced in VFS API v2 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); -/* Get the current read / write position for the file. Returns - 1 for error. +/* Get the current read / write position for the file. Returns -1 for error. * Introduced in VFS API v1 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); @@ -1169,6 +1206,39 @@ typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); * Introduced in VFS API v1 */ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); +/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid. + * Additionally stores file size in given variable, unless NULL is given. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size); + +/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir); + +/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error. + * Support for the include_hidden argument may vary depending on the platform. + * Introduced in VFS API v3 */ +typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden); + +/* Read the directory entry at the current position, and move the read pointer to the next position. + * Returns true on success, false if already on the last entry. + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Get the name of the last entry read. Returns a string on success, or NULL for error. + * The returned string pointer is valid until the next call to readdir or closedir. + * Introduced in VFS API v3 */ +typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream); + +/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error). + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure. + * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream); + struct retro_vfs_interface { /* VFS API v1 */ @@ -1185,6 +1255,14 @@ struct retro_vfs_interface retro_vfs_rename_t rename; /* VFS API v2 */ retro_vfs_truncate_t truncate; + /* VFS API v3 */ + retro_vfs_stat_t stat; + retro_vfs_mkdir_t mkdir; + retro_vfs_opendir_t opendir; + retro_vfs_readdir_t readdir; + retro_vfs_dirent_get_name_t dirent_get_name; + retro_vfs_dirent_is_dir_t dirent_is_dir; + retro_vfs_closedir_t closedir; }; struct retro_vfs_interface_info @@ -1207,6 +1285,7 @@ enum retro_hw_render_interface_type RETRO_HW_RENDER_INTERFACE_D3D10 = 2, RETRO_HW_RENDER_INTERFACE_D3D11 = 3, RETRO_HW_RENDER_INTERFACE_D3D12 = 4, + RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5, RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX }; diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 8e324a6..077790d 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -564,6 +564,8 @@ struct st_palettes palettes[] = { } }; +static bool libretro_supports_bitmasks = false; + unsigned retro_api_version(void) { return RETRO_API_VERSION; @@ -907,6 +909,9 @@ void retro_init(void) if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) log_cb.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); #endif + + if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) + libretro_supports_bitmasks = true; } static void retro_set_custom_palette(void) @@ -1020,7 +1025,7 @@ void retro_deinit (void) #if defined(RENDER_GSKIT_PS2) ps2 = NULL; #endif - + libretro_supports_bitmasks = false; } void retro_reset(void) @@ -1034,16 +1039,6 @@ typedef struct unsigned nes; } keymap; -static const keymap bindmap[] = { - { RETRO_DEVICE_ID_JOYPAD_A, JOY_A }, - { RETRO_DEVICE_ID_JOYPAD_B, JOY_B }, - { RETRO_DEVICE_ID_JOYPAD_SELECT, JOY_SELECT }, - { RETRO_DEVICE_ID_JOYPAD_START, JOY_START }, - { RETRO_DEVICE_ID_JOYPAD_UP, JOY_UP }, - { RETRO_DEVICE_ID_JOYPAD_DOWN, JOY_DOWN }, - { RETRO_DEVICE_ID_JOYPAD_LEFT, JOY_LEFT }, - { RETRO_DEVICE_ID_JOYPAD_RIGHT, JOY_RIGHT }, -}; static const keymap turbomap[] = { { RETRO_DEVICE_ID_JOYPAD_X, JOY_A }, @@ -1491,9 +1486,45 @@ static void FCEUD_UpdateInput(void) if (player_enabled) { - for (i = 0; i < MAX_BUTTONS; i++) - input_buf |= input_cb(player, RETRO_DEVICE_JOYPAD, 0, - bindmap[i].retro) ? bindmap[i].nes : 0; + int16_t ret; + + if (libretro_supports_bitmasks) + { + ret = input_cb(player, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); + + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_A)) + input_buf |= JOY_A; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_B)) + input_buf |= JOY_B; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_SELECT)) + input_buf |= JOY_SELECT; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_START)) + input_buf |= JOY_START; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_UP)) + input_buf |= JOY_UP; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN)) + input_buf |= JOY_DOWN; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT)) + input_buf |= JOY_LEFT; + if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT)) + input_buf |= JOY_RIGHT; + } + else + { + static const keymap bindmap[] = { + { RETRO_DEVICE_ID_JOYPAD_A, JOY_A }, + { RETRO_DEVICE_ID_JOYPAD_B, JOY_B }, + { RETRO_DEVICE_ID_JOYPAD_SELECT, JOY_SELECT }, + { RETRO_DEVICE_ID_JOYPAD_START, JOY_START }, + { RETRO_DEVICE_ID_JOYPAD_UP, JOY_UP }, + { RETRO_DEVICE_ID_JOYPAD_DOWN, JOY_DOWN }, + { RETRO_DEVICE_ID_JOYPAD_LEFT, JOY_LEFT }, + { RETRO_DEVICE_ID_JOYPAD_RIGHT, JOY_RIGHT }, + }; + for (i = 0; i < MAX_BUTTONS; i++) + input_buf |= input_cb(player, RETRO_DEVICE_JOYPAD, 0, + bindmap[i].retro) ? bindmap[i].nes : 0; + } /* Turbo A and Turbo B buttons are * mapped to Joypad X and Joypad Y From 706ee282943209c6e818f122c30c132a3803df06 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 23 Jun 2019 20:04:11 +0800 Subject: [PATCH 26/74] UNIF: Allow mirroring override (removes hard mirroring in vertical/horizontal modes) - A few multi-cart UNIF carts are incorrectly using vertical/horizontal mirroring but the mapper used has mapper-controlled mirroring which does not work when using previous hard-mirroring. - This PR allows overriding the initial mirroring set (vertical/horizontal) when cart requests a mirroring change for multi-cart games. --- src/unif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/unif.c b/src/unif.c index 2ff053e..c969909 100644 --- a/src/unif.c +++ b/src/unif.c @@ -113,7 +113,8 @@ static uint8 exntar[2048]; static void MooMirroring(void) { if (mirrortodo < 0x4) - SetupCartMirroring(mirrortodo, 1, 0); + /* 06-22-19 Allow override when using vertical/horizontal mirroring. */ + SetupCartMirroring(mirrortodo, (mirrortodo >> 1) & 1, 0); else if (mirrortodo == 0x4) { SetupCartMirroring(4, 1, exntar); AddExState(exntar, 2048, 0, "EXNR"); From 130580d70eb55d69ad28899f4ee3ebda9cb8e4dc Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 23 Jun 2019 20:15:32 +0800 Subject: [PATCH 27/74] BMC-830425C-4391T: Update cpu banking - Fixes loading Mermaid game. --- src/boards/bmc830425C4391t.c | 52 +++++++++++------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src/boards/bmc830425C4391t.c b/src/boards/bmc830425C4391t.c index db18618..ce64fd2 100644 --- a/src/boards/bmc830425C4391t.c +++ b/src/boards/bmc830425C4391t.c @@ -26,66 +26,46 @@ #include "mapinc.h" -static uint8 regs[2]; -static uint8 isMermaid = 0; +static uint8 bank_size; +static uint8 inner_bank; +static uint8 outer_bank; static SFORMAT StateRegs[] = { - { regs, 2, "REGS" }, - { &isMermaid, 1, "MERM" }, + { &inner_bank, 1, "INNB" }, + { &outer_bank, 1, "OUTB" }, + { &bank_size, 1, "SIZE" }, { 0 } }; static void Sync(void) { - uint8 bank_size = (regs[0] & 0x80) ? 0x07: 0x0F; - uint8 outer_bank = !isMermaid ? (regs[0] & 0x78) : 0x04; - uint8 inner_bank = regs[1]; - uint8 game_block = regs[0] & 0x78; - - /* TODO: Hacky and forced mapping of outer banks(game block)... */ - if (!isMermaid) { - switch(game_block) { - case 0x00: /* botb outerbank=0 */ - case 0x10: /* rocketeer outerbank=1 */ - case 0x20: /* contra outerbank=2 */ - case 0x28: /* ducktales outerbank=3 */ - case 0x38: /* school fight outerbank=5 */ - outer_bank = (game_block >> 4) + ((game_block & 0x08) ? 0x01 : 0x00); - outer_bank |= (game_block >> 3) & 1; - break; - case 0x30: - /* Mermaid game block is tricky (to me at least). Aim here is - * when this register is selected, ignore any other outer bank reg changes */ - isMermaid = 1; - outer_bank = 0x04; - break; - } - } - setprg16r(outer_bank, 0x8000, (inner_bank & bank_size)); setprg16r(outer_bank, 0xC000, bank_size); setchr8(0); } static DECLFW(M320Write) { - if ((A & 0xF0E0) == 0xF0E0) { - regs[0] = (A & 0x1F) << 3; + const uint8 chip[] = { 0, 0, 1, 0, 2, 3, 4, 5 }; + /* address mask is inconsistent with that is in the wiki. Mask should be + * 0xFFE0 or Mermaid game will not work. */ + if ((A & 0xFFE0) == 0xF0E0) { + outer_bank = chip[(A & 0x0F)]; + bank_size = (A & 0x10) ? 0x07 : 0x0F; } - regs[1] = V & 0x0F; + inner_bank = (V & 0x0F); Sync(); } static void M320Power(void) { - regs[0] = regs[1] = 0; - isMermaid = 0; + bank_size = 0x0F; Sync(); SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x8000, 0xFFFF, M320Write); } static void M320Reset(void) { - regs[0] = regs[1] = 0; - isMermaid = 0; + inner_bank = outer_bank = 0; + bank_size = 0x0F; Sync(); } From e89bcbfb0d0763127d01213ce391bab90af6554c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 23 Jun 2019 20:51:46 +0800 Subject: [PATCH 28/74] UNIF: Update mirroring on some boards based on last commit --- src/boards/addrlatch.c | 4 ++-- src/boards/bmc60311c.c | 2 +- src/boards/bmc80013b.c | 2 +- src/boards/bmcctc09.c | 2 +- src/boards/bmck3036.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index ee18af9..473559e 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -553,7 +553,7 @@ static void BMCTJ03Sync(void) { setchr8(bank); if (bank == 3) mirr ^= 1; /* Twin Bee has incorrect mirroring */ - SetupCartMirroring(mirr, 1, NULL); + setmirror(mirr); } void BMCTJ03_Init(CartInfo *info) { @@ -568,7 +568,7 @@ static void BMCSA005ASync(void) { setprg16(0x8000, latche & 0x0F); setprg16(0xC000, latche & 0x0F); setchr8(latche & 0x0F); - SetupCartMirroring((latche >> 3) & 1, 1, NULL); + setmirror((latche >> 3) & 1); } void BMCSA005A_Init(CartInfo *info) { diff --git a/src/boards/bmc60311c.c b/src/boards/bmc60311c.c index 8f313ee..03eaf11 100644 --- a/src/boards/bmc60311c.c +++ b/src/boards/bmc60311c.c @@ -66,7 +66,7 @@ static void Sync(void) { setchr8(0); setprg16(0x8000, preg[0]); setprg16(0xC000, preg[1]); - SetupCartMirroring(((mode & 8) >> 3) ^ 1, 1, NULL); + setmirror(((mode & 8) >> 3) ^ 1); } static DECLFW(Write0) { diff --git a/src/boards/bmc80013b.c b/src/boards/bmc80013b.c index 51fb150..82dc4cf 100644 --- a/src/boards/bmc80013b.c +++ b/src/boards/bmc80013b.c @@ -39,7 +39,7 @@ static void Sync(void) { else setprg16r(1, 0x8000, regs[0] & 0x03); setprg16(0xC000, regs[1]); - SetupCartMirroring(((regs[0] >> 4) & 1) ^ 1, 1, NULL); + setmirror(((regs[0] >> 4) & 1) ^ 1); } static DECLFW(BMC80013BWrite) { diff --git a/src/boards/bmcctc09.c b/src/boards/bmcctc09.c index 185576c..8651ad9 100644 --- a/src/boards/bmcctc09.c +++ b/src/boards/bmcctc09.c @@ -43,7 +43,7 @@ static void Sync(void) { setprg32(0x8000, regs[PRG] & 0x07); setchr8(regs[CHR] & 0x0F); - SetupCartMirroring(((regs[PRG] >> 5) & 1) ^ 1, 1, NULL); + setmirror(((regs[PRG] >> 5) & 1) ^ 1); } static DECLFW(WritePRG) { diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c index 2e716e0..c013579 100644 --- a/src/boards/bmck3036.c +++ b/src/boards/bmck3036.c @@ -43,7 +43,7 @@ static void Sync(void) { setprg16(0xC000, regs[0] & 0x1F | 0x07); } setchr8(0); - SetupCartMirroring(((regs[0] & 0x25) == 0x25 ? MI_H : MI_V), 1, NULL); + setmirror(((regs[0] & 0x25) == 0x25) ? MI_H : MI_V); } static DECLFW(M340Write) { From 503dd5249b97d460d92160a3b9df1328af8e4ba5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 24 Jun 2019 06:26:44 +0800 Subject: [PATCH 29/74] Add BMC-JC-016-2 --- src/boards/mmc3.c | 21 +++++++++++++++------ src/unif.c | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 9ac6f86..90a34b4 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -1169,20 +1169,29 @@ void Mapper198_Init(CartInfo *info) { } /* ---------------------------- Mapper 205 ------------------------------ */ -/* https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */ +/* UNIF boardname BMC-JC-016-2 +https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */ +static uint8 block[] = {0, 0, 1, 2}; static void M205PW(uint32 A, uint8 V) { - setprg8(A, EXPREGS[0] & 0x30 | (V & (!(EXPREGS[0] & 0xC0) ? 0x1F : 0x0F))); + uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); + if (PRGptr[1]) + setprg8r(block[EXPREGS[0]], A, bank); + else + setprg8(A, EXPREGS[0] << 4 | bank); } static void M205CW(uint32 A, uint8 V) { - uint16 reg = (uint16)EXPREGS[0] & 0x30; - setchr1(A, (reg << 3) | V); + uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF); + if (PRGptr[1]) + setchr1r(block[EXPREGS[0]], A, bank); + else + setchr1(A, (EXPREGS[0] << 7) | bank); } static DECLFW(M205Write0) { if (EXPREGS[1] == 0) { - EXPREGS[0] = (V << 4) & 0x30; + EXPREGS[0] = V & 0x03; EXPREGS[1] = A & 0x80; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); @@ -1212,7 +1221,7 @@ static void M205Power(void) { } void Mapper205_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 128, 8, 0); + GenMMC3_Init(info, 256, 128, 8, 0); pwrap = M205PW; cwrap = M205CW; info->Power = M205Power; diff --git a/src/unif.c b/src/unif.c index c969909..68403a6 100644 --- a/src/unif.c +++ b/src/unif.c @@ -493,6 +493,8 @@ static BMAPPING bmap[] = { { "KS106C", BMCKS106C_Init, 0 }, { "900218", BTL900218_Init, 0 }, + { "JC-016-2", Mapper205_Init, 0 }, + #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, { "COPYFAMI", MapperCopyFami_Init, 0 }, From c9b3dfb8d590041e5e187c687a2d06183002c41e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 24 Jun 2019 07:00:29 +0800 Subject: [PATCH 30/74] Add BMC-T-262 --- src/boards/t-262.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/boards/t-262.c b/src/boards/t-262.c index ae8c818..d887ef6 100644 --- a/src/boards/t-262.c +++ b/src/boards/t-262.c @@ -33,8 +33,13 @@ static SFORMAT StateRegs[] = static void Sync(void) { setchr8(0); - setprg16(0x8000, base | bank); - setprg16(0xC000, base | (mode ? bank : 7)); + if (PRGptr[1]) { + setprg16r(base >> 3, 0x8000, bank); + setprg16r(base >> 3, 0xC000, (mode ? bank : 7)); + } else { + setprg16(0x8000, base | bank); + setprg16(0xC000, base | (mode ? bank : 7)); + } setmirror(mirr); } From db8a5ab2c99bbe9b7baf5df7798cf03e6612756e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 24 Jun 2019 18:03:18 +0800 Subject: [PATCH 31/74] Add UNL-AX-40G --- src/boards/ax40g.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 1 + src/unif.h | 1 + 3 files changed, 96 insertions(+) create mode 100644 src/boards/ax40g.c diff --git a/src/boards/ax40g.c b/src/boards/ax40g.c new file mode 100644 index 0000000..87be2a7 --- /dev/null +++ b/src/boards/ax40g.c @@ -0,0 +1,94 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 527 is used for a bootleg version of + * Taito's 不動明王伝 (Fudō Myōō Den). + * Its UNIF board name is UNL-AX-40G. The original INES Mapper 207 is + * replaced with a VRC2 clone (A0/A1, i.e. VRC2b) while retaining + * Mapper 207's extended mirroring. + */ + +#include "mapinc.h" + +static uint8 preg[2], creg[8], NT[2]; + +static SFORMAT StateRegs[] = +{ + { preg, 2, "PREG" }, + { creg, 8, "CREG" }, + { NT, 2, "NMT" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, 0x1E); + setprg8(0xE000, 0x1F); + for (i = 0; i < 8; i++) + setchr1(i << 10, creg[i]); + setmirrorw(NT[0], NT[0], NT[1], NT[1]); +} + +static DECLFW(UNLAX40GWrite8) { + A &= 0xF003; + preg[0] = V & 0x1F; + Sync(); +} + +static DECLFW(UNLAX40GWriteA) { + A &= 0xF003; + preg[1] = V & 0x1F; + Sync(); +} + +static DECLFW(UNLAX40GWriteB) { + uint16 i, shift; + A &= 0xF003; + i = ((A >> 1) & 1) | ((A - 0xB000) >> 11); + shift = ((A & 1) << 2); + creg[i] = (creg[i] & (0xF0 >> shift)) | ((V & 0xF) << shift); + if (i < 2) + NT[i] = (creg[i] & 0x80) >> 7; + Sync(); +} + +static void UNLAX40GPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, UNLAX40GWrite8); + SetWriteHandler(0xA000, 0xAFFF, UNLAX40GWriteA); + SetWriteHandler(0xB000, 0xEFFF, UNLAX40GWriteB); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLAX40G_Init(CartInfo *info) { + info->Power = UNLAX40GPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +/*void UNLAX40G_Init(CartInfo *info); // m527 +{ "AX-40G", UNLAX40G_Init, 0 }, +{ "JC-016-2", Mapper205_Init, 0 }, +*/ diff --git a/src/unif.c b/src/unif.c index 68403a6..ebd60fa 100644 --- a/src/unif.c +++ b/src/unif.c @@ -494,6 +494,7 @@ static BMAPPING bmap[] = { { "900218", BTL900218_Init, 0 }, { "JC-016-2", Mapper205_Init, 0 }, + { "AX-40G", UNLAX40G_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 93b3df8..6181f3b 100644 --- a/src/unif.h +++ b/src/unif.h @@ -179,6 +179,7 @@ void BMCK3036_Init(CartInfo *info); /* m340 */ void MINDKIDS_Init(CartInfo *info); /* m268 */ void UNLKS7021A_Init(CartInfo *info); /* m525 */ void BTL900218_Init(CartInfo *info); /* m524 */ +void UNLAX40G_Init(CartInfo *info); /* m527 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 78c0cb422e9d4757f57efa6ebafe2c9f1ed75395 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 24 Jun 2019 18:24:22 +0800 Subject: [PATCH 32/74] BMC-K-3088: move to its own mapper for better compatibility. --- src/boards/bmck3088.c | 72 +++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 2 +- src/unif.h | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/boards/bmck3088.c diff --git a/src/boards/bmck3088.c b/src/boards/bmck3088.c new file mode 100644 index 0000000..e59c38c --- /dev/null +++ b/src/boards/bmck3088.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 287 + * similar to BMC-411120-C but without jumper or dipswitch */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCK3088CW(uint32 A, uint8 V) { + if (CHRptr[EXPREGS[0] & 7]) + setchr1r(EXPREGS[0] & 7, A, V); + else + setchr1(A, V | ((EXPREGS[0] & 3) << 7)); +} + +static void BMCK3088PW(uint32 A, uint8 V) { + if (PRGptr[EXPREGS[0] & 7]) { + uint8 chip = EXPREGS[0] & 7; + if (EXPREGS[0] & 8) + setprg32r(chip, 0x8000, ((EXPREGS[0] >> 4) & 3)); + else + setprg8r(chip, A, (V & 0x0F)); + } else { + if (EXPREGS[0] & 8) + setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); + else + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); + } +} + +static DECLFW(BMCK3088LoWrite) { + EXPREGS[0] = A; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCK3088Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMCK3088Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCK3088LoWrite); +} + +void BMCK3088_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMCK3088PW; + cwrap = BMCK3088CW; + info->Power = BMCK3088Power; + info->Reset = BMCK3088Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/unif.c b/src/unif.c index ebd60fa..9e8cc07 100644 --- a/src/unif.c +++ b/src/unif.c @@ -479,7 +479,7 @@ static BMAPPING bmap[] = { { "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 }, { " BMC-RESET-TXROM", BMCRESETTXROM_Init, 0 }, { "RESET-TXROM", BMCRESETTXROM_Init, 0 }, - { "K-3088", BMC411120C_Init, 0 }, + { "K-3088", BMCK3088_Init, 0 }, { "FARID_SLROM_8-IN-1", FARIDSLROM8IN1_Init, 0 }, { "830425C-4391T", BMC830425C4391T_Init, 0 }, { "TJ-03", BMCTJ03_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 6181f3b..2c9f269 100644 --- a/src/unif.h +++ b/src/unif.h @@ -180,6 +180,7 @@ void MINDKIDS_Init(CartInfo *info); /* m268 */ void UNLKS7021A_Init(CartInfo *info); /* m525 */ void BTL900218_Init(CartInfo *info); /* m524 */ void UNLAX40G_Init(CartInfo *info); /* m527 */ +void BMCK3088_Init(CartInfo *info); /* m287 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 42ae290d46c0b6473eb269200b89b315adbb9389 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 24 Jun 2019 18:45:20 +0800 Subject: [PATCH 33/74] Add BMC-STREETFIGTER-GAME4IN1 --- src/boards/mmc3.c | 20 +++++++++++++++++++- src/unif.c | 1 + src/unif.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 90a34b4..083aa4e 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -599,6 +599,12 @@ void Mapper47_Init(CartInfo *info) { } /* ---------------------------- Mapper 49 ------------------------------- */ +/* -------------------- BMC-STREETFIGTER-GAME4IN1 ----------------------- */ +/* added 6-24-19: + * BMC-STREETFIGTER-GAME4IN1 - Sic. $6000 set to $41 rather than $00 on power-up. + */ + +static uint8 isUNIF = 0; static void M49PW(uint32 A, uint8 V) { if (EXPREGS[0] & 1) { @@ -625,11 +631,12 @@ static DECLFW(M49Write) { } static void M49Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = isUNIF ? 0x41 : 0; MMC3RegReset(); } static void M49Power(void) { + EXPREGS[0] = isUNIF ? 0x41 : 0; M49Reset(); GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, M49Write); @@ -637,6 +644,7 @@ static void M49Power(void) { } void Mapper49_Init(CartInfo *info) { + isUNIF = 0; GenMMC3_Init(info, 512, 256, 0, 0); cwrap = M49CW; pwrap = M49PW; @@ -645,6 +653,16 @@ void Mapper49_Init(CartInfo *info) { AddExState(EXPREGS, 1, 0, "EXPR"); } +void BMCSFGAME4IN1_Init(CartInfo *info) { + isUNIF = 1; + GenMMC3_Init(info, 512, 512, 0, 0); + cwrap = M49CW; + pwrap = M49PW; + info->Reset = M49Reset; + info->Power = M49Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + /* ---------------------------- Mapper 52 ------------------------------- */ static void M52PW(uint32 A, uint8 V) { uint32 mask = 0x1F ^ ((EXPREGS[0] & 8) << 1); diff --git a/src/unif.c b/src/unif.c index 9e8cc07..3e482e7 100644 --- a/src/unif.c +++ b/src/unif.c @@ -495,6 +495,7 @@ static BMAPPING bmap[] = { { "JC-016-2", Mapper205_Init, 0 }, { "AX-40G", UNLAX40G_Init, 0 }, + { " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 2c9f269..9bcf745 100644 --- a/src/unif.h +++ b/src/unif.h @@ -181,6 +181,7 @@ void UNLKS7021A_Init(CartInfo *info); /* m525 */ void BTL900218_Init(CartInfo *info); /* m524 */ void UNLAX40G_Init(CartInfo *info); /* m527 */ void BMCK3088_Init(CartInfo *info); /* m287 */ +void BMCSFGAME4IN1_Init(CartInfo *info); /* m049 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 177cd68d9922d01e6a2b07c7699f091f8cd31a73 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 25 Jun 2019 08:10:36 +0800 Subject: [PATCH 34/74] Add support for UNL-BJ-56 and BMC-G631 (probably a Ghostbuster63in1 mislabel) --- src/boards/bj56.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 2 + src/unif.h | 1 + 3 files changed, 122 insertions(+) create mode 100644 src/boards/bj56.c diff --git a/src/boards/bj56.c b/src/boards/bj56.c new file mode 100644 index 0000000..a73a2ce --- /dev/null +++ b/src/boards/bj56.c @@ -0,0 +1,119 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 526 is used for a bootleg version of Namco's 三国志: 中原の覇者 (Sangokushi: Chūgen no Hasha). + * Its UNIF board name is UNL-BJ-56. + * Mirroring seems to be hard-wired (to vertical). + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_526 + */ + +#include "mapinc.h" + +static uint8 preg[4], creg[8]; +static uint32 IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, preg[3]); + for (i = 0; i < 8; i++) + setchr1((i << 10), creg[i]); + setmirror(MI_V); +} + +static DECLFW(UNLBJ56Write) { +/* FCEU_printf("Wr: A:%04x V:%02x\n", A, V); */ + A &= 0xF00F; + if (A <= 0x8007) { + creg[A & 0x07] = V; + Sync(); + } else if (A <= 0x800B) { + preg[A & 0x03] = V; + Sync(); + } else { + switch (A & 0x0F) { + case 0x0D: + case 0x0F: + /* One of these two acknowledges a pending IRQ, and the other + * resets to IRQ counter to zero. Because they are always written + * to one after the other, it's not clear which one does which. */ + X6502_IRQEnd(FCEU_IQEXT); + IRQCount = 0; + break; + } + } +} + +static void FP_FASTAPASS(1) UNLBJ56IRQHook(int a) { + IRQCount += a; + if (IRQCount & 4096) + X6502_IRQBegin(FCEU_IQEXT); +} + +static void UNLBJ56Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void UNLBJ56Power(void) { + preg[0] = ~3; + preg[1] = ~2; + preg[2] = ~1; + preg[3] = ~0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x800F, UNLBJ56Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLBJ56_Init(CartInfo *info) { + info->Power = UNLBJ56Power; + info->Close = UNLBJ56Close; + MapIRQHook = UNLBJ56IRQHook; + GameStateRestore = StateRestore; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/unif.c b/src/unif.c index 3e482e7..c2f4b89 100644 --- a/src/unif.c +++ b/src/unif.c @@ -496,6 +496,8 @@ static BMAPPING bmap[] = { { "JC-016-2", Mapper205_Init, 0 }, { "AX-40G", UNLAX40G_Init, 0 }, { " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 }, + { "G631", BMCGhostbusters63in1_Init, 0 }, + { "BJ-56", UNLBJ56_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 9bcf745..d2111b3 100644 --- a/src/unif.h +++ b/src/unif.h @@ -182,6 +182,7 @@ void BTL900218_Init(CartInfo *info); /* m524 */ void UNLAX40G_Init(CartInfo *info); /* m527 */ void BMCK3088_Init(CartInfo *info); /* m287 */ void BMCSFGAME4IN1_Init(CartInfo *info); /* m049 */ +void UNLBJ56_Init(CartInfo *info); /* m526 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 6ff34f4c7ae6a0ce52c2a1a7985db543cd1b37af Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 25 Jun 2019 10:48:42 +0800 Subject: [PATCH 35/74] Add support for BMC-L6IN1 --- src/boards/bmcl6in1.c | 74 +++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 1 + src/unif.h | 1 + 3 files changed, 76 insertions(+) create mode 100644 src/boards/bmcl6in1.c diff --git a/src/boards/bmcl6in1.c b/src/boards/bmcl6in1.c new file mode 100644 index 0000000..f788537 --- /dev/null +++ b/src/boards/bmcl6in1.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 345 + * BMC-L6IN1 + * New Star 6-in-1 Game Cartridge + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_345 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCL6IN1CW(uint32 A, uint8 V) { + setchr8(V); +} + +static void BMCL6IN1PW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x0C) + setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0xC0) >> 2); + else + setprg32(0x8000, ((EXPREGS[0] & 0xC0) >> 4) | (EXPREGS[0] & 0x03)); +} + +static void BMCL6IN1MW(uint8 V) { + if (EXPREGS[0] & 0x20) + setmirror(MI_0 + ((EXPREGS[0] & 0x10) >> 1)); + else { + A000B = V; + setmirror((V & 1) ^ 1); + } +} + +static DECLFW(BMCL6IN1Write) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCL6IN1Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMCL6IN1Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCL6IN1Write); +} + +void BMCL6IN1_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 0, 1, 0); + pwrap = BMCL6IN1PW; + cwrap = BMCL6IN1CW; + mwrap = BMCL6IN1MW; + info->Power = BMCL6IN1Power; + info->Reset = BMCL6IN1Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/unif.c b/src/unif.c index c2f4b89..a918888 100644 --- a/src/unif.c +++ b/src/unif.c @@ -498,6 +498,7 @@ static BMAPPING bmap[] = { { " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 }, { "G631", BMCGhostbusters63in1_Init, 0 }, { "BJ-56", UNLBJ56_Init, 0 }, + { "L6IN1", BMCL6IN1_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index d2111b3..a378f12 100644 --- a/src/unif.h +++ b/src/unif.h @@ -183,6 +183,7 @@ void UNLAX40G_Init(CartInfo *info); /* m527 */ void BMCK3088_Init(CartInfo *info); /* m287 */ void BMCSFGAME4IN1_Init(CartInfo *info); /* m049 */ void UNLBJ56_Init(CartInfo *info); /* m526 */ +void BMCL6IN1_Init(CartInfo *info); /* m345 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From afaa5eab6ce1eebd4cb526a896df2c54852e14e5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 25 Jun 2019 16:47:18 +0800 Subject: [PATCH 36/74] Add support for BMC-CTC-12IN1 and BMC-891227 --- src/boards/bmcgamecard.c | 95 ++++++++++++++++++++++++++++++++++++++++ src/unif.c | 4 +- src/unif.h | 3 ++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/boards/bmcgamecard.c diff --git a/src/boards/bmcgamecard.c b/src/boards/bmcgamecard.c new file mode 100644 index 0000000..e634abd --- /dev/null +++ b/src/boards/bmcgamecard.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 337 - BMC-CTC-12IN1 + * 12-in-1 Game Card multicart + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_337 + + * NES 2.0 Mapper 350 - BMC-891227 + * Super 15-in-1 Game Card + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_350 + */ + +#include "mapinc.h" + +static uint8 latche, m350; + +static SFORMAT StateRegs[] = +{ + { &latche, 1, "LATC" }, + { &m350, 1, "M350" }, + { 0 } +}; + +static void Sync(void) { + uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1); + uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03); + uint8 chip = m350 ? ((mode & 2) ? ((latche >> 5) & 1) : 0) : 0; + + setchr8(0); + setprg8(0x6000, 1); + setprg16r(PRGptr[1] ? chip : 0, 0x8000, (latche & 0x1F)); + setprg16r(PRGptr[1] ? chip : 0, 0xC000, (latche & 0x1F) | ((mode & 2) ? 0x07 : (mode & 1))); + setmirror(mirroring ^ 1); +} + +static DECLFW(BMCCTC12IN1Write8) { + latche = (latche & 7) | (V & ~7); + Sync(); +} + +static DECLFW(BMCCTC12IN1WriteC) { + latche = (latche & ~7) | (V & 7); + Sync(); +} + +static void BMCCTC12IN1Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, BMCCTC12IN1Write8); + SetWriteHandler(0xC000, 0xFFFF, BMCCTC12IN1WriteC); +} + +static void BMCCTC12IN1Reset(void) { + latche = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +/* Mapper 337 - BMC-CTC-12IN1 */ +void BMCCTC12IN1_Init(CartInfo *info) { + m350 = 0; + info->Power = BMCCTC12IN1Power; + info->Reset = BMCCTC12IN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +/* Mapper 350 - BMC-891227 */ +void BMC891227_Init(CartInfo *info) { + m350 = 1; + info->Power = BMCCTC12IN1Power; + info->Reset = BMCCTC12IN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/unif.c b/src/unif.c index a918888..1d8159c 100644 --- a/src/unif.c +++ b/src/unif.c @@ -473,7 +473,6 @@ static BMAPPING bmap[] = { { "WAIXING-FW01", Mapper227_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 */ { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ { "80013-B", BMC80013B_Init, 0 }, - { "TH2131-1", UNLTH21311_Init, 0 }, { "LH51", LH51_Init, 0 }, { "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 }, @@ -492,13 +491,14 @@ static BMAPPING bmap[] = { { "KS7021A", UNLKS7021A_Init, 0 }, { "KS106C", BMCKS106C_Init, 0 }, { "900218", BTL900218_Init, 0 }, - { "JC-016-2", Mapper205_Init, 0 }, { "AX-40G", UNLAX40G_Init, 0 }, { " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 }, { "G631", BMCGhostbusters63in1_Init, 0 }, { "BJ-56", UNLBJ56_Init, 0 }, { "L6IN1", BMCL6IN1_Init, 0 }, + { "CTC-12IN1", BMCCTC12IN1_Init, 0 }, + { "891227", BMC891227_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index a378f12..98bb3b1 100644 --- a/src/unif.h +++ b/src/unif.h @@ -185,6 +185,9 @@ void BMCSFGAME4IN1_Init(CartInfo *info); /* m049 */ void UNLBJ56_Init(CartInfo *info); /* m526 */ void BMCL6IN1_Init(CartInfo *info); /* m345 */ +void BMCCTC12IN1_Init(CartInfo *info); /* m337 */ +void BMC891227_Init(CartInfo *info); /* m350 */ + #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); void MapperCopyFami_Init(CartInfo *info); From 0cb1c866a17657a7a08c97760e385048714f4b35 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 25 Jun 2019 16:56:05 +0800 Subject: [PATCH 37/74] Silence clang warnings --- src/boards/90.c | 4 ++-- src/boards/bmc80013b.c | 2 +- src/boards/bmck3036.c | 4 ++-- src/boards/mmc1.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/boards/90.c b/src/boards/90.c index 2bc867a..ff2b0b4 100644 --- a/src/boards/90.c +++ b/src/boards/90.c @@ -130,13 +130,13 @@ static void tekprom(void) { case 0x00: if (tkcom[0] & 0x80) setprg8(0x6000, (((prgb[3] << 2) + 3) & 0x3F) | bankmode); - setprg32(0x8000, last_bank & prgmask | bankmode); + setprg32(0x8000, (last_bank & prgmask) | bankmode); break; case 0x01: if (tkcom[0] & 0x80) setprg8(0x6000, (((prgb[3] << 1) + 1) & 0x3F) | bankmode); setprg16(0x8000, (prgb[1] & prgmask) | bankmode); - setprg16(0xC000, last_bank & prgmask | bankmode); + setprg16(0xC000, (last_bank & prgmask) | bankmode); break; case 0x02: case 0x03: diff --git a/src/boards/bmc80013b.c b/src/boards/bmc80013b.c index 82dc4cf..bfe6b27 100644 --- a/src/boards/bmc80013b.c +++ b/src/boards/bmc80013b.c @@ -35,7 +35,7 @@ static SFORMAT StateRegs[] = static void Sync(void) { if (mode & 0x02) - setprg16(0x8000, regs[0] & 0x0F | regs[1] & 0x70); + setprg16(0x8000, (regs[0] & 0x0F) | (regs[1] & 0x70)); else setprg16r(1, 0x8000, regs[0] & 0x03); setprg16(0xC000, regs[1]); diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c index c013579..77ced85 100644 --- a/src/boards/bmck3036.c +++ b/src/boards/bmck3036.c @@ -39,8 +39,8 @@ static void Sync(void) { setprg16(0x8000, regs[0] & 0x1F); setprg16(0xC000, regs[0] & 0x1F); } else { /* UNROM */ - setprg16(0x8000, regs[0] & 0x1F | regs[1] & 0x07); - setprg16(0xC000, regs[0] & 0x1F | 0x07); + setprg16(0x8000, (regs[0] & 0x1F) | (regs[1] & 0x07)); + setprg16(0xC000, (regs[0] & 0x1F) | 0x07); } setchr8(0); setmirror(((regs[0] & 0x25) == 0x25) ? MI_H : MI_V); diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index 4dc4f69..f3ef3c1 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -440,6 +440,6 @@ void FARIDSLROM8IN1_Init(CartInfo *info) { MMC1PRGHook16 = FARIDSLROM8IN1PRGHook; info->Power = FARIDSLROM8IN1Power; info->Reset = FARIDSLROM8IN1Reset; - AddExState(lock, 1, 0, "LOCK"); - AddExState(reg, 1, 0, "REG6"); + AddExState(&lock, 1, 0, "LOCK"); + AddExState(®, 1, 0, "REG6"); } From 3666962090e5cd3747ec678badc71a9a2ebdc2eb Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 25 Jun 2019 18:23:23 +0800 Subject: [PATCH 38/74] UNL-KS7017: Smoother state loading... - Smoother states loading by using the the register value used during call to Sync() instead of the last value written since write and sync are called at different times. - (reg value written @ $4A000, sync happens $5100) --- src/boards/KS7017.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/boards/KS7017.c b/src/boards/KS7017.c index 64812a4..b1c9d87 100644 --- a/src/boards/KS7017.c +++ b/src/boards/KS7017.c @@ -23,7 +23,7 @@ #include "mapinc.h" -static uint8 reg, mirr; +static uint8 latche, reg, mirr; static int32 IRQa, IRQCount, IRQLatch; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; @@ -35,6 +35,7 @@ static SFORMAT StateRegs[] = { &IRQa, 4, "IRQA" }, { &IRQCount, 4, "IRQC" }, { &IRQLatch, 4, "IRQL" }, + { &latche, 1, "LATC" }, { 0 } }; @@ -47,8 +48,9 @@ static void Sync(void) { static DECLFW(UNLKS7017Write) { /* FCEU_printf("bs %04x %02x\n",A,V); */ if ((A & 0xFF00) == 0x4A00) { - reg = ((A >> 2) & 3) | ((A >> 4) & 4); + latche = ((A >> 2) & 3) | ((A >> 4) & 4); } else if ((A & 0xFF00) == 0x5100) { + reg = latche; Sync(); } else if (A == 0x4020) { X6502_IRQEnd(FCEU_IQEXT); From 024a2f904eed22414140d6ffa7c05afcf16d1c7d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 00:11:14 +0800 Subject: [PATCH 39/74] Add support for FARID_UNROM_8-IN-1 and NEWSTAR-GRM070-8IN1 --- src/boards/faridunrom.c | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/boards/faridunrom.c diff --git a/src/boards/faridunrom.c b/src/boards/faridunrom.c new file mode 100644 index 0000000..219b8d7 --- /dev/null +++ b/src/boards/faridunrom.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 324 + * FARID_UNROM_8-IN-1 + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_324 + */ + +#include "mapinc.h" + +static uint8 latch; + +static SFORMAT StateRegs[] = +{ + { &latch, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg16(0x8000, ((latch & 0x70) >> 1) | (latch & 0x07)); + setprg16(0xC000, ((latch & 0x70) >> 1) | 0x07 ); +} + +static DECLFW(FARIDUNROMWrite) { + V &= CartBR(A); + if ((V & 0x80) && !(latch & 0x80) && !(latch & 0x08)) + latch = (latch & 0x87) | (V & 0x78); + latch = (latch & 0x78) | (V & 0x87); + Sync(); +} + +static void FARIDUNROMPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, FARIDUNROMWrite); +} + +static void FARIDUNROMReset(void) { + latch &= ~0x78; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void FARIDUNROM_Init(CartInfo *info) { + info->Power = FARIDUNROMPower; + info->Reset = FARIDUNROMReset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} From 93986604acb5905894826a67d4d4879edcc48333 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 09:03:01 +0800 Subject: [PATCH 40/74] Add support for BMC-K-3033 --- src/boards/bcmk3033.c | 89 +++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 3 ++ src/unif.h | 2 + 3 files changed, 94 insertions(+) create mode 100644 src/boards/bcmk3033.c diff --git a/src/boards/bcmk3033.c b/src/boards/bcmk3033.c new file mode 100644 index 0000000..90ff0af --- /dev/null +++ b/src/boards/bcmk3033.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 322 + * BMC-K-3033 + * 35-in-1 (K-3033) + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_322 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCK3033CW(uint32 A, uint8 V) { + if (EXPREGS[2]) { + if (EXPREGS[3]) { // MMC3-256 + setchr1r(EXPREGS[1] & ~0x01, A, (V & 0xFF)); + } else { // MMC3-128 + setchr1r(EXPREGS[1], A, (V & 0x7F)); + } + } else { // NROM + setchr1r(EXPREGS[1], A, (V & 0x7F)); + } +} + +static void BMCK3033PW(uint32 A, uint8 V) { + if (EXPREGS[2]) { + if (EXPREGS[3] ) { +/* FCEU_printf("MMC3-256 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1] & ~0x01); */ + setprg8r((EXPREGS[1] & ~0x01), A, (V & 0x1F)); + } else { +/* FCEU_printf("MMC3-128 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1]); */ + setprg8r(EXPREGS[1], A, (V & 0x0F)); + } + } else { + if (EXPREGS[0] & 0x03) { +/* FCEU_printf("NROM-256 base:%02x chip:%02x\n", EXPREGS[0] >> 1, EXPREGS[1]); */ + setprg32r(EXPREGS[1], 0x8000, EXPREGS[0] >> 1); + } else { +/* FCEU_printf("NROM-128 base:%02x chip:%02x\n", EXPREGS[0], EXPREGS[1]); */ + setprg16r(EXPREGS[1], 0x8000, EXPREGS[0]); + setprg16r(EXPREGS[1], 0xC000, EXPREGS[0]); + } + } +} + +static DECLFW(BMCK3033Write) { + EXPREGS[0] = (A & 0x07); + EXPREGS[1] = ((A & 0x18) >> 3) | ((A & 0x40) >> 4); + EXPREGS[2] = (A & 0x20); + EXPREGS[3] = (A & 0x80); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCK3033Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCK3033Write); +} + +static void BMCK3033Reset(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + MMC3RegReset(); +} + +void BMCK3033_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 1, 0); + pwrap = BMCK3033PW; + cwrap = BMCK3033CW; + info->Power = BMCK3033Power; + info->Reset = BMCK3033Reset; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/unif.c b/src/unif.c index 1d8159c..9772d75 100644 --- a/src/unif.c +++ b/src/unif.c @@ -499,6 +499,9 @@ static BMAPPING bmap[] = { { "L6IN1", BMCL6IN1_Init, 0 }, { "CTC-12IN1", BMCCTC12IN1_Init, 0 }, { "891227", BMC891227_Init, 0 }, + { "NEWSTAR-GRM070-8IN1", BMC8IN1_Init, 0 }, + { "FARID_UNROM_8-IN-1", FARIDUNROM_Init, 0 }, + { "K-3033", BMCK3033_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 98bb3b1..5bc341d 100644 --- a/src/unif.h +++ b/src/unif.h @@ -187,6 +187,8 @@ void BMCL6IN1_Init(CartInfo *info); /* m345 */ void BMCCTC12IN1_Init(CartInfo *info); /* m337 */ void BMC891227_Init(CartInfo *info); /* m350 */ +void FARIDUNROM_Init(CartInfo *info); /* m324 */ +void BMCK3033_Init(CartInfo *info); /* mm22 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 38a560df82ef44ecdc6dbaf03bbb09ccc7fdad1a Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 11:04:42 +0800 Subject: [PATCH 41/74] A few unif board fixes - RESET-NROM-XIN1 - fix MD5 mismatch due to uninitialized variable - RESET-TXROM - improve compatibility with some rom types --- src/boards/resetnromxin1.c | 2 +- src/boards/resettxrom.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c index c97837d..d17bc81 100644 --- a/src/boards/resetnromxin1.c +++ b/src/boards/resetnromxin1.c @@ -59,7 +59,7 @@ static void StateRestore(int version) { void BMCRESETNROMXIN1_Init(CartInfo *info) { uint8 x; - uint64 partialmd5; + uint64 partialmd5 = 0; for (x = 0; x < 8; x++) partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c index fdf1d1b..e4bced0 100644 --- a/src/boards/resettxrom.c +++ b/src/boards/resettxrom.c @@ -28,11 +28,11 @@ #include "mmc3.h" static void M313CW(uint32 A, uint8 V) { - setchr1r(EXPREGS[0], A, V & 0x7F); + setchr1r(CHRptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 7) | (V & 0x7F)); } static void M313PW(uint32 A, uint8 V) { - setprg8r(EXPREGS[0], A, V & 0x0F); + setprg8r(PRGptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 4) | (V & 0x0F)); } static void M313Reset(void) { @@ -48,7 +48,7 @@ static void M313Power(void) { /* NES 2.0 313, UNIF BMC-RESET-TXROM */ void BMCRESETTXROM_Init(CartInfo *info) { - GenMMC3_Init(info, 512, 256, 0, 0); + GenMMC3_Init(info, 128, 128, 0, 0); cwrap = M313CW; pwrap = M313PW; info->Power = M313Power; From 6653f4028a8a1d2a3790a9674a2f8f49b0e2f765 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 16:45:08 +0800 Subject: [PATCH 42/74] Add support for BMC-830134C --- src/boards/830134C.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 1 + src/unif.h | 1 + 3 files changed, 74 insertions(+) create mode 100644 src/boards/830134C.c diff --git a/src/boards/830134C.c b/src/boards/830134C.c new file mode 100644 index 0000000..7d546d5 --- /dev/null +++ b/src/boards/830134C.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 315 + * BMC-830134C + * Used for multicarts using 820732C- and 830134C-numbered PCBs such as 4-in-1 Street Blaster 5 + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_315 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMC830134CCW(uint32 A, uint8 V) { + uint32 chip = (EXPREGS[0] & 0x03) & ~((EXPREGS[0] & 0x02) >> 1); + setchr1r(chip, A, (V & 0xFF) | ((EXPREGS[0] & 0x01) << 8) | ((EXPREGS[0] & 0x02) << 6) | ((EXPREGS[0] & 0x08) << 3)); +} + +static void BMC830134CPW(uint32 A, uint8 V) { + uint32 chip = (EXPREGS[0] & 0x06) >> 1; + if ((EXPREGS[0] & 0x06) == 0x06) { + if (A == 0x8000) { + setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); + setprg8r(chip, 0xC000, (V & 0x0F) | 0x32); + } else if (A == 0xA000) { + setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); + setprg8r(chip, 0xE000, (V & 0x0F) | 0x32); + } + } else + setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); +} + +static DECLFW(BMC830134CWrite) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMC830134CReset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMC830134CPower(void) { + GenMMC3Power(); + SetWriteHandler(0x6800, 0x68FF, BMC830134CWrite); +} + +void BMC830134C_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 1, 0); + pwrap = BMC830134CPW; + cwrap = BMC830134CCW; + info->Power = BMC830134CPower; + info->Reset = BMC830134CReset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/unif.c b/src/unif.c index 9772d75..d58c1d4 100644 --- a/src/unif.c +++ b/src/unif.c @@ -502,6 +502,7 @@ static BMAPPING bmap[] = { { "NEWSTAR-GRM070-8IN1", BMC8IN1_Init, 0 }, { "FARID_UNROM_8-IN-1", FARIDUNROM_Init, 0 }, { "K-3033", BMCK3033_Init, 0 }, + { "830134C", BMC830134C_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 5bc341d..b35c250 100644 --- a/src/unif.h +++ b/src/unif.h @@ -189,6 +189,7 @@ void BMCCTC12IN1_Init(CartInfo *info); /* m337 */ void BMC891227_Init(CartInfo *info); /* m350 */ void FARIDUNROM_Init(CartInfo *info); /* m324 */ void BMCK3033_Init(CartInfo *info); /* mm22 */ +void BMC830134C_Init(CartInfo *info); /* m315 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From 6d26ce4f9f4207b02a3539d74be19824a1b8806d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 22:14:48 +0800 Subject: [PATCH 43/74] BMC-K-3036: Fix incorrect write address range --- src/boards/{bcmk3006.c => bmck3006.c} | 0 src/boards/{bcmk3033.c => bmck3033.c} | 0 src/boards/bmck3036.c | 28 +++++++++++++++------------ 3 files changed, 16 insertions(+), 12 deletions(-) rename src/boards/{bcmk3006.c => bmck3006.c} (100%) rename src/boards/{bcmk3033.c => bmck3033.c} (100%) diff --git a/src/boards/bcmk3006.c b/src/boards/bmck3006.c similarity index 100% rename from src/boards/bcmk3006.c rename to src/boards/bmck3006.c diff --git a/src/boards/bcmk3033.c b/src/boards/bmck3033.c similarity index 100% rename from src/boards/bcmk3033.c rename to src/boards/bmck3033.c diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c index 77ced85..bd72ca3 100644 --- a/src/boards/bmck3036.c +++ b/src/boards/bmck3036.c @@ -26,40 +26,44 @@ #include "mapinc.h" -static uint8 regs[2]; +static uint8 regs[2], mirr, mode; static SFORMAT StateRegs[] = { - { regs, 2, "REGS" }, + { regs, 2, "REGS" }, + { &mode, 1, "MODE" }, + { &mirr, 1, "MIRR" }, { 0 } }; static void Sync(void) { - if (regs[0] & 0x20) { /* NROM-128 */ - setprg16(0x8000, regs[0] & 0x1F); - setprg16(0xC000, regs[0] & 0x1F); + if (mode) { /* NROM-128 */ + setprg16(0x8000, regs[0]); + setprg16(0xC000, regs[0]); } else { /* UNROM */ - setprg16(0x8000, (regs[0] & 0x1F) | (regs[1] & 0x07)); - setprg16(0xC000, (regs[0] & 0x1F) | 0x07); + setprg16(0x8000, regs[0] | regs[1]); + setprg16(0xC000, regs[0] | 0x07); } setchr8(0); - setmirror(((regs[0] & 0x25) == 0x25) ? MI_H : MI_V); + setmirror(mirr); } static DECLFW(M340Write) { - regs[0] = A & 0xFF; - regs[1] = V & 0xFF; + regs[0] = A & 0x1F; + regs[1] = V & 0x07; + mode = A & 0x20; + mirr = ((A & 0x25) == 0x25) ? 0 : 1; Sync(); } static void BMCK3036Power(void) { Sync(); SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xBFFF, M340Write); + SetWriteHandler(0x8000, 0xFFFF, M340Write); } static void BMCK3036Reset(void) { - regs[0] = regs[1] = 0; + regs[0] = regs[1] = mode = mirr = 0; Sync(); } From e734fa87965c272391fce046923123af875bf096 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 26 Jun 2019 23:51:19 +0800 Subject: [PATCH 44/74] Add support for BMC-GN-26 --- src/boards/gn26.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ src/unif.c | 1 + src/unif.h | 1 + 3 files changed, 70 insertions(+) create mode 100644 src/boards/gn26.c diff --git a/src/boards/gn26.c b/src/boards/gn26.c new file mode 100644 index 0000000..a712cc2 --- /dev/null +++ b/src/boards/gn26.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 344 + * BMC-GN-26 + * Kuai Da Jin Ka Zhong Ji Tiao Zhan 3-in-1 (3-in-1,6-in-1,Unl) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCGN26CW(uint32 A, uint8 V) { + uint32 chip = (EXPREGS[0] & 0x03); + if (chip) chip -= 1; + setchr1r(chip, A, (V & 0xFF)); +} + +static void BMCGN26PW(uint32 A, uint8 V) { + uint32 chip = (EXPREGS[0] & 0x03); + if (chip) chip -= 1; /* Re-ordered -> 0:SF4 1:Contra Force 2:Revolution Hero */ + if (EXPREGS[0] & 4) { + if (A == 0x8000) + setprg32r(chip, 0x8000, (V >> 2)); + } else + setprg8r(chip, A, (V & 0x0F)); +} + +static DECLFW(BMCGN26Write) { + EXPREGS[0] = A & 0x0F; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCGN26Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMCGN26Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6800, 0x68FF, BMCGN26Write); +} + +void BMCGN26_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 1, 0); + pwrap = BMCGN26PW; + cwrap = BMCGN26CW; + info->Power = BMCGN26Power; + info->Reset = BMCGN26Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/unif.c b/src/unif.c index d58c1d4..567ba59 100644 --- a/src/unif.c +++ b/src/unif.c @@ -503,6 +503,7 @@ static BMAPPING bmap[] = { { "FARID_UNROM_8-IN-1", FARIDUNROM_Init, 0 }, { "K-3033", BMCK3033_Init, 0 }, { "830134C", BMC830134C_Init, 0 }, + { "GN-26", BMCGN26_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index b35c250..661fff3 100644 --- a/src/unif.h +++ b/src/unif.h @@ -190,6 +190,7 @@ void BMC891227_Init(CartInfo *info); /* m350 */ void FARIDUNROM_Init(CartInfo *info); /* m324 */ void BMCK3033_Init(CartInfo *info); /* mm22 */ void BMC830134C_Init(CartInfo *info); /* m315 */ +void BMCGN26_Init(CartInfo *info); /* m344 */ #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); From fa21e91ef5eebdbc334e4995054c7f2dd9f2973f Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 27 Jun 2019 00:56:24 +0800 Subject: [PATCH 45/74] UNL-EH8813A: Update based on latest wiki --- src/boards/ax40g.c | 1 + src/boards/eh8813a.c | 30 +++++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/boards/ax40g.c b/src/boards/ax40g.c index 87be2a7..f3fe1d1 100644 --- a/src/boards/ax40g.c +++ b/src/boards/ax40g.c @@ -1,6 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 diff --git a/src/boards/eh8813a.c b/src/boards/eh8813a.c index ab15b39..d8998a3 100644 --- a/src/boards/eh8813a.c +++ b/src/boards/eh8813a.c @@ -18,36 +18,40 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + /* Updated 6-27-19 */ + #include "mapinc.h" -static uint16 addrlatch; -static uint8 datalatch, hw_mode; +static uint8 datalatch, addrlatch, lock, hw_mode; static SFORMAT StateRegs[] = { - { &addrlatch, 2, "ADRL" }, + { &addrlatch, 1, "ADRL" }, { &datalatch, 1, "DATL" }, - { &hw_mode, 1, "HWMO" }, + { &hw_mode, 1, "HWMO" }, + { &lock, 1, "LOCK" }, { 0 } }; static void Sync(void) { - uint8 prg = (addrlatch & 7); + uint8 prg = (addrlatch & 0x3F); setchr8(datalatch); - if(addrlatch & 0x80) { + if (addrlatch & 0x80) { setprg16(0x8000,prg); setprg16(0xC000,prg); } else { setprg32(0x8000,prg >> 1); } - setmirror(MI_V); + setmirror(((datalatch >> 7) & 1) ^ 1); } static DECLFW(EH8813AWrite) { - if((addrlatch & 0x100) == 0) { - addrlatch = A & 0x1FF; - datalatch = V & 0xF; + if (lock == 0) { + addrlatch = A & 0xFF; + datalatch = V & 0xFC; + lock = (A & 0x100) >> 8; } + datalatch = (datalatch & ~0x03) | (V & 0x03); Sync(); } @@ -56,16 +60,16 @@ static DECLFR(EH8813ARead) { A= (A & 0xFFF0) + hw_mode; return CartBR(A); } - + static void EH8813APower(void) { - addrlatch = datalatch = hw_mode = 0; + addrlatch = datalatch = hw_mode = lock = 0; Sync(); SetReadHandler(0x8000, 0xFFFF, EH8813ARead); SetWriteHandler(0x8000, 0xFFFF, EH8813AWrite); } static void EH8813AReset(void) { - addrlatch = datalatch = 0; + addrlatch = datalatch = lock = 0; hw_mode = (hw_mode + 1) & 0xF; FCEU_printf("Hardware Switch is %01X\n", hw_mode); Sync(); From 3259e34303442fbb0ec821b20a77001665215f98 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 28 Jun 2019 23:39:38 +0200 Subject: [PATCH 46/74] Remove stale references to src/mappers --- Makefile.common | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.common b/Makefile.common index 37f20d9..22f0e5e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1,5 +1,5 @@ LIBRETRO_COMM_DIR := $(CORE_DIR)/drivers/libretro/libretro-common -INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include -I$(CORE_DIR) -I$(CORE_DIR)/input -I$(CORE_DIR)/boards -I$(CORE_DIR)/mappers +INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include -I$(CORE_DIR) -I$(CORE_DIR)/input -I$(CORE_DIR)/boards COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565 INCLUDE_STDINT = 0 @@ -21,7 +21,7 @@ else COREDEFINES += -DPSS_STYLE=1 endif -FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers +FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) ifeq ($(HAVE_GRIFFIN),1) From 74e43dbd02a8f24a5b65931a88ef366b8d950361 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sun, 24 Feb 2019 17:29:49 +0100 Subject: [PATCH 47/74] Tupfile for super-repositories - Revert Genode Make rules - Tweak Makefile.common for compatiblity - Allow LIBRETRO_COMM_DIR override --- Makefile.common | 21 +++++++-------------- Makefile.libretro | 26 +++++++++++++------------- Tupfile | 3 +++ 3 files changed, 23 insertions(+), 27 deletions(-) create mode 100644 Tupfile diff --git a/Makefile.common b/Makefile.common index 22f0e5e..88a46ff 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1,19 +1,8 @@ +ifeq ($(LIBRETRO_COMM_DIR),) LIBRETRO_COMM_DIR := $(CORE_DIR)/drivers/libretro/libretro-common +endif INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include -I$(CORE_DIR) -I$(CORE_DIR)/input -I$(CORE_DIR)/boards -COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565 - -INCLUDE_STDINT = 0 -ifneq (,$(findstring msvc200,$(platform))) -INCLUDE_STDINT = 1 -endif - -ifeq ($(INCLUDE_STDINT), 1) -INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc -endif - -ifneq (,$(findstring msvc,$(platform))) -COREDEFINES += -DINLINE=_inline -endif +COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565 ifeq ($(PSS_STYLE),2) COREDEFINES += -DPSS_STYLE=2 @@ -21,8 +10,12 @@ else COREDEFINES += -DPSS_STYLE=1 endif +ifeq ($(TUP_CWD),) FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) +else +SOURCES_C = $(CORE_DIR)/boards/*.c $(CORE_DIR)/input/*.c +endif ifeq ($(HAVE_GRIFFIN),1) SOURCES_C += $(CORE_DIR)/drivers/libretro/griffin.c diff --git a/Makefile.libretro b/Makefile.libretro index abf874b..b1e1d35 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -386,16 +386,6 @@ else ifeq ($(platform), gcw0) PLATFORM_DEFINES += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float EXTERNAL_ZLIB = 1 -# Genode -else ifeq ($(platform), genode) - TARGET := $(TARGET_NAME)_libretro.lib.so - CC := $(shell pkg-config genode-base --variable=cc) - LD := $(shell pkg-config genode-base --variable=ld) - CFLAGS += $(shell pkg-config --cflags genode-libc) - LDFLAGS += -shared --version-script=src/drivers/libretro/link.T - LDFLAGS += $(shell pkg-config --libs genode-lib genode-libc) - LIBM = - # Windows MSVC 2017 all architectures else ifneq (,$(findstring windows_msvc2017,$(platform))) CC = cl.exe @@ -673,6 +663,19 @@ CORE_DIR := src include Makefile.common +INCLUDE_STDINT = 0 +ifneq (,$(findstring msvc200,$(platform))) +INCLUDE_STDINT = 1 +endif + +ifeq ($(INCLUDE_STDINT), 1) +INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc +endif + +ifneq (,$(findstring msvc,$(platform))) +COREDEFINES += -DINLINE=_inline +endif + CFLAGS += -DWANT_GRIFFIN OBJECTS := $(SOURCES_C:.c=.o) @@ -714,9 +717,6 @@ else ifeq ($(platform), switch) OBJOUT = -o LINKOUT = -o # libtransistor.mk sets LD for us -else ifeq ($(platform), genode) - OBJOUT = -o - LINKOUT = -o else OBJOUT = -o LINKOUT = -o diff --git a/Tupfile b/Tupfile new file mode 100644 index 0000000..b0e54a8 --- /dev/null +++ b/Tupfile @@ -0,0 +1,3 @@ +TARGET_NAME=fceumm +CORE_DIR=$(TUP_CWD)/src +include_rules From 83b2f99527e5b4cd46259fa686c598e1926243c5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 27 Jun 2019 12:22:07 +0800 Subject: [PATCH 48/74] Mapper134: Update and add support for UNL-T4A54A unif board --- src/boards/mmc3.c | 15 +++++++++++---- src/unif.c | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 083aa4e..b783b67 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -905,13 +905,19 @@ void Mapper119_Init(CartInfo *info) { } /* ---------------------------- Mapper 134 ------------------------------ */ +/* ---------------------------- UNL-T4A54A ------------------------------ */ + +/* UNL-T4A54A, functionally the same as mapper 134. + * Writes @ $6801. Menu @ prg $20000, chr $00000 */ static void M134PW(uint32 A, uint8 V) { - setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 2) << 4)); + uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; + setprg8r(PRGptr[1] ? (EXPREGS[0] & 3) : 0, A, (V & mask) | ((EXPREGS[0] & 3) << 4)); } static void M134CW(uint32 A, uint8 V) { - setchr1(A, (V & 0xFF) | ((EXPREGS[0] & 0x20) << 3)); + uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; + setchr1r(PRGptr[1] ? (EXPREGS[0] & 0x30) >> 4 : 0, A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); } static DECLFW(M134Write) { @@ -921,13 +927,14 @@ static DECLFW(M134Write) { } static void M134Power(void) { - EXPREGS[0] = 0; + EXPREGS[0] = 0x01; GenMMC3Power(); SetWriteHandler(0x6001, 0x6001, M134Write); + SetWriteHandler(0x6801, 0x6801, M134Write); } static void M134Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = 0x01; MMC3RegReset(); } diff --git a/src/unif.c b/src/unif.c index 567ba59..504a2b8 100644 --- a/src/unif.c +++ b/src/unif.c @@ -504,6 +504,7 @@ static BMAPPING bmap[] = { { "K-3033", BMCK3033_Init, 0 }, { "830134C", BMC830134C_Init, 0 }, { "GN-26", BMCGN26_Init, 0 }, + { "T4A54A", Mapper134_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, From 634eb688c13d747e9c055fcc8ce530401cf3034e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 28 Jun 2019 19:25:35 +0800 Subject: [PATCH 49/74] UNIF: Fix potential crash when accessing non-existing rom banks - As stated, prevent a potential crash on some certain roms using split rom banks. This is done by counting the number of prg/chr banks loaded and using this as limit count during mapper bank switching. - Update related boards. --- src/boards/8157.c | 14 +++++++------- src/boards/ax40g.c | 5 ----- src/boards/bmcgamecard.c | 2 +- src/boards/bmck3088.c | 29 ++++++++++++++++++----------- src/boards/gn26.c | 2 +- src/boards/mmc3.c | 32 ++++++++++++++++++++++++-------- src/boards/resettxrom.c | 16 ++++++++++++++-- src/boards/t-262.c | 7 +++++-- src/cart.c | 5 +++++ src/cart.h | 3 +++ src/unif.c | 14 +++++++++++++- 11 files changed, 91 insertions(+), 38 deletions(-) diff --git a/src/boards/8157.c b/src/boards/8157.c index f62cb8f..1d72957 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -23,6 +23,7 @@ #include "mapinc.h" +static uint8 chip; static uint16 cmdreg; static uint8 reset; static SFORMAT StateRegs[] = @@ -36,13 +37,12 @@ static void Sync(void) { uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; uint32 bank = (cmdreg & 0x01C) >> 2; uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); - /* this fails to load at least one game, which probably has invalid PRG size in header - * (rom is only 512KB but reported as having 3 prg banks with 128k each) */ - /*if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs - setprg16r(base >> 3, 0xC000, lbank); - } else*/ - { + if (PRGptr[1]) { + chip = base >> 3; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg16r(chip, 0x8000, bank); /* for versions with split ROMs */ + setprg16r(chip, 0xC000, lbank); + } else { setprg16(0x8000, base | bank); setprg16(0xC000, base | lbank); } diff --git a/src/boards/ax40g.c b/src/boards/ax40g.c index f3fe1d1..b372574 100644 --- a/src/boards/ax40g.c +++ b/src/boards/ax40g.c @@ -88,8 +88,3 @@ void UNLAX40G_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } - -/*void UNLAX40G_Init(CartInfo *info); // m527 -{ "AX-40G", UNLAX40G_Init, 0 }, -{ "JC-016-2", Mapper205_Init, 0 }, -*/ diff --git a/src/boards/bmcgamecard.c b/src/boards/bmcgamecard.c index e634abd..0cc58af 100644 --- a/src/boards/bmcgamecard.c +++ b/src/boards/bmcgamecard.c @@ -41,7 +41,7 @@ static SFORMAT StateRegs[] = static void Sync(void) { uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1); uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03); - uint8 chip = m350 ? ((mode & 2) ? ((latche >> 5) & 1) : 0) : 0; + uint8 chip = m350 ? ((latche & 0x40) ? ((latche & 0x20) >> 5) : 0) : 0; setchr8(0); setprg8(0x6000, 1); diff --git a/src/boards/bmck3088.c b/src/boards/bmck3088.c index e59c38c..588a65a 100644 --- a/src/boards/bmck3088.c +++ b/src/boards/bmck3088.c @@ -24,24 +24,31 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 chip; + static void BMCK3088CW(uint32 A, uint8 V) { - if (CHRptr[EXPREGS[0] & 7]) - setchr1r(EXPREGS[0] & 7, A, V); - else + if (CHRptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, V); + } else setchr1(A, V | ((EXPREGS[0] & 3) << 7)); } static void BMCK3088PW(uint32 A, uint8 V) { - if (PRGptr[EXPREGS[0] & 7]) { - uint8 chip = EXPREGS[0] & 7; - if (EXPREGS[0] & 8) - setprg32r(chip, 0x8000, ((EXPREGS[0] >> 4) & 3)); - else + if (PRGptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > PRGchip_max) chip &= PRGchip_max; + if (EXPREGS[0] & 8) { + if (A == 0x8000) + setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); + } else setprg8r(chip, A, (V & 0x0F)); } else { - if (EXPREGS[0] & 8) - setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - else + if (EXPREGS[0] & 8) { + if (A == 0x8000) + setprg32(A, ((EXPREGS[0] >> 4) & 3) | (0x0C)); + } else setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); } } diff --git a/src/boards/gn26.c b/src/boards/gn26.c index a712cc2..b55967d 100644 --- a/src/boards/gn26.c +++ b/src/boards/gn26.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * + * Copyright (C) 2019 Libretro 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 diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index b783b67..93d36b6 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -44,6 +44,8 @@ uint8 mmc3opts = 0; uint8 IRQCount, IRQLatch, IRQa; uint8 IRQReload; +static uint8 chip; + static SFORMAT MMC3_StateRegs[] = { { DRegBuf, 8, "REGS" }, @@ -912,12 +914,22 @@ void Mapper119_Init(CartInfo *info) { static void M134PW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; - setprg8r(PRGptr[1] ? (EXPREGS[0] & 3) : 0, A, (V & mask) | ((EXPREGS[0] & 3) << 4)); + if (PRGptr[1]) { + chip = (EXPREGS[0] & 3); + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, (V & mask)); + } else + setprg8(A, (V & mask) | ((EXPREGS[0] & 3) << 4)); } static void M134CW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; - setchr1r(PRGptr[1] ? (EXPREGS[0] & 0x30) >> 4 : 0, A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); + if (CHRptr[1]) { + chip = (EXPREGS[0] & 0x30) >> 4; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, (V & mask)); + } else + setchr1(A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); } static DECLFW(M134Write) { @@ -1200,17 +1212,21 @@ static uint8 block[] = {0, 0, 1, 2}; static void M205PW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); - if (PRGptr[1]) - setprg8r(block[EXPREGS[0]], A, bank); - else + if (PRGptr[1]) { + chip = block[EXPREGS[0]]; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, bank); + } else setprg8(A, EXPREGS[0] << 4 | bank); } static void M205CW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF); - if (PRGptr[1]) - setchr1r(block[EXPREGS[0]], A, bank); - else + if (CHRptr[1]) { + chip = block[EXPREGS[0]]; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, bank); + } else setchr1(A, (EXPREGS[0] << 7) | bank); } diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c index e4bced0..039b5c8 100644 --- a/src/boards/resettxrom.c +++ b/src/boards/resettxrom.c @@ -27,12 +27,24 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 chip; + static void M313CW(uint32 A, uint8 V) { - setchr1r(CHRptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 7) | (V & 0x7F)); + if (CHRptr[1]) { + chip = EXPREGS[0]; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, (V & 0x7F)); + } else + setchr1(A, (EXPREGS[0] << 7) | (V & 0x7F)); } static void M313PW(uint32 A, uint8 V) { - setprg8r(PRGptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 4) | (V & 0x0F)); + if (PRGptr[1]) { + chip = EXPREGS[0]; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, (V & 0x0F)); + } else + setprg8(A, (EXPREGS[0] << 4) | (V & 0x0F)); } static void M313Reset(void) { diff --git a/src/boards/t-262.c b/src/boards/t-262.c index d887ef6..7806d56 100644 --- a/src/boards/t-262.c +++ b/src/boards/t-262.c @@ -20,6 +20,7 @@ #include "mapinc.h" +static uint8 chip; static uint8 bank, base, lock, mirr, mode; static SFORMAT StateRegs[] = { @@ -34,8 +35,10 @@ static SFORMAT StateRegs[] = static void Sync(void) { setchr8(0); if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); - setprg16r(base >> 3, 0xC000, (mode ? bank : 7)); + chip = base >> 3; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg16r(chip, 0x8000, bank); + setprg16r(chip, 0xC000, (mode ? bank : 7)); } else { setprg16(0x8000, base | bank); setprg16(0xC000, base | (mode ? bank : 7)); diff --git a/src/cart.c b/src/cart.c index 911cb0c..d0b7cd1 100644 --- a/src/cart.c +++ b/src/cart.c @@ -53,6 +53,9 @@ static int PRGram[32]; uint8 *PRGptr[32]; uint8 *CHRptr[32]; +uint32 PRGchip_max; +uint32 CHRchip_max; + uint32 PRGsize[32]; uint32 CHRsize[32]; @@ -104,6 +107,8 @@ void ResetCartMapping(void) { for (x = 0; x < 8; x++) { MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x400 * x; } + PRGchip_max = 0; + CHRchip_max = 0; } void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram) { diff --git a/src/cart.h b/src/cart.h index 37eca2c..fbac352 100644 --- a/src/cart.h +++ b/src/cart.h @@ -40,6 +40,9 @@ DECLFW(CartBW); extern uint8 *PRGptr[32]; extern uint8 *CHRptr[32]; +extern uint32 PRGchip_max; +extern uint32 CHRchip_max; + extern uint32 PRGsize[32]; extern uint32 CHRsize[32]; diff --git a/src/unif.c b/src/unif.c index 504a2b8..a7c252b 100644 --- a/src/unif.c +++ b/src/unif.c @@ -73,6 +73,9 @@ static UNIF_HEADER uchead; static uint8 *malloced[32]; static uint32 mallocedsizes[32]; +static uint32 prg_chip_count; +static uint32 chr_chip_count; + static int FixRomSize(uint32 size, uint32 minimum) { uint32 x = 1; @@ -107,6 +110,8 @@ static void ResetUNIF(void) { mirrortodo = 0; memset(&UNIFCart, 0, sizeof(UNIFCart)); UNIFchrrama = 0; + prg_chip_count = 0; + chr_chip_count = 0; } static uint8 exntar[2048]; @@ -272,6 +277,7 @@ static int LoadPRG(FCEUFILE *fp) { FCEU_printf("\n"); */ SetupCartPRGMapping(z, malloced[z], t, 0); + prg_chip_count++; return(1); } @@ -307,6 +313,7 @@ static int LoadCHR(FCEUFILE *fp) { FCEU_printf("\n"); */ SetupCartCHRMapping(z, malloced[16 + z], t, 0); + chr_chip_count++; return(1); } @@ -584,12 +591,17 @@ static int InitializeBoard(void) { if (bmap[x].flags & BMCFLAG_FORCE4) mirrortodo = 4; MooMirroring(); + + PRGchip_max = prg_chip_count - 1; + if (chr_chip_count) + CHRchip_max = chr_chip_count - 1; + bmap[x].init(&UNIFCart); return(1); } x++; } - FCEU_PrintError("Board type not supported.", boardname); + FCEU_PrintError("Board type not supported, '%s'.", boardname); return(0); } From dce349932cce7b7a9aa629382b6b586ed8828306 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 29 Jun 2019 16:09:44 +0800 Subject: [PATCH 50/74] BMC-411120-C/K-3088: Update PRG banking. Combine both boards - Both are functionally the same, only dipswitch is different. - These boards are assigned as NES 2.0 287 mapper in wiki --- src/boards/411120-c.c | 50 +++++++++++++++++++++++---- src/boards/bmck3088.c | 79 ------------------------------------------- 2 files changed, 44 insertions(+), 85 deletions(-) delete mode 100644 src/boards/bmck3088.c diff --git a/src/boards/411120-c.c b/src/boards/411120-c.c index a4c30e0..706f192 100644 --- a/src/boards/411120-c.c +++ b/src/boards/411120-c.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2008 CaH4e3 + * Copyright (C) 2019 Libretro 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 @@ -18,25 +19,51 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* actually cart ID is 811120-C, sorry ;) K-3094 - another ID */ +/* NES 2.0 Mapper 287 + * BMC-411120-C, actually cart ID is 811120-C, sorry ;) K-3094 - another ID + * - 4-in-1 (411120-C) + * - 4-in-1 (811120-C,411120-C) [p4][U] + * + * BMC-K-3088, similar to BMC-411120-C but without jumper or dipswitch + * - 19-in-1(K-3088)(810849-C)(Unl) + */ #include "mapinc.h" #include "mmc3.h" static uint8 reset_flag = 0; +static uint8 chip, isK3088; static void BMC411120CCW(uint32 A, uint8 V) { - setchr1(A, V | ((EXPREGS[0] & 3) << 7)); + if (CHRptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, V); + } else + setchr1(A, V | ((EXPREGS[0] & 3) << 7)); } static void BMC411120CPW(uint32 A, uint8 V) { - if (EXPREGS[0] & (8 | reset_flag)) - setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - else - setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); + if (PRGptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > PRGchip_max) chip &= PRGchip_max; + if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ + if (A == 0x8000) + setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); + } else /* MMC3 Mode */ + setprg8r(chip, A, (V & 0x0F)); + } else { + if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ + if (A == 0x8000) + /* bit 0-1 of register should be used as outer bank regardless of banking modes */ + setprg32(A, ((EXPREGS[0] >> 4) & 3) | ((EXPREGS[0] & 3) << 2)); + } else /* MMC3 Mode */ + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); + } } static DECLFW(BMC411120CLoWrite) { +/* printf("Wr: A:%04x V:%02x\n", A, V); */ EXPREGS[0] = A; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); @@ -55,6 +82,17 @@ static void BMC411120CPower(void) { } void BMC411120C_Init(CartInfo *info) { + isK3088 = 0; + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMC411120CPW; + cwrap = BMC411120CCW; + info->Power = BMC411120CPower; + info->Reset = BMC411120CReset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +void BMCK3088_Init(CartInfo *info) { + isK3088 = 1; GenMMC3_Init(info, 128, 128, 8, 0); pwrap = BMC411120CPW; cwrap = BMC411120CCW; diff --git a/src/boards/bmck3088.c b/src/boards/bmck3088.c deleted file mode 100644 index 588a65a..0000000 --- a/src/boards/bmck3088.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 287 - * similar to BMC-411120-C but without jumper or dipswitch */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chip; - -static void BMCK3088CW(uint32 A, uint8 V) { - if (CHRptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, V); - } else - setchr1(A, V | ((EXPREGS[0] & 3) << 7)); -} - -static void BMCK3088PW(uint32 A, uint8 V) { - if (PRGptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > PRGchip_max) chip &= PRGchip_max; - if (EXPREGS[0] & 8) { - if (A == 0x8000) - setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); - } else - setprg8r(chip, A, (V & 0x0F)); - } else { - if (EXPREGS[0] & 8) { - if (A == 0x8000) - setprg32(A, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - } else - setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); - } -} - -static DECLFW(BMCK3088LoWrite) { - EXPREGS[0] = A; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); -} - -static void BMCK3088Reset(void) { - EXPREGS[0] = 0; - MMC3RegReset(); -} - -static void BMCK3088Power(void) { - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, BMCK3088LoWrite); -} - -void BMCK3088_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 128, 8, 0); - pwrap = BMCK3088PW; - cwrap = BMCK3088CW; - info->Power = BMCK3088Power; - info->Reset = BMCK3088Reset; - AddExState(EXPREGS, 1, 0, "EXPR"); -} From 06c99179be2623f00c60086dc78420afeb84e8b2 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 30 Jun 2019 16:41:17 +0800 Subject: [PATCH 51/74] Add support for Mapper 237 (Teletubies Y2K multicart) --- Makefile.common | 2 +- src/boards/237.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/ines-correct.h | 1 + src/ines.c | 2 +- 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/boards/237.c diff --git a/Makefile.common b/Makefile.common index 88a46ff..4012987 100644 --- a/Makefile.common +++ b/Makefile.common @@ -11,7 +11,7 @@ COREDEFINES += -DPSS_STYLE=1 endif ifeq ($(TUP_CWD),) -FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input +FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) else SOURCES_C = $(CORE_DIR)/boards/*.c $(CORE_DIR)/input/*.c diff --git a/src/boards/237.c b/src/boards/237.c new file mode 100644 index 0000000..e2b784a --- /dev/null +++ b/src/boards/237.c @@ -0,0 +1,91 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 237 - "Teletubbies / Y2K" 420-in-1 pirate multicart. + * Dipswitch settings: + * 0: 42-in-1 + * 1: 5,000-in-1 + * 2: 420-in-1 + * 3: 10,000,000-in-1 (lol) + */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 dipswitch; + +static SFORMAT StateRegs[] = +{ + { ®[0], 1, "REG0" }, + { ®[1], 1, "REG1" }, + { &dipswitch, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (reg[1] & 0x07); + uint8 base = (reg[1] & 0x18) | ((reg[0] & 0x04) << 3); + uint8 mode = (reg[1] & 0xC0) >> 6; + + setchr8(0); + setprg16(0x8000, base | (bank & ~(mode & 1))); + setprg16(0xC000, base | ((mode & 0x02) ? (bank | (mode & 0x01)) : 0x07)); + setmirror(((reg[1] & 0x20) >> 5) ^ 1); +} + +static DECLFW(M237Write) { + if (!(reg[0] & 0x02)) { + reg[0] = A & 0x0F; + reg[1] = (reg[1] & 0x07) | (V & 0xF8); + } + reg[1] = (reg[1] & 0xF8) | (V & 0x07); + Sync(); +} + +static DECLFR(M237Read) { + if (!(reg[0] & 0x02) && (reg[0] & 0x01)) + return dipswitch; + return CartBR(A); +} + +static void M237Power(void) { + Sync(); + SetReadHandler (0x8000, 0xFFFF, M237Read); + SetWriteHandler(0x8000, 0xFFFF, M237Write); +} + +static void M237Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper237_Init(CartInfo *info) { + dipswitch = 0; + if ((info->CRC32) == 0x272709b9) /* Teletubbies Y2K (420-in-1) */ + dipswitch = 2; + info->Power = M237Power; + info->Reset = M237Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index e26aa65..85a8dbe 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -353,6 +353,7 @@ {0x071e4ee8, 114, 0}, /* m114,submapper 1 test rom */ {0xfe3e03a1, 197, -1}, /* Mortal Kombat III Special (YY-030) (Ch) [!] */ {0x9151d311, 197, -1}, /* Mortal Kombat III 28 Peoples (NT-328) (Ch) [!] */ + {0x272709b9, 237, -1}, /* Teletubbies Y2K (420-in-1) */ /* ines mappers that uses iNes 2.0 numbers */ diff --git a/src/ines.c b/src/ines.c index 8edac57..656337a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -629,7 +629,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"BMC MAXI", 234, Mapper234_Init}, {(uint8_t*)"", 235, Mapper235_Init}, /* {(uint8_t*)"", 236, Mapper236_Init}, */ -/* {(uint8_t*)"", 237, Mapper237_Init}, */ + {(uint8_t*)"Teletubbies / Y2K", 237, Mapper237_Init}, {(uint8_t*)"UNL6035052", 238, UNL6035052_Init}, /* {(uint8_t*)"", 239, Mapper239_Init}, */ {(uint8_t*)"", 240, Mapper240_Init}, From 7e9b3b146d233fd09b2ab1b99dbb7819f1784621 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 2 Jul 2019 19:34:55 +0800 Subject: [PATCH 52/74] UNIF: Initial implementation of game overrides (move exiting ones out of mapper code) --- src/boards/datalatch.c | 60 +++++++++++++++++++++-------------- src/boards/resetnromxin1.c | 15 ++------- src/cart.h | 1 + src/unif.c | 65 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 1846bb7..c221310 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -153,27 +153,29 @@ static void CNROMSync(void) { } void CNROM_Init(CartInfo *info) { + unsigned _no_busc, _busc; + + _busc = 1; /* by default, CNROM is set to emulate bus conflicts to all games */ + _no_busc = 0; + + if (GameInfo->cspecial == 1) + _no_busc = 1; + /* TODO: move these to extended database when implemented. */ - int _busc, x; - uint64 partialmd5 = 0; - _busc = 1; - for (x = 0; x < 8; x++) - partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); - if (partialmd5 == 0x117181328eb1ad23LL) /* 75 Bingo (Sachen-English) [U].unf */ - _busc = 0; - else - switch (info->CRC32) { - case 0xf283cf58: /* Colorful Dragon (Asia) (PAL) (Unl).nes */ - case 0x2915faf0: /* Incantation (Asia) (Unl).nes */ - case 0xebd0644d: /* Dao Shuai (Asia) (Unl).nes */ - case 0x8f154a0d: /* Pu Ke Jing Ling (China) (Unl).nes */ - case 0xd04a40e6: /* Bingo 75 (Asia) (Unl).nes */ - case 0xe41b440f: /* Sidewinder (Joy Van) */ - case 0xb0c871c5: /* Wei Lai Xiao Zi (Joy Van) */ - case 0xb3be2f71: /* Yanshan Chess (Unl) */ - _busc = 0; - break; + switch (info->CRC32) { + case 0xf283cf58: /* Colorful Dragon (Asia) (PAL) (Unl).nes */ + case 0x2915faf0: /* Incantation (Asia) (Unl).nes */ + case 0xebd0644d: /* Dao Shuai (Asia) (Unl).nes */ + case 0x8f154a0d: /* Pu Ke Jing Ling (China) (Unl).nes */ + case 0xd04a40e6: /* Bingo 75 (Asia) (Unl).nes */ + case 0xe41b440f: /* Sidewinder (Joy Van) */ + case 0xb0c871c5: /* Wei Lai Xiao Zi (Joy Van) */ + case 0xb3be2f71: /* Yanshan Chess (Unl) */ + _no_busc = 1; + break; } + + if (_no_busc == 1) _busc = 0; Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, _busc); } @@ -495,22 +497,32 @@ void Mapper241_Init(CartInfo *info) { * 16 bankswitching mode and normal mirroring... But there is no any * correlations between modes and they can be used in one mapper code. */ - +static int A65ASsubmapper; static void BMCA65ASSync(void) { if (latche & 0x40) setprg32(0x8000, (latche >> 1) & 0x0F); else { - setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); - setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + if (A65ASsubmapper == 1) { + setprg16(0x8000, ((latche & 0x38) >> 0) | (latche & 7)); + setprg16(0xC000, ((latche & 0x38) >> 0) | 7); + } else { + setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); + setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + } } setchr8(0); if (latche & 0x80) setmirror(MI_0 + (((latche >> 5) & 1))); - else - setmirror(((latche >> 3) & 1) ^ 1); + else { + if (A65ASsubmapper == 1) /* added as workaround since games for this cart uses vertical mirroring */ + setmirror(MI_V); + else + setmirror(((latche >> 3) & 1) ^ 1); + } } void BMCA65AS_Init(CartInfo *info) { + A65ASsubmapper = info->submapper; /* not a real submapper */ Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); } diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c index d17bc81..76c6e84 100644 --- a/src/boards/resetnromxin1.c +++ b/src/boards/resetnromxin1.c @@ -18,7 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* BMC-RESETNROM-XIN1 +/* NES 2.0 Mapper 343 + * BMC-RESETNROM-XIN1 * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee * @@ -58,18 +59,6 @@ static void StateRestore(int version) { } void BMCRESETNROMXIN1_Init(CartInfo *info) { - uint8 x; - uint64 partialmd5 = 0; - - for (x = 0; x < 8; x++) - partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); - - /* Mirroring override - these boards have incorrect mirroring for some reasons in their headers */ - if (partialmd5 == 0x616851e56946893bLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ - SetupCartMirroring(1, 1, NULL); - else if (partialmd5 == 0x4cd729b5ae23a3cfLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ - SetupCartMirroring(0, 1, NULL); - limit = 0x01; info->Power = BMCRESETNROMXIN1Power; info->Reset = BMCRESETNROMXIN1Reset; diff --git a/src/cart.h b/src/cart.h index fbac352..16ab243 100644 --- a/src/cart.h +++ b/src/cart.h @@ -11,6 +11,7 @@ typedef struct { /* Set by iNES/UNIF loading code. */ int mapper; /* mapper used */ + int submapper; /* submapper used */ /* TODO: */ int mirror; /* As set in the header or chunk. * iNES/UNIF specific. Intended * to help support games like "Karnov" diff --git a/src/unif.c b/src/unif.c index a7c252b..6072129 100644 --- a/src/unif.c +++ b/src/unif.c @@ -60,6 +60,8 @@ CartInfo UNIFCart; static int vramo; static int mirrortodo; +static int submapper; +static int cspecial; static uint8 *boardname; static uint8 *sboardname; @@ -317,6 +319,65 @@ static int LoadCHR(FCEUFILE *fp) { return(1); } +#define NO_BUSC 1 + +struct _unif_db { + uint64 partialMD5; + char *boardname; + int submapper; + int mirroring; + int special; /* TODO: for bus conflicts, set 1 for no bus_conflict */ +}; + +static struct _unif_db unif_db[] = { + { 0x8ebad077d08e6c78ULL, "A65AS", 1, -1 }, /* 3-in-1 (N080) [p1][U][!], not a real submapper */ + { 0x117181328eb1ad23ULL, "CNROM", 0, MI_H, NO_BUSC }, /* 75 Bingo (Sachen-English) [U] */ + { 0x616851e56946893bULL, "RESETNROM-XIN1", 0, MI_V }, /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ + { 0x4cd729b5ae23a3cfULL, "RESETNROM-XIN1", 0, MI_H }, /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ + + { 0, NULL, -1, -1, -1 } /* end of the line */ +}; + +static void CheckHashInfo(void) { + unsigned x = 0; + uint64 partialMD5 = 0; + + for (x = 0; x < 8; x++) + partialMD5 |= (uint64)UNIFCart.MD5[15 - x] << (x * 8); + + x = 0; + do { + if (partialMD5 == unif_db[x].partialMD5) { + FCEU_printf("\n"); + FCEU_PrintError(" The UNIF header contains incorrect information.\n"); + FCEU_PrintError(" For now, the information will be corrected in RAM.\n"); + if (unif_db[x].boardname != NULL && strcmp((char*)unif_db[x].boardname, (char*)sboardname) != 0) { + FCEU_printf(" Boardname should be set to %s\n", unif_db[x].boardname); + sboardname = unif_db[x].boardname; + } + if (unif_db[x].submapper >= 0 && unif_db[x].submapper != submapper) { + FCEU_PrintError(" Submapper should be set to %d\n", unif_db[x].submapper); + submapper = unif_db[x].submapper; + } + if (unif_db[x].mirroring >= 0 && unif_db[x].mirroring != mirrortodo) { + static char *stuffo[6] = { "Horizontal", "Vertical", "$2000", "$2400", "\"Four-screen\"", "Controlled by Mapper Hardware" }; + FCEU_PrintError(" Mirroring should be set to %s\n", stuffo[unif_db[x].mirroring]); + mirrortodo = unif_db[x].mirroring; + } + if (unif_db[x].special >= 0 && unif_db[x].special != cspecial) { + if (!(strcmp((char*)sboardname, "CNROM"))) { + FCEU_PrintError(" Special flags applied, No bus conflict.\n"); + cspecial = unif_db[x].special; + } + } + /* todo special case aka, dipswitches, busc-like in fk23c/a, etc */ + FCEU_printf("\n"); + } + x++; + } while (unif_db[x].partialMD5 > 0); + +} + #define BMCFLAG_FORCE4 0x01 #define BMCFLAG_16KCHRR 0x02 #define BMCFLAG_32KCHRR 0x04 @@ -595,6 +656,8 @@ static int InitializeBoard(void) { PRGchip_max = prg_chip_count - 1; if (chr_chip_count) CHRchip_max = chr_chip_count - 1; + UNIFCart.submapper = submapper; + GameInfo->cspecial = cspecial; bmap[x].init(&UNIFCart); return(1); @@ -655,6 +718,8 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5)); } + CheckHashInfo(); + if (!InitializeBoard()) goto aborto; From 51199e59d771124860d81d6fe4c5b0a396581773 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 5 Jul 2019 22:46:22 +0800 Subject: [PATCH 53/74] NES 2.0: Add preliminary support for iNES 2.0 format Currently reads and sets the following: - mapper number up to 4095, prg rom size, chr rom size - chr ram (volatile + non-volatile), region (ntsc, pal, dendy or multi-region) todo: submapper handling, w-ram and prg nvram at least... --- src/boards/unrom512.c | 6 +- src/cart.h | 8 +- src/ines.c | 241 +++++++++++++++++++++++++++--------------- src/ines.h | 9 +- src/unif.c | 2 +- 5 files changed, 176 insertions(+), 90 deletions(-) diff --git a/src/boards/unrom512.c b/src/boards/unrom512.c index 59ac51d..5e703b0 100644 --- a/src/boards/unrom512.c +++ b/src/boards/unrom512.c @@ -217,9 +217,9 @@ void UNROM512_Init(CartInfo *info) { flash_bank = 0; flash_save = info->battery; - if (info->vram_size == 8192) + if (info->chrRam == 8192) chrram_mask = 0; - else if (info->vram_size == 16384) + else if (info->chrRam == 16384) chrram_mask = 0x20; else chrram_mask = 0x60; @@ -236,7 +236,7 @@ void UNROM512_Init(CartInfo *info) { SetupCartMirroring(MI_0, 0, NULL); break; case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */ - SetupCartMirroring(4, 1, VROM + (info->vram_size - 8192)); + SetupCartMirroring(4, 1, VROM + (info->chrRam - 8192)); break; } bus_conflict = !info->battery; diff --git a/src/cart.h b/src/cart.h index 16ab243..66f3e83 100644 --- a/src/cart.h +++ b/src/cart.h @@ -10,6 +10,7 @@ typedef struct { uint32 SaveGameLen[4]; /* How much memory to save/load. */ /* Set by iNES/UNIF loading code. */ + int iNES2; /* iNES version */ int mapper; /* mapper used */ int submapper; /* submapper used */ /* TODO: */ int mirror; /* As set in the header or chunk. @@ -19,7 +20,12 @@ typedef struct { * set to mapper 4. */ int battery; /* Presence of an actual battery. */ - int vram_size; + int prgRam; /* prg ram size (volatile) */ + int chrRam; /* chr ram size (volatile) */ + int prgRam_battery; /* prg ram size (non-volatile or battery backed) */ + int chrRam_battery; /* chr ram size (non-volatile or battery backed) */ + int region; /* video system timing (ntsc, pal, dendy */ + uint8 MD5[16]; uint32 CRC32; /* Should be set by the iNES/UNIF loading * code, used by mapper/board code, maybe diff --git a/src/ines.c b/src/ines.c index 656337a..68371f2 100644 --- a/src/ines.c +++ b/src/ines.c @@ -57,7 +57,9 @@ uint32 VROM_size = 0; static int CHRRAMSize = -1; static int iNES_Init(int num); +static int iNES2 = 0; static int MapperNo = 0; +static int subMapper = 0; static DECLFR(TrainerRead) { return(trainerpoo[A & 0x1FF]); @@ -376,7 +378,7 @@ static void CheckHInfo(void) { if (tofix & 8) strcat(gigastr, "This game should not have any CHR ROM. "); strcat(gigastr, "\n"); - FCEU_printf("%s", gigastr); + FCEU_printf("%s\n", gigastr); } } @@ -661,14 +663,19 @@ static BMAPPINGLocal bmap[] = { int iNESLoad(const char *name, FCEUFILE *fp) { struct md5_context md5; - char* mappername; - uint32 mappertest; + char* mappername = NULL; + uint32 filesize = fp->fp->size; + uint32 mappertest = 0; + uint32 prgRom = 0; + uint32 chrRom = 0; if (FCEU_fread(&head, 1, 16, fp) != 16) return 0; + filesize -= 16; /* remove header size from total size */ + if (memcmp(&head, "NES\x1a", 4)) { - FCEU_PrintError("Missing header or invalid iNES format file!\n"); + FCEU_PrintError("Not an iNES file!\n"); return 0; } @@ -689,20 +696,51 @@ int iNESLoad(const char *name, FCEUFILE *fp) { memset((char*)(&head) + 0xA, 0, 0x6); } - MapperNo = (head.ROM_type >> 4); - MapperNo |= (head.ROM_type2 & 0xF0); - if (head.ROM_type & 8) { - Mirroring = 2; - } else - Mirroring = (head.ROM_type & 1); + Mirroring = 0; + ROM_size = 0; + VROM_size = 0; + iNES2 = 0; + MapperNo = 0; + subMapper = 0; - if (!head.ROM_size) - ROM_size = 256; - else - ROM_size = uppow2(head.ROM_size); + MapperNo = (head.ROM_type >> 4) | (head.ROM_type2 & 0xF0); + Mirroring = (head.ROM_type & 8) ? 2 : (head.ROM_type & 1); + prgRom = head.ROM_size; + chrRom = head.VROM_size; - VROM_size = uppow2(head.VROM_size); + if ((head.ROM_type2 & 0x0C) == 0x08) { + iNES2 = 1; + MapperNo |= ((uint32)head.ROM_type3 << 8) & 0xF00; + prgRom |= ((uint32)head.upper_PRG_CHR_size << 8) & 0xF00; + chrRom |= ((uint32)head.upper_PRG_CHR_size << 4) & 0xF00; + subMapper = head.ROM_type3 >> 4 & 0x0F; + iNESCart.prgRam = (head.PRGRAM_size & 0x0F) ? (64 << (head.PRGRAM_size & 0x0F)) : 0; + iNESCart.chrRam = (head.CHRRAM_size & 0x0F) ? (64 << (head.CHRRAM_size & 0x0F)) : 0; + iNESCart.prgRam_battery = (head.PRGRAM_size & 0xF0) ? (64 << ((head.PRGRAM_size & 0xF0) >> 4)) : 0; + iNESCart.chrRam_battery = (head.CHRRAM_size & 0xF0) ? (64 << ((head.CHRRAM_size & 0xF0) >> 4)) : 0; + iNESCart.region = head.Region; + } else { + if (!prgRom) + prgRom = 256; + } + + if (head.ROM_type & 4) { /* Trainer */ + trainerpoo = (uint8*)FCEU_gmalloc(512); + FCEU_fread(trainerpoo, 512, 1, fp); + filesize -= 512; + } + + if (((prgRom * 0x4000) + (chrRom * 0x2000)) > filesize) { + FCEU_PrintError(" File length is too short to contain all data reported from header by %llu\n", ((prgRom * 0x4000) + (chrRom * 0x2000)) - filesize); + return 0; + } else if (((prgRom * 0x4000) + (chrRom * 0x2000)) < filesize) + FCEU_PrintError(" File contains %llu bytes of unused data\n", filesize - ((prgRom * 0x4000) + (chrRom * 0x2000))); + + ROM_size = uppow2(prgRom); + + if (chrRom) + VROM_size = uppow2(chrRom); if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL) return 0; @@ -717,36 +755,23 @@ int iNESLoad(const char *name, FCEUFILE *fp) { memset(VROM, 0xFF, VROM_size << 13); } - if (head.ROM_type & 4) { /* Trainer */ - trainerpoo = (uint8*)FCEU_gmalloc(512); - FCEU_fread(trainerpoo, 512, 1, fp); - } - ResetCartMapping(); ResetExState(0, 0); SetupCartPRGMapping(0, ROM, ROM_size << 14, 0); - if (head.ROM_size) - FCEU_fread(ROM, 0x4000, head.ROM_size, fp); - else - FCEU_fread(ROM, 0x4000, ROM_size, fp); + FCEU_fread(ROM, 0x4000, prgRom, fp); if (VROM_size) - FCEU_fread(VROM, 0x2000, VROM_size, fp); + FCEU_fread(VROM, 0x2000, chrRom, fp); md5_starts(&md5); - if (head.ROM_size) { - md5_update(&md5, ROM, head.ROM_size << 14); - iNESGameCRC32 = CalcCRC32(0, ROM, head.ROM_size << 14); - } else { - md5_update(&md5, ROM, ROM_size << 14); - iNESGameCRC32 = CalcCRC32(0, ROM, ROM_size << 14); - } + md5_update(&md5, ROM, prgRom << 14); + iNESGameCRC32 = CalcCRC32(0, ROM, prgRom << 14); if (VROM_size) { - iNESGameCRC32 = CalcCRC32(iNESGameCRC32, VROM, VROM_size << 13); - md5_update(&md5, VROM, VROM_size << 13); + iNESGameCRC32 = CalcCRC32(iNESGameCRC32, VROM, chrRom << 13); + md5_update(&md5, VROM, chrRom << 13); } md5_finish(&md5, iNESCart.MD5); memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5)); @@ -755,14 +780,7 @@ int iNESLoad(const char *name, FCEUFILE *fp) { SetInput(); CheckHInfo(); - mappername = "Not Listed"; - for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { - if (bmap[mappertest].number == MapperNo) { - mappername = (char*)bmap[mappertest].name; - break; - } - } { int x; uint64 partialmd5 = 0; @@ -787,43 +805,92 @@ int iNESLoad(const char *name, FCEUFILE *fp) { else SetupCartMirroring(Mirroring & 1, (Mirroring & 4) >> 2, 0); + iNESCart.iNES2 = iNES2; + iNESCart.mapper = MapperNo; + iNESCart.submapper = subMapper; iNESCart.battery = (head.ROM_type & 2) ? 1 : 0; iNESCart.mirror = Mirroring; + mappername = "Not Listed"; + + for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { + if (bmap[mappertest].number == MapperNo) { + mappername = (char*)bmap[mappertest].name; + break; + } + } + + if (iNES2) FCEU_printf(" NES 2.0 extended iNES.\n"); FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); - FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256); - FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); + FCEU_printf(" PRG ROM: %3d x 16KiB\n", prgRom); + FCEU_printf(" CHR ROM: %3d x 8KiB\n", chrRom); - if (!iNES_Init(MapperNo)) - FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo); - iNESCart.mapper = MapperNo; + if (iNES2) { + const char *tv_region[] = { "NTSC", "PAL", "Multi-region", "Dendy" }; + unsigned PRGRAM = iNESCart.prgRam + iNESCart.prgRam_battery; + unsigned CHRRAM = iNESCart.chrRam + iNESCart.chrRam_battery; - FCEU_printf(" \n"); - FCEU_printf(" Mapper #: %3d\n", MapperNo); - FCEU_printf(" Mapper name: %s\n", mappername); - FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); - FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); - FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + FCEU_printf(" Mapper #: %3d\n", MapperNo); + FCEU_printf(" Sub Mapper #: %3d\n", subMapper); + FCEU_printf(" Mapper name: %s\n", mappername); + if (PRGRAM || CHRRAM) { + FCEU_printf(" PRG RAM: %d KiB\n", PRGRAM / 1024); + FCEU_printf(" CHR RAM: %d KiB\n", CHRRAM / 1024); + if (head.ROM_type & 0x02) { + FCEU_printf(" PRG RAM backed by battery: %d KiB\n", iNESCart.prgRam_battery / 1024); + FCEU_printf(" CHR RAM backed by battery: %d KiB\n", iNESCart.chrRam_battery / 1024); + } + } + FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); + FCEU_printf(" System: %s\n", tv_region[(iNESCart.region & 3)]); + FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + } else { + FCEU_printf(" Mapper #: %3d\n", MapperNo); + FCEU_printf(" Mapper name: %s\n", mappername); + FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); + FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); + FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + } + + if (!iNES_Init(MapperNo)) { + FCEU_printf("\n"); + FCEU_PrintError(" iNES mapper #%d is not supported at all.\n", MapperNo); + return 0; + } GameInterface = iNESGI; - FCEU_printf("\n"); - if (strstr(name, "(E)") || strstr(name, "(e)") - || strstr(name, "(Europe)") || strstr(name, "(PAL)") - || strstr(name, "(F)") || strstr(name, "(f)") - || strstr(name, "(G)") || strstr(name, "(g)") - || strstr(name, "(I)") || strstr(name, "(i)") - || strstr(name, "(S)") || strstr(name, "(s)") - || strstr(name, "(France)") || strstr(name, "(Germany)") - || strstr(name, "(Italy)") || strstr(name, "(Spain)") - || strstr(name, "(Sweden)") || strstr(name, "(Sw)") - || strstr(name, "(Australia)") || strstr(name, "(A)") - || strstr(name, "(a)")) { - FCEUI_SetVidSystem(1); + if (iNES2) { + switch (iNESCart.region & 0x03) { + /* 0: RP2C02 ("NTSC NES") + * 1: RP2C07 ("Licensed PAL NES") + * 2: Multiple-region + * 3: UMC 6527P ("Dendy") + */ + case 0: case 2: FCEUI_SetVidSystem(0); break; + case 1: FCEUI_SetVidSystem(1); break; + case 3: dendy = 1; FCEUI_SetVidSystem(0); break; + } + } else { + if (strstr(name, "(E)") || strstr(name, "(e)") || + strstr(name, "(Europe)") || strstr(name, "(PAL)") || + strstr(name, "(F)") || strstr(name, "(f)") || + strstr(name, "(G)") || strstr(name, "(g)") || + strstr(name, "(I)") || strstr(name, "(i)") || + strstr(name, "(S)") || strstr(name, "(s)") || + strstr(name, "(France)") || strstr(name, "(Germany)") || + strstr(name, "(Italy)") || strstr(name, "(Spain)") || + strstr(name, "(Sweden)") || strstr(name, "(Sw)") || + strstr(name, "(Australia)") || strstr(name, "(A)") || + strstr(name, "(a)")) { + iNESCart.region = 1; + FCEUI_SetVidSystem(1); + } else { + iNESCart.region = 0; + FCEUI_SetVidSystem(0); + } } - else - FCEUI_SetVidSystem(0); return 1; } @@ -840,24 +907,30 @@ static int iNES_Init(int num) { if (num == tmp->number) { UNIFchrrama = 0; /* need here for compatibility with UNIF mapper code */ if (!VROM_size) { - switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */ - case 13: CHRRAMSize = 16 * 1024; break; - case 6: - case 28: - case 29: - case 30: - case 45: - case 96: CHRRAMSize = 32 * 1024; break; - case 176: CHRRAMSize = 128 * 1024; break; - default: CHRRAMSize = 8 * 1024; break; + if (iNESCart.iNES2) { + CHRRAMSize = iNESCart.chrRam + iNESCart.chrRam_battery; + } else { + switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */ + case 13: CHRRAMSize = 16 * 1024; break; + case 6: + case 28: + case 29: + case 30: + case 45: + case 96: CHRRAMSize = 32 * 1024; break; + case 176: CHRRAMSize = 128 * 1024; break; + default: CHRRAMSize = 8 * 1024; break; + } + iNESCart.chrRam = CHRRAMSize; + FCEU_printf(" CHR-RAM: %3d KiB\n", CHRRAMSize / 1024); + } + if (CHRRAMSize) { /* TODO: CHR-RAM are sometimes handled in mappers e.g. MMC1 using submapper 1/2/4 and CHR-RAM can be zero here */ + if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0; + FCEU_MemoryRand(VROM, CHRRAMSize); + UNIFchrrama = VROM; + SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); + AddExState(VROM, CHRRAMSize, 0, "CHRR"); } - iNESCart.vram_size = CHRRAMSize; - if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0; - FCEU_MemoryRand(VROM, CHRRAMSize); - UNIFchrrama = VROM; - SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); - AddExState(VROM, CHRRAMSize, 0, "CHRR"); - FCEU_printf(" CHR RAM: %3d x 1KiB\n", CHRRAMSize / 1024); } if (head.ROM_type & 8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); diff --git a/src/ines.h b/src/ines.h index 1d6dee7..2b29b29 100644 --- a/src/ines.h +++ b/src/ines.h @@ -28,7 +28,14 @@ typedef struct { uint8 VROM_size; uint8 ROM_type; uint8 ROM_type2; - uint8 reserve[8]; + uint8 ROM_type3; + uint8 upper_PRG_CHR_size; + uint8 PRGRAM_size; + uint8 CHRRAM_size; + uint8 Region; + uint8 VS_hardware; + uint8 MiscRoms; + uint8 ExpDevice; } iNES_HEADER; extern uint8 *ROM; diff --git a/src/unif.c b/src/unif.c index 6072129..ce3c61a 100644 --- a/src/unif.c +++ b/src/unif.c @@ -353,7 +353,7 @@ static void CheckHashInfo(void) { FCEU_PrintError(" For now, the information will be corrected in RAM.\n"); if (unif_db[x].boardname != NULL && strcmp((char*)unif_db[x].boardname, (char*)sboardname) != 0) { FCEU_printf(" Boardname should be set to %s\n", unif_db[x].boardname); - sboardname = unif_db[x].boardname; + sboardname = (uint8*)unif_db[x].boardname; } if (unif_db[x].submapper >= 0 && unif_db[x].submapper != submapper) { FCEU_PrintError(" Submapper should be set to %d\n", unif_db[x].submapper); From 8f19234f55f32e2804424e5e14aa02e8620494ee Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 8 Jul 2019 21:42:20 +0800 Subject: [PATCH 54/74] Start assigning NES 2.0 mapper numbers to UNIF boards (256+ boards) --- src/ines.c | 96 +++++++++++++- src/unif.c | 384 +++++++++++++++++++++++++++-------------------------- 2 files changed, 283 insertions(+), 197 deletions(-) diff --git a/src/ines.c b/src/ines.c index 68371f2..1db9530 100644 --- a/src/ines.c +++ b/src/ines.c @@ -651,14 +651,96 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"", 254, Mapper254_Init}, {(uint8_t*)"", 255, Mapper255_Init}, /* Duplicate of M225? */ - {(uint8_t*)"BMC-HPxx", 260, BMCHPxx_Init}, - {(uint8_t*)"UNL-SHERO", 262, UNLSHeroes_Init}, + /* -------------- ----NES 2.0 -------------------------- */ + + /* NES 2.0 BOARDS THAT DO NOT HAVE UNIF ASSOCIATION */ + {(uint8_t*)"OK-411", 361, GN45_Init}, /* OK-411 is emulated together with GN-45 */ {(uint8_t*)"HUMMER/JY-052", 281, Mapper281_Init}, - {(uint8_t*)"GN-45", 366, GN45_Init}, - {(uint8_t*)"DREAMTECH01", 521, DreamTech01_Init}, + {(uint8_t*)"GN-45", 366, GN45_Init}, - {(uint8_t*)"", 0, NULL} + /* UNIF to NES 2.0 BOARDS */ + + {(uint8_t*)"OneBus", 256, UNLOneBus_Init }, + {(uint8_t*)"158B", 258, UNL158B_Init }, + {(uint8_t*)"F-15", 259, BMCF15_Init }, + {(uint8_t*)"HPxx / HP2018-A", 260, BMCHPxx_Init }, + {(uint8_t*)"810544-C-A1", 261, BMC810544CA1_Init }, + {(uint8_t*)"SHERO", 262, UNLSHeroes_Init }, + {(uint8_t*)"KOF97", 263, UNLKOF97_Init }, + {(uint8_t*)"YOKO", 264, UNLYOKO_Init }, + {(uint8_t*)"T-262", 265, BMCT262_Init }, + {(uint8_t*)"CITYFIGHT", 266, UNLCITYFIGHT_Init }, + {(uint8_t*)"COOLBOY", 268, COOLBOY_Init }, +/* {(uint8_t*)"MINDKIDS", 268, MINDKIDS_Init }, */ + {(uint8_t*)"80013-B", 274, BMC80013B_Init }, + {(uint8_t*)"GS-2004", 283, BMCGS2004_Init }, +/* {(uint8_t*)"GS-2013", 283, BMCGS2013_Init }, */ + {(uint8_t*)"A65AS", 285, BMCA65AS_Init }, + {(uint8_t*)"BS-5", 286, BMCBS5_Init }, + {(uint8_t*)"411120-C", 287, BMC411120C_Init }, +/* {(uint8_t*)"K-3088", 287, BMCK3088_Init }, */ + {(uint8_t*)"60311C", 289, BMC60311C_Init }, + {(uint8_t*)"NTD-03", 290, BMCNTD03_Init }, + {(uint8_t*)"DRAGONFIGHTER", 292, UNLBMW8544_Init }, + {(uint8_t*)"13in1JY110", 295, BMC13in1JY110_Init }, + {(uint8_t*)"TF1201", 298, UNLTF1201_Init }, + {(uint8_t*)"11160", 299, BMC11160_Init }, + {(uint8_t*)"190in1", 300, BMC190in1_Init }, + {(uint8_t*)"8157", 301, UNL8157_Init }, + {(uint8_t*)"KS7057", 302, UNLKS7057_Init }, + {(uint8_t*)"KS7017", 303, UNLKS7017_Init }, + {(uint8_t*)"SMB2J", 304, UNLSMB2J_Init }, + {(uint8_t*)"KS7031", 305, UNLKS7031_Init }, + {(uint8_t*)"KS7016", 306, UNLKS7016_Init }, + {(uint8_t*)"KS7037", 307, UNLKS7037_Init }, + {(uint8_t*)"TH2131-1", 308, UNLTH21311_Init }, + {(uint8_t*)"LH51", 309, LH51_Init }, + {(uint8_t*)"KS7013B", 312, UNLKS7013B_Init }, + {(uint8_t*)"RESET-TXROM", 313, BMCRESETTXROM_Init }, + {(uint8_t*)"64in1NoRepeat", 314, BMC64in1nr_Init }, + {(uint8_t*)"830134C", 315, BMC830134C_Init }, + {(uint8_t*)"HP898F", 319, BMCHP898F_Init }, + {(uint8_t*)"830425C-4391T", 320, BMC830425C4391T_Init }, + {(uint8_t*)"K-3033", 322, BMCK3033_Init }, + {(uint8_t*)"FARID_SLROM_8-IN-1", 323, FARIDSLROM8IN1_Init }, + {(uint8_t*)"FARID_UNROM_8-IN-1", 324, FARIDUNROM_Init }, + {(uint8_t*)"MALISB", 325, UNLMaliSB_Init }, + {(uint8_t*)"10-24-C-A1", 327, BMC1024CA1_Init }, + {(uint8_t*)"RT-01", 328, UNLRT01_Init }, + {(uint8_t*)"EDU2000", 329, UNLEDU2000_Init }, + {(uint8_t*)"12-IN-1", 331, BMC12IN1_Init }, + {(uint8_t*)"WS", 332, BMCWS_Init }, + {(uint8_t*)"NEWSTAR-GRM070-8IN1", 333, BMC8IN1_Init }, + {(uint8_t*)"CTC-09", 335, BMCCTC09_Init }, + {(uint8_t*)"K-3046", 336, BMCK3046_Init }, + {(uint8_t*)"CTC-12IN1", 337, BMCCTC12IN1_Init }, + {(uint8_t*)"SA005-A", 338, BMCSA005A_Init }, + {(uint8_t*)"K-3006", 339, BMCK3006_Init }, + {(uint8_t*)"K-3036", 340, BMCK3036_Init }, + {(uint8_t*)"TJ-03", 341, BMCTJ03_Init }, + {(uint8_t*)"GN-26", 344, BMCGN26_Init }, + {(uint8_t*)"L6IN1", 345, BMCL6IN1_Init }, + {(uint8_t*)"KS7012", 346, UNLKS7012_Init }, + {(uint8_t*)"KS7030", 347, UNLKS7030_Init }, + {(uint8_t*)"830118C", 348, BMC830118C_Init }, + {(uint8_t*)"G-146", 349, BMCG146_Init }, + {(uint8_t*)"891227", 350, BMC891227_Init }, + {(uint8_t*)"3D-BLOCK", 355, UNL3DBlock_Init }, + {(uint8_t*)"SA-9602B", 513, SA9602B_Init }, + {(uint8_t*)"DANCE2000", 518, UNLD2000_Init }, + {(uint8_t*)"EH8813A", 519, UNLEH8813A_Init }, + {(uint8_t*)"DREAMTECH01", 521, DreamTech01_Init }, + {(uint8_t*)"LH10", 522, LH10_Init }, + {(uint8_t*)"900218", 524, BTL900218_Init }, + {(uint8_t*)"KS7021A", 525, UNLKS7021A_Init }, + {(uint8_t*)"BJ-56", 526, UNLBJ56_Init }, + {(uint8_t*)"AX-40G", 527, UNLAX40G_Init }, + {(uint8_t*)"T-230", 529, UNLT230_Init }, + {(uint8_t*)"AX5705", 530, UNLAX5705_Init }, + {(uint8_t*)"LH53", 535, LH53_Init }, + + {(uint8_t*)"", 0, NULL} }; int iNESLoad(const char *name, FCEUFILE *fp) { @@ -917,8 +999,10 @@ static int iNES_Init(int num) { case 29: case 30: case 45: - case 96: CHRRAMSize = 32 * 1024; break; + case 96: + case 513: CHRRAMSize = 32 * 1024; break; case 176: CHRRAMSize = 128 * 1024; break; + case 268: CHRRAMSize = 256 * 1024; break; default: CHRRAMSize = 8 * 1024; break; } iNESCart.chrRam = CHRRAMSize; diff --git a/src/unif.c b/src/unif.c index ce3c61a..7f8e672 100644 --- a/src/unif.c +++ b/src/unif.c @@ -47,6 +47,7 @@ typedef struct { typedef struct { char *name; + int ines_mapper; void (*init)(CartInfo *); int flags; } BMAPPING; @@ -378,6 +379,7 @@ static void CheckHashInfo(void) { } +#define NO_INES -1 #define BMCFLAG_FORCE4 0x01 #define BMCFLAG_16KCHRR 0x02 #define BMCFLAG_32KCHRR 0x04 @@ -385,201 +387,201 @@ static void CheckHashInfo(void) { #define BMCFLAG_256KCHRR 0x10 static BMAPPING bmap[] = { - { "11160", BMC11160_Init, 0 }, - { "12-IN-1", BMC12IN1_Init, 0 }, - { "13in1JY110", BMC13in1JY110_Init, 0 }, - { "190in1", BMC190in1_Init, 0 }, - { "22211", UNL22211_Init, 0 }, - { "3D-BLOCK", UNL3DBlock_Init, 0 }, - { "411120-C", BMC411120C_Init, 0 }, - { "42in1ResetSwitch", Mapper226_Init, 0 }, - { "43272", UNL43272_Init, 0 }, - { "603-5052", UNL6035052_Init, 0 }, - { "64in1NoRepeat", BMC64in1nr_Init, 0 }, - { "70in1", BMC70in1_Init, 0 }, - { "70in1B", BMC70in1B_Init, 0 }, - { "810544-C-A1", BMC810544CA1_Init, 0 }, - { "8157", UNL8157_Init, 0 }, - { "8237", UNL8237_Init, 0 }, - { "8237A", UNL8237A_Init, 0 }, - { "830118C", BMC830118C_Init, 0 }, - { "A65AS", BMCA65AS_Init, 0 }, - { "AC08", AC08_Init, 0 }, - { "ANROM", ANROM_Init, 0 }, - { "AX5705", UNLAX5705_Init, 0 }, - { "BB", UNLBB_Init, 0 }, - { "BS-5", BMCBS5_Init, 0 }, - { "CC-21", UNLCC21_Init, 0 }, - { "CITYFIGHT", UNLCITYFIGHT_Init, 0 }, - { "10-24-C-A1", BMC1024CA1_Init, 0 }, - { "CNROM", CNROM_Init, 0 }, - { "CPROM", CPROM_Init, BMCFLAG_16KCHRR }, - { "D1038", BMCD1038_Init, 0 }, - { "DANCE", UNLOneBus_Init, 0 }, /* redundant */ - { "DANCE2000", UNLD2000_Init, 0 }, - { "DREAMTECH01", DreamTech01_Init, 0 }, - { "EDU2000", UNLEDU2000_Init, 0 }, - { "EKROM", EKROM_Init, 0 }, - { "ELROM", ELROM_Init, 0 }, - { "ETROM", ETROM_Init, 0 }, - { "EWROM", EWROM_Init, 0 }, - { "FK23C", BMCFK23C_Init, BMCFLAG_256KCHRR }, - { "FK23CA", BMCFK23CA_Init, BMCFLAG_256KCHRR }, - { "FS304", UNLFS304_Init, 0 }, - { "G-146", BMCG146_Init, 0 }, - { "GK-192", BMCGK192_Init, 0 }, - { "GS-2004", BMCGS2004_Init, 0 }, - { "GS-2013", BMCGS2013_Init, 0 }, - { "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0 }, - { "H2288", UNLH2288_Init, 0 }, - { "HKROM", HKROM_Init, 0 }, - { "KOF97", UNLKOF97_Init, 0 }, - { "KONAMI-QTAI", Mapper190_Init, 0 }, - { "KS7012", UNLKS7012_Init, 0 }, - { "KS7013B", UNLKS7013B_Init, 0 }, - { "KS7016", UNLKS7016_Init, 0 }, - { "KS7017", UNLKS7017_Init, 0 }, - { "KS7030", UNLKS7030_Init, 0 }, - { "KS7031", UNLKS7031_Init, 0 }, - { "KS7032", UNLKS7032_Init, 0 }, - { "KS7037", UNLKS7037_Init, 0 }, - { "KS7057", UNLKS7057_Init, 0 }, - { "LE05", LE05_Init, 0 }, - { "LH10", LH10_Init, 0 }, - { "LH32", LH32_Init, 0 }, - { "LH53", LH53_Init, 0 }, - { "MALISB", UNLMaliSB_Init, 0 }, - { "MARIO1-MALEE2", MALEE_Init, 0 }, - { "MHROM", MHROM_Init, 0 }, - { "N625092", UNLN625092_Init, 0 }, - { "NROM", NROM_Init, 0 }, - { "NROM-128", NROM_Init, 0 }, - { "NROM-256", NROM_Init, 0 }, - { "NTBROM", Mapper68_Init, 0 }, - { "NTD-03", BMCNTD03_Init, 0 }, - { "NovelDiamond9999999in1", Novel_Init, 0 }, - { "OneBus", UNLOneBus_Init, 0 }, - { "PEC-586", UNLPEC586Init, 0 }, - { "RROM", NROM_Init, 0 }, - { "RROM-128", NROM_Init, 0 }, - { "SA-002", TCU02_Init, 0 }, - { "SA-0036", SA0036_Init, 0 }, - { "SA-0037", SA0037_Init, 0 }, - { "SA-009", SA009_Init, 0 }, - { "SA-016-1M", SA0161M_Init, 0 }, - { "SA-72007", SA72007_Init, 0 }, - { "SA-72008", SA72008_Init, 0 }, - { "SA-9602B", SA9602B_Init, BMCFLAG_32KCHRR }, - { "SA-NROM", TCA01_Init, 0 }, - { "SAROM", SAROM_Init, 0 }, - { "SBROM", SBROM_Init, 0 }, - { "SC-127", UNLSC127_Init, 0 }, - { "SCROM", SCROM_Init, 0 }, - { "SEROM", SEROM_Init, 0 }, - { "SGROM", SGROM_Init, 0 }, - { "SHERO", UNLSHeroes_Init, 0 }, - { "SKROM", SKROM_Init, 0 }, - { "SL12", UNLSL12_Init, 0 }, - { "SL1632", UNLSL1632_Init, 0 }, - { "SL1ROM", SL1ROM_Init, 0 }, - { "SLROM", SLROM_Init, 0 }, - { "SMB2J", UNLSMB2J_Init, 0 }, - { "SNROM", SNROM_Init, 0 }, - { "SOROM", SOROM_Init, 0 }, - { "SSS-NROM-256", SSSNROM_Init, 0 }, - { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init, 0 }, /* fix me, real pcb name, real pcb type */ - { "Sachen-74LS374N", S74LS374N_Init, 0 }, - { "Sachen-74LS374NA", S74LS374NA_Init, 0 }, /* seems to be custom mapper */ - { "Sachen-8259A", S8259A_Init, 0 }, - { "Sachen-8259B", S8259B_Init, 0 }, - { "Sachen-8259C", S8259C_Init, 0 }, - { "Sachen-8259D", S8259D_Init, 0 }, - { "Super24in1SC03", Super24_Init, 0 }, - { "SuperHIK8in1", Mapper45_Init, 0 }, - { "Supervision16in1", Supervision16_Init, 0 }, - { "T-227-1", BMCT2271_Init, 0 }, - { "T-230", UNLT230_Init, 0 }, - { "T-262", BMCT262_Init, 0 }, - { "TBROM", TBROM_Init, 0 }, - { "TC-U01-1.5M", TCU01_Init, 0 }, - { "TEK90", Mapper90_Init, 0 }, - { "TEROM", TEROM_Init, 0 }, - { "TF1201", UNLTF1201_Init, 0 }, - { "TFROM", TFROM_Init, 0 }, - { "TGROM", TGROM_Init, 0 }, - { "TKROM", TKROM_Init, 0 }, - { "TKSROM", TKSROM_Init, 0 }, - { "TLROM", TLROM_Init, 0 }, - { "TLSROM", TLSROM_Init, 0 }, - { "TQROM", TQROM_Init, 0 }, - { "TR1ROM", TFROM_Init, BMCFLAG_FORCE4 }, - { "TSROM", TSROM_Init, 0 }, - { "TVROM", TLROM_Init, BMCFLAG_FORCE4 }, - { "Transformer", Transformer_Init, 0 }, - { "UNROM", UNROM_Init, 0 }, - { "UNROM-512-8", UNROM512_Init, 0 }, - { "UNROM-512-16", UNROM512_Init, BMCFLAG_16KCHRR }, - { "UNROM-512-32", UNROM512_Init, BMCFLAG_32KCHRR }, - { "UOROM", UNROM_Init, 0 }, - { "VRC7", UNLVRC7_Init, 0 }, - { "YOKO", UNLYOKO_Init, 0 }, - { "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR }, - { "158B", UNL158B_Init, 0 }, - { "DRAGONFIGHTER", UNLBMW8544_Init, 0 }, - { "EH8813A", UNLEH8813A_Init, 0 }, - { "HP898F", BMCHP898F_Init, 0 }, - { "F-15", BMCF15_Init, 0 }, - { "RT-01", UNLRT01_Init, 0 }, - { "81-01-31-C", BMC810131C_Init, 0 }, - { "8-IN-1", BMC8IN1_Init, 0 }, - { "RET-CUFROM", Mapper29_Init, BMCFLAG_32KCHRR }, - { "60311C", BMC60311C_Init, 0 }, - { "WS", BMCWS_Init, 0 }, - { "HPxx", BMCHPxx_Init, 0 }, - { "HP2018-A", BMCHPxx_Init, 0 }, - { "CHINA_ER_SAN2", Mapper19_Init, 0 }, /* http://forums.nesdev.com/viewtopic.php?t=16465&p=216531 */ - { "WAIXING-FW01", Mapper227_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 */ - { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ - { "80013-B", BMC80013B_Init, 0 }, - { "TH2131-1", UNLTH21311_Init, 0 }, - { "LH51", LH51_Init, 0 }, - { "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 }, - { " BMC-RESET-TXROM", BMCRESETTXROM_Init, 0 }, - { "RESET-TXROM", BMCRESETTXROM_Init, 0 }, - { "K-3088", BMCK3088_Init, 0 }, - { "FARID_SLROM_8-IN-1", FARIDSLROM8IN1_Init, 0 }, - { "830425C-4391T", BMC830425C4391T_Init, 0 }, - { "TJ-03", BMCTJ03_Init, 0 }, - { "CTC-09", BMCCTC09_Init, 0 }, - { "K-3046", BMCK3046_Init, 0 }, - { "SA005-A", BMCSA005A_Init, 0 }, - { "K-3006", BMCK3006_Init, 0 }, - { "K-3036", BMCK3036_Init, 0 }, - { "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR }, - { "KS7021A", UNLKS7021A_Init, 0 }, - { "KS106C", BMCKS106C_Init, 0 }, - { "900218", BTL900218_Init, 0 }, - { "JC-016-2", Mapper205_Init, 0 }, - { "AX-40G", UNLAX40G_Init, 0 }, - { " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 }, - { "G631", BMCGhostbusters63in1_Init, 0 }, - { "BJ-56", UNLBJ56_Init, 0 }, - { "L6IN1", BMCL6IN1_Init, 0 }, - { "CTC-12IN1", BMCCTC12IN1_Init, 0 }, - { "891227", BMC891227_Init, 0 }, - { "NEWSTAR-GRM070-8IN1", BMC8IN1_Init, 0 }, - { "FARID_UNROM_8-IN-1", FARIDUNROM_Init, 0 }, - { "K-3033", BMCK3033_Init, 0 }, - { "830134C", BMC830134C_Init, 0 }, - { "GN-26", BMCGN26_Init, 0 }, - { "T4A54A", Mapper134_Init, 0 }, + { "11160", 299, BMC11160_Init, 0 }, + { "12-IN-1", 331, BMC12IN1_Init, 0 }, + { "13in1JY110", 295, BMC13in1JY110_Init, 0 }, + { "190in1", 300, BMC190in1_Init, 0 }, + { "22211", 132, UNL22211_Init, 0 }, + { "3D-BLOCK", 355, UNL3DBlock_Init, 0 }, + { "411120-C", 287, BMC411120C_Init, 0 }, + { "42in1ResetSwitch", 226, Mapper226_Init, 0 }, + { "43272", 227, UNL43272_Init, 0 }, + { "603-5052", 238, UNL6035052_Init, 0 }, + { "64in1NoRepeat", 314, BMC64in1nr_Init, 0 }, + { "70in1", 236, BMC70in1_Init, 0 }, + { "70in1B", 236, BMC70in1B_Init, 0 }, + { "810544-C-A1", 261, BMC810544CA1_Init, 0 }, + { "8157", 301, UNL8157_Init, 0 }, + { "8237", 215, UNL8237_Init, 0 }, + { "8237A", 215, UNL8237A_Init, 0 }, + { "830118C", 348, BMC830118C_Init, 0 }, + { "A65AS", 285, BMCA65AS_Init, 0 }, + { "AC08", NO_INES, AC08_Init, 0 }, /* Mapper 42.. but not.. Used for Green Beret */ + { "ANROM", 7, ANROM_Init, 0 }, + { "AX5705", 530, UNLAX5705_Init, 0 }, + { "BB", 108, UNLBB_Init, 0 }, + { "BS-5", 286, BMCBS5_Init, 0 }, + { "CC-21", 27, UNLCC21_Init, 0 }, + { "CITYFIGHT", 266, UNLCITYFIGHT_Init, 0 }, + { "10-24-C-A1", 327, BMC1024CA1_Init, 0 }, + { "CNROM", 3, CNROM_Init, 0 }, + { "CPROM", 13, CPROM_Init, BMCFLAG_16KCHRR }, + { "D1038", 59, BMCD1038_Init, 0 }, + { "DANCE", 256, UNLOneBus_Init, 0 }, /* redundant */ + { "DANCE2000", 518, UNLD2000_Init, 0 }, + { "DREAMTECH01", 521, DreamTech01_Init, 0 }, + { "EDU2000", 329, UNLEDU2000_Init, 0 }, + { "EKROM", 5, EKROM_Init, 0 }, + { "ELROM", 5, ELROM_Init, 0 }, + { "ETROM", 5, ETROM_Init, 0 }, + { "EWROM", 5, EWROM_Init, 0 }, + { "FK23C", 176, BMCFK23C_Init, BMCFLAG_256KCHRR }, + { "FK23CA", 176, BMCFK23CA_Init, BMCFLAG_256KCHRR }, + { "FS304", 162, UNLFS304_Init, 0 }, + { "G-146", 349, BMCG146_Init, 0 }, + { "GK-192", NO_INES, BMCGK192_Init, 0 }, /* mapper 58? */ + { "GS-2004", 283, BMCGS2004_Init, 0 }, + { "GS-2013", 283, BMCGS2013_Init, 0 }, + { "Ghostbusters63in1", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* 226 is non-split version */ + { "H2288", 123, UNLH2288_Init, 0 }, + { "HKROM", 4, HKROM_Init, 0 }, + { "KOF97", 263, UNLKOF97_Init, 0 }, + { "KONAMI-QTAI", NO_INES, Mapper190_Init, 0 }, + { "KS7012", 346, UNLKS7012_Init, 0 }, + { "KS7013B", 312, UNLKS7013B_Init, 0 }, + { "KS7016", 306, UNLKS7016_Init, 0 }, + { "KS7017", 303, UNLKS7017_Init, 0 }, + { "KS7030", 347, UNLKS7030_Init, 0 }, + { "KS7031", 305, UNLKS7031_Init, 0 }, + { "KS7032", 142, UNLKS7032_Init, 0 }, + { "KS7037", 307, UNLKS7037_Init, 0 }, + { "KS7057", 302, UNLKS7057_Init, 0 }, + { "LE05", NO_INES, LE05_Init, 0 }, + { "LH10", 522, LH10_Init, 0 }, + { "LH32", 125, LH32_Init, 0 }, + { "LH53", 535, LH53_Init, 0 }, + { "MALISB", 325, UNLMaliSB_Init, 0 }, + { "MARIO1-MALEE2", 42, MALEE_Init, 0 }, + { "MHROM", 66, MHROM_Init, 0 }, + { "N625092", 221, UNLN625092_Init, 0 }, + { "NROM", 0, NROM_Init, 0 }, + { "NROM-128", 0, NROM_Init, 0 }, + { "NROM-256", 0, NROM_Init, 0 }, + { "NTBROM", 68, Mapper68_Init, 0 }, + { "NTD-03", 290, BMCNTD03_Init, 0 }, + { "NovelDiamond9999999in1", 201, Novel_Init, 0 }, + { "OneBus", 256, UNLOneBus_Init, 0 }, + { "PEC-586", NO_INES, UNLPEC586Init, 0 }, + { "RROM", 0, NROM_Init, 0 }, + { "RROM-128", 0, NROM_Init, 0 }, + { "SA-002", 136, TCU02_Init, 0 }, + { "SA-0036", 149, SA0036_Init, 0 }, + { "SA-0037", 148, SA0037_Init, 0 }, + { "SA-009", 160, SA009_Init, 0 }, + { "SA-016-1M", 146, SA0161M_Init, 0 }, + { "SA-72007", 145, SA72007_Init, 0 }, + { "SA-72008", 133, SA72008_Init, 0 }, + { "SA-9602B", 513, SA9602B_Init, BMCFLAG_32KCHRR }, + { "SA-NROM", 143, TCA01_Init, 0 }, + { "SAROM", 1, SAROM_Init, 0 }, + { "SBROM", 1, SBROM_Init, 0 }, + { "SC-127", 35, UNLSC127_Init, 0 }, + { "SCROM", 1, SCROM_Init, 0 }, + { "SEROM", 1, SEROM_Init, 0 }, + { "SGROM", 1, SGROM_Init, 0 }, + { "SHERO", 262, UNLSHeroes_Init, 0 }, + { "SKROM", 1, SKROM_Init, 0 }, + { "SL12", 116, UNLSL12_Init, 0 }, + { "SL1632", 14, UNLSL1632_Init, 0 }, + { "SL1ROM", 1, SL1ROM_Init, 0 }, + { "SLROM", 1, SLROM_Init, 0 }, + { "SMB2J", 304, UNLSMB2J_Init, 0 }, + { "SNROM", 1, SNROM_Init, 0 }, + { "SOROM", 1, SOROM_Init, 0 }, + { "SSS-NROM-256", NO_INES, SSSNROM_Init, 0 }, + { "SUNSOFT_UNROM", 93, SUNSOFT_UNROM_Init, 0 }, /* fix me, real pcb name, real pcb type */ + { "Sachen-74LS374N", 150, S74LS374N_Init, 0 }, + { "Sachen-74LS374NA", 243, S74LS374NA_Init, 0 }, /* seems to be custom mapper */ + { "Sachen-8259A", 141, S8259A_Init, 0 }, + { "Sachen-8259B", 138, S8259B_Init, 0 }, + { "Sachen-8259C", 139, S8259C_Init, 0 }, + { "Sachen-8259D", 137, S8259D_Init, 0 }, + { "Super24in1SC03", 176, Super24_Init, 0 }, + { "SuperHIK8in1", 45, Mapper45_Init, 0 }, + { "Supervision16in1", 53, Supervision16_Init, 0 }, + { "T-227-1", NO_INES, BMCT2271_Init, 0 }, + { "T-230", 529, UNLT230_Init, 0 }, + { "T-262", 265, BMCT262_Init, 0 }, + { "TBROM", 4, TBROM_Init, 0 }, + { "TC-U01-1.5M", 147, TCU01_Init, 0 }, + { "TEK90", 90, Mapper90_Init, 0 }, + { "TEROM", 4, TEROM_Init, 0 }, + { "TF1201", 298, UNLTF1201_Init, 0 }, + { "TFROM", 4, TFROM_Init, 0 }, + { "TGROM", 4, TGROM_Init, 0 }, + { "TKROM", 4, TKROM_Init, 0 }, + { "TKSROM", 118, TKSROM_Init, 0 }, + { "TLROM", 4, TLROM_Init, 0 }, + { "TLSROM", 118, TLSROM_Init, 0 }, + { "TQROM", 119, TQROM_Init, 0 }, + { "TR1ROM", 4, TFROM_Init, BMCFLAG_FORCE4 }, + { "TSROM", 4, TSROM_Init, 0 }, + { "TVROM", 4, TLROM_Init, BMCFLAG_FORCE4 }, + { "Transformer", NO_INES, Transformer_Init, 0 }, + { "UNROM", 2, UNROM_Init, 0 }, + { "UNROM-512-8", 30, UNROM512_Init, 0 }, + { "UNROM-512-16", 30, UNROM512_Init, BMCFLAG_16KCHRR }, + { "UNROM-512-32", 30, UNROM512_Init, BMCFLAG_32KCHRR }, + { "UOROM", 2, UNROM_Init, 0 }, + { "VRC7", 85, UNLVRC7_Init, 0 }, + { "YOKO", 264, UNLYOKO_Init, 0 }, + { "COOLBOY", 268, COOLBOY_Init, BMCFLAG_256KCHRR }, + { "158B", 258, UNL158B_Init, 0 }, + { "DRAGONFIGHTER", 292, UNLBMW8544_Init, 0 }, + { "EH8813A", 519, UNLEH8813A_Init, 0 }, + { "HP898F", 319, BMCHP898F_Init, 0 }, + { "F-15", 259, BMCF15_Init, 0 }, + { "RT-01", 328, UNLRT01_Init, 0 }, + { "81-01-31-C", NO_INES, BMC810131C_Init, 0 }, + { "8-IN-1", 333, BMC8IN1_Init, 0 }, + { "RET-CUFROM", 29, Mapper29_Init, BMCFLAG_32KCHRR }, + { "60311C", 289, BMC60311C_Init, 0 }, + { "WS", 332, BMCWS_Init, 0 }, + { "HPxx", 260, BMCHPxx_Init, 0 }, + { "HP2018-A", 260, BMCHPxx_Init, 0 }, + { "CHINA_ER_SAN2", 19, Mapper19_Init, 0 }, + { "WAIXING-FW01", 227, Mapper227_Init, 0 }, + { "WAIXING-FS005", 176, BMCFK23C_Init, 0 }, + { "80013-B", 274, BMC80013B_Init, 0 }, + { "TH2131-1", 308, UNLTH21311_Init, 0 }, + { "LH51", 309, LH51_Init, 0 }, + { "RESETNROM-XIN1", NO_INES, BMCRESETNROMXIN1_Init, 0 }, /* split roms */ + { " BMC-RESET-TXROM", 313, BMCRESETTXROM_Init, 0 }, + { "RESET-TXROM", 313, BMCRESETTXROM_Init, 0 }, + { "K-3088", 287, BMCK3088_Init, 0 }, + { "FARID_SLROM_8-IN-1", 323, FARIDSLROM8IN1_Init, 0 }, + { "830425C-4391T", 320, BMC830425C4391T_Init, 0 }, + { "TJ-03", 341, BMCTJ03_Init, 0 }, + { "CTC-09", 335, BMCCTC09_Init, 0 }, + { "K-3046", 336, BMCK3046_Init, 0 }, + { "SA005-A", 338, BMCSA005A_Init, 0 }, + { "K-3006", 339, BMCK3006_Init, 0 }, + { "K-3036", 340, BMCK3036_Init, 0 }, + { "MINDKIDS", 268, MINDKIDS_Init, BMCFLAG_256KCHRR }, + { "KS7021A", 525, UNLKS7021A_Init, 0 }, + { "KS106C", NO_INES, BMCKS106C_Init, 0 }, /* split roms */ + { "900218", 524, BTL900218_Init, 0 }, + { "JC-016-2", 205, Mapper205_Init, 0 }, + { "AX-40G", 527, UNLAX40G_Init, 0 }, + { " BMC-STREETFIGTER-GAME4IN1", NO_INES, BMCSFGAME4IN1_Init, 0 }, /* mapper 49? */ + { "G631", 226, BMCGhostbusters63in1_Init, 0 }, /* duplicate, probably wrong name */ + { "BJ-56", 526, UNLBJ56_Init, 0 }, + { "L6IN1", 345, BMCL6IN1_Init, 0 }, + { "CTC-12IN1", 337, BMCCTC12IN1_Init, 0 }, + { "891227", 350, BMC891227_Init, 0 }, + { "NEWSTAR-GRM070-8IN1", 333, BMC8IN1_Init, 0 }, + { "FARID_UNROM_8-IN-1", 324, FARIDUNROM_Init, 0 }, + { "K-3033", 322, BMCK3033_Init, 0 }, + { "830134C", 315, BMC830134C_Init, 0 }, + { "GN-26", 344, BMCGN26_Init, 0 }, + { "T4A54A", 134, Mapper134_Init, 0 }, #ifdef COPYFAMI - { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, - { "COPYFAMI", MapperCopyFami_Init, 0 }, + { "COPYFAMI_MMC3", NO_INES, MapperCopyFamiMMC3_Init, 0 }, + { "COPYFAMI", NO_INES, MapperCopyFami_Init, 0 }, #endif - { NULL, NULL, 0 } + { NULL, NO_INES, NULL, 0 } }; static BFMAPPING bfunc[] = { From 2a7bd3727657b3281fa775127256b9e7c3dabce5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 10 Jul 2019 11:11:01 +0800 Subject: [PATCH 55/74] UNIF: Change how roms are loaded in multiple prg/chr file versions - Part of migrating UNIF to NES 2.0 conversion, which should make each unif roms to be compatible with each other. Some roms have separate prg and chr banks, which mapper has to do separate banking for such file versions. - This change would also make the boards to be easily usuable iNes/Nes 2.0. --- src/unif.c | 93 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/src/unif.c b/src/unif.c index 7f8e672..8f496cf 100644 --- a/src/unif.c +++ b/src/unif.c @@ -75,10 +75,16 @@ static UNIF_HEADER uchead; static uint8 *malloced[32]; static uint32 mallocedsizes[32]; +/* used to preserve the rom order as found in the rom file + * at least one mapper has bank 4 at the beginning for e.g. */ +static uint32 prg_idx[16]; +static uint32 chr_idx[16]; static uint32 prg_chip_count; static uint32 chr_chip_count; +static uint64 UNIF_PRGROMSize, UNIF_CHRROMSize; + static int FixRomSize(uint32 size, uint32 minimum) { uint32 x = 1; @@ -102,12 +108,20 @@ static void FreeUNIF(void) { free(malloced[x]); malloced[x] = 0; } } + if (ROM) { + free(ROM); ROM = 0; + } + if (VROM) { + free(VROM); VROM = 0; + } } static void ResetUNIF(void) { int x; for (x = 0; x < 32; x++) malloced[x] = 0; + for (x = 0; x < 16; x++) + prg_idx[x] = chr_idx[x] = 0; vramo = 0; boardname = 0; mirrortodo = 0; @@ -115,6 +129,10 @@ static void ResetUNIF(void) { UNIFchrrama = 0; prg_chip_count = 0; chr_chip_count = 0; + UNIF_PRGROMSize = 0; + UNIF_CHRROMSize = 0; + ROM_size = 0; + VROM_size = 0; } static uint8 exntar[2048]; @@ -268,7 +286,7 @@ static int LoadPRG(FCEUFILE *fp) { FCEU_printf(" PRG ROM %d size: %d\n", z, (int)uchead.info); if (malloced[z]) free(malloced[z]); - t = FixRomSize(uchead.info, 2048); + t = uchead.info; if (!(malloced[z] = (uint8*)FCEU_malloc(t))) return(0); mallocedsizes[z] = t; @@ -276,11 +294,12 @@ static int LoadPRG(FCEUFILE *fp) { if (FCEU_fread(malloced[z], 1, uchead.info, fp) != uchead.info) { FCEU_printf("Read Error!\n"); return(0); - } /* else - FCEU_printf("\n"); */ + } - SetupCartPRGMapping(z, malloced[z], t, 0); + UNIF_PRGROMSize += t; + prg_idx[prg_chip_count] = z; prg_chip_count++; + return(1); } @@ -304,7 +323,7 @@ static int LoadCHR(FCEUFILE *fp) { FCEU_printf(" CHR ROM %d size: %d\n", z, (int)uchead.info); if (malloced[16 + z]) free(malloced[16 + z]); - t = FixRomSize(uchead.info, 8192); + t = uchead.info; if (!(malloced[16 + z] = (uint8*)FCEU_malloc(t))) return(0); mallocedsizes[16 + z] = t; @@ -312,11 +331,12 @@ static int LoadCHR(FCEUFILE *fp) { if (FCEU_fread(malloced[16 + z], 1, uchead.info, fp) != uchead.info) { FCEU_printf("Read Error!\n"); return(0); - } /* else - FCEU_printf("\n"); */ + } - SetupCartCHRMapping(z, malloced[16 + z], t, 0); + UNIF_CHRROMSize += t; + chr_idx[chr_chip_count] = z; chr_chip_count++; + return(1); } @@ -497,6 +517,7 @@ static BMAPPING bmap[] = { { "Sachen-8259C", 139, S8259C_Init, 0 }, { "Sachen-8259D", 137, S8259D_Init, 0 }, { "Super24in1SC03", 176, Super24_Init, 0 }, + { "Super24in1SC03", 176, Super24_Init, 0 }, { "SuperHIK8in1", 45, Mapper45_Init, 0 }, { "Supervision16in1", 53, Supervision16_Init, 0 }, { "T-227-1", NO_INES, BMCT2271_Init, 0 }, @@ -563,7 +584,7 @@ static BMAPPING bmap[] = { { "900218", 524, BTL900218_Init, 0 }, { "JC-016-2", 205, Mapper205_Init, 0 }, { "AX-40G", 527, UNLAX40G_Init, 0 }, - { " BMC-STREETFIGTER-GAME4IN1", NO_INES, BMCSFGAME4IN1_Init, 0 }, /* mapper 49? */ + { " BMC-STREETFIGTER-GAME4IN1", NO_INES, BMCSFGAME4IN1_Init, 0 }, /* mapper 49? submapper 1*/ { "G631", 226, BMCGhostbusters63in1_Init, 0 }, /* duplicate, probably wrong name */ { "BJ-56", 526, UNLBJ56_Init, 0 }, { "L6IN1", 345, BMCL6IN1_Init, 0 }, @@ -633,7 +654,7 @@ static int InitializeBoard(void) { while (bmap[x].name) { if (!strcmp((char*)sboardname, (char*)bmap[x].name)) { - if (!malloced[16]) { + if (VROM_size == 0) { if (bmap[x].flags & BMCFLAG_16KCHRR) CHRRAMSize = 16; else if (bmap[x].flags & BMCFLAG_32KCHRR) @@ -690,6 +711,10 @@ static void UNIFGI(int h) { } int UNIFLoad(const char *name, FCEUFILE *fp) { + struct md5_context md5; + uint32 x = 0; + uint64 PRGptr = 0, CHRptr = 0; + FCEU_fseek(fp, 0, SEEK_SET); FCEU_fread(&unhead, 1, 4, fp); if (memcmp(&unhead, "UNIF", 4)) @@ -705,23 +730,49 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { goto aborto; if (!LoadUNIFChunks(fp)) goto aborto; - { - int x; - struct md5_context md5; - md5_starts(&md5); + ROM_size = FixRomSize(UNIF_PRGROMSize, 2048); + if (UNIF_CHRROMSize) + VROM_size = FixRomSize(UNIF_CHRROMSize, 8192); - for (x = 0; x < 32; x++) - if (malloced[x]) { - md5_update(&md5, malloced[x], mallocedsizes[x]); - } - md5_finish(&md5, UNIFCart.MD5); - FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(UNIFCart.MD5)); - memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5)); + ROM = (uint8*)malloc(ROM_size); + if (VROM_size) + VROM = (uint8*)malloc(VROM_size); + + for (x = 0; x < 16; x++) { + if (malloced[prg_idx[x]]) { + memcpy(ROM + PRGptr, malloced[(prg_idx[x])], mallocedsizes[(prg_idx[x])]); + PRGptr += mallocedsizes[(prg_idx[x])]; + free(malloced[(prg_idx[x])]); + malloced[(prg_idx[x])] = 0; + } + + if (malloced[16 + (chr_idx[x])]) { + memcpy(VROM + CHRptr, malloced[16 + (chr_idx[x])], mallocedsizes[16 + (chr_idx[x])]); + CHRptr += mallocedsizes[16 + (chr_idx[x])]; + free(malloced[16 + (chr_idx[x])]); + malloced[16 + (chr_idx[x])] = 0; + } } + FCEU_printf(" PRG ROM: %d KiB\n", UNIF_PRGROMSize / 1024); + if (VROM_size) + FCEU_printf(" CHR ROM: %d KiB\n", UNIF_CHRROMSize / 1024); + + md5_starts(&md5); + md5_update(&md5, ROM, UNIF_PRGROMSize); + if (VROM_size) + md5_update(&md5, VROM, UNIF_CHRROMSize); + md5_finish(&md5, UNIFCart.MD5); + FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(UNIFCart.MD5)); + memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5)); + CheckHashInfo(); + SetupCartPRGMapping(0, ROM, ROM_size, 0); + if (VROM_size) + SetupCartCHRMapping(0, VROM, VROM_size, 0); + if (!InitializeBoard()) goto aborto; From 429f6c45455ca7f969fff670b68ceaeef21aff20 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 11 Jul 2019 16:34:39 +0800 Subject: [PATCH 56/74] UNIF: Update boards based on last commit - fixes (if necessary), update and cleanup the following boards that now dont need alternate mappings: - this is part of migrating unif to be usuable in ines mappers - boards affected in this commit are: SUPERVISION16IN1, GS-2004, GS-2013, UNL-SMB2J, MARIO1-MALEE2, UNL-SA-9602B, UNL-KS106C / RESETNROM-XIN1 UNL-AC08, NES-NTBROM, BMC-K-3033, BMC-GN-26, BMC-GHOSTBUSTERS63IN1, BMC-830425C-4391T BMC-830134C, BMC-891227 / BMC-CTC-12IN1, BMC-JC-016-2, UNL-T4A54A, UNL-8157, BMC-T-262 (might have forgotten to list some...) --- src/boards/09-034a.c | 2 +- src/boards/68.c | 2 +- src/boards/8157.c | 12 +++--------- src/boards/830134C.c | 14 ++++++-------- src/boards/SA-9602B.c | 10 +++++----- src/boards/ac-08.c | 2 +- src/boards/bmc830425C4391t.c | 7 +++---- src/boards/bmcgamecard.c | 6 +++--- src/boards/bmck3033.c | 26 +++++++++++++++----------- src/boards/ghostbusters63in1.c | 6 +++--- src/boards/gn26.c | 15 ++++++++------- src/boards/gs-2004.c | 6 +++--- src/boards/gs-2013.c | 8 ++++---- src/boards/malee.c | 2 +- src/boards/mmc3.c | 28 ++++------------------------ src/boards/resetnromxin1.c | 4 ++-- src/boards/resettxrom.c | 14 ++------------ src/boards/supervision.c | 15 ++------------- src/boards/t-262.c | 11 ++--------- src/unif.c | 4 ++-- 20 files changed, 71 insertions(+), 123 deletions(-) diff --git a/src/boards/09-034a.c b/src/boards/09-034a.c index b39d595..12e5b79 100644 --- a/src/boards/09-034a.c +++ b/src/boards/09-034a.c @@ -44,7 +44,7 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - setprg8r(1, 0x6000, prg); + setprg8(0x6000, 4 | prg); setprg32(0x8000, 0); setchr8(0); } diff --git a/src/boards/68.c b/src/boards/68.c index 19da627..2e0ec8f 100644 --- a/src/boards/68.c +++ b/src/boards/68.c @@ -73,7 +73,7 @@ static void Sync(void) { setchr2(0x1800, chr_reg[3]); setprg8r(0x10, 0x6000, 0); setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg_reg); - setprg16(0xC000, ~0); + setprg16(0xC000, 0x07); } static DECLFR(M68Read) { diff --git a/src/boards/8157.c b/src/boards/8157.c index 1d72957..b81c05f 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -37,15 +37,9 @@ static void Sync(void) { uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; uint32 bank = (cmdreg & 0x01C) >> 2; uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); - if (PRGptr[1]) { - chip = base >> 3; - if (chip > PRGchip_max) chip &= PRGchip_max; - setprg16r(chip, 0x8000, bank); /* for versions with split ROMs */ - setprg16r(chip, 0xC000, lbank); - } else { - setprg16(0x8000, base | bank); - setprg16(0xC000, base | lbank); - } + + setprg16(0x8000, base | bank); + setprg16(0xC000, base | lbank); setmirror(((cmdreg & 2) >> 1) ^ 1); } diff --git a/src/boards/830134C.c b/src/boards/830134C.c index 7d546d5..5637c7a 100644 --- a/src/boards/830134C.c +++ b/src/boards/830134C.c @@ -28,22 +28,20 @@ #include "mmc3.h" static void BMC830134CCW(uint32 A, uint8 V) { - uint32 chip = (EXPREGS[0] & 0x03) & ~((EXPREGS[0] & 0x02) >> 1); - setchr1r(chip, A, (V & 0xFF) | ((EXPREGS[0] & 0x01) << 8) | ((EXPREGS[0] & 0x02) << 6) | ((EXPREGS[0] & 0x08) << 3)); + setchr1(A, (V & 0xFF) | ((EXPREGS[0] & 0x01) << 8) | ((EXPREGS[0] & 0x02) << 6) | ((EXPREGS[0] & 0x08) << 3)); } static void BMC830134CPW(uint32 A, uint8 V) { - uint32 chip = (EXPREGS[0] & 0x06) >> 1; if ((EXPREGS[0] & 0x06) == 0x06) { if (A == 0x8000) { - setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); - setprg8r(chip, 0xC000, (V & 0x0F) | 0x32); + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); + setprg8(0xC000, (V & 0x0F) | 0x32); } else if (A == 0xA000) { - setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); - setprg8r(chip, 0xE000, (V & 0x0F) | 0x32); + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); + setprg8(0xE000, (V & 0x0F) | 0x32); } } else - setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3)); } static DECLFW(BMC830134CWrite) { diff --git a/src/boards/SA-9602B.c b/src/boards/SA-9602B.c index 7acd049..10b4315 100644 --- a/src/boards/SA-9602B.c +++ b/src/boards/SA-9602B.c @@ -22,12 +22,12 @@ #include "mmc3.h" static void SA9602BPW(uint32 A, uint8 V) { - setprg8r(EXPREGS[1], A, V & 0x3F); + setprg8(A, (EXPREGS[1] & 0xC0) | (V & 0x3F)); if (MMC3_cmd & 0x40) - setprg8r(0, 0x8000, ~(1)); + setprg8(0x8000, 62); else - setprg8r(0, 0xc000, ~(1)); - setprg8r(0, 0xe000, ~(0)); + setprg8(0xc000, 62); + setprg8(0xe000, 63); } static DECLFW(SA9602BWrite) { @@ -35,7 +35,7 @@ static DECLFW(SA9602BWrite) { case 0x8000: EXPREGS[0] = V; break; case 0x8001: if ((EXPREGS[0] & 7) < 6) { - EXPREGS[1] = V >> 6; + EXPREGS[1] = V; FixMMC3PRG(MMC3_cmd); } break; diff --git a/src/boards/ac-08.c b/src/boards/ac-08.c index 8dd16eb..081512e 100644 --- a/src/boards/ac-08.c +++ b/src/boards/ac-08.c @@ -34,7 +34,7 @@ static SFORMAT StateRegs[] = static void Sync(void) { setprg8(0x6000, reg); - setprg32r(1, 0x8000, 0); + setprg32(0x8000, 4); setchr8(0); setmirror(mirr); } diff --git a/src/boards/bmc830425C4391t.c b/src/boards/bmc830425C4391t.c index ce64fd2..108425a 100644 --- a/src/boards/bmc830425C4391t.c +++ b/src/boards/bmc830425C4391t.c @@ -39,17 +39,16 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - setprg16r(outer_bank, 0x8000, (inner_bank & bank_size)); - setprg16r(outer_bank, 0xC000, bank_size); + setprg16(0x8000, (outer_bank << 3) | (inner_bank & bank_size)); + setprg16(0xC000, (outer_bank << 3) | bank_size); setchr8(0); } static DECLFW(M320Write) { - const uint8 chip[] = { 0, 0, 1, 0, 2, 3, 4, 5 }; /* address mask is inconsistent with that is in the wiki. Mask should be * 0xFFE0 or Mermaid game will not work. */ if ((A & 0xFFE0) == 0xF0E0) { - outer_bank = chip[(A & 0x0F)]; + outer_bank = (A & 0x0F); bank_size = (A & 0x10) ? 0x07 : 0x0F; } inner_bank = (V & 0x0F); diff --git a/src/boards/bmcgamecard.c b/src/boards/bmcgamecard.c index 0cc58af..aab0e4c 100644 --- a/src/boards/bmcgamecard.c +++ b/src/boards/bmcgamecard.c @@ -41,12 +41,12 @@ static SFORMAT StateRegs[] = static void Sync(void) { uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1); uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03); - uint8 chip = m350 ? ((latche & 0x40) ? ((latche & 0x20) >> 5) : 0) : 0; + uint8 base = m350 ? ((latche & 0x40) ? (latche & 0x20) : 0) : 0; setchr8(0); setprg8(0x6000, 1); - setprg16r(PRGptr[1] ? chip : 0, 0x8000, (latche & 0x1F)); - setprg16r(PRGptr[1] ? chip : 0, 0xC000, (latche & 0x1F) | ((mode & 2) ? 0x07 : (mode & 1))); + setprg16r(0, 0x8000, base | (latche & 0x1F)); + setprg16r(0, 0xC000, base | ((latche & 0x1F) | ((mode & 2) ? 0x07 : (mode & 1)))); setmirror(mirroring ^ 1); } diff --git a/src/boards/bmck3033.c b/src/boards/bmck3033.c index 90ff0af..686d278 100644 --- a/src/boards/bmck3033.c +++ b/src/boards/bmck3033.c @@ -29,13 +29,16 @@ static void BMCK3033CW(uint32 A, uint8 V) { if (EXPREGS[2]) { - if (EXPREGS[3]) { // MMC3-256 - setchr1r(EXPREGS[1] & ~0x01, A, (V & 0xFF)); - } else { // MMC3-128 - setchr1r(EXPREGS[1], A, (V & 0x7F)); + if (EXPREGS[3]) { +/* FCEU_printf("MMC3-256: A:%04x V:%02x R1:%02x\n", A, V, EXPREGS[1]); */ + setchr1(A, (EXPREGS[1] << 8) | (V & 0xFF)); + } else { +/* FCEU_printf("MMC3-128: A:%04x V:%02x R1:%02x\n", A, V, EXPREGS[1]); */ + setchr1(A, (EXPREGS[1] << 7) | (V & 0x7F)); } - } else { // NROM - setchr1r(EXPREGS[1], A, (V & 0x7F)); + } else { +/* FCEU_printf("NROM: A:%04x V:%02x R1:%02x\n", A, V, EXPREGS[1]); */ + setchr1(A, (V & 0x7F)); } } @@ -43,19 +46,20 @@ static void BMCK3033PW(uint32 A, uint8 V) { if (EXPREGS[2]) { if (EXPREGS[3] ) { /* FCEU_printf("MMC3-256 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1] & ~0x01); */ - setprg8r((EXPREGS[1] & ~0x01), A, (V & 0x1F)); + setprg8(A, (EXPREGS[1] << 5) | (V & 0x1F)); } else { /* FCEU_printf("MMC3-128 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1]); */ - setprg8r(EXPREGS[1], A, (V & 0x0F)); + setprg8(A, (EXPREGS[1] << 4) | (V & 0x0F)); } } else { + uint32 base = (EXPREGS[1] << 3); if (EXPREGS[0] & 0x03) { /* FCEU_printf("NROM-256 base:%02x chip:%02x\n", EXPREGS[0] >> 1, EXPREGS[1]); */ - setprg32r(EXPREGS[1], 0x8000, EXPREGS[0] >> 1); + setprg32(0x8000, base | EXPREGS[0] >> 1); } else { /* FCEU_printf("NROM-128 base:%02x chip:%02x\n", EXPREGS[0], EXPREGS[1]); */ - setprg16r(EXPREGS[1], 0x8000, EXPREGS[0]); - setprg16r(EXPREGS[1], 0xC000, EXPREGS[0]); + setprg16(0x8000, base | EXPREGS[0]); + setprg16(0xC000, base | EXPREGS[0]); } } } diff --git a/src/boards/ghostbusters63in1.c b/src/boards/ghostbusters63in1.c index 2ca6ee1..bdd1f1e 100644 --- a/src/boards/ghostbusters63in1.c +++ b/src/boards/ghostbusters63in1.c @@ -35,10 +35,10 @@ static SFORMAT StateRegs[] = static void Sync(void) { if (reg[0] & 0x20) { - setprg16r(banks[bank], 0x8000, reg[0] & 0x1F); - setprg16r(banks[bank], 0xC000, reg[0] & 0x1F); + setprg16(0x8000, (banks[bank] << 5) | (reg[0] & 0x1F)); + setprg16(0xC000, (banks[bank] << 5) | (reg[0] & 0x1F)); } else - setprg32r(banks[bank], 0x8000, (reg[0] >> 1) & 0x0F); + setprg32(0x8000, ((banks[bank] << 5) | (reg[0] & 0x1F)) >> 1); if (reg[1] & 2) setchr8r(0x10, 0); else diff --git a/src/boards/gn26.c b/src/boards/gn26.c index b55967d..0af480b 100644 --- a/src/boards/gn26.c +++ b/src/boards/gn26.c @@ -27,19 +27,20 @@ #include "mmc3.h" static void BMCGN26CW(uint32 A, uint8 V) { - uint32 chip = (EXPREGS[0] & 0x03); - if (chip) chip -= 1; - setchr1r(chip, A, (V & 0xFF)); + uint32 base = (EXPREGS[0] & 0x03) << 7; + setchr1(A, base | (V & 0xFF)); } static void BMCGN26PW(uint32 A, uint8 V) { - uint32 chip = (EXPREGS[0] & 0x03); - if (chip) chip -= 1; /* Re-ordered -> 0:SF4 1:Contra Force 2:Revolution Hero */ + /* Re-ordered -> 0:SF4 1:Contra Force 2:Revolution Hero */ + uint32 table[] = { 0, 0, 1, 2 }; + uint32 base = table[(EXPREGS[0] & 0x03)]; + if (EXPREGS[0] & 4) { if (A == 0x8000) - setprg32r(chip, 0x8000, (V >> 2)); + setprg32(0x8000, (base << 2) | (V >> 2)); } else - setprg8r(chip, A, (V & 0x0F)); + setprg8(A, (base << 4) | (V & 0x0F)); } static DECLFW(BMCGN26Write) { diff --git a/src/boards/gs-2004.c b/src/boards/gs-2004.c index b292d90..fd964e5 100644 --- a/src/boards/gs-2004.c +++ b/src/boards/gs-2004.c @@ -29,7 +29,7 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - setprg8r(1, 0x6000, 0); + setprg8(0x6000, 32); setprg32(0x8000, reg); setchr8(0); } @@ -40,7 +40,7 @@ static DECLFW(BMCGS2004Write) { } static void BMCGS2004Power(void) { - reg = ~0; + reg = 0x07; Sync(); SetReadHandler(0x6000, 0x7FFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR); @@ -48,7 +48,7 @@ static void BMCGS2004Power(void) { } static void BMCGS2004Reset(void) { - reg = ~0; + reg = 0x07; } static void StateRestore(int version) { diff --git a/src/boards/gs-2013.c b/src/boards/gs-2013.c index fe81a53..e7cda5f 100644 --- a/src/boards/gs-2013.c +++ b/src/boards/gs-2013.c @@ -29,8 +29,8 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - setprg8r(0, 0x6000, ~0); - setprg32r((reg & 8) >> 3, 0x8000, reg); + setprg8(0x6000, 31); + setprg32(0x8000, reg); setchr8(0); } @@ -40,7 +40,7 @@ static DECLFW(BMCGS2013Write) { } static void BMCGS2013Power(void) { - reg = ~0; + reg = 0; Sync(); SetReadHandler(0x6000, 0x7FFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR); @@ -48,7 +48,7 @@ static void BMCGS2013Power(void) { } static void BMCGS2013Reset(void) { - reg = ~0; + reg = 0; } static void StateRestore(int version) { diff --git a/src/boards/malee.c b/src/boards/malee.c index 84c353a..a4a0721 100644 --- a/src/boards/malee.c +++ b/src/boards/malee.c @@ -31,7 +31,7 @@ static void MALEEPower(void) { SetReadHandler(0x6000, 0x67FF, CartBR); SetReadHandler(0x7000, 0x77FF, CartBR); SetWriteHandler(0x7000, 0x77FF, CartBW); - setprg2r(1, 0x6000, 0); + setprg2(0x6000, 16); setprg32(0x8000, 0); setchr8(0); } diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 93d36b6..3c9d42a 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -914,22 +914,12 @@ void Mapper119_Init(CartInfo *info) { static void M134PW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; - if (PRGptr[1]) { - chip = (EXPREGS[0] & 3); - if (chip > PRGchip_max) chip &= PRGchip_max; - setprg8r(chip, A, (V & mask)); - } else - setprg8(A, (V & mask) | ((EXPREGS[0] & 3) << 4)); + setprg8(A, (V & mask) | ((EXPREGS[0] & 3) << 4)); } static void M134CW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; - if (CHRptr[1]) { - chip = (EXPREGS[0] & 0x30) >> 4; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, (V & mask)); - } else - setchr1(A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); + setchr1(A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); } static DECLFW(M134Write) { @@ -1212,22 +1202,12 @@ static uint8 block[] = {0, 0, 1, 2}; static void M205PW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); - if (PRGptr[1]) { - chip = block[EXPREGS[0]]; - if (chip > PRGchip_max) chip &= PRGchip_max; - setprg8r(chip, A, bank); - } else - setprg8(A, EXPREGS[0] << 4 | bank); + setprg8(A, EXPREGS[0] << 4 | bank); } static void M205CW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF); - if (CHRptr[1]) { - chip = block[EXPREGS[0]]; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, bank); - } else - setchr1(A, (EXPREGS[0] << 7) | bank); + setchr1(A, (EXPREGS[0] << 7) | bank); } static DECLFW(M205Write0) { diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c index 76c6e84..0f0372f 100644 --- a/src/boards/resetnromxin1.c +++ b/src/boards/resetnromxin1.c @@ -38,8 +38,8 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - setchr8r(gameblock, 0); - setprg32r(gameblock, 0x8000, 0); + setchr8(gameblock); + setprg32(0x8000, gameblock); } static void BMCRESETNROMXIN1Power(void) { diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c index 039b5c8..8bef280 100644 --- a/src/boards/resettxrom.c +++ b/src/boards/resettxrom.c @@ -30,21 +30,11 @@ static uint8 chip; static void M313CW(uint32 A, uint8 V) { - if (CHRptr[1]) { - chip = EXPREGS[0]; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, (V & 0x7F)); - } else - setchr1(A, (EXPREGS[0] << 7) | (V & 0x7F)); + setchr1(A, (EXPREGS[0] << 7) | (V & 0x7F)); } static void M313PW(uint32 A, uint8 V) { - if (PRGptr[1]) { - chip = EXPREGS[0]; - if (chip > PRGchip_max) chip &= PRGchip_max; - setprg8r(chip, A, (V & 0x0F)); - } else - setprg8(A, (EXPREGS[0] << 4) | (V & 0x0F)); + setprg8(A, (EXPREGS[0] << 4) | (V & 0x0F)); } static void M313Reset(void) { diff --git a/src/boards/supervision.c b/src/boards/supervision.c index 46be8ed..43b67f5 100644 --- a/src/boards/supervision.c +++ b/src/boards/supervision.c @@ -30,23 +30,12 @@ static SFORMAT StateRegs[] = static void Sync(void) { setchr8(0); - if (PRGptr[1]) - setprg8r((cmd0 & 0xC) >> 2, 0x6000, ((cmd0 & 0x3) << 4) | 0xF); - else - setprg8(0x6000, (((cmd0 & 0xF) << 4) | 0xF) + 4); + setprg8(0x6000, (((cmd0 & 0xF) << 4) | 0xF) + 4); if (cmd0 & 0x10) { - if (PRGptr[1]) { - setprg16r((cmd0 & 0xC) >> 2, 0x8000, ((cmd0 & 0x3) << 3) | (cmd1 & 7)); - setprg16r((cmd0 & 0xC) >> 2, 0xc000, ((cmd0 & 0x3) << 3) | 7); - } else { setprg16(0x8000, (((cmd0 & 0xF) << 3) | (cmd1 & 7)) + 2); setprg16(0xc000, (((cmd0 & 0xF) << 3) | 7) + 2); - } } else - if (PRGptr[4]) - setprg32r(4, 0x8000, 0); - else - setprg32(0x8000, 0); + setprg32(0x8000, 0); setmirror(((cmd0 & 0x20) >> 5) ^ 1); } diff --git a/src/boards/t-262.c b/src/boards/t-262.c index 7806d56..5aaa515 100644 --- a/src/boards/t-262.c +++ b/src/boards/t-262.c @@ -34,15 +34,8 @@ static SFORMAT StateRegs[] = static void Sync(void) { setchr8(0); - if (PRGptr[1]) { - chip = base >> 3; - if (chip > PRGchip_max) chip &= PRGchip_max; - setprg16r(chip, 0x8000, bank); - setprg16r(chip, 0xC000, (mode ? bank : 7)); - } else { - setprg16(0x8000, base | bank); - setprg16(0xC000, base | (mode ? bank : 7)); - } + setprg16(0x8000, base | bank); + setprg16(0xC000, base | (mode ? bank : 7)); setmirror(mirr); } diff --git a/src/unif.c b/src/unif.c index 8f496cf..a4a5fc0 100644 --- a/src/unif.c +++ b/src/unif.c @@ -452,7 +452,7 @@ static BMAPPING bmap[] = { { "GK-192", NO_INES, BMCGK192_Init, 0 }, /* mapper 58? */ { "GS-2004", 283, BMCGS2004_Init, 0 }, { "GS-2013", 283, BMCGS2013_Init, 0 }, - { "Ghostbusters63in1", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* 226 is non-split version */ + { "Ghostbusters63in1", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* similar to 226 but different bank order */ { "H2288", 123, UNLH2288_Init, 0 }, { "HKROM", 4, HKROM_Init, 0 }, { "KOF97", 263, UNLKOF97_Init, 0 }, @@ -585,7 +585,7 @@ static BMAPPING bmap[] = { { "JC-016-2", 205, Mapper205_Init, 0 }, { "AX-40G", 527, UNLAX40G_Init, 0 }, { " BMC-STREETFIGTER-GAME4IN1", NO_INES, BMCSFGAME4IN1_Init, 0 }, /* mapper 49? submapper 1*/ - { "G631", 226, BMCGhostbusters63in1_Init, 0 }, /* duplicate, probably wrong name */ + { "G631", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* duplicate, probably wrong name */ { "BJ-56", 526, UNLBJ56_Init, 0 }, { "L6IN1", 345, BMCL6IN1_Init, 0 }, { "CTC-12IN1", 337, BMCCTC12IN1_Init, 0 }, From 748f27571ded95ea2fa49d1a8b9bcf3bded171ae Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 11 Jul 2019 20:55:01 +0800 Subject: [PATCH 57/74] BMC-K-3088: Fix outer bank size --- src/boards/411120-c.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/boards/411120-c.c b/src/boards/411120-c.c index 706f192..765ce19 100644 --- a/src/boards/411120-c.c +++ b/src/boards/411120-c.c @@ -35,31 +35,18 @@ static uint8 reset_flag = 0; static uint8 chip, isK3088; static void BMC411120CCW(uint32 A, uint8 V) { - if (CHRptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, V); - } else - setchr1(A, V | ((EXPREGS[0] & 3) << 7)); + uint32 mask = isK3088 ? 0x07 : 0x03; + setchr1(A, V | ((EXPREGS[0] & mask) << 7)); } static void BMC411120CPW(uint32 A, uint8 V) { - if (PRGptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > PRGchip_max) chip &= PRGchip_max; - if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ - if (A == 0x8000) - setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); - } else /* MMC3 Mode */ - setprg8r(chip, A, (V & 0x0F)); - } else { - if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ - if (A == 0x8000) - /* bit 0-1 of register should be used as outer bank regardless of banking modes */ - setprg32(A, ((EXPREGS[0] >> 4) & 3) | ((EXPREGS[0] & 3) << 2)); - } else /* MMC3 Mode */ - setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); - } + uint32 mask = isK3088 ? 0x07 : 0x03; + if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ + if (A == 0x8000) + /* bit 0-1 of register should be used as outer bank regardless of banking modes */ + setprg32(A, ((EXPREGS[0] >> 4) & 3) | ((EXPREGS[0] & mask) << 2)); + } else /* MMC3 Mode */ + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & mask) << 4)); } static DECLFW(BMC411120CLoWrite) { From ec19b07b4d36cfe784bdac61260e1adb2e45527d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 12 Jul 2019 23:35:11 +0800 Subject: [PATCH 58/74] Mapper 226: Updated and remove duplicate mapper - Updated mapper 226 to support 1.5mb carts, which in turn makes Unif Ghostbusters63n1 a duplicate. - Unif 42in1ResetSwitch switch to mapper 233 --- src/boards/bmc42in1r.c | 31 +++++++++-- src/boards/ghostbusters63in1.c | 96 ---------------------------------- src/cart.h | 6 ++- src/ines.c | 3 ++ src/unif.c | 11 ++-- 5 files changed, 43 insertions(+), 104 deletions(-) delete mode 100644 src/boards/ghostbusters63in1.c diff --git a/src/boards/bmc42in1r.c b/src/boards/bmc42in1r.c index 6f7a2b3..ce66030 100644 --- a/src/boards/bmc42in1r.c +++ b/src/boards/bmc42in1r.c @@ -3,6 +3,7 @@ * Copyright notice for this file: * Copyright (C) 2005 CaH4e3 * Copyright (C) 2009 qeed + * Copyright (C) 2019 Libretro 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 @@ -22,10 +23,18 @@ * */ +/* Updated 2019-07-12 + * Mapper 266 - Updated and combine UNIF Ghostbusters63in1 board (1.5 MB carts), different bank order + * - some 1MB carts can switch game lists using Select + * Mapper 233 - UNIF 42in1ResetSwitch - reset-based switching + */ + #include "mapinc.h" +static uint8 reorder_banks = 0; static uint8 isresetbased = 0; static uint8 latche[2], reset; +static uint8 banks[4] = { 0, 0, 1, 2 }; static SFORMAT StateRegs[] = { { &reset, 1, "RST" }, @@ -34,11 +43,17 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { - uint8 bank; + uint8 bank = 0; + uint8 base = ((latche[0] & 0x80) >> 7) | ((latche[1] & 1) << 1); + if (isresetbased) bank = (latche[0] & 0x1f) | (reset << 5) | ((latche[1] & 1) << 6); - else - bank = (latche[0] & 0x1f) | ((latche[0] & 0x80) >> 2) | ((latche[1] & 1) << 6); + else { + if (reorder_banks) /* for 1536 KB prg roms */ + base = banks[base]; + bank = (base << 5) | (latche[0] & 0x1f); + } + if (!(latche[0] & 0x20)) setprg32(0x8000, bank >> 1); else { @@ -65,19 +80,29 @@ static void StateRestore(int version) { Sync(); } +static void M226Reset(void) { + latche[0] = latche[1] = reset = 0; + Sync(); +} + void Mapper226_Init(CartInfo *info) { isresetbased = 0; + /* 1536KiB PRG roms have different bank order */ + reorder_banks = ((info->prgRom * 16) == 1536) ? 1 : 0; info->Power = M226Power; + info->Reset = M226Reset; AddExState(&StateRegs, ~0, 0, 0); GameStateRestore = StateRestore; } static void M233Reset(void) { + latche[0] = latche[1] = 0; reset ^= 1; Sync(); } void Mapper233_Init(CartInfo *info) { + reorder_banks = 0; isresetbased = 1; info->Power = M226Power; info->Reset = M233Reset; diff --git a/src/boards/ghostbusters63in1.c b/src/boards/ghostbusters63in1.c deleted file mode 100644 index bdd1f1e..0000000 --- a/src/boards/ghostbusters63in1.c +++ /dev/null @@ -1,96 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * 63in1 ghostbusters - */ - -#include "mapinc.h" - -static uint8 reg[2], bank; -static uint8 banks[4] = { 0, 0, 1, 2 }; -static uint8 *CHRROM = NULL; -static uint32 CHRROMSIZE; - -static SFORMAT StateRegs[] = -{ - { reg, 2, "REGS" }, - { &bank, 1, "BANK" }, - { 0 } -}; - -static void Sync(void) { - if (reg[0] & 0x20) { - setprg16(0x8000, (banks[bank] << 5) | (reg[0] & 0x1F)); - setprg16(0xC000, (banks[bank] << 5) | (reg[0] & 0x1F)); - } else - setprg32(0x8000, ((banks[bank] << 5) | (reg[0] & 0x1F)) >> 1); - if (reg[1] & 2) - setchr8r(0x10, 0); - else - setchr8(0); - setmirror((reg[0] & 0x40) >> 6); -} - -static DECLFW(BMCGhostbusters63in1Write) { - reg[A & 1] = V; - bank = ((reg[0] & 0x80) >> 7) | ((reg[1] & 1) << 1); -/* FCEU_printf("reg[0]=%02x, reg[1]=%02x, bank=%02x\n",reg[0],reg[1],bank); */ - Sync(); -} - -static DECLFR(BMCGhostbusters63in1Read) { - if (bank == 1) - return X.DB; - else - return CartBR(A); -} - -static void BMCGhostbusters63in1Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, BMCGhostbusters63in1Read); - SetWriteHandler(0x8000, 0xFFFF, BMCGhostbusters63in1Write); -} - -static void BMCGhostbusters63in1Reset(void) { - reg[0] = reg[1] = 0; -} - -static void StateRestore(int version) { - Sync(); -} - -static void BMCGhostbusters63in1Close(void) { - if (CHRROM) - FCEU_gfree(CHRROM); - CHRROM = NULL; -} - -void BMCGhostbusters63in1_Init(CartInfo *info) { - info->Reset = BMCGhostbusters63in1Reset; - info->Power = BMCGhostbusters63in1Power; - info->Close = BMCGhostbusters63in1Close; - - CHRROMSIZE = 8192; /* dummy CHRROM, VRAM disable */ - CHRROM = (uint8*)FCEU_gmalloc(CHRROMSIZE); - SetupCartPRGMapping(0x10, CHRROM, CHRROMSIZE, 0); - AddExState(CHRROM, CHRROMSIZE, 0, "CROM"); - - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/cart.h b/src/cart.h index 66f3e83..56875da 100644 --- a/src/cart.h +++ b/src/cart.h @@ -20,8 +20,10 @@ typedef struct { * set to mapper 4. */ int battery; /* Presence of an actual battery. */ - int prgRam; /* prg ram size (volatile) */ - int chrRam; /* chr ram size (volatile) */ + int prgRom; /* total prg rom size in 16 K chunks */ + int chrRom; /* total chr rom size in 8 K chunks */ + int prgRam; /* prg ram size (volatile) */ + int chrRam; /* chr ram size (volatile) */ int prgRam_battery; /* prg ram size (non-volatile or battery backed) */ int chrRam_battery; /* chr ram size (non-volatile or battery backed) */ int region; /* video system timing (ntsc, pal, dendy */ diff --git a/src/ines.c b/src/ines.c index 1db9530..781f4d3 100644 --- a/src/ines.c +++ b/src/ines.c @@ -819,6 +819,9 @@ int iNESLoad(const char *name, FCEUFILE *fp) { } else if (((prgRom * 0x4000) + (chrRom * 0x2000)) < filesize) FCEU_PrintError(" File contains %llu bytes of unused data\n", filesize - ((prgRom * 0x4000) + (chrRom * 0x2000))); + iNESCart.prgRom = prgRom; + iNESCart.chrRom = chrRom; + ROM_size = uppow2(prgRom); if (chrRom) diff --git a/src/unif.c b/src/unif.c index a4a5fc0..51502a4 100644 --- a/src/unif.c +++ b/src/unif.c @@ -414,7 +414,7 @@ static BMAPPING bmap[] = { { "22211", 132, UNL22211_Init, 0 }, { "3D-BLOCK", 355, UNL3DBlock_Init, 0 }, { "411120-C", 287, BMC411120C_Init, 0 }, - { "42in1ResetSwitch", 226, Mapper226_Init, 0 }, + { "42in1ResetSwitch", 233, Mapper233_Init, 0 }, { "43272", 227, UNL43272_Init, 0 }, { "603-5052", 238, UNL6035052_Init, 0 }, { "64in1NoRepeat", 314, BMC64in1nr_Init, 0 }, @@ -452,7 +452,7 @@ static BMAPPING bmap[] = { { "GK-192", NO_INES, BMCGK192_Init, 0 }, /* mapper 58? */ { "GS-2004", 283, BMCGS2004_Init, 0 }, { "GS-2013", 283, BMCGS2013_Init, 0 }, - { "Ghostbusters63in1", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* similar to 226 but different bank order */ + { "Ghostbusters63in1", 226, Mapper226_Init, 0 }, { "H2288", 123, UNLH2288_Init, 0 }, { "HKROM", 4, HKROM_Init, 0 }, { "KOF97", 263, UNLKOF97_Init, 0 }, @@ -585,7 +585,7 @@ static BMAPPING bmap[] = { { "JC-016-2", 205, Mapper205_Init, 0 }, { "AX-40G", 527, UNLAX40G_Init, 0 }, { " BMC-STREETFIGTER-GAME4IN1", NO_INES, BMCSFGAME4IN1_Init, 0 }, /* mapper 49? submapper 1*/ - { "G631", NO_INES, BMCGhostbusters63in1_Init, 0 }, /* duplicate, probably wrong name */ + { "G631", 226, Mapper226_Init, 0 }, /* duplicate, probably wrong name */ { "BJ-56", 526, UNLBJ56_Init, 0 }, { "L6IN1", 345, BMCL6IN1_Init, 0 }, { "CTC-12IN1", 337, BMCCTC12IN1_Init, 0 }, @@ -731,6 +731,11 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { if (!LoadUNIFChunks(fp)) goto aborto; + UNIFCart.prgRom = (UNIF_PRGROMSize / 0x1000) + ((UNIF_PRGROMSize % 0x1000) ? 1 : 0); + UNIFCart.prgRom = (UNIFCart.prgRom >> 2) + ((UNIFCart.prgRom & 3) ? 1: 0); + UNIFCart.chrRom = (UNIF_CHRROMSize / 0x400) + ((UNIF_CHRROMSize % 0x400) ? 1 : 0); + UNIFCart.chrRom = (UNIFCart.chrRom >> 3) + ((UNIFCart.chrRom & 7) ? 1: 0); + ROM_size = FixRomSize(UNIF_PRGROMSize, 2048); if (UNIF_CHRROMSize) VROM_size = FixRomSize(UNIF_CHRROMSize, 8192); From 26f2dcafe277ea0e4f4da2270636bc2fe1037a37 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 17 Jul 2019 05:55:37 +0800 Subject: [PATCH 59/74] Try to fix PS3 save state issue. In the past while fixing state problems i Wii, this section was the last one i found to be a problem as well. Ignoring this state variable fixes the last Wii state loading problem. PS3 has recently been reported as having state problems and could be similar issue. So, lets just ignore this state variable for all big-endian platforms. --- src/sound.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sound.c b/src/sound.c index 03646af..7ba8d84 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1233,7 +1233,8 @@ SFORMAT FCEUSND_STATEINFO[] = { * issues loading states with this. Increasing it only helps a few games. * Disabling this state variable for Wii/WiiU/GC for now. */ /* TODO: fix this for better runahead feature for big-endian */ -#ifndef GEKKO +/* UPDATE: Try to ignore this for all big-endian for now */ +#ifndef MSB_FIRST /* wave buffer is used for filtering, only need first 17 values from it */ { &Wave, 32 * sizeof(int32), "WAVE"}, #endif From 3a4556dec6785b2d22c4bdd5e3c131327ece9b2d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 19 Jul 2019 15:02:30 +0800 Subject: [PATCH 60/74] Update libretro-common --- .../libretro-common/compat/compat_snprintf.c | 19 +- .../libretro-common/include/compat/msvc.h | 9 +- .../include/compat/msvc/stdint.h | 3 - .../libretro-common/include/libretro.h | 202 +++++++++++++++++- .../libretro-common/include/retro_common.h | 3 +- .../include/retro_common_api.h | 3 +- .../libretro-common/include/retro_inline.h | 39 ++++ .../include/streams/memory_stream.h | 2 +- .../libretro-common/streams/memory_stream.c | 2 +- 9 files changed, 262 insertions(+), 20 deletions(-) create mode 100644 src/drivers/libretro/libretro-common/include/retro_inline.h diff --git a/src/drivers/libretro/libretro-common/compat/compat_snprintf.c b/src/drivers/libretro/libretro-common/compat/compat_snprintf.c index 40734a6..b69ad04 100644 --- a/src/drivers/libretro/libretro-common/compat/compat_snprintf.c +++ b/src/drivers/libretro/libretro-common/compat/compat_snprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_snprintf.c). @@ -23,9 +23,7 @@ /* THIS FILE HAS NOT BEEN VALIDATED ON PLATFORMS BESIDES MSVC */ #ifdef _MSC_VER -#include - -#include /* added for _vsnprintf_s and _vscprintf on VS2015 and VS2017 */ +#include #include #if _MSC_VER < 1800 @@ -53,14 +51,23 @@ int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list int count = -1; if (size != 0) + { #if (_MSC_VER <= 1310) - count = _vsnprintf(outBuf, size, format, ap); + count = _vsnprintf(outBuf, size - 1, format, ap); #else - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + count = _vsnprintf_s(outBuf, size, size - 1, format, ap); #endif + } + if (count == -1) count = _vscprintf(format, ap); + if (count == size) + { + /* there was no room for a NULL, so truncate the last character */ + outBuf[size - 1] = '\0'; + } + return count; } diff --git a/src/drivers/libretro/libretro-common/include/compat/msvc.h b/src/drivers/libretro/libretro-common/include/compat/msvc.h index fea4b53..4681b12 100644 --- a/src/drivers/libretro/libretro-common/include/compat/msvc.h +++ b/src/drivers/libretro/libretro-common/include/compat/msvc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (msvc.h). @@ -39,8 +39,8 @@ extern "C" { int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); #endif -/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ -#if _MSC_VER < 1600 +/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ +#if _MSC_VER < 1500 #include #include #ifndef vsnprintf @@ -56,6 +56,8 @@ extern "C" { #undef UNICODE /* Do not bother with UNICODE at this time. */ #include #include + +#define _USE_MATH_DEFINES #include /* Python headers defines ssize_t and sets HAVE_SSIZE_T. @@ -125,4 +127,3 @@ typedef int ssize_t; #endif #endif - diff --git a/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h b/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h index c791176..7c91a68 100644 --- a/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h +++ b/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h @@ -67,7 +67,6 @@ extern "C" { # endif #endif - /* 7.18.1 Integer types. */ /* 7.18.1.1 Exact-width integer types. */ @@ -94,7 +93,6 @@ extern "C" { typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; - /* 7.18.1.2 Minimum-width integer types. */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; @@ -255,4 +253,3 @@ typedef uint64_t uintmax_t; #endif #endif - diff --git a/src/drivers/libretro/libretro-common/include/libretro.h b/src/drivers/libretro/libretro-common/include/libretro.h index 8daec83..1fd2f5b 100644 --- a/src/drivers/libretro/libretro-common/include/libretro.h +++ b/src/drivers/libretro/libretro-common/include/libretro.h @@ -614,7 +614,7 @@ enum retro_mod * Afterward it may be called again for the core to communicate * updated options to the frontend, but the number of core * options must not change from the number in the initial call. - * + * * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. * retro_variable::key should be namespaced to not collide @@ -1106,6 +1106,148 @@ enum retro_mod * It will return a bitmask of all the digital buttons. */ +#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52 + /* unsigned * -- + * Unsigned value is the API version number of the core options + * interface supported by the frontend. If callback return false, + * API version is assumed to be 0. + * + * In legacy code, core options are set by passing an array of + * retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES. + * This may be still be done regardless of the core options + * interface version. + * + * If version is 1 however, core options may instead be set by + * passing an array of retro_core_option_definition structs to + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of + * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. + * This allows the core to additionally set option sublabel information + * and/or provide localisation support. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53 + /* const struct retro_core_option_definition ** -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS + * returns an API version of 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * 'data' points to an array of retro_core_option_definition structs + * terminated by a { NULL, NULL, NULL, {{0}}, NULL } element. + * retro_core_option_definition::key should be namespaced to not collide + * with other implementations' keys. e.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_core_option_definition::desc should contain a human readable + * description of the key. + * retro_core_option_definition::info should contain any additional human + * readable information text that a typical user may need to + * understand the functionality of the option. + * retro_core_option_definition::values is an array of retro_core_option_value + * structs terminated by a { NULL, NULL } element. + * > retro_core_option_definition::values[index].value is an expected option + * value. + * > retro_core_option_definition::values[index].label is a human readable + * label used when displaying the value on screen. If NULL, + * the value itself is used. + * retro_core_option_definition::default_value is the default core option + * setting. It must match one of the expected option values in the + * retro_core_option_definition::values array. If it does not, or the + * default value is NULL, the first entry in the + * retro_core_option_definition::values array is treated as the default. + * + * The number of possible options should be very limited, + * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * First entry should be treated as a default. + * + * Example entry: + * { + * "foo_option", + * "Speed hack coprocessor X", + * "Provides increased performance at the expense of reduced accuracy", + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54 + /* const struct retro_core_options_intl * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS + * returns an API version of 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS, + * with the addition of localisation support. The description of the + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted + * for further details. + * + * 'data' points to a retro_core_options_intl struct. + * + * retro_core_options_intl::us is a pointer to an array of + * retro_core_option_definition structs defining the US English + * core options implementation. It must point to a valid array. + * + * retro_core_options_intl::local is a pointer to an array of + * retro_core_option_definition structs defining core options for + * the current frontend language. It may be NULL (in which case + * retro_core_options_intl::us is used by the frontend). Any items + * missing from this array will be read from retro_core_options_intl::us + * instead. + * + * NOTE: Default core option values are always taken from the + * retro_core_options_intl::us array. Any default values in + * retro_core_options_intl::local array will be ignored. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55 + /* struct retro_core_option_display * -- + * + * Allows an implementation to signal the environment to show + * or hide a variable when displaying core options. This is + * considered a *suggestion*. The frontend is free to ignore + * this callback, and its implementation not considered mandatory. + * + * 'data' points to a retro_core_option_display struct + * + * retro_core_option_display::key is a variable identifier + * which has already been set by SET_VARIABLES/SET_CORE_OPTIONS. + * + * retro_core_option_display::visible is a boolean, specifying + * whether variable should be displayed + * + * Note that all core option variables will be set visible by + * default when calling SET_VARIABLES/SET_CORE_OPTIONS. + */ + /* VFS functionality */ /* File paths: @@ -2351,6 +2493,64 @@ struct retro_variable const char *value; }; +struct retro_core_option_display +{ + /* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */ + const char *key; + + /* Specifies whether variable should be displayed + * when presenting core options to the user */ + bool visible; +}; + +/* Maximum number of values permitted for a core option + * NOTE: This may be increased on a core-by-core basis + * if required (doing so has no effect on the frontend) */ +#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 + +struct retro_core_option_value +{ + /* Expected option value */ + const char *value; + + /* Human-readable value label. If NULL, value itself + * will be displayed by the frontend */ + const char *label; +}; + +struct retro_core_option_definition +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */ + const char *key; + + /* Human-readable core option description (used as menu label) */ + const char *desc; + + /* Human-readable core option information (used as menu sublabel) */ + const char *info; + + /* Array of retro_core_option_value structs, terminated by NULL */ + struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; + + /* Default core option value. Must match one of the values + * in the retro_core_option_value array, otherwise will be + * ignored */ + const char *default_value; +}; + +struct retro_core_options_intl +{ + /* Pointer to an array of retro_core_option_definition structs + * - US English implementation + * - Must point to a valid array */ + struct retro_core_option_definition *us; + + /* Pointer to an array of retro_core_option_definition structs + * - Implementation for current frontend language + * - May be NULL */ + struct retro_core_option_definition *local; +}; + struct retro_game_info { const char *path; /* Path to game, UTF-8 encoded. diff --git a/src/drivers/libretro/libretro-common/include/retro_common.h b/src/drivers/libretro/libretro-common/include/retro_common.h index 5938bea..9a1fd5f 100644 --- a/src/drivers/libretro/libretro-common/include/retro_common.h +++ b/src/drivers/libretro/libretro-common/include/retro_common.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common.h). @@ -34,4 +34,3 @@ in a public API, you may need this. #include #endif - diff --git a/src/drivers/libretro/libretro-common/include/retro_common_api.h b/src/drivers/libretro/libretro-common/include/retro_common_api.h index ff38f98..fc4f745 100644 --- a/src/drivers/libretro/libretro-common/include/retro_common_api.h +++ b/src/drivers/libretro/libretro-common/include/retro_common_api.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common_api.h). @@ -113,6 +113,5 @@ Of course, another school of thought is that you should do as little damage as p in as few places as possible... */ - /* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ #endif diff --git a/src/drivers/libretro/libretro-common/include/retro_inline.h b/src/drivers/libretro/libretro-common/include/retro_inline.h new file mode 100644 index 0000000..e4a21f6 --- /dev/null +++ b/src/drivers/libretro/libretro-common/include/retro_inline.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_inline.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_INLINE_H +#define __LIBRETRO_SDK_INLINE_H + +#ifndef INLINE + +#if defined(_WIN32) || defined(__INTEL_COMPILER) +#define INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L +#define INLINE inline +#elif defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + +#endif +#endif diff --git a/src/drivers/libretro/libretro-common/include/streams/memory_stream.h b/src/drivers/libretro/libretro-common/include/streams/memory_stream.h index fba8783..c594808 100644 --- a/src/drivers/libretro/libretro-common/include/streams/memory_stream.h +++ b/src/drivers/libretro/libretro-common/include/streams/memory_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.h). diff --git a/src/drivers/libretro/libretro-common/streams/memory_stream.c b/src/drivers/libretro/libretro-common/streams/memory_stream.c index 784d0fe..77a2c00 100644 --- a/src/drivers/libretro/libretro-common/streams/memory_stream.c +++ b/src/drivers/libretro/libretro-common/streams/memory_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.c). From 1df85a748328c02004fb17ce4d8648c4022c8ef8 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 20 Jul 2019 00:55:17 +0800 Subject: [PATCH 61/74] BMC-80013B: Fix incorrect bank map --- src/boards/bmc80013b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/bmc80013b.c b/src/boards/bmc80013b.c index bfe6b27..ddf413e 100644 --- a/src/boards/bmc80013b.c +++ b/src/boards/bmc80013b.c @@ -37,7 +37,7 @@ static void Sync(void) { if (mode & 0x02) setprg16(0x8000, (regs[0] & 0x0F) | (regs[1] & 0x70)); else - setprg16r(1, 0x8000, regs[0] & 0x03); + setprg16(0x8000, regs[0] & 0x0F | 0x80); setprg16(0xC000, regs[1]); setmirror(((regs[0] >> 4) & 1) ^ 1); } From 3659603d19d3c0bb3dd90c0542729fe422d807e9 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 20 Jul 2019 00:12:02 +0800 Subject: [PATCH 62/74] Add core option sublabels --- src/drivers/libretro/dipswitch.c | 164 ++++-- src/drivers/libretro/dipswitch.h | 2 +- src/drivers/libretro/libretro.c | 68 +-- src/drivers/libretro/libretro_core_options.h | 563 +++++++++++++++++++ 4 files changed, 690 insertions(+), 107 deletions(-) create mode 100644 src/drivers/libretro/libretro_core_options.h diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/dipswitch.c index 610dde2..b30b318 100644 --- a/src/drivers/libretro/dipswitch.c +++ b/src/drivers/libretro/dipswitch.c @@ -944,9 +944,14 @@ static VSUNIGAME dipswitch_topgun = { } }; +typedef struct { + char value[100]; + char label[100]; +} VSUNIGAMEOPT_VALUE; + typedef struct { char key[64]; - char val[150]; + VSUNIGAMEOPT_VALUE val[10]; } VSUNIGAMEOPT; static VSUNIGAME *vsgame = NULL; @@ -967,34 +972,32 @@ static void str_to_corekey_label(char *str) static void make_core_options(void) { - unsigned i, dipswitch_size; - char core_prefix[32]; + unsigned i, j, num_dipswitch; + char *romname_short = NULL; - dipswitch_size = vsgame->dipswitch_size; - sprintf(core_prefix, "fceumm_dipswitch_%s", vsgame->romname_short); - for (i = 0; i < dipswitch_size; i++) + num_dipswitch = vsgame->dipswitch_size; + romname_short = vsgame->romname_short; + for (i = 0; i < num_dipswitch; i++) { - unsigned x; char core_key[64], core_values[150]; - DIPSWITCH *coreoptions = &vsgame->dipswitch_core_options[i]; + unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + const char *option_name = vsgame->dipswitch_core_options[i].option_name; - /* make var key string from list */ - sprintf(core_key, "%s%c%s", core_prefix, '-', coreoptions->option_name); + memset(core_key, 0 , sizeof(core_key)); + memset(core_values, 0 , sizeof(core_values)); + + /* Create core key string */ + sprintf(core_key, "fceumm_dipswitch_%s-%s", romname_short, option_name); + /* sanitize core key string */ str_to_corekey_label(core_key); - - /* make var values string from lists of values */ - sprintf(core_values, "%s; ", coreoptions->option_name); - for (x = 0; x < coreoptions->settings_size; x++) - { - SETTING *corevalues = &coreoptions->settings[x]; - - strcat(core_values, corevalues->name); - if ((coreoptions->settings_size - 1) > x) - strcat(core_values, "|"); - } - sprintf(vscoreopt[i].key, "%s", core_key); - sprintf(vscoreopt[i].val, "%s", core_values); + + /* Create core values */ + for (j = 0; j < num_values; j++) + { + const char *var_value = vsgame->dipswitch_core_options[i].settings[j].name; + sprintf(vscoreopt[i].val[j].value, "%s", var_value); + } } } @@ -1067,25 +1070,25 @@ static void update_dipswitch_vsuni(void) { struct retro_variable var = {0}; unsigned idx_dips, idx_var; - uint8 vsdip_new = 0x00; + uint8 vsdip_new = FCEUI_VSUniGetDIPs(); - if (vsgame == NULL) - return; - - vsdip_new = FCEUI_VSUniGetDIPs(); for (idx_dips = 0; idx_dips < vsgame->dipswitch_size; idx_dips++) { - DIPSWITCH *core_option = &vsgame->dipswitch_core_options[idx_dips]; - var.key = vscoreopt[idx_dips].key; + const char *key = vscoreopt[idx_dips].key; + unsigned num_options = vsgame->dipswitch_core_options[idx_dips].settings_size; + + var.key = key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) continue; - for (idx_var = 0; idx_var < core_option->settings_size; idx_var++) + for (idx_var = 0; idx_var < num_options; idx_var++) { - SETTING *vs_settings = &core_option->settings[idx_var]; - if (strcmp(var.value, vs_settings->name) != 0) + const char *var_value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].name; + uint8 value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].value; + uint8 mask = vsgame->dipswitch_core_options[idx_dips].mask; + if (strcmp(var.value, var_value) != 0) continue; - vsdip_new &= ~core_option->mask; - vsdip_new |= vs_settings->value; + vsdip_new &= ~mask; + vsdip_new |= value; } } @@ -1101,28 +1104,67 @@ static void update_dipswitch_vsuni(void) } /* Nintendo World Championship */ -static struct retro_variable dipswitch_nwc[] = { - { "fceumm_dipswitch_nwc_swa", "Dipswitch SW1 (18.7s); disabled|enabled" }, - { "fceumm_dipswitch_nwc_swb", "Dipswitch SW2 (37.5s); disabled|enabled" }, - { "fceumm_dipswitch_nwc_swc", "Dipswitch SW3 (1m 15s); enabled|disabled" }, - { "fceumm_dipswitch_nwc_swd", "Dipswitch SW4 (2m 30s); disabled|enabled" }, - { NULL, NULL } +static struct retro_core_option_definition dipswitch_nwc[] = { + { + "fceumm_dipswitch_nwc_swa", + "Dipswitch SW1 (+18.7secs)", + "Adds 18.7 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_dipswitch_nwc_swb", + "Dipswitch SW1 (+37.5s)", + "Adds 37.5 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_dipswitch_nwc_swc", + "Dipswitch SW1 (+1m 15s)", + "Adds 1 minute and 15 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_dipswitch_nwc_swd", + "Dipswitch SW1 (+2m 30s)", + "Adds 2 minutes and 30 seconds to total time. Total time = 5 mins + time of enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, }; static void update_dipswitch_nwc(void) { struct retro_variable var = {0}; unsigned dips = 0x00; - unsigned index; + unsigned i; - for (index = 0; index < 4; index++) + for (i = 0; i < 4; i++) { - struct retro_variable *nwc = &dipswitch_nwc[index]; - var.key = nwc->key; + const char *key = dipswitch_nwc[i].key; + var.key = key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) - dips |= (1 << index); + dips |= (1 << i); } } @@ -1136,9 +1178,9 @@ static void update_dipswitch_nwc(void) } } -void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) +void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars) { - unsigned i, idx = *index; + unsigned idx = *index; /* VSUNI Dipswitch */ if (GameInfo->type == GIT_VSUNI) @@ -1146,10 +1188,25 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) vsgame = get_vsuni_dipswitch(GameInfo->gameid); if (vsgame) { + unsigned i, j; + unsigned num_options = vsgame->dipswitch_size; + make_core_options(); - for (i = 0; i < vsgame->dipswitch_size; i++, idx++) { - vars[idx].key = vscoreopt[i].key; - vars[idx].value = vscoreopt[i].val; + + for (i = 0; i < num_options; i++) { + const char *key = vscoreopt[i].key; + const char *desc = vsgame->dipswitch_core_options[i].option_name; + unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + + vars[idx].key = key; + vars[idx].desc = desc; + + for (j = 0; j < num_values; j++) { + char *value = vscoreopt[i].val[j].value; + vars[idx].values[j].value = value; + } + + idx++; } } } @@ -1157,7 +1214,8 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) /* Nintendo World Championship cart (Mapper 105)*/ if (iNESCart.mapper == 105) { - i = 0; + unsigned i = 0; + while (dipswitch_nwc[i].key) { vars[idx] = dipswitch_nwc[i]; idx++; @@ -1165,7 +1223,7 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) } } - *index = idx; + *index = idx; } void update_dipswitch(void) diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/dipswitch.h index 8b03006..d5a1d8a 100644 --- a/src/drivers/libretro/dipswitch.h +++ b/src/drivers/libretro/dipswitch.h @@ -3,7 +3,7 @@ #include -void set_dipswitch_variables(unsigned *index, struct retro_variable *vars); +void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars); void update_dipswitch(void); extern retro_environment_t environ_cb; diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 077790d..7c40219 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -30,6 +30,7 @@ #include "libretro-common/include/streams/memory_stream.h" #include "dipswitch.h" +#include "libretro_core_options.h" #define MAX_PLAYERS 4 /* max supported players */ #define MAX_PORTS 2 /* max controller ports, @@ -80,6 +81,7 @@ static unsigned turbo_delay = 0; static unsigned input_type[MAX_PLAYERS + 1] = {0}; /* 4-players + famicom expansion */ enum RetroZapperInputModes{RetroLightgun, RetroMouse, RetroPointer}; static enum RetroZapperInputModes zappermode = RetroLightgun; +static unsigned show_advance_sound_options; /* emulator-specific variables */ @@ -744,63 +746,22 @@ void retro_set_controller_port_device(unsigned port, unsigned device) static void set_variables(void) { - static const struct retro_variable vars[] = { - { "fceumm_region", "Region Override; Auto|NTSC|PAL|Dendy" }, - { "fceumm_aspect", "Preferred aspect ratio; 8:7 PAR|4:3" }, - { "fceumm_palette", "Color Palette; default|asqrealc|nintendo-vc|rgb|yuv-v3|unsaturated-final|sony-cxa2025as-us|pal|bmf-final2|bmf-final3|smooth-fbx|composite-direct-fbx|pvm-style-d93-fbx|ntsc-hardware-fbx|nes-classic-fbx-fs|nescap|wavebeam|raw|custom" }, - { "fceumm_up_down_allowed", "Allow Opposing Directions; disabled|enabled" }, -#ifdef PSP - { "fceumm_overscan", "Crop Overscan; enabled|disabled" }, -#else - { "fceumm_overscan_h", "Crop Overscan (Horizontal); disabled|enabled" }, - { "fceumm_overscan_v", "Crop Overscan (Vertical); enabled|disabled" }, -#endif - { "fceumm_nospritelimit", "No Sprite Limit; disabled|enabled" }, - { "fceumm_sndvolume", "Sound Volume; 150|160|170|180|190|200|210|220|230|240|250|0|10|20|30|40|50|60|70|80|90|100|110|120|130|140" }, - { "fceumm_sndquality", "Sound Quality; Low|High|Very High" }, - { "fceumm_swapduty", "Swap Duty Cycles; disabled|enabled" }, -#ifdef DEBUG - { "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" }, - { "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" }, - { "fceumm_apu_3", "Enable Sound Channel 3 (Triangle); enabled|disabled" }, - { "fceumm_apu_4", "Enable Sound Channel 4 (Noise); enabled|disabled" }, - { "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" }, -#endif - { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, - { "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" }, - { "fceumm_zapper_mode", "Zapper Mode; lightgun|touchscreen|mouse" }, - { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, - { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, - { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, - { NULL, NULL } - }; + unsigned i = 0, index = 0; - static struct retro_variable vars_empty = { NULL, NULL }; - static struct retro_variable retro_vars[32]; - unsigned i = 0, index_core = 0; + /* Initialize main core option struct */ + for (i = 0; i < MAX_CORE_OPTIONS; i++) + option_defs_us[i] = option_defs_empty; - while (vars[index_core].key != NULL) - { - retro_vars[index_core].key = vars[index_core].key; - retro_vars[index_core].value = vars[index_core].value; - index_core++; + /* Write common core options to main struct */ + while (option_defs_common[index].key) { + option_defs_us[index] = option_defs_common[index]; + index++; } - /* append dipswitches to core options if available */ - set_dipswitch_variables(&index_core, retro_vars); + /* Append dipswitch settings to core options if available */ + set_dipswitch_variables(&index, option_defs_us); - /* NULL terminate */ - retro_vars[index_core] = vars_empty; - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)retro_vars); - -#ifdef DEBUG - /* list core options */ - i = 0; - while (retro_vars[i].key) { - FCEU_printf(" { '%s', '%s' }\n", retro_vars[i].key, retro_vars[i].value); - i++; - } -#endif + libretro_set_core_options(environ_cb); } void retro_set_environment(retro_environment_t cb) @@ -1316,7 +1277,8 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - sndvolume = atoi(var.value); + int val = (int)(atof(var.value) * 25.6); + sndvolume = val; FCEUD_SoundToggle(); } diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h new file mode 100644 index 0000000..877c05f --- /dev/null +++ b/src/drivers/libretro/libretro_core_options.h @@ -0,0 +1,563 @@ +#ifndef LIBRETRO_CORE_OPTIONS_H__ +#define LIBRETRO_CORE_OPTIONS_H__ + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ******************************** + * Core Option Definitions + ******************************** +*/ + +/* RETRO_LANGUAGE_ENGLISH */ + +/* Default language: + * - All other languages must include the same keys and values + * - Will be used as a fallback in the event that frontend language + * is not available + * - Will be used as a fallback for any missing entries in + * frontend language definition */ + +#define MAX_CORE_OPTIONS 32 + +struct retro_core_option_definition option_defs_common[] = { + { + "fceumm_region", + "Region Override", + "Force core to use NTSC, PAL or Dendy region timings.", + { + { "Auto", NULL }, + { "NTSC", NULL }, + { "PAL", NULL }, + { "Dendy", NULL }, + { NULL, NULL}, + }, + "Auto", + }, + { + "fceumm_aspect", + "Preferred aspect ratio", + "Choose prefered aspect ratio.", + { + { "8:7 PAR", NULL }, + { "4:3", NULL }, + { NULL, NULL}, + }, + "8:7 PAR", + }, + { + "fceumm_palette", + "Color Palette", + "Choose from pre-generted palettes, a custom 64x3 palette from file or raw format (needs to use a nes-decoder shader).", + { + { "default", NULL }, + { "asqrealc", NULL }, + { "nintendo-vc", NULL }, + { "rgb", NULL }, + { "yuv-v3", NULL }, + { "unsaturated-final", NULL }, + { "sony-cxa2025as-us", NULL }, + { "pal", NULL }, + { "bmf-final2", NULL }, + { "bmf-final3", NULL }, + { "smooth-fbx", NULL }, + { "composite-direct-fbx", NULL }, + { "pvm-style-d93-fbx", NULL }, + { "ntsc-hardware-fbx", NULL }, + { "nes-classic-fbx-fs", NULL }, + { "nescap", NULL }, + { "wavebeam", NULL }, + { "raw", NULL }, + { "custom", NULL }, + { NULL, NULL}, + }, + "default", + }, + { + "fceumm_up_down_allowed", + "Allow Opposing Directions", + "Allows simultaneous UP+DOWN or LEFT+RIGHT button combination which can create different effects in some games.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + +#ifdef PSP + { + "fceumm_overscan", + "Crop Overscan", + "Removes 8 pixel overscan from all sides", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#else + { + "fceumm_overscan_h", + "Crop Overscan (Horizontal)", + "Removes 8 pixel from left and right of screen to simulates overscans seen on standard CRT television.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_overscan_v", + "Crop Overscan (Vertical)", + "Removes 8 pixel from top and bottom of screen to simulates overscans seen on standard CRT television.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#endif + { + "fceumm_nospritelimit", + "No Sprite Limit", + "Removes the 8-per-scanline hardware limit. This reduces sprite flickering but can cause some games to glitch since some use this for effects.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_sndvolume", + "Sound Volume", + "Change master volume level", + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL}, + }, + "7", + }, + { + "fceumm_sndquality", + "Sound Quality", + "Enable higher quality sounds in exchange for more processing power required", + { + { "Low", NULL }, + { "High", NULL }, + { "Very High", NULL }, + { NULL, NULL}, + }, + "Low", + }, + { + "fceumm_swapduty", + "Swap Duty Cycles", + "Simulates the sound from famiclones has the pulse wave channels duty cycle bits reversed.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_turbo_enable", + "Turbo Enable", + "Enables or disables turbo buttons.", + { + { "None", NULL }, + { "Player 1", NULL }, + { "Player 2", NULL }, + { "Both", NULL }, + { NULL, NULL}, + }, + "None", + }, + { + "fceumm_turbo_delay", + "Turbo Delay (in frames)", + "Repeat rate of turbo buttons in frames.", + { + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "30", NULL }, + { "60", NULL }, + { NULL, NULL}, + }, + "3", + }, + { + "fceumm_zapper_mode", + "Zapper Mode", + "Selects device to use for zapper games.", + { + { "lightgun", NULL }, + { "touchscreen", NULL }, + { "mouse", NULL }, + { NULL, NULL}, + }, + "lightgun", + }, + { + "fceumm_show_crosshair", + "Show Crosshair", + "Shows or hides on-screen crosshairs when using a zapper.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_overclocking", + "Overclocking", + "Enables or disables overclocking which can reduce slowdowns in some games. Postrender method is more compatible with every game with Vblank more effective for games like Contra Force.", + { + { "disabled", NULL }, + { "2x-Postrender", NULL }, + { "2x-VBlank", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_ramstate", + "RAM power up state (Restart)", + "Choose RAM startup during power up. Some games rely on initial ram values for random generator as an example.", + { + { "fill $ff", NULL }, + { "fill $00", NULL }, + { "random", NULL }, + { NULL, NULL}, + }, + "fill $ff", + }, +#ifdef DEBUG + { + "fceumm_apu_1", + "Channel 1 (Square 1)", + "Enables or disables pulse wave generator audio output 1.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_2", + "Channel 2 (Square 2)", + "Enables or disables pulse wave generator audio output 2.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_3", + "Channel 3 (Triangle)", + "Enables or disables triangle wave generator audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_4", + "Channel 4 (Noise)", + "Enables or disables noise generator audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_5", + "Channel 5 (PCM)", + "Enables or disables delta modulation channel audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#endif + + { NULL, NULL, NULL, { NULL, NULL }, NULL }, +}; + +struct retro_core_option_definition option_defs_empty = { + NULL, NULL, NULL, { NULL, NULL }, NULL +}; + +struct retro_core_option_definition option_defs_us[MAX_CORE_OPTIONS]; + +/* RETRO_LANGUAGE_JAPANESE */ + +/* RETRO_LANGUAGE_FRENCH */ + +/* RETRO_LANGUAGE_SPANISH */ + +/* RETRO_LANGUAGE_GERMAN */ + +/* RETRO_LANGUAGE_ITALIAN */ + +/* RETRO_LANGUAGE_DUTCH */ + +/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + +/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + +/* RETRO_LANGUAGE_RUSSIAN */ + +/* RETRO_LANGUAGE_KOREAN */ + +/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + +/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + +/* RETRO_LANGUAGE_ESPERANTO */ + +/* RETRO_LANGUAGE_POLISH */ + +/* RETRO_LANGUAGE_VIETNAMESE */ + +/* RETRO_LANGUAGE_ARABIC */ + +/* RETRO_LANGUAGE_GREEK */ + +/* RETRO_LANGUAGE_TURKISH */ + +/* + ******************************** + * Language Mapping + ******************************** +*/ + +struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { + option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ + NULL, /* RETRO_LANGUAGE_JAPANESE */ + NULL, /* RETRO_LANGUAGE_FRENCH */ + NULL, /* RETRO_LANGUAGE_SPANISH */ + NULL, /* RETRO_LANGUAGE_GERMAN */ + NULL, /* RETRO_LANGUAGE_ITALIAN */ + NULL, /* RETRO_LANGUAGE_DUTCH */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + NULL, /* RETRO_LANGUAGE_RUSSIAN */ + NULL, /* RETRO_LANGUAGE_KOREAN */ + NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + NULL, /* RETRO_LANGUAGE_ESPERANTO */ + NULL, /* RETRO_LANGUAGE_POLISH */ + NULL, /* RETRO_LANGUAGE_VIETNAMESE */ + NULL, /* RETRO_LANGUAGE_ARABIC */ + NULL, /* RETRO_LANGUAGE_GREEK */ + NULL, /* RETRO_LANGUAGE_TURKISH */ +}; + +/* + ******************************** + * Functions + ******************************** +*/ + +/* Handles configuration/setting of core options. + * Should only be called inside retro_set_environment(). + * > We place the function body in the header to avoid the + * necessity of adding more .c files (i.e. want this to + * be as painless as possible for core devs) + */ + +static INLINE void libretro_set_core_options(retro_environment_t environ_cb) +{ + unsigned version = 0; + + if (!environ_cb) + return; + + if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1)) + { + struct retro_core_options_intl core_options_intl; + unsigned language = 0; + + core_options_intl.us = option_defs_us; + core_options_intl.local = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && + (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) + core_options_intl.local = option_defs_intl[language]; + + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); + } + else + { + size_t i; + size_t option_index = 0; + size_t num_options = 0; + struct retro_variable *variables = NULL; + char **values_buf = NULL; + + /* Determine number of options + * > Note: We are going to skip a number of irrelevant + * core options when building the retro_variable array, + * but we'll allocate space for all of them. The difference + * in resource usage is negligible, and this allows us to + * keep the code 'cleaner' */ + while (true) + { + if (option_defs_us[num_options].key) + num_options++; + else + break; + } + + /* Allocate arrays */ + variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); + values_buf = (char **)calloc(num_options, sizeof(char *)); + + if (!variables || !values_buf) + goto error; + + /* Copy parameters from option_defs_us array */ + for (i = 0; i < num_options; i++) + { + const char *key = option_defs_us[i].key; + const char *desc = option_defs_us[i].desc; + const char *default_value = option_defs_us[i].default_value; + struct retro_core_option_value *values = option_defs_us[i].values; + size_t buf_len = 3; + size_t default_index = 0; + + values_buf[i] = NULL; + + /* Skip options that are irrelevant when using the + * old style core options interface */ + if ((strcmp(key, "fceumm_advance_sound_options") == 0)) + continue; + + if (desc) + { + size_t num_values = 0; + + /* Determine number of values */ + while (true) + { + if (values[num_values].value) + { + /* Check if this is the default value */ + if (default_value) + if (strcmp(values[num_values].value, default_value) == 0) + default_index = num_values; + + buf_len += strlen(values[num_values].value); + num_values++; + } + else + break; + } + + /* Build values string */ + if (num_values > 1) + { + size_t j; + + buf_len += num_values - 1; + buf_len += strlen(desc); + + values_buf[i] = (char *)calloc(buf_len, sizeof(char)); + if (!values_buf[i]) + goto error; + + strcpy(values_buf[i], desc); + strcat(values_buf[i], "; "); + + /* Default value goes first */ + strcat(values_buf[i], values[default_index].value); + + /* Add remaining values */ + for (j = 0; j < num_values; j++) + { + if (j != default_index) + { + strcat(values_buf[i], "|"); + strcat(values_buf[i], values[j].value); + } + } + } + } + + variables[option_index].key = key; + variables[option_index].value = values_buf[i]; + option_index++; + } + + /* Set variables */ + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); + +error: + + /* Clean up */ + if (values_buf) + { + for (i = 0; i < num_options; i++) + { + if (values_buf[i]) + { + free(values_buf[i]); + values_buf[i] = NULL; + } + } + + free(values_buf); + values_buf = NULL; + } + + if (variables) + { + free(variables); + variables = NULL; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif From c31005008475f5d908ac9c200a0830e25b2cb989 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 20 Jul 2019 17:54:56 +0800 Subject: [PATCH 63/74] Allow compiling with asan --- Makefile.libretro | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile.libretro b/Makefile.libretro index b1e1d35..7a0b1e2 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -651,6 +651,12 @@ else endif endif +ifneq ($(SANITIZER),) +CFLAGS += -fsanitize=$(SANITIZER) +CXXFLAGS += -fsanitize=$(SANITIZER) +LDFLAGS += -fsanitize=$(SANITIZER) +endif + ifeq ($(EXTERNAL_ZLIB), 1) CFLAGS += -DHAVE_EXTERNAL_ZLIB endif From be1d0a3dac243d6c480d9dc0362e8c75a338a50e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 21 Jul 2019 09:57:03 +0800 Subject: [PATCH 64/74] diswitch.c: Fix crash issues and and cleanup - Partial rewrite to clean up dipswitch struct to prevent potential crashes - Fix problems on vs games without dipswitch to cause core to crash - Create dipswitch struct based on new core options layout --- src/drivers/libretro/dipswitch.c | 945 ++++++++++++++++++------------- src/drivers/libretro/dipswitch.h | 3 +- src/drivers/libretro/libretro.c | 4 +- 3 files changed, 552 insertions(+), 400 deletions(-) diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/dipswitch.c index b30b318..f5025e5 100644 --- a/src/drivers/libretro/dipswitch.c +++ b/src/drivers/libretro/dipswitch.c @@ -1,4 +1,5 @@ #include +#include #include #include "../../fceu.h" @@ -13,54 +14,54 @@ extern CartInfo iNESCart; typedef struct { - char *name; + const char *name; uint8 value; } SETTING; typedef struct { const char *option_name; - unsigned settings_size; uint8 mask; - SETTING settings[8]; + SETTING settings[10]; } DIPSWITCH; typedef struct { unsigned gameid; - char *romname_short; - unsigned dipswitch_size; - DIPSWITCH dipswitch_core_options[5]; + const char *romname_short; + DIPSWITCH dipswitch_core_options[8]; } VSUNIGAME; static VSUNIGAME dipswitch_battlecity = { - VS_BATTLECITY, "battlecity", 3, + VS_BATTLECITY, "battlecity", { - { "Credits for 2 Players", 2, 0x01, + { "Credits for 2 Players", 0x01, { { "2", 0x01 }, - { "1", 0x00 } - } + { "1", 0x00 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x02, + { "Lives", 0x02, { { "5", 0x02 }, - { "3", 0x00 } - } + { "3", 0x00 }, + { NULL, 0 }, + }, }, - { "Demo Sounds", 2, 0x04, + { "Demo Sounds", 0x04, { { "disabled", 0x04 }, - { "enabled", 0x00 } - } - } - } + { "enabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } + }, }; static VSUNIGAME dipswitch_castlevania = { - VS_CASTLEVANIA, "castlevania", 4, + VS_CASTLEVANIA, "castlevania", { - { "Coinage", - 8, - 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -69,37 +70,42 @@ static VSUNIGAME dipswitch_castlevania = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x08, + { "Lives", 0x08, { { "3", 0x00 }, { "2", 0x08 } } }, - { "Bonus", 4, 0x30, + { "Bonus", 0x30, { { "100k", 0x00 }, { "200k", 0x20 }, { "300k", 0x10 }, - { "400k", 0x30 } - } + { "400k", 0x30 }, + { NULL, 0 }, + }, }, - { "Difficulty", 2, 0x40, + { "Difficulty", 0x40, { { "Normal", 0x00 }, - { "Hard", 0x40 } - } - } + { "Hard", 0x40 }, + { NULL, 0 }, + }, + }, + + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_clucluland = { - VS_CLUCLULAND, "clucluland", 2, + VS_CLUCLULAND, "clucluland", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -108,24 +114,27 @@ static VSUNIGAME dipswitch_clucluland = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 4, 0x60, + { "Lives", 0x60, { { "3", 0x00 }, { "4", 0x40 }, { "5", 0x20 }, - { "2", 0x60 } - } - } + { "2", 0x60 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_drmario = { - VS_DRMARIO, "drmario", 5, + VS_DRMARIO, "drmario", { - { "Drop Rate Increase After", 4, 0x03, + { "Drop Rate Increase After", 0x03, { { "7 Pills", 0x00 }, { "8 Pills", 0x01 }, @@ -133,7 +142,7 @@ static VSUNIGAME dipswitch_drmario = { { "10 Pills", 0x03 } }, }, - { "Virus Level", 4, 0x0c, + { "Virus Level", 0x0c, { { "1", 0x00 }, { "3", 0x04 }, @@ -141,7 +150,7 @@ static VSUNIGAME dipswitch_drmario = { { "7", 0x0c } }, }, - { "Drop Speed Up", 4, 0x30, + { "Drop Speed Up", 0x30, { { "Slow", 0x00 }, { "Medium", 0x10 }, @@ -149,25 +158,27 @@ static VSUNIGAME dipswitch_drmario = { { "Fastest", 0x30 } }, }, - { "Free Play", 2, 0x40, + { "Free Play", 0x40, { { "disabled", 0x00 }, { "enabled", 0x40 } }, }, - { "Demo Sounds", 2, 0x80, + { "Demo Sounds", 0x80, { { "enabled", 0x80 }, - { "disabled", 0x00 } - } - } + { "disabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_duckhunt = { - VS_DUCKHUNT, "duckhunt", 4, + VS_DUCKHUNT, "duckhunt", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -176,38 +187,43 @@ static VSUNIGAME dipswitch_duckhunt = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x18, + { "Difficulty", 0x18, { { "Normal", 0x08 }, { "Medium", 0x10 }, { "Hard", 0x18 }, - { "Easy", 0x00 } - } + { "Easy", 0x00 }, + { NULL, 0 }, + }, }, - { "Miss per game", 2, 0x20, + { "Miss per game", 0x20, { { "5", 0x20 }, - { "3", 0x00 } - } + { "3", 0x00 }, + { NULL, 0 }, + }, }, - { "Bonus Life", 4, 0xc0, + { "Bonus Life", 0xc0, { { "30000", 0x00 }, { "50000", 0x40 }, { "80000", 0x80 }, - { "100000", 0xc0 } - } - } + { "100000", 0xc0 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_excitebike = { - VS_EXITEBIKE, "excitebike", 4, + VS_EXITEBIKE, "excitebike", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -216,36 +232,41 @@ static VSUNIGAME dipswitch_excitebike = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Bonus Bike", 4, 0x18, + { "Bonus Bike", 0x18, { { "100k and Every 50k", 0x00 }, { "100k Only", 0x08 }, { "Every 100k", 0x10 }, - { "None", 0x18 } - } + { "None", 0x18 }, + { NULL, 0 }, + }, }, - { "1st Qualifying Time", 2, 0x20, + { "1st Qualifying Time", 0x20, { { "Easy", 0x00 }, - { "Hard", 0x20 } - } + { "Hard", 0x20 }, + { NULL, 0 }, + }, }, - { "2nd Qualifying Time", 2, 0x40, + { "2nd Qualifying Time", 0x40, { { "Easy", 0x00 }, - { "Hard", 0x40 } - } - } + { "Hard", 0x40 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_freedomforce = { - VS_FREEDOMFORCE, "freedomforce", 4, + VS_FREEDOMFORCE, "freedomforce", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -254,38 +275,43 @@ static VSUNIGAME dipswitch_freedomforce = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Health Awarded At", 4, 0x18, + { "Health Awarded At", 0x18, { { "10k 50k", 0x10 }, { "20k 60k", 0x00 }, { "20k 60k Every 60k", 0x08 }, - { "10k 50k Every 50k", 0x18 } - } + { "10k 50k Every 50k", 0x18 }, + { NULL, 0 }, + }, }, - { "Difficulty (Damage)", 4, 0x60, + { "Difficulty (Damage)", 0x60, { { "Normal", 0x00 }, { "Easy", 0x40 }, { "Hard", 0x20 }, - { "Hardest", 0x60 } - } + { "Hardest", 0x60 }, + { NULL, 0 }, + }, }, - { "Difficulty (Enemy)", 2, 0x80, + { "Difficulty (Enemy)", 0x80, { { "Normal", 0x80 }, - { "Hard", 0x00 } - } - } + { "Hard", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_goonies = { - VS_GOONIES, "goonies", 5, + VS_GOONIES, "goonies", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -294,42 +320,48 @@ static VSUNIGAME dipswitch_goonies = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x08, + { "Lives", 0x08, { { "3", 0x08 }, - { "4", 0x00 } - } + { "4", 0x00 }, + { NULL, 0 }, + }, }, - { "Bonus", 4, 0x30, + { "Bonus", 0x30, { { "40000", 0x00 }, { "50000", 0x20 }, { "60000", 0x10 }, - { "70000", 0x30 } - } + { "70000", 0x30 }, + { NULL, 0 }, + }, }, - { "Timer", 2, 0x40, + { "Timer", 0x40, { { "Slow", 0x00 }, - { "Fast", 0x40 } - } + { "Fast", 0x40 }, + { NULL, 0 }, + }, }, - { "Demo Sounds", 2, 0x80, + { "Demo Sounds", 0x80, { { "enabled", 0x80 }, - { "disabled", 0x00 } - } - } + { "disabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_gradius = { - VS_GRADIUS, "gradius", 5, + VS_GRADIUS, "gradius", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -338,42 +370,48 @@ static VSUNIGAME dipswitch_gradius = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x08, + { "Lives", 0x08, { { "3", 0x08 }, - { "4", 0x00 } - } + { "4", 0x00 }, + { NULL, 0 }, + }, }, - { "Bonus", 4, 0x30, + { "Bonus", 0x30, { { "100k", 0x00 }, { "200k", 0x20 }, { "300k", 0x10 }, - { "400k", 0x30 } - } + { "400k", 0x30 }, + { NULL, 0 }, + }, }, - { "Difficulty", 2, 0x40, + { "Difficulty", 0x40, { { "Normal", 0x00 }, - { "Hard", 0x40 } - } + { "Hard", 0x40 }, + { NULL, 0 }, + }, }, - { "Demo Sounds", 2, 0x80, + { "Demo Sounds", 0x80, { { "enabled", 0x80 }, - { "disabled", 0x00 } - } - } + { "disabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_gumshoe = { - VS_GUMSHOE, "gumshoe", 5, + VS_GUMSHOE, "gumshoe", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -382,42 +420,48 @@ static VSUNIGAME dipswitch_gumshoe = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x18, + { "Difficulty", 0x18, { { "Normal", 0x08 }, { "Easy", 0x00 }, { "Hard", 0x10 }, - { "Hardest", 0x18 } - } + { "Hardest", 0x18 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x20, + { "Lives", 0x20, { { "3", 0x20 }, - { "5", 0x00 } - } + { "5", 0x00 }, + { NULL, 0 }, + }, }, - { "Bullets per Balloon", 2, 0x40, + { "Bullets per Balloon", 0x40, { { "3", 0x00 }, - { "2", 0x40 } - } + { "2", 0x40 }, + { NULL, 0 }, + }, }, - { "Bonus Man Awarded", 2, 0x80, + { "Bonus Man Awarded", 0x80, { { "At 50000", 0x00 }, - { "None", 0x80 } - } - } + { "None", 0x80 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_hogansalley = { - VS_HOGANSALLEY, "hogansalley", 4, + VS_HOGANSALLEY, "hogansalley", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -426,38 +470,43 @@ static VSUNIGAME dipswitch_hogansalley = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x18, + { "Difficulty", 0x18, { { "Normal", 0x08 }, { "Easy", 0x00 }, { "Hard", 0x10 }, - { "Hardest", 0x18 } - } + { "Hardest", 0x18 }, + { NULL, 0 }, + }, }, - { "Misses Per Game", 2, 0x20, + { "Misses Per Game", 0x20, { { "5", 0x20 }, - { "3", 0x00 } - } + { "3", 0x00 }, + { NULL, 0 }, + }, }, - { "Bonus Life", 4, 0xc0, + { "Bonus Life", 0xc0, { { "30000", 0x00 }, { "50000", 0x40 }, { "80000", 0x80 }, - { "100000", 0xc0 } - } - } + { "100000", 0xc0 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_iceclimber = { - VS_ICECLIMBER, "iceclimber", 4, + VS_ICECLIMBER, "iceclimber", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -466,36 +515,41 @@ static VSUNIGAME dipswitch_iceclimber = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 4, 0x18, + { "Lives", 0x18, { { "3", 0x00 }, { "4", 0x10 }, { "5", 0x08 }, - { "7", 0x18 } - } + { "7", 0x18 }, + { NULL, 0 }, + }, }, - { "Difficulty", 2, 0x20, + { "Difficulty", 0x20, { { "Easy", 0x00 }, - { "Hard", 0x20 } - } + { "Hard", 0x20 }, + { NULL, 0 }, + }, }, - { "Time before bear appears", 2, 0x40, + { "Time before bear appears", 0x40, { { "Long", 0x00 }, - { "Short", 0x40 } - } - } + { "Short", 0x40 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_jajamaru = { - VS_JAJAMARU, "jajamaru", 3, + VS_JAJAMARU, "jajamaru", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -504,29 +558,33 @@ static VSUNIGAME dipswitch_jajamaru = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 3, 0x18, + { "Lives", 0x18, { { "3", 0x00 }, { "4", 0x10 }, - { "5", 0x08 } - } + { "5", 0x08 }, + { NULL, 0 }, + }, }, - { "Demo Sounds", 2, 0x80, + { "Demo Sounds", 0x80, { { "enabled", 0x80 }, - { "disabled", 0x00 } - } - } + { "disabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_machrider = { - VS_MACHRIDER, "machrider", 3, + VS_MACHRIDER, "machrider", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -535,30 +593,34 @@ static VSUNIGAME dipswitch_machrider = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Time", 4, 0x18, + { "Time", 0x18, { { "280 (Easy)", 0x00 }, { "250", 0x10 }, { "220", 0x08 }, - { "200 (Hard)", 0x18 } - } + { "200 (Hard)", 0x18 }, + { NULL, 0 }, + }, }, - { "Enemies", 2, 0x40, + { "Enemies", 0x40, { { "Less", 0x00 }, - { "More", 0x40 } - } - } + { "More", 0x40 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_mightybj = { - VS_MIGHTYBOMBJACK, "mightybj", 2, + VS_MIGHTYBOMBJACK, "mightybj", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -567,24 +629,26 @@ static VSUNIGAME dipswitch_mightybj = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "5 Coins 1 Credit", 0x07 } - } + { "5 Coins 1 Credit", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 4, 0x18, + { "Lives", 0x18, { { "3", 0x00 }, { "4", 0x08 }, { "5", 0x18 }, { "2", 0x10 }, - } - } + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_pinball = { - VS_PINBALL, "pinball", 5, + VS_PINBALL, "pinball", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x01 }, { "1 Coin 2 Credits", 0x06 }, @@ -593,22 +657,25 @@ static VSUNIGAME dipswitch_pinball = { { "2 Coins 1 Credit", 0x05 }, { "3 Coins 1 Credit", 0x03 }, { "4 Coins 1 Credit", 0x07 }, - { "Free Play", 0x00 } - } + { "Free Play", 0x00 }, + { NULL, 0 }, + }, }, - { "Side Drain Walls", 2, 0x08, + { "Side Drain Walls", 0x08, { { "High", 0x00 }, - { "Low", 0x08 } - } + { "Low", 0x08 }, + { NULL, 0 }, + }, }, - { "Bonus Life", 2, 0x10, + { "Bonus Life", 0x10, { { "50000", 0x00 }, - { "70000", 0x10 } - } + { "70000", 0x10 }, + { NULL, 0 }, + }, }, - { "Balls", 4, 0x60, + { "Balls", 0x60, { { "3", 0x00 }, { "4", 0x40 }, @@ -616,25 +683,28 @@ static VSUNIGAME dipswitch_pinball = { { "2", 0x60 }, } }, - { "Ball Speed", 2, 0x80, + { "Ball Speed", 0x80, { { "Slow", 0x00 }, - { "Fast", 0x80 } - } - } + { "Fast", 0x80 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_platoon = { - VS_PLATOON, "platoon", 3, + VS_PLATOON, "platoon", { - { "Demo Sounds", 2, 0x04, + { "Demo Sounds", 0x04, { { "enabled", 0x00 }, - { "disabled", 0x04 } - } + { "disabled", 0x04 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x18, + { "Difficulty", 0x18, { { "Normal", 0x08 }, { "Medium", 0x10 }, @@ -642,7 +712,7 @@ static VSUNIGAME dipswitch_platoon = { { "Easy", 0x00 }, } }, - { "Coinage", 8, 0xe0, + { "Coinage", 0xe0, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x20 }, @@ -651,24 +721,27 @@ static VSUNIGAME dipswitch_platoon = { { "3 Coins 1 Credit", 0x80 }, { "4 Coins 1 Credit", 0xa0 }, { "5 Coins 1 Credit", 0xc0 }, - { "Free Play", 0xe0 } - } - } + { "Free Play", 0xe0 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_rbibaseball = { - VS_RBIBASEBALL, "atari_rbibb", 3, + VS_RBIBASEBALL, "atari_rbibb", { - { "Coinage", 4, 0x03, + { "Coinage", 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, { "2 Coins 1 Credit", 0x02 }, - { "3 Coins 1 Credit", 0x03 } - } + { "3 Coins 1 Credit", 0x03 }, + { NULL, 0 }, + }, }, - { "1p-inn 2p-inn time-min", 4, 0x0c, + { "1p-inn 2p-inn time-min", 0x0c, { { "2 2 4", 0x0c }, { "3 2 6", 0x00 }, @@ -676,19 +749,21 @@ static VSUNIGAME dipswitch_rbibaseball = { { "2 1 3", 0x04 }, } }, - { "Demo Sounds", 2, 0x10, + { "Demo Sounds", 0x10, { { "enabled", 0x00 }, - { "disabled", 0x10 } - } - } + { "disabled", 0x10 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_slalom = { - VS_SLALOM, "slalom", 5, + VS_SLALOM, "slalom", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -697,42 +772,48 @@ static VSUNIGAME dipswitch_slalom = { { "3 Coins 1 Credit", 0x01 }, { "4 Coins 1 Credit", 0x05 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Freestyle Points", 2, 0x08, + { "Freestyle Points", 0x08, { { "Hold Time", 0x08 }, - { "Left Right", 0x00 } - } + { "Left Right", 0x00 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x30, + { "Difficulty", 0x30, { { "Normal", 0x10 }, { "Medium", 0x20 }, { "Hard", 0x30 }, - { "Easy", 0x00 } - } + { "Easy", 0x00 }, + { NULL, 0 }, + }, }, - { "Allow Continue", 2, 0x40, + { "Allow Continue", 0x40, { { "enabled", 0x00 }, - { "disabled", 0x40 } - } + { "disabled", 0x40 }, + { NULL, 0 }, + }, }, - { "Inverted Input", 2, 0x80, + { "Inverted Input", 0x80, { { "disabled", 0x00 }, - { "enabled", 0x80 } - } - } + { "enabled", 0x80 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_smb = { - VS_SMB, "smb", 5, + VS_SMB, "smb", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x06 }, @@ -741,42 +822,48 @@ static VSUNIGAME dipswitch_smb = { { "1 Coin 5 Credits", 0x03 }, { "2 Coins 1 Credit", 0x04 }, { "3 Coins 1 Credit", 0x02 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives", 2, 0x08, + { "Lives", 0x08, { { "3", 0x00 }, - { "2", 0x08 } - } + { "2", 0x08 }, + { NULL, 0 }, + }, }, - { "Bonus Life", 4, 0x30, + { "Bonus Life", 0x30, { { "100 coins", 0x00 }, { "150 coins", 0x20 }, { "200 coins", 0x10 }, - { "250 coins", 0x30 } - } + { "250 coins", 0x30 }, + { NULL, 0 }, + }, }, - { "Timer", 2, 0x40, + { "Timer", 0x40, { { "Slow", 0x00 }, - { "Fast", 0x40 } - } + { "Fast", 0x40 }, + { NULL, 0 }, + }, }, - { "Continue Lives", 2, 0x80, + { "Continue Lives", 0x80, { { "3", 0x80 }, - { "4", 0x00 } - } - } + { "4", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_soccer = { - VS_SOCCER, "soccer", 3, + VS_SOCCER, "soccer", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -785,46 +872,52 @@ static VSUNIGAME dipswitch_soccer = { { "2 Coins 1 Credit", 0x01 }, { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Points Timer", 4, 0x18, + { "Points Timer", 0x18, { { "1000 Pts", 0x08 }, { "1200 Pts", 0x18 }, { "600 Pts", 0x00 }, - { "800 Pts", 0x10 } - } + { "800 Pts", 0x10 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x60, + { "Difficulty", 0x60, { { "Normal", 0x40 }, { "Medium", 0x20 }, { "Hard", 0x60 }, - { "Easy", 0x00 } - } - } + { "Easy", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_starluster = { - VS_STARLUSTER, "starluster", 1, + VS_STARLUSTER, "starluster", { - { "Coinage", 4, 0x03, + { "Coinage", 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x02 }, { "2 Coins 1 Credit", 0x01 }, - { "3 Coins 1 Credit", 0x03 } - } - } + { "3 Coins 1 Credit", 0x03 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_superskykid = { - VS_SUPERSKYKID, "superskykid", 3, + VS_SUPERSKYKID, "superskykid", { - { "Difficulty", 4, 0x03, + { "Difficulty", 0x03, { { "Normal", 0x01 }, @@ -833,77 +926,85 @@ static VSUNIGAME dipswitch_superskykid = { { "Easy", 0x00 }, } }, - { "Lives", 2, 0x04, + { "Lives", 0x04, { { "3", 0x04 }, - { "2", 0x00 } - } + { "2", 0x00 }, + { NULL, 0 }, + }, }, - { "Coinage", 4, 0x18, + { "Coinage", 0x18, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x08 }, { "2 Coins 1 Credit", 0x10 }, - { "3 Coins 1 Credit", 0x18 } - } - } + { "3 Coins 1 Credit", 0x18 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_superxevious = { - VS_SUPERXEVIOUS, "superxevious", 1, + VS_SUPERXEVIOUS, "superxevious", { - { "Coinage", 4, 0x30, + { "Coinage", 0x30, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x10 }, { "2 Coins 1 Credit", 0x20 }, - { "3 Coins 1 Credit", 0x30 } - } - } + { "3 Coins 1 Credit", 0x30 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_tetris = { - VS_TETRIS, "tetris", 1, + VS_TETRIS, "tetris", { - { "Difficulty", 4, 0x0c, + { "Difficulty", 0x0c, { { "Normal", 0x04 }, { "Medium", 0x08 }, { "Hard", 0x0c }, { "Easy", 0x00 }, - } - } + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_tkoboxing = { - VS_TKOBOXING, "tkoboxing", 2, + VS_TKOBOXING, "tkoboxing", { - { "Coinage", 4, 0x03, + { "Coinage", 0x03, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, { "2 Coins 1 Credit", 0x02 }, - { "3 Coins 1 Credit", 0x03 } - } + { "3 Coins 1 Credit", 0x03 }, + { NULL, 0 }, + }, }, - { "Difficulty", 4, 0x0c, + { "Difficulty", 0x0c, { { "Normal", 0x04 }, { "Hard", 0x08 }, { "Very Hard", 0x0c }, { "Easy", 0x00 }, - } - } + }, + }, + { NULL, 0, { NULL, 0 } } } }; static VSUNIGAME dipswitch_topgun = { - VS_TOPGUN, "topgun", 5, + VS_TOPGUN, "topgun", { - { "Coinage", 8, 0x07, + { "Coinage", 0x07, { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -912,53 +1013,65 @@ static VSUNIGAME dipswitch_topgun = { { "3 Coins 1 Credit", 0x05 }, { "4 Coins 1 Credit", 0x06 }, { "5 Coins 1 Credit", 0x03 }, - { "Free Play", 0x07 } - } + { "Free Play", 0x07 }, + { NULL, 0 }, + }, }, - { "Lives per Coin", 2, 0x08, + { "Lives per Coin", 0x08, { { "3-12 Max", 0x00 }, - { "2-9 Max", 0x08 } - } + { "2-9 Max", 0x08 }, + { NULL, 0 }, + }, }, - { "Bonus Life", 4, 0x30, + { "Bonus Life", 0x30, { { "30k and Every 50k", 0x00 }, { "50k and Every 100k", 0x20 }, { "100k and Every 150k", 0x10 }, - { "200k and Every 200k", 0x30 } - } + { "200k and Every 200k", 0x30 }, + { NULL, 0 }, + }, }, - { "Difficulty", 2, 0x40, + { "Difficulty", 0x40, { { "Easy", 0x00 }, - { "Hard", 0x40 } - } + { "Hard", 0x40 }, + { NULL, 0 }, + }, }, - { "Demo Sounds", 2, 0x80, + { "Demo Sounds", 0x80, { { "enabled", 0x80 }, - { "disabled", 0x00 } - } - } + { "disabled", 0x00 }, + { NULL, 0 }, + }, + }, + { NULL, 0, { NULL, 0 } } } }; -typedef struct { - char value[100]; - char label[100]; -} VSUNIGAMEOPT_VALUE; +#define DPSW_MAX 6 -typedef struct { - char key[64]; - VSUNIGAMEOPT_VALUE val[10]; -} VSUNIGAMEOPT; +enum { + DPSW_NONE = 0, + DPSW_VSUNI, + DPSW_NWC, +}; +static struct retro_core_option_definition option_defs_empty = { + NULL, NULL, NULL, { NULL, NULL }, NULL +}; + +static struct retro_core_option_definition vscoreopt[DPSW_MAX]; static VSUNIGAME *vsgame = NULL; -static VSUNIGAMEOPT vscoreopt[5]; +static char *core_key[DPSW_MAX]; +static unsigned num_core_options; +static unsigned dipswitch_type = DPSW_NONE; -static void str_to_corekey_label(char *str) +static const char *str_to_corekey(char *s) { + char *str = s; unsigned i = 0; while (str[i] != '\0') @@ -968,36 +1081,45 @@ static void str_to_corekey_label(char *str) i++; } str[i] = '\0'; + + return str; } -static void make_core_options(void) +static void make_core_options(struct retro_core_option_definition *opt) { - unsigned i, j, num_dipswitch; - char *romname_short = NULL; + unsigned i, j; - num_dipswitch = vsgame->dipswitch_size; - romname_short = vsgame->romname_short; - for (i = 0; i < num_dipswitch; i++) + for (i = 0; i < num_core_options; i++) { - char core_key[64], core_values[150]; - unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + struct retro_core_option_value vars_empty = { NULL, NULL }; + const char *romname_short = vsgame->romname_short; const char *option_name = vsgame->dipswitch_core_options[i].option_name; + unsigned num_values = 0, len = 0; + char key[100] = {0}; - memset(core_key, 0 , sizeof(core_key)); - memset(core_values, 0 , sizeof(core_values)); + /* Set core key and sanitize string */ + len = snprintf(key, sizeof(key), "%s%s%c%s", "fceumm_dipswitch_", romname_short, '-', option_name); + core_key[i] = calloc(len + 1, sizeof(char)); + strcpy(core_key[i], key); + opt[i].key = str_to_corekey(core_key[i]); - /* Create core key string */ - sprintf(core_key, "fceumm_dipswitch_%s-%s", romname_short, option_name); - /* sanitize core key string */ - str_to_corekey_label(core_key); - sprintf(vscoreopt[i].key, "%s", core_key); + /* Set desc */ + opt[i].desc = option_name; - /* Create core values */ - for (j = 0; j < num_values; j++) - { + /* Set info */ + opt[i].info = NULL; + + j = 0; + /* Set core values */ + while (vsgame->dipswitch_core_options[i].settings[j].name) { const char *var_value = vsgame->dipswitch_core_options[i].settings[j].name; - sprintf(vscoreopt[i].val[j].value, "%s", var_value); + opt[i].values[j].value = var_value; + j++; } + opt[i].values[j] = vars_empty; + + /* Set default value. Top entry used as default */ + opt[i].default_value = vsgame->dipswitch_core_options[i].settings[0].name; } } @@ -1068,27 +1190,34 @@ static VSUNIGAME *get_vsuni_dipswitch(unsigned id) static void update_dipswitch_vsuni(void) { - struct retro_variable var = {0}; - unsigned idx_dips, idx_var; + unsigned index_key; uint8 vsdip_new = FCEUI_VSUniGetDIPs(); - for (idx_dips = 0; idx_dips < vsgame->dipswitch_size; idx_dips++) + for (index_key = 0; index_key < num_core_options; index_key++) { - const char *key = vscoreopt[idx_dips].key; - unsigned num_options = vsgame->dipswitch_core_options[idx_dips].settings_size; + struct retro_variable var = { NULL, NULL }; + const char *key = vscoreopt[index_key].key; + unsigned index_value; var.key = key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) continue; - for (idx_var = 0; idx_var < num_options; idx_var++) + + index_value = 0; + while (vscoreopt[index_key].values[index_value].value) { - const char *var_value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].name; - uint8 value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].value; - uint8 mask = vsgame->dipswitch_core_options[idx_dips].mask; - if (strcmp(var.value, var_value) != 0) + const char *var_value = vscoreopt[index_key].values[index_value].value; + uint8 value, mask; + + if (strcmp(var.value, var_value) != 0) { + index_value++; continue; - vsdip_new &= ~mask; + } + value = vsgame->dipswitch_core_options[index_key].settings[index_value].value; + mask = vsgame->dipswitch_core_options[index_key].mask; + vsdip_new &= (~mask); vsdip_new |= value; + index_value++; } } @@ -1149,23 +1278,25 @@ static struct retro_core_option_definition dipswitch_nwc[] = { }, "disabled", }, + + { NULL, NULL, NULL, { NULL, NULL }, NULL }, }; static void update_dipswitch_nwc(void) { - struct retro_variable var = {0}; - unsigned dips = 0x00; - unsigned i; + unsigned i, dips = 0x00; for (i = 0; i < 4; i++) { + struct retro_variable var = { NULL, NULL }; const char *key = dipswitch_nwc[i].key; + var.key = key; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "enabled") == 0) - dips |= (1 << i); - } + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) + continue; + if (strcmp(var.value, "enabled") != 0) + continue; + dips |= (1 << i); } if (GameInfo->cspecial != dips) @@ -1178,9 +1309,10 @@ static void update_dipswitch_nwc(void) } } -void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars) +size_t set_dipswitch_variables(unsigned current_index, struct retro_core_option_definition *vars) { - unsigned idx = *index; + unsigned index = current_index; + int dipsw_size = 0; /* VSUNI Dipswitch */ if (GameInfo->type == GIT_VSUNI) @@ -1189,48 +1321,65 @@ void set_dipswitch_variables(unsigned *index, struct retro_core_option_definitio if (vsgame) { unsigned i, j; - unsigned num_options = vsgame->dipswitch_size; - make_core_options(); + num_core_options = 0; + dipswitch_type = DPSW_VSUNI; - for (i = 0; i < num_options; i++) { - const char *key = vscoreopt[i].key; - const char *desc = vsgame->dipswitch_core_options[i].option_name; - unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + /* Initialize dipswitch struct and count number of core options */ + for (i = 0; i < DPSW_MAX; i++) { + vscoreopt[i] = option_defs_empty; + if (vsgame->dipswitch_core_options[i].option_name) + num_core_options++; + } - vars[idx].key = key; - vars[idx].desc = desc; + make_core_options(vscoreopt); - for (j = 0; j < num_values; j++) { - char *value = vscoreopt[i].val[j].value; - vars[idx].values[j].value = value; - } - - idx++; + /* Copy dpsw struct to main core option struct */ + while (vscoreopt[dipsw_size].key) { + vars[index] = vscoreopt[dipsw_size]; + index++; + dipsw_size++; } } + return (dipsw_size); } /* Nintendo World Championship cart (Mapper 105)*/ if (iNESCart.mapper == 105) { - unsigned i = 0; + dipswitch_type = DPSW_NWC; - while (dipswitch_nwc[i].key) { - vars[idx] = dipswitch_nwc[i]; - idx++; - i++; + while (dipswitch_nwc[dipsw_size].key) { + vars[index] = dipswitch_nwc[dipsw_size]; + index++; + dipsw_size++; } + return (dipsw_size); } - *index = idx; + return (0); } void update_dipswitch(void) { - if (iNESCart.mapper == 105) - update_dipswitch_nwc(); - - if (GameInfo->type == GIT_VSUNI) + switch (dipswitch_type) { + case DPSW_VSUNI: update_dipswitch_vsuni(); + break; + case DPSW_NWC: + update_dipswitch_nwc(); + break; + } +} + +void DPSW_Cleanup(void) +{ + unsigned i; + + for (i = 0; i < DPSW_MAX; i++) { + if (core_key[i]) { + free(core_key[i]); + core_key[i] = NULL; + } + } } diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/dipswitch.h index d5a1d8a..bf6ace7 100644 --- a/src/drivers/libretro/dipswitch.h +++ b/src/drivers/libretro/dipswitch.h @@ -3,8 +3,9 @@ #include -void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars); +size_t set_dipswitch_variables(unsigned current_index, struct retro_core_option_definition *vars); void update_dipswitch(void); +void DPSW_Cleanup(void); extern retro_environment_t environ_cb; diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 7c40219..dd418ca 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -759,7 +759,8 @@ static void set_variables(void) } /* Append dipswitch settings to core options if available */ - set_dipswitch_variables(&index, option_defs_us); + index += set_dipswitch_variables(index, option_defs_us); + option_defs_us[index] = option_defs_empty; libretro_set_core_options(environ_cb); } @@ -987,6 +988,7 @@ void retro_deinit (void) ps2 = NULL; #endif libretro_supports_bitmasks = false; + DPSW_Cleanup(); } void retro_reset(void) From 8446a7ba5888906ddb3eb33923e2d0aee90bebd9 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 21 Jul 2019 10:27:26 +0800 Subject: [PATCH 65/74] dipswitch.c: Rename src and header file - (non function-changing update) just for consistency, append "libretro_" to source file to be consistent with new core option file --- Makefile.common | 2 +- src/drivers/libretro/libretro.c | 2 +- src/drivers/libretro/{dipswitch.c => libretro_dipswitch.c} | 2 +- src/drivers/libretro/{dipswitch.h => libretro_dipswitch.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/drivers/libretro/{dipswitch.c => libretro_dipswitch.c} (99%) rename src/drivers/libretro/{dipswitch.h => libretro_dipswitch.h} (100%) diff --git a/Makefile.common b/Makefile.common index 4012987..1d7a7b6 100644 --- a/Makefile.common +++ b/Makefile.common @@ -57,4 +57,4 @@ endif SOURCES_C += \ $(CORE_DIR)/ines.c \ $(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c \ - $(CORE_DIR)/drivers/libretro/dipswitch.c + $(CORE_DIR)/drivers/libretro/libretro_dipswitch.c diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index dd418ca..342902a 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -29,7 +29,7 @@ #endif #include "libretro-common/include/streams/memory_stream.h" -#include "dipswitch.h" +#include "libretro_dipswitch.h" #include "libretro_core_options.h" #define MAX_PLAYERS 4 /* max supported players */ diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/libretro_dipswitch.c similarity index 99% rename from src/drivers/libretro/dipswitch.c rename to src/drivers/libretro/libretro_dipswitch.c index f5025e5..a64d3fc 100644 --- a/src/drivers/libretro/dipswitch.c +++ b/src/drivers/libretro/libretro_dipswitch.c @@ -9,7 +9,7 @@ #include "../../driver.h" #include "../../cart.h" -#include "dipswitch.h" +#include "libretro_dipswitch.h" extern CartInfo iNESCart; diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/libretro_dipswitch.h similarity index 100% rename from src/drivers/libretro/dipswitch.h rename to src/drivers/libretro/libretro_dipswitch.h From de89c5bcfb7a562b872f51514d5c73c36f13a1c3 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 21 Jul 2019 15:40:02 +0800 Subject: [PATCH 66/74] Use sprintf() instead of snprintf() - fix msvc2010 build --- src/drivers/libretro/libretro_dipswitch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/libretro/libretro_dipswitch.c b/src/drivers/libretro/libretro_dipswitch.c index a64d3fc..5f5f099 100644 --- a/src/drivers/libretro/libretro_dipswitch.c +++ b/src/drivers/libretro/libretro_dipswitch.c @@ -1098,7 +1098,7 @@ static void make_core_options(struct retro_core_option_definition *opt) char key[100] = {0}; /* Set core key and sanitize string */ - len = snprintf(key, sizeof(key), "%s%s%c%s", "fceumm_dipswitch_", romname_short, '-', option_name); + len = sprintf(key, "fceumm_dipswitch_%s-%s", romname_short, option_name); core_key[i] = calloc(len + 1, sizeof(char)); strcpy(core_key[i], key); opt[i].key = str_to_corekey(core_key[i]); From 0a0fdb8c2bab4ae1b72a08566213b9f89cc58cd8 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Wed, 31 Jul 2019 03:38:05 +0200 Subject: [PATCH 67/74] Update libretro_core_options.h --- src/drivers/libretro/libretro_core_options.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h index 877c05f..1d160ae 100644 --- a/src/drivers/libretro/libretro_core_options.h +++ b/src/drivers/libretro/libretro_core_options.h @@ -45,7 +45,7 @@ struct retro_core_option_definition option_defs_common[] = { { "fceumm_aspect", "Preferred aspect ratio", - "Choose prefered aspect ratio.", + "Choose preferred aspect ratio.", { { "8:7 PAR", NULL }, { "4:3", NULL }, @@ -56,7 +56,7 @@ struct retro_core_option_definition option_defs_common[] = { { "fceumm_palette", "Color Palette", - "Choose from pre-generted palettes, a custom 64x3 palette from file or raw format (needs to use a nes-decoder shader).", + "Choose from pre-generated palettes, a custom 64x3 palette from file or raw format (needs to use a nes-decoder shader).", { { "default", NULL }, { "asqrealc", NULL }, @@ -84,7 +84,7 @@ struct retro_core_option_definition option_defs_common[] = { { "fceumm_up_down_allowed", "Allow Opposing Directions", - "Allows simultaneous UP+DOWN or LEFT+RIGHT button combination which can create different effects in some games.", + "Allows simultaneous UP+DOWN or LEFT+RIGHT button combinations which can create different effects in some games.", { { "disabled", NULL }, { "enabled", NULL }, @@ -109,7 +109,7 @@ struct retro_core_option_definition option_defs_common[] = { { "fceumm_overscan_h", "Crop Overscan (Horizontal)", - "Removes 8 pixel from left and right of screen to simulates overscans seen on standard CRT television.", + "Removes 8 pixel from left and right side of the screen to simulate overscan seen on standard CRT television.", { { "disabled", NULL }, { "enabled", NULL }, @@ -120,7 +120,7 @@ struct retro_core_option_definition option_defs_common[] = { { "fceumm_overscan_v", "Crop Overscan (Vertical)", - "Removes 8 pixel from top and bottom of screen to simulates overscans seen on standard CRT television.", + "Removes 8 pixel from the top and bottom of the screen to simulate overscan seen on standard CRT television.", { { "disabled", NULL }, { "enabled", NULL }, From 313f69daaf4c60de1f294949fa6e8a8bd55bcf49 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 1 Aug 2019 20:02:17 +0800 Subject: [PATCH 68/74] Silence warning and fix missing NULL terminators on core option struct - silence warning: missing braces around initializer [-Wmissing-braces] --- src/drivers/libretro/libretro_core_options.h | 4 +- src/drivers/libretro/libretro_dipswitch.c | 88 +++++++++++--------- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h index 1d160ae..39760bd 100644 --- a/src/drivers/libretro/libretro_core_options.h +++ b/src/drivers/libretro/libretro_core_options.h @@ -318,11 +318,11 @@ struct retro_core_option_definition option_defs_common[] = { }, #endif - { NULL, NULL, NULL, { NULL, NULL }, NULL }, + { NULL, NULL, NULL, { {0} }, NULL }, }; struct retro_core_option_definition option_defs_empty = { - NULL, NULL, NULL, { NULL, NULL }, NULL + NULL, NULL, NULL, { {0} }, NULL }; struct retro_core_option_definition option_defs_us[MAX_CORE_OPTIONS]; diff --git a/src/drivers/libretro/libretro_dipswitch.c b/src/drivers/libretro/libretro_dipswitch.c index 5f5f099..4e3e148 100644 --- a/src/drivers/libretro/libretro_dipswitch.c +++ b/src/drivers/libretro/libretro_dipswitch.c @@ -54,7 +54,7 @@ static VSUNIGAME dipswitch_battlecity = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } }, }; @@ -77,8 +77,8 @@ static VSUNIGAME dipswitch_castlevania = { { "Lives", 0x08, { { "3", 0x00 }, - { "2", 0x08 } - + { "2", 0x08 }, + { NULL, 0 }, } }, { "Bonus", 0x30, @@ -98,7 +98,7 @@ static VSUNIGAME dipswitch_castlevania = { }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -127,7 +127,7 @@ static VSUNIGAME dipswitch_clucluland = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -139,7 +139,8 @@ static VSUNIGAME dipswitch_drmario = { { "7 Pills", 0x00 }, { "8 Pills", 0x01 }, { "9 Pills", 0x02 }, - { "10 Pills", 0x03 } + { "10 Pills", 0x03 }, + { NULL, 0 }, }, }, { "Virus Level", 0x0c, @@ -147,7 +148,8 @@ static VSUNIGAME dipswitch_drmario = { { "1", 0x00 }, { "3", 0x04 }, { "5", 0x08 }, - { "7", 0x0c } + { "7", 0x0c }, + { NULL, 0 }, }, }, { "Drop Speed Up", 0x30, @@ -155,13 +157,15 @@ static VSUNIGAME dipswitch_drmario = { { "Slow", 0x00 }, { "Medium", 0x10 }, { "Fast", 0x20 }, - { "Fastest", 0x30 } + { "Fastest", 0x30 }, + { NULL, 0 }, }, }, { "Free Play", 0x40, { { "disabled", 0x00 }, - { "enabled", 0x40 } + { "enabled", 0x40 }, + { NULL, 0 }, }, }, { "Demo Sounds", 0x80, @@ -171,7 +175,7 @@ static VSUNIGAME dipswitch_drmario = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -216,7 +220,7 @@ static VSUNIGAME dipswitch_duckhunt = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -259,7 +263,7 @@ static VSUNIGAME dipswitch_excitebike = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -304,7 +308,7 @@ static VSUNIGAME dipswitch_freedomforce = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -354,7 +358,7 @@ static VSUNIGAME dipswitch_goonies = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -404,7 +408,7 @@ static VSUNIGAME dipswitch_gradius = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -454,7 +458,7 @@ static VSUNIGAME dipswitch_gumshoe = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -499,7 +503,7 @@ static VSUNIGAME dipswitch_hogansalley = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -542,7 +546,7 @@ static VSUNIGAME dipswitch_iceclimber = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -577,7 +581,7 @@ static VSUNIGAME dipswitch_jajamaru = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -613,7 +617,7 @@ static VSUNIGAME dipswitch_machrider = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -639,9 +643,10 @@ static VSUNIGAME dipswitch_mightybj = { { "4", 0x08 }, { "5", 0x18 }, { "2", 0x10 }, + { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -681,6 +686,7 @@ static VSUNIGAME dipswitch_pinball = { { "4", 0x40 }, { "5", 0x20 }, { "2", 0x60 }, + { NULL, 0 }, } }, { "Ball Speed", 0x80, @@ -690,7 +696,7 @@ static VSUNIGAME dipswitch_pinball = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -710,6 +716,7 @@ static VSUNIGAME dipswitch_platoon = { { "Medium", 0x10 }, { "Hard", 0x18 }, { "Easy", 0x00 }, + { NULL, 0 }, } }, { "Coinage", 0xe0, @@ -725,7 +732,7 @@ static VSUNIGAME dipswitch_platoon = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -747,6 +754,7 @@ static VSUNIGAME dipswitch_rbibaseball = { { "3 2 6", 0x00 }, { "4 3 7", 0x08 }, { "2 1 3", 0x04 }, + { NULL, 0 }, } }, { "Demo Sounds", 0x10, @@ -756,7 +764,7 @@ static VSUNIGAME dipswitch_rbibaseball = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -806,7 +814,7 @@ static VSUNIGAME dipswitch_slalom = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -856,7 +864,7 @@ static VSUNIGAME dipswitch_smb = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -894,7 +902,7 @@ static VSUNIGAME dipswitch_soccer = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -910,7 +918,7 @@ static VSUNIGAME dipswitch_starluster = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -924,6 +932,7 @@ static VSUNIGAME dipswitch_superskykid = { { "Medium", 0x02 }, { "Hard", 0x03 }, { "Easy", 0x00 }, + { NULL, 0 }, } }, { "Lives", 0x04, @@ -942,7 +951,7 @@ static VSUNIGAME dipswitch_superskykid = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -958,7 +967,7 @@ static VSUNIGAME dipswitch_superxevious = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -971,9 +980,10 @@ static VSUNIGAME dipswitch_tetris = { { "Medium", 0x08 }, { "Hard", 0x0c }, { "Easy", 0x00 }, + { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -995,9 +1005,10 @@ static VSUNIGAME dipswitch_tkoboxing = { { "Hard", 0x08 }, { "Very Hard", 0x0c }, { "Easy", 0x00 }, + { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -1047,7 +1058,7 @@ static VSUNIGAME dipswitch_topgun = { { NULL, 0 }, }, }, - { NULL, 0, { NULL, 0 } } + { NULL, 0, { {0} } } } }; @@ -1060,7 +1071,7 @@ enum { }; static struct retro_core_option_definition option_defs_empty = { - NULL, NULL, NULL, { NULL, NULL }, NULL + NULL, NULL, NULL, { {0} }, NULL }; static struct retro_core_option_definition vscoreopt[DPSW_MAX]; @@ -1094,12 +1105,11 @@ static void make_core_options(struct retro_core_option_definition *opt) struct retro_core_option_value vars_empty = { NULL, NULL }; const char *romname_short = vsgame->romname_short; const char *option_name = vsgame->dipswitch_core_options[i].option_name; - unsigned num_values = 0, len = 0; char key[100] = {0}; /* Set core key and sanitize string */ - len = sprintf(key, "fceumm_dipswitch_%s-%s", romname_short, option_name); - core_key[i] = calloc(len + 1, sizeof(char)); + sprintf(key, "fceumm_dipswitch_%s-%s", romname_short, option_name); + core_key[i] = calloc(strlen(key) + 1, sizeof(char)); strcpy(core_key[i], key); opt[i].key = str_to_corekey(core_key[i]); @@ -1279,7 +1289,7 @@ static struct retro_core_option_definition dipswitch_nwc[] = { "disabled", }, - { NULL, NULL, NULL, { NULL, NULL }, NULL }, + { NULL, NULL, NULL, { {0} }, NULL }, }; static void update_dipswitch_nwc(void) @@ -1320,7 +1330,7 @@ size_t set_dipswitch_variables(unsigned current_index, struct retro_core_option_ vsgame = get_vsuni_dipswitch(GameInfo->gameid); if (vsgame) { - unsigned i, j; + unsigned i; num_core_options = 0; dipswitch_type = DPSW_VSUNI; From d807bac15b433b849aa2a3c49cec45453448d339 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 1 Aug 2019 20:31:42 +0800 Subject: [PATCH 69/74] Remove unused variables --- src/boards/411120-c.c | 2 +- src/boards/69.c | 1 - src/boards/8157.c | 1 - src/boards/KS7032.c | 2 +- src/boards/bmc80013b.c | 2 +- src/boards/mmc3.c | 3 --- src/boards/resettxrom.c | 2 -- src/boards/t-262.c | 1 - src/boards/vrc2and4.c | 12 ++---------- src/vsuni.c | 11 ++++------- 10 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/boards/411120-c.c b/src/boards/411120-c.c index 765ce19..a21a898 100644 --- a/src/boards/411120-c.c +++ b/src/boards/411120-c.c @@ -32,7 +32,7 @@ #include "mmc3.h" static uint8 reset_flag = 0; -static uint8 chip, isK3088; +static uint8 isK3088; static void BMC411120CCW(uint32 A, uint8 V) { uint32 mask = isK3088 ? 0x07 : 0x03; diff --git a/src/boards/69.c b/src/boards/69.c index 2a7093b..3117106 100644 --- a/src/boards/69.c +++ b/src/boards/69.c @@ -135,7 +135,6 @@ static DECLFW(M69SWrite0) { } static DECLFW(M69SWrite1) { - int x; GameExpSound.Fill = AYSound; GameExpSound.HiFill = AYSoundHQ; switch (sndcmd) { diff --git a/src/boards/8157.c b/src/boards/8157.c index b81c05f..eb9224f 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -23,7 +23,6 @@ #include "mapinc.h" -static uint8 chip; static uint16 cmdreg; static uint8 reset; static SFORMAT StateRegs[] = diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 41739af..8e123e5 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -31,7 +31,7 @@ #include "mapinc.h" -static uint8 reg[8], creg[8], mirr, cmd, IRQa = 0, isirqused = 0; +static uint8 reg[8], creg[8], mirr, cmd, IRQa = 0; static int32 IRQCount, IRQLatch; static uint8 KS7032; static uint8 *WRAM = NULL; diff --git a/src/boards/bmc80013b.c b/src/boards/bmc80013b.c index ddf413e..2966bde 100644 --- a/src/boards/bmc80013b.c +++ b/src/boards/bmc80013b.c @@ -37,7 +37,7 @@ static void Sync(void) { if (mode & 0x02) setprg16(0x8000, (regs[0] & 0x0F) | (regs[1] & 0x70)); else - setprg16(0x8000, regs[0] & 0x0F | 0x80); + setprg16(0x8000, (regs[0] & 0x0F) | 0x80); setprg16(0xC000, regs[1]); setmirror(((regs[0] >> 4) & 1) ^ 1); } diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 3c9d42a..5c498fc 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -44,8 +44,6 @@ uint8 mmc3opts = 0; uint8 IRQCount, IRQLatch, IRQa; uint8 IRQReload; -static uint8 chip; - static SFORMAT MMC3_StateRegs[] = { { DRegBuf, 8, "REGS" }, @@ -1198,7 +1196,6 @@ void Mapper198_Init(CartInfo *info) { /* ---------------------------- Mapper 205 ------------------------------ */ /* UNIF boardname BMC-JC-016-2 https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */ -static uint8 block[] = {0, 0, 1, 2}; static void M205PW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c index 8bef280..910c8a2 100644 --- a/src/boards/resettxrom.c +++ b/src/boards/resettxrom.c @@ -27,8 +27,6 @@ #include "mapinc.h" #include "mmc3.h" -static uint8 chip; - static void M313CW(uint32 A, uint8 V) { setchr1(A, (EXPREGS[0] << 7) | (V & 0x7F)); } diff --git a/src/boards/t-262.c b/src/boards/t-262.c index 5aaa515..ae8c818 100644 --- a/src/boards/t-262.c +++ b/src/boards/t-262.c @@ -20,7 +20,6 @@ #include "mapinc.h" -static uint8 chip; static uint8 bank, base, lock, mirr, mode; static SFORMAT StateRegs[] = { diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c index b26d804..9749d48 100644 --- a/src/boards/vrc2and4.c +++ b/src/boards/vrc2and4.c @@ -31,7 +31,6 @@ static uint8 prgreg[2], chrreg[8]; static uint16 chrhi[8]; static uint8 regcmd, irqcmd, mirr, big_bank; static uint16 acount = 0; -static uint16 weirdo = 0; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; @@ -65,15 +64,8 @@ static void Sync(void) { setchr8(0); else { uint8 i; - /* if (!weirdo) */ - for (i = 0; i < 8; i++) - setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22); - /* else { - setchr1(0x0000, 0xFC); - setchr1(0x0400, 0xFD); - setchr1(0x0800, 0xFF); - weirdo--; - } */ + for (i = 0; i < 8; i++) + setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22); } switch (mirr & 0x3) { case 0: setmirror(MI_V); break; diff --git a/src/vsuni.c b/src/vsuni.c index 6c7dc1c..6645046 100644 --- a/src/vsuni.c +++ b/src/vsuni.c @@ -309,13 +309,10 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) { secptr = 0; - { - static int64 tko = 0x6e1ee06171d8ce3aULL, rbi = 0x6a02d345812938afULL; - if (vs->gameid & VS_TKOBOXING) - secptr = secdata[0]; - if (md5partial == rbi) - secptr = secdata[1]; - } + if (vs->gameid & VS_TKOBOXING) + secptr = secdata[0]; + if (vs->gameid & VS_RBIBASEBALL) + secptr = secdata[1]; vsdip = 0x0; if (vs->ioption & IOPTION_PREDIP) { From 878b0937f570788905577f93362d1b1ce558b228 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 1 Aug 2019 22:25:58 +0800 Subject: [PATCH 70/74] Update libretro_dipswitch.c --- src/drivers/libretro/libretro_dipswitch.c | 346 +++++++++++----------- src/git.h | 2 +- 2 files changed, 178 insertions(+), 170 deletions(-) diff --git a/src/drivers/libretro/libretro_dipswitch.c b/src/drivers/libretro/libretro_dipswitch.c index 4e3e148..fb778c5 100644 --- a/src/drivers/libretro/libretro_dipswitch.c +++ b/src/drivers/libretro/libretro_dipswitch.c @@ -11,6 +11,9 @@ #include "libretro_dipswitch.h" +#define MAX_CORE_OPTIONS 8 +#define MAX_VALUES 10 + extern CartInfo iNESCart; typedef struct { @@ -20,48 +23,47 @@ typedef struct { typedef struct { const char *option_name; - uint8 mask; - SETTING settings[10]; + SETTING settings[MAX_VALUES]; } DIPSWITCH; typedef struct { - unsigned gameid; - const char *romname_short; - DIPSWITCH dipswitch_core_options[8]; + unsigned game_id; + const char *game_name; + DIPSWITCH core_options[MAX_CORE_OPTIONS]; } VSUNIGAME; static VSUNIGAME dipswitch_battlecity = { VS_BATTLECITY, "battlecity", { - { "Credits for 2 Players", 0x01, + { "Credits for 2 Players", { { "2", 0x01 }, { "1", 0x00 }, { NULL, 0 }, }, }, - { "Lives", 0x02, + { "Lives", { { "5", 0x02 }, { "3", 0x00 }, { NULL, 0 }, }, }, - { "Demo Sounds", 0x04, + { "Demo Sounds", { { "disabled", 0x04 }, { "enabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, }, }; static VSUNIGAME dipswitch_castlevania = { VS_CASTLEVANIA, "castlevania", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -74,14 +76,14 @@ static VSUNIGAME dipswitch_castlevania = { { NULL, 0 }, }, }, - { "Lives", 0x08, + { "Lives", { { "3", 0x00 }, { "2", 0x08 }, { NULL, 0 }, } }, - { "Bonus", 0x30, + { "Bonus", { { "100k", 0x00 }, { "200k", 0x20 }, @@ -90,22 +92,21 @@ static VSUNIGAME dipswitch_castlevania = { { NULL, 0 }, }, }, - { "Difficulty", 0x40, + { "Difficulty", { { "Normal", 0x00 }, { "Hard", 0x40 }, { NULL, 0 }, }, }, - - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_clucluland = { VS_CLUCLULAND, "clucluland", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -118,7 +119,7 @@ static VSUNIGAME dipswitch_clucluland = { { NULL, 0 }, }, }, - { "Lives", 0x60, + { "Lives", { { "3", 0x00 }, { "4", 0x40 }, @@ -127,14 +128,14 @@ static VSUNIGAME dipswitch_clucluland = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_drmario = { VS_DRMARIO, "drmario", { - { "Drop Rate Increase After", 0x03, + { "Drop Rate Increase After", { { "7 Pills", 0x00 }, { "8 Pills", 0x01 }, @@ -143,7 +144,7 @@ static VSUNIGAME dipswitch_drmario = { { NULL, 0 }, }, }, - { "Virus Level", 0x0c, + { "Virus Level", { { "1", 0x00 }, { "3", 0x04 }, @@ -152,7 +153,7 @@ static VSUNIGAME dipswitch_drmario = { { NULL, 0 }, }, }, - { "Drop Speed Up", 0x30, + { "Drop Speed Up", { { "Slow", 0x00 }, { "Medium", 0x10 }, @@ -161,28 +162,28 @@ static VSUNIGAME dipswitch_drmario = { { NULL, 0 }, }, }, - { "Free Play", 0x40, + { "Free Play", { { "disabled", 0x00 }, { "enabled", 0x40 }, { NULL, 0 }, }, }, - { "Demo Sounds", 0x80, + { "Demo Sounds", { { "enabled", 0x80 }, { "disabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_duckhunt = { VS_DUCKHUNT, "duckhunt", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -195,7 +196,7 @@ static VSUNIGAME dipswitch_duckhunt = { { NULL, 0 }, }, }, - { "Difficulty", 0x18, + { "Difficulty", { { "Normal", 0x08 }, { "Medium", 0x10 }, @@ -204,14 +205,14 @@ static VSUNIGAME dipswitch_duckhunt = { { NULL, 0 }, }, }, - { "Miss per game", 0x20, + { "Miss per game", { { "5", 0x20 }, { "3", 0x00 }, { NULL, 0 }, }, }, - { "Bonus Life", 0xc0, + { "Bonus Life", { { "30000", 0x00 }, { "50000", 0x40 }, @@ -220,14 +221,14 @@ static VSUNIGAME dipswitch_duckhunt = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_excitebike = { VS_EXITEBIKE, "excitebike", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -240,7 +241,7 @@ static VSUNIGAME dipswitch_excitebike = { { NULL, 0 }, }, }, - { "Bonus Bike", 0x18, + { "Bonus Bike", { { "100k and Every 50k", 0x00 }, { "100k Only", 0x08 }, @@ -249,28 +250,28 @@ static VSUNIGAME dipswitch_excitebike = { { NULL, 0 }, }, }, - { "1st Qualifying Time", 0x20, + { "1st Qualifying Time", { { "Easy", 0x00 }, { "Hard", 0x20 }, { NULL, 0 }, }, }, - { "2nd Qualifying Time", 0x40, + { "2nd Qualifying Time", { { "Easy", 0x00 }, { "Hard", 0x40 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_freedomforce = { VS_FREEDOMFORCE, "freedomforce", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -283,7 +284,7 @@ static VSUNIGAME dipswitch_freedomforce = { { NULL, 0 }, }, }, - { "Health Awarded At", 0x18, + { "Health Awarded At", { { "10k 50k", 0x10 }, { "20k 60k", 0x00 }, @@ -292,7 +293,7 @@ static VSUNIGAME dipswitch_freedomforce = { { NULL, 0 }, }, }, - { "Difficulty (Damage)", 0x60, + { "Difficulty (Damage)", { { "Normal", 0x00 }, { "Easy", 0x40 }, @@ -301,21 +302,21 @@ static VSUNIGAME dipswitch_freedomforce = { { NULL, 0 }, }, }, - { "Difficulty (Enemy)", 0x80, + { "Difficulty (Enemy)", { { "Normal", 0x80 }, { "Hard", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_goonies = { VS_GOONIES, "goonies", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -328,14 +329,14 @@ static VSUNIGAME dipswitch_goonies = { { NULL, 0 }, }, }, - { "Lives", 0x08, + { "Lives", { { "3", 0x08 }, { "4", 0x00 }, { NULL, 0 }, }, }, - { "Bonus", 0x30, + { "Bonus", { { "40000", 0x00 }, { "50000", 0x20 }, @@ -344,28 +345,28 @@ static VSUNIGAME dipswitch_goonies = { { NULL, 0 }, }, }, - { "Timer", 0x40, + { "Timer", { { "Slow", 0x00 }, { "Fast", 0x40 }, { NULL, 0 }, }, }, - { "Demo Sounds", 0x80, + { "Demo Sounds", { { "enabled", 0x80 }, { "disabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_gradius = { VS_GRADIUS, "gradius", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -378,14 +379,14 @@ static VSUNIGAME dipswitch_gradius = { { NULL, 0 }, }, }, - { "Lives", 0x08, + { "Lives", { { "3", 0x08 }, { "4", 0x00 }, { NULL, 0 }, }, }, - { "Bonus", 0x30, + { "Bonus", { { "100k", 0x00 }, { "200k", 0x20 }, @@ -394,28 +395,28 @@ static VSUNIGAME dipswitch_gradius = { { NULL, 0 }, }, }, - { "Difficulty", 0x40, + { "Difficulty", { { "Normal", 0x00 }, { "Hard", 0x40 }, { NULL, 0 }, }, }, - { "Demo Sounds", 0x80, + { "Demo Sounds", { { "enabled", 0x80 }, { "disabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_gumshoe = { VS_GUMSHOE, "gumshoe", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -428,7 +429,7 @@ static VSUNIGAME dipswitch_gumshoe = { { NULL, 0 }, }, }, - { "Difficulty", 0x18, + { "Difficulty", { { "Normal", 0x08 }, { "Easy", 0x00 }, @@ -437,35 +438,35 @@ static VSUNIGAME dipswitch_gumshoe = { { NULL, 0 }, }, }, - { "Lives", 0x20, + { "Lives", { { "3", 0x20 }, { "5", 0x00 }, { NULL, 0 }, }, }, - { "Bullets per Balloon", 0x40, + { "Bullets per Balloon", { { "3", 0x00 }, { "2", 0x40 }, { NULL, 0 }, }, }, - { "Bonus Man Awarded", 0x80, + { "Bonus Man Awarded", { { "At 50000", 0x00 }, { "None", 0x80 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_hogansalley = { VS_HOGANSALLEY, "hogansalley", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -478,7 +479,7 @@ static VSUNIGAME dipswitch_hogansalley = { { NULL, 0 }, }, }, - { "Difficulty", 0x18, + { "Difficulty", { { "Normal", 0x08 }, { "Easy", 0x00 }, @@ -487,14 +488,14 @@ static VSUNIGAME dipswitch_hogansalley = { { NULL, 0 }, }, }, - { "Misses Per Game", 0x20, + { "Misses Per Game", { { "5", 0x20 }, { "3", 0x00 }, { NULL, 0 }, }, }, - { "Bonus Life", 0xc0, + { "Bonus Life", { { "30000", 0x00 }, { "50000", 0x40 }, @@ -503,14 +504,14 @@ static VSUNIGAME dipswitch_hogansalley = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_iceclimber = { VS_ICECLIMBER, "iceclimber", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -523,7 +524,7 @@ static VSUNIGAME dipswitch_iceclimber = { { NULL, 0 }, }, }, - { "Lives", 0x18, + { "Lives", { { "3", 0x00 }, { "4", 0x10 }, @@ -532,28 +533,28 @@ static VSUNIGAME dipswitch_iceclimber = { { NULL, 0 }, }, }, - { "Difficulty", 0x20, + { "Difficulty", { { "Easy", 0x00 }, { "Hard", 0x20 }, { NULL, 0 }, }, }, - { "Time before bear appears", 0x40, + { "Time before bear appears", { { "Long", 0x00 }, { "Short", 0x40 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_jajamaru = { VS_JAJAMARU, "jajamaru", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -566,7 +567,7 @@ static VSUNIGAME dipswitch_jajamaru = { { NULL, 0 }, }, }, - { "Lives", 0x18, + { "Lives", { { "3", 0x00 }, { "4", 0x10 }, @@ -574,21 +575,21 @@ static VSUNIGAME dipswitch_jajamaru = { { NULL, 0 }, }, }, - { "Demo Sounds", 0x80, + { "Demo Sounds", { { "enabled", 0x80 }, { "disabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_machrider = { VS_MACHRIDER, "machrider", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -601,7 +602,7 @@ static VSUNIGAME dipswitch_machrider = { { NULL, 0 }, }, }, - { "Time", 0x18, + { "Time", { { "280 (Easy)", 0x00 }, { "250", 0x10 }, @@ -610,21 +611,21 @@ static VSUNIGAME dipswitch_machrider = { { NULL, 0 }, }, }, - { "Enemies", 0x40, + { "Enemies", { { "Less", 0x00 }, { "More", 0x40 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_mightybj = { VS_MIGHTYBOMBJACK, "mightybj", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -637,7 +638,7 @@ static VSUNIGAME dipswitch_mightybj = { { NULL, 0 }, }, }, - { "Lives", 0x18, + { "Lives", { { "3", 0x00 }, { "4", 0x08 }, @@ -646,14 +647,14 @@ static VSUNIGAME dipswitch_mightybj = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_pinball = { VS_PINBALL, "pinball", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x01 }, { "1 Coin 2 Credits", 0x06 }, @@ -666,21 +667,21 @@ static VSUNIGAME dipswitch_pinball = { { NULL, 0 }, }, }, - { "Side Drain Walls", 0x08, + { "Side Drain Walls", { { "High", 0x00 }, { "Low", 0x08 }, { NULL, 0 }, }, }, - { "Bonus Life", 0x10, + { "Bonus Life", { { "50000", 0x00 }, { "70000", 0x10 }, { NULL, 0 }, }, }, - { "Balls", 0x60, + { "Balls", { { "3", 0x00 }, { "4", 0x40 }, @@ -689,28 +690,28 @@ static VSUNIGAME dipswitch_pinball = { { NULL, 0 }, } }, - { "Ball Speed", 0x80, + { "Ball Speed", { { "Slow", 0x00 }, { "Fast", 0x80 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_platoon = { VS_PLATOON, "platoon", { - { "Demo Sounds", 0x04, + { "Demo Sounds", { { "enabled", 0x00 }, { "disabled", 0x04 }, { NULL, 0 }, }, }, - { "Difficulty", 0x18, + { "Difficulty", { { "Normal", 0x08 }, { "Medium", 0x10 }, @@ -719,7 +720,7 @@ static VSUNIGAME dipswitch_platoon = { { NULL, 0 }, } }, - { "Coinage", 0xe0, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x20 }, @@ -732,14 +733,14 @@ static VSUNIGAME dipswitch_platoon = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_rbibaseball = { VS_RBIBASEBALL, "atari_rbibb", { - { "Coinage", 0x03, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, @@ -748,7 +749,7 @@ static VSUNIGAME dipswitch_rbibaseball = { { NULL, 0 }, }, }, - { "1p-inn 2p-inn time-min", 0x0c, + { "1p-inn 2p-inn time-min", { { "2 2 4", 0x0c }, { "3 2 6", 0x00 }, @@ -757,21 +758,21 @@ static VSUNIGAME dipswitch_rbibaseball = { { NULL, 0 }, } }, - { "Demo Sounds", 0x10, + { "Demo Sounds", { { "enabled", 0x00 }, { "disabled", 0x10 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_slalom = { VS_SLALOM, "slalom", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -784,14 +785,14 @@ static VSUNIGAME dipswitch_slalom = { { NULL, 0 }, }, }, - { "Freestyle Points", 0x08, + { "Freestyle Points", { { "Hold Time", 0x08 }, { "Left Right", 0x00 }, { NULL, 0 }, }, }, - { "Difficulty", 0x30, + { "Difficulty", { { "Normal", 0x10 }, { "Medium", 0x20 }, @@ -800,28 +801,28 @@ static VSUNIGAME dipswitch_slalom = { { NULL, 0 }, }, }, - { "Allow Continue", 0x40, + { "Allow Continue", { { "enabled", 0x00 }, { "disabled", 0x40 }, { NULL, 0 }, }, }, - { "Inverted Input", 0x80, + { "Inverted Input", { { "disabled", 0x00 }, { "enabled", 0x80 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_smb = { VS_SMB, "smb", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x06 }, @@ -834,14 +835,14 @@ static VSUNIGAME dipswitch_smb = { { NULL, 0 }, }, }, - { "Lives", 0x08, + { "Lives", { { "3", 0x00 }, { "2", 0x08 }, { NULL, 0 }, }, }, - { "Bonus Life", 0x30, + { "Bonus Life", { { "100 coins", 0x00 }, { "150 coins", 0x20 }, @@ -850,28 +851,28 @@ static VSUNIGAME dipswitch_smb = { { NULL, 0 }, }, }, - { "Timer", 0x40, + { "Timer", { { "Slow", 0x00 }, { "Fast", 0x40 }, { NULL, 0 }, }, }, - { "Continue Lives", 0x80, + { "Continue Lives", { { "3", 0x80 }, { "4", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_soccer = { VS_SOCCER, "soccer", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -884,7 +885,7 @@ static VSUNIGAME dipswitch_soccer = { { NULL, 0 }, }, }, - { "Points Timer", 0x18, + { "Points Timer", { { "1000 Pts", 0x08 }, { "1200 Pts", 0x18 }, @@ -893,7 +894,7 @@ static VSUNIGAME dipswitch_soccer = { { NULL, 0 }, }, }, - { "Difficulty", 0x60, + { "Difficulty", { { "Normal", 0x40 }, { "Medium", 0x20 }, @@ -902,14 +903,14 @@ static VSUNIGAME dipswitch_soccer = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_starluster = { VS_STARLUSTER, "starluster", { - { "Coinage", 0x03, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x02 }, @@ -918,14 +919,14 @@ static VSUNIGAME dipswitch_starluster = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_superskykid = { VS_SUPERSKYKID, "superskykid", { - { "Difficulty", 0x03, + { "Difficulty", { { "Normal", 0x01 }, @@ -935,14 +936,14 @@ static VSUNIGAME dipswitch_superskykid = { { NULL, 0 }, } }, - { "Lives", 0x04, + { "Lives", { { "3", 0x04 }, { "2", 0x00 }, { NULL, 0 }, }, }, - { "Coinage", 0x18, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x08 }, @@ -951,14 +952,14 @@ static VSUNIGAME dipswitch_superskykid = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_superxevious = { VS_SUPERXEVIOUS, "superxevious", { - { "Coinage", 0x30, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x10 }, @@ -967,14 +968,14 @@ static VSUNIGAME dipswitch_superxevious = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_tetris = { VS_TETRIS, "tetris", { - { "Difficulty", 0x0c, + { "Difficulty", { { "Normal", 0x04 }, { "Medium", 0x08 }, @@ -983,14 +984,14 @@ static VSUNIGAME dipswitch_tetris = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_tkoboxing = { VS_TKOBOXING, "tkoboxing", { - { "Coinage", 0x03, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x01 }, @@ -999,7 +1000,7 @@ static VSUNIGAME dipswitch_tkoboxing = { { NULL, 0 }, }, }, - { "Difficulty", 0x0c, + { "Difficulty", { { "Normal", 0x04 }, { "Hard", 0x08 }, @@ -1008,14 +1009,14 @@ static VSUNIGAME dipswitch_tkoboxing = { { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; static VSUNIGAME dipswitch_topgun = { VS_TOPGUN, "topgun", { - { "Coinage", 0x07, + { "Coinage", { { "1 Coin 1 Credit", 0x00 }, { "1 Coin 2 Credits", 0x04 }, @@ -1028,14 +1029,14 @@ static VSUNIGAME dipswitch_topgun = { { NULL, 0 }, }, }, - { "Lives per Coin", 0x08, + { "Lives per Coin", { { "3-12 Max", 0x00 }, { "2-9 Max", 0x08 }, { NULL, 0 }, }, }, - { "Bonus Life", 0x30, + { "Bonus Life", { { "30k and Every 50k", 0x00 }, { "50k and Every 100k", 0x20 }, @@ -1044,26 +1045,24 @@ static VSUNIGAME dipswitch_topgun = { { NULL, 0 }, }, }, - { "Difficulty", 0x40, + { "Difficulty", { { "Easy", 0x00 }, { "Hard", 0x40 }, { NULL, 0 }, }, }, - { "Demo Sounds", 0x80, + { "Demo Sounds", { { "enabled", 0x80 }, { "disabled", 0x00 }, { NULL, 0 }, }, }, - { NULL, 0, { {0} } } + { NULL, { {0} } }, } }; -#define DPSW_MAX 6 - enum { DPSW_NONE = 0, DPSW_VSUNI, @@ -1074,11 +1073,14 @@ static struct retro_core_option_definition option_defs_empty = { NULL, NULL, NULL, { {0} }, NULL }; -static struct retro_core_option_definition vscoreopt[DPSW_MAX]; +static struct retro_core_option_definition vscoreopt[MAX_CORE_OPTIONS]; static VSUNIGAME *vsgame = NULL; -static char *core_key[DPSW_MAX]; -static unsigned num_core_options; + +static char *core_key[MAX_CORE_OPTIONS]; static unsigned dipswitch_type = DPSW_NONE; +static unsigned numCoreOptions = 0; +static unsigned numValues[MAX_VALUES] = {0}; +static uint8 dipswitchPreset = 0; static const char *str_to_corekey(char *s) { @@ -1096,40 +1098,39 @@ static const char *str_to_corekey(char *s) return str; } -static void make_core_options(struct retro_core_option_definition *opt) +static void make_core_options(struct retro_core_option_definition *vs_core_options) { unsigned i, j; - for (i = 0; i < num_core_options; i++) + for (i = 0; i < numCoreOptions; i++) { struct retro_core_option_value vars_empty = { NULL, NULL }; - const char *romname_short = vsgame->romname_short; - const char *option_name = vsgame->dipswitch_core_options[i].option_name; + const char *game_name = vsgame->game_name; + const char *option_name = vsgame->core_options[i].option_name; char key[100] = {0}; /* Set core key and sanitize string */ - sprintf(key, "fceumm_dipswitch_%s-%s", romname_short, option_name); + sprintf(key, "fceumm_dipswitch_%s-%s", game_name, option_name); core_key[i] = calloc(strlen(key) + 1, sizeof(char)); strcpy(core_key[i], key); - opt[i].key = str_to_corekey(core_key[i]); + vs_core_options[i].key = str_to_corekey(core_key[i]); /* Set desc */ - opt[i].desc = option_name; + vs_core_options[i].desc = option_name; /* Set info */ - opt[i].info = NULL; + vs_core_options[i].info = NULL; - j = 0; /* Set core values */ - while (vsgame->dipswitch_core_options[i].settings[j].name) { - const char *var_value = vsgame->dipswitch_core_options[i].settings[j].name; - opt[i].values[j].value = var_value; - j++; + for (j = 0; j < numValues[i]; j++) { + const char *var_value = vsgame->core_options[i].settings[j].name; + vs_core_options[i].values[j].value = var_value; } - opt[i].values[j] = vars_empty; + + vs_core_options[i].values[j] = vars_empty; /* Set default value. Top entry used as default */ - opt[i].default_value = vsgame->dipswitch_core_options[i].settings[0].name; + vs_core_options[i].default_value = vsgame->core_options[i].settings[0].name; } } @@ -1201,9 +1202,10 @@ static VSUNIGAME *get_vsuni_dipswitch(unsigned id) static void update_dipswitch_vsuni(void) { unsigned index_key; - uint8 vsdip_new = FCEUI_VSUniGetDIPs(); + uint8 vsdip_new = 0; + uint8 last_vsdip = FCEUI_VSUniGetDIPs(); - for (index_key = 0; index_key < num_core_options; index_key++) + for (index_key = 0; index_key < numCoreOptions; index_key++) { struct retro_variable var = { NULL, NULL }; const char *key = vscoreopt[index_key].key; @@ -1213,25 +1215,21 @@ static void update_dipswitch_vsuni(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) continue; - index_value = 0; - while (vscoreopt[index_key].values[index_value].value) + for (index_value = 0; index_value < numValues[index_key]; index_value++) { const char *var_value = vscoreopt[index_key].values[index_value].value; - uint8 value, mask; + uint8 value = 0; - if (strcmp(var.value, var_value) != 0) { - index_value++; + if (strcmp(var.value, var_value) != 0) continue; - } - value = vsgame->dipswitch_core_options[index_key].settings[index_value].value; - mask = vsgame->dipswitch_core_options[index_key].mask; - vsdip_new &= (~mask); + + value = vsgame->core_options[index_key].settings[index_value].value; vsdip_new |= value; - index_value++; } } - if (FCEUI_VSUniGetDIPs() != vsdip_new) + vsdip_new |= dipswitchPreset; /* Append any default preset to new value */ + if (last_vsdip != vsdip_new) { vsdip = vsdip_new; #ifdef DEBUG @@ -1327,24 +1325,33 @@ size_t set_dipswitch_variables(unsigned current_index, struct retro_core_option_ /* VSUNI Dipswitch */ if (GameInfo->type == GIT_VSUNI) { + dipswitchPreset = FCEUI_VSUniGetDIPs(); vsgame = get_vsuni_dipswitch(GameInfo->gameid); if (vsgame) { - unsigned i; + unsigned i, j; - num_core_options = 0; + numCoreOptions = 0; dipswitch_type = DPSW_VSUNI; - /* Initialize dipswitch struct and count number of core options */ - for (i = 0; i < DPSW_MAX; i++) { + /* Initialize dipswitch struct with empty values */ + for (i = 0; i < MAX_CORE_OPTIONS; i++) vscoreopt[i] = option_defs_empty; - if (vsgame->dipswitch_core_options[i].option_name) - num_core_options++; + + /* Count number of core options and the number of values for each */ + for (i = 0; i < MAX_CORE_OPTIONS; i++) { + if (vsgame->core_options[i].option_name) { + for (j = 0; j < MAX_VALUES; j++) { + if (vsgame->core_options[i].settings[j].name) + numValues[i]++; + } + numCoreOptions++; + } } make_core_options(vscoreopt); - /* Copy dpsw struct to main core option struct */ + /* Append dipswitch struct to main core options struct */ while (vscoreopt[dipsw_size].key) { vars[index] = vscoreopt[dipsw_size]; index++; @@ -1367,7 +1374,8 @@ size_t set_dipswitch_variables(unsigned current_index, struct retro_core_option_ return (dipsw_size); } - return (0); + dipswitch_type = DPSW_NONE; + return (0); } void update_dipswitch(void) @@ -1386,7 +1394,7 @@ void DPSW_Cleanup(void) { unsigned i; - for (i = 0; i < DPSW_MAX; i++) { + for (i = 0; i < MAX_CORE_OPTIONS; i++) { if (core_key[i]) { free(core_key[i]); core_key[i] = NULL; diff --git a/src/git.h b/src/git.h index 913ac60..d14e792 100644 --- a/src/git.h +++ b/src/git.h @@ -25,7 +25,7 @@ typedef struct { uint8 MD5[16]; int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */ int soundchan; /* Number of sound channels. */ - int gameid; /* VS game id for per-game settings e.g. dip switches */ + int gameid; /* Currently used for VS game id for per-game dipswitch */ } FCEUGI; #endif From e724410ac466acfacd8d6072e0cec41191d0b178 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 1 Aug 2019 23:47:55 +0800 Subject: [PATCH 71/74] Update ines-correct.h --- src/ines-correct.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ines-correct.h b/src/ines-correct.h index 85a8dbe..b18c35f 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -354,6 +354,10 @@ {0xfe3e03a1, 197, -1}, /* Mortal Kombat III Special (YY-030) (Ch) [!] */ {0x9151d311, 197, -1}, /* Mortal Kombat III 28 Peoples (NT-328) (Ch) [!] */ {0x272709b9, 237, -1}, /* Teletubbies Y2K (420-in-1) */ + {0x2e27e0af, 227, -1}, /* Bio Hazard (No-Bug) (Unl).nes */ + {0x0e7e9309, 189, -1}, /* Street Fighter II - The World Warrior (Unl) [a1].nes */ + {0xa3ac0095, 189, -1}, /* Street Fighter II - The World Warrior (Unl) [a2].nes */ + {0xeced5899, 121, -1}, /* Ultimate Mortal Kombat 4 (Unl) [!].nes */ /* ines mappers that uses iNes 2.0 numbers */ @@ -368,6 +372,7 @@ {0x4dc6107d, 260, -1}, /* 2-in-1 - Boogerman + Flintstones, The (Unl) [p1][!] */ {0xb72b2cf4, 260, -1}, /* 2-in-1 - Aladdin + Lion King, The (Unl) [p1][!] */ {0xa1dc16c0, 262, -1}, /* Street Heroes (Asia) (Ja) (Unl */ + {0x1df10182, 263, -1}, /* Boogerman II (Rex-Soft) [!].nes */ {0xf956fcea, 521, -1}, /* Korean Igo (Korea) (Unl) */ {0x00000000, -1, -1} From bf08124293a8572479c937d00d1305263560a425 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 1 Aug 2019 23:57:52 +0800 Subject: [PATCH 72/74] Update vsuni.c Change this to normal comparison check --- src/vsuni.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vsuni.c b/src/vsuni.c index 6645046..b75f3fc 100644 --- a/src/vsuni.c +++ b/src/vsuni.c @@ -309,9 +309,9 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) { secptr = 0; - if (vs->gameid & VS_TKOBOXING) + if (vs->gameid == VS_TKOBOXING) secptr = secdata[0]; - if (vs->gameid & VS_RBIBASEBALL) + if (vs->gameid == VS_RBIBASEBALL) secptr = secdata[1]; vsdip = 0x0; From f667f86715e6af16aa8b374ae159d785fbf93331 Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Mon, 3 Jun 2019 22:37:09 -0500 Subject: [PATCH 73/74] libretro: allow mingw cross compile --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 7a0b1e2..06dc1f4 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -612,7 +612,7 @@ CFLAGS += -D_CRT_SECURE_NO_DEPRECATE # Windows else TARGET := $(TARGET_NAME)_libretro.dll - CC = gcc + CC ?= gcc SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=src/drivers/libretro/link.T PSS_STYLE :=2 endif From 3f0cf67403f2e9d92fcc0b054594b2b3a2c6da9f Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Wed, 17 Jul 2019 15:03:29 -0500 Subject: [PATCH 74/74] libretro: fix wiiu compile --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 06dc1f4..5c07900 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -279,7 +279,7 @@ else ifeq ($(platform), wiiu) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - PLATFORM_DEFINES := -DGEKKO -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float + PLATFORM_DEFINES := -DGEKKO -DHW_RVL -mcpu=750 -meabi -mhard-float PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int ENDIANNESS_DEFINES += -DMSB_FIRST STATIC_LINKING=1