diff --git a/pia.cpp b/pia.cpp index 6f4eb8e..584d14e 100644 --- a/pia.cpp +++ b/pia.cpp @@ -17,6 +17,8 @@ inline bool c2_low_to_high(uint8_t cr) { return cr & 0x10; } inline bool c2_high_to_low(uint8_t cr) { return !c2_low_to_high(cr); } +inline bool output_selected(uint8_t cr) { return cr & 0x04; } + void PIA::write(Memory::address a, uint8_t b) { #if defined(DEBUGGING) Serial.print(millis()); @@ -27,13 +29,13 @@ void PIA::write(Memory::address a, uint8_t b) { #endif switch(a % 4) { case 0: - write_porta(b); + output_selected(porta_cr)? write_porta(b): write_ddra(b); break; case 1: write_porta_cr(b); break; case 2: - write_portb(b); + output_selected(portb_cr)? write_portb(b): write_ddrb(b); break; case 3: write_portb_cr(b); @@ -49,11 +51,11 @@ uint8_t PIA::read(Memory::address a) { #endif switch (a % 4) { case 0: - return read_porta(); + return output_selected(porta_cr)? read_porta(): read_ddra(); case 1: return read_porta_cr(); case 2: - return read_portb(); + return output_selected(portb_cr)? read_portb(): read_ddrb(); case 3: return read_portb_cr(); } @@ -63,8 +65,10 @@ uint8_t PIA::read(Memory::address a) { void PIA::checkpoint(Stream &s) { s.write(portb_cr); s.write(portb); + s.write(ddrb); s.write(porta_cr); s.write(porta); + s.write(ddra); s.write(irq_b1); s.write(irq_b2); s.write(irq_a1); @@ -78,8 +82,10 @@ void PIA::checkpoint(Stream &s) { void PIA::restore(Stream &s) { portb_cr = s.read(); portb = s.read(); + ddrb = s.read(); porta_cr = s.read(); porta = s.read(); + ddra = s.read(); irq_b1 = s.read(); irq_b2 = s.read(); irq_a1 = s.read(); diff --git a/pia.h b/pia.h index 0916194..7aa9946 100644 --- a/pia.h +++ b/pia.h @@ -1,15 +1,16 @@ #ifndef __PIA_H__ #define __PIA_H__ +// Motorola 6820 / 6821 PIA // https://en.wikipedia.org/wiki/Peripheral_Interface_Adapter class PIA { public: - PIA(): portb(0), portb_cr(0), porta(0), porta_cr(0), + PIA(): portb(0), portb_cr(0), porta(0), porta_cr(0), ddrb(0), ddra(0), ca1(false), ca2(false), cb1(false), cb2(false), irq_a1(false), irq_a2(false), irq_b1(false), irq_b2(false) {} virtual void reset() { - portb = portb_cr = porta = porta_cr = 0; + portb = portb_cr = ddrb = porta = porta_cr = ddra = 0; irq_a1 = irq_a2 = irq_b1 = irq_b2 = ca1 = ca2 = cb1 = cb2 = false; } @@ -28,19 +29,23 @@ public: static const uint8_t IRQ2 = 0x40; protected: - // "device-side" operations (called from memory interface) + virtual uint8_t read_ddra() { return ddra; } virtual uint8_t read_porta() { irq_a1 = irq_a2 = false; return porta; } virtual uint8_t read_porta_cr(); + virtual uint8_t read_ddrb() { return ddrb; } virtual uint8_t read_portb() { irq_b1 = irq_b2 = false; return portb; } virtual uint8_t read_portb_cr(); + virtual void write_ddra(uint8_t b) { ddra = b; } virtual void write_porta(uint8_t b) { porta = b; } virtual void write_porta_cr(uint8_t b) { porta_cr = (b & 0x3f); } + virtual void write_ddrb(uint8_t b) { ddrb = b; } virtual void write_portb(uint8_t b) { portb = b; } virtual void write_portb_cr(uint8_t b) { portb_cr = (b & 0x3f); } private: - uint8_t portb_cr, portb, porta_cr, porta; + uint8_t porta_cr, porta, ddra; + uint8_t portb_cr, portb, ddrb; bool ca1, ca2, irq_a1, irq_a2; bool cb1, cb2, irq_b1, irq_b2; };