|
|
1.1.1.3 root 1: /*
1.1 root 2: * UAE - The Un*x Amiga Emulator
1.1.1.3 root 3: *
1.1 root 4: * CIA chip support
5: *
6: * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
1.1.1.3 root 7: * Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
1.1 root 8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12: #include <assert.h>
13:
14: #include "config.h"
15: #include "options.h"
1.1.1.12! root 16: #include "threaddep/thread.h"
1.1 root 17: #include "events.h"
18: #include "memory.h"
19: #include "custom.h"
20: #include "cia.h"
1.1.1.3 root 21: #include "serial.h"
1.1 root 22: #include "disk.h"
23: #include "xwin.h"
24: #include "keybuf.h"
25: #include "gui.h"
1.1.1.11 root 26: #include "savestate.h"
1.1 root 27:
1.1.1.10 root 28: #define DIV10 (5*CYCLE_UNIT) /* Yes, a bad identifier. */
1.1 root 29:
30: /* battclock stuff */
31: #define RTC_D_ADJ 8
32: #define RTC_D_IRQ 4
33: #define RTC_D_BUSY 2
34: #define RTC_D_HOLD 1
35: #define RTC_E_t1 8
36: #define RTC_E_t0 4
37: #define RTC_E_INTR 2
38: #define RTC_E_MASK 1
39: #define RTC_F_TEST 8
40: #define RTC_F_24_12 4
41: #define RTC_F_STOP 2
42: #define RTC_F_RSET 1
43:
1.1.1.3 root 44: static unsigned int clock_control_d = RTC_D_ADJ + RTC_D_HOLD;
45: static unsigned int clock_control_e = 0;
46: static unsigned int clock_control_f = RTC_F_24_12;
47:
1.1.1.11 root 48: unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask;
49: unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb;
1.1.1.10 root 50:
51: /* Values of the CIA timers. */
1.1.1.11 root 52: unsigned long ciaata, ciaatb, ciabta, ciabtb;
1.1.1.10 root 53: /* Computed by compute_passed_time. */
54: unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
55:
1.1.1.11 root 56: unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
57: int ciaatlatch, ciabtlatch;
1.1.1.3 root 58:
59: unsigned int ciabpra;
60:
61: unsigned int gui_ledstate;
62:
1.1.1.11 root 63: static unsigned long ciaala, ciaalb, ciabla, ciablb;
1.1.1.3 root 64: static int ciaatodon, ciabtodon;
1.1.1.11 root 65: static unsigned int ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr;
66: static unsigned int ciabprb, ciabdra, ciabdrb, ciabsdr;
1.1 root 67: static int div10;
1.1.1.2 root 68: static int kbstate, kback, ciaasdr_unread = 0;
1.1 root 69:
70: static int prtopen;
71: static FILE *prttmp;
72:
1.1.1.10 root 73: static void setclr (unsigned int *p, unsigned int val)
1.1 root 74: {
75: if (val & 0x80) {
76: *p |= val & 0x7F;
77: } else {
78: *p &= ~val;
79: }
80: }
81:
1.1.1.10 root 82: static void RethinkICRA (void)
1.1 root 83: {
84: if (ciaaimask & ciaaicr) {
85: ciaaicr |= 0x80;
1.1.1.11 root 86: INTREQ_0 (0x8008);
1.1 root 87: } else {
88: ciaaicr &= 0x7F;
89: /* custom_bank.wput(0xDFF09C,0x0008);*/
90: }
91: }
92:
1.1.1.10 root 93: static void RethinkICRB (void)
1.1 root 94: {
95: #if 0 /* ??? What's this then? */
96: if (ciabicr & 0x10) {
97: custom_bank.wput(0xDFF09C,0x9000);
98: }
99: #endif
100: if (ciabimask & ciabicr) {
101: ciabicr |= 0x80;
1.1.1.11 root 102: INTREQ_0 (0xA000);
1.1 root 103: } else {
104: ciabicr &= 0x7F;
105: /* custom_bank.wput(0xDFF09C,0x2000);*/
106: }
107: }
108:
1.1.1.11 root 109: void rethink_cias (void)
110: {
111: RethinkICRA ();
112: RethinkICRB ();
113: }
114:
1.1.1.10 root 115: /* Figure out how many CIA timer cycles have passed for each timer since the
116: last call of CIA_calctimers. */
1.1 root 117:
1.1.1.10 root 118: static void compute_passed_time (void)
1.1 root 119: {
1.1.1.10 root 120: unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
121: unsigned long int ciaclocks = ccount / DIV10;
122:
123: ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
124:
125: /* CIA A timers */
126: if ((ciaacra & 0x21) == 0x01) {
127: assert ((ciaata+1) >= ciaclocks);
128: ciaata_passed = ciaclocks;
129: }
130: if ((ciaacrb & 0x61) == 0x01) {
131: assert ((ciaatb+1) >= ciaclocks);
132: ciaatb_passed = ciaclocks;
133: }
134:
135: /* CIA B timers */
136: if ((ciabcra & 0x21) == 0x01) {
137: assert ((ciabta+1) >= ciaclocks);
138: ciabta_passed = ciaclocks;
139: }
140: if ((ciabcrb & 0x61) == 0x01) {
141: assert ((ciabtb+1) >= ciaclocks);
142: ciabtb_passed = ciaclocks;
143: }
144: }
145:
146: /* Called to advance all CIA timers to the current time. This expects that
147: one of the timer values will be modified, and CIA_calctimers will be called
148: in the same cycle. */
149:
150: static void CIA_update (void)
151: {
152: unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
1.1 root 153: unsigned long int ciaclocks = ccount / DIV10;
154:
155: int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
156:
157: div10 = ccount % DIV10;
1.1.1.3 root 158:
1.1 root 159: /* CIA A timers */
160: if ((ciaacra & 0x21) == 0x01) {
1.1.1.10 root 161: assert ((ciaata+1) >= ciaclocks);
1.1 root 162: if ((ciaata+1) == ciaclocks) {
163: aovfla = 1;
164: if ((ciaacrb & 0x61) == 0x41) {
1.1.1.3 root 165: if (ciaatb-- == 0) aovflb = 1;
1.1 root 166: }
1.1.1.3 root 167: }
1.1 root 168: ciaata -= ciaclocks;
169: }
170: if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10 root 171: assert ((ciaatb+1) >= ciaclocks);
1.1 root 172: if ((ciaatb+1) == ciaclocks) aovflb = 1;
173: ciaatb -= ciaclocks;
174: }
1.1.1.3 root 175:
1.1 root 176: /* CIA B timers */
177: if ((ciabcra & 0x21) == 0x01) {
1.1.1.10 root 178: assert ((ciabta+1) >= ciaclocks);
1.1 root 179: if ((ciabta+1) == ciaclocks) {
180: bovfla = 1;
181: if ((ciabcrb & 0x61) == 0x41) {
182: if (ciabtb-- == 0) bovflb = 1;
183: }
1.1.1.3 root 184: }
1.1 root 185: ciabta -= ciaclocks;
186: }
187: if ((ciabcrb & 0x61) == 0x01) {
188: assert ((ciabtb+1) >= ciaclocks);
189: if ((ciabtb+1) == ciaclocks) bovflb = 1;
190: ciabtb -= ciaclocks;
191: }
192: if (aovfla) {
193: ciaaicr |= 1; RethinkICRA();
194: ciaata = ciaala;
195: if (ciaacra & 0x8) ciaacra &= ~1;
196: }
197: if (aovflb) {
198: ciaaicr |= 2; RethinkICRA();
199: ciaatb = ciaalb;
200: if (ciaacrb & 0x8) ciaacrb &= ~1;
201: }
202: if (bovfla) {
203: ciabicr |= 1; RethinkICRB();
204: ciabta = ciabla;
205: if (ciabcra & 0x8) ciabcra &= ~1;
206: }
207: if (bovflb) {
208: ciabicr |= 2; RethinkICRB();
209: ciabtb = ciablb;
210: if (ciabcrb & 0x8) ciabcrb &= ~1;
211: }
212: }
213:
1.1.1.10 root 214: /* Call this only after CIA_update has been called in the same cycle. */
215:
216: static void CIA_calctimers (void)
1.1 root 217: {
1.1.1.10 root 218: long ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
1.1 root 219:
1.1.1.10 root 220: eventtab[ev_cia].oldcycles = get_cycles ();
1.1 root 221: if ((ciaacra & 0x21) == 0x01) {
1.1.1.10 root 222: ciaatimea = (DIV10 - div10) + DIV10 * ciaata;
1.1 root 223: }
224: if ((ciaacrb & 0x61) == 0x41) {
225: /* Timer B will not get any pulses if Timer A is off. */
226: if (ciaatimea >= 0) {
227: /* If Timer A is in one-shot mode, and Timer B needs more than
228: * one pulse, it will not underflow. */
229: if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
230: /* Otherwise, we can determine the time of the underflow. */
231: ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
232: }
233: }
234: }
235: if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10 root 236: ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb;
1.1 root 237: }
238:
239: if ((ciabcra & 0x21) == 0x01) {
1.1.1.10 root 240: ciabtimea = (DIV10 - div10) + DIV10 * ciabta;
1.1 root 241: }
242: if ((ciabcrb & 0x61) == 0x41) {
243: /* Timer B will not get any pulses if Timer A is off. */
244: if (ciabtimea >= 0) {
245: /* If Timer A is in one-shot mode, and Timer B needs more than
246: * one pulse, it will not underflow. */
247: if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
248: /* Otherwise, we can determine the time of the underflow. */
249: ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
250: }
251: }
252: }
253: if ((ciabcrb & 0x61) == 0x01) {
1.1.1.10 root 254: ciabtimeb = (DIV10 - div10) + DIV10 * ciabtb;
1.1 root 255: }
256: eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
257: || ciabtimea != -1 || ciabtimeb != -1);
258: if (eventtab[ev_cia].active) {
259: unsigned long int ciatime = ~0L;
260: if (ciaatimea != -1) ciatime = ciaatimea;
261: if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
262: if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
263: if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
1.1.1.10 root 264: eventtab[ev_cia].evtime = ciatime + get_cycles ();
1.1 root 265: }
266: events_schedule();
267: }
268:
1.1.1.10 root 269: void CIA_handler (void)
1.1 root 270: {
1.1.1.10 root 271: CIA_update ();
272: CIA_calctimers ();
1.1 root 273: }
274:
1.1.1.10 root 275: void cia_diskindex (void)
1.1 root 276: {
277: ciabicr |= 0x10;
278: RethinkICRB();
279: }
280:
1.1.1.10 root 281: void CIA_hsync_handler (void)
1.1 root 282: {
1.1.1.3 root 283: static unsigned int keytime = 0, sleepyhead = 0;
1.1 root 284:
285: if (ciabtodon)
286: ciabtod++;
287: ciabtod &= 0xFFFFFF;
288:
289: if (ciabtod == ciabalarm) {
290: ciabicr |= 4; RethinkICRB();
291: }
1.1.1.3 root 292:
293: /* check wether the serial port gets some data */
294: if (doreadser)
295: doreadser = SERDATS();
296:
1.1 root 297: if (keys_available() && kback && (++keytime & 15) == 0) {
1.1.1.3 root 298: /*
1.1.1.2 root 299: * This hack lets one possible ciaaicr cycle go by without any key
300: * being read, for every cycle in which a key is pulled out of the
301: * queue. If no hack is used, a lot of key events just get lost
302: * when you type fast. With a simple hack that waits for ciaasdr
303: * to be read before feeding it another, it will keep up until the
304: * queue gets about 14 characters ahead and then lose events, and
305: * the mouse pointer will freeze while typing is being taken in.
306: * With this hack, you can type 30 or 40 characters ahead with little
307: * or no lossage, and the mouse doesn't get stuck. The tradeoff is
308: * that the total slowness of typing appearing on screen is worse.
309: */
1.1.1.3 root 310: if (ciaasdr_unread == 2)
311: ciaasdr_unread = 0;
312: else if (ciaasdr_unread == 0) {
313: switch (kbstate) {
1.1.1.2 root 314: case 0:
1.1.1.3 root 315: ciaasdr = (uae_s8)~0xFB; /* aaarghh... stupid compiler */
316: kbstate++;
317: break;
1.1.1.2 root 318: case 1:
1.1.1.3 root 319: kbstate++;
320: ciaasdr = (uae_s8)~0xFD;
321: break;
1.1.1.2 root 322: case 2:
1.1.1.3 root 323: ciaasdr = ~get_next_key();
324: ciaasdr_unread = 1; /* interlock to prevent lost keystrokes */
325: break;
1.1.1.2 root 326: }
327: ciaaicr |= 8;
328: RethinkICRA();
329: sleepyhead = 0;
1.1.1.3 root 330: } else if (!(++sleepyhead & 15))
331: ciaasdr_unread = 0; /* give up on this key event after unread for a long time */
1.1 root 332: }
333: }
334:
1.1.1.10 root 335: void CIA_vsync_handler ()
1.1.1.3 root 336: {
337: if (ciaatodon)
1.1 root 338: ciaatod++;
339: ciaatod &= 0xFFFFFF;
340: if (ciaatod == ciaaalarm) {
341: ciaaicr |= 4; RethinkICRA();
342: }
1.1.1.3 root 343:
344: doreadser = 1;
345: serstat = -1;
346: serial_flush_buffer();
1.1 root 347: }
348:
1.1.1.10 root 349: static uae_u8 ReadCIAA (unsigned int addr)
1.1 root 350: {
1.1.1.3 root 351: unsigned int tmp;
352:
1.1.1.10 root 353: compute_passed_time ();
354:
355: switch (addr & 0xf) {
1.1.1.7 root 356: case 0:
1.1.1.3 root 357: if (currprefs.use_serial && (serstat < 0)) /* Only read status when needed */
358: serstat=serial_readstatus(); /* and only once per frame */
359:
1.1 root 360: tmp = (DISK_status() & 0x3C);
1.1.1.6 root 361: if ((JSEM_ISMOUSE (0, &currprefs) && !buttonstate[0])
362: || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1)))
1.1.1.3 root 363: tmp |= 0x40;
364: if (!(joy1button & 1))
365: tmp |= 0x80;
1.1 root 366: return tmp;
1.1.1.7 root 367: case 1:
368: /* Returning 0xFF is necessary for Tie Break - otherwise its joystick
369: code won't work. */
370: return prtopen ? ciaaprb : 0xFF;
371: case 2:
1.1 root 372: return ciaadra;
1.1.1.7 root 373: case 3:
1.1 root 374: return ciaadrb;
1.1.1.7 root 375: case 4:
1.1.1.10 root 376: return (ciaata - ciaata_passed) & 0xff;
1.1.1.7 root 377: case 5:
1.1.1.10 root 378: return (ciaata - ciaata_passed) >> 8;
1.1.1.7 root 379: case 6:
1.1.1.10 root 380: return (ciaatb - ciaatb_passed) & 0xff;
1.1.1.7 root 381: case 7:
1.1.1.10 root 382: return (ciaatb - ciaatb_passed) >> 8;
1.1.1.7 root 383: case 8:
1.1 root 384: if (ciaatlatch) {
385: ciaatlatch = 0;
386: return ciaatol & 0xff;
1.1.1.3 root 387: } else
388: return ciaatod & 0xff;
1.1.1.7 root 389: case 9:
1.1.1.3 root 390: if (ciaatlatch)
391: return (ciaatol >> 8) & 0xff;
392: else
393: return (ciaatod >> 8) & 0xff;
1.1.1.7 root 394: case 10:
1.1.1.3 root 395: ciaatlatch = 1;
396: ciaatol = ciaatod; /* ??? only if not already latched? */
1.1 root 397: return (ciaatol >> 16) & 0xff;
1.1.1.7 root 398: case 12:
1.1.1.3 root 399: if (ciaasdr == 1) ciaasdr_unread = 2;
1.1 root 400: return ciaasdr;
1.1.1.7 root 401: case 13:
1.1 root 402: tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
1.1.1.7 root 403: case 14:
1.1 root 404: return ciaacra;
1.1.1.7 root 405: case 15:
1.1 root 406: return ciaacrb;
407: }
408: return 0;
409: }
410:
1.1.1.10 root 411: static uae_u8 ReadCIAB (unsigned int addr)
1.1 root 412: {
1.1.1.3 root 413: unsigned int tmp;
414:
1.1.1.10 root 415: compute_passed_time ();
416:
417: switch (addr & 0xf) {
1.1.1.7 root 418: case 0:
1.1.1.3 root 419: if (currprefs.use_serial && serstat < 0) /* Only read status when needed */
420: serstat=serial_readstatus(); /* and only once per frame */
1.1.1.7 root 421: /* Returning some 1 bits is necessary for Tie Break - otherwise its joystick
422: code won't work. */
423: return ciabpra | (prtopen ? 0 : 3);
424: case 1:
1.1 root 425: return ciabprb;
1.1.1.7 root 426: case 2:
1.1 root 427: return ciabdra;
1.1.1.7 root 428: case 3:
1.1 root 429: return ciabdrb;
1.1.1.7 root 430: case 4:
1.1.1.10 root 431: return (ciabta - ciabta_passed) & 0xff;
1.1.1.7 root 432: case 5:
1.1.1.10 root 433: return (ciabta - ciabta_passed) >> 8;
1.1.1.7 root 434: case 6:
1.1.1.10 root 435: return (ciabtb - ciabtb_passed) & 0xff;
1.1.1.7 root 436: case 7:
1.1.1.10 root 437: return (ciabtb - ciabtb_passed) >> 8;
1.1.1.7 root 438: case 8:
1.1 root 439: if (ciabtlatch) {
440: ciabtlatch = 0;
441: return ciabtol & 0xff;
1.1.1.3 root 442: } else
443: return ciabtod & 0xff;
1.1.1.7 root 444: case 9:
1.1.1.3 root 445: if (ciabtlatch)
446: return (ciabtol >> 8) & 0xff;
447: else
448: return (ciabtod >> 8) & 0xff;
1.1.1.7 root 449: case 10:
1.1.1.3 root 450: ciabtlatch = 1;
451: ciabtol = ciabtod;
1.1 root 452: return (ciabtol >> 16) & 0xff;
1.1.1.7 root 453: case 12:
1.1 root 454: return ciabsdr;
1.1.1.7 root 455: case 13:
1.1 root 456: tmp = ciabicr; ciabicr = 0; RethinkICRB();
457: return tmp;
1.1.1.7 root 458: case 14:
1.1 root 459: return ciabcra;
1.1.1.7 root 460: case 15:
1.1 root 461: return ciabcrb;
462: }
463: return 0;
464: }
465:
1.1.1.10 root 466: static void WriteCIAA (uae_u16 addr,uae_u8 val)
1.1 root 467: {
1.1.1.3 root 468: int oldled, oldovl;
1.1.1.10 root 469: switch (addr & 0xf) {
1.1.1.7 root 470: case 0:
1.1.1.3 root 471: oldovl = ciaapra & 1;
1.1 root 472: oldled = ciaapra & 2;
1.1.1.11 root 473: ciaapra = (ciaapra & ~0x3) | (val & 0x3);
474: LED(ciaapra & 0x2);
1.1.1.3 root 475: gui_ledstate &= ~1;
476: gui_ledstate |= ((~ciaapra & 2) >> 1);
1.1.1.12! root 477: gui_data.powerled = ((~ciaapra & 2) >> 1);
1.1 root 478: if ((ciaapra & 2) != oldled)
479: gui_led (0, !(ciaapra & 2));
1.1.1.3 root 480: if ((ciaapra & 1) != oldovl) {
1.1.1.11 root 481: int i = (allocated_chipmem>>16) > 32 ? allocated_chipmem >> 16 : 32;
482:
483: if (oldovl || ersatzkickfile) {
484: map_banks (&chipmem_bank, 0, i, allocated_chipmem);
485: } else {
486: /* Is it OK to do this for more than 2M of chip? */
487: map_banks (&kickmem_bank, 0, i, 0x80000);
488: }
1.1.1.3 root 489: }
1.1 root 490: break;
1.1.1.7 root 491: case 1:
1.1 root 492: ciaaprb = val;
493: if (prtopen==1) {
494: #ifndef __DOS__
1.1.1.4 root 495: fprintf (prttmp, "%c",val);
1.1 root 496: #else
497: fputc (val, prttmp);
498: fflush (prttmp);
499: #endif
500: if (val==0x04) {
1.1.1.2 root 501: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1 root 502: pclose (prttmp);
503: #else
504: fclose (prttmp);
505: #endif
506: prtopen = 0;
507: }
1.1.1.3 root 508: } else {
1.1.1.2 root 509: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1.1.6 root 510: prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w");
1.1 root 511: #else
1.1.1.6 root 512: prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb");
1.1 root 513: #endif
514: if (prttmp != NULL) {
515: prtopen = 1;
516: #ifndef __DOS__
517: fprintf (prttmp,"%c",val);
518: #else
519: fputc (val, prttmp);
520: fflush (prttmp);
521: #endif
522: }
1.1.1.3 root 523: }
1.1 root 524: ciaaicr |= 0x10;
525: break;
1.1.1.7 root 526: case 2:
1.1 root 527: ciaadra = val; break;
1.1.1.7 root 528: case 3:
1.1 root 529: ciaadrb = val; break;
1.1.1.7 root 530: case 4:
1.1.1.10 root 531: CIA_update ();
1.1 root 532: ciaala = (ciaala & 0xff00) | val;
1.1.1.10 root 533: CIA_calctimers ();
1.1 root 534: break;
1.1.1.7 root 535: case 5:
1.1.1.10 root 536: CIA_update ();
1.1 root 537: ciaala = (ciaala & 0xff) | (val << 8);
538: if ((ciaacra & 1) == 0)
539: ciaata = ciaala;
1.1.1.3 root 540: if (ciaacra & 8) {
541: ciaata = ciaala;
542: ciaacra |= 1;
1.1 root 543: }
1.1.1.10 root 544: CIA_calctimers ();
1.1 root 545: break;
1.1.1.7 root 546: case 6:
1.1.1.10 root 547: CIA_update ();
1.1 root 548: ciaalb = (ciaalb & 0xff00) | val;
1.1.1.10 root 549: CIA_calctimers ();
1.1 root 550: break;
1.1.1.7 root 551: case 7:
1.1.1.10 root 552: CIA_update ();
1.1 root 553: ciaalb = (ciaalb & 0xff) | (val << 8);
554: if ((ciaacrb & 1) == 0)
555: ciaatb = ciaalb;
1.1.1.3 root 556: if (ciaacrb & 8) {
1.1 root 557: ciaatb = ciaalb;
1.1.1.3 root 558: ciaacrb |= 1;
1.1 root 559: }
1.1.1.10 root 560: CIA_calctimers ();
1.1 root 561: break;
1.1.1.7 root 562: case 8:
1.1.1.5 root 563: if (ciaacrb & 0x80) {
1.1 root 564: ciaaalarm = (ciaaalarm & ~0xff) | val;
565: } else {
566: ciaatod = (ciaatod & ~0xff) | val;
567: ciaatodon = 1;
568: }
569: break;
1.1.1.7 root 570: case 9:
1.1.1.5 root 571: if (ciaacrb & 0x80) {
1.1 root 572: ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
573: } else {
574: ciaatod = (ciaatod & ~0xff00) | (val << 8);
575: ciaatodon = 0;
576: }
577: break;
1.1.1.7 root 578: case 10:
1.1.1.5 root 579: if (ciaacrb & 0x80) {
1.1 root 580: ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
581: } else {
582: ciaatod = (ciaatod & ~0xff0000) | (val << 16);
583: ciaatodon = 0;
584: }
585: break;
1.1.1.7 root 586: case 12:
1.1 root 587: ciaasdr = val; break;
1.1.1.7 root 588: case 13:
1.1 root 589: setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
1.1.1.7 root 590: case 14:
1.1.1.10 root 591: CIA_update ();
1.1 root 592: ciaacra = val;
1.1.1.5 root 593: if (ciaacra & 0x10) {
1.1 root 594: ciaacra &= ~0x10;
595: ciaata = ciaala;
596: }
597: if (ciaacra & 0x40) {
598: kback = 1;
599: }
1.1.1.10 root 600: CIA_calctimers ();
1.1 root 601: break;
1.1.1.7 root 602: case 15:
1.1.1.10 root 603: CIA_update ();
1.1.1.3 root 604: ciaacrb = val;
1.1.1.5 root 605: if (ciaacrb & 0x10) {
1.1 root 606: ciaacrb &= ~0x10;
607: ciaatb = ciaalb;
608: }
1.1.1.10 root 609: CIA_calctimers ();
1.1 root 610: break;
611: }
612: }
613:
1.1.1.10 root 614: static void WriteCIAB (uae_u16 addr,uae_u8 val)
1.1 root 615: {
1.1.1.3 root 616: int oldval;
1.1.1.10 root 617: switch (addr & 0xf) {
1.1.1.7 root 618: case 0:
1.1.1.3 root 619: if (currprefs.use_serial) {
1.1.1.7 root 620: oldval = ciabpra;
621: ciabpra = serial_writestatus(oldval,val);
1.1.1.3 root 622: } else
1.1.1.7 root 623: ciabpra = val;
1.1.1.3 root 624: break;
1.1.1.7 root 625: case 1:
1.1 root 626: ciabprb = val; DISK_select(val); break;
1.1.1.7 root 627: case 2:
1.1 root 628: ciabdra = val; break;
1.1.1.7 root 629: case 3:
1.1 root 630: ciabdrb = val; break;
1.1.1.7 root 631: case 4:
1.1.1.10 root 632: CIA_update ();
1.1 root 633: ciabla = (ciabla & 0xff00) | val;
1.1.1.10 root 634: CIA_calctimers ();
1.1 root 635: break;
1.1.1.7 root 636: case 5:
1.1.1.10 root 637: CIA_update ();
1.1 root 638: ciabla = (ciabla & 0xff) | (val << 8);
1.1.1.3 root 639: if ((ciabcra & 1) == 0)
1.1 root 640: ciabta = ciabla;
641: if (ciabcra & 8) {
1.1.1.3 root 642: ciabta = ciabla;
643: ciabcra |= 1;
644: }
1.1.1.10 root 645: CIA_calctimers ();
1.1 root 646: break;
1.1.1.7 root 647: case 6:
1.1.1.10 root 648: CIA_update ();
1.1 root 649: ciablb = (ciablb & 0xff00) | val;
1.1.1.10 root 650: CIA_calctimers ();
1.1 root 651: break;
1.1.1.7 root 652: case 7:
1.1.1.10 root 653: CIA_update ();
1.1 root 654: ciablb = (ciablb & 0xff) | (val << 8);
655: if ((ciabcrb & 1) == 0)
656: ciabtb = ciablb;
657: if (ciabcrb & 8) {
658: ciabtb = ciablb;
659: ciabcrb |= 1;
660: }
1.1.1.10 root 661: CIA_calctimers ();
1.1 root 662: break;
1.1.1.7 root 663: case 8:
1.1.1.5 root 664: if (ciabcrb & 0x80) {
1.1 root 665: ciabalarm = (ciabalarm & ~0xff) | val;
666: } else {
667: ciabtod = (ciabtod & ~0xff) | val;
668: ciabtodon = 1;
669: }
670: break;
1.1.1.7 root 671: case 9:
1.1.1.5 root 672: if (ciabcrb & 0x80) {
1.1 root 673: ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
674: } else {
675: ciabtod = (ciabtod & ~0xff00) | (val << 8);
676: ciabtodon = 0;
677: }
678: break;
1.1.1.7 root 679: case 10:
1.1.1.5 root 680: if (ciabcrb & 0x80) {
1.1 root 681: ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
682: } else {
683: ciabtod = (ciabtod & ~0xff0000) | (val << 16);
684: ciabtodon = 0;
685: }
686: break;
1.1.1.7 root 687: case 12:
1.1.1.3 root 688: ciabsdr = val;
1.1 root 689: break;
1.1.1.7 root 690: case 13:
1.1.1.3 root 691: setclr(&ciabimask,val);
1.1 root 692: break;
1.1.1.7 root 693: case 14:
1.1.1.10 root 694: CIA_update ();
1.1 root 695: ciabcra = val;
1.1.1.5 root 696: if (ciabcra & 0x10) {
1.1 root 697: ciabcra &= ~0x10;
698: ciabta = ciabla;
699: }
1.1.1.10 root 700: CIA_calctimers ();
1.1 root 701: break;
1.1.1.7 root 702: case 15:
1.1.1.10 root 703: CIA_update ();
1.1.1.3 root 704: ciabcrb = val;
1.1.1.5 root 705: if (ciabcrb & 0x10) {
1.1 root 706: ciabcrb &= ~0x10;
707: ciabtb = ciablb;
708: }
1.1.1.10 root 709: CIA_calctimers ();
1.1 root 710: break;
711: }
712: }
713:
1.1.1.10 root 714: void CIA_reset (void)
1.1 root 715: {
716: kback = 1;
717: kbstate = 0;
1.1.1.3 root 718:
1.1.1.11 root 719: if (!savestate_state) {
720: ciaatlatch = ciabtlatch = 0;
721: ciaapra = 3;
722: ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
723: ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
724: ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
725: ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
726: ciabpra = 0x8C;
727: }
1.1 root 728: div10 = 0;
1.1.1.10 root 729: CIA_calctimers ();
1.1.1.3 root 730: if (! ersatzkickfile)
1.1.1.11 root 731: map_banks (&kickmem_bank, 0, 32, 0x80000);
1.1.1.3 root 732:
1.1.1.11 root 733: if (currprefs.use_serial && !savestate_state)
734: serial_dtr_off (); /* Drop DTR at reset */
735:
736: if (savestate_state) {
737: /* Reset oldovl and oldled */
738: uae_u8 v = ReadCIAA (0);
739: WriteCIAA (0,3);
740: WriteCIAA (0,0);
741: WriteCIAA (0,v);
742: /* select drives */
743: DISK_select (ciabprb);
744: }
1.1 root 745: }
746:
1.1.1.10 root 747: void dumpcia (void)
1.1 root 748: {
749: printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3 root 750: (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod,
1.1 root 751: ciaatlatch ? " latched" : "", ciaata, ciaatb);
752: printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3 root 753: (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod,
1.1 root 754: ciabtlatch ? " latched" : "", ciabta, ciabtb);
755: }
756:
757: /* CIA memory access */
758:
1.1.1.3 root 759: static uae_u32 cia_lget (uaecptr) REGPARAM;
760: static uae_u32 cia_wget (uaecptr) REGPARAM;
761: static uae_u32 cia_bget (uaecptr) REGPARAM;
762: static void cia_lput (uaecptr, uae_u32) REGPARAM;
763: static void cia_wput (uaecptr, uae_u32) REGPARAM;
764: static void cia_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 765:
766: addrbank cia_bank = {
767: cia_lget, cia_wget, cia_bget,
768: cia_lput, cia_wput, cia_bput,
1.1.1.11 root 769: default_xlate, default_check, NULL
1.1 root 770: };
771:
1.1.1.3 root 772: uae_u32 REGPARAM2 cia_lget (uaecptr addr)
1.1 root 773: {
1.1.1.9 root 774: special_mem |= S_READ;
775: return cia_bget (addr + 3);
1.1 root 776: }
777:
1.1.1.3 root 778: uae_u32 REGPARAM2 cia_wget (uaecptr addr)
1.1 root 779: {
1.1.1.9 root 780: special_mem |= S_READ;
781: return cia_bget (addr + 1);
1.1 root 782: }
783:
1.1.1.3 root 784: uae_u32 REGPARAM2 cia_bget (uaecptr addr)
1.1 root 785: {
1.1.1.9 root 786: special_mem |= S_READ;
1.1 root 787: if ((addr & 0x3001) == 0x2001)
1.1.1.3 root 788: return ReadCIAA((addr & 0xF00) >> 8);
1.1 root 789: if ((addr & 0x3001) == 0x1000)
1.1.1.3 root 790: return ReadCIAB((addr & 0xF00) >> 8);
1.1 root 791: return 0;
792: }
793:
1.1.1.3 root 794: void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
1.1 root 795: {
1.1.1.9 root 796: special_mem |= S_WRITE;
797: cia_bput (addr + 3, value); /* FIXME ? */
1.1 root 798: }
799:
1.1.1.3 root 800: void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
1.1 root 801: {
1.1.1.9 root 802: special_mem |= S_WRITE;
803: cia_bput (addr + 1, value);
1.1 root 804: }
805:
1.1.1.3 root 806: void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
1.1 root 807: {
1.1.1.9 root 808: special_mem |= S_WRITE;
1.1 root 809: if ((addr & 0x3001) == 0x2001)
1.1.1.9 root 810: WriteCIAA ((addr & 0xF00) >> 8, value);
1.1 root 811: if ((addr & 0x3001) == 0x1000)
1.1.1.9 root 812: WriteCIAB ((addr & 0xF00) >> 8, value);
1.1 root 813: }
814:
815: /* battclock memory access */
816:
1.1.1.3 root 817: static uae_u32 clock_lget (uaecptr) REGPARAM;
818: static uae_u32 clock_wget (uaecptr) REGPARAM;
819: static uae_u32 clock_bget (uaecptr) REGPARAM;
820: static void clock_lput (uaecptr, uae_u32) REGPARAM;
821: static void clock_wput (uaecptr, uae_u32) REGPARAM;
822: static void clock_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 823:
824: addrbank clock_bank = {
825: clock_lget, clock_wget, clock_bget,
826: clock_lput, clock_wput, clock_bput,
1.1.1.11 root 827: default_xlate, default_check, NULL
1.1 root 828: };
829:
1.1.1.3 root 830: uae_u32 REGPARAM2 clock_lget (uaecptr addr)
1.1 root 831: {
1.1.1.9 root 832: special_mem |= S_READ;
833: return clock_bget (addr + 3);
1.1 root 834: }
835:
1.1.1.3 root 836: uae_u32 REGPARAM2 clock_wget (uaecptr addr)
1.1 root 837: {
1.1.1.9 root 838: special_mem |= S_READ;
839: return clock_bget (addr + 1);
1.1 root 840: }
841:
1.1.1.3 root 842: uae_u32 REGPARAM2 clock_bget (uaecptr addr)
1.1 root 843: {
1.1.1.9 root 844: time_t t = time(0);
1.1 root 845: struct tm *ct;
1.1.1.9 root 846:
847: ct = localtime (&t);
848: special_mem |= S_READ;
849:
1.1.1.7 root 850: switch (addr & 0x3f) {
851: case 0x03: return ct->tm_sec % 10;
852: case 0x07: return ct->tm_sec / 10;
853: case 0x0b: return ct->tm_min % 10;
854: case 0x0f: return ct->tm_min / 10;
855: case 0x13: return ct->tm_hour % 10;
856: case 0x17: return ct->tm_hour / 10;
857: case 0x1b: return ct->tm_mday % 10;
858: case 0x1f: return ct->tm_mday / 10;
859: case 0x23: return (ct->tm_mon+1) % 10;
860: case 0x27: return (ct->tm_mon+1) / 10;
861: case 0x2b: return ct->tm_year % 10;
862: case 0x2f: return ct->tm_year / 10;
863:
864: case 0x33: return ct->tm_wday; /*Hack by -=SR=- */
865: case 0x37: return clock_control_d;
866: case 0x3b: return clock_control_e;
867: case 0x3f: return clock_control_f;
1.1 root 868: }
869: return 0;
870: }
871:
1.1.1.3 root 872: void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
1.1 root 873: {
1.1.1.9 root 874: special_mem |= S_WRITE;
1.1 root 875: /* No way */
876: }
877:
1.1.1.3 root 878: void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
1.1 root 879: {
1.1.1.9 root 880: special_mem |= S_WRITE;
1.1 root 881: /* No way */
882: }
883:
1.1.1.3 root 884: void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
1.1 root 885: {
1.1.1.9 root 886: special_mem |= S_WRITE;
1.1.1.7 root 887: switch (addr & 0x3f) {
1.1.1.9 root 888: case 0x37: clock_control_d = value; break;
889: case 0x3b: clock_control_e = value; break;
890: case 0x3f: clock_control_f = value; break;
1.1 root 891: }
892: }
1.1.1.11 root 893:
894: /* CIA-A and CIA-B save/restore code */
895:
896: uae_u8 *restore_cia (int num, uae_u8 *src)
897: {
898: uae_u8 b;
899: uae_u16 w;
900: uae_u32 l;
901:
902: /* CIA registers */
903: b = restore_u8 (); /* 0 PRA */
904: if (num) ciabpra = b; else ciaapra = b;
905: b = restore_u8 (); /* 1 PRB */
906: if (num) ciabprb = b; else ciaaprb = b;
907: b = restore_u8 (); /* 2 DDRA */
908: if (num) ciabdra = b; else ciaadra = b;
909: b = restore_u8 (); /* 3 DDRB */
910: if (num) ciabdrb = b; else ciaadrb = b;
911: w = restore_u16 (); /* 4 TA */
912: if (num) ciabta = w; else ciaata = w;
913: w = restore_u16 (); /* 6 TB */
914: if (num) ciabtb = w; else ciaatb = w;
915: l = restore_u8 (); /* 8/9/A TOD */
916: l |= restore_u8 () << 8;
917: l |= restore_u8 () << 16;
918: if (num) ciabtod = l; else ciaatod = l;
919: restore_u8 (); /* B unused */
920: b = restore_u8 (); /* C SDR */
921: if (num) ciabsdr = b; else ciaasdr = b;
922: b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
923: if (num) ciabicr = b; else ciaaicr = b;
924: b = restore_u8 (); /* E CRA */
925: if (num) ciabcra = b; else ciaacra = b;
926: b = restore_u8 (); /* F CRB */
927: if (num) ciabcrb = b; else ciaacrb = b;
928:
929: /* CIA internal data */
930:
931: b = restore_u8 (); /* ICR MASK */
932: if (num) ciabimask = b; else ciaaimask = b;
933: w = restore_u8 (); /* timer A latch */
934: w |= restore_u8 () << 8;
935: if (num) ciabla = w; else ciaala = b;
936: w = restore_u8 (); /* timer B latch */
937: w |= restore_u8 () << 8;
938: if (num) ciablb = w; else ciaalb = w;
939: w = restore_u8 (); /* TOD latched value */
940: w |= restore_u8 () << 8;
941: w |= restore_u8 () << 16;
942: if (num) ciabtol = w; else ciaatol = w;
943: l = restore_u8 (); /* alarm */
944: l |= restore_u8 () << 8;
945: l |= restore_u8 () << 16;
946: if (num) ciabalarm = l; else ciaaalarm = l;
947: b = restore_u8 ();
948: if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
949: if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
950: if (num) {
951: div10 = CYCLE_UNIT * restore_u8 ();
952: }
953: return src;
954: }
955:
956: uae_u8 *save_cia (int num, int *len)
957: {
958: uae_u8 *dstbak,*dst, b;
959: uae_u16 t;
960:
961: dstbak = dst = malloc (16 + 12 + 1);
962:
963: compute_passed_time ();
964:
965: /* CIA registers */
966:
967: b = num ? ciabpra : ciaapra; /* 0 PRA */
968: save_u8 (b);
969: b = num ? ciabprb : ciaaprb; /* 1 PRB */
970: save_u8 (b);
971: b = num ? ciabdra : ciaadra; /* 2 DDRA */
972: save_u8 (b);
973: b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
974: save_u8 (b);
975: t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
976: save_u16 (t);
977: t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 8 TB */
978: save_u16 (t);
979: b = (num ? ciabtod : ciaatod); /* 8 TODL */
980: save_u8 (b);
981: b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
982: save_u8 (b);
983: b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
984: save_u8 (b);
985: save_u8 (0); /* B unused */
986: b = num ? ciabsdr : ciaasdr; /* C SDR */
987: save_u8 (b);
988: b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
989: save_u8 (b);
990: b = num ? ciabcra : ciaacra; /* E CRA */
991: save_u8 (b);
992: b = num ? ciabcrb : ciaacrb; /* F CRB */
993: save_u8 (b);
994:
995: /* CIA internal data */
996:
997: save_u8 (num ? ciabimask : ciaaimask); /* ICR */
998: b = (num ? ciabla : ciaala); /* timer A latch LO */
999: save_u8 (b);
1000: b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
1001: save_u8 (b);
1002: b = (num ? ciablb : ciaalb); /* timer B latch LO */
1003: save_u8 (b);
1004: b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
1005: save_u8 (b);
1006: b = (num ? ciabtol : ciaatol); /* latched TOD LO */
1007: save_u8 (b);
1008: b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
1009: save_u8 (b);
1010: b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
1011: save_u8 (b);
1012: b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
1013: save_u8 (b);
1014: b = (num ? ciabalarm >> 8 : ciaaalarm >>8 ); /* alarm MED */
1015: save_u8 (b);
1016: b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
1017: save_u8 (b);
1018: b = 0;
1019: if (num)
1020: b |= ciabtlatch ? 1 : 0;
1021: else
1022: b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
1023: if (num)
1024: b |= ciabtodon ? 2 : 0;
1025: else
1026: b |= ciaatodon ? 2 : 0; /* TOD stopped? */
1027: save_u8 (b);
1028: if (num) {
1029: /* Save extra state with CIAB. */
1030: save_u8 (div10 / CYCLE_UNIT);
1031: }
1032: *len = dst - dstbak;
1033: return dstbak;
1034: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.