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