Genesis-Plus-GX/source/mem68k.c

1032 lines
27 KiB
C

/***************************************************************************************
* Genesis Plus 1.2a
* 68k memory handlers
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
****************************************************************************************/
#include "m68kcpu.h"
#include "shared.h"
uint8 m68k_readmap_8[32];
uint8 m68k_readmap_16[32];
uint8 m68k_writemap_8[32];
uint8 m68k_writemap_16[32];
uint8 pico_current;
static uint8 pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F};
static inline unsigned int m68k_read_bus_8(unsigned int address)
{
#ifdef LOGERROR
if ((address != 0xa11100) && (address != 0xc00004) && (address != 0xc00006))
{
error("Unused read8 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0));
error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1));
error("D2 = %x \n", m68k_get_reg (NULL, M68K_REG_D2));
error("D3 = %x \n", m68k_get_reg (NULL, M68K_REG_D3));
error("D4 = %x \n", m68k_get_reg (NULL, M68K_REG_D4));
error("D5 = %x \n", m68k_get_reg (NULL, M68K_REG_D5));
error("D6 = %x \n", m68k_get_reg (NULL, M68K_REG_D6));
error("D7 = %x \n", m68k_get_reg (NULL, M68K_REG_D7));
error("A0 = %x \n", m68k_get_reg (NULL, M68K_REG_A0));
error("A1 = %x \n", m68k_get_reg (NULL, M68K_REG_A1));
error("A2 = %x \n", m68k_get_reg (NULL, M68K_REG_A2));
error("A3 = %x \n", m68k_get_reg (NULL, M68K_REG_A3));
error("A4 = %x \n", m68k_get_reg (NULL, M68K_REG_A4));
error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5));
error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6));
error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7));
}
#endif
int bus_addr = (REG_PC & 0xffffe) | (address & 1);
int offset = bus_addr >> 19;
if (offset > 8) return READ_BYTE(work_ram, bus_addr & 0xffff);
else return READ_BYTE(rom_readmap[offset], bus_addr & 0x7ffff);
}
static inline unsigned int m68k_read_bus_16(unsigned int address)
{
#ifdef LOGERROR
if ((address != 0xa11100) && (address != 0xc00004) && (address != 0xc00006))
{
error("Unused read16 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0));
error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1));
error("D2 = %x \n", m68k_get_reg (NULL, M68K_REG_D2));
error("D3 = %x \n", m68k_get_reg (NULL, M68K_REG_D3));
error("D4 = %x \n", m68k_get_reg (NULL, M68K_REG_D4));
error("D5 = %x \n", m68k_get_reg (NULL, M68K_REG_D5));
error("D6 = %x \n", m68k_get_reg (NULL, M68K_REG_D6));
error("D7 = %x \n", m68k_get_reg (NULL, M68K_REG_D7));
error("A0 = %x \n", m68k_get_reg (NULL, M68K_REG_A0));
error("A1 = %x \n", m68k_get_reg (NULL, M68K_REG_A1));
error("A2 = %x \n", m68k_get_reg (NULL, M68K_REG_A2));
error("A3 = %x \n", m68k_get_reg (NULL, M68K_REG_A3));
error("A4 = %x \n", m68k_get_reg (NULL, M68K_REG_A4));
error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5));
error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6));
error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7));
}
#endif
int bus_addr = REG_PC & 0xfffffe;
int offset = bus_addr >> 19;
if (offset > 8) return *(uint16 *)(work_ram + (bus_addr & 0xffff));
else return *(uint16 *)(rom_readmap[offset] + (bus_addr & 0x7ffff));
}
static inline void m68k_unused_8_w (unsigned int address, unsigned int value)
{
#ifdef LOGERROR
error("Unused write8 %08X = %02X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC));
#endif
}
static inline void m68k_unused_16_w (unsigned int address, unsigned int value)
{
#ifdef LOGERROR
error("Unused write16 %08X = %04X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC));
#endif
}
/*
Functions to handle memory accesses which cause the Genesis to halt
either temporarily (press RESET button to restart) or unrecoverably
(cycle power to restart).
*/
static inline void m68k_lockup_w_8 (unsigned int address, unsigned int value)
{
#ifdef LOGERROR
error ("Lockup %08X = %02X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC));
#endif
gen_running = config.force_dtack;
if (!gen_running) m68k_end_timeslice ();
}
static inline void m68k_lockup_w_16 (unsigned int address, unsigned int value)
{
#ifdef LOGERROR
error ("Lockup %08X = %04X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC));
#endif
gen_running = config.force_dtack;
if (!gen_running) m68k_end_timeslice ();
}
static inline unsigned int m68k_lockup_r_8 (unsigned int address)
{
#ifdef LOGERROR
error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
#endif
gen_running = config.force_dtack;
if (!gen_running) m68k_end_timeslice ();
return -1;
}
static inline unsigned int m68k_lockup_r_16 (unsigned int address)
{
#ifdef LOGERROR
error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
#endif
gen_running = config.force_dtack;
if (!gen_running) m68k_end_timeslice ();
return -1;
}
/*--------------------------------------------------------------------------*/
/* 68000 memory handlers */
/*--------------------------------------------------------------------------*/
unsigned int m68k_read_memory_8(unsigned int address)
{
int offset = address >> 19;
switch (m68k_readmap_8[offset])
{
case WRAM:
return READ_BYTE(work_ram, address & 0xffff);
case SYSTEM_IO:
{
unsigned int base = address >> 8;
/* Z80 */
if (base <= 0xa0ff)
{
/* Z80 controls Z bus ? */
if (zbusack) return m68k_read_bus_8(address);
/* Read data from Z bus */
switch (base & 0x60)
{
case 0x40: /* YM2612 */
return fm_read(0, address & 3);
case 0x60: /* VDP */
if (base == 0xa07f) return m68k_lockup_r_8(address);
return (m68k_read_bus_8(address) | 0xff);
default: /* ZRAM */
return zram[address & 0x1fff];
}
}
/* I/O & CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip */
if (address & 0xe0) return m68k_read_bus_8(address);
return (io_read((address >> 1) & 0x0f));
case 0x11: /* BUSACK */
return (zbusack | (address & 1) | (m68k_read_bus_8(address) & 0xFE));
case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address);
else return m68k_read_bus_8(address);
case 0x10: /* MEMORY MODE */
case 0x12: /* RESET */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x41: /* BOOTROM */
case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */
return m68k_read_bus_8(address);
default: /* Invalid address */
return m68k_lockup_r_8(address);
}
}
/* Invalid address */
return m68k_lockup_r_8(address);
}
case VDP:
/* Valid VDP addresses */
if (((address >> 16) & 0x07) == 0)
{
switch (address & 0xff)
{
case 0x00: /* DATA */
case 0x02:
return (vdp_data_r() >> 8);
case 0x01: /* DATA */
case 0x03:
return (vdp_data_r() & 0xff);
case 0x04: /* CTRL */
case 0x06:
return ((m68k_read_bus_8(address) & 0xfc) | ((vdp_ctrl_r() >> 8) & 3));
case 0x05: /* CTRL */
case 0x07:
return (vdp_ctrl_r() & 0xff);
case 0x08: /* HVC */
case 0x0a:
case 0x0c:
case 0x0e:
return (vdp_hvc_r() >> 8);
case 0x09: /* HVC */
case 0x0b:
case 0x0d:
case 0x0f:
return (vdp_hvc_r() & 0xff);
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f: /* Unused */
return m68k_read_bus_8(address);
default: /* Invalid address */
return m68k_lockup_r_8(address);
}
}
/* Invalid address */
return (m68k_lockup_r_8 (address));
case SRAM:
if (address <= sram.end) return READ_BYTE(sram.sram, address - sram.start);
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
case EEPROM:
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0);
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
case CART_HW:
return cart_hw.regs_r(address);
case UNUSED:
return m68k_read_bus_8(address);
case ILLEGAL:
return m68k_lockup_r_8(address);
case UMK3_HACK:
return READ_BYTE(&cart_rom[offset<<19], address & 0x7ffff);
case PICO_HW:
switch (address & 0xff)
{
case 0x01: /* VERSION register */
return (0x40);
case 0x03: /* IO register */
{
uint8 retval = 0xff;
if (input.pad[0] & INPUT_B) retval &= ~0x10;
if (input.pad[0] & INPUT_A) retval &= ~0x80;
if (input.pad[0] & INPUT_UP) retval &= ~0x01;
if (input.pad[0] & INPUT_DOWN) retval &= ~0x02;
if (input.pad[0] & INPUT_LEFT) retval &= ~0x04;
if (input.pad[0] & INPUT_RIGHT) retval &= ~0x08;
retval &= ~0x20;
retval &= ~0x40;
return retval;
}
case 0x05: /* MSB PEN X coordinate */
return (input.analog[0][0] >> 8);
case 0x07: /* LSB PEN X coordinate */
return (input.analog[0][0] & 0xff);
case 0x09: /* MSB PEN Y coordinate */
return (input.analog[0][1] >> 8);
case 0x0b: /* LSB PEN Y coordinate */
return (input.analog[0][1] & 0xff);
case 0x0d: /* PAGE register */
return pico_page[pico_current]; /* TODO */
case 0x10: /* PCM registers */
case 0x11:
case 0x12:
case 0x13:
return 0x80; /* TODO */
default:
return m68k_read_bus_8(address);
}
default: /* ROM */
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
}
}
unsigned int m68k_read_memory_16 (unsigned int address)
{
int offset = address >> 19;
switch (m68k_readmap_16[offset])
{
case WRAM:
return *(uint16 *)(work_ram + (address & 0xffff));
case SVP_DRAM:
return *(uint16 *)(svp->dram + (address & 0x1fffe));
case SVP_CELL:
switch (address >> 16)
{
case 0x39:
address >>= 1;
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
return *(uint16 *)(svp->dram + (address & 0x1fffe));
case 0x3A:
address >>= 1;
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
return *(uint16 *)(svp->dram + (address & 0x1fffe));
default:
return m68k_read_bus_16(address);
}
case SYSTEM_IO:
{
unsigned int base = address >> 8;
/* Z80 */
if (base <= 0xa0ff)
{
/* Z80 controls Z bus ? */
if (zbusack) return m68k_read_bus_16(address);
/* Read data from Z bus */
switch (base & 0x60)
{
case 0x40: /* YM2612 */
{
int temp = fm_read(0, address & 3);
return (temp << 8 | temp);
}
case 0x60: /* VDP */
if (base == 0xa07f) return m68k_lockup_r_16(address);
return (m68k_read_bus_16(address) | 0xffff);
default: /* ZRAM */
{
int temp = zram[address & 0x1fff];
return (temp << 8 | temp);
}
}
}
/* CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip */
{
if (address & 0xe0) return m68k_read_bus_16(address);
int temp = io_read((address >> 1) & 0x0f);
return (temp << 8 | temp);
}
case 0x11: /* BUSACK */
return ((m68k_read_bus_16(address) & 0xfeff) | (zbusack << 8));
case 0x50: /* SVP */
if (svp)
{
switch (address & 0xff)
{
case 0:
case 2:
return svp->ssp1601.gr[SSP_XST].h;
case 4:
{
unsigned int temp = svp->ssp1601.gr[SSP_PM0].h;
svp->ssp1601.gr[SSP_PM0].h &= ~1;
return temp;
}
}
}
return m68k_read_bus_16(address);
case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address);
else return m68k_read_bus_16(address);
case 0x10: /* MEMORY MODE */
case 0x12: /* RESET */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x41: /* BOOTROM */
case 0x44: /* RADICA */
return m68k_read_bus_16(address);
default: /* Invalid address */
return m68k_lockup_r_16(address);
}
}
/* Invalid address */
return m68k_lockup_r_16 (address);
}
case VDP:
/* Valid VDP addresses */
if (((address >> 16) & 0x07) == 0)
{
switch (address & 0xfc)
{
case 0x00: /* DATA */
return vdp_data_r();
case 0x04: /* CTRL */
return ((vdp_ctrl_r() & 0x3FF) | (m68k_read_bus_16(address) & 0xFC00));
case 0x08: /* HVC */
case 0x0c:
return vdp_hvc_r();
case 0x18: /* Unused */
case 0x1c:
return m68k_read_bus_16(address);
default:
return m68k_lockup_r_16(address);
}
}
/* Invalid address */
return m68k_lockup_r_16 (address);
case SRAM:
if (address <= sram.end) return *(uint16 *)(sram.sram + (address - sram.start));
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
case EEPROM:
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
case J_CART:
return jcart_read();
case REALTEC_ROM:
return *(uint16 *)(&cart_rom[0x7e000] + (address & 0x1fff));
case UNUSED:
return m68k_read_bus_16(address);
case ILLEGAL:
return m68k_lockup_r_16(address);
case UMK3_HACK:
return *(uint16 *)(&cart_rom[offset << 19] + (address & 0x7ffff));
case PICO_HW:
switch (address & 0xff)
{
case 0x00: /* VERSION register */
return (0x40);
case 0x02: /* IO register */
{
uint8 retval = 0xff;
if (input.pad[0] & INPUT_B) retval &= ~0x10;
if (input.pad[0] & INPUT_A) retval &= ~0x80;
if (input.pad[0] & INPUT_UP) retval &= ~0x01;
if (input.pad[0] & INPUT_DOWN) retval &= ~0x02;
if (input.pad[0] & INPUT_LEFT) retval &= ~0x04;
if (input.pad[0] & INPUT_RIGHT) retval &= ~0x08;
retval &= ~0x20;
retval &= ~0x40;
return retval;
}
case 0x04: /* MSB PEN X coordinate */
return (input.analog[0][0] >> 8);
case 0x06: /* LSB PEN X coordinate */
return (input.analog[0][0] & 0xff);
case 0x08: /* MSB PEN Y coordinate */
return (input.analog[0][1] >> 8);
case 0x0a: /* LSB PEN Y coordinate */
return (input.analog[0][1] & 0xff);
case 0x0c: /* PAGE register */
return pico_page[pico_current]; /* TODO */
case 0x10: /* PCM data register */
return 0x8000; /* TODO */
case 0x12: /* PCM control registe */
return 0x8000; /* TODO */
default:
return m68k_read_bus_16(address);
}
default: /* ROM */
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
}
}
unsigned int m68k_read_memory_32(unsigned int address)
{
/* Split into 2 reads */
return ((m68k_read_memory_16 (address) << 16) |
(m68k_read_memory_16 ((address+ 2)&0xffffff)));
}
void m68k_write_memory_8(unsigned int address, unsigned int value)
{
int offset = address >> 19;
switch (m68k_writemap_8[offset])
{
case VDP:
/* Valid VDP addresses */
if (((address >> 16) & 0x07) == 0)
{
switch (address & 0xff)
{
case 0x00: /* Data port */
case 0x01:
case 0x02:
case 0x03:
vdp_data_w(value << 8 | value);
return;
case 0x04: /* Control port */
case 0x05:
case 0x06:
case 0x07:
vdp_ctrl_w(value << 8 | value);
return;
case 0x10: /* Unused */
case 0x12:
case 0x14:
case 0x16:
m68k_unused_8_w(address, value);
return;
case 0x11: /* PSG */
case 0x13:
case 0x15:
case 0x17:
psg_write(0, value);
return;
case 0x18: /* Unused */
case 0x19:
case 0x1a:
case 0x1b:
m68k_unused_8_w(address, value);
return;
case 0x1c: /* Test register */
case 0x1d:
case 0x1e:
case 0x1f:
vdp_test_w(value << 8 | value);
return;
default: /* Invalid address */
m68k_lockup_w_8(address, value);
return;
}
}
/* Invalid address */
m68k_lockup_w_8(address, value);
return;
case SYSTEM_IO:
{
unsigned int base = address >> 8;
/* Z80 */
if (base <= 0xa0ff)
{
/* Writes are ignored when the Z80 hogs the Z-bus */
if (zbusack)
{
m68k_unused_8_w (address, value);
return;
}
/* Read data from Z bus */
switch (base & 0x60)
{
case 0x40: /* YM2612 */
fm_write(0, address & 3, value);
return;
case 0x60:
switch (base & 0x7f)
{
case 0x60: /* Bank register */
gen_bank_w(value & 1);
return;
case 0x7f: /* VDP */
m68k_lockup_w_8(address, value);
return;
default:
m68k_unused_8_w(address, value);
return;
}
default: /* ZRAM */
zram[address & 0x1fff] = value;
count_m68k ++;
return;
}
}
/* CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip (only gets /LWR) */
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, value);
else m68k_unused_8_w(address, value);
return;
case 0x11: /* BUSREQ */
if (address & 1) m68k_unused_8_w(address, value);
else gen_busreq_w(value & 1);
return;
case 0x12: /* RESET */
if (address & 1) m68k_unused_8_w(address, value);
else gen_reset_w(value & 1);
return;
case 0x30: /* TIME */
if (cart_hw.time_w) cart_hw.time_w(address, value);
else m68k_unused_8_w(address, value);
return;
case 0x41: /* BOOTROM */
if (address & 1)
{
if (value & 1)
{
rom_readmap[0] = &cart_rom[0];
rom_size = genromsize;
}
else
{
rom_readmap[0] = &bios_rom[0];
rom_size = 0x800;
}
if (!(config.bios_enabled & 2))
{
config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800);
memset(cart_rom, 0, 0x500000);
}
}
else m68k_unused_8_w (address, value);
return;
case 0x10: /* MEMORY MODE */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */
m68k_unused_8_w(address, value);
return;
default: /* Invalid address */
m68k_lockup_w_8(address, value);
return;
}
}
/* Invalid address */
m68k_lockup_w_8(address, value);
return;
}
case ROM:
WRITE_BYTE(rom_readmap[offset], address & 0x7ffff, value);
return;
case SRAM:
if (address <= sram.end) WRITE_BYTE(sram.sram, address - sram.start, value);
else m68k_unused_8_w(address, value);
return;
case EEPROM:
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, value, 0);
else m68k_unused_8_w(address, value);
return;
case CART_HW:
cart_hw.regs_w(address, value);
return;
case UNUSED:
m68k_unused_8_w(address, value);
return;
case ILLEGAL:
m68k_lockup_w_8(address, value);
return;
case PICO_HW:
switch (address & 0xff)
{
case 0x19:
case 0x1b:
case 0x1d:
case 0x1f: /* TMSS register */
return;
default:
m68k_unused_8_w(address, value);
return;
}
default: /* WRAM */
WRITE_BYTE(work_ram, address & 0xffff, value);
return;
}
}
void m68k_write_memory_16 (unsigned int address, unsigned int value)
{
int offset = address >> 19;
switch (m68k_writemap_16[offset])
{
case SVP_DRAM:
*(uint16 *)(svp->dram + (address & 0x1fffe)) = value;
if ((address == 0x30fe06) && value) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
if ((address == 0x30fe08) && value) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
return;
case VDP:
/* Valid VDP addresses */
if (((address >> 16) & 0x07) == 0)
{
switch (address & 0xfc)
{
case 0x00: /* DATA */
vdp_data_w(value);
return;
case 0x04: /* CTRL */
vdp_ctrl_w(value);
return;
case 0x10: /* PSG */
case 0x14:
psg_write(0, value & 0xff);
return;
case 0x18: /* Unused */
m68k_unused_16_w(address, value);
return;
case 0x1c: /* Test register */
vdp_test_w(value);
return;
default: /* Invalid address */
m68k_lockup_w_16 (address, value);
return;
}
}
/* Invalid address */
m68k_lockup_w_16 (address, value);
return;
case SYSTEM_IO:
{
unsigned int base = address >> 8;
/* Z80 */
if (base <= 0xa0ff)
{
/* Writes are ignored when the Z80 hogs the Z-bus */
if (zbusack)
{
m68k_unused_16_w (address, value);
return;
}
/* Write into Z80 address space */
switch (base & 0x60)
{
case 0x40: /* YM2612 */
fm_write (0, address & 3, value >> 8);
return;
case 0x60:
switch (base & 0x7f)
{
case 0x60: /* Bank register */
gen_bank_w ((value >> 8) & 1);
return;
case 0x7f: /* VDP */
m68k_lockup_w_16(address, value);
return;
default:
m68k_unused_16_w(address, value);
return;
}
default: /* ZRAM */
zram[address & 0x1fff] = value >> 8;
return;
}
}
/* CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip */
if (address & 0xe0) m68k_unused_16_w (address, value);
else io_write ((address >> 1) & 0x0f, value & 0xff);
return;
case 0x11: /* BUSREQ */
gen_busreq_w ((value >> 8) & 1);
return;
case 0x12: /* RESET */
gen_reset_w ((value >> 8) & 1);
return;
case 0x50: /* SVP REGISTERS */
if (svp && ((address & 0xfd) == 0))
{
/* just guessing here (Notaz) */
svp->ssp1601.gr[SSP_XST].h = value;
svp->ssp1601.gr[SSP_PM0].h |= 2;
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
return;
}
m68k_unused_16_w(address, value);
return;
case 0x30: /* TIME */
if (cart_hw.time_w)
{
cart_hw.time_w(address & 0xfe, value >> 8);
cart_hw.time_w(address, value & 0xff);
}
else m68k_unused_16_w (address, value);
return;
case 0x41: /* BOOTROM */
if (value & 1)
{
rom_readmap[0] = &cart_rom[0];
rom_size = genromsize;
}
else
{
rom_readmap[0] = &bios_rom[0];
rom_size = 0x800;
}
if (!(config.bios_enabled & 2))
{
config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800);
memset(cart_rom, 0, 0x500000);
}
return;
case 0x10: /* MEMORY MODE */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x44: /* RADICA */
m68k_unused_16_w (address, value);
return;
default: /* Unused */
m68k_lockup_w_16 (address, value);
return;
}
}
/* Invalid address */
m68k_lockup_w_16 (address, value);
return;
}
case ROM:
*(uint16 *)(rom_readmap[offset] + (address & 0x7ffff)) = value;
return;
case SRAM:
if (address <= sram.end) *(uint16 *)(sram.sram + (address - sram.start)) = value;
else m68k_unused_16_w (address, value);
return;
case EEPROM:
if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe)))
eeprom_write(address, value, 1);
else m68k_unused_16_w (address, value);
return;
case J_CART:
jcart_write(value);
return;
case UNUSED:
m68k_unused_16_w (address, value);
return;
case ILLEGAL:
m68k_lockup_w_16 (address, value);
return;
case PICO_HW:
switch (address & 0xff)
{
case 0x10: /* PCM data register */
return; /* TODO */
case 0x12: /* PCM control resiter */
return; /* TODO */
case 0x18:
case 0x1a:
case 0x1c:
case 0x1e: /* TMSS register */
return;
default:
m68k_unused_16_w(address, value);
return;
}
default: /* WRAM */
*(uint16 *)(work_ram + (address & 0xffff)) = value;
return;
}
}
void m68k_write_memory_32 (unsigned int address, unsigned int value)
{
/* Split into 2 writes */
m68k_write_memory_16 (address, value >> 16);
m68k_write_memory_16 ((address+2) & 0xffffff, value & 0xffff);
}