From 7c6f79147b78894fc056582f699f109be5dafd54 Mon Sep 17 00:00:00 2001
From: kub <derkub@gmail.com>
Date: Wed, 14 Sep 2022 19:29:02 +0000
Subject: [PATCH] sms, add xor 4x8k mapper

---
 pico/pico_int.h             |  1 +
 pico/sms.c                  | 32 +++++++++++++++++++++++++++++---
 platform/common/menu_pico.c |  5 +++--
 platform/linux/menu.c       |  1 -
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/pico/pico_int.h b/pico/pico_int.h
index 15d151ba..d64c6cc6 100644
--- a/pico/pico_int.h
+++ b/pico/pico_int.h
@@ -357,6 +357,7 @@ struct PicoMisc
 #define PMS_MAP_JANGGUN	7
 #define PMS_MAP_NEMESIS	8
 #define PMS_MAP_8KBRAM	9
+#define PMS_MAP_XOR	10
 
 struct PicoMS
 {
diff --git a/pico/sms.c b/pico/sms.c
index bb310935..eb8da7e5 100644
--- a/pico/sms.c
+++ b/pico/sms.c
@@ -454,6 +454,23 @@ static void write_bank_jang(unsigned short a, unsigned char d)
   }
 }
 
+// Korean 188-in-1. 4 8KB banks from 0x4000, selected by xor'd bank index
+static void write_bank_xor(unsigned short a, unsigned char d)
+{
+  // 4x8KB bank select @0x2000
+  if ((a&0x6000) != 0x2000) return;
+  if (Pico.ms.mapper != PMS_MAP_XOR && Pico.ms.mapper) return;
+
+  elprintf(EL_Z80BNK, "bank 32k %04x %02x @ %04x", a, d, z80_pc());
+  Pico.ms.mapper = PMS_MAP_XOR;
+
+  Pico.ms.carthw[0] = d;
+  z80_map_set(z80_read_map,  0x4000, 0x5fff, Pico.rom + ((d^0x1f) << 13), 0);
+  z80_map_set(z80_read_map,  0x6000, 0x7fff, Pico.rom + ((d^0x1e) << 13), 0);
+  z80_map_set(z80_read_map,  0x8000, 0x9fff, Pico.rom + ((d^0x1d) << 13), 0);
+  z80_map_set(z80_read_map,  0xa000, 0xbfff, Pico.rom + ((d^0x1c) << 13), 0);
+}
+
 // SG-1000 8KB RAM Adaptor mapper. 8KB RAM at address 0x2000
 static void write_bank_x8k(unsigned short a, unsigned char d)
 {
@@ -481,6 +498,7 @@ char *mappers[] = {
   [PMS_MAP_JANGGUN]  = "Korea Janggun",
   [PMS_MAP_NEMESIS]  = "Korea Nemesis",
   [PMS_MAP_8KBRAM]   = "Taiwan 8K RAM",
+  [PMS_MAP_XOR]      = "Korea XOR",
 };
 
 // TODO auto-selecting is not really reliable.
@@ -501,6 +519,7 @@ static void xwrite(unsigned int a, unsigned char d)
   case PMS_MAP_JANGGUN: write_bank_jang(a, d);  break;
   case PMS_MAP_NEMESIS: write_bank_msxn(a, d);  break;
   case PMS_MAP_8KBRAM:  write_bank_x8k(a, d);   break;
+  case PMS_MAP_XOR:     write_bank_xor(a, d);   break;
 
   case PMS_MAP_AUTO:
         // disable autodetection after some time
@@ -515,6 +534,7 @@ static void xwrite(unsigned int a, unsigned char d)
           write_bank_codem(a, d);
           write_bank_korea(a, d);
           write_bank_n16k(a, d);
+          write_bank_xor(a, d);
         }
 
         Pico.ms.mapcnt ++;
