|
|
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.16! root 48: static unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask;
! 49: static unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb;
1.1.1.10 root 50:
51: /* Values of the CIA timers. */
1.1.1.16! root 52: static unsigned long ciaata, ciaatb, ciabta, ciabtb;
1.1.1.10 root 53: /* Computed by compute_passed_time. */
1.1.1.16! root 54: static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
1.1.1.10 root 55:
1.1.1.16! root 56: static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
! 57: static int ciaatlatch, ciabtlatch;
1.1.1.3 root 58:
1.1.1.16! root 59: static unsigned int ciabpra;
1.1.1.3 root 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. */
1.1.1.15 root 231: /* This may overflow, however. So just ignore this timer and
232: use the fact that we'll call CIA_handler for the A timer. */
233: #if 0
1.1 root 234: ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
1.1.1.15 root 235: #endif
1.1 root 236: }
237: }
238: }
239: if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10 root 240: ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb;
1.1 root 241: }
242:
243: if ((ciabcra & 0x21) == 0x01) {
1.1.1.10 root 244: ciabtimea = (DIV10 - div10) + DIV10 * ciabta;
1.1 root 245: }
246: if ((ciabcrb & 0x61) == 0x41) {
247: /* Timer B will not get any pulses if Timer A is off. */
248: if (ciabtimea >= 0) {
249: /* If Timer A is in one-shot mode, and Timer B needs more than
250: * one pulse, it will not underflow. */
251: if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
252: /* Otherwise, we can determine the time of the underflow. */
1.1.1.15 root 253: #if 0
1.1 root 254: ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
1.1.1.15 root 255: #endif
1.1 root 256: }
257: }
258: }
259: if ((ciabcrb & 0x61) == 0x01) {
1.1.1.10 root 260: ciabtimeb = (DIV10 - div10) + DIV10 * ciabtb;
1.1 root 261: }
262: eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
263: || ciabtimea != -1 || ciabtimeb != -1);
264: if (eventtab[ev_cia].active) {
265: unsigned long int ciatime = ~0L;
266: if (ciaatimea != -1) ciatime = ciaatimea;
267: if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
268: if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
269: if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
1.1.1.10 root 270: eventtab[ev_cia].evtime = ciatime + get_cycles ();
1.1 root 271: }
272: events_schedule();
273: }
274:
1.1.1.10 root 275: void CIA_handler (void)
1.1 root 276: {
1.1.1.10 root 277: CIA_update ();
278: CIA_calctimers ();
1.1 root 279: }
280:
1.1.1.10 root 281: void cia_diskindex (void)
1.1 root 282: {
283: ciabicr |= 0x10;
284: RethinkICRB();
285: }
286:
1.1.1.10 root 287: void CIA_hsync_handler (void)
1.1 root 288: {
1.1.1.3 root 289: static unsigned int keytime = 0, sleepyhead = 0;
1.1 root 290:
291: if (ciabtodon)
292: ciabtod++;
293: ciabtod &= 0xFFFFFF;
294:
295: if (ciabtod == ciabalarm) {
296: ciabicr |= 4; RethinkICRB();
297: }
1.1.1.3 root 298:
299: /* check wether the serial port gets some data */
300: if (doreadser)
301: doreadser = SERDATS();
302:
1.1 root 303: if (keys_available() && kback && (++keytime & 15) == 0) {
1.1.1.3 root 304: /*
1.1.1.2 root 305: * This hack lets one possible ciaaicr cycle go by without any key
306: * being read, for every cycle in which a key is pulled out of the
307: * queue. If no hack is used, a lot of key events just get lost
308: * when you type fast. With a simple hack that waits for ciaasdr
309: * to be read before feeding it another, it will keep up until the
310: * queue gets about 14 characters ahead and then lose events, and
311: * the mouse pointer will freeze while typing is being taken in.
312: * With this hack, you can type 30 or 40 characters ahead with little
313: * or no lossage, and the mouse doesn't get stuck. The tradeoff is
314: * that the total slowness of typing appearing on screen is worse.
315: */
1.1.1.3 root 316: if (ciaasdr_unread == 2)
317: ciaasdr_unread = 0;
318: else if (ciaasdr_unread == 0) {
319: switch (kbstate) {
1.1.1.2 root 320: case 0:
1.1.1.3 root 321: ciaasdr = (uae_s8)~0xFB; /* aaarghh... stupid compiler */
322: kbstate++;
323: break;
1.1.1.2 root 324: case 1:
1.1.1.3 root 325: kbstate++;
326: ciaasdr = (uae_s8)~0xFD;
327: break;
1.1.1.2 root 328: case 2:
1.1.1.3 root 329: ciaasdr = ~get_next_key();
330: ciaasdr_unread = 1; /* interlock to prevent lost keystrokes */
331: break;
1.1.1.2 root 332: }
333: ciaaicr |= 8;
334: RethinkICRA();
335: sleepyhead = 0;
1.1.1.3 root 336: } else if (!(++sleepyhead & 15))
337: ciaasdr_unread = 0; /* give up on this key event after unread for a long time */
1.1 root 338: }
339: }
340:
1.1.1.10 root 341: void CIA_vsync_handler ()
1.1.1.3 root 342: {
343: if (ciaatodon)
1.1 root 344: ciaatod++;
345: ciaatod &= 0xFFFFFF;
346: if (ciaatod == ciaaalarm) {
347: ciaaicr |= 4; RethinkICRA();
348: }
1.1.1.3 root 349:
350: doreadser = 1;
351: serstat = -1;
352: serial_flush_buffer();
1.1 root 353: }
354:
1.1.1.10 root 355: static uae_u8 ReadCIAA (unsigned int addr)
1.1 root 356: {
1.1.1.3 root 357: unsigned int tmp;
358:
1.1.1.10 root 359: compute_passed_time ();
360:
361: switch (addr & 0xf) {
1.1.1.7 root 362: case 0:
1.1.1.3 root 363: if (currprefs.use_serial && (serstat < 0)) /* Only read status when needed */
364: serstat=serial_readstatus(); /* and only once per frame */
365:
1.1 root 366: tmp = (DISK_status() & 0x3C);
1.1.1.6 root 367: if ((JSEM_ISMOUSE (0, &currprefs) && !buttonstate[0])
368: || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1)))
1.1.1.3 root 369: tmp |= 0x40;
370: if (!(joy1button & 1))
371: tmp |= 0x80;
1.1 root 372: return tmp;
1.1.1.7 root 373: case 1:
374: /* Returning 0xFF is necessary for Tie Break - otherwise its joystick
375: code won't work. */
376: return prtopen ? ciaaprb : 0xFF;
377: case 2:
1.1 root 378: return ciaadra;
1.1.1.7 root 379: case 3:
1.1 root 380: return ciaadrb;
1.1.1.7 root 381: case 4:
1.1.1.10 root 382: return (ciaata - ciaata_passed) & 0xff;
1.1.1.7 root 383: case 5:
1.1.1.10 root 384: return (ciaata - ciaata_passed) >> 8;
1.1.1.7 root 385: case 6:
1.1.1.10 root 386: return (ciaatb - ciaatb_passed) & 0xff;
1.1.1.7 root 387: case 7:
1.1.1.10 root 388: return (ciaatb - ciaatb_passed) >> 8;
1.1.1.7 root 389: case 8:
1.1 root 390: if (ciaatlatch) {
391: ciaatlatch = 0;
392: return ciaatol & 0xff;
1.1.1.3 root 393: } else
394: return ciaatod & 0xff;
1.1.1.7 root 395: case 9:
1.1.1.3 root 396: if (ciaatlatch)
397: return (ciaatol >> 8) & 0xff;
398: else
399: return (ciaatod >> 8) & 0xff;
1.1.1.7 root 400: case 10:
1.1.1.3 root 401: ciaatlatch = 1;
402: ciaatol = ciaatod; /* ??? only if not already latched? */
1.1 root 403: return (ciaatol >> 16) & 0xff;
1.1.1.7 root 404: case 12:
1.1.1.3 root 405: if (ciaasdr == 1) ciaasdr_unread = 2;
1.1 root 406: return ciaasdr;
1.1.1.7 root 407: case 13:
1.1 root 408: tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
1.1.1.7 root 409: case 14:
1.1 root 410: return ciaacra;
1.1.1.7 root 411: case 15:
1.1 root 412: return ciaacrb;
413: }
414: return 0;
415: }
416:
1.1.1.10 root 417: static uae_u8 ReadCIAB (unsigned int addr)
1.1 root 418: {
1.1.1.3 root 419: unsigned int tmp;
420:
1.1.1.10 root 421: compute_passed_time ();
422:
423: switch (addr & 0xf) {
1.1.1.7 root 424: case 0:
1.1.1.3 root 425: if (currprefs.use_serial && serstat < 0) /* Only read status when needed */
426: serstat=serial_readstatus(); /* and only once per frame */
1.1.1.7 root 427: /* Returning some 1 bits is necessary for Tie Break - otherwise its joystick
428: code won't work. */
429: return ciabpra | (prtopen ? 0 : 3);
430: case 1:
1.1 root 431: return ciabprb;
1.1.1.7 root 432: case 2:
1.1 root 433: return ciabdra;
1.1.1.7 root 434: case 3:
1.1 root 435: return ciabdrb;
1.1.1.7 root 436: case 4:
1.1.1.10 root 437: return (ciabta - ciabta_passed) & 0xff;
1.1.1.7 root 438: case 5:
1.1.1.10 root 439: return (ciabta - ciabta_passed) >> 8;
1.1.1.7 root 440: case 6:
1.1.1.10 root 441: return (ciabtb - ciabtb_passed) & 0xff;
1.1.1.7 root 442: case 7:
1.1.1.10 root 443: return (ciabtb - ciabtb_passed) >> 8;
1.1.1.7 root 444: case 8:
1.1 root 445: if (ciabtlatch) {
446: ciabtlatch = 0;
447: return ciabtol & 0xff;
1.1.1.3 root 448: } else
449: return ciabtod & 0xff;
1.1.1.7 root 450: case 9:
1.1.1.3 root 451: if (ciabtlatch)
452: return (ciabtol >> 8) & 0xff;
453: else
454: return (ciabtod >> 8) & 0xff;
1.1.1.7 root 455: case 10:
1.1.1.3 root 456: ciabtlatch = 1;
457: ciabtol = ciabtod;
1.1 root 458: return (ciabtol >> 16) & 0xff;
1.1.1.7 root 459: case 12:
1.1 root 460: return ciabsdr;
1.1.1.7 root 461: case 13:
1.1 root 462: tmp = ciabicr; ciabicr = 0; RethinkICRB();
463: return tmp;
1.1.1.7 root 464: case 14:
1.1 root 465: return ciabcra;
1.1.1.7 root 466: case 15:
1.1 root 467: return ciabcrb;
468: }
469: return 0;
470: }
471:
1.1.1.10 root 472: static void WriteCIAA (uae_u16 addr,uae_u8 val)
1.1 root 473: {
1.1.1.3 root 474: int oldled, oldovl;
1.1.1.10 root 475: switch (addr & 0xf) {
1.1.1.7 root 476: case 0:
1.1.1.3 root 477: oldovl = ciaapra & 1;
1.1 root 478: oldled = ciaapra & 2;
1.1.1.11 root 479: ciaapra = (ciaapra & ~0x3) | (val & 0x3);
480: LED(ciaapra & 0x2);
1.1.1.3 root 481: gui_ledstate &= ~1;
482: gui_ledstate |= ((~ciaapra & 2) >> 1);
1.1.1.12 root 483: gui_data.powerled = ((~ciaapra & 2) >> 1);
1.1 root 484: if ((ciaapra & 2) != oldled)
485: gui_led (0, !(ciaapra & 2));
1.1.1.3 root 486: if ((ciaapra & 1) != oldovl) {
1.1.1.11 root 487: int i = (allocated_chipmem>>16) > 32 ? allocated_chipmem >> 16 : 32;
488:
489: if (oldovl || ersatzkickfile) {
490: map_banks (&chipmem_bank, 0, i, allocated_chipmem);
491: } else {
492: /* Is it OK to do this for more than 2M of chip? */
493: map_banks (&kickmem_bank, 0, i, 0x80000);
494: }
1.1.1.3 root 495: }
1.1 root 496: break;
1.1.1.7 root 497: case 1:
1.1 root 498: ciaaprb = val;
499: if (prtopen==1) {
500: #ifndef __DOS__
1.1.1.4 root 501: fprintf (prttmp, "%c",val);
1.1 root 502: #else
503: fputc (val, prttmp);
504: fflush (prttmp);
505: #endif
506: if (val==0x04) {
1.1.1.2 root 507: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1 root 508: pclose (prttmp);
509: #else
510: fclose (prttmp);
511: #endif
512: prtopen = 0;
513: }
1.1.1.3 root 514: } else {
1.1.1.2 root 515: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1.1.6 root 516: prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w");
1.1 root 517: #else
1.1.1.6 root 518: prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb");
1.1 root 519: #endif
520: if (prttmp != NULL) {
521: prtopen = 1;
522: #ifndef __DOS__
523: fprintf (prttmp,"%c",val);
524: #else
525: fputc (val, prttmp);
526: fflush (prttmp);
527: #endif
528: }
1.1.1.3 root 529: }
1.1 root 530: ciaaicr |= 0x10;
531: break;
1.1.1.7 root 532: case 2:
1.1 root 533: ciaadra = val; break;
1.1.1.7 root 534: case 3:
1.1 root 535: ciaadrb = val; break;
1.1.1.7 root 536: case 4:
1.1.1.10 root 537: CIA_update ();
1.1 root 538: ciaala = (ciaala & 0xff00) | val;
1.1.1.10 root 539: CIA_calctimers ();
1.1 root 540: break;
1.1.1.7 root 541: case 5:
1.1.1.10 root 542: CIA_update ();
1.1 root 543: ciaala = (ciaala & 0xff) | (val << 8);
544: if ((ciaacra & 1) == 0)
545: ciaata = ciaala;
1.1.1.3 root 546: if (ciaacra & 8) {
547: ciaata = ciaala;
548: ciaacra |= 1;
1.1 root 549: }
1.1.1.10 root 550: CIA_calctimers ();
1.1 root 551: break;
1.1.1.7 root 552: case 6:
1.1.1.10 root 553: CIA_update ();
1.1 root 554: ciaalb = (ciaalb & 0xff00) | val;
1.1.1.10 root 555: CIA_calctimers ();
1.1 root 556: break;
1.1.1.7 root 557: case 7:
1.1.1.10 root 558: CIA_update ();
1.1 root 559: ciaalb = (ciaalb & 0xff) | (val << 8);
560: if ((ciaacrb & 1) == 0)
561: ciaatb = ciaalb;
1.1.1.3 root 562: if (ciaacrb & 8) {
1.1 root 563: ciaatb = ciaalb;
1.1.1.3 root 564: ciaacrb |= 1;
1.1 root 565: }
1.1.1.10 root 566: CIA_calctimers ();
1.1 root 567: break;
1.1.1.7 root 568: case 8:
1.1.1.5 root 569: if (ciaacrb & 0x80) {
1.1 root 570: ciaaalarm = (ciaaalarm & ~0xff) | val;
571: } else {
572: ciaatod = (ciaatod & ~0xff) | val;
573: ciaatodon = 1;
574: }
575: break;
1.1.1.7 root 576: case 9:
1.1.1.5 root 577: if (ciaacrb & 0x80) {
1.1 root 578: ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
579: } else {
580: ciaatod = (ciaatod & ~0xff00) | (val << 8);
581: ciaatodon = 0;
582: }
583: break;
1.1.1.7 root 584: case 10:
1.1.1.5 root 585: if (ciaacrb & 0x80) {
1.1 root 586: ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
587: } else {
588: ciaatod = (ciaatod & ~0xff0000) | (val << 16);
589: ciaatodon = 0;
590: }
591: break;
1.1.1.7 root 592: case 12:
1.1 root 593: ciaasdr = val; break;
1.1.1.7 root 594: case 13:
1.1 root 595: setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
1.1.1.7 root 596: case 14:
1.1.1.10 root 597: CIA_update ();
1.1 root 598: ciaacra = val;
1.1.1.5 root 599: if (ciaacra & 0x10) {
1.1 root 600: ciaacra &= ~0x10;
601: ciaata = ciaala;
602: }
603: if (ciaacra & 0x40) {
604: kback = 1;
605: }
1.1.1.10 root 606: CIA_calctimers ();
1.1 root 607: break;
1.1.1.7 root 608: case 15:
1.1.1.10 root 609: CIA_update ();
1.1.1.3 root 610: ciaacrb = val;
1.1.1.5 root 611: if (ciaacrb & 0x10) {
1.1 root 612: ciaacrb &= ~0x10;
613: ciaatb = ciaalb;
614: }
1.1.1.10 root 615: CIA_calctimers ();
1.1 root 616: break;
617: }
618: }
619:
1.1.1.10 root 620: static void WriteCIAB (uae_u16 addr,uae_u8 val)
1.1 root 621: {
1.1.1.3 root 622: int oldval;
1.1.1.10 root 623: switch (addr & 0xf) {
1.1.1.7 root 624: case 0:
1.1.1.3 root 625: if (currprefs.use_serial) {
1.1.1.7 root 626: oldval = ciabpra;
627: ciabpra = serial_writestatus(oldval,val);
1.1.1.3 root 628: } else
1.1.1.7 root 629: ciabpra = val;
1.1.1.3 root 630: break;
1.1.1.7 root 631: case 1:
1.1 root 632: ciabprb = val; DISK_select(val); break;
1.1.1.7 root 633: case 2:
1.1 root 634: ciabdra = val; break;
1.1.1.7 root 635: case 3:
1.1 root 636: ciabdrb = val; break;
1.1.1.7 root 637: case 4:
1.1.1.10 root 638: CIA_update ();
1.1 root 639: ciabla = (ciabla & 0xff00) | val;
1.1.1.10 root 640: CIA_calctimers ();
1.1 root 641: break;
1.1.1.7 root 642: case 5:
1.1.1.10 root 643: CIA_update ();
1.1 root 644: ciabla = (ciabla & 0xff) | (val << 8);
1.1.1.3 root 645: if ((ciabcra & 1) == 0)
1.1 root 646: ciabta = ciabla;
647: if (ciabcra & 8) {
1.1.1.3 root 648: ciabta = ciabla;
649: ciabcra |= 1;
650: }
1.1.1.10 root 651: CIA_calctimers ();
1.1 root 652: break;
1.1.1.7 root 653: case 6:
1.1.1.10 root 654: CIA_update ();
1.1 root 655: ciablb = (ciablb & 0xff00) | val;
1.1.1.10 root 656: CIA_calctimers ();
1.1 root 657: break;
1.1.1.7 root 658: case 7:
1.1.1.10 root 659: CIA_update ();
1.1 root 660: ciablb = (ciablb & 0xff) | (val << 8);
661: if ((ciabcrb & 1) == 0)
662: ciabtb = ciablb;
663: if (ciabcrb & 8) {
664: ciabtb = ciablb;
665: ciabcrb |= 1;
666: }
1.1.1.10 root 667: CIA_calctimers ();
1.1 root 668: break;
1.1.1.7 root 669: case 8:
1.1.1.5 root 670: if (ciabcrb & 0x80) {
1.1 root 671: ciabalarm = (ciabalarm & ~0xff) | val;
672: } else {
673: ciabtod = (ciabtod & ~0xff) | val;
674: ciabtodon = 1;
675: }
676: break;
1.1.1.7 root 677: case 9:
1.1.1.5 root 678: if (ciabcrb & 0x80) {
1.1 root 679: ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
680: } else {
681: ciabtod = (ciabtod & ~0xff00) | (val << 8);
682: ciabtodon = 0;
683: }
684: break;
1.1.1.7 root 685: case 10:
1.1.1.5 root 686: if (ciabcrb & 0x80) {
1.1 root 687: ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
688: } else {
689: ciabtod = (ciabtod & ~0xff0000) | (val << 16);
690: ciabtodon = 0;
691: }
692: break;
1.1.1.7 root 693: case 12:
1.1.1.3 root 694: ciabsdr = val;
1.1 root 695: break;
1.1.1.7 root 696: case 13:
1.1.1.3 root 697: setclr(&ciabimask,val);
1.1 root 698: break;
1.1.1.7 root 699: case 14:
1.1.1.10 root 700: CIA_update ();
1.1 root 701: ciabcra = val;
1.1.1.5 root 702: if (ciabcra & 0x10) {
1.1 root 703: ciabcra &= ~0x10;
704: ciabta = ciabla;
705: }
1.1.1.10 root 706: CIA_calctimers ();
1.1 root 707: break;
1.1.1.7 root 708: case 15:
1.1.1.10 root 709: CIA_update ();
1.1.1.3 root 710: ciabcrb = val;
1.1.1.5 root 711: if (ciabcrb & 0x10) {
1.1 root 712: ciabcrb &= ~0x10;
713: ciabtb = ciablb;
714: }
1.1.1.10 root 715: CIA_calctimers ();
1.1 root 716: break;
717: }
718: }
719:
1.1.1.10 root 720: void CIA_reset (void)
1.1 root 721: {
722: kback = 1;
723: kbstate = 0;
1.1.1.3 root 724:
1.1.1.11 root 725: if (!savestate_state) {
726: ciaatlatch = ciabtlatch = 0;
727: ciaapra = 3;
728: ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
729: ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
730: ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
731: ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
732: ciabpra = 0x8C;
1.1.1.13 root 733: div10 = 0;
1.1.1.11 root 734: }
1.1.1.10 root 735: CIA_calctimers ();
1.1.1.14 root 736: if (! ersatzkickfile) {
737: int i = allocated_chipmem > 0x200000 ? allocated_chipmem >> 16 : 32;
738: map_banks (&kickmem_bank, 0, i, 0x80000);
739: }
1.1.1.3 root 740:
1.1.1.11 root 741: if (currprefs.use_serial && !savestate_state)
742: serial_dtr_off (); /* Drop DTR at reset */
743:
744: if (savestate_state) {
745: /* Reset oldovl and oldled */
746: uae_u8 v = ReadCIAA (0);
747: WriteCIAA (0,3);
748: WriteCIAA (0,0);
749: WriteCIAA (0,v);
750: /* select drives */
751: DISK_select (ciabprb);
752: }
1.1 root 753: }
754:
1.1.1.10 root 755: void dumpcia (void)
1.1 root 756: {
1.1.1.13 root 757: printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n",
1.1.1.3 root 758: (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod,
1.1.1.13 root 759: ciaatlatch ? "L" : "", ciaata, ciaala, ciaatb, ciaalb);
760: printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n",
1.1.1.3 root 761: (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod,
1.1.1.13 root 762: ciabtlatch ? "L" : "", ciabta, ciabla, ciabtb, ciablb);
1.1 root 763: }
764:
765: /* CIA memory access */
766:
1.1.1.3 root 767: static uae_u32 cia_lget (uaecptr) REGPARAM;
768: static uae_u32 cia_wget (uaecptr) REGPARAM;
769: static uae_u32 cia_bget (uaecptr) REGPARAM;
770: static void cia_lput (uaecptr, uae_u32) REGPARAM;
771: static void cia_wput (uaecptr, uae_u32) REGPARAM;
772: static void cia_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 773:
774: addrbank cia_bank = {
775: cia_lget, cia_wget, cia_bget,
776: cia_lput, cia_wput, cia_bput,
1.1.1.11 root 777: default_xlate, default_check, NULL
1.1 root 778: };
779:
1.1.1.15 root 780: static void cia_wait (void)
1.1 root 781: {
1.1.1.15 root 782: if (!div10)
783: return;
784: do_cycles (DIV10 - div10 + CYCLE_UNIT);
785: CIA_handler ();
786: }
787:
788: uae_u32 REGPARAM2 cia_bget (uaecptr addr)
789: {
790: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 791: special_mem |= S_READ;
1.1.1.15 root 792: cia_wait ();
793: switch ((addr >> 12) & 3)
794: {
795: case 0:
796: return (addr & 1) ? ReadCIAA (r) : ReadCIAB (r);
797: case 1:
798: return (addr & 1) ? 0xff : ReadCIAB (r);
799: case 2:
800: return (addr & 1) ? ReadCIAA (r) : 0xff;
801: }
802: return 0xff;
1.1 root 803: }
804:
1.1.1.3 root 805: uae_u32 REGPARAM2 cia_wget (uaecptr addr)
1.1 root 806: {
1.1.1.15 root 807: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 808: special_mem |= S_READ;
1.1.1.15 root 809: cia_wait ();
810: switch ((addr >> 12) & 3)
811: {
812: case 0:
813: return (ReadCIAB (r) << 8) | ReadCIAA (r);
814: case 1:
815: return (ReadCIAB (r) << 8) | 0xff;
816: case 2:
817: return (0xff << 8) | ReadCIAA (r);
818: }
819: return 0xffff;
1.1 root 820: }
821:
1.1.1.15 root 822: uae_u32 REGPARAM2 cia_lget (uaecptr addr)
1.1 root 823: {
1.1.1.15 root 824: uae_u32 v;
1.1.1.9 root 825: special_mem |= S_READ;
1.1.1.15 root 826: v = cia_wget (addr) << 16;
827: v |= cia_wget (addr + 2);
828: return v;
1.1 root 829: }
830:
1.1.1.15 root 831: void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
1.1 root 832: {
1.1.1.15 root 833: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 834: special_mem |= S_WRITE;
1.1.1.15 root 835: cia_wait ();
836: if ((addr & 0x2000) == 0)
837: WriteCIAB (r, value);
838: if ((addr & 0x1000) == 0)
839: WriteCIAA (r, value);
1.1 root 840: }
841:
1.1.1.3 root 842: void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
1.1 root 843: {
1.1.1.15 root 844: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 845: special_mem |= S_WRITE;
1.1.1.15 root 846: cia_wait ();
847: if ((addr & 0x2000) == 0)
848: WriteCIAB (r, value >> 8);
849: if ((addr & 0x1000) == 0)
850: WriteCIAA (r, value & 0xff);
1.1 root 851: }
852:
1.1.1.15 root 853: void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
1.1 root 854: {
1.1.1.9 root 855: special_mem |= S_WRITE;
1.1.1.15 root 856: cia_wput (addr, value >> 16);
857: cia_wput (addr + 2, value & 0xffff);
1.1 root 858: }
859:
860: /* battclock memory access */
861:
1.1.1.3 root 862: static uae_u32 clock_lget (uaecptr) REGPARAM;
863: static uae_u32 clock_wget (uaecptr) REGPARAM;
864: static uae_u32 clock_bget (uaecptr) REGPARAM;
865: static void clock_lput (uaecptr, uae_u32) REGPARAM;
866: static void clock_wput (uaecptr, uae_u32) REGPARAM;
867: static void clock_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 868:
869: addrbank clock_bank = {
870: clock_lget, clock_wget, clock_bget,
871: clock_lput, clock_wput, clock_bput,
1.1.1.11 root 872: default_xlate, default_check, NULL
1.1 root 873: };
874:
1.1.1.3 root 875: uae_u32 REGPARAM2 clock_lget (uaecptr addr)
1.1 root 876: {
1.1.1.9 root 877: special_mem |= S_READ;
878: return clock_bget (addr + 3);
1.1 root 879: }
880:
1.1.1.3 root 881: uae_u32 REGPARAM2 clock_wget (uaecptr addr)
1.1 root 882: {
1.1.1.9 root 883: special_mem |= S_READ;
884: return clock_bget (addr + 1);
1.1 root 885: }
886:
1.1.1.3 root 887: uae_u32 REGPARAM2 clock_bget (uaecptr addr)
1.1 root 888: {
1.1.1.9 root 889: time_t t = time(0);
1.1 root 890: struct tm *ct;
1.1.1.9 root 891:
892: ct = localtime (&t);
893: special_mem |= S_READ;
894:
1.1.1.7 root 895: switch (addr & 0x3f) {
896: case 0x03: return ct->tm_sec % 10;
897: case 0x07: return ct->tm_sec / 10;
898: case 0x0b: return ct->tm_min % 10;
899: case 0x0f: return ct->tm_min / 10;
900: case 0x13: return ct->tm_hour % 10;
901: case 0x17: return ct->tm_hour / 10;
902: case 0x1b: return ct->tm_mday % 10;
903: case 0x1f: return ct->tm_mday / 10;
904: case 0x23: return (ct->tm_mon+1) % 10;
905: case 0x27: return (ct->tm_mon+1) / 10;
906: case 0x2b: return ct->tm_year % 10;
907: case 0x2f: return ct->tm_year / 10;
908:
909: case 0x33: return ct->tm_wday; /*Hack by -=SR=- */
910: case 0x37: return clock_control_d;
911: case 0x3b: return clock_control_e;
912: case 0x3f: return clock_control_f;
1.1 root 913: }
914: return 0;
915: }
916:
1.1.1.3 root 917: void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
1.1 root 918: {
1.1.1.9 root 919: special_mem |= S_WRITE;
1.1 root 920: /* No way */
921: }
922:
1.1.1.3 root 923: void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
1.1 root 924: {
1.1.1.9 root 925: special_mem |= S_WRITE;
1.1 root 926: /* No way */
927: }
928:
1.1.1.3 root 929: void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
1.1 root 930: {
1.1.1.9 root 931: special_mem |= S_WRITE;
1.1.1.7 root 932: switch (addr & 0x3f) {
1.1.1.9 root 933: case 0x37: clock_control_d = value; break;
934: case 0x3b: clock_control_e = value; break;
935: case 0x3f: clock_control_f = value; break;
1.1 root 936: }
937: }
1.1.1.11 root 938:
939: /* CIA-A and CIA-B save/restore code */
940:
941: uae_u8 *restore_cia (int num, uae_u8 *src)
942: {
943: uae_u8 b;
944: uae_u16 w;
945: uae_u32 l;
946:
947: /* CIA registers */
948: b = restore_u8 (); /* 0 PRA */
949: if (num) ciabpra = b; else ciaapra = b;
950: b = restore_u8 (); /* 1 PRB */
951: if (num) ciabprb = b; else ciaaprb = b;
952: b = restore_u8 (); /* 2 DDRA */
953: if (num) ciabdra = b; else ciaadra = b;
954: b = restore_u8 (); /* 3 DDRB */
955: if (num) ciabdrb = b; else ciaadrb = b;
956: w = restore_u16 (); /* 4 TA */
957: if (num) ciabta = w; else ciaata = w;
958: w = restore_u16 (); /* 6 TB */
959: if (num) ciabtb = w; else ciaatb = w;
960: l = restore_u8 (); /* 8/9/A TOD */
961: l |= restore_u8 () << 8;
962: l |= restore_u8 () << 16;
963: if (num) ciabtod = l; else ciaatod = l;
964: restore_u8 (); /* B unused */
965: b = restore_u8 (); /* C SDR */
966: if (num) ciabsdr = b; else ciaasdr = b;
967: b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
968: if (num) ciabicr = b; else ciaaicr = b;
969: b = restore_u8 (); /* E CRA */
970: if (num) ciabcra = b; else ciaacra = b;
971: b = restore_u8 (); /* F CRB */
972: if (num) ciabcrb = b; else ciaacrb = b;
973:
974: /* CIA internal data */
975:
976: b = restore_u8 (); /* ICR MASK */
977: if (num) ciabimask = b; else ciaaimask = b;
978: w = restore_u8 (); /* timer A latch */
979: w |= restore_u8 () << 8;
1.1.1.13 root 980: if (num) ciabla = w; else ciaala = w;
1.1.1.11 root 981: w = restore_u8 (); /* timer B latch */
982: w |= restore_u8 () << 8;
983: if (num) ciablb = w; else ciaalb = w;
984: w = restore_u8 (); /* TOD latched value */
985: w |= restore_u8 () << 8;
986: w |= restore_u8 () << 16;
987: if (num) ciabtol = w; else ciaatol = w;
988: l = restore_u8 (); /* alarm */
989: l |= restore_u8 () << 8;
990: l |= restore_u8 () << 16;
991: if (num) ciabalarm = l; else ciaaalarm = l;
992: b = restore_u8 ();
993: if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
994: if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
995: if (num) {
996: div10 = CYCLE_UNIT * restore_u8 ();
997: }
998: return src;
999: }
1000:
1001: uae_u8 *save_cia (int num, int *len)
1002: {
1003: uae_u8 *dstbak,*dst, b;
1004: uae_u16 t;
1005:
1006: dstbak = dst = malloc (16 + 12 + 1);
1007:
1008: compute_passed_time ();
1009:
1010: /* CIA registers */
1011:
1012: b = num ? ciabpra : ciaapra; /* 0 PRA */
1013: save_u8 (b);
1014: b = num ? ciabprb : ciaaprb; /* 1 PRB */
1015: save_u8 (b);
1016: b = num ? ciabdra : ciaadra; /* 2 DDRA */
1017: save_u8 (b);
1018: b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
1019: save_u8 (b);
1020: t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
1021: save_u16 (t);
1022: t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 8 TB */
1023: save_u16 (t);
1024: b = (num ? ciabtod : ciaatod); /* 8 TODL */
1025: save_u8 (b);
1026: b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
1027: save_u8 (b);
1028: b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
1029: save_u8 (b);
1030: save_u8 (0); /* B unused */
1031: b = num ? ciabsdr : ciaasdr; /* C SDR */
1032: save_u8 (b);
1033: b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
1034: save_u8 (b);
1035: b = num ? ciabcra : ciaacra; /* E CRA */
1036: save_u8 (b);
1037: b = num ? ciabcrb : ciaacrb; /* F CRB */
1038: save_u8 (b);
1039:
1040: /* CIA internal data */
1041:
1042: save_u8 (num ? ciabimask : ciaaimask); /* ICR */
1043: b = (num ? ciabla : ciaala); /* timer A latch LO */
1044: save_u8 (b);
1045: b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
1046: save_u8 (b);
1047: b = (num ? ciablb : ciaalb); /* timer B latch LO */
1048: save_u8 (b);
1049: b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
1050: save_u8 (b);
1051: b = (num ? ciabtol : ciaatol); /* latched TOD LO */
1052: save_u8 (b);
1053: b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
1054: save_u8 (b);
1055: b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
1056: save_u8 (b);
1057: b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
1058: save_u8 (b);
1059: b = (num ? ciabalarm >> 8 : ciaaalarm >>8 ); /* alarm MED */
1060: save_u8 (b);
1061: b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
1062: save_u8 (b);
1063: b = 0;
1064: if (num)
1065: b |= ciabtlatch ? 1 : 0;
1066: else
1067: b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
1068: if (num)
1069: b |= ciabtodon ? 2 : 0;
1070: else
1071: b |= ciaatodon ? 2 : 0; /* TOD stopped? */
1072: save_u8 (b);
1073: if (num) {
1074: /* Save extra state with CIAB. */
1075: save_u8 (div10 / CYCLE_UNIT);
1076: }
1077: *len = dst - dstbak;
1078: return dstbak;
1079: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.