|
|
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.3 root 16: #include "threaddep/penguin.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 root 477: if ((ciaapra & 2) != oldled)
478: gui_led (0, !(ciaapra & 2));
1.1.1.3 root 479: if ((ciaapra & 1) != oldovl) {
1.1.1.11! root 480: int i = (allocated_chipmem>>16) > 32 ? allocated_chipmem >> 16 : 32;
! 481:
! 482: if (oldovl || ersatzkickfile) {
! 483: map_banks (&chipmem_bank, 0, i, allocated_chipmem);
! 484: } else {
! 485: /* Is it OK to do this for more than 2M of chip? */
! 486: map_banks (&kickmem_bank, 0, i, 0x80000);
! 487: }
1.1.1.3 root 488: }
1.1 root 489: break;
1.1.1.7 root 490: case 1:
1.1 root 491: ciaaprb = val;
492: if (prtopen==1) {
493: #ifndef __DOS__
1.1.1.4 root 494: fprintf (prttmp, "%c",val);
1.1 root 495: #else
496: fputc (val, prttmp);
497: fflush (prttmp);
498: #endif
499: if (val==0x04) {
1.1.1.2 root 500: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1 root 501: pclose (prttmp);
502: #else
503: fclose (prttmp);
504: #endif
505: prtopen = 0;
506: }
1.1.1.3 root 507: } else {
1.1.1.2 root 508: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1.1.6 root 509: prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w");
1.1 root 510: #else
1.1.1.6 root 511: prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb");
1.1 root 512: #endif
513: if (prttmp != NULL) {
514: prtopen = 1;
515: #ifndef __DOS__
516: fprintf (prttmp,"%c",val);
517: #else
518: fputc (val, prttmp);
519: fflush (prttmp);
520: #endif
521: }
1.1.1.3 root 522: }
1.1 root 523: ciaaicr |= 0x10;
524: break;
1.1.1.7 root 525: case 2:
1.1 root 526: ciaadra = val; break;
1.1.1.7 root 527: case 3:
1.1 root 528: ciaadrb = val; break;
1.1.1.7 root 529: case 4:
1.1.1.10 root 530: CIA_update ();
1.1 root 531: ciaala = (ciaala & 0xff00) | val;
1.1.1.10 root 532: CIA_calctimers ();
1.1 root 533: break;
1.1.1.7 root 534: case 5:
1.1.1.10 root 535: CIA_update ();
1.1 root 536: ciaala = (ciaala & 0xff) | (val << 8);
537: if ((ciaacra & 1) == 0)
538: ciaata = ciaala;
1.1.1.3 root 539: if (ciaacra & 8) {
540: ciaata = ciaala;
541: ciaacra |= 1;
1.1 root 542: }
1.1.1.10 root 543: CIA_calctimers ();
1.1 root 544: break;
1.1.1.7 root 545: case 6:
1.1.1.10 root 546: CIA_update ();
1.1 root 547: ciaalb = (ciaalb & 0xff00) | val;
1.1.1.10 root 548: CIA_calctimers ();
1.1 root 549: break;
1.1.1.7 root 550: case 7:
1.1.1.10 root 551: CIA_update ();
1.1 root 552: ciaalb = (ciaalb & 0xff) | (val << 8);
553: if ((ciaacrb & 1) == 0)
554: ciaatb = ciaalb;
1.1.1.3 root 555: if (ciaacrb & 8) {
1.1 root 556: ciaatb = ciaalb;
1.1.1.3 root 557: ciaacrb |= 1;
1.1 root 558: }
1.1.1.10 root 559: CIA_calctimers ();
1.1 root 560: break;
1.1.1.7 root 561: case 8:
1.1.1.5 root 562: if (ciaacrb & 0x80) {
1.1 root 563: ciaaalarm = (ciaaalarm & ~0xff) | val;
564: } else {
565: ciaatod = (ciaatod & ~0xff) | val;
566: ciaatodon = 1;
567: }
568: break;
1.1.1.7 root 569: case 9:
1.1.1.5 root 570: if (ciaacrb & 0x80) {
1.1 root 571: ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
572: } else {
573: ciaatod = (ciaatod & ~0xff00) | (val << 8);
574: ciaatodon = 0;
575: }
576: break;
1.1.1.7 root 577: case 10:
1.1.1.5 root 578: if (ciaacrb & 0x80) {
1.1 root 579: ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
580: } else {
581: ciaatod = (ciaatod & ~0xff0000) | (val << 16);
582: ciaatodon = 0;
583: }
584: break;
1.1.1.7 root 585: case 12:
1.1 root 586: ciaasdr = val; break;
1.1.1.7 root 587: case 13:
1.1 root 588: setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
1.1.1.7 root 589: case 14:
1.1.1.10 root 590: CIA_update ();
1.1 root 591: ciaacra = val;
1.1.1.5 root 592: if (ciaacra & 0x10) {
1.1 root 593: ciaacra &= ~0x10;
594: ciaata = ciaala;
595: }
596: if (ciaacra & 0x40) {
597: kback = 1;
598: }
1.1.1.10 root 599: CIA_calctimers ();
1.1 root 600: break;
1.1.1.7 root 601: case 15:
1.1.1.10 root 602: CIA_update ();
1.1.1.3 root 603: ciaacrb = val;
1.1.1.5 root 604: if (ciaacrb & 0x10) {
1.1 root 605: ciaacrb &= ~0x10;
606: ciaatb = ciaalb;
607: }
1.1.1.10 root 608: CIA_calctimers ();
1.1 root 609: break;
610: }
611: }
612:
1.1.1.10 root 613: static void WriteCIAB (uae_u16 addr,uae_u8 val)
1.1 root 614: {
1.1.1.3 root 615: int oldval;
1.1.1.10 root 616: switch (addr & 0xf) {
1.1.1.7 root 617: case 0:
1.1.1.3 root 618: if (currprefs.use_serial) {
1.1.1.7 root 619: oldval = ciabpra;
620: ciabpra = serial_writestatus(oldval,val);
1.1.1.3 root 621: } else
1.1.1.7 root 622: ciabpra = val;
1.1.1.3 root 623: break;
1.1.1.7 root 624: case 1:
1.1 root 625: ciabprb = val; DISK_select(val); break;
1.1.1.7 root 626: case 2:
1.1 root 627: ciabdra = val; break;
1.1.1.7 root 628: case 3:
1.1 root 629: ciabdrb = val; break;
1.1.1.7 root 630: case 4:
1.1.1.10 root 631: CIA_update ();
1.1 root 632: ciabla = (ciabla & 0xff00) | val;
1.1.1.10 root 633: CIA_calctimers ();
1.1 root 634: break;
1.1.1.7 root 635: case 5:
1.1.1.10 root 636: CIA_update ();
1.1 root 637: ciabla = (ciabla & 0xff) | (val << 8);
1.1.1.3 root 638: if ((ciabcra & 1) == 0)
1.1 root 639: ciabta = ciabla;
640: if (ciabcra & 8) {
1.1.1.3 root 641: ciabta = ciabla;
642: ciabcra |= 1;
643: }
1.1.1.10 root 644: CIA_calctimers ();
1.1 root 645: break;
1.1.1.7 root 646: case 6:
1.1.1.10 root 647: CIA_update ();
1.1 root 648: ciablb = (ciablb & 0xff00) | val;
1.1.1.10 root 649: CIA_calctimers ();
1.1 root 650: break;
1.1.1.7 root 651: case 7:
1.1.1.10 root 652: CIA_update ();
1.1 root 653: ciablb = (ciablb & 0xff) | (val << 8);
654: if ((ciabcrb & 1) == 0)
655: ciabtb = ciablb;
656: if (ciabcrb & 8) {
657: ciabtb = ciablb;
658: ciabcrb |= 1;
659: }
1.1.1.10 root 660: CIA_calctimers ();
1.1 root 661: break;
1.1.1.7 root 662: case 8:
1.1.1.5 root 663: if (ciabcrb & 0x80) {
1.1 root 664: ciabalarm = (ciabalarm & ~0xff) | val;
665: } else {
666: ciabtod = (ciabtod & ~0xff) | val;
667: ciabtodon = 1;
668: }
669: break;
1.1.1.7 root 670: case 9:
1.1.1.5 root 671: if (ciabcrb & 0x80) {
1.1 root 672: ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
673: } else {
674: ciabtod = (ciabtod & ~0xff00) | (val << 8);
675: ciabtodon = 0;
676: }
677: break;
1.1.1.7 root 678: case 10:
1.1.1.5 root 679: if (ciabcrb & 0x80) {
1.1 root 680: ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
681: } else {
682: ciabtod = (ciabtod & ~0xff0000) | (val << 16);
683: ciabtodon = 0;
684: }
685: break;
1.1.1.7 root 686: case 12:
1.1.1.3 root 687: ciabsdr = val;
1.1 root 688: break;
1.1.1.7 root 689: case 13:
1.1.1.3 root 690: setclr(&ciabimask,val);
1.1 root 691: break;
1.1.1.7 root 692: case 14:
1.1.1.10 root 693: CIA_update ();
1.1 root 694: ciabcra = val;
1.1.1.5 root 695: if (ciabcra & 0x10) {
1.1 root 696: ciabcra &= ~0x10;
697: ciabta = ciabla;
698: }
1.1.1.10 root 699: CIA_calctimers ();
1.1 root 700: break;
1.1.1.7 root 701: case 15:
1.1.1.10 root 702: CIA_update ();
1.1.1.3 root 703: ciabcrb = val;
1.1.1.5 root 704: if (ciabcrb & 0x10) {
1.1 root 705: ciabcrb &= ~0x10;
706: ciabtb = ciablb;
707: }
1.1.1.10 root 708: CIA_calctimers ();
1.1 root 709: break;
710: }
711: }
712:
1.1.1.10 root 713: void CIA_reset (void)
1.1 root 714: {
715: kback = 1;
716: kbstate = 0;
1.1.1.3 root 717:
1.1.1.11! root 718: if (!savestate_state) {
! 719: ciaatlatch = ciabtlatch = 0;
! 720: ciaapra = 3;
! 721: ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
! 722: ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
! 723: ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
! 724: ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
! 725: ciabpra = 0x8C;
! 726: }
1.1 root 727: div10 = 0;
1.1.1.10 root 728: CIA_calctimers ();
1.1.1.3 root 729: if (! ersatzkickfile)
1.1.1.11! root 730: map_banks (&kickmem_bank, 0, 32, 0x80000);
1.1.1.3 root 731:
1.1.1.11! root 732: if (currprefs.use_serial && !savestate_state)
! 733: serial_dtr_off (); /* Drop DTR at reset */
! 734:
! 735: if (savestate_state) {
! 736: /* Reset oldovl and oldled */
! 737: uae_u8 v = ReadCIAA (0);
! 738: WriteCIAA (0,3);
! 739: WriteCIAA (0,0);
! 740: WriteCIAA (0,v);
! 741: /* select drives */
! 742: DISK_select (ciabprb);
! 743: }
1.1 root 744: }
745:
1.1.1.10 root 746: void dumpcia (void)
1.1 root 747: {
748: printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3 root 749: (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod,
1.1 root 750: ciaatlatch ? " latched" : "", ciaata, ciaatb);
751: printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3 root 752: (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod,
1.1 root 753: ciabtlatch ? " latched" : "", ciabta, ciabtb);
754: }
755:
756: /* CIA memory access */
757:
1.1.1.3 root 758: static uae_u32 cia_lget (uaecptr) REGPARAM;
759: static uae_u32 cia_wget (uaecptr) REGPARAM;
760: static uae_u32 cia_bget (uaecptr) REGPARAM;
761: static void cia_lput (uaecptr, uae_u32) REGPARAM;
762: static void cia_wput (uaecptr, uae_u32) REGPARAM;
763: static void cia_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 764:
765: addrbank cia_bank = {
766: cia_lget, cia_wget, cia_bget,
767: cia_lput, cia_wput, cia_bput,
1.1.1.11! root 768: default_xlate, default_check, NULL
1.1 root 769: };
770:
1.1.1.3 root 771: uae_u32 REGPARAM2 cia_lget (uaecptr addr)
1.1 root 772: {
1.1.1.9 root 773: special_mem |= S_READ;
774: return cia_bget (addr + 3);
1.1 root 775: }
776:
1.1.1.3 root 777: uae_u32 REGPARAM2 cia_wget (uaecptr addr)
1.1 root 778: {
1.1.1.9 root 779: special_mem |= S_READ;
780: return cia_bget (addr + 1);
1.1 root 781: }
782:
1.1.1.3 root 783: uae_u32 REGPARAM2 cia_bget (uaecptr addr)
1.1 root 784: {
1.1.1.9 root 785: special_mem |= S_READ;
1.1 root 786: if ((addr & 0x3001) == 0x2001)
1.1.1.3 root 787: return ReadCIAA((addr & 0xF00) >> 8);
1.1 root 788: if ((addr & 0x3001) == 0x1000)
1.1.1.3 root 789: return ReadCIAB((addr & 0xF00) >> 8);
1.1 root 790: return 0;
791: }
792:
1.1.1.3 root 793: void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
1.1 root 794: {
1.1.1.9 root 795: special_mem |= S_WRITE;
796: cia_bput (addr + 3, value); /* FIXME ? */
1.1 root 797: }
798:
1.1.1.3 root 799: void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
1.1 root 800: {
1.1.1.9 root 801: special_mem |= S_WRITE;
802: cia_bput (addr + 1, value);
1.1 root 803: }
804:
1.1.1.3 root 805: void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
1.1 root 806: {
1.1.1.9 root 807: special_mem |= S_WRITE;
1.1 root 808: if ((addr & 0x3001) == 0x2001)
1.1.1.9 root 809: WriteCIAA ((addr & 0xF00) >> 8, value);
1.1 root 810: if ((addr & 0x3001) == 0x1000)
1.1.1.9 root 811: WriteCIAB ((addr & 0xF00) >> 8, value);
1.1 root 812: }
813:
814: /* battclock memory access */
815:
1.1.1.3 root 816: static uae_u32 clock_lget (uaecptr) REGPARAM;
817: static uae_u32 clock_wget (uaecptr) REGPARAM;
818: static uae_u32 clock_bget (uaecptr) REGPARAM;
819: static void clock_lput (uaecptr, uae_u32) REGPARAM;
820: static void clock_wput (uaecptr, uae_u32) REGPARAM;
821: static void clock_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 822:
823: addrbank clock_bank = {
824: clock_lget, clock_wget, clock_bget,
825: clock_lput, clock_wput, clock_bput,
1.1.1.11! root 826: default_xlate, default_check, NULL
1.1 root 827: };
828:
1.1.1.3 root 829: uae_u32 REGPARAM2 clock_lget (uaecptr addr)
1.1 root 830: {
1.1.1.9 root 831: special_mem |= S_READ;
832: return clock_bget (addr + 3);
1.1 root 833: }
834:
1.1.1.3 root 835: uae_u32 REGPARAM2 clock_wget (uaecptr addr)
1.1 root 836: {
1.1.1.9 root 837: special_mem |= S_READ;
838: return clock_bget (addr + 1);
1.1 root 839: }
840:
1.1.1.3 root 841: uae_u32 REGPARAM2 clock_bget (uaecptr addr)
1.1 root 842: {
1.1.1.9 root 843: time_t t = time(0);
1.1 root 844: struct tm *ct;
1.1.1.9 root 845:
846: ct = localtime (&t);
847: special_mem |= S_READ;
848:
1.1.1.7 root 849: switch (addr & 0x3f) {
850: case 0x03: return ct->tm_sec % 10;
851: case 0x07: return ct->tm_sec / 10;
852: case 0x0b: return ct->tm_min % 10;
853: case 0x0f: return ct->tm_min / 10;
854: case 0x13: return ct->tm_hour % 10;
855: case 0x17: return ct->tm_hour / 10;
856: case 0x1b: return ct->tm_mday % 10;
857: case 0x1f: return ct->tm_mday / 10;
858: case 0x23: return (ct->tm_mon+1) % 10;
859: case 0x27: return (ct->tm_mon+1) / 10;
860: case 0x2b: return ct->tm_year % 10;
861: case 0x2f: return ct->tm_year / 10;
862:
863: case 0x33: return ct->tm_wday; /*Hack by -=SR=- */
864: case 0x37: return clock_control_d;
865: case 0x3b: return clock_control_e;
866: case 0x3f: return clock_control_f;
1.1 root 867: }
868: return 0;
869: }
870:
1.1.1.3 root 871: void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
1.1 root 872: {
1.1.1.9 root 873: special_mem |= S_WRITE;
1.1 root 874: /* No way */
875: }
876:
1.1.1.3 root 877: void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
1.1 root 878: {
1.1.1.9 root 879: special_mem |= S_WRITE;
1.1 root 880: /* No way */
881: }
882:
1.1.1.3 root 883: void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
1.1 root 884: {
1.1.1.9 root 885: special_mem |= S_WRITE;
1.1.1.7 root 886: switch (addr & 0x3f) {
1.1.1.9 root 887: case 0x37: clock_control_d = value; break;
888: case 0x3b: clock_control_e = value; break;
889: case 0x3f: clock_control_f = value; break;
1.1 root 890: }
891: }
1.1.1.11! root 892:
! 893: /* CIA-A and CIA-B save/restore code */
! 894:
! 895: uae_u8 *restore_cia (int num, uae_u8 *src)
! 896: {
! 897: uae_u8 b;
! 898: uae_u16 w;
! 899: uae_u32 l;
! 900:
! 901: /* CIA registers */
! 902: b = restore_u8 (); /* 0 PRA */
! 903: if (num) ciabpra = b; else ciaapra = b;
! 904: b = restore_u8 (); /* 1 PRB */
! 905: if (num) ciabprb = b; else ciaaprb = b;
! 906: b = restore_u8 (); /* 2 DDRA */
! 907: if (num) ciabdra = b; else ciaadra = b;
! 908: b = restore_u8 (); /* 3 DDRB */
! 909: if (num) ciabdrb = b; else ciaadrb = b;
! 910: w = restore_u16 (); /* 4 TA */
! 911: if (num) ciabta = w; else ciaata = w;
! 912: w = restore_u16 (); /* 6 TB */
! 913: if (num) ciabtb = w; else ciaatb = w;
! 914: l = restore_u8 (); /* 8/9/A TOD */
! 915: l |= restore_u8 () << 8;
! 916: l |= restore_u8 () << 16;
! 917: if (num) ciabtod = l; else ciaatod = l;
! 918: restore_u8 (); /* B unused */
! 919: b = restore_u8 (); /* C SDR */
! 920: if (num) ciabsdr = b; else ciaasdr = b;
! 921: b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
! 922: if (num) ciabicr = b; else ciaaicr = b;
! 923: b = restore_u8 (); /* E CRA */
! 924: if (num) ciabcra = b; else ciaacra = b;
! 925: b = restore_u8 (); /* F CRB */
! 926: if (num) ciabcrb = b; else ciaacrb = b;
! 927:
! 928: /* CIA internal data */
! 929:
! 930: b = restore_u8 (); /* ICR MASK */
! 931: if (num) ciabimask = b; else ciaaimask = b;
! 932: w = restore_u8 (); /* timer A latch */
! 933: w |= restore_u8 () << 8;
! 934: if (num) ciabla = w; else ciaala = b;
! 935: w = restore_u8 (); /* timer B latch */
! 936: w |= restore_u8 () << 8;
! 937: if (num) ciablb = w; else ciaalb = w;
! 938: w = restore_u8 (); /* TOD latched value */
! 939: w |= restore_u8 () << 8;
! 940: w |= restore_u8 () << 16;
! 941: if (num) ciabtol = w; else ciaatol = w;
! 942: l = restore_u8 (); /* alarm */
! 943: l |= restore_u8 () << 8;
! 944: l |= restore_u8 () << 16;
! 945: if (num) ciabalarm = l; else ciaaalarm = l;
! 946: b = restore_u8 ();
! 947: if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
! 948: if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
! 949: if (num) {
! 950: div10 = CYCLE_UNIT * restore_u8 ();
! 951: }
! 952: return src;
! 953: }
! 954:
! 955: uae_u8 *save_cia (int num, int *len)
! 956: {
! 957: uae_u8 *dstbak,*dst, b;
! 958: uae_u16 t;
! 959:
! 960: dstbak = dst = malloc (16 + 12 + 1);
! 961:
! 962: compute_passed_time ();
! 963:
! 964: /* CIA registers */
! 965:
! 966: b = num ? ciabpra : ciaapra; /* 0 PRA */
! 967: save_u8 (b);
! 968: b = num ? ciabprb : ciaaprb; /* 1 PRB */
! 969: save_u8 (b);
! 970: b = num ? ciabdra : ciaadra; /* 2 DDRA */
! 971: save_u8 (b);
! 972: b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
! 973: save_u8 (b);
! 974: t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
! 975: save_u16 (t);
! 976: t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 8 TB */
! 977: save_u16 (t);
! 978: b = (num ? ciabtod : ciaatod); /* 8 TODL */
! 979: save_u8 (b);
! 980: b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
! 981: save_u8 (b);
! 982: b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
! 983: save_u8 (b);
! 984: save_u8 (0); /* B unused */
! 985: b = num ? ciabsdr : ciaasdr; /* C SDR */
! 986: save_u8 (b);
! 987: b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
! 988: save_u8 (b);
! 989: b = num ? ciabcra : ciaacra; /* E CRA */
! 990: save_u8 (b);
! 991: b = num ? ciabcrb : ciaacrb; /* F CRB */
! 992: save_u8 (b);
! 993:
! 994: /* CIA internal data */
! 995:
! 996: save_u8 (num ? ciabimask : ciaaimask); /* ICR */
! 997: b = (num ? ciabla : ciaala); /* timer A latch LO */
! 998: save_u8 (b);
! 999: b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
! 1000: save_u8 (b);
! 1001: b = (num ? ciablb : ciaalb); /* timer B latch LO */
! 1002: save_u8 (b);
! 1003: b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
! 1004: save_u8 (b);
! 1005: b = (num ? ciabtol : ciaatol); /* latched TOD LO */
! 1006: save_u8 (b);
! 1007: b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
! 1008: save_u8 (b);
! 1009: b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
! 1010: save_u8 (b);
! 1011: b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
! 1012: save_u8 (b);
! 1013: b = (num ? ciabalarm >> 8 : ciaaalarm >>8 ); /* alarm MED */
! 1014: save_u8 (b);
! 1015: b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
! 1016: save_u8 (b);
! 1017: b = 0;
! 1018: if (num)
! 1019: b |= ciabtlatch ? 1 : 0;
! 1020: else
! 1021: b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
! 1022: if (num)
! 1023: b |= ciabtodon ? 2 : 0;
! 1024: else
! 1025: b |= ciaatodon ? 2 : 0; /* TOD stopped? */
! 1026: save_u8 (b);
! 1027: if (num) {
! 1028: /* Save extra state with CIAB. */
! 1029: save_u8 (div10 / CYCLE_UNIT);
! 1030: }
! 1031: *len = dst - dstbak;
! 1032: return dstbak;
! 1033: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.