From: kub <derkub@gmail.com>
Date: Thu, 26 Sep 2024 21:21:28 +0000 (+0200)
Subject: core, mode 1 support
X-Git-Tag: v2.04~120
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=549dd4070217bf20759d3dbe068c6c855341f5f8;p=picodrive.git

core, mode 1 support
---

diff --git a/pico/cart.c b/pico/cart.c
index ce067921..2a5d12e3 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 9079f74d..6841b947 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 368181be..178bac3d 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 53f3aa53..b53f8d32 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 f6d64e5a..7699df29 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<<M68K_MEM_SHIFT), 0x03ffff, msd_write8, 1);
     cpu68k_map_set(m68k_write16_map, 0x040000-(1<<M68K_MEM_SHIFT), 0x03ffff, msd_write16, 1);
     cpu68k_map_set(m68k_write8_map,  0x0c0000-(1<<M68K_MEM_SHIFT), 0x0bffff, msd_write8, 1);
     cpu68k_map_set(m68k_write16_map, 0x0c0000-(1<<M68K_MEM_SHIFT), 0x0bffff, msd_write16, 1);
     msd_reset();
-  } else {
+  } else { // no cartridge
     // RAM cart
     cpu68k_map_set(m68k_read8_map,   0x400000, 0x7fffff, PicoReadM68k8_ramc, 1);
     cpu68k_map_set(m68k_read16_map,  0x400000, 0x7fffff, PicoReadM68k16_ramc, 1);
diff --git a/pico/cd/sek.c b/pico/cd/sek.c
index 9bb72829..a0a0f432 100644
--- a/pico/cd/sek.c
+++ b/pico/cd/sek.c
@@ -129,8 +129,6 @@ PICO_INTERNAL void SekInitS68k(void)
 // Reset the 68000:
 PICO_INTERNAL int SekResetS68k(void)
 {
-  if (Pico.rom==NULL) return 1;
-
 #ifdef EMU_C68K
   CycloneReset(&PicoCpuCS68k);
 #endif
diff --git a/pico/media.c b/pico/media.c
index 51e3fbd8..c02cea1f 100644
--- a/pico/media.c
+++ b/pico/media.c
@@ -1,6 +1,7 @@
 /*
  * PicoDrive
  * (C) notaz, 2006-2010,2013
+ * (C) irixxxx, 2024
  *
  * This work is licensed under the terms of MAME license.
  * See COPYING file in the top-level directory.
@@ -256,6 +257,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))
 {
   const char *rom_fname = filename;
@@ -283,15 +285,40 @@ enum media_type_e PicoLoadMedia(const char *filename,
     cd_img_type = PicoCdCheck(filename, &cd_region);
     if ((int)cd_img_type >= 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 3b5bdf87..1d52a858 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 6d061c2a..357ba8e0 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 a48310f4..32522c5c 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 546e5ec3..a7da9123 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 9bab033f..348d8577 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 9c35162d..3004e1c6 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 403c4c43..8f7baed6 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 97023a00..c66d9598 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;