[Core/MD] fixed Game Genie / (Pro) Action Replay lock-on support with ROM larger than 8MB

This commit is contained in:
ekeeke 2021-08-09 16:05:24 +02:00
parent e6ab7563e7
commit 298676294a
7 changed files with 126 additions and 151 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Genesis Plus
* Action Replay / Pro Action Replay emulation
* Action Replay / Pro Action Replay hardware support
*
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
@ -45,8 +45,7 @@ static struct
{
uint8 enabled;
uint8 status;
uint8 *rom;
uint8 *ram;
uint8 ram[0x10000];
uint16 regs[13];
uint16 old[4];
uint16 data[4];
@ -54,64 +53,52 @@ static struct
} action_replay;
static void ar_write_regs(uint32 address, uint32 data);
static void ar_write_regs_2(uint32 address, uint32 data);
static void ar2_write_reg(uint32 address, uint32 data);
static void ar_write_ram_8(uint32 address, uint32 data);
void areplay_init(void)
{
int size;
memset(&action_replay,0,sizeof(action_replay));
action_replay.enabled = action_replay.status = 0;
/* store Action replay ROM (max. 128KB) & RAM (64KB) above cartridge ROM (max. 8MB) */
if (cart.romsize > 0x800000) return;
action_replay.rom = cart.rom + 0x800000;
action_replay.ram = cart.rom + 0x820000;
/* try to load Action Replay ROM file */
size = load_archive(AR_ROM, action_replay.rom, 0x20000, NULL);
/* detect Action Replay board type */
switch (size)
/* try to load Action Replay ROM file (max. 64KB) */
if (load_archive(AR_ROM, cart.lockrom, 0x10000, NULL) > 0)
{
case 0x8000:
/* detect Action Replay board type */
if (!memcmp(cart.lockrom + 0x120, "ACTION REPLAY ", 16))
{
if (!memcmp(action_replay.rom + 0x120, "ACTION REPLAY ", 16))
{
/* normal Action Replay (32K) */
action_replay.enabled = TYPE_AR;
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
break;
}
}
/* normal Action Replay (32KB ROM) */
action_replay.enabled = TYPE_AR;
case 0x10000:
case 0x20000:
/* $0000-$7fff mirrored into $8000-$ffff */
memcpy(cart.lockrom + 0x8000, cart.lockrom, 0x8000);
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
}
else
{
/* Read stack pointer MSB */
uint8 sp = READ_BYTE(action_replay.rom, 0x01);
uint8 sp = cart.lockrom[0x01];
/* Detect board version */
if ((sp == 0x42) && !memcmp(action_replay.rom + 0x120, "ACTION REPLAY 2 ", 16))
if ((sp == 0x42) && !memcmp(cart.lockrom + 0x120, "ACTION REPLAY 2 ", 16))
{
/* PRO Action Replay 1 (64/128K) */
/* PRO Action Replay (2x32KB ROM) */
action_replay.enabled = TYPE_PRO1;
/* internal registers mapped at $010000-$01ffff */
m68k.memory_map[0x01].write16 = ar_write_regs;
}
else if ((sp == 0x60) && !memcmp(action_replay.rom + 0x3c6, "ACTION REPLAY II", 16))
else if ((sp == 0x60) && !memcmp(cart.lockrom + 0x3c6, "ACTION REPLAY II", 16))
{
/* PRO Action Replay 2 (64K) */
/* PRO Action Replay 2 (2x32KB ROM) */
action_replay.enabled = TYPE_PRO2;
/* internal registers mapped at $100000-$10ffff */
m68k.memory_map[0x10].write16 = ar_write_regs_2;
/* internal register mapped at $100000-$10ffff */
m68k.memory_map[0x10].write16 = ar2_write_reg;
}
/* internal RAM (64k), mapped at $420000-$42ffff or $600000-$60ffff */
/* internal RAM (64KB), mapped at $420000-$42ffff or $600000-$60ffff */
if (action_replay.enabled)
{
m68k.memory_map[sp].base = action_replay.ram;
@ -120,28 +107,22 @@ void areplay_init(void)
m68k.memory_map[sp].write8 = ar_write_ram_8;
m68k.memory_map[sp].write16 = NULL;
}
break;
}
default:
{
break;
}
}
#ifdef LSB_FIRST
if (action_replay.enabled)
{
int i;
for (i= 0; i<size; i+=2)
if (action_replay.enabled)
{
/* Byteswap ROM */
uint8 temp = action_replay.rom[i];
action_replay.rom[i] = action_replay.rom[i+1];
action_replay.rom[i+1] = temp;
int i;
for (i= 0; i<0x10000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.lockrom[i];
cart.lockrom[i] = cart.lockrom[i+1];
cart.lockrom[i+1] = temp;
}
}
}
#endif
}
}
void areplay_shutdown(void)
@ -166,7 +147,7 @@ void areplay_reset(int hard)
memset(action_replay.addr, 0, sizeof(action_replay.addr));
/* by default, internal ROM is mapped at $000000-$00FFFF */
m68k.memory_map[0].base = action_replay.rom;
m68k.memory_map[0].base = cart.lockrom;
/* reset internal RAM on power-on */
if (hard)
@ -287,7 +268,7 @@ static void ar_write_regs(uint32 address, uint32 data)
}
}
static void ar_write_regs_2(uint32 address, uint32 data)
static void ar2_write_reg(uint32 address, uint32 data)
{
/* enable Cartridge ROM */
if (((address & 0xff) == 0x78) && (data == 0xffff))
@ -301,4 +282,3 @@ static void ar_write_ram_8(uint32 address, uint32 data)
/* byte writes are handled as word writes, with LSB duplicated in MSB (/LWR is not used) */
*(uint16 *)(action_replay.ram + (address & 0xfffe)) = (data | (data << 8));
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Genesis Plus
* DATEL Action Replay / Pro Action Replay emulation
* Action Replay / Pro Action Replay hardware support
*
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Genesis Plus
* Game Genie Hardware emulation
* Game Genie hardware support
*
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*
@ -44,7 +44,6 @@
static struct
{
uint8 enabled;
uint8 *rom;
uint16 regs[0x20];
uint16 old[6];
uint16 data[6];
@ -58,29 +57,25 @@ static void ggenie_write_word(unsigned int address, unsigned int data);
static void ggenie_write_regs(unsigned int offset, unsigned int data);
void ggenie_init(void)
{
memset(&ggenie,0,sizeof(ggenie));
{
ggenie.enabled = 0;
/* Store Game Genie ROM (32KB) above cartridge ROM (max. 8MB) */
if (cart.romsize > 0x800000) return;
ggenie.rom = cart.rom + 0x800000;
/* Try to load Game Genie ROM file */
if (load_archive(GG_ROM, ggenie.rom, 0x8000, NULL) > 0)
/* Try to load Game Genie ROM file (32KB) */
if (load_archive(GG_ROM, cart.lockrom, 0x8000, NULL) > 0)
{
#ifdef LSB_FIRST
int i;
for (i=0; i<0x8000; i+=2)
{
/* Byteswap ROM */
uint8 temp = ggenie.rom[i];
ggenie.rom[i] = ggenie.rom[i+1];
ggenie.rom[i+1] = temp;
uint8 temp = cart.lockrom[i];
cart.lockrom[i] = cart.lockrom[i+1];
cart.lockrom[i+1] = temp;
}
#endif
/* $0000-$7fff mirrored into $8000-$ffff */
memcpy(ggenie.rom + 0x8000, ggenie.rom, 0x8000);
memcpy(cart.lockrom + 0x8000, cart.lockrom, 0x8000);
/* Game Genie hardware is enabled */
ggenie.enabled = 1;
@ -113,7 +108,7 @@ void ggenie_reset(int hard)
}
/* Game Genie ROM is mapped at $000000-$007fff */
m68k.memory_map[0].base = ggenie.rom;
m68k.memory_map[0].base = cart.lockrom;
/* Internal registers are mapped at $000000-$00001f */
m68k.memory_map[0].write8 = ggenie_write_byte;
@ -214,7 +209,7 @@ static void ggenie_write_regs(unsigned int offset, unsigned int data)
else
{
/* $0000-$7ffff reads mapped to Game Genie ROM */
m68k.memory_map[0].base = ggenie.rom;
m68k.memory_map[0].base = cart.lockrom;
m68k.memory_map[0].read8 = NULL;
m68k.memory_map[0].read16 = NULL;

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Genesis Plus
* Game Genie Hardware emulation
* Game Genie hardware support
*
* Copyright (C) 2009-2021 Eke-Eke (Genesis Plus GX)
*

View File

@ -453,79 +453,6 @@ void md_cart_init(void)
svp_init();
}
/**********************************************
LOCK-ON
***********************************************/
/* clear existing patches */
ggenie_shutdown();
areplay_shutdown();
/* initialize extra hardware */
switch (config.lock_on)
{
case TYPE_GG:
{
ggenie_init();
break;
}
case TYPE_AR:
{
areplay_init();
break;
}
case TYPE_SK:
{
/* store Sonic & Knuckles ROM files after cartridge ROM area */
if (cart.romsize > 0x400000) break;
/* try to load Sonic & Knuckles ROM file (2MB) */
if (load_archive(SK_ROM, cart.rom + 0x400000, 0x200000, NULL) == 0x200000)
{
/* check ROM header */
if (!memcmp(cart.rom + 0x400000 + 0x120, "SONIC & KNUCKLES",16))
{
/* try to load Sonic 2 & Knuckles upmem ROM file (256KB) */
if (load_archive(SK_UPMEM, cart.rom + 0x600000, 0x40000, NULL) == 0x40000)
{
/* $000000-$1FFFFF is mapped to S&K ROM */
for (i=0x00; i<0x20; i++)
{
m68k.memory_map[i].base = cart.rom + 0x400000 + (i << 16);
}
#ifdef LSB_FIRST
for (i=0; i<0x200000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x400000];
cart.rom[i + 0x400000] = cart.rom[i + 0x400000 + 1];
cart.rom[i + 0x400000 + 1] = temp;
}
for (i=0; i<0x40000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x600000];
cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1];
cart.rom[i + 0x600000 + 1] = temp;
}
#endif
cart.special |= HW_LOCK_ON;
}
}
}
break;
}
default:
{
break;
}
}
/**********************************************
CARTRIDGE EXTRA HARDWARE
***********************************************/
@ -760,6 +687,79 @@ void md_cart_init(void)
{
cart.hw.time_w = default_time_w;
}
/**********************************************
LOCK-ON
***********************************************/
/* clear existing patches */
ggenie_shutdown();
areplay_shutdown();
/* initialize extra hardware */
switch (config.lock_on)
{
case TYPE_GG:
{
ggenie_init();
break;
}
case TYPE_AR:
{
areplay_init();
break;
}
case TYPE_SK:
{
/* store Sonic & Knuckles ROM files after cartridge ROM area */
if (cart.romsize > 0x400000) break;
/* try to load Sonic & Knuckles ROM file (2MB) */
if (load_archive(SK_ROM, cart.rom + 0x400000, 0x200000, NULL) == 0x200000)
{
/* check ROM header */
if (!memcmp(cart.rom + 0x400000 + 0x120, "SONIC & KNUCKLES",16))
{
/* try to load Sonic 2 & Knuckles upmem ROM file (256KB) */
if (load_archive(SK_UPMEM, cart.rom + 0x600000, 0x40000, NULL) == 0x40000)
{
/* $000000-$1FFFFF is mapped to S&K ROM */
for (i=0x00; i<0x20; i++)
{
m68k.memory_map[i].base = cart.rom + 0x400000 + (i << 16);
}
#ifdef LSB_FIRST
for (i=0; i<0x200000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x400000];
cart.rom[i + 0x400000] = cart.rom[i + 0x400000 + 1];
cart.rom[i + 0x400000 + 1] = temp;
}
for (i=0; i<0x40000; i+=2)
{
/* Byteswap ROM */
uint8 temp = cart.rom[i + 0x600000];
cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1];
cart.rom[i + 0x600000 + 1] = temp;
}
#endif
cart.special |= HW_LOCK_ON;
}
}
}
break;
}
default:
{
break;
}
}
}
/* hardware that need to be reseted on power on */

