|
|
1.1 root 1: /*
2: * UAE - The Unusable Amiga Emulator
3: *
4: * CIA chip support v0.1
5: * v0.0: 950301
6: * stubs
7: * v0.1: 950304
8: * hopefully all the timer functionality is implemented correctly
9: *
10: * (c) 1995 Bernd Schmidt
11: */
12:
13: #include <iostream.h>
14: #include <iomanip.h>
15:
16: #include "amiga.h"
17: #include "memory.h"
18: #include "disk.h"
19:
20: static UBYTE ciaaicr,ciaaimask,ciabicr,ciabimask;
21: static UBYTE ciaacra,ciaacrb,ciabcra,ciabcrb;
22: static UWORD ciaata,ciaatb,ciabta,ciabtb;
23: static UWORD ciaala,ciaalb,ciabla,ciablb;
24: static ULONG ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
25: static bool ciaatlatch,ciabtlatch;
26: static UBYTE ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr;
27: static UBYTE ciabpra,ciabprb,ciabdra,ciabdrb,ciabsdr;
28: static int div10,hsync,vsync;
29:
30: static void setclr(UBYTE &p, UBYTE val)
31: {
32: cout << "setclr\n";
33: if (val & 0x80) {
34: p |= val & 0x7F;
35: } else {
36: p &= ~val;
37: }
38: }
39:
40: static void RethinkICRA()
41: {
42: if (ciaaimask & ciaaicr) {
43: ciaaicr |= 0x80;
44: mem.put_word(0xDFF09C,0x8008);
45: cout << "CIA A int\n";
46: } else {
47: ciaaicr &= 0x7F;
48: mem.put_word(0xDFF09C,0x0008);
49: }
50: }
51:
52: static void RethinkICRB()
53: {
54: if (ciabimask & ciabicr) {
55: ciabicr |= 0x80;
56: mem.put_word(0xDFF09C,0xA000);
57: cout << "CIA B int\n";
58: } else {
59: ciabicr &= 0x7F;
60: mem.put_word(0xDFF09C,0x2000);
61: }
62: }
63:
64: UBYTE ReadCIAA(UWORD addr)
65: {
66: UBYTE tmp;
67:
68: switch(addr & 0xf){
69: case 0:
70: return (DISK_status() & 0x3C) | 0xc0; // no mouse
71: case 1:
72: return ciaaprb;
73: case 2:
74: return ciaadra;
75: case 3:
76: return ciaadrb;
77: case 4:
78: return ciaata & 0xff;
79: case 5:
80: return ciaata >> 8;
81: case 6:
82: return ciaatb & 0xff;
83: case 7:
84: return ciaatb >> 8;
85: case 8:
86: if (ciaatlatch) {
87: ciaatlatch = 0;
88: return ciaatol & 0xff;
89: } else return ciaatod & 0xff;
90: case 9:
91: if (ciaatlatch) return (ciaatol >> 8) & 0xff;
92: else return (ciaatod >> 8) & 0xff;
93: case 10:
94: ciaatlatch = 1; ciaatol = ciaatod; // ??? only if not already latched?
95: return (ciaatol >> 16) & 0xff;
96: case 12:
97: return ciaasdr;
98: case 13:
99: tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
100: case 14:
101: return ciaacra;
102: case 15:
103: return ciaacrb;
104: }
105: return 0;
106: }
107:
108: UBYTE ReadCIAB(UWORD addr)
109: {
110: UBYTE tmp;
111:
112: switch(addr & 0xf){
113: case 0:
114: return ciabpra;
115: case 1:
116: return ciabprb;
117: case 2:
118: return ciabdra;
119: case 3:
120: return ciabdrb;
121: case 4:
122: return ciabta & 0xff;
123: case 5:
124: return ciabta >> 8;
125: case 6:
126: return ciabtb & 0xff;
127: case 7:
128: return ciabtb >> 8;
129: case 8:
130: if (ciabtlatch) {
131: ciabtlatch = 0;
132: return ciabtol & 0xff;
133: } else return ciabtod & 0xff;
134: case 9:
135: if (ciabtlatch) return (ciabtol >> 8) & 0xff;
136: else return (ciabtod >> 8) & 0xff;
137: case 10:
138: ciabtlatch = 1; ciabtol = ciabtod;
139: return (ciabtol >> 16) & 0xff;
140: case 12:
141: return ciabsdr;
142: case 13:
143: tmp = ciabicr; ciabicr = 0; RethinkICRB(); return tmp;
144: case 14:
145: return ciabcra;
146: case 15:
147: return ciabcrb;
148: }
149: return 0;
150: }
151:
152: void WriteCIAA(UWORD addr,UBYTE val)
153: {
154: switch(addr & 0xf){
155: case 0:
156: ciaapra = (ciaapra & ~0x3) | (val & 0x3); break;
157: case 1:
158: ciaaprb = val; break;
159: case 2:
160: ciaadra = val; break;
161: case 3:
162: ciaadrb = val; break;
163: case 4:
164: ciaala = (ciaala & 0xff00) | val;
165: break;
166: case 5:
167: ciaala = (ciaala & 0xff) | (val << 8);
168: if ((ciaacra & 1) == 0) ciaata = ciaala;
169: if (ciaacra & 8) { ciaata = ciaala; ciaacra |= 1; }//??? load latch always?
170: break;
171: case 6:
172: ciaalb = (ciaalb & 0xff00) | val;
173: break;
174: case 7:
175: ciaalb = (ciaalb & 0xff) | (val << 8);
176: if ((ciaacrb & 1) == 0) ciaatb = ciaalb;
177: if (ciaacrb & 8) { ciaatb = ciaalb; ciaacrb |= 1; }
178: break;
179: case 8:
180: if (ciaacrb & 0x80){
181: ciaaalarm = (ciaaalarm & ~0xff) | val;
182: } else {
183: ciaatod = (ciaatod & ~0xff) | val;
184: }
185: break;
186: case 9:
187: if (ciaacrb & 0x80){
188: ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
189: } else {
190: ciaatod = (ciaatod & ~0xff00) | (val << 8);
191: }
192: break;
193: case 10:
194: if (ciaacrb & 0x80){
195: ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
196: } else {
197: ciaatod = (ciaatod & ~0xff0000) | (val << 16);
198: }
199: break;
200: case 12:
201: ciaasdr = val; break;
202: case 13:
203: setclr(ciaaimask,val); break; // ??? call RethinkICR() ?
204: case 14:
205: ciaacra = val;
206: if (ciaacra & 0x10){
207: ciaacra &= ~0x10;
208: ciaata = ciaala;
209: }
210: cout << "CIAACRA write" << val << "\n";
211: break;
212: case 15:
213: ciaacrb = val;
214: if (ciaacrb & 0x10){
215: ciaacrb &= ~0x10;
216: ciaatb = ciaalb;
217: }
218: cout << "CIAACRB write" << val << "\n";
219: break;
220: }
221: }
222:
223: void WriteCIAB(UWORD addr,UBYTE val)
224: {
225: switch(addr & 0xf){
226: case 0:
227: ciabpra = (ciabpra & ~0x3) | (val & 0x3); break;
228: case 1:
229: ciabprb = val; DISK_select(val); break;
230: case 2:
231: ciabdra = val; break;
232: case 3:
233: ciabdrb = val; break;
234: case 4:
235: ciabla = (ciabla & 0xff00) | val;
236: break;
237: case 5:
238: ciabla = (ciabla & 0xff) | (val << 8);
239: if ((ciabcra & 1) == 0) ciabta = ciabla;
240: if (ciabcra & 8) { ciabta = ciabla; ciabcra |= 1; }
241: break;
242: case 6:
243: ciablb = (ciablb & 0xff00) | val;
244: break;
245: case 7:
246: ciablb = (ciablb & 0xff) | (val << 8);
247: if ((ciabcrb & 1) == 0) ciabtb = ciablb;
248: if (ciabcrb & 8) { ciabtb = ciablb; ciabcrb |= 1; }
249: break;
250: case 8:
251: if (ciabcrb & 0x80){
252: ciabalarm = (ciabalarm & ~0xff) | val;
253: } else {
254: ciabtod = (ciabtod & ~0xff) | val;
255: }
256: break;
257: case 9:
258: if (ciabcrb & 0x80){
259: ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
260: } else {
261: ciabtod = (ciabtod & ~0xff00) | (val << 8);
262: }
263: break;
264: case 10:
265: if (ciabcrb & 0x80){
266: ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
267: } else {
268: ciabtod = (ciabtod & ~0xff0000) | (val << 16);
269: }
270: break;
271: case 12:
272: ciabsdr = val; break;
273: case 13:
274: setclr(ciabimask,val); break;
275: case 14:
276: ciabcra = val;
277: if (ciabcra & 0x10){
278: ciabcra &= ~0x10;
279: ciabta = ciabla;
280: }
281: break;
282: cout << "CIABCRA write" << val << "\n";
283: case 15:
284: ciabcrb = val;
285: if (ciabcrb & 0x10){
286: ciabcrb &= ~0x10;
287: ciabtb = ciablb;
288: }
289: break;
290: cout << "CIBACRB write" << val << "\n";
291: }
292: }
293:
294: void CIA_reset()
295: {
296: ciaatlatch = ciabtlatch = 0;
297: ciaatod = ciabtod = 0;
298: ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
299: ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; // outmode = toggle;
300: div10 = 0; hsync = vsync = 0;
301: }
302:
303: void CIA_hsync() { hsync = 1; }
304: void CIA_vsync() { vsync = 1; }
305:
306: void CIA_cycle()
307: {
308: int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
309: //int foo = ciaacra | ciaacrb | ciabcra | ciabcrb;
310:
311: if (++div10 > 9) {
312: // if (foo & 1) cout << "CIA is ON: ICRs "<< hex << (int)ciaaimask << " " << (int)ciabimask << "!\n";
313: div10 = 0;
314: // CIA A timers
315: if ((ciaacra & 0x21) == 0x01) {
316: if (ciaata-- == 0) {
317: aovfla = 1;
318: if ((ciaacrb & 0x61) == 0x41) {
319: if (ciaatb-- == 0) aovflb = 1;
320: }
321: }
322: }
323: if ((ciaacrb & 0x61) == 0x01) {
324: if (ciaatb-- == 0) {
325: aovflb = 1;
326: }
327: }
328: // CIA B timers
329: if ((ciabcra & 0x21) == 0x01) {
330: if (ciabta-- == 0) {
331: bovfla = 1;
332: if ((ciabcrb & 0x61) == 0x41) {
333: if (ciabtb-- == 0) bovflb = 1;
334: }
335: }
336: }
337: if ((ciabcrb & 0x61) == 0x01) {
338: if (ciabtb-- == 0) {
339: bovflb = 1;
340: }
341: }
342: if (aovfla) {
343: ciaaicr |= 1; RethinkICRA();
344: ciaata = ciaala;
345: if (ciaacra & 0x8) ciaacra &= ~1;
346: }
347: if (aovflb) {
348: ciaaicr |= 2; RethinkICRA();
349: ciaatb = ciaalb;
350: if (ciaacrb & 0x8) ciaacrb &= ~1;
351: }
352: if (bovfla) {
353: ciabicr |= 1; RethinkICRB();
354: ciabta = ciabla;
355: if (ciabcra & 0x8) ciabcra &= ~1;
356: }
357: if (bovflb) {
358: ciabicr |= 2; RethinkICRA();
359: ciabtb = ciablb;
360: if (ciabcrb & 0x8) ciabcrb &= ~1;
361: }
362: }
363: if (hsync){
364: hsync = 0;
365: ciabtod++;
366: ciabtod &= 0xFFFFFF;
367: if (ciabtod == ciabalarm) {
368: ciabicr |= 4; RethinkICRB();
369: }
370: }
371: if (vsync){
372: vsync = 0;
373: ciaatod++;
374: ciaatod &= 0xFFFFFF;
375: if (ciaatod == ciaaalarm) {
376: ciaaicr |= 4; RethinkICRA();
377: }
378: }
379:
380: }
381:
382: void dumpcia()
383: {
384: cout << hex << setw(2);
385: cout << "A: CRA: " << (int)ciaacra << " CRB: " <<(int)ciaacrb << "IMASK: " <<
386: (int)ciaaimask << " TOD: " << ciaatod << (ciaatlatch ? " latched" : "") <<
387: " TA: " << ciaata << " TB:" << ciaatb << "\n";
388: cout << "B: CRA: " << (int)ciabcra << " CRB: " <<(int)ciabcrb << "IMASK: " <<
389: (int)ciabimask << " TOD: " << ciabtod << (ciabtlatch ? " latched" : "") <<
390: " TA:" << ciabta << " TB:" << ciabtb << "\n";
391: }
392:
393: UWORD cia64k::wget(UWORD addr)
394: {
395: return bget(addr+1);
396: }
397:
398: UBYTE cia64k::bget(UWORD addr)
399: {
400: // cout << "CIA read at " << addr << "\n";
401: if ((addr & 0xF0FF) == 0xE001)
402: return ReadCIAA((addr & 0xF00) >> 8);
403: if ((addr & 0xF0FF) == 0xD000)
404: return ReadCIAB((addr & 0xF00) >> 8);
405: return 0;
406: }
407:
408: void cia64k::wput(UWORD addr,UWORD value)
409: {
410: bput(addr+1,value);
411: }
412:
413: void cia64k::bput(UWORD addr,UBYTE value)
414: {
415: // cout << "CIA write " << (int)value << " at " << addr << "\n";
416: if ((addr & 0xF0FF) == 0xE001)
417: WriteCIAA((addr & 0xF00) >> 8,value);
418: if ((addr & 0xF0FF) == 0xD000)
419: WriteCIAB((addr & 0xF00) >> 8,value);
420: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.