diff options
Diffstat (limited to 'libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6526/mos6526.cpp')
-rw-r--r-- | libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6526/mos6526.cpp | 322 |
1 files changed, 0 insertions, 322 deletions
diff --git a/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6526/mos6526.cpp b/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6526/mos6526.cpp deleted file mode 100644 index 32b6f1f2..00000000 --- a/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6526/mos6526.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/*************************************************************************** - mos6526.cpp - CIA Timer - ------------------- - begin : Wed Jun 7 2000 - copyright : (C) 2000 by Simon White - email : s_a_white@email.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ -/*************************************************************************** - * $Log: mos6526.cpp,v $ - * Revision 1.10 2002/12/16 22:12:24 s_a_white - * Simulate serial input from data port A to prevent kernel lockups. - * - * Revision 1.9 2002/11/20 22:50:27 s_a_white - * Reload count when timers are stopped - * - * Revision 1.8 2002/10/02 19:49:21 s_a_white - * Revert previous change as was incorrect. - * - * Revision 1.7 2002/09/11 22:30:47 s_a_white - * Counter interval writes now go to a new register call prescaler. This is - * copied to the timer latch/counter as appropriate. - * - * Revision 1.6 2002/09/09 22:49:06 s_a_white - * Proper idr clear if interrupt was only internally pending. - * - * Revision 1.5 2002/07/20 08:34:52 s_a_white - * Remove unnecessary and pointless conts. - * - * Revision 1.4 2002/03/03 22:04:08 s_a_white - * Tidy. - * - * Revision 1.3 2001/07/14 13:03:33 s_a_white - * Now uses new component classes and event generation. - * - * Revision 1.2 2001/03/23 23:21:38 s_a_white - * Removed redundant reset funtion. Timer b now gets initialised properly. - * Switch case now allows write/read from timer b. - * - * Revision 1.1 2001/03/21 22:41:45 s_a_white - * Non faked CIA emulation with NMI support. Removal of Hacked VIC support - * off CIA timer. - * - * Revision 1.8 2001/03/09 23:44:30 s_a_white - * Integrated more 6526 features. All timer modes and interrupts correctly - * supported. - * - * Revision 1.7 2001/02/21 22:07:10 s_a_white - * Prevent re-triggering of interrupt if it's already active. - * - * Revision 1.6 2001/02/13 21:00:01 s_a_white - * Support for real interrupts. - * - * Revision 1.4 2000/12/11 18:52:12 s_a_white - * Conversion to AC99 - * - ***************************************************************************/ - -#include "sidendian.h" -#include "mos6526.h" - -enum -{ - INTERRUPT_TA = 1 << 0, - INTERRUPT_TB = 1 << 1, - INTERRUPT_ALARM = 1 << 2, - INTERRUPT_SP = 1 << 3, - INTERRUPT_FLAG = 1 << 4, - INTERRUPT_REQUEST = 1 << 7 -}; - -const char *MOS6526::credit = -{ // Optional information - "*MOS6526 (CIA) Emulation:\0" - "\tCopyright (C) 2001 Simon White <sidplay2@email.com>\0" -}; - - -MOS6526::MOS6526 (EventContext *context) -:idr(0), - event_context(*context), - event_ta(this), - event_tb(this) -{ - reset (); -} - -void MOS6526::reset (void) -{ - ta = ta_latch = 0xffff; - tb = tb_latch = 0xffff; - cra = crb = 0; - // Clear off any IRQs - trigger (0); - cnt_high = true; - icr = idr = 0; - m_accessClk = 0; - dpa = 0xf0; -} - -uint8_t MOS6526::read (uint_least8_t addr) -{ - event_clock_t cycles; - if (addr > 0x0f) return 0; - - cycles = event_context.getTime (m_accessClk); - m_accessClk += cycles; - - // Sync up timers - if ((cra & 0x21) == 0x01) - ta -= cycles; - if ((crb & 0x61) == 0x01) - tb -= cycles; - - switch (addr) - { - case 0x0: // Simulate a serial port - dpa = ((dpa << 1) | (dpa >> 7)) & 0xff; - if (dpa & 0x80) - return 0xc0; - return 0; - case 0x4: return endian_16lo8 (ta); - case 0x5: return endian_16hi8 (ta); - case 0x6: return endian_16lo8 (tb); - case 0x7: return endian_16hi8 (tb); - - case 0xd: - { // Clear IRQs, and return interrupt - // data register - uint8_t ret = idr; - trigger (0); - return ret; - } - - case 0x0e: return cra; - case 0x0f: return crb; - default: return regs[addr]; - } -} - -void MOS6526::write (uint_least8_t addr, uint8_t data) -{ - event_clock_t cycles; - if (addr > 0x0f) return; - - regs[addr] = data; - cycles = event_context.getTime (m_accessClk); - m_accessClk += cycles; - - // Sync up timers - if ((cra & 0x21) == 0x01) - ta -= cycles; - if ((crb & 0x61) == 0x01) - tb -= cycles; - - switch (addr) - { - case 0x4: endian_16lo8 (ta_latch, data); break; - case 0x5: - endian_16hi8 (ta_latch, data); - if (!(cra & 0x01)) // Reload timer if stopped - ta = ta_latch; - break; - - case 0x6: endian_16lo8 (tb_latch, data); break; - case 0x7: - endian_16hi8 (tb_latch, data); - if (!(crb & 0x01)) // Reload timer if stopped - tb = tb_latch; - break; - - case 0xd: - if (data & 0x80) - icr |= data & 0x1f; - else - icr &= ~data; - trigger (idr); - break; - - case 0x0e: - // Check for forced load - cra = data; - if (data & 0x10) - { - cra &= (~0x10); - ta = ta_latch; - } - - if ((data & 0x21) == 0x01) - { // Active - event_context.schedule (&event_ta, (event_clock_t) ta + 1); - } else - { // Inactive - ta = ta_latch; - event_context.cancel (&event_ta); - } - break; - - case 0x0f: - // Check for forced load - crb = data; - if (data & 0x10) - { - crb &= (~0x10); - tb = tb_latch; - } - - if ((data & 0x61) == 0x01) - { // Active - event_context.schedule (&event_tb, (event_clock_t) tb + 1); - } else - { // Inactive - tb = tb_latch; - event_context.cancel (&event_tb); - } - break; - - default: - break; - } -} - -void MOS6526::trigger (int irq) -{ - if (!irq) - { // Clear any requested IRQs - if (idr & INTERRUPT_REQUEST) - interrupt (false); - idr = 0; - return; - } - - idr |= irq; - if (icr & idr) - { - if (!(idr & INTERRUPT_REQUEST)) - { - idr |= INTERRUPT_REQUEST; - interrupt (true); - } - } -} - -void MOS6526::ta_event (void) -{ // Timer Modes - event_clock_t cycles; - uint8_t mode = cra & 0x21; - - if (mode == 0x21) - { - if (ta--) - return; - } - - cycles = event_context.getTime (m_accessClk); - m_accessClk += cycles; - - ta = ta_latch; - if (cra & 0x08) - { // one shot, stop timer A - cra &= (~0x01); - } else if (mode == 0x01) - { // Reset event - event_context.schedule (&event_ta, (event_clock_t) ta + 1); - } - trigger (INTERRUPT_TA); - - switch (crb & 0x61) - { - case 0x01: tb -= cycles; break; - case 0x41: - case 0x61: - tb_event (); - break; - } -} - -void MOS6526::tb_event (void) -{ // Timer Modes - uint8_t mode = crb & 0x61; - switch (mode) - { - case 0x01: - break; - - case 0x21: - case 0x41: - if (tb--) - return; - break; - - case 0x61: - if (cnt_high) - { - if (tb--) - return; - } - break; - - default: - return; - } - - m_accessClk = event_context.getTime (); - tb = tb_latch; - if (crb & 0x08) - { // one shot, stop timer A - crb &= (~0x01); - } else if (mode == 0x01) - { // Reset event - event_context.schedule (&event_tb, (event_clock_t) tb + 1); - } - trigger (INTERRUPT_TB); -} |