View File

@ -81,10 +81,10 @@ typedef struct
uint32 mask; /* ROM mask */
uint8 special; /* custom external hardware (Lock-On, J-Cart, 3-D glasses, Terebi Oekaki,...) */
cart_hw_t hw; /* cartridge internal hardware */
uint8 rom[MAXROMSIZE]; /* ROM area */
uint8 lockrom[0x10000]; /* Game Genie / (Pro) Action Replay Lock-On ROM area (max 64KB) */
uint8 rom[MAXROMSIZE]; /* cartridge ROM area */
} md_cart_t;
/* Function prototypes */
extern void md_cart_init(void);
extern void md_cart_reset(int hard_reset);

View File

@ -41,7 +41,7 @@
typedef struct
{
uint8 reserved[0x80]; /* reserved for ROM cartridge infos (see md_cart.h) */
uint8 area[0x830000]; /* cartridge ROM/RAM area (max. 8MB ROM + Pro Action Replay 128KB ROM / 64KB RAM) */
uint8 area[0x810000]; /* cartridge ROM/RAM area (max. 8MB ROM + Pro Action Replay 64KB ROM) */
uint8 boot; /* cartridge boot mode (0x00: boot from CD with ROM/RAM cartridge enabled, 0x40: boot from ROM cartridge with CD enabled) */
uint8 id; /* RAM cartridge ID (related to RAM size, 0 if disabled) */
uint8 prot; /* RAM cartridge write protection */