MCUME/MCUME_teensy41/teensygen/membnk.c

328 wiersze
8.7 KiB
C

/*
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)
gen_io_w((address >> 1) & 0x0F, data);
else
z80bank_unused_w(address, data);
return;
case 0x10: /* DRAM refresh */
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 0x13: /* /TIME region */
z80bank_unused_w(address, data);
return;
case 0x20: /* ? */
z80bank_unused_w(address, data);
return;
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 readb_swap_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 gen_io_r((address >> 1) & 0x0F);
else
return z80bank_unused_r(address);
break;
case 0x10: /* Unused */
return z80bank_unused_r(address);
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 0x12: /* Unused */
return z80bank_unused_r(address);
case 0x13: /* /TIME region */
return z80bank_unused_r(address);
case 0x20: /* Unused */
return z80bank_unused_r(address);
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)
if((address & 0xE700E0) == 0xC0000)
{
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)
if((address & 0xE700E0) == 0xC0000)
{
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;
}