diff options
author | 2015-09-13 08:41:44 +0200 | |
---|---|---|
committer | 2015-09-13 08:41:44 +0200 | |
commit | f88cefad27a1737c76e09d99c9fb43e173506081 (patch) | |
tree | 2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/machine/mos8722.c | |
parent | e92ac9e0fa8e99869894bea00589bbb526be30aa (diff) |
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/machine/mos8722.c')
-rw-r--r-- | src/devices/machine/mos8722.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/src/devices/machine/mos8722.c b/src/devices/machine/mos8722.c new file mode 100644 index 00000000000..31b2beb1f27 --- /dev/null +++ b/src/devices/machine/mos8722.c @@ -0,0 +1,366 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + MOS Technology 8722 Memory Management Unit emulation + +**********************************************************************/ + +#include "mos8722.h" + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type MOS8722 = &device_creator<mos8722_device>; + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 0 + + +#define CR_IO BIT(m_reg[CR], 0) +#define CR_ROM_LO BIT(m_reg[CR], 1) +#define CR_ROM_MID ((m_reg[CR] >> 2) & 0x03) +#define CR_ROM_HI ((m_reg[CR] >> 4) & 0x03) +#define CR_A16 BIT(m_reg[CR], 6) + + +// mode configuration register +#define MCR_8500 BIT(m_reg[MCR], 0) +#define MCR_FSDIR BIT(m_reg[MCR], 3) +#define MCR_GAME BIT(m_reg[MCR], 4) +#define MCR_EXROM BIT(m_reg[MCR], 5) +#define MCR_C64 BIT(m_reg[MCR], 6) +#define MCR_40_80 BIT(m_reg[MCR], 7) + + +// RAM configuration register +static const offs_t RCR_BOTTOM_ADDRESS[4] = { 0x0400, 0x1000, 0x0400, 0x1000 }; +static const offs_t RCR_TOP_ADDRESS[4] = { 0xf000, 0xf000, 0xe000, 0xc000 }; + +#define RCR_SHARE (m_reg[RCR] & 0x03) +#define RCR_BOTTOM BIT(m_reg[RCR], 2) +#define RCR_TOP BIT(m_reg[RCR], 3) +#define RCR_VA16 BIT(m_reg[RCR], 6) + + +// page 0 pointer register +#define P0H_A16 BIT(m_reg[P0H], 0) + + +// page 1 pointer register +#define P1H_A16 BIT(m_reg[P1H], 0) + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// mos8722_device - constructor +//------------------------------------------------- + +mos8722_device::mos8722_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, MOS8722, "MOS8722", tag, owner, clock, "mos8722", __FILE__), + m_write_z80en(*this), + m_write_fsdir(*this), + m_read_game(*this), + m_read_exrom(*this), + m_read_sense40(*this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mos8722_device::device_start() +{ + // resolve callbacks + m_write_z80en.resolve_safe(); + m_write_fsdir.resolve_safe(); + m_read_game.resolve_safe(1); + m_read_exrom.resolve_safe(1); + m_read_sense40.resolve_safe(1); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void mos8722_device::device_reset() +{ + for (int i = 0; i < 16; i++) + { + m_reg[i] = 0; + } + + m_reg[P1L] = 0x01; + + m_p0h_latch = 0; + m_p1h_latch = 0; + + m_write_z80en(MCR_8500); + m_write_fsdir(MCR_FSDIR); +} + + +//------------------------------------------------- +// read - register read +//------------------------------------------------- + +UINT8 mos8722_device::read(offs_t offset, UINT8 data) +{ + if (MCR_C64) return data; + + if (!CR_IO && offset >= 0xd500 && offset < 0xd50c) + { + switch (offset & 0x0f) + { + case CR: + data = m_reg[CR] | 0x80; + break; + + case MCR: + data = m_reg[MCR] | 0x06; + + data &= ((m_read_game() << 4) | ~0x10); + data &= ((m_read_exrom() << 5) | ~0x20); + data &= ((m_read_sense40() << 7) | ~0x80); + break; + + case VR: + data = 0x20; + break; + + default: + data = m_reg[offset & 0x0f]; + break; + } + } + else if (offset >= 0xff00 && offset < 0xff05) + { + switch (offset & 0x0f) + { + case CR: + data = m_reg[CR] | 0x80; + break; + + default: + data = m_reg[offset & 0x0f]; + break; + } + } + + return data; +} + + +//------------------------------------------------- +// write - register write +//------------------------------------------------- + +WRITE8_MEMBER( mos8722_device::write ) +{ + if (MCR_C64) return; + + if (!CR_IO && offset >= 0xd500 && offset < 0xd50c) + { + if (LOG) logerror("MOS8722 '%s' Write %01x : %02x\n", tag(), offset & 0x0f, data); + + switch (offset & 0x0f) + { + case CR: + m_reg[CR] = data & 0x7f; + break; + + case PCRA: + case PCRB: + case PCRC: + case PCRD: + m_reg[offset & 0x0f] = data & 0x7f; + break; + + case MCR: + { + int _8500 = MCR_8500; + int fsdir = MCR_FSDIR; + + m_reg[MCR] = data; + + if (_8500 != MCR_8500) m_write_z80en(MCR_8500); + if (fsdir != MCR_FSDIR) m_write_fsdir(MCR_FSDIR); + break; + } + + case RCR: + m_reg[RCR] = data & 0x4f; + break; + + case P0L: + m_reg[P0L] = data; + m_reg[P0H] = m_p0h_latch; + break; + + case P0H: + m_p0h_latch = data & 0x01; + break; + + case P1L: + m_reg[P1L] = data; + m_reg[P1H] = m_p1h_latch; + break; + + case P1H: + m_p1h_latch = data & 0x01; + break; + + default: + m_reg[offset & 0x0f] = data; + } + } + else if (offset >= 0xff00 && offset < 0xff05) + { + if (LOG) logerror("MOS8722 '%s' Write %01x : %02x\n", tag(), offset & 0x0f, data); + + switch (offset & 0x0f) + { + case CR: + m_reg[CR] = data & 0x7f; + break; + + default: + m_reg[CR] = m_reg[offset & 0x0f]; + break; + } + } +} + + +//------------------------------------------------- +// fsdir_r - fast serial direction read +//------------------------------------------------- + +READ_LINE_MEMBER( mos8722_device::fsdir_r ) +{ + return MCR_FSDIR; +} + + +//------------------------------------------------- +// ta_r - translated address read +//------------------------------------------------- + +offs_t mos8722_device::ta_r(offs_t offset, int aec, int *ms0, int *ms1, int *ms2, int *ms3, int *cas0, int *cas1) +{ + offs_t ta; + + *ms0 = 1; + *ms1 = 1; + *ms2 = CR_IO; + *ms3 = !MCR_C64; + + if (aec) + { + // CPU access + ta = offset & 0xff00; + + *cas0 = CR_A16; + *cas1 = !*cas0; + + if (!MCR_C64) + { + if (offset >= 0xff00 && offset < 0xff05) + { + // MMU registers + *cas0 = 1; + *cas1 = 1; + } + else if (!MCR_8500 && !CR_A16 && offset < 0x1000) + { + // Z80 ROM + ta = 0xd000 | (offset & 0xf00); + + *ms0 = 0; + *ms1 = 0; + } + else + { + if (offset < 0x0100) + { + // page 0 pointer + ta = m_reg[P0L] << 8; + + *cas0 = P0H_A16; + *cas1 = !*cas0; + } + else if (offset < 0x0200) + { + // page 1 pointer + ta = m_reg[P1L] << 8; + + *cas0 = P1H_A16; + *cas1 = !*cas0; + } + else if (offset >= 0x4000 && offset < 0x8000) + { + // low ROM + *ms0 = CR_ROM_LO; + *ms1 = CR_ROM_LO; + } + else if (offset >= 0x8000 && offset < 0xc000) + { + // middle ROM + *ms0 = BIT(CR_ROM_MID, 1); + *ms1 = BIT(CR_ROM_MID, 0); + } + else if (offset >= 0xc000) + { + // high ROM + *ms0 = BIT(CR_ROM_HI, 1); + *ms1 = BIT(CR_ROM_HI, 0); + } + + if (*ms0 && *ms1) + { + if ((offset >> 8) == m_reg[P0L]) + { + ta = 0x0000; + } + else if ((offset >> 8) == m_reg[P1L]) + { + ta = 0x0100; + } + } + + if ((RCR_BOTTOM && offset < RCR_BOTTOM_ADDRESS[RCR_SHARE]) || + (RCR_TOP && offset >= RCR_TOP_ADDRESS[RCR_SHARE])) + { + // RAM sharing + *cas0 = 0; + *cas1 = !*cas0; + } + } + } + } + else + { + // VIC access + ta = 0xf000 | (offset & 0xf00); + + *cas0 = RCR_VA16; + *cas1 = !*cas0; + } + + return ta; +} |