diff --git a/builds/genesis_plus_gx_libretro.dll b/builds/genesis_plus_gx_libretro.dll index 076a753..d0bcea2 100644 Binary files a/builds/genesis_plus_gx_libretro.dll and b/builds/genesis_plus_gx_libretro.dll differ diff --git a/builds/genplus_cube.dol b/builds/genplus_cube.dol index 954bac8..9cbacad 100644 Binary files a/builds/genplus_cube.dol and b/builds/genplus_cube.dol differ diff --git a/builds/genplus_wii.dol b/builds/genplus_wii.dol index d17e09f..7f9503f 100644 Binary files a/builds/genplus_wii.dol and b/builds/genplus_wii.dol differ diff --git a/core/cart_hw/sms_cart.c b/core/cart_hw/sms_cart.c index 3d153e6..7f924ec 100644 --- a/core/cart_hw/sms_cart.c +++ b/core/cart_hw/sms_cart.c @@ -4,6 +4,9 @@ * * Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX) * + * Credits to Ben Sittler and Omar Cornut at smspower.org for Korean mappers + * reverse-engineering and description + * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: * @@ -40,23 +43,27 @@ #include "eeprom_93c.h" #include "terebi_oekaki.h" -#define MAPPER_NONE (0x00) -#define MAPPER_TEREBI (0x01) -#define MAPPER_RAM_2K (0x02) -#define MAPPER_RAM_8K (0x03) -#define MAPPER_RAM_8K_EXT1 (0x04) -#define MAPPER_SEGA (0x10) -#define MAPPER_SEGA_X (0x11) -#define MAPPER_93C46 (0x12) -#define MAPPER_CODIES (0x13) -#define MAPPER_MULTI_16K (0x14) -#define MAPPER_KOREA (0x15) -#define MAPPER_KOREA_16K (0x16) -#define MAPPER_KOREA_8K (0x20) -#define MAPPER_MSX (0x21) -#define MAPPER_MSX_NEMESIS (0x22) -#define MAPPER_MULTI_4X8K (0x23) -#define MAPPER_MULTI_32K (0x40) +#define MAPPER_NONE (0x00) +#define MAPPER_TEREBI (0x01) +#define MAPPER_RAM_2K (0x02) +#define MAPPER_RAM_8K (0x03) +#define MAPPER_RAM_8K_EXT1 (0x04) +#define MAPPER_SEGA (0x10) +#define MAPPER_SEGA_X (0x11) +#define MAPPER_93C46 (0x12) +#define MAPPER_CODIES (0x13) +#define MAPPER_MULTI_16K (0x14) +#define MAPPER_KOREA (0x15) +#define MAPPER_KOREA_16K (0x16) +#define MAPPER_MULTI_2x16K_V1 (0x17) +#define MAPPER_MULTI_2x16K_V2 (0x18) +#define MAPPER_MULTI_32K_16K (0x19) +#define MAPPER_KOREA_8K (0x20) +#define MAPPER_MSX (0x21) +#define MAPPER_MSX_NEMESIS (0x22) +#define MAPPER_MULTI_8K (0x23) +#define MAPPER_MULTI_4x8K (0x24) +#define MAPPER_MULTI_32K (0x40) typedef struct { @@ -92,36 +99,50 @@ static const rominfo_t game_list[] = {0x23BAC434, 0, 0, 0, MAPPER_SEGA_X, SYSTEM_GG, REGION_USA}, /* Shining Force Gaiden - Final Conflict (JP) [T-Eng] */ /* games using "Korean" mappers */ - {0x445525E2, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */ - {0x83F0EEDE, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Street Master (KR) */ - {0xA05258F5, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Won-Si-In (KR) */ - {0x06965ED9, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */ - {0x77EFE84A, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Cyborg Z (KR) */ - {0xF89AF3CC, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Knightmare II - The Maze of Galious (KR) */ - {0x9195C34C, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Boy 3 (KR) */ - {0xE316C06D, 0, 0, 0, MAPPER_MSX_NEMESIS, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis (KR) */ - {0x0A77FA5E, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis 2 (KR) */ - {0x89B79E77, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */ - {0x929222C4, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung II (KR) */ - {0x18FB98A3, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */ - {0x97D03541, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR) */ - {0x192949D5, 0, 0, 0, MAPPER_KOREA_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Janggun-ui Adeul (KR) */ - {0x76C5BDFB, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Jang Pung II [SMS-GG] (KR) */ - {0x01A2D595, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Battle [Proto] [SMS-GG] (US) */ - {0x9FA727A0, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 0] [SMS-GG] (US) */ - {0xFB481971, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 1] [SMS-GG] (US) */ - {0xA67F2A5C, 0, 0, 0, MAPPER_MULTI_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 4-Pak All Action (KR) */ - {0x98AF0236, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 1) (KR) */ - {0x6EBFE1C3, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 2) (KR) */ - {0x81A36A4F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 3) (KR) */ - {0x8D2D695D, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 4) (KR) */ - {0x82C09B57, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 5) (KR) */ - {0x4088EEB4, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 6) (KR) */ - {0xFBA94148, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 1) (KR) */ - {0x8333C86E, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 2) (KR) */ - {0x00E9809F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 3) (KR) */ - {0xBA5EC0E3, 0, 0, 0, MAPPER_MULTI_4X8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 128 Hap (KR) */ - {0x380D7400, 0, 0, 0, MAPPER_MULTI_4X8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Mo-eumjip 188 Hap (KR) */ + {0x445525E2, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */ + {0x83F0EEDE, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Street Master (KR) */ + {0xA05258F5, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Wonsiin (KR) */ + {0x06965ED9, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */ + {0x77EFE84A, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Cyborg Z (KR) */ + {0xF89AF3CC, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Knightmare II: The Maze of Galious (KR) */ + {0x9195C34C, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Boy 3 (KR) */ + {0xE316C06D, 0, 0, 0, MAPPER_MSX_NEMESIS, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis (KR) */ + {0x0A77FA5E, 0, 0, 0, MAPPER_MSX, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Nemesis 2 (KR) */ + {0x89B79E77, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */ + {0x929222C4, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung II (KR) */ + {0x18FB98A3, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */ + {0x97D03541, 0, 0, 0, MAPPER_KOREA, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR) */ + {0x192949D5, 0, 0, 0, MAPPER_KOREA_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Janggun-ui Adeul (KR) */ + {0x76C5BDFB, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_JAPAN_NTSC}, /* Jang Pung II [SMS-GG] (KR) */ + {0x01A2D595, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Battle [Proto] [SMS-GG] (US) */ + {0x9FA727A0, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 0] [SMS-GG] (US) */ + {0xFB481971, 0, 0, 0, MAPPER_KOREA_16K, SYSTEM_GGMS, REGION_USA}, /* Street Hero [Proto 1] [SMS-GG] (US) */ + {0xA67F2A5C, 0, 0, 0, MAPPER_MULTI_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 4-Pak All Action (KR) */ + {0x98AF0236, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 1) (KR) */ + {0x6EBFE1C3, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 2) (KR) */ + {0x81A36A4F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 3) (KR) */ + {0x8D2D695D, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 4) (KR) */ + {0x82C09B57, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 5) (KR) */ + {0x4088EEB4, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 3-in-1 The Best Game Collection (Vol. 6) (KR) */ + {0xFBA94148, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 1) (KR) */ + {0x8333C86E, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 2) (KR) */ + {0x00E9809F, 0, 0, 0, MAPPER_MULTI_32K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Hi-Com 8-in-1 The Best Game Collection (Vol. 3) (KR) */ + {0xBA5EC0E3, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* 128 Hap (KR) */ + {0x380D7400, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Mo-eumjip 188 Hap [v0] (KR) */ + {0xC76601E0, 0, 0, 0, MAPPER_MULTI_4x8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Mo-eumjip 188 Hap [v1] (KR) */ + {0x38B3A72F, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Game Chongjiphap 200 (KR).sms */ + {0xD3056492, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 270 Hap ~ Jaemissneun-270 (KR) */ + {0xAB07ECD4, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 260 Hap (KR) */ + {0x0CDE0938, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 30 Hap (KR) */ + {0xC29BB8CD, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game World 75 Hap (KR) */ + {0x660BF6EC, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Multi Game - Super 75 in 1 (KR) */ + {0xEB7790DE, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Multi Game - Super 125 in 1 (KR) */ + {0xE6AD4D4B, 0, 0, 0, MAPPER_MULTI_8K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super World 30 Hap (KR) */ + {0xEDB13847, 0, 0, 0, MAPPER_MULTI_2x16K_V1, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 45 (KR) */ + {0xA841C0B7, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 52 Hap (KR) */ + {0x4E202AA2, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 180 (KR) */ + {0xBA5D2776, 0, 0, 0, MAPPER_MULTI_2x16K_V2, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Super Game 200 (KR) */ + {0xC0AC6956, 0, 0, 0, MAPPER_MULTI_32K_16K, SYSTEM_SMS, REGION_JAPAN_NTSC}, /* Pigu-Wang 7 Hap - Jaemiiss-neun Game Mo-eumjip (KR) */ /* games using Codemaster mapper */ {0x29822980, 0, 0, 0, MAPPER_CODIES, SYSTEM_SMS2, REGION_EUROPE}, /* Cosmic Spacehead */ @@ -145,6 +166,7 @@ static const rominfo_t game_list[] = /* games using serial EEPROM */ {0x36EBCD6D, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* Majors Pro Baseball */ + {0x2DA8E943, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* Pro Yakyuu GG League */ {0x3D8D0DD6, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball [v0] */ {0xBB38CFD7, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball [v1] */ {0x578A8A38, 0, 0, 0, MAPPER_93C46, SYSTEM_GG, REGION_USA}, /* World Series Baseball '95 */ @@ -160,22 +182,24 @@ static const rominfo_t game_list[] = {0x092F29D6, 0, 0, 0, MAPPER_RAM_8K, SYSTEM_SG, REGION_JAPAN_NTSC}, /* The Castle (J) */ /* games requiring SG-1000 II 8K RAM extension adapter (type A) */ + {0x16F240D3, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Adventure Island [DahJee] (TW) */ {0xCE5648C3, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Bomberman Special [DahJee] (TW) */ {0x223397A1, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* King's Valley (TW) */ - {0x281D2888, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Knightmare (TW) */ + {0x281D2888, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Knightmare [Jumbo] (TW) */ {0x306D5F78, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Rally-X [DahJee] (TW) */ {0x29E047CC, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Road Fighter (TW) */ {0x5CBD1163, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Tank Battalion (TW) */ + {0x40414556, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* The Goonies (TW) */ {0x2E7166D5, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* The Legend of Kage (TW) */ {0xC550B4F0, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* TwinBee (TW) */ {0xFC87463C, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Yie Ar Kung-Fu II (TW) */ {0xDF7CBFA5, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Pippols (TW) */ - {0xE0816BB7, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Star Soldier (TW) */ + {0xE0816BB7, 0, 0, 0, MAPPER_RAM_8K_EXT1, SYSTEM_SGII, REGION_JAPAN_NTSC}, /* Star Soldier [DahJee] (TW) */ /* games requiring SG-1000 II 8K RAM extension adapter (type B) */ {0x69FC1494, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Bomberman Special (TW) */ {0xFFC4EE3F, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Magical Kid Wiz (TW) */ - {0x2E366CCF, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* The Castle (TW) */ + {0x2E366CCF, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* The Castle [MSX] (TW) */ {0xAAAC12CF, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Rally-X (TW) */ {0xD2EDD329, 0, 0, 0, MAPPER_NONE, SYSTEM_SGII_RAM_EXT, REGION_JAPAN_NTSC}, /* Road Fighter (TW) */ @@ -427,7 +451,11 @@ static void write_mapper_korea_8k(unsigned int address, unsigned char data); static void write_mapper_korea_16k(unsigned int address, unsigned char data); static void write_mapper_msx(unsigned int address, unsigned char data); static void write_mapper_multi_16k(unsigned int address, unsigned char data); +static void write_mapper_multi_2x16k_v1(unsigned int address, unsigned char data); +static void write_mapper_multi_2x16k_v2(unsigned int address, unsigned char data); +static void write_mapper_multi_32k_16k(unsigned int address, unsigned char data); static void write_mapper_multi_32k(unsigned int address, unsigned char data); +static void write_mapper_multi_8k(unsigned int address, unsigned char data); static void write_mapper_multi_4x8k(unsigned int address, unsigned char data); static void write_mapper_93c46(unsigned int address, unsigned char data); static void write_mapper_terebi(unsigned int address, unsigned char data); @@ -616,7 +644,8 @@ void sms_cart_reset(void) case MAPPER_KOREA_8K: case MAPPER_MSX: case MAPPER_MSX_NEMESIS: - case MAPPER_MULTI_4X8K: + case MAPPER_MULTI_4x8K: + case MAPPER_MULTI_8K: cart_rom.fcr[0] = 0; cart_rom.fcr[1] = 0; cart_rom.fcr[2] = 0; @@ -855,7 +884,8 @@ int sms_cart_context_load(uint8 *state) case MAPPER_KOREA_8K: case MAPPER_MSX: case MAPPER_MSX_NEMESIS: - case MAPPER_MULTI_4X8K: + case MAPPER_MULTI_4x8K: + case MAPPER_MULTI_8K: cart_rom.fcr[0] = 0; cart_rom.fcr[1] = 0; cart_rom.fcr[2] = 0; @@ -1029,7 +1059,7 @@ static void mapper_reset(void) /* "Nemesis" mapper specific */ if (slot.mapper == MAPPER_MSX_NEMESIS) { - /* first 8KB page is mapped to last 8KB ROM bank */ + /* first 8KB page ($0000-$1FFF) is mapped to last 8KB ROM bank */ for (i = 0x00; i < 0x08; i++) { z80_readmap[i] = &slot.rom[(0x0f << 13) | ((i & 0x07) << 10)]; @@ -1044,10 +1074,24 @@ static void mapper_reset(void) else { /* 16KB pages */ - mapper_16k_w(0,slot.fcr[0]); - mapper_16k_w(1,slot.fcr[1]); - mapper_16k_w(2,slot.fcr[2]); - mapper_16k_w(3,slot.fcr[3]); + if ((slot.mapper == MAPPER_MULTI_2x16K_V1) || (slot.mapper == MAPPER_MULTI_2x16K_V2)) + { + mapper_16k_w(1,slot.fcr[1]); + mapper_16k_w(2,slot.fcr[2]); + } + else if (slot.mapper == MAPPER_MULTI_32K_16K) + { + mapper_16k_w(1,slot.fcr[1]); + mapper_16k_w(2,slot.fcr[2]); + mapper_16k_w(3,slot.fcr[3]); + } + else + { + mapper_16k_w(0,slot.fcr[0]); + mapper_16k_w(1,slot.fcr[1]); + mapper_16k_w(2,slot.fcr[2]); + mapper_16k_w(3,slot.fcr[3]); + } } } @@ -1091,12 +1135,32 @@ static void mapper_reset(void) z80_writemem = write_mapper_multi_16k; break; + case MAPPER_MULTI_2x16K_V1: + z80_readmem = read_mapper_default; + z80_writemem = write_mapper_multi_2x16k_v1; + break; + + case MAPPER_MULTI_2x16K_V2: + z80_readmem = read_mapper_default; + z80_writemem = write_mapper_multi_2x16k_v2; + break; + + case MAPPER_MULTI_32K_16K: + z80_readmem = read_mapper_default; + z80_writemem = write_mapper_multi_32k_16k; + break; + case MAPPER_MULTI_32K: z80_readmem = read_mapper_default; z80_writemem = write_mapper_multi_32k; break; - case MAPPER_MULTI_4X8K: + case MAPPER_MULTI_8K: + z80_readmem = read_mapper_default; + z80_writemem = write_mapper_multi_8k; + break; + + case MAPPER_MULTI_4x8K: z80_readmem = read_mapper_default; z80_writemem = write_mapper_multi_4x8k; break; @@ -1146,6 +1210,17 @@ static void mapper_8k_w(int offset, unsigned char data) { z80_readmap[i] = &page[(i & 0x07) << 10]; } + + /* Multi Korean mapper specific */ + if (slot.mapper == MAPPER_MULTI_8K) + { + /* $2000-$3FFF is mirror of $A000-$BFFF */ + for (i = 0x08; i < 0x10; i++) + { + z80_readmap[i] = z80_readmap[0x20 + i]; + } + } + break; } @@ -1243,7 +1318,7 @@ static void mapper_16k_w(int offset, unsigned char data) case 1: /* cartridge ROM bank (16KB) at $0000-$3FFF */ { /* first 1KB is not fixed (CODEMASTER or MULTI mappers only) */ - if ((slot.mapper == MAPPER_CODIES) || (slot.mapper == MAPPER_MULTI_16K)) + if (slot.mapper >= MAPPER_CODIES) { z80_readmap[0] = &slot.rom[(page << 14)]; } @@ -1286,13 +1361,66 @@ static void mapper_16k_w(int offset, unsigned char data) } } } + + /* Multi Korean mappers specific */ + else if (slot.mapper == MAPPER_MULTI_2x16K_V1) + { + if (slot.fcr[0] != 0x01) + { + /* $8000-$BFFF is not mapped to cartridge ROM (unused area) */ + for (i = 0x20; i < 0x30; i++) + { + z80_readmap[i] = cart.rom + 0x510400; + } + } + else + { + /* $8000-$9FFF is mirror of $6000-$7FFF */ + for (i = 0x20; i < 0x28; i++) + { + z80_readmap[i] = z80_readmap[i - 0x08]; + } + + /* $A000-$BFFF is mirror of $4000-$5FFF */ + for (i = 0x28; i < 0x30; i++) + { + z80_readmap[i] = z80_readmap[i - 0x18]; + } + } + } + else if (slot.mapper == MAPPER_MULTI_2x16K_V2) + { + if (slot.fcr[0] != 0x03) + { + /* $8000-$BFFF is not mapped to cartridge ROM (unused area) */ + for (i = 0x20; i < 0x30; i++) + { + z80_readmap[i] = cart.rom + 0x510400; + } + } + else + { + /* $8000-$9FFF is mirror of $6000-$7FFF */ + for (i = 0x20; i < 0x28; i++) + { + z80_readmap[i] = z80_readmap[i - 0x08]; + } + + /* $A000-$BFFF is mirror of $4000-$5FFF */ + for (i = 0x28; i < 0x30; i++) + { + z80_readmap[i] = z80_readmap[i - 0x18]; + } + } + } + break; } case 3: /* cartridge ROM bank (16KB) at $8000-$BFFF */ { /* check that external RAM (16KB) is not mapped at $8000-$BFFF (SEGA mapper only) */ - if ((slot.fcr[0] & 0x08)) break; + if ((slot.fcr[0] & 0x08) && (slot.mapper != MAPPER_MULTI_32K_16K)) break; /* first 8KB */ for (i = 0x20; i < 0x28; i++) @@ -1407,6 +1535,116 @@ static void write_mapper_multi_16k(unsigned int address, unsigned char data) z80_writemap[address >> 10][address & 0x03FF] = data; } +static void write_mapper_multi_2x16k_v1(unsigned int address, unsigned char data) +{ + if (address == 0xFFFE) + { + /* save mapper configuration to unused register */ + slot.fcr[0] = (data >> 5) & 0x03; + + switch (slot.fcr[0]) + { + case 0x00: + { + data &= 0x1f; + mapper_16k_w(1,0x00); + mapper_16k_w(2,data); + break; + } + + case 0x01: + { + data &= 0x1f; + mapper_16k_w(1,0x00); + mapper_16k_w(2,data); + break; + } + + default: + { + data &= 0x1e; + mapper_16k_w(1,data); + mapper_16k_w(2,data+1); + break; + } + } + } + + z80_writemap[address >> 10][address & 0x03FF] = data; +} + +static void write_mapper_multi_2x16k_v2(unsigned int address, unsigned char data) +{ + if (address == 0xBFFC) + { + /* save mapper configuration to unused register */ + slot.fcr[0] = (data >> 6) & 0x03; + + switch (slot.fcr[0]) + { + case 0x00: + { + data &= 0x3e; + mapper_16k_w(1,data); + mapper_16k_w(2,data+1); + return; + } + + case 0x01: + { + data &= 0x3f; + mapper_16k_w(1,data); + mapper_16k_w(2,data); + return; + } + + case 0x02: + { + data &= 0x3f; + mapper_16k_w(1,0x20); + mapper_16k_w(2,data); + return; + } + + default: + { + data &= 0x3f; + mapper_16k_w(1,0x20); + mapper_16k_w(2,data); + return; + } + } + } + + z80_writemap[address >> 10][address & 0x03FF] = data; +} + +static void write_mapper_multi_32k_16k(unsigned int address, unsigned char data) +{ + z80_writemap[address >> 10][address & 0x03FF] = data; + + address &= 0xBFEF; + + if (address == 0xBFE5) + { + /* save 16K bank index to unused register */ + slot.fcr[0] = (data & 0x3f) << 1; + mapper_16k_w(1,slot.fcr[0]); + mapper_16k_w(2,slot.fcr[0]+1); + mapper_16k_w(3,slot.fcr[0]+1); + } + else if (address == 0xBFEE) + { + data &= 0x1f; + mapper_16k_w(2,slot.fcr[0]+data); + } + else if (address == 0xBFEF) + { + data &= 0x1f; + mapper_16k_w(3,slot.fcr[0]+data); + } +} + static void write_mapper_multi_32k(unsigned int address, unsigned char data) { if (address == 0xFFFF) @@ -1417,6 +1655,35 @@ static void write_mapper_multi_32k(unsigned int address, unsigned char data) z80_writemap[address >> 10][address & 0x03FF] = data; } +static void write_mapper_multi_8k(unsigned int address, unsigned char data) +{ + if (address == 0x0000) + { + mapper_8k_w(0,data); + return; + } + + if (address == 0x0100) + { + mapper_8k_w(2,data); + return; + } + + if (address == 0x0200) + { + mapper_8k_w(1,data); + return; + } + + if (address == 0x0300) + { + mapper_8k_w(3,data); + return; + } + + z80_writemap[address >> 10][address & 0x03FF] = data; +} + static void write_mapper_multi_4x8k(unsigned int address, unsigned char data) { if (address == 0x2000)