@@ -671,17 +691,21 @@ void PicoMemSetupMS(void)
   } else if (mapper == PMS_MAP_JANGGUN) {
     xwrite(0xfffe, 1);
     xwrite(0xffff, 2);
+  } else if (mapper == PMS_MAP_XOR) {
+    xwrite(0x2000, 0);
   } else if (mapper == PMS_MAP_CODEM) {
     xwrite(0x0000, 0);
     xwrite(0x4000, 1);
     xwrite(0x8000, 2);
-  } else if (mapper != PMS_MAP_8KBRAM) {
-    // pre-initialize Sega mapper to linear mapping (else state load may fail)
+  } else if (mapper == PMS_MAP_SEGA) {
     xwrite(0xfffc, 0);
     xwrite(0xfffd, 0);
     xwrite(0xfffe, 1);
     xwrite(0xffff, 2);
-    Pico.ms.mapper = mapper;
+  } else if (mapper == PMS_MAP_AUTO) {
+    // pre-initialize Sega mapper to linear mapping (else state load may fail)
+    Pico.ms.carthw[0xe] = 0x1;
+    Pico.ms.carthw[0xf] = 0x2;
   }
 }
 
@@ -709,6 +733,8 @@ void PicoStateLoadedMS(void)
     xwrite(0x6000, Pico.ms.carthw[3]);
     xwrite(0x8000, Pico.ms.carthw[4]);
     xwrite(0xa000, Pico.ms.carthw[5]);
+  } else if (mapper == PMS_MAP_XOR) {
+    xwrite(0x2000, Pico.ms.carthw[0]);
   } else if (mapper == PMS_MAP_CODEM) {
     xwrite(0x0000, Pico.ms.carthw[0]);
     xwrite(0x4000, Pico.ms.carthw[1]);
diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c
index 559e5cd3..4515bd28 100644
--- a/platform/common/menu_pico.c
+++ b/platform/common/menu_pico.c
@@ -562,14 +562,15 @@ static int menu_loop_32x_options(int id, int keys)
 #ifndef NO_SMS
 
 static const char *sms_hardwares[] = { "auto", "Game Gear", "Master System", "SG-1000", NULL };
-static const char *sms_mappers[] = { "auto", "Sega", "Codemasters", "Korea", "Korea MSX", "Korea X-in-1", "Korea 4-Pak", "Korea Janggun", "Korea Nemesis", "Taiwan 8K RAM", NULL };
+static const char *gg_ghosting_opts[] = { "OFF", "weak", "normal", NULL };
+static const char *sms_mappers[] = { "auto", "Sega", "Codemasters", "Korea", "Korea MSX", "Korea X-in-1", "Korea 4-Pak", "Korea Janggun", "Korea Nemesis", "Taiwan 8K RAM", "Korea XOR", NULL };
 static const char h_smsfm[] = "FM sound is only supported by few games\nOther games may crash with FM enabled";
 static const char h_ghost[] = "simulates the inertia of the GG LCD display";
 
 static menu_entry e_menu_sms_options[] =
 {
 	mee_enum      ("System",            MA_SMSOPT_HARDWARE, PicoIn.hwSelect, sms_hardwares),
-	mee_enum_h    ("Game Gear LCD ghosting", MA_SMSOPT_GHOSTING, currentConfig.ghosting, men_ghosting_opts, h_ghost),
+	mee_enum_h    ("Game Gear LCD ghosting", MA_SMSOPT_GHOSTING, currentConfig.ghosting, gg_ghosting_opts, h_ghost),
 	mee_onoff_h   ("FM Sound Unit",     MA_OPT2_ENABLE_YM2413, PicoIn.opt, POPT_EN_YM2413, h_smsfm),
 	mee_enum      ("Cartridge mapping", MA_SMSOPT_MAPPER, PicoIn.mapper, sms_mappers),
 	mee_end,
diff --git a/platform/linux/menu.c b/platform/linux/menu.c
index 63305e37..f53380c4 100644
--- a/platform/linux/menu.c
+++ b/platform/linux/menu.c
@@ -2,7 +2,6 @@
 
 static const char *men_scaling_opts[] = { "OFF", "software", "hardware", NULL };
 static const char *men_filter_opts[] = { "nearest", "smoother", "bilinear 1", "bilinear 2", NULL };
-static const char *men_ghosting_opts[] = { "OFF", "weak", "normal", NULL };
 
 static const char h_scale[] = "hardware scaling might not work on some devices";
 static const char h_stype[] = "scaler algorithm for software scaling";
-- 
2.39.5