]> Shamusworld >> Repos - stargem2/blob - src/v6821.cpp
Finally fixed problems with demo mode.
[stargem2] / src / v6821.cpp
1 //
2 // Virtual 6821 Peripheral Interface Adapter (PIA) Emulator v1.0
3 //
4 // by James Hammons
5 // (C) 2022 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  12/27/2022  Created this file.  :-)
12
13 #include "v6821.h"
14
15 //#include "log.h"
16 //#include "v6809.h"
17
18 // A "1" bit in the DDR means that line is an output
19
20 V6821PIA::V6821PIA(): ddra(0), ddrb(0), pa(0), pb(0), cra(0), crb(0), ora(0), orb(0), ca1(false), ca2(false), cb1(false), cb2(false), irqa1(false), irqa2(false), irqb1(false), irqb2(false), irqaState(false), irqbState(false), IRQA(NULL), IRQB(NULL)
21 {
22 }
23
24 V6821PIA::V6821PIA(void (* a)(bool), void (*b)(bool)): ddra(0), ddrb(0), pa(0), pb(0), cra(0), crb(0), ora(0), orb(0), ca1(false), ca2(false), cb1(false), cb2(false), irqa1(false), irqa2(false), irqb1(false), irqb2(false), irqaState(false), irqbState(false), IRQA(a), IRQB(b)
25 {
26 }
27
28 void V6821PIA::Reset(void)
29 {
30 }
31
32 uint8_t V6821PIA::Read(uint8_t addr)
33 {
34         switch (addr & 0x03)
35         {
36         case 0:
37                 if (cra & 0x04)
38                 {
39                         // IRQ flags are implicitly cleared by a read
40                         irqa1 = irqa2 = false;
41                         HandleIRQs();
42
43                         return pa & ~ddra;
44                 }
45
46                 return ddra;
47
48         case 1:
49                 return cra | (irqa1 ? 0x80 : 0x00) | (irqa2 ? 0x40 : 0x00);
50
51         case 2:
52                 if (crb & 0x04)
53                 {
54                         // IRQ flags are implicitly cleared by a read
55                         irqb1 = irqb2 = false;
56                         HandleIRQs();
57
58                         return pb & ~ddrb;
59                 }
60
61                 return ddrb;
62
63         case 3:
64                 return crb | (irqb1 ? 0x80 : 0x00) | (irqb2 ? 0x40 : 0x00);
65         }
66
67         // This is only here to silence the the compiler...  :-/
68         return 0xFF;
69 }
70
71 void V6821PIA::Write(uint8_t addr, uint8_t data)
72 {
73         switch (addr & 0x03)
74         {
75         case 0:
76                 if (cra & 0x04)
77                         pa = data;
78                 else
79                         ddra = data;
80
81                 break;
82
83         case 1:
84                 cra = data & 0x3F; // Bits 6-7 are RO
85                 HandleIRQs();
86                 break;
87
88         case 2:
89                 if (crb & 0x04)
90                         pb = data;
91                 else
92                         ddrb = data;
93
94                 break;
95
96         case 3:
97                 crb = data & 0x3F; // Bits 6-7 are RO
98                 HandleIRQs();
99         }
100 }
101
102 void V6821PIA::CA1(bool state)
103 {
104         // Do nothing if nothing changed...
105         if (ca1 == state)
106                 return;
107
108         // Check if there's been a transition (bit 1 = lo to hi transition)
109         if ((state && (cra & 0x02)) || (!state && !(cra & 0x02)))
110         {
111                 irqa1 = true;
112                 HandleIRQs();
113         }
114
115         ca1 = state;
116 }
117
118 void V6821PIA::CA2(bool state)
119 {
120         ca2 = state;
121 }
122
123 void V6821PIA::CB1(bool state)
124 {
125         // Do nothing if nothing changed...
126         if (cb1 == state)
127                 return;
128
129         // Check if there's been a transition (bit 1 = lo to hi transition)
130         if ((state && (crb & 0x02)) || (!state && !(crb & 0x02)))
131         {
132                 irqb1 = true;
133                 HandleIRQs();
134         }
135
136         cb1 = state;
137 }
138
139 void V6821PIA::CB2(bool state)
140 {
141         cb2 = state;
142 }
143
144 void V6821PIA::HandleIRQs(void)
145 {
146         bool newState = (irqa1 && (cra & 0x01)) || (irqa2 && (cra & 0x08));
147
148         if (newState != irqaState)
149         {
150                 irqaState = newState;
151
152                 if (IRQA)
153                         IRQA(irqaState);
154         }
155
156         newState = (irqb1 && (crb & 0x01)) || (irqb2 && (crb & 0x08));
157
158         if (newState != irqbState)
159         {
160                 irqbState = newState;
161
162                 if (IRQB)
163                         IRQB(irqbState);
164         }
165 }