From 549dd4070217bf20759d3dbe068c6c855341f5f8 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 26 Sep 2024 23:21:28 +0200 Subject: [PATCH] core, mode 1 support --- pico/cart.c | 24 +++++----- pico/cd/cdd.c | 2 +- pico/cd/mcd.c | 17 ++++++- pico/cd/megasd.c | 6 ++- pico/cd/memory.c | 42 +++++------------ pico/cd/sek.c | 2 - pico/media.c | 87 ++++++++++++++++++++++++++---------- pico/memory.c | 6 ++- pico/pico.c | 5 +-- pico/pico.h | 1 + pico/pico_int.h | 2 + pico/sek.c | 2 - pico/videoport.c | 7 +-- platform/common/emu.c | 36 ++++++++------- platform/libretro/libretro.c | 41 ++++++++++------- 15 files changed, 161 insertions(+), 119 deletions(-) diff --git a/pico/cart.c b/pico/cart.c index ce067921b..2a5d12e3e 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -797,12 +797,6 @@ int PicoCartLoad(pm_file *f, const unsigned char *rom, unsigned int romsize, if (!is_sms) { - // maybe we are loading MegaCD BIOS? - if (!(PicoIn.AHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom_data+0x124, "BOOT", 4) || - !strncmp((char *)rom_data+0x128, "BOOT", 4))) { - PicoIn.AHW |= PAHW_MCD; - } - // Check for SMD: if (size >= 0x4200 && (size&0x3fff) == 0x200 && ((rom_data[0x2280] == 'S' && rom_data[0x280] == 'E') || (rom_data[0x280] == 'S' && rom_data[0x2281] == 'E'))) { @@ -932,14 +926,18 @@ static unsigned int rom_crc32(int size) return crc; } -static int rom_strcmp(int rom_offset, const char *s1) +int rom_strcmp(void *rom, int size, int offset, const char *s1) { int i, len = strlen(s1); - const char *s_rom = (const char *)Pico.rom; - if (rom_offset + len > Pico.romsize) - return 0; + const char *s_rom = (const char *)rom; + if (offset + len > size) + return 1; + + if (PicoIn.AHW & PAHW_SMS) + return strncmp(s_rom + offset, s1, strlen(s1)); + for (i = 0; i < len; i++) - if (s1[i] != s_rom[MEM_BE2(i + rom_offset)]) + if (s1[i] != s_rom[MEM_BE2(i + offset)]) return 1; return 0; } @@ -1063,7 +1061,7 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram, { int offs; offs = strtoul(p, &r, 0); - if (offs < 0 || offs > Pico.romsize) { + if (offs < 0) { elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs); goto bad; } @@ -1079,7 +1077,7 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram, goto bad; *r = 0; - if (rom_strcmp(offs, p) == 0) + if (rom_strcmp(Pico.rom, Pico.romsize, offs, p) == 0) any_checks_passed = 1; else skip_sect = 1; diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 9079f74d1..6841b9470 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -165,7 +165,7 @@ void cdd_reset(void) cdd.latency = 0; /* reset track index */ - cdd.index = -1; + cdd.index = 0; /* reset logical block address */ cdd.lba = 0; diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 368181bec..178bac3d4 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -20,6 +20,19 @@ static unsigned int mcd_s68k_cycle_base; mcd_state *Pico_mcd; +PICO_INTERNAL void PicoCreateMCD(unsigned char *bios_data, int bios_size) +{ + if (!Pico_mcd) { + Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0); + memset(Pico_mcd, 0, sizeof(mcd_state)); + } + if (bios_data && bios_size > 0) { + if (bios_size > sizeof(Pico_mcd->bios)) + bios_size = sizeof(Pico_mcd->bios); + memcpy(Pico_mcd->bios, bios_data, bios_size); + } +} + PICO_INTERNAL void PicoInitMCD(void) { SekInitS68k(); @@ -59,8 +72,8 @@ PICO_INTERNAL void PicoPowerMCD(void) Pico_mcd->m.state_flags = PCD_ST_S68K_RST; Pico_mcd->m.busreq = 2; // busreq on, s68k in reset Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode, m68k access - if (Pico.romsize == 0x20000) // hack to detect BIOS, no GA HINT vector for MSU - memset(Pico.rom + 0x70, 0xff, 4); + if (Pico.romsize == 0) // no HINT vector from gate array for MSU + memset(Pico_mcd->bios + 0x70, 0xff, 4); } void pcd_soft_reset(void) diff --git a/pico/cd/megasd.c b/pico/cd/megasd.c index 53f3aa538..b53f8d320 100644 --- a/pico/cd/megasd.c +++ b/pico/cd/megasd.c @@ -20,7 +20,7 @@ #include "cdd.h" #include "megasd.h" -#define CDD_PLAY_OFFSET 3 // CDD starts this many sectors early +#define CDD_PLAY_OFFSET 3 // CDD play starts this many sectors early struct megasd Pico_msd; // MEGASD state @@ -145,7 +145,7 @@ static void msd_transfer() // update msd state (called every 1/75s, like CDD irq) void msd_update() { - if (Pico_msd.initialized) { + if (Pico_msd.initialized && (Pico_msd.readlba >= 0 || Pico_msd.index >= 0)) { // CD LEDs s68k_write8(0xff8000,(cdd.status == CD_PLAY) | 0x2); @@ -162,6 +162,7 @@ void msd_update() if (!Pico_msd.loop || Pico_msd.index < 0) { cdd_stop(); // audio done + Pico_msd.index = -1; } else cdd_play(Pico_msd.looplba - CDD_PLAY_OFFSET); } @@ -213,6 +214,7 @@ static void msd_init(void) // enable CD drive s68k_write8(0xff8037, 0x4); + s68k_write8(0xff8000, 0x2); PicoResetHook = msd_reset; } diff --git a/pico/cd/memory.c b/pico/cd/memory.c index f6d64e5a4..7699df296 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -127,7 +127,7 @@ static u32 m68k_reg_read16(u32 a) d = Pico_mcd->s68k_regs[4]<<8; goto end; case 6: - d = *(u16 *)(Pico.rom + 0x72); + d = *(u16 *)(Pico_mcd->bios + 0x72); goto end; case 8: d = cdc_host_r(0); @@ -233,12 +233,12 @@ void m68k_reg_write8(u32 a, u32 d) remap_word_ram(d); goto write_comm; case 6: - Pico.rom[MEM_BE2(0x72)] = d; // simple hint vector changer + Pico_mcd->bios[MEM_BE2(0x72)] = d; // simple hint vector changer return; case 7: - Pico.rom[MEM_BE2(0x73)] = d; + Pico_mcd->bios[MEM_BE2(0x73)] = d; elprintf(EL_CDREGS, "hint vector set to %04x%04x", - ((u16 *)Pico.rom)[0x70/2], ((u16 *)Pico.rom)[0x72/2]); + ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]); return; case 8: (void) cdc_host_r(0); // acts same as reading @@ -673,23 +673,6 @@ static void PicoWriteM68k16_cell1(u32 a, u32 d) } #endif -// BIOS faking for MSU-MD, checks for "SEGA" at 0x400100 to detect CD drive -static u8 bios_id[4] = "SEGA"; - -static u32 PicoReadM68k8_bios(u32 a) -{ - if ((a & 0xfffffc) == BASE+0x100) // CD detection by MSU - return bios_id[a&3]; - return 0; -} - -static u32 PicoReadM68k16_bios(u32 a) -{ - if ((a & 0xfffffc) == BASE+0x100) // CD detection by MSU - return (bios_id[a&2]<<8) | bios_id[(a&2)+1]; - return 0; -} - // RAM cart (400000 - 7fffff, optional) static u32 PicoReadM68k8_ramc(u32 a) { @@ -1228,7 +1211,7 @@ void pcd_state_loaded_mem(void) Pico_mcd->m.dmna_ret_2m &= 3; // restore hint vector - *(u16 *)(Pico.rom + 0x72) = Pico_mcd->m.hint_vector; + *(u16 *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; } #ifdef EMU_M68K @@ -1237,27 +1220,22 @@ static void m68k_mem_setup_cd(void); PICO_INTERNAL void PicoMemSetupCD(void) { - if (!Pico_mcd) { - Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0); - memset(Pico_mcd, 0, sizeof(mcd_state)); - } - pcd_base_address = (Pico.romsize != 0x20000 ? 0x400000 : 0x000000); + pcd_base_address = (Pico.romsize ? 0x400000 : 0x000000); // setup default main68k map PicoMemSetup(); // main68k map (BIOS or MSU mapped by PicoMemSetup()): - if (pcd_base_address != 0) { - // MSU cartridge. Fake BIOS detection - cpu68k_map_set(m68k_read8_map, 0x400000, 0x41ffff, PicoReadM68k8_bios, 1); - cpu68k_map_set(m68k_read16_map, 0x400000, 0x41ffff, PicoReadM68k16_bios, 1); + cpu68k_map_set(m68k_read8_map, BASE, BASE+0x01ffff, Pico_mcd->bios, 0); + cpu68k_map_set(m68k_read16_map, BASE, BASE+0x01ffff, Pico_mcd->bios, 0); + if (pcd_base_address != 0) { // cartridge (for MSU/MD+) // MD+ on MEGASD plus mirror cpu68k_map_set(m68k_write8_map, 0x040000-(1<= 0 && cd_img_type != CT_UNKNOWN) { - // valid CD image, ask frontend for BIOS.. + // valid CD image, ask frontend for BIOS. rom_fname = NULL; if (get_bios_filename != NULL) rom_fname = get_bios_filename(&cd_region, filename); - if (rom_fname == NULL) { + rom_file = pm_open(rom_fname); + + // ask frontend if there's an MSU/MD+ rom + rom_fname = NULL; + if (get_msu_filename != NULL) + rom_fname = get_msu_filename(filename); + + // BIOS is required for CD games, but MSU/MD+ usually doesn't need it + if (rom_file == NULL && rom_fname == NULL) { + lprintf("opening BIOS failed\n"); media_type = PM_BAD_CD_NO_BIOS; goto out; } + ret = PicoCartLoad(rom_file, NULL, 0, &rom_data, &rom_size, 0); + if (ret != 0) { + lprintf("reading BIOS failed\n"); + media_type = PM_ERROR; + goto out; + } + + // copy BIOS and close file + PicoCreateMCD(rom_data, rom_size); + + PicoCartUnload(); + pm_close(rom_file); + rom_file = NULL; + rom_size = 0; + + // if there is an MSU ROM, it's name is now in rom_fname for loading PicoIn.AHW |= PAHW_MCD; } else { @@ -306,7 +333,7 @@ enum media_type_e PicoLoadMedia(const char *filename, PicoIn.AHW = PAHW_PICO; } - if (!rom) { + if (rom == NULL && rom_fname != NULL) { rom_file = pm_open(rom_fname); if (rom_file == NULL) { lprintf("Failed to open ROM\n"); @@ -315,33 +342,45 @@ enum media_type_e PicoLoadMedia(const char *filename, } } - ret = PicoCartLoad(rom_file, rom, romsize, &rom_data, &rom_size, (PicoIn.AHW & PAHW_SMS) ? 1 : 0); - if (ret != 0) { - if (ret == 2) lprintf("Out of memory\n"); - else if (ret == 3) lprintf("Read failed\n"); - else lprintf("PicoCartLoad() failed.\n"); - media_type = PM_ERROR; - goto out; - } - - // detect wrong files - if (strncmp((char *)rom_data, "Pico", 4) == 0) { - lprintf("savestate selected?\n"); - media_type = PM_BAD_DETECT; - goto out; - } + if (rom != NULL || rom_file != NULL) { + ret = PicoCartLoad(rom_file, rom, romsize, &rom_data, &rom_size, (PicoIn.AHW & PAHW_SMS) ? 1 : 0); + if (ret != 0) { + if (ret == 2) lprintf("Out of memory\n"); + else if (ret == 3) lprintf("Read failed\n"); + else lprintf("PicoCartLoad() failed.\n"); + media_type = PM_ERROR; + goto out; + } - if (!(PicoIn.AHW & PAHW_SMS)) { - unsigned short *d = (unsigned short *)(rom_data + 4); - if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) { - lprintf("bad reset vector\n"); + // detect wrong files + if (rom_strcmp(rom_data, rom_size, 0, "Pico") == 0) { + lprintf("savestate selected?\n"); media_type = PM_BAD_DETECT; goto out; } + + if (!(PicoIn.AHW & PAHW_SMS)) { + unsigned short *d = (unsigned short *)(rom_data + 4); + if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) { + lprintf("bad reset vector\n"); + media_type = PM_BAD_DETECT; + goto out; + } + } + + // maybe we are loading MegaCD BIOS? + if (!(PicoIn.AHW & PAHW_MCD) && rom_size <= 0x20000 && (!rom_strcmp(rom_data, rom_size, 0x124, "BOOT") || + !rom_strcmp(rom_data, rom_size, 0x128, "BOOT"))) { + PicoIn.AHW |= PAHW_MCD; + // copy to Pmcd as BIOS + PicoCreateMCD(rom_data, rom_size); + PicoCartUnload(); + rom_size = 0; + } } - // load config for this ROM (do this before insert to get correct region) if (!(PicoIn.AHW & PAHW_MCD)) { + // load config for this ROM (do this before insert to get correct region) memcpy(media_id_header, rom_data + 0x100, sizeof(media_id_header)); if (do_region_override != NULL) do_region_override(filename); @@ -386,7 +425,7 @@ enum media_type_e PicoLoadMedia(const char *filename, media_type = PM_BAD_CD; goto out; } - if (Pico.romsize <= 0x20000) + if (Pico.romsize == 0) Pico.m.ncart_in = 1; } diff --git a/pico/memory.c b/pico/memory.c index 3b5bdf87f..1d52a8586 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -952,8 +952,10 @@ PICO_INTERNAL void PicoMemSetup(void) mask = (1 << M68K_MEM_SHIFT) - 1; rs = (Pico.romsize + mask) & ~mask; if (rs > 0xa00000) rs = 0xa00000; // max cartridge area - cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0); - cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0); + if (rs) { + cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0); + } // Common case of on-cart (save) RAM, usually at 0x200000-... if ((Pico.sv.flags & SRF_ENABLED) && Pico.sv.data != NULL) { diff --git a/pico/pico.c b/pico/pico.c index 6d061c2ad..357ba8e04 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -49,9 +49,9 @@ void PicoInit(void) // to be called once on emu exit void PicoExit(void) { + PicoCartUnload(); if (PicoIn.AHW & PAHW_MCD) PicoExitMCD(); - PicoCartUnload(); z80_exit(); PsndExit(); @@ -161,9 +161,6 @@ PICO_INTERNAL void PicoDetectRegion(void) int PicoReset(void) { - if (Pico.romsize <= 0) - return 1; - #if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) PicoIn.opt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET; #endif diff --git a/pico/pico.h b/pico/pico.h index a48310f4f..32522c5cc 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -318,6 +318,7 @@ enum media_type_e PicoLoadMedia(const char *filename, const unsigned char *rom, unsigned int romsize, const char *carthw_cfg_fname, const char *(*get_bios_filename)(int *region, const char *cd_fname), + const char *(*get_msu_filename)(const char *cd_fname), void (*do_region_override)(const char *media_filename)); int PicoCdCheck(const char *fname_in, int *pregion); diff --git a/pico/pico_int.h b/pico/pico_int.h index 546e5ec35..a7da9123c 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -702,6 +702,7 @@ extern carthw_state_chunk *carthw_chunks; #define CHUNK_CARTHW 64 // cart.c +extern int rom_strcmp(void *rom, int size, int offset, const char *s1); extern int PicoCartResize(int newsize); extern void Byteswap(void *dst, const void *src, int len); extern void (*PicoCartMemSetup)(void); @@ -816,6 +817,7 @@ PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done); extern mcd_state *Pico_mcd; +PICO_INTERNAL void PicoCreateMCD(unsigned char *bios_data, int bios_size); PICO_INTERNAL void PicoInitMCD(void); PICO_INTERNAL void PicoExitMCD(void); PICO_INTERNAL void PicoPowerMCD(void); diff --git a/pico/sek.c b/pico/sek.c index 9bab033fe..348d85774 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -140,8 +140,6 @@ PICO_INTERNAL void SekInit(void) // Reset the 68000: PICO_INTERNAL int SekReset(void) { - if (Pico.rom==NULL) return 1; - #ifdef EMU_C68K CycloneReset(&PicoCpuCM68k); #endif diff --git a/pico/videoport.c b/pico/videoport.c index 9c35162d9..3004e1c61 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -554,8 +554,8 @@ static void DmaSlow(int len, u32 source) { u8 r3 = Pico_mcd->s68k_regs[3]; elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", r3); - if (source < Pico.romsize /*0x20000*/) { // Bios area - base = (u16 *)(Pico.rom + (source & 0xfe0000)); + if ((source & 0xfc0000) == pcd_base_address) { // Bios area + base = (u16 *)(Pico_mcd->bios + (source & 0xfe0000)); } else if ((source & 0xfc0000) == pcd_base_address+0x200000) { // Word Ram if (!(r3 & 4)) { // 2M mode base = (u16 *)(Pico_mcd->word_ram2M + (source & 0x20000)); @@ -572,7 +572,8 @@ static void DmaSlow(int len, u32 source) } else if ((source & 0xfe0000) == pcd_base_address+0x020000) { // Prg Ram base = (u16 *)Pico_mcd->prg_ram_b[r3 >> 6]; source -= 2; // XXX: test - } + } else // Rom + base = m68k_dma_source(source); } else { diff --git a/platform/common/emu.c b/platform/common/emu.c index 403c4c43b..8f7baed60 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -184,20 +184,6 @@ static const char *find_bios(int *region, const char *cd_fname) (*region == 8 ? "EU" : "JAP") : "USA"); } - // look for MSU.MD or MD+ rom file. XXX another extension list? ugh... - static const char *md_exts[] = { "gen", "smd", "md", "32x" }; - char *ext = strrchr(cd_fname, '.'); - int extpos = ext ? ext-cd_fname : strlen(cd_fname); - strcpy(static_buff, cd_fname); - static_buff[extpos++] = '.'; - for (i = 0; i < ARRAY_SIZE(md_exts); i++) { - strcpy(static_buff+extpos, md_exts[i]); - if (access(static_buff, R_OK) == 0) { - printf("found MSU rom: %s\n",static_buff); - return static_buff; - } - } - // locate BIOS file if (*region == 4) { // US files = biosfiles_us; @@ -247,6 +233,26 @@ static const char *find_bios(int *region, const char *cd_fname) } } +static const char *find_msu(const char *cd_fname) +{ + int i; + + // look for MSU.MD or MD+ rom file. XXX another extension list? ugh... + static const char *md_exts[] = { "gen", "smd", "md", "32x" }; + char *ext = strrchr(cd_fname, '.'); + int extpos = ext ? ext-cd_fname : strlen(cd_fname); + strcpy(static_buff, cd_fname); + static_buff[extpos++] = '.'; + for (i = 0; i < ARRAY_SIZE(md_exts); i++) { + strcpy(static_buff+extpos, md_exts[i]); + if (access(static_buff, R_OK) == 0) { + printf("found MSU rom: %s\n",static_buff); + return static_buff; + } + } + return NULL; +} + /* check if the name begins with BIOS name */ /* static int emu_isBios(const char *name) @@ -471,7 +477,7 @@ int emu_reload_rom(const char *rom_fname_in) emu_make_path(carthw_path, "carthw.cfg", sizeof(carthw_path)); media_type = PicoLoadMedia(rom_fname, NULL, 0, carthw_path, - find_bios, do_region_override); + find_bios, find_msu, do_region_override); switch (media_type) { case PM_BAD_DETECT: diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 97023a002..c66d95981 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1286,22 +1286,6 @@ static const char *find_bios(int *region, const char *cd_fname) int i, count; FILE *f = NULL; - // look for MSU.MD rom file. XXX another extension list? ugh... - static const char *md_exts[] = { "gen", "smd", "md", "32x" }; - char *ext = strrchr(cd_fname, '.'); - int extpos = ext ? ext-cd_fname : strlen(cd_fname); - strcpy(path, cd_fname); - path[extpos++] = '.'; - for (i = 0; i < ARRAY_SIZE(md_exts); i++) { - strcpy(path+extpos, md_exts[i]); - f = fopen(path, "rb"); - if (f != NULL) { - log_cb(RETRO_LOG_INFO, "found MSU rom: %s\n", path); - fclose(f); - return path; - } - } - if (*region == 4) { // US files = biosfiles_us; count = sizeof(biosfiles_us) / sizeof(char *); @@ -1338,6 +1322,29 @@ static const char *find_bios(int *region, const char *cd_fname) return NULL; } +static const char *find_msu(const char *cd_fname) +{ + static char path[256]; + FILE *f = NULL; + int i; + + // look for MSU.MD rom file. XXX another extension list? ugh... + static const char *md_exts[] = { "gen", "smd", "md", "32x" }; + char *ext = strrchr(cd_fname, '.'); + int extpos = ext ? ext-cd_fname : strlen(cd_fname); + strcpy(path, cd_fname); + path[extpos++] = '.'; + for (i = 0; i < ARRAY_SIZE(md_exts); i++) { + strcpy(path+extpos, md_exts[i]); + f = fopen(path, "rb"); + if (f != NULL) { + log_cb(RETRO_LOG_INFO, "found MSU rom: %s\n", path); + fclose(f); + return path; + } + } +} + static void set_memory_maps(void) { if (PicoIn.AHW & PAHW_MCD) @@ -1586,7 +1593,7 @@ bool retro_load_game(const struct retro_game_info *info) make_system_path(carthw_path, sizeof(carthw_path), "carthw", ".cfg"); media_type = PicoLoadMedia(content_path, content_data, content_size, - carthw_path, find_bios, NULL); + carthw_path, find_bios, find_msu, NULL); disk_current_index = cd_index;