Skip to content

Commit

Permalink
core, mode 1 support
Browse files Browse the repository at this point in the history
  • Loading branch information
irixxxx committed Sep 26, 2024
1 parent d600fee commit 549dd40
Show file tree
Hide file tree
Showing 15 changed files with 161 additions and 119 deletions.
24 changes: 11 additions & 13 deletions pico/cart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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'))) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion pico/cd/cdd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 15 additions & 2 deletions pico/cd/mcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions pico/cd/megasd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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);

Expand All @@ -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);
}
Expand Down Expand Up @@ -213,6 +214,7 @@ static void msd_init(void)

// enable CD drive
s68k_write8(0xff8037, 0x4);
s68k_write8(0xff8000, 0x2);

PicoResetHook = msd_reset;
}
Expand Down
42 changes: 10 additions & 32 deletions pico/cd/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
2 changes: 0 additions & 2 deletions pico/cd/sek.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
87 changes: 63 additions & 24 deletions pico/media.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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");
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions pico/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 549dd40

Please sign in to comment.