\r
if (!is_sms)\r
{\r
- // maybe we are loading MegaCD BIOS?\r
- if (!(PicoIn.AHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom_data+0x124, "BOOT", 4) ||\r
- !strncmp((char *)rom_data+0x128, "BOOT", 4))) {\r
- PicoIn.AHW |= PAHW_MCD;\r
- }\r
-\r
// Check for SMD:\r
if (size >= 0x4200 && (size&0x3fff) == 0x200 &&\r
((rom_data[0x2280] == 'S' && rom_data[0x280] == 'E') || (rom_data[0x280] == 'S' && rom_data[0x2281] == 'E'))) {\r
return crc;\r
}\r
\r
-static int rom_strcmp(int rom_offset, const char *s1)\r
+int rom_strcmp(void *rom, int size, int offset, const char *s1)\r
{\r
int i, len = strlen(s1);\r
- const char *s_rom = (const char *)Pico.rom;\r
- if (rom_offset + len > Pico.romsize)\r
- return 0;\r
+ const char *s_rom = (const char *)rom;\r
+ if (offset + len > size)\r
+ return 1;\r
+\r
+ if (PicoIn.AHW & PAHW_SMS)\r
+ return strncmp(s_rom + offset, s1, strlen(s1));\r
+\r
for (i = 0; i < len; i++)\r
- if (s1[i] != s_rom[MEM_BE2(i + rom_offset)])\r
+ if (s1[i] != s_rom[MEM_BE2(i + offset)])\r
return 1;\r
return 0;\r
}\r
{\r
int offs;\r
offs = strtoul(p, &r, 0);\r
- if (offs < 0 || offs > Pico.romsize) {\r
+ if (offs < 0) {\r
elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs);\r
goto bad;\r
}\r
goto bad;\r
*r = 0;\r
\r
- if (rom_strcmp(offs, p) == 0)\r
+ if (rom_strcmp(Pico.rom, Pico.romsize, offs, p) == 0)\r
any_checks_passed = 1;\r
else\r
skip_sect = 1;\r
cdd.latency = 0;
/* reset track index */
- cdd.index = -1;
+ cdd.index = 0;
/* reset logical block address */
cdd.lba = 0;
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();
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)
#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
// 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);
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);
}
// enable CD drive
s68k_write8(0xff8037, 0x4);
+ s68k_write8(0xff8000, 0x2);
PicoResetHook = msd_reset;
}
d = Pico_mcd->s68k_regs[4]<<8;\r
goto end;\r
case 6:\r
- d = *(u16 *)(Pico.rom + 0x72);\r
+ d = *(u16 *)(Pico_mcd->bios + 0x72);\r
goto end;\r
case 8:\r
d = cdc_host_r(0);\r
remap_word_ram(d);\r
goto write_comm;\r
case 6:\r
- Pico.rom[MEM_BE2(0x72)] = d; // simple hint vector changer\r
+ Pico_mcd->bios[MEM_BE2(0x72)] = d; // simple hint vector changer\r
return;\r
case 7:\r
- Pico.rom[MEM_BE2(0x73)] = d;\r
+ Pico_mcd->bios[MEM_BE2(0x73)] = d;\r
elprintf(EL_CDREGS, "hint vector set to %04x%04x",\r
- ((u16 *)Pico.rom)[0x70/2], ((u16 *)Pico.rom)[0x72/2]);\r
+ ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]);\r
return;\r
case 8:\r
(void) cdc_host_r(0); // acts same as reading\r
}\r
#endif\r
\r
-// BIOS faking for MSU-MD, checks for "SEGA" at 0x400100 to detect CD drive\r
-static u8 bios_id[4] = "SEGA";\r
-\r
-static u32 PicoReadM68k8_bios(u32 a)\r
-{\r
- if ((a & 0xfffffc) == BASE+0x100) // CD detection by MSU\r
- return bios_id[a&3];\r
- return 0;\r
-}\r
-\r
-static u32 PicoReadM68k16_bios(u32 a)\r
-{\r
- if ((a & 0xfffffc) == BASE+0x100) // CD detection by MSU\r
- return (bios_id[a&2]<<8) | bios_id[(a&2)+1];\r
- return 0;\r
-}\r
-\r
// RAM cart (400000 - 7fffff, optional)\r
static u32 PicoReadM68k8_ramc(u32 a)\r
{\r
Pico_mcd->m.dmna_ret_2m &= 3;\r
\r
// restore hint vector\r
- *(u16 *)(Pico.rom + 0x72) = Pico_mcd->m.hint_vector;\r
+ *(u16 *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;\r
}\r
\r
#ifdef EMU_M68K\r
\r
PICO_INTERNAL void PicoMemSetupCD(void)\r
{\r
- if (!Pico_mcd) {\r
- Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0);\r
- memset(Pico_mcd, 0, sizeof(mcd_state));\r
- }\r
- pcd_base_address = (Pico.romsize != 0x20000 ? 0x400000 : 0x000000);\r
+ pcd_base_address = (Pico.romsize ? 0x400000 : 0x000000);\r
\r
// setup default main68k map\r
PicoMemSetup();\r
\r
// main68k map (BIOS or MSU mapped by PicoMemSetup()):\r
- if (pcd_base_address != 0) {\r
- // MSU cartridge. Fake BIOS detection\r
- cpu68k_map_set(m68k_read8_map, 0x400000, 0x41ffff, PicoReadM68k8_bios, 1);\r
- cpu68k_map_set(m68k_read16_map, 0x400000, 0x41ffff, PicoReadM68k16_bios, 1);\r
+ cpu68k_map_set(m68k_read8_map, BASE, BASE+0x01ffff, Pico_mcd->bios, 0);\r
+ cpu68k_map_set(m68k_read16_map, BASE, BASE+0x01ffff, Pico_mcd->bios, 0);\r
+ if (pcd_base_address != 0) { // cartridge (for MSU/MD+)\r
// MD+ on MEGASD plus mirror\r
cpu68k_map_set(m68k_write8_map, 0x040000-(1<<M68K_MEM_SHIFT), 0x03ffff, msd_write8, 1);\r
cpu68k_map_set(m68k_write16_map, 0x040000-(1<<M68K_MEM_SHIFT), 0x03ffff, msd_write16, 1);\r
cpu68k_map_set(m68k_write8_map, 0x0c0000-(1<<M68K_MEM_SHIFT), 0x0bffff, msd_write8, 1);\r
cpu68k_map_set(m68k_write16_map, 0x0c0000-(1<<M68K_MEM_SHIFT), 0x0bffff, msd_write16, 1);\r
msd_reset();\r
- } else {\r
+ } else { // no cartridge\r
// RAM cart\r
cpu68k_map_set(m68k_read8_map, 0x400000, 0x7fffff, PicoReadM68k8_ramc, 1);\r
cpu68k_map_set(m68k_read16_map, 0x400000, 0x7fffff, PicoReadM68k16_ramc, 1);\r
// Reset the 68000:
PICO_INTERNAL int SekResetS68k(void)
{
- if (Pico.rom==NULL) return 1;
-
#ifdef EMU_C68K
CycloneReset(&PicoCpuCS68k);
#endif
/*
* 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.
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;
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 {
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");
}
}
- 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);
media_type = PM_BAD_CD;
goto out;
}
- if (Pico.romsize <= 0x20000)
+ if (Pico.romsize == 0)
Pico.m.ncart_in = 1;
}
mask = (1 << M68K_MEM_SHIFT) - 1;\r
rs = (Pico.romsize + mask) & ~mask;\r
if (rs > 0xa00000) rs = 0xa00000; // max cartridge area\r
- cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0);\r
- cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);\r
+ if (rs) {\r
+ cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0);\r
+ cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);\r
+ }\r
\r
// Common case of on-cart (save) RAM, usually at 0x200000-...\r
if ((Pico.sv.flags & SRF_ENABLED) && Pico.sv.data != NULL) {\r
// to be called once on emu exit\r
void PicoExit(void)\r
{\r
+ PicoCartUnload();\r
if (PicoIn.AHW & PAHW_MCD)\r
PicoExitMCD();\r
- PicoCartUnload();\r
z80_exit();\r
PsndExit();\r
\r
\r
int PicoReset(void)\r
{\r
- if (Pico.romsize <= 0)\r
- return 1;\r
-\r
#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP)\r
PicoIn.opt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET;\r
#endif\r
const unsigned char *rom, unsigned int romsize,\r
const char *carthw_cfg_fname,\r
const char *(*get_bios_filename)(int *region, const char *cd_fname),\r
+ const char *(*get_msu_filename)(const char *cd_fname),\r
void (*do_region_override)(const char *media_filename));\r
int PicoCdCheck(const char *fname_in, int *pregion);\r
\r
#define CHUNK_CARTHW 64\r
\r
// cart.c\r
+extern int rom_strcmp(void *rom, int size, int offset, const char *s1);\r
extern int PicoCartResize(int newsize);\r
extern void Byteswap(void *dst, const void *src, int len);\r
extern void (*PicoCartMemSetup)(void);\r
\r
extern mcd_state *Pico_mcd;\r
\r
+PICO_INTERNAL void PicoCreateMCD(unsigned char *bios_data, int bios_size);\r
PICO_INTERNAL void PicoInitMCD(void);\r
PICO_INTERNAL void PicoExitMCD(void);\r
PICO_INTERNAL void PicoPowerMCD(void);\r
// Reset the 68000:\r
PICO_INTERNAL int SekReset(void)\r
{\r
- if (Pico.rom==NULL) return 1;\r
-\r
#ifdef EMU_C68K\r
CycloneReset(&PicoCpuCM68k);\r
#endif\r
{\r
u8 r3 = Pico_mcd->s68k_regs[3];\r
elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", r3);\r
- if (source < Pico.romsize /*0x20000*/) { // Bios area\r
- base = (u16 *)(Pico.rom + (source & 0xfe0000));\r
+ if ((source & 0xfc0000) == pcd_base_address) { // Bios area\r
+ base = (u16 *)(Pico_mcd->bios + (source & 0xfe0000));\r
} else if ((source & 0xfc0000) == pcd_base_address+0x200000) { // Word Ram\r
if (!(r3 & 4)) { // 2M mode\r
base = (u16 *)(Pico_mcd->word_ram2M + (source & 0x20000));\r
} else if ((source & 0xfe0000) == pcd_base_address+0x020000) { // Prg Ram\r
base = (u16 *)Pico_mcd->prg_ram_b[r3 >> 6];\r
source -= 2; // XXX: test\r
- }\r
+ } else // Rom\r
+ base = m68k_dma_source(source);\r
}\r
else\r
{\r
(*region == 8 ? "EU" : "JAP") : "USA");\r
}\r
\r
- // look for MSU.MD or MD+ rom file. XXX another extension list? ugh...\r
- static const char *md_exts[] = { "gen", "smd", "md", "32x" };\r
- char *ext = strrchr(cd_fname, '.');\r
- int extpos = ext ? ext-cd_fname : strlen(cd_fname);\r
- strcpy(static_buff, cd_fname);\r
- static_buff[extpos++] = '.';\r
- for (i = 0; i < ARRAY_SIZE(md_exts); i++) {\r
- strcpy(static_buff+extpos, md_exts[i]);\r
- if (access(static_buff, R_OK) == 0) {\r
- printf("found MSU rom: %s\n",static_buff);\r
- return static_buff;\r
- }\r
- }\r
-\r
// locate BIOS file\r
if (*region == 4) { // US\r
files = biosfiles_us;\r
}\r
}\r
\r
+static const char *find_msu(const char *cd_fname)\r
+{\r
+ int i;\r
+\r
+ // look for MSU.MD or MD+ rom file. XXX another extension list? ugh...\r
+ static const char *md_exts[] = { "gen", "smd", "md", "32x" };\r
+ char *ext = strrchr(cd_fname, '.');\r
+ int extpos = ext ? ext-cd_fname : strlen(cd_fname);\r
+ strcpy(static_buff, cd_fname);\r
+ static_buff[extpos++] = '.';\r
+ for (i = 0; i < ARRAY_SIZE(md_exts); i++) {\r
+ strcpy(static_buff+extpos, md_exts[i]);\r
+ if (access(static_buff, R_OK) == 0) {\r
+ printf("found MSU rom: %s\n",static_buff);\r
+ return static_buff;\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
/* check if the name begins with BIOS name */\r
/*\r
static int emu_isBios(const char *name)\r
emu_make_path(carthw_path, "carthw.cfg", sizeof(carthw_path));\r
\r
media_type = PicoLoadMedia(rom_fname, NULL, 0, carthw_path,\r
- find_bios, do_region_override);\r
+ find_bios, find_msu, do_region_override);\r
\r
switch (media_type) {\r
case PM_BAD_DETECT:\r
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 *);
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)
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;