diff options
Diffstat (limited to 'src/mess/machine/6883sam.c')
-rw-r--r-- | src/mess/machine/6883sam.c | 557 |
1 files changed, 0 insertions, 557 deletions
diff --git a/src/mess/machine/6883sam.c b/src/mess/machine/6883sam.c deleted file mode 100644 index cb5d0685fba..00000000000 --- a/src/mess/machine/6883sam.c +++ /dev/null @@ -1,557 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -/*************************************************************************** - - 6883sam.c - - Motorola 6883 Synchronous Address Multiplexer - - The Motorola 6883 SAM has 16 bits worth of state, but the state is changed - by writing into a 32 byte address space; odd bytes set bits and even bytes - clear bits. Here is the layout: - - 31 Set TY Map Type 0: RAM/ROM 1: All RAM - 30 Clear TY Map Type - 29 Set M1 Memory Size 00: 4K 10: 64K Dynamic - 28 Clear M1 Memory Size 01: 16K 11: 64K Static - 27 Set M0 Memory Size - 26 Clear M0 Memory Size - 25 Set R1 MPU Rate 00: Slow 10: Fast - 24 Clear R1 MPU Rate 01: Dual 11: Fast - 23 Set R0 MPU Rate - 22 Clear R0 MPU Rate - 21 Set P1 Page #1 0: Low 1: High - 20 Clear P1 Page #1 - 19 Set F6 Display Offset - 18 Clear F6 Display Offset - 17 Set F5 Display Offset - 16 Clear F5 Display Offset - 15 Set F4 Display Offset - 14 Clear F4 Display Offset - 13 Set F3 Display Offset - 12 Clear F3 Display Offset - 11 Set F2 Display Offset - 10 Clear F2 Display Offset - 9 Set F1 Display Offset - 8 Clear F1 Display Offset - 7 Set F0 Display Offset - 6 Clear F0 Display Offset - 5 Set V2 VDG Mode - 4 Clear V2 VDG Mode - 3 Set V1 VDG Mode - 2 Clear V1 VDG Mode - 1 Set V0 VDG Mode - 0 Clear V0 VDG Mode - - All parts of the SAM are fully emulated except R1/R0 (the changes in the - MPU rate are approximated) and M1/M0 - -***************************************************************************/ - - -#include "machine/6883sam.h" - - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -#define LOG_SAM 0 - -const device_type SAM6883 = &device_creator<sam6883_device>; - - - -//************************************************************************** -// DEVICE SETUP -//************************************************************************** - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -sam6883_device::sam6883_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, SAM6883, "SAM6883", tag, owner, clock, "sam6883", __FILE__), - m_cpu_tag(NULL), - m_cpu_space_ref(AS_PROGRAM), - m_read_res(*this), - m_space_0000(*this), - m_space_8000(*this), - m_space_A000(*this), - m_space_C000(*this), - m_space_FF00(*this), - m_space_FF20(*this), - m_space_FF40(*this), - m_space_FF60(*this), - m_space_FFE0(*this) -{ - memset(m_banks, '\0', sizeof(m_banks)); -} - - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sam6883_device::device_start() -{ - // find the CPU - m_cpu = machine().device<cpu_device>(m_cpu_tag); - m_cpu_space = &m_cpu->space(m_cpu_space_ref); - - // resolve callbacks - m_read_res.resolve_safe(0); - - // install SAM handlers - m_cpu_space->install_read_handler(0xFFC0, 0xFFDF, 0, 0, read8_delegate(FUNC(sam6883_device::read), this)); - m_cpu_space->install_write_handler(0xFFC0, 0xFFDF, 0, 0, write8_delegate(FUNC(sam6883_device::write), this)); - - // save state support - save_item(NAME(m_sam_state)); - save_item(NAME(m_counter)); - save_item(NAME(m_counter_xdiv)); - save_item(NAME(m_counter_ydiv)); -} - - - -//------------------------------------------------- -// configure_bank - bank configuration -//------------------------------------------------- - -void sam6883_device::configure_bank(int bank, UINT8 *memory, UINT32 memory_size, bool is_read_only) -{ - configure_bank(bank, memory, memory_size, is_read_only, read8_delegate(), write8_delegate()); -} - - - -//------------------------------------------------- -// configure_bank - bank configuration -//------------------------------------------------- - -void sam6883_device::configure_bank(int bank, read8_delegate rhandler, write8_delegate whandler) -{ - configure_bank(bank, NULL, 0, false, rhandler, whandler); -} - - - -//------------------------------------------------- -// configure_bank - bank configuration -//------------------------------------------------- - -void sam6883_device::configure_bank(int bank, UINT8 *memory, UINT32 memory_size, bool is_read_only, read8_delegate rhandler, write8_delegate whandler) -{ - assert((bank >= 0) && (bank < ARRAY_LENGTH(m_banks))); - m_banks[bank].m_memory = memory; - m_banks[bank].m_memory_size = memory_size; - m_banks[bank].m_memory_read_only = is_read_only; - m_banks[bank].m_rhandler = rhandler; - m_banks[bank].m_whandler = whandler; - - /* if we're configuring a bank that never changes, update it now */ - switch(bank) - { - case 4: - m_space_FF00.point(&m_banks[4], 0x0000, 0); - break; - case 5: - m_space_FF20.point(&m_banks[5], 0x0000, 0); - break; - case 6: - m_space_FF40.point(&m_banks[6], 0x0000, 0); - break; - case 7: - m_space_FF60.point(&m_banks[7], 0x0000, 0); - break; - case 2: - m_space_FFE0.point(&m_banks[2], 0x1FE0, 0); - break; - } -} - - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sam6883_device::device_reset() -{ - m_counter = 0; - m_counter_xdiv = 0; - m_counter_ydiv = 0; - m_sam_state = 0x0000; - update_state(); -} - - - -//------------------------------------------------- -// device_post_load - device-specific post load -//------------------------------------------------- - -void sam6883_device::device_post_load() -{ - device_t::device_post_load(); - update_state(); -} - - - -//------------------------------------------------- -// update_state -//------------------------------------------------- - -void sam6883_device::update_state(void) -{ - update_memory(); - update_cpu_clock(); -} - - - -//------------------------------------------------- -// update_memory -//------------------------------------------------- - -void sam6883_device::update_memory(void) -{ - // Memory size - allowed restricting memory accesses to something less than - // 32k - // - // This was a SAM switch that occupied 4 addresses: - // - // $FFDD (set) R1 - // $FFDC (clear) R1 - // $FFDB (set) R0 - // $FFDA (clear) R0 - // - // R1:R0 formed the following states: - // 00 - 4k - // 01 - 16k - // 10 - 64k - // 11 - static RAM (??) - // - // If something less than 64k was set, the low RAM would be smaller and - // mirror the other parts of the RAM - // - // TODO: Find out what "static RAM" is - // TODO: This should affect _all_ memory accesses, not just video ram - // TODO: Verify that the CoCo 3 ignored this - - // for now, lets assume that the caller is nice and made m_memory_size - // a power of two - UINT16 ram_mask = (UINT16) m_banks[0].m_memory_size - 1; - - // switch depending on the M1/M0 variables - bool setup_rom = true; - switch(m_sam_state & (SAM_STATE_M1|SAM_STATE_M0)) - { - case 0: - // 4K mode - m_space_0000.point(&m_banks[0], 0x0000, ram_mask); - m_counter_mask = 0x0FFF; - m_counter_or = 0x0000; - break; - - case SAM_STATE_M0: - // 16K mode - m_space_0000.point(&m_banks[0], 0x0000, ram_mask); - m_counter_mask = 0x3FFF; - m_counter_or = 0x0000; - break; - - case SAM_STATE_M1: - case SAM_STATE_M1|SAM_STATE_M0: - // 64k mode - if (m_sam_state & SAM_STATE_TY) - { - // full 64k RAM - m_space_0000.point(&m_banks[0], 0x0000, ram_mask); - m_space_8000.point(&m_banks[0], 0x8000, 0); - m_space_A000.point(&m_banks[0], 0xA000, 0); - m_space_C000.point(&m_banks[0], 0xC000, 0); - m_counter_mask = 0xFFFF; - m_counter_or = 0x0000; - setup_rom = false; - } - else - { - // ROM/RAM - UINT16 ram_base = (m_sam_state & SAM_STATE_P1) ? 0x8000 : 0x0000; - m_space_0000.point(&m_banks[0], ram_base, ram_mask); - m_counter_mask = 0x7FFF; - m_counter_or = ram_base; - } - break; - } - - if (setup_rom) - { - m_space_8000.point(&m_banks[1], m_banks[1].m_memory_offset, 0); - m_space_A000.point(&m_banks[2], m_banks[2].m_memory_offset, 0); - m_space_C000.point(&m_banks[3], m_banks[3].m_memory_offset, 0); - } - - // update $FFE0-$FFFF - m_space_FFE0.point(&m_banks[2], m_banks[2].m_memory_offset + 0x1FE0, 0); -} - - - -//------------------------------------------------- -// update_cpu_clock - adjusts the speed of the CPU -// clock -//------------------------------------------------- - -void sam6883_friend_device::update_cpu_clock(void) -{ - // The infamous speed up poke. - // - // This was a SAM switch that occupied 4 addresses: - // - // $FFD9 (set) R1 - // $FFD8 (clear) R1 - // $FFD7 (set) R0 - // $FFD6 (clear) R0 - // - // R1:R0 formed the following states: - // 00 - slow 0.89 MHz - // 01 - dual speed ??? - // 1x - fast 1.78 MHz - // - // R1 controlled whether the video addressing was speeded up and R0 - // did the same for the CPU. On pre-CoCo 3 machines, setting R1 caused - // the screen to display garbage because the M6847 could not display - // fast enough. - // - // TODO: Make the overclock more accurate. In dual speed, ROM was a fast - // access but RAM was not. I don't know how to simulate this. - - int speed = (m_sam_state & (SAM_STATE_R1|SAM_STATE_R0)) / SAM_STATE_R0; - - // the line below is weird because we are not strictly emulating the M6809E with emphasis on the 'E' - m_cpu->set_clock_scale(speed ? 2 : 1); -} - - - -//------------------------------------------------- -// set_bank_offset -//------------------------------------------------- - -void sam6883_device::set_bank_offset(int bank, offs_t offset) -{ - if (m_banks[bank].m_memory_offset != offset) - { - m_banks[bank].m_memory_offset = offset; - update_memory(); - } -} - - - -//------------------------------------------------- -// read -//------------------------------------------------- - -READ8_MEMBER( sam6883_device::read ) -{ - return 0; -} - - - -//------------------------------------------------- -// write -//------------------------------------------------- - -WRITE8_MEMBER( sam6883_device::write ) -{ - /* alter the SAM state */ - UINT16 xorval = alter_sam_state(offset); - - /* based on the mask, apply effects */ - if (xorval & (SAM_STATE_TY|SAM_STATE_M1|SAM_STATE_M0|SAM_STATE_P1)) - update_memory(); - if (xorval & (SAM_STATE_R1|SAM_STATE_R0)) - update_cpu_clock(); -} - - - -//------------------------------------------------- -// horizontal_sync -//------------------------------------------------- - -void sam6883_device::horizontal_sync(void) -{ - bool carry; - - // When horizontal sync occurs, bits B1-B3 or B1-B4 may be cleared (except in DMA mode). The catch - // is that the SAM's counter is a chain of flip-flops. Clearing the counter can cause carries to - // occur just as they can when the counter is bumped. - // - // This is critical in getting certain semigraphics modes to work correctly. Guardian uses this - // mode (see bug #1153). Special thanks to Ciaran Anscomb and Phill Harvey-Smith for figuring this - // out - switch((m_sam_state & (SAM_STATE_V2|SAM_STATE_V1|SAM_STATE_V0)) / SAM_STATE_V0) - { - case 0x01: - case 0x03: - case 0x05: - /* these SAM modes clear bits B1-B3 */ - carry = (m_counter & 0x0008) ? true : false; - m_counter &= ~0x000F; - if (carry) - counter_carry_bit3(); - break; - - case 0x00: - case 0x02: - case 0x04: - case 0x06: - /* clear bits B1-B4 */ - carry = (m_counter & 0x0010) ? true : false; - m_counter &= ~0x001F; - if (carry) - counter_carry_bit4(); - break; - - case 0x07: - /* DMA mode - do nothing */ - break; - - default: - fatalerror("Should not get here\n"); - } -} - - - -//------------------------------------------------- -// hs_w -//------------------------------------------------- - -WRITE_LINE_MEMBER( sam6883_device::hs_w ) -{ - if (state) - { - horizontal_sync(); - } -} - - - -//------------------------------------------------- -// sam_space::ctor -//------------------------------------------------- - -template<UINT16 _addrstart, UINT16 _addrend> -sam6883_device::sam_space<_addrstart, _addrend>::sam_space(sam6883_device &owner) - : m_owner(owner) -{ - m_read_bank = NULL; - m_write_bank = NULL; - m_mask = 0; -} - - - -//------------------------------------------------- -// sam_space::cpu_space -//------------------------------------------------- - -template<UINT16 _addrstart, UINT16 _addrend> -address_space &sam6883_device::sam_space<_addrstart, _addrend>::cpu_space() const -{ - assert(m_owner.m_cpu_space != NULL); - return *m_owner.m_cpu_space; -} - - - -//------------------------------------------------- -// sam_space::point -//------------------------------------------------- - -template<UINT16 _addrstart, UINT16 _addrend> -void sam6883_device::sam_space<_addrstart, _addrend>::point(const sam_bank *bank, UINT16 offset, UINT16 mask) -{ - if (LOG_SAM) - { - logerror("sam6883_device::sam_space::point(): addrstart=0x%04X addrend=0x%04X offset=0x%04X mask=0x%04X bank->m_memory=0x%p bank->m_memory_read_only=%s\n", - (unsigned) _addrstart, - (unsigned) _addrend, - (unsigned) offset, - (unsigned) mask, - bank->m_memory, - bank->m_memory_read_only ? "true" : "false"); - } - - point_specific_bank(bank, offset, mask, m_read_bank, _addrstart, _addrend, false); - point_specific_bank(bank, offset, mask, m_write_bank, _addrstart, _addrend, true); -} - - - -//------------------------------------------------- -// sam_space::point_specific_bank -//------------------------------------------------- -template<UINT16 _addrstart, UINT16 _addrend> -void sam6883_device::sam_space<_addrstart, _addrend>::point_specific_bank(const sam_bank *bank, UINT16 offset, UINT16 mask, memory_bank *&memory_bank, INT32 addrstart, INT32 addrend, bool is_write) -{ - char buffer[16]; - - if (bank->m_memory != NULL) - { - // normalize offset - if (mask != 0) - offset &= mask; - - // this bank is a memory bank - first ensure that we have a bank - if (!memory_bank || !memory_bank->matches_exactly(addrstart, addrend) || (mask != m_mask)) - { - // name the bank - snprintf(buffer, ARRAY_LENGTH(buffer), "bank%04X_%c", addrstart, is_write ? 'w' : 'r'); - - // install it - if (is_write) - cpu_space().install_write_bank(addrstart, addrend, mask, 0, buffer); - else - cpu_space().install_read_bank(addrstart, addrend, mask, 0, buffer); - m_mask = mask; - - // and get it - memory_bank = cpu_space().device().owner()->membank(buffer); - } - - // point the bank - if (memory_bank != NULL) - { - if (is_write && bank->m_memory_read_only) - memory_bank->set_base(m_owner.m_dummy); - else - memory_bank->set_base(bank->m_memory + offset); - } - } - else - { - // this bank uses handlers - assert((offset == 0) && (mask == 0)); // changes to the offset are not supported - - if (is_write) - { - if (!bank->m_whandler.isnull()) - cpu_space().install_write_handler(addrstart, addrend, 0, 0, bank->m_whandler); - } - else - { - if (!bank->m_rhandler.isnull()) - cpu_space().install_read_handler(addrstart, addrend, 0, 0, bank->m_rhandler); - } - } -} |