From df6c895c5c7a24a26af967341fef3a8e7370187b Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 28 Feb 2022 21:45:50 +0000 Subject: [PATCH] sms, add sg-1000 support --- pico/media.c | 9 ++-- pico/mode4.c | 24 ++++----- pico/pico.h | 2 +- pico/pico_int.h | 3 +- pico/sms.c | 62 ++++++++++++++++------- platform/common/emu.c | 6 ++- platform/common/menu_pico.c | 2 +- platform/libretro/libretro.c | 4 +- platform/libretro/libretro_core_options.h | 1 + 9 files changed, 72 insertions(+), 41 deletions(-) diff --git a/pico/media.c b/pico/media.c index ae878f92..9bdb6370 100644 --- a/pico/media.c +++ b/pico/media.c @@ -313,10 +313,13 @@ enum media_type_e PicoLoadMedia(const char *filename, rom_data = NULL; // now belongs to PicoCart // simple test for GG. Do this here since m.hardware is nulled in Insert - if (PicoIn.AHW & PAHW_SMS) { - if (!strcmp(rom->ext,"gg") && !PicoIn.hwSelect) { - Pico.m.hardware |= 0x1; + if ((PicoIn.AHW & PAHW_SMS) && !PicoIn.hwSelect) { + if (!strcmp(rom->ext,"gg")) { + Pico.m.hardware |= PMS_HW_GG; lprintf("detected GG ROM\n"); + } else if (!strcmp(rom->ext,"sg")) { + Pico.m.hardware |= PMS_HW_SG; + lprintf("detected SG-1000 ROM\n"); } else lprintf("detected SMS ROM\n"); } diff --git a/pico/mode4.c b/pico/mode4.c index 6cabd38e..21bd95b1 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -163,7 +163,7 @@ static void ParseSpritesM4(int scanline) if (pv->reg[0] & 8) xoff = 0; xoff += line_offset; - if ((Pico.m.hardware & 0x3) == 0x3) + if ((Pico.m.hardware & (PMS_HW_GG|PMS_HW_LCD)) == (PMS_HW_GG|PMS_HW_LCD)) xoff -= 48; // GG LCD, adjust to center 160 px sat = (u8 *)PicoMem.vram + ((pv->reg[5] & 0x7e) << 7); @@ -302,7 +302,7 @@ static void DrawDisplayM4(int scanline) // tiles if (!(pv->debug_p & PVD_KILL_B)) { - if ((Pico.m.hardware & 0x3) == 0x3) { + if ((Pico.m.hardware & (PMS_HW_GG|PMS_HW_LCD)) == (PMS_HW_GG|PMS_HW_LCD)) { // on GG render only the center 160 px DrawStripM4(nametab , dx | ((cells-12)<< 16),(tilex+6) | (ty << 16)); } else if (pv->reg[0] & 0x80) { @@ -318,7 +318,7 @@ static void DrawDisplayM4(int scanline) if (!(pv->debug_p & PVD_KILL_S_LO)) DrawSpritesM4(); - if ((pv->reg[0] & 0x20) && (Pico.m.hardware & 0x3) != 0x3) { + if ((pv->reg[0] & 0x20) && (Pico.m.hardware & (PMS_HW_GG|PMS_HW_LCD)) != (PMS_HW_GG|PMS_HW_LCD)) { // first column masked with background, caculate offset to start of line dx = (dx&~0x1f) / 4; ty = ((pv->reg[7]&0x0f)|0x10) * 0x01010101; @@ -736,11 +736,11 @@ void PicoFrameStartSMS(void) } // Copy LCD enable flag for easier handling - Pico.m.hardware &= ~0x2; + Pico.m.hardware &= ~PMS_HW_LCD; if (PicoIn.opt & POPT_EN_GG_LCD) - Pico.m.hardware |= 0x2; + Pico.m.hardware |= PMS_HW_LCD; - if ((Pico.m.hardware & 0x3) == 0x3) { + if ((Pico.m.hardware & (PMS_HW_GG|PMS_HW_LCD)) == (PMS_HW_GG|PMS_HW_LCD)) { // GG LCD always has 160x144 regardless of settings screen_offset = 24; // nonetheless the vdp timing has 224 lines loffs = 48; @@ -796,7 +796,7 @@ void PicoLineSMS(int line) unsigned bgcolor; // GG LCD, render only visible part of screen - if ((Pico.m.hardware & 0x3) == 0x3 && (line < 24 || line >= 24+144)) + if ((Pico.m.hardware & (PMS_HW_GG|PMS_HW_LCD)) == (PMS_HW_GG|PMS_HW_LCD) && (line < 24 || line >= 24+144)) goto norender; if (PicoScanBegin != NULL && skip == 0) @@ -832,12 +832,10 @@ norender: /* Palette for TMS9918 mode, see https://www.smspower.org/Development/Palette */ // RGB values: #000000 #000000 #21c842 #5edc78 #5455ed #7d76fc #d4524d #42ebf5 // #fc5554 #ff7978 #d4c154 #e6ce80 #21b03b #c95bba #cccccc #ffffff -// 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff -// 0007 0818 1929 2a3a 3b4b 4c5c 5d6d 6e7e 7f8f 90a0 a1b1 b2c2 c3d3 d4e4 e5f5 f6 static u16 tmspal[32] = { // SMS palette -// 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0a00, 0x0f00, 0x0005, 0x0ff0, -// 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, + 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0a00, 0x0f00, 0x0005, 0x0ff0, + 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, // GG palette 0x0000, 0x0000, 0x04c2, 0x07d6, 0x0e55, 0x0f77, 0x055d, 0x0ee4, 0x055f, 0x077f, 0x05bd, 0x08ce, 0x04a2, 0x0b5c, 0x0ccc, 0x0fff, @@ -861,8 +859,8 @@ void PicoDoHighPal555SMS(void) /* SMS 6 bit cram data was already converted to MD/GG format by vdp write, * hence GG/SMS/TMS can all be handled the same here */ for (j = cnt; j > 0; j--) { - if (!(Pico.video.reg[0] & 0x4)) - spal = (u32 *)tmspal; // fixed palette in TMS modes + if (!(Pico.video.reg[0] & 0x4)) // fixed palette in TMS modes + spal = (u32 *)tmspal + (Pico.m.hardware & PMS_HW_SG ? 16/2 : 0); for (i = 0x20/2; i > 0; i--, spal++, dpal++) { t = *spal; #if defined(USE_BGR555) diff --git a/pico/pico.h b/pico/pico.h index 162a9bf6..dc596796 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -86,7 +86,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; #define PHWS_AUTO 0 #define PHWS_GG 1 #define PHWS_SMS 2 -#define PHWS_SG1000 3 +#define PHWS_SG 3 #define PQUIRK_FORCE_6BTN (1<<0) diff --git a/pico/pico_int.h b/pico/pico_int.h index 15d35161..85df6c5b 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -368,7 +368,8 @@ struct PicoMS unsigned char vdp_buffer; unsigned char vdp_hlatch; unsigned char io_gg[0x08]; - unsigned char pad[0x42]; + unsigned char mapcnt; + unsigned char pad[0x41]; }; // emu state and data for the asm code diff --git a/pico/sms.c b/pico/sms.c index c045d610..6f1cfc39 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -346,7 +346,7 @@ static void write_bank_msx(unsigned short a, unsigned char d) { if (a > 0x0003) return; // don't detect linear mapping to avoid confusing with Codemasters - if (Pico.ms.mapper != PMS_MAP_MSX && (Pico.ms.mapper || (a|d) == 0)) return; + if (Pico.ms.mapper != PMS_MAP_MSX && (Pico.ms.mapper || (a|d) == 0 || d >= 0x80)) return; elprintf(EL_Z80BNK, "bank msx %04x %02x @ %04x", a, d, z80_pc()); Pico.ms.mapper = PMS_MAP_MSX; Pico.ms.carthw[a] = d; @@ -457,19 +457,32 @@ static void write_bank_jang(unsigned short a, unsigned char d) // SG-1000 8KB RAM Adaptor mapper. 8KB RAM at address 0x2000 static void write_bank_x8k(unsigned short a, unsigned char d) { - // 8KB address range @ 0x2000 + // 8KB address range @ 0x2000 (adaptor) or @ 0x8000 (cartridge) if ((a&0xe000) != 0x2000 && (a&0xe000) != 0x8000) return; - // this is only available on SG-1000 - if (Pico.ms.mapper != PMS_MAP_8KBRAM && (Pico.ms.mapper || !(Pico.m.hardware & PMS_HW_SG))) return; + if (Pico.ms.mapper != PMS_MAP_8KBRAM && Pico.ms.mapper) return; + elprintf(EL_Z80BNK, "bank x8k %04x %02x @ %04x", a, d, z80_pc()); + ((unsigned char *)PicoMem.vram)[(a&0x1fff)+0x8000] = d; Pico.ms.mapper = PMS_MAP_8KBRAM; - ((unsigned char *)PicoMem.vram)[(a&0x1fff)+0x8000] = d; a &= 0xe000; + Pico.ms.carthw[0] = a >> 12; z80_map_set(z80_read_map, a, a+0x1fff, PicoMem.vram+0x4000, 0); z80_map_set(z80_write_map, a, a+0x1fff, PicoMem.vram+0x4000, 0); } +char *mappers[] = { + [PMS_MAP_SEGA] = "Sega", + [PMS_MAP_CODEM] = "Codemasters", + [PMS_MAP_KOREA] = "Korea", + [PMS_MAP_MSX] = "Korea MSX", + [PMS_MAP_N32K] = "Korea X-in-1", + [PMS_MAP_N16K] = "Korea 4-Pak", + [PMS_MAP_JANGGUN] = "Korea Janggun", + [PMS_MAP_NEMESIS] = "Korea Nemesis", + [PMS_MAP_8KBRAM] = "Taiwan 8K RAM", +}; + // TODO auto-selecting is not really reliable. // Before adding more mappers this should be revised. static void xwrite(unsigned int a, unsigned char d) @@ -490,14 +503,23 @@ static void xwrite(unsigned int a, unsigned char d) case PMS_MAP_8KBRAM: write_bank_x8k(a, d); break; case PMS_MAP_AUTO: + // disable autodetection after some time + if ((a >= 0xc000 && a < 0xfff8) || Pico.ms.mapcnt > 20) break; // NB the sequence of mappers is crucial for the auto detection - write_bank_x8k(a, d); - write_bank_n32k(a, d); - write_bank_sega(a, d); - write_bank_msx(a, d); - write_bank_codem(a, d); - write_bank_korea(a, d); - write_bank_n16k(a, d); + if (Pico.m.hardware & PMS_HW_SG) + write_bank_x8k(a, d); + else { + write_bank_n32k(a, d); + write_bank_sega(a, d); + write_bank_msx(a, d); + write_bank_codem(a, d); + write_bank_korea(a, d); + write_bank_n16k(a, d); + } + + Pico.ms.mapcnt ++; + if (Pico.ms.mapper) + elprintf(EL_STATUS, "autodetected %s mapper",mappers[Pico.ms.mapper]); break; } } @@ -520,23 +542,23 @@ void PicoResetMS(void) // set preselected hw/mapper from config if (PicoIn.hwSelect) { + Pico.m.hardware &= ~(PMS_HW_GG|PMS_HW_SG); switch (PicoIn.hwSelect) { case PHWS_GG: Pico.m.hardware |= PMS_HW_GG; break; - default: Pico.m.hardware &= ~PMS_HW_GG; break; + case PHWS_SG: Pico.m.hardware |= PMS_HW_SG; break; } } + Pico.ms.mapcnt = Pico.ms.mapper = 0; if (PicoIn.mapper) Pico.ms.mapper = PicoIn.mapper; Pico.m.hardware |= PMS_HW_JAP; // default region Japan if no TMR header - Pico.m.hardware |= PMS_HW_SG; // default to SG-1000 if no TMR header // check if the ROM header contains more system information for (tmr = 0x2000; tmr < 0xbfff && tmr <= Pico.romsize; tmr *= 2) { if (!memcmp(Pico.rom + tmr-16, "TMR SEGA", 8)) { - Pico.m.hardware &= ~PMS_HW_SG; // not SG-1000 hw = Pico.rom[tmr-1] >> 4; if (!PicoIn.hwSelect) { - Pico.m.hardware &= ~PMS_HW_GG; + Pico.m.hardware &= ~(PMS_HW_GG|PMS_HW_SG); if (hw >= 0x5 && hw < 0x8) Pico.m.hardware |= PMS_HW_GG; // GG cartridge detected } @@ -647,19 +669,21 @@ void PicoMemSetupMS(void) xwrite(0x0000, 0); xwrite(0x4000, 1); xwrite(0x8000, 2); - } else { + } else if (mapper) { xwrite(0xfffc, 0); xwrite(0xfffd, 0); xwrite(0xfffe, 1); xwrite(0xffff, 2); } - Pico.ms.mapper = mapper; } void PicoStateLoadedMS(void) { u8 mapper = Pico.ms.mapper; - if (Pico.ms.mapper == PMS_MAP_MSX || Pico.ms.mapper == PMS_MAP_NEMESIS) { + if (Pico.ms.mapper == PMS_MAP_8KBRAM) { + u16 a = Pico.ms.carthw[0] << 12; + xwrite(a+0x888, *((unsigned char *)PicoMem.vram+0x8888)); + } else if (Pico.ms.mapper == PMS_MAP_MSX || Pico.ms.mapper == PMS_MAP_NEMESIS) { xwrite(0x0000, Pico.ms.carthw[0]); xwrite(0x0001, Pico.ms.carthw[1]); xwrite(0x0002, Pico.ms.carthw[2]); diff --git a/platform/common/emu.c b/platform/common/emu.c index 845951ea..b233050a 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -332,9 +332,11 @@ static void system_announce(void) if (PicoIn.AHW & PAHW_SMS) { sys_name = "Master System"; - if (Pico.m.hardware & 0x1) + if (Pico.m.hardware & PMS_HW_GG) sys_name = "Game Gear"; - else if (Pico.m.hardware & 0x4) + else if (Pico.m.hardware & PMS_HW_SG) + sys_name = "SG-1000"; + else if (Pico.m.hardware & PMS_HW_JAP) sys_name = "Mark III"; #ifdef NO_SMS extra = " [no support]"; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 00da408c..6a72bc26 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -536,7 +536,7 @@ static int menu_loop_32x_options(int id, int keys) #ifndef NO_SMS -static const char *sms_hardwares[] = { "auto", "Game Gear", "Master System", NULL }; +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 h_smsfm[] = "FM sound is only supported by few games\nOther games may crash with FM enabled"; diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 4bbcb9d7..99fc826a 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1494,6 +1494,8 @@ static void update_variables(bool first_run) PicoIn.hwSelect = PHWS_AUTO; else if (strcmp(var.value, "Game Gear") == 0) PicoIn.hwSelect = PHWS_GG; + else if (strcmp(var.value, "SG-1000") == 0) + PicoIn.hwSelect = PHWS_SG; else PicoIn.hwSelect = PHWS_SMS; } @@ -1527,7 +1529,7 @@ static void update_variables(bool first_run) else if (strcmp(var.value, "Korea Nemesis") == 0) PicoIn.mapper = PMS_MAP_NEMESIS; else if (strcmp(var.value, "Taiwan 8K RAM") == 0) - PicoIn.mapper = PMS_MAP_8KRAM; + PicoIn.mapper = PMS_MAP_8KBRAM; else PicoIn.mapper = PMS_MAP_SEGA; } diff --git a/platform/libretro/libretro_core_options.h b/platform/libretro/libretro_core_options.h index 45edb1c1..6e627d49 100644 --- a/platform/libretro/libretro_core_options.h +++ b/platform/libretro/libretro_core_options.h @@ -117,6 +117,7 @@ struct retro_core_option_v2_definition option_defs_us[] = { { "Auto", NULL }, { "Game Gear", NULL }, { "Master System", NULL }, + { "SG-1000" , NULL }, { NULL, NULL }, }, "Auto" -- 2.39.5