diff options
Diffstat (limited to 'src/devices/bus/a800/rom.c')
-rw-r--r-- | src/devices/bus/a800/rom.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/src/devices/bus/a800/rom.c b/src/devices/bus/a800/rom.c new file mode 100644 index 00000000000..f52a489bcf0 --- /dev/null +++ b/src/devices/bus/a800/rom.c @@ -0,0 +1,447 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli +/*********************************************************************************************************** + + A800/A5200/XEGS ROM cart emulation + + Basic carts work the same (in addition of being mostly compatible) for all these systems + and thus we deal with them in a single file + +***********************************************************************************************************/ + + +#include "emu.h" +#include "rom.h" + + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +const device_type A800_ROM = &device_creator<a800_rom_device>; +const device_type A800_ROM_BBSB = &device_creator<a800_rom_bbsb_device>; +const device_type A800_ROM_WILLIAMS = &device_creator<a800_rom_williams_device>; +const device_type A800_ROM_EXPRESS = &device_creator<a800_rom_express_device>; +const device_type A800_ROM_TURBO = &device_creator<a800_rom_turbo_device>; +const device_type A800_ROM_TELELINK2 = &device_creator<a800_rom_telelink2_device>; +const device_type A800_ROM_MICROCALC = &device_creator<a800_rom_microcalc_device>; +const device_type XEGS_ROM = &device_creator<xegs_rom_device>; +const device_type A5200_ROM_2CHIPS = &device_creator<a5200_rom_2chips_device>; +const device_type A5200_ROM_BBSB = &device_creator<a5200_rom_bbsb_device>; + + +a800_rom_device::a800_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_a800_cart_interface( mconfig, *this ) +{ +} + +a800_rom_device::a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, A800_ROM, "Atari 800 ROM Carts", tag, owner, clock, "a800_rom", __FILE__), + device_a800_cart_interface( mconfig, *this ) +{ +} + + +a800_rom_bbsb_device::a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_BBSB, "Atari 800 ROM Cart BBSB", tag, owner, clock, "a800_bbsb", __FILE__) +{ +} + + + +xegs_rom_device::xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, XEGS_ROM, "Atari XEGS 64K ROM Carts", tag, owner, clock, "a800_xegs", __FILE__) +{ +} + + +a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_WILLIAMS, "Atari 800 64K ROM Carts Williams", tag, owner, clock, "a800_williams", __FILE__) +{ +} + + +a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_EXPRESS, "Atari 800 64K ROM Carts Express/Diamond", tag, owner, clock, "a800_express", __FILE__) +{ +} + + +a800_rom_turbo_device::a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_TURBO, "Atari 800 64K ROM Carts Turbosoft", tag, owner, clock, "a800_turbo", __FILE__) +{ +} + + +a800_rom_telelink2_device::a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_TELELINK2, "Atari 800 64K ROM Cart Telelink II", tag, owner, clock, "a800_tlink2", __FILE__) +{ +} + + +a800_rom_microcalc_device::a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A800_ROM_MICROCALC, "Atari 800 64K ROM Cart SITSA MicroCalc", tag, owner, clock, "a800_sitsa", __FILE__) +{ +} + + +a5200_rom_2chips_device::a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A5200_ROM_2CHIPS, "Atari 5200 ROM Cart 16K in 2 Chips", tag, owner, clock, "a5200_16k2c", __FILE__) +{ +} + + +a5200_rom_bbsb_device::a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : a800_rom_device(mconfig, A5200_ROM_BBSB, "Atari 5200 ROM Cart BBSB", tag, owner, clock, "a5200_bbsb", __FILE__) +{ +} + + + + +void a800_rom_device::device_start() +{ +} + +void a800_rom_device::device_reset() +{ +} + + +void a800_rom_bbsb_device::device_start() +{ + save_item(NAME(m_banks)); +} + +void a800_rom_bbsb_device::device_reset() +{ + m_banks[0] = 0; + m_banks[1] = 0; +} + + +void xegs_rom_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void xegs_rom_device::device_reset() +{ + m_bank = 0; +} + + +void a800_rom_williams_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_williams_device::device_reset() +{ + m_bank = 0; +} + + +void a800_rom_express_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_express_device::device_reset() +{ + m_bank = 0; +} + + +void a800_rom_turbo_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_turbo_device::device_reset() +{ + m_bank = 0; +} + + +void a800_rom_microcalc_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_microcalc_device::device_reset() +{ + m_bank = 0; +} + + +void a5200_rom_bbsb_device::device_start() +{ + save_item(NAME(m_banks)); +} + +void a5200_rom_bbsb_device::device_reset() +{ + m_banks[0] = 0; + m_banks[1] = 0; +} + + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +/*------------------------------------------------- + + Carts with no bankswitch (8K, 16K) + + The cart accessors are mapped in the correct + range at driver start + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_device::read_80xx) +{ + return m_rom[offset & (m_rom_size - 1)]; +} + + + +/*------------------------------------------------- + + Bounty Bob Strikes Back! cart (40K) + + Area 0xa000-0xbfff always point to last 8K bank + Areas 0x8000-0x8fff and 0x9000-0x9fff are + separate banks of 4K mapped either in the first + 16K chunk or in the second 16K chunk + Bankswitch is controlled by data written in + 0x8000-0x8fff and 0x9000-0x9fff respectively + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_bbsb_device::read_80xx) +{ + if (offset < 0x1000) + return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0]; + else if (offset < 0x2000) + return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x4000]; + else + return m_rom[(offset & 0x1fff) + 0x8000]; +} + +WRITE8_MEMBER(a800_rom_bbsb_device::write_80xx) +{ + UINT16 addr = offset & 0xfff; + if (addr >= 0xff6 && addr <= 0xff9) + m_banks[BIT(offset, 12)] = (addr - 0xff6); +} + +/*------------------------------------------------- + + XEGS carts (32K, 64K or 128K) + + Bankswitch is controlled by data written in + 0xd500-0xd5ff + + -------------------------------------------------*/ + +READ8_MEMBER(xegs_rom_device::read_80xx) +{ + if (offset < 0x2000) + return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; + else + return m_rom[(offset & 0x1fff) + (m_bank_mask * 0x2000)]; // always last 8K bank + +} + +WRITE8_MEMBER(xegs_rom_device::write_d5xx) +{ + m_bank = data & m_bank_mask; +} + + +/*------------------------------------------------- + + Williams 64K + + The rom is accessed in 8K chunks at 0xa000-0xbfff + Bankswitch is controlled by writing to 7 diff + offsets (their location varies with the cart type): + offs 0 points to bank 0, offs 1 points to bank 1, + and so on... the rom can be disabled by writing to + the offsets 0x8-0xf of the same range as the bankswitch + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_williams_device::read_80xx) +{ + return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; +} + +WRITE8_MEMBER(a800_rom_williams_device::write_d5xx) +{ + m_bank = (offset & 0x07); +} + +/*------------------------------------------------- + + Express 64K / Diamond 64K carts + + The rom is accessed in 8K chunks at 0xa000-0xbfff + Bankswitch is the same as above, but writes trigger + banks in reverse order: offs 7 points to bank 0, offs 6 + points to bank 1, and so on... the rom can be disabled + by writing to the offsets 0x8-0xf of the same range + as the bankswitch + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_express_device::read_80xx) +{ + return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; +} + +WRITE8_MEMBER(a800_rom_express_device::write_d5xx) +{ + m_bank = (offset ^ 0x07) & 0x0f; +} + + +/*------------------------------------------------- + + Turbosoft 64K / 128K + + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_turbo_device::read_80xx) +{ + return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; +} + +WRITE8_MEMBER(a800_rom_turbo_device::write_d5xx) +{ + m_bank = offset & m_bank_mask; +} + + +/*------------------------------------------------- + + Telelink II + + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_telelink2_device::read_80xx) +{ + if (offset >= 0x2000) + return m_rom[offset & 0x1fff]; + if (offset >= 0x1000 && offset < 0x1100) + return m_nvram[offset & 0xff]; + + return 0xff; +} + +WRITE8_MEMBER(a800_rom_telelink2_device::write_80xx) +{ + m_nvram[offset & 0xff] = data | 0xf0; // low 4bits only +} + +READ8_MEMBER(a800_rom_telelink2_device::read_d5xx) +{ + // this should affect NVRAM enable / save + return 0xff; +} + +WRITE8_MEMBER(a800_rom_telelink2_device::write_d5xx) +{ + // this should affect NVRAM enable / save +} + + + +/*------------------------------------------------- + + SITSA Microcalc + + + -------------------------------------------------*/ + +READ8_MEMBER(a800_rom_microcalc_device::read_80xx) +{ + return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; +} + +WRITE8_MEMBER(a800_rom_microcalc_device::write_d5xx) +{ + m_bank = data; +} + + + +// Atari 5200 + + +/*------------------------------------------------- + + Carts with no bankswitch (4K, 8K, 16K, 32K) + + Same as base carts above + + -------------------------------------------------*/ + +/*------------------------------------------------- + + Carts with 2x8K (16K) with A13 line not connected + + Range 0x4000-0x7fff contains two copies of the low + 8K, range 0x8000-0xbfff contains two copies of the + high 8K + + -------------------------------------------------*/ + +READ8_MEMBER(a5200_rom_2chips_device::read_80xx) +{ + if (offset < 0x4000) + return m_rom[offset & 0x1fff]; + else + return m_rom[(offset & 0x1fff) + 0x2000]; +} + + +/*------------------------------------------------- + + Bounty Bob Strikes Back! cart (40K) + + Similar to the A800 version, but: + Area 0x8000-0xbfff always point to last 8K bank + (repeated twice) + Areas 0x4000-0x4fff and 0x5000-0x5fff are + separate banks of 4K mapped either in the first + 16K chunk or in the second 16K chunk + Bankswitch is controlled by data written in + 0x4000-0x4fff and 0x5000-0x5fff respectively + + -------------------------------------------------*/ + +READ8_MEMBER(a5200_rom_bbsb_device::read_80xx) +{ + if (offset < 0x1000) + return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0]; + else if (offset < 0x2000) + return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x4000]; + else if (offset >= 0x4000) + return m_rom[(offset & 0x1fff) + 0x8000]; + else + return 0; +} + +WRITE8_MEMBER(a5200_rom_bbsb_device::write_80xx) +{ + UINT16 addr = offset & 0xfff; + if (addr >= 0xff6 && addr <= 0xff9) + m_banks[BIT(offset, 12)] = (addr - 0xff6); +} |