Genesis-Plus-GX/ genplus-gx/source/membnk.c

297 lines
5.6 KiB
C
Raw Normal View History

2007-08-09 22:13:54 +02:00
/*
membnk.c --
Memory handlers Z80 access to the banked V-bus address space.
*/
#include "shared.h"
void z80_write_banked_memory(unsigned int address, unsigned int data)
{
switch ((address >> 21) & 7)
{
case 0: /* Cartridge ROM */
case 1:
z80bank_unused_w (address, data);
return;
case 2: /* Unused */
case 3:
z80bank_unused_w (address, data);
return;
case 4: /* Unused (lockup) */
z80bank_lockup_w (address, data);
return;
case 5: /* Z80, I/O chip, etc. */
if (address <= 0xA0FFFF)
{
z80bank_lockup_w (address, data);
return;
}
else
{
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
if(address <= 0xA1001F) io_write((address >> 1) & 0x0F, data);
else z80bank_unused_w (address, data);
return;
case 0x11: /* /BUSREQ */
if (address & 1) z80bank_unused_w (address, data);
else gen_busreq_w (data & 1);
return;
case 0x12: /* /RESET (w) */
if (address & 1) z80bank_unused_w (address, data);
else gen_reset_w (data & 1);
return;
case 0x10: /* MEMORY MODE */
case 0x13: /* TIME */
case 0x20: /* ? */
case 0x30: /* ? */
z80bank_unused_w (address, data);
return;
default: /* Invalid */
z80bank_lockup_w (address, data);
return;
}
}
return;
case 6: /* VDP */
z80bank_vdp_w (address, data);
return;
case 7: /* Work RAM */
WRITE_BYTE(work_ram, address & 0xFFFF, data);
return;
}
}
int z80_read_banked_memory(unsigned int address)
{
switch ((address >> 21) & 7)
{
case 0: /* Cartridge ROM */
case 1:
return READ_BYTE(cart_rom, address);
case 2: /* Unused */
case 3:
return z80bank_unused_r (address);
case 4: /* Unused (lockup) */
return z80bank_lockup_r (address);
case 5: /* Z80, I/O chip, etc. */
if (address <= 0xA0FFFF) return z80bank_lockup_r (address);
else
{
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
if (address <= 0xA1001F) return io_read((address >> 1) & 0x0F);
else return z80bank_unused_r (address);
break;
case 0x11: /* /BUSACK from Z80 */
/* The Z80 can't read this bit (it would be halted
when the bit was zero) so we always return '1'. */
return 0xFF;
case 0x10: /* Unused */
case 0x12: /* Unused */
case 0x13: /* /TIME region */
case 0x20: /* Unused */
case 0x30: /* Unused */
return z80bank_unused_r (address);
default: /* Lockup */
return z80bank_lockup_r (address);
}
}
break;
case 6: /* VDP */
return z80bank_vdp_r (address);
case 7: /* Work RAM - can't be read on some Genesis models (!) */
return 0xFF;
}
return (-1);
}
void z80bank_vdp_w(int address, int data)
{
if ((address & 0xE700E0) == 0xC00000)
{
switch (address & 0x1F)
{
case 0x00: /* Data port */
case 0x01:
case 0x02:
case 0x03:
vdp_data_w (data << 8 | data);
return;
case 0x04: /* Control port */
case 0x05:
case 0x06:
case 0x07:
vdp_ctrl_w (data << 8 | data);
return;
case 0x08: /* Lockup (HVC) */
case 0x09:
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
z80bank_lockup_w (address, data);
return;
case 0x10: /* Unused */
case 0x12:
case 0x14:
case 0x16:
z80bank_unused_w (address, data);
return;
case 0x11: /* PSG */
case 0x13:
case 0x15:
case 0x17:
psg_write (data);
return;
case 0x18: /* Unused */
case 0x19:
case 0x1A:
case 0x1B:
z80bank_unused_w (address, data);
return;
case 0x1C: /* Test register */
case 0x1D:
case 0x1E:
case 0x1F:
vdp_test_w (data << 8 | data);
return;
}
}
else
{
/* Invalid VDP address */
z80bank_lockup_w (address, data);
return;
}
}
int z80bank_vdp_r(int address)
{
if ((address & 0xE700E0) == 0xC00000)
{
switch (address & 0x1F)
{
case 0x00: /* Data */
case 0x02:
return (vdp_data_r () >> 8) & 0xFF;
case 0x01: /* Data */
case 0x03:
return vdp_data_r () & 0xFF;
case 0x04: /* Control */
case 0x06:
return (0xFC | (vdp_ctrl_r () >> 8)) & 0xFF;
case 0x05: /* Control */
case 0x07:
return vdp_ctrl_r () & 0xFF;
case 0x08: /* HVC */
case 0x0A:
case 0x0C:
case 0x0E:
return (vdp_hvc_r () >> 8) & 0xFF;
case 0x09: /* HVC */
case 0x0B:
case 0x0D:
case 0x0F:
return vdp_hvc_r () & 0xFF;
case 0x10: /* Lockup */
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
return z80bank_lockup_r (address);
case 0x18: /* Unused */
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x1E:
case 0x1F:
return (z80bank_unused_r (address) | 0xFF);
}
}
else
{
/* Invalid VDP address */
return z80bank_lockup_r (address);
}
return 0xFF;
}
/*
Handlers for access to unused addresses and those which make the
machine lock up.
*/
void z80bank_unused_w(int address, int data)
{
error("Z80 bank unused write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
}
int z80bank_unused_r(int address)
{
error ("Z80 bank unused read %06X (%04X)\n", address, z80_get_reg (Z80_PC));
return (address & 1) ? 0x00 : 0xFF;
}
void z80bank_lockup_w(int address, int data)
{
error("Z80 bank lockup write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
gen_running = 0;
z80_end_timeslice ();
}
int z80bank_lockup_r(int address)
{
error ("Z80 bank lockup read %06X (%04X)\n", address, z80_get_reg (Z80_PC));
gen_running = 0;
z80_end_timeslice ();
return 0xFF;
}