]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/c64/mem.c
8e00bec4bb9b89602b537936c38e566b06f888a8
[plan9front.git] / sys / src / games / c64 / mem.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <emu.h>
5 #include "dat.h"
6 #include "fns.h"
7
8 u8int pla;
9 u8int ram[65536], krom[8192], brom[8192], crom[4096], cart[16384], cram[1024];
10 u8int reg[47];
11 u16int vicbank;
12 u8int cia[32];
13 u16int timer[4], timrel[4];
14
15 enum {
16         TIMEREN = 1,
17         TIMERUND = 2,
18         TIMERSTOP = 8,
19         TIMERASRC = 0x20,
20         TIMERBSRC = 0x60,
21         TIMERBSYS = 0,
22         TIMERBA = 0x40,
23 };
24
25 u8int 
26 ciaread(int n, u8int a)
27 {
28         u8int r;
29         int i;
30
31         switch(a){
32         case 0:
33                 return (cia[0] | ~cia[2]) & (~joys >> 5 | 0xe0);
34         case 1:
35                 if(!n){
36                         r = 0;
37                         for(i = 0; i < 8; i++)
38                                 if((cia[0] & 1<<i) == 0)
39                                         r |= keys >> 8 * i;
40                         return (cia[1] | ~cia[3]) & ~r & (~joys | 0xe0);
41                 }
42                 break;
43         case 4: return timer[n*2];
44         case 5: return timer[n*2] >> 8;
45         case 6: return timer[n*2+1];
46         case 7: return timer[n*2+1] >> 8;
47         case 13:
48                 if(n){
49                         r = nmi >> 4 & 0x1f | ((nmi & nmien & 0x1f0) != 0) << 7;
50                         nmi &= ~0x1f0;
51                         return r;
52                 }else{
53                         r = irq >> 4 & 0x1f | ((irq & irqen & 0x1f0) != 0) << 7;
54                         irq &= ~0x1f0;
55                         return r;
56                 }
57         }
58         return cia[n * 16 + a];
59 }
60
61 void
62 ciawrite(int n, u8int a, u8int v)
63 {
64         switch(a){
65         case 0:
66                 if(n)
67                         vicbank = (~v & 3) << 14;
68                 break;
69         case 4: timrel[n*2] = v | timrel[n*2] & 0xff00; break;
70         case 5: timrel[n*2] = v << 8 | timrel[n*2] & 0xff; break;
71         case 6: timrel[n*2+1] = v | timrel[n*2+1] & 0xff00; break;
72         case 7: timrel[n*2+1] = v << 8 | timrel[n*2+1] & 0xff; break;
73         case 13:
74                 if(n)
75                         if((v & 0x80) != 0)
76                                 nmien |= v << 4 & 0x1f0;
77                         else
78                                 nmien &= ~(v << 4 & 0x1f0);
79                 else
80                         if((v & 0x80) != 0)
81                                 irqen |= v << 4 & 0x1f0;
82                         else
83                                 irqen &= ~(v << 4 & 0x1f0);
84                 break;
85         case 14: case 15:
86                 if((v & 0x10) != 0){
87                         timer[n * 2 + (a & 1)] = timrel[n * 2 + (a & 1)];
88                         v &= ~0x10;
89                 }
90                 break;
91         }
92         cia[n * 16 + a] = v;
93 }
94
95 u8int
96 mioread(u16int a)
97 {
98         u8int b, v;
99
100         switch(a & 0xc00){
101         case 0:
102                 b = a & 63;
103                 switch(b){
104                 case CTRL1:
105                         return reg[b] & 0x7f | ppuy >> 1 & 0x80;
106                 case RASTER:
107                         return ppuy;
108                 case IRQLATCH:
109                         return irq & 0xf | (irq & irqen & 0xf) + 0x7f & 0x80;
110                 case IRQEN:
111                         return irqen & 0xf;
112                 case SPRSPR:
113                 case SPRBG:
114                         v = reg[b];
115                         reg[b] = 0;
116                         return v;
117                 }
118                 if(b >= 0x20)
119                         return reg[b] | 0xf0;
120                 if(b >= 47)
121                         return 0xff;
122                 return reg[b];
123         case 0x800:
124                 return cram[a & 0x3ff];
125         case 0xc00:
126                 if((a & 0x200) == 0)
127                         return ciaread(a >> 8 & 1, a & 0xf);
128         default:
129                 return 0xff;
130         }
131 }
132
133 void
134 miowrite(u16int a, u8int v)
135 {
136         u8int b;
137
138         switch(a & 0xc00){
139         case 0:
140                 b = a & 63;
141                 if(b >= 0x20)
142                         v &= 0xf;
143                 switch(b){
144                 case CTRL2: v |= 0xc0; break;
145                 case IRQLATCH:
146                         v |= 0xf0;
147                         irq &= ~(v & 0xf);
148                         break;
149                 case IRQEN:
150                         irqen = irqen & ~0xf | v & 0xf;
151                         v |= 0xf0;
152                         break;
153                 }
154                 if(b < 47)
155                         reg[b] = v;
156                 if(b == CTRL1 || b == CTRL2)
157                         bordset();
158                 return;
159         case 0x800:
160                 cram[a & 0x3ff] = v & 0xf;
161                 return;
162         case 0xc00:
163                 if((a & 0x200) == 0)
164                         ciawrite(a >> 8 & 1, a & 0xf, v);
165                 return;
166         }
167 }
168
169 void
170 tapestep(void)
171 {
172         static int tapectr;
173         static int idx;
174         
175         if((ram[1] & 1<<5) != 0)
176                 return;
177         if(tapectr == 0){
178                 if(idx >= tapelen){
179                         progress(0, 0);
180                         tapeplay = 0;
181                         idx = 0;
182                         return;
183                 }
184                 tapectr = tape[idx++] << 3;
185                 if(tapever == 1 && tapectr == 0){
186                         tapectr = tape[idx++];
187                         tapectr |= tape[idx++] << 8;
188                         tapectr |= tape[idx++] << 16;
189                 }
190                 progress(idx, tapelen);
191         }else{
192                 tapectr--;
193                 if(tapectr == 0)
194                         irq |= IRQFLAG;
195         }
196 }
197
198 void
199 timerstep(void)
200 {
201         int i, at;
202         u8int a, b;
203         u16int *t;
204         
205         for(i = 0; i < 2; i++){
206                 a = cia[i * 16 + 14];
207                 b = cia[i * 16 + 15];
208                 at = 0;
209                 t = &timer[2 * i];
210                 if((a & (TIMEREN|TIMERASRC)) == TIMEREN){
211                         t[0]--;
212                         if(t[0] == 0){
213                                 at = 1;
214                                 if(i)
215                                         nmi |= IRQTIMERA;
216                                 else
217                                         irq |= IRQTIMERA;
218                                 if((a & TIMERSTOP) != 0)
219                                         cia[i * 16 + 14] &= ~TIMEREN;
220                                 t[0] = timrel[2 * i];
221                         }
222                 }
223                 if((b & TIMEREN) != 0 && ((b & TIMERBSRC) == TIMERBSYS || (b & TIMERBSRC) == TIMERBA && at)){
224                         t[1]--;
225                         if(t[1] == 0){
226                                 if(i)
227                                         nmi |= IRQTIMERB;
228                                 else
229                                         irq |= IRQTIMERB;
230                                 if((b & TIMERSTOP) == 0)
231                                         cia[i * 16 + 15] &= ~TIMEREN;
232                                 t[1] = timrel[2 * i + 1];
233                         }
234                 }
235         }
236         if(tapeplay)
237                 tapestep();
238 }
239
240 void
241 io(void)
242 {
243         vicstep();
244         timerstep();
245 }
246
247 u8int
248 memread(u16int a)
249 {
250         io();
251         if(a == 1)
252                 return ram[1] & ~(1<<4) | (tapeplay ^ 1) << 4;
253         switch(a >> 12){
254         case 8: case 9:
255                 if((pla & (EXROM|GAME)) == EXROM || (pla & (EXROM|HIRAM|LORAM)) == (HIRAM|LORAM))
256                         return cart[a & 0x1fff];
257                 goto def;
258         case 10: case 11:
259                 if((pla & (GAME|HIRAM|LORAM)) == (GAME|HIRAM|LORAM))
260                         return brom[a & 0x1fff];
261                 if((pla & (EXROM|GAME|HIRAM)) == HIRAM)
262                         return cart[8192 + (a & 0x1fff)];
263                 goto def;
264         case 13:
265                 if((pla & (HIRAM|LORAM)) == 0 || pla == 1)
266                         goto def;
267                 if((pla & CHAREN) == 0 && (pla & (EXROM|GAME)) != EXROM)
268                         return crom[a & 0xfff];
269                 return mioread(a & 0xfff);
270         case 14: case 15:
271                 if((pla & (EXROM|GAME)) == EXROM)
272                         return cart[8192 + (a & 0x1fff)];
273                 if((pla & HIRAM) == HIRAM)
274                         return krom[a & 0x1fff];
275         def:
276         default:
277                 return ram[a];
278         }
279 }
280
281 void
282 memwrite(u16int a, u8int v)
283 {
284         if(a >> 12 == 13 && !((pla & (HIRAM|LORAM)) == 0 || pla == 1 || (pla & CHAREN) == 0 && (pla & (EXROM|GAME)) != EXROM)){
285                 miowrite(a & 0xfff, v);
286                 io();
287                 return;
288         }
289         ram[a] = v;
290         if(a == 1)
291                 pla = pla & ~7 | v & 7;
292         io();
293 }
294
295 u8int
296 vmemread(u16int a)
297 {
298         a |= vicbank;
299         if((a & 0x7000) == 0x1000)
300                 return crom[a & 0xfff];
301         return ram[a];
302 }
303
304 void
305 memreset(void)
306 {
307         pla = 0x1f;
308 }