mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-04 18:05:06 +01:00
fixed Action Replay & Game Genie emulation
This commit is contained in:
parent
5078244cd1
commit
61e4873c07
@ -175,7 +175,8 @@ void cart_hw_init()
|
||||
|
||||
/* calculate nearest size with factor of 2 */
|
||||
int size = 0x10000;
|
||||
while (cart.romsize > size) size <<= 1;
|
||||
while (cart.romsize > size)
|
||||
size <<= 1;
|
||||
|
||||
/* total ROM size is not a factor of 2 */
|
||||
/* TODO: handle more possible ROM configurations (using cartridge database ???) */
|
||||
@ -408,6 +409,12 @@ void cart_hw_init()
|
||||
/**********************************************
|
||||
LOCK-ON
|
||||
***********************************************/
|
||||
|
||||
/* clear all existing patches */
|
||||
ggenie_shutdown();
|
||||
datel_shutdown();
|
||||
|
||||
/* initialize extra hardware */
|
||||
cart.lock_on = 0;
|
||||
switch (config.lock_on)
|
||||
{
|
||||
@ -426,15 +433,25 @@ void cart_hw_init()
|
||||
/* load Sonic & Knuckles ROM (2 MBytes) */
|
||||
FILE *f = fopen(SK_ROM,"r+b");
|
||||
if (!f) break;
|
||||
fread(cart.rom+0x700000,1,0x200000,f);
|
||||
int done = 0;
|
||||
while (done < 0x200000)
|
||||
{
|
||||
fread(cart.rom+0x700000+done,4096,1,f);
|
||||
done += 4096;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
/* load Sonic 2 UPMEM ROM (256 KBytes) */
|
||||
f = fopen(SK_UPMEM,"r+b");
|
||||
if (!f) break;
|
||||
fread(cart.rom+0x900000,1,0x40000,f);
|
||||
done = 0;
|
||||
while (done < 0x40000)
|
||||
{
|
||||
fread(cart.rom+0x900000+done,4096,1,f);
|
||||
done += 4096;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
/* Byteswap ROM */
|
||||
int i;
|
||||
@ -575,7 +592,7 @@ void cart_hw_reset()
|
||||
case TYPE_SK:
|
||||
if (cart.lock_on)
|
||||
{
|
||||
/* reset memory map */
|
||||
/* disable UPMEM chip at $300000-$3fffff */
|
||||
for (i=0x30; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define TYPE_PRO1 0x12
|
||||
#define TYPE_PRO2 0x22
|
||||
|
||||
static struct
|
||||
struct
|
||||
{
|
||||
uint8 enabled;
|
||||
uint8 rom[0x20000];
|
||||
@ -44,37 +44,43 @@ void datel_init(void)
|
||||
{
|
||||
memset(&action_replay,0,sizeof(action_replay));
|
||||
|
||||
/* load Action Replay ROM program */
|
||||
/* Open Action Replay ROM */
|
||||
FILE *f = fopen(AR_ROM,"rb");
|
||||
if (!f) return;
|
||||
int size = fread(action_replay.rom,1,0x20000,f);
|
||||
fclose(f);
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
/* detect Action Replay yype */
|
||||
if (size < 0x10000)
|
||||
action_replay.enabled = TYPE_AR;
|
||||
else if (size < 0x20000)
|
||||
action_replay.enabled = TYPE_PRO2;
|
||||
else
|
||||
action_replay.enabled = TYPE_PRO1;
|
||||
/* ROM size */
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
|
||||
/* default memory map */
|
||||
switch (action_replay.enabled)
|
||||
/* Detect Action Replay type */
|
||||
switch (size)
|
||||
{
|
||||
case TYPE_AR:
|
||||
case 0x8000: /* ACTION REPLAY (32K) */
|
||||
{
|
||||
/* internal registers mapped at $010000-$01ffff */
|
||||
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||
action_replay.enabled = TYPE_AR;
|
||||
|
||||
/* $0000-$7fff mirrored into $8000-$ffff */
|
||||
memcpy(action_replay.rom+0x8000,action_replay.rom,0x8000);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_PRO1:
|
||||
case 0x10000: /* PRO ACTION REPLAY 2 (64K) */
|
||||
{
|
||||
/* internal registers mapped at $010000-$01ffff */
|
||||
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||
action_replay.enabled = TYPE_PRO2;
|
||||
|
||||
/* RAM (64k) mapped at $600000-$60ffff */
|
||||
m68k_memory_map[0x60].base = action_replay.ram;
|
||||
m68k_memory_map[0x60].read8 = NULL;
|
||||
m68k_memory_map[0x60].read16 = NULL;
|
||||
m68k_memory_map[0x60].write8 = NULL;
|
||||
m68k_memory_map[0x60].write16 = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20000: /* PRO ACTION REPLAY (128K) */
|
||||
{
|
||||
action_replay.enabled = TYPE_PRO1;
|
||||
|
||||
/* RAM (64k) mapped at $420000-$42ffff */
|
||||
m68k_memory_map[0x42].base = action_replay.ram;
|
||||
@ -85,114 +91,132 @@ void datel_init(void)
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_PRO2:
|
||||
{
|
||||
/* internal registers mapped at $100000-$10ffff */
|
||||
m68k_memory_map[0x10].write16 = ar_write_regs_pro2;
|
||||
|
||||
/* RAM (64k) mapped at $600000-$60ffff */
|
||||
m68k_memory_map[0x60].base = action_replay.ram;
|
||||
m68k_memory_map[0x60].read8 = NULL;
|
||||
m68k_memory_map[0x60].read16 = NULL;
|
||||
m68k_memory_map[0x60].write8 = NULL;
|
||||
m68k_memory_map[0x60].write16 = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (action_replay.enabled)
|
||||
{
|
||||
/* Load ROM */
|
||||
fseek(f, 0, SEEK_SET);
|
||||
int i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
fread(action_replay.rom+i,0x1000,1,f);
|
||||
i += 0x1000;
|
||||
}
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
/* Byteswap ROM */
|
||||
int i;
|
||||
uint8 temp;
|
||||
for(i = 0; i < 0x20000; i += 2)
|
||||
{
|
||||
temp = action_replay.rom[i];
|
||||
action_replay.rom[i] = action_replay.rom[i+1];
|
||||
action_replay.rom[i+1] = temp;
|
||||
}
|
||||
/* Byteswap ROM */
|
||||
uint8 temp;
|
||||
for(i = 0; i < size; i += 2)
|
||||
{
|
||||
temp = action_replay.rom[i];
|
||||
action_replay.rom[i] = action_replay.rom[i+1];
|
||||
action_replay.rom[i+1] = temp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void datel_shutdown(void)
|
||||
{
|
||||
if (action_replay.enabled)
|
||||
{
|
||||
datel_switch(0);
|
||||
action_replay.enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void datel_reset(int hard_reset)
|
||||
{
|
||||
if (action_replay.enabled)
|
||||
/* reset external mapping */
|
||||
switch (action_replay.enabled)
|
||||
{
|
||||
if (hard_reset)
|
||||
{
|
||||
/* clear RAM */
|
||||
memset(action_replay.ram,0,sizeof(action_replay.ram));
|
||||
}
|
||||
case TYPE_AR:
|
||||
|
||||
/* reset codes */
|
||||
datel_switch(0);
|
||||
/* internal registers mapped at $010000-$01ffff */
|
||||
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||
|
||||
/* reset internal state */
|
||||
memset(action_replay.regs,0,sizeof(action_replay.regs));
|
||||
memset(action_replay.old,0,sizeof(action_replay.old));
|
||||
memset(action_replay.data,0,sizeof(action_replay.data));
|
||||
memset(action_replay.addr,0,sizeof(action_replay.addr));
|
||||
/* internal ROM mapped at $000000-$00ffff */
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
break;
|
||||
|
||||
/* ROM mapped at $000000-$3fffff */
|
||||
switch (action_replay.enabled)
|
||||
{
|
||||
case TYPE_AR: /* 32k ROM */
|
||||
case TYPE_PRO2: /* 64k ROM */
|
||||
{
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
break;
|
||||
}
|
||||
case TYPE_PRO2:
|
||||
|
||||
case TYPE_PRO1: /* 128k ROM */
|
||||
{
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
m68k_memory_map[1].base = action_replay.rom + 0x10000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* internal registers mapped at $100000-$10ffff */
|
||||
m68k_memory_map[0x10].write16 = ar_write_regs_pro2;
|
||||
|
||||
/* internal ROM mapped at $000000-$00ffff */
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
break;
|
||||
|
||||
case TYPE_PRO1:
|
||||
|
||||
/* internal registers mapped at $010000-$01ffff */
|
||||
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||
|
||||
/* internal ROM mapped at $000000-$01ffff */
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
m68k_memory_map[1].base = action_replay.rom + 0x10000;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear existing codes */
|
||||
datel_switch(0);
|
||||
|
||||
/* reset internal state */
|
||||
memset(action_replay.regs,0,sizeof(action_replay.regs));
|
||||
memset(action_replay.old,0,sizeof(action_replay.old));
|
||||
memset(action_replay.data,0,sizeof(action_replay.data));
|
||||
memset(action_replay.addr,0,sizeof(action_replay.addr));
|
||||
|
||||
/* clear RAM on hard reset only */
|
||||
if (hard_reset)
|
||||
memset(action_replay.ram,0,sizeof(action_replay.ram));
|
||||
}
|
||||
|
||||
void datel_switch(int enable)
|
||||
{
|
||||
int i;
|
||||
int i,use_wram = 0;
|
||||
if (enable)
|
||||
{
|
||||
int offset;
|
||||
|
||||
/* store old values */
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (action_replay.data[i])
|
||||
{
|
||||
offset = action_replay.addr[i] >> 16;
|
||||
|
||||
if (offset < 0x40) /* cartridge ROM */
|
||||
action_replay.old[i] = *(uint16 *)(cart.rom + action_replay.addr[i]);
|
||||
else if (offset >= 0xe0) /* Work RAM */
|
||||
action_replay.old[i] = *(uint16 *)(work_ram + (action_replay.addr[i]&0xffff));
|
||||
/* store old values & patch new values */
|
||||
if (action_replay.addr[i] < 0x400000)
|
||||
{
|
||||
action_replay.old[i] = *(uint16 *)(cart.rom + (action_replay.addr[i]&~1));
|
||||
*(uint16 *)(cart.rom + (action_replay.addr[i]&~1)) = action_replay.data[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
use_wram = 1;
|
||||
action_replay.old[i] = *(uint16 *)(work_ram + (action_replay.addr[i]&0xfffe));
|
||||
if (action_replay.data[i] & 0xff00)
|
||||
*(uint16 *)(work_ram + (action_replay.addr[i]&0xfffe)) = action_replay.data[i];
|
||||
else
|
||||
WRITE_BYTE(work_ram, (action_replay.addr[i]&0xfffe) + 1, action_replay.data[i] & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* patch new values */
|
||||
for (i=0; i<4; i++)
|
||||
if (use_wram)
|
||||
{
|
||||
if (action_replay.data[i])
|
||||
/* use specific WRAM write handlers */
|
||||
for (i=0xe0; i<0x100; i++)
|
||||
{
|
||||
offset = action_replay.addr[i] >> 16;
|
||||
|
||||
if (offset < 0x40) /* cartridge ROM */
|
||||
*(uint16 *)(cart.rom + action_replay.addr[i]) = action_replay.data[i];
|
||||
else if (offset >= 0xe0) /* Work RAM */
|
||||
*(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.data[i];
|
||||
m68k_memory_map[i].write8 = wram_write_byte;
|
||||
m68k_memory_map[i].write16 = wram_write_word;
|
||||
}
|
||||
}
|
||||
|
||||
/* set RAM write handlers */
|
||||
for (i=0xe0; i<0x100; i++)
|
||||
{
|
||||
m68k_memory_map[i].write8 = wram_write_byte;
|
||||
m68k_memory_map[i].write16 = wram_write_word;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -203,12 +227,12 @@ void datel_switch(int enable)
|
||||
{
|
||||
if (action_replay.addr[i] < 0x400000)
|
||||
*(uint16 *)(cart.rom + action_replay.addr[i]) = action_replay.old[i];
|
||||
else if (action_replay.addr[i] >= 0xe00000)
|
||||
*(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.old[i];
|
||||
else
|
||||
*(uint16 *)(work_ram + (action_replay.addr[i]&0xfffe)) = action_replay.old[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* set default Work RAM write handlers */
|
||||
/* default WRAM write handlers */
|
||||
for (i=0xe0; i<0x100; i++)
|
||||
{
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
@ -223,13 +247,16 @@ static void wram_write_byte(uint32 address, uint32 data)
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & 0xe0fffe) == (action_replay.addr[i]&0xe0fffe))
|
||||
if (action_replay.data[i])
|
||||
{
|
||||
if (address & 1) /* lower byte write */
|
||||
action_replay.old[i] = (action_replay.old[i] & 0xff00) | (data & 0xff);
|
||||
else /* upper byte write */
|
||||
action_replay.old[i] = (action_replay.old[i] & 0x00ff) | (data << 8);
|
||||
return;
|
||||
if ((address & 0xfffe) == (action_replay.addr[i] & 0xfffe))
|
||||
{
|
||||
WRITE_BYTE(&action_replay.old[i], address & 1, data);
|
||||
if (action_replay.data[i] & 0xff00)
|
||||
return;
|
||||
if ((address & 0xffff) == ((action_replay.addr[i]&0xfffe) + 1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,35 +265,40 @@ static void wram_write_byte(uint32 address, uint32 data)
|
||||
|
||||
static void wram_write_word(uint32 address, uint32 data)
|
||||
{
|
||||
*(uint16 *)(work_ram + (address & 0xffff)) = data;
|
||||
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & 0xe0fffe) == (action_replay.addr[i]&0xe0fffe))
|
||||
if (action_replay.data[i])
|
||||
{
|
||||
action_replay.old[i] = data;
|
||||
return;
|
||||
if ((address & 0xffff) == (action_replay.addr[i] & 0xfffe))
|
||||
{
|
||||
action_replay.old[i] = data;
|
||||
if (action_replay.data[i] & 0xff00)
|
||||
*(uint16 *)(work_ram + (address & 0xfffe)) = action_replay.data[i];
|
||||
else
|
||||
WRITE_BYTE(work_ram, (action_replay.addr[i] & 0xfffe) + 1, action_replay.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*(uint16 *)(work_ram + (address & 0xffff)) = data;
|
||||
}
|
||||
|
||||
static void ar_write_regs(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address > 0x10018) || (action_replay.regs[3] == 0xffff))
|
||||
/* register offset */
|
||||
int offset = (address & 0xffff) >> 1;
|
||||
if (offset > 12)
|
||||
{
|
||||
m68k_unused_16_w(address,data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* register offset */
|
||||
int offset = (address >> 1) & 0x0F;
|
||||
|
||||
/* update internal register */
|
||||
action_replay.regs[offset] = data;
|
||||
|
||||
/* decode patch value & address on exit */
|
||||
if ((offset == 3) && (data == 0xffff))
|
||||
/* exit program */
|
||||
if (action_replay.regs[3] == 0xffff)
|
||||
{
|
||||
/* decode patch data */
|
||||
action_replay.data[0] = action_replay.regs[0];
|
||||
@ -280,17 +312,21 @@ static void ar_write_regs(uint32 address, uint32 data)
|
||||
action_replay.addr[2] = (action_replay.regs[8] | ((action_replay.regs[9] & 0x7f00) << 8)) << 1;
|
||||
action_replay.addr[3] = (action_replay.regs[11] | ((action_replay.regs[12] & 0x7f00) << 8)) << 1;
|
||||
|
||||
/* Enable Cartridge ROM */
|
||||
/* NOTE: codes should be disabled on startup */
|
||||
/* enable Cartridge ROM */
|
||||
m68k_memory_map[0].base = cart.rom;
|
||||
m68k_memory_map[1].base = cart.rom + ((1<<16) & cart.mask);
|
||||
|
||||
/* disable internal registers (?) */
|
||||
m68k_memory_map[0x01].write16 = m68k_unused_16_w;
|
||||
|
||||
/* enable patches */
|
||||
datel_switch(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ar_write_regs_pro2(uint32 address, uint32 data)
|
||||
{
|
||||
/* Enable Cartridge ROM */
|
||||
/* enable Cartridge ROM */
|
||||
if (((address & 0xff) == 0x78) && (data == 0xffff))
|
||||
m68k_memory_map[0].base = cart.rom;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define _DATEL_H_
|
||||
|
||||
extern void datel_init(void);
|
||||
extern void datel_shutdown(void);
|
||||
extern void datel_reset(int hard_reset);
|
||||
extern void datel_switch(int enable);
|
||||
|
||||
|
@ -43,20 +43,24 @@ void ggenie_init(void)
|
||||
{
|
||||
memset(&ggenie,0,sizeof(ggenie));
|
||||
|
||||
/* load Game Genie ROM program */
|
||||
/* Open Game Genie ROM */
|
||||
FILE *f = fopen(GG_ROM,"rb");
|
||||
if (!f) return;
|
||||
fread(ggenie.rom,1,0x8000,f);
|
||||
fclose(f);
|
||||
|
||||
/* $0000-$7fff mirrored into $8000-$ffff */
|
||||
memcpy(ggenie.rom+0x8000,ggenie.rom,0x8000);
|
||||
/* Load ROM */
|
||||
int i = 0;
|
||||
while (i < 0x8000)
|
||||
{
|
||||
fread(ggenie.rom+i,0x1000,1,f);
|
||||
i += 0x1000;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
/* Byteswap ROM */
|
||||
int i;
|
||||
uint8 temp;
|
||||
for(i = 0; i < 0x10000; i += 2)
|
||||
for(i = 0; i < 0x8000; i += 2)
|
||||
{
|
||||
temp = ggenie.rom[i];
|
||||
ggenie.rom[i] = ggenie.rom[i+1];
|
||||
@ -64,36 +68,48 @@ void ggenie_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* enable registers write */
|
||||
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||
/* $0000-$7fff mirrored into $8000-$ffff */
|
||||
memcpy(ggenie.rom+0x8000,ggenie.rom,0x8000);
|
||||
|
||||
/* set flag */
|
||||
ggenie.enabled = 1;
|
||||
}
|
||||
|
||||
void ggenie_reset(void)
|
||||
void ggenie_shutdown(void)
|
||||
{
|
||||
if (ggenie.enabled)
|
||||
{
|
||||
/* reset codes */
|
||||
ggenie_switch(0);
|
||||
|
||||
/* reset internal state */
|
||||
memset(ggenie.regs,0,sizeof(ggenie.regs));
|
||||
memset(ggenie.old,0,sizeof(ggenie.old));
|
||||
memset(ggenie.data,0,sizeof(ggenie.data));
|
||||
memset(ggenie.addr,0,sizeof(ggenie.addr));
|
||||
|
||||
/* slot 0 is mapped to Game Genie ROM */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
|
||||
/* Internal registers are write only */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
ggenie.enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ggenie_switch(uint8 enable)
|
||||
void ggenie_reset(void)
|
||||
{
|
||||
if (!ggenie.enabled)
|
||||
return;
|
||||
|
||||
/* clear codes */
|
||||
ggenie_switch(0);
|
||||
|
||||
/* reset internal state */
|
||||
memset(ggenie.regs,0,sizeof(ggenie.regs));
|
||||
memset(ggenie.old,0,sizeof(ggenie.old));
|
||||
memset(ggenie.data,0,sizeof(ggenie.data));
|
||||
memset(ggenie.addr,0,sizeof(ggenie.addr));
|
||||
|
||||
/* Game Genie ROM is mapped at $000000-$007fff */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
|
||||
/* Internal registers are mapped at $000000-$00001f */
|
||||
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||
|
||||
/* Disable registers reads */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
}
|
||||
|
||||
void ggenie_switch(int enable)
|
||||
{
|
||||
int i,j;
|
||||
if (enable)
|
||||
@ -137,18 +153,10 @@ void ggenie_switch(uint8 enable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Byte write handler */
|
||||
/* Note: 2nd revision of the Game Genie software use byte writes to set register values on exit */
|
||||
static void ggenie_write_byte(uint32 address, uint32 data)
|
||||
{
|
||||
/* Lock bit */
|
||||
if (ggenie.regs[0] & 0x100)
|
||||
{
|
||||
m68k_unused_8_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Register offset */
|
||||
uint8 offset = (address >> 1) & 0x1f;
|
||||
|
||||
@ -159,13 +167,6 @@ static void ggenie_write_byte(uint32 address, uint32 data)
|
||||
/* Word write handler */
|
||||
static void ggenie_write_word(uint32 address, uint32 data)
|
||||
{
|
||||
/* Lock bit */
|
||||
if (ggenie.regs[0] & 0x100)
|
||||
{
|
||||
m68k_unused_8_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Register offset */
|
||||
uint8 offset = (address >> 1) & 0x1f;
|
||||
|
||||
@ -194,7 +195,7 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
ggenie.regs[offset] = data;
|
||||
|
||||
/* Mode Register */
|
||||
if (!offset)
|
||||
if (offset == 0)
|
||||
{
|
||||
/* by default, registers are write only */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
@ -204,11 +205,13 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
{
|
||||
/* $0000-$7ffff reads mapped to Cartridge ROM */
|
||||
m68k_memory_map[0].base = cart.rom;
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $0000-$7ffff reads mapped to Game Genie ROM */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
|
||||
if (data & 0x200)
|
||||
{
|
||||
@ -222,7 +225,7 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
if (data & 0x100)
|
||||
{
|
||||
/* decode patch address (ROM area only)*/
|
||||
/* note: Charles's documment is wrong, first register holds bits 23-16 of patch address */
|
||||
/* note: Charles's doc is wrong, first register holds bits 23-16 of patch address */
|
||||
ggenie.addr[0] = ((ggenie.regs[2] & 0x3f) << 16) | ggenie.regs[3];
|
||||
ggenie.addr[1] = ((ggenie.regs[5] & 0x3f) << 16) | ggenie.regs[6];
|
||||
ggenie.addr[2] = ((ggenie.regs[8] & 0x3f) << 16) | ggenie.regs[9];
|
||||
@ -238,17 +241,26 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
ggenie.data[4] = ggenie.regs[16];
|
||||
ggenie.data[5] = ggenie.regs[19];
|
||||
|
||||
/* disable internal registers */
|
||||
m68k_memory_map[0].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[0].write16 = m68k_unused_16_w;
|
||||
|
||||
/* patch ROM when GG program exits (LOCK bit set) */
|
||||
/* this is done here to handle patched program reads faster & more easily */
|
||||
/* on real HW, address decoding would be done on each reads */
|
||||
ggenie_switch(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* RESET register */
|
||||
else if (offset == 1)
|
||||
{
|
||||
ggenie.regs[1] |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 ggenie_read_regs(uint32 address)
|
||||
{
|
||||
if (address < 0x40) return ggenie.regs[address >> 1];
|
||||
else return *(uint16 *)(cart.rom + address); /* is that correct ? */
|
||||
return ggenie.regs[(address >> 1) & 0x1f];
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,8 @@
|
||||
|
||||
/* Function prototypes */
|
||||
extern void ggenie_init(void);
|
||||
extern void ggenie_shutdown(void);
|
||||
extern void ggenie_reset(void);
|
||||
extern void ggenie_switch(uint8 enable);
|
||||
extern void ggenie_switch(int enable);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user