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