|
|
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.17! root 86: INTREQ_0 (0x8000 | 0x0008);
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 (ciabimask & ciabicr) {
96: ciabicr |= 0x80;
1.1.1.17! root 97: INTREQ_0 (0x8000 | 0x2000);
1.1 root 98: } else {
99: ciabicr &= 0x7F;
100: }
101: }
102:
1.1.1.11 root 103: void rethink_cias (void)
104: {
105: RethinkICRA ();
106: RethinkICRB ();
107: }
108:
1.1.1.10 root 109: /* Figure out how many CIA timer cycles have passed for each timer since the
110: last call of CIA_calctimers. */
1.1 root 111:
1.1.1.10 root 112: static void compute_passed_time (void)
1.1 root 113: {
1.1.1.10 root 114: unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
115: unsigned long int ciaclocks = ccount / DIV10;
116:
117: ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
118:
119: /* CIA A timers */
120: if ((ciaacra & 0x21) == 0x01) {
121: assert ((ciaata+1) >= ciaclocks);
122: ciaata_passed = ciaclocks;
123: }
124: if ((ciaacrb & 0x61) == 0x01) {
125: assert ((ciaatb+1) >= ciaclocks);
126: ciaatb_passed = ciaclocks;
127: }
128:
129: /* CIA B timers */
130: if ((ciabcra & 0x21) == 0x01) {
131: assert ((ciabta+1) >= ciaclocks);
132: ciabta_passed = ciaclocks;
133: }
134: if ((ciabcrb & 0x61) == 0x01) {
135: assert ((ciabtb+1) >= ciaclocks);
136: ciabtb_passed = ciaclocks;
137: }
138: }
139:
140: /* Called to advance all CIA timers to the current time. This expects that
141: one of the timer values will be modified, and CIA_calctimers will be called
142: in the same cycle. */
143:
144: static void CIA_update (void)
145: {
146: unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
1.1 root 147: unsigned long int ciaclocks = ccount / DIV10;
148:
149: int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
150:
151: div10 = ccount % DIV10;
1.1.1.3 root 152:
1.1 root 153: /* CIA A timers */
154: if ((ciaacra & 0x21) == 0x01) {
1.1.1.10 root 155: assert ((ciaata+1) >= ciaclocks);
1.1 root 156: if ((ciaata+1) == ciaclocks) {
157: aovfla = 1;
158: if ((ciaacrb & 0x61) == 0x41) {
1.1.1.3 root 159: if (ciaatb-- == 0) aovflb = 1;
1.1 root 160: }
1.1.1.3 root 161: }
1.1 root 162: ciaata -= ciaclocks;
163: }
164: if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10 root 165: assert ((ciaatb+1) >= ciaclocks);
1.1 root 166: if ((ciaatb+1) == ciaclocks) aovflb = 1;
167: ciaatb -= ciaclocks;
168: }
1.1.1.3 root 169:
1.1 root 170: /* CIA B timers */
171: if ((ciabcra & 0x21) == 0x01) {
1.1.1.10 root 172: assert ((ciabta+1) >= ciaclocks);
1.1 root 173: if ((ciabta+1) == ciaclocks) {
174: bovfla = 1;
175: if ((ciabcrb & 0x61) == 0x41) {
176: if (ciabtb-- == 0) bovflb = 1;
177: }
1.1.1.3 root 178: }
1.1 root 179: ciabta -= ciaclocks;
180: }
181: if ((ciabcrb & 0x61) == 0x01) {
182: assert ((ciabtb+1) >= ciaclocks);
183: if ((ciabtb+1) == ciaclocks) bovflb = 1;
184: ciabtb -= ciaclocks;
185: }
186: if (aovfla) {
187: ciaaicr |= 1; RethinkICRA();
188: ciaata = ciaala;
189: if (ciaacra & 0x8) ciaacra &= ~1;
190: }
191: if (aovflb) {
192: ciaaicr |= 2; RethinkICRA();
193: ciaatb = ciaalb;
194: if (ciaacrb & 0x8) ciaacrb &= ~1;
195: }
196: if (bovfla) {
197: ciabicr |= 1; RethinkICRB();
198: ciabta = ciabla;
199: if (ciabcra & 0x8) ciabcra &= ~1;
200: }
201: if (bovflb) {
202: ciabicr |= 2; RethinkICRB();
203: ciabtb = ciablb;
204: if (ciabcrb & 0x8) ciabcrb &= ~1;
205: }
206: }
207:
1.1.1.10 root 208: /* Call this only after CIA_update has been called in the same cycle. */
209:
210: static void CIA_calctimers (void)
1.1 root 211: {
1.1.1.17! root 212: long int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
1.1 root 213:
1.1.1.10 root 214: eventtab[ev_cia].oldcycles = get_cycles ();
1.1 root 215: if ((ciaacra & 0x21) == 0x01) {
1.1.1.10 root 216: ciaatimea = (DIV10 - div10) + DIV10 * ciaata;
1.1 root 217: }
218: if ((ciaacrb & 0x61) == 0x41) {
219: /* Timer B will not get any pulses if Timer A is off. */
220: if (ciaatimea >= 0) {
221: /* If Timer A is in one-shot mode, and Timer B needs more than
222: * one pulse, it will not underflow. */
223: if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
224: /* Otherwise, we can determine the time of the underflow. */
1.1.1.15 root 225: /* This may overflow, however. So just ignore this timer and
226: use the fact that we'll call CIA_handler for the A timer. */
227: #if 0
1.1 root 228: ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
1.1.1.15 root 229: #endif
1.1 root 230: }
231: }
232: }
233: if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10 root 234: ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb;
1.1 root 235: }
236:
237: if ((ciabcra & 0x21) == 0x01) {
1.1.1.10 root 238: ciabtimea = (DIV10 - div10) + DIV10 * ciabta;
1.1 root 239: }
240: if ((ciabcrb & 0x61) == 0x41) {
241: /* Timer B will not get any pulses if Timer A is off. */
242: if (ciabtimea >= 0) {
243: /* If Timer A is in one-shot mode, and Timer B needs more than
244: * one pulse, it will not underflow. */
245: if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
246: /* Otherwise, we can determine the time of the underflow. */
1.1.1.15 root 247: #if 0
1.1 root 248: ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
1.1.1.15 root 249: #endif
1.1 root 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.17! root 310: if (ciaasdr_unread == 2) {
1.1.1.3 root 311: ciaasdr_unread = 0;
1.1.1.17! root 312: } else if (ciaasdr_unread == 0) {
1.1.1.3 root 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.17! root 330: } else if (!(++sleepyhead & 15)) {
1.1.1.3 root 331: ciaasdr_unread = 0; /* give up on this key event after unread for a long time */
1.1.1.17! root 332: }
1.1 root 333: }
334: }
335:
1.1.1.10 root 336: void CIA_vsync_handler ()
1.1.1.3 root 337: {
338: if (ciaatodon)
1.1 root 339: ciaatod++;
340: ciaatod &= 0xFFFFFF;
341: if (ciaatod == ciaaalarm) {
342: ciaaicr |= 4; RethinkICRA();
343: }
1.1.1.3 root 344:
345: doreadser = 1;
346: serstat = -1;
347: serial_flush_buffer();
1.1 root 348: }
349:
1.1.1.10 root 350: static uae_u8 ReadCIAA (unsigned int addr)
1.1 root 351: {
1.1.1.3 root 352: unsigned int tmp;
353:
1.1.1.10 root 354: compute_passed_time ();
355:
356: switch (addr & 0xf) {
1.1.1.7 root 357: case 0:
1.1.1.3 root 358: if (currprefs.use_serial && (serstat < 0)) /* Only read status when needed */
359: serstat=serial_readstatus(); /* and only once per frame */
360:
1.1 root 361: tmp = (DISK_status() & 0x3C);
1.1.1.6 root 362: if ((JSEM_ISMOUSE (0, &currprefs) && !buttonstate[0])
363: || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1)))
1.1.1.3 root 364: tmp |= 0x40;
365: if (!(joy1button & 1))
366: tmp |= 0x80;
1.1 root 367: return tmp;
1.1.1.7 root 368: case 1:
369: /* Returning 0xFF is necessary for Tie Break - otherwise its joystick
370: code won't work. */
371: return prtopen ? ciaaprb : 0xFF;
372: case 2:
1.1 root 373: return ciaadra;
1.1.1.7 root 374: case 3:
1.1 root 375: return ciaadrb;
1.1.1.7 root 376: case 4:
1.1.1.10 root 377: return (ciaata - ciaata_passed) & 0xff;
1.1.1.7 root 378: case 5:
1.1.1.10 root 379: return (ciaata - ciaata_passed) >> 8;
1.1.1.7 root 380: case 6:
1.1.1.10 root 381: return (ciaatb - ciaatb_passed) & 0xff;
1.1.1.7 root 382: case 7:
1.1.1.10 root 383: return (ciaatb - ciaatb_passed) >> 8;
1.1.1.7 root 384: case 8:
1.1 root 385: if (ciaatlatch) {
386: ciaatlatch = 0;
387: return ciaatol & 0xff;
1.1.1.3 root 388: } else
389: return ciaatod & 0xff;
1.1.1.7 root 390: case 9:
1.1.1.3 root 391: if (ciaatlatch)
392: return (ciaatol >> 8) & 0xff;
393: else
394: return (ciaatod >> 8) & 0xff;
1.1.1.7 root 395: case 10:
1.1.1.3 root 396: ciaatlatch = 1;
397: ciaatol = ciaatod; /* ??? only if not already latched? */
1.1 root 398: return (ciaatol >> 16) & 0xff;
1.1.1.7 root 399: case 12:
1.1.1.3 root 400: if (ciaasdr == 1) ciaasdr_unread = 2;
1.1 root 401: return ciaasdr;
1.1.1.7 root 402: case 13:
1.1.1.17! root 403: tmp = ciaaicr; ciaaicr = 0; RethinkICRA();
! 404: return tmp;
1.1.1.7 root 405: case 14:
1.1 root 406: return ciaacra;
1.1.1.7 root 407: case 15:
1.1 root 408: return ciaacrb;
409: }
410: return 0;
411: }
412:
1.1.1.10 root 413: static uae_u8 ReadCIAB (unsigned int addr)
1.1 root 414: {
1.1.1.3 root 415: unsigned int tmp;
416:
1.1.1.10 root 417: compute_passed_time ();
418:
419: switch (addr & 0xf) {
1.1.1.7 root 420: case 0:
1.1.1.3 root 421: if (currprefs.use_serial && serstat < 0) /* Only read status when needed */
422: serstat=serial_readstatus(); /* and only once per frame */
1.1.1.7 root 423: /* Returning some 1 bits is necessary for Tie Break - otherwise its joystick
424: code won't work. */
425: return ciabpra | (prtopen ? 0 : 3);
426: case 1:
1.1 root 427: return ciabprb;
1.1.1.7 root 428: case 2:
1.1 root 429: return ciabdra;
1.1.1.7 root 430: case 3:
1.1 root 431: return ciabdrb;
1.1.1.7 root 432: case 4:
1.1.1.10 root 433: return (ciabta - ciabta_passed) & 0xff;
1.1.1.7 root 434: case 5:
1.1.1.10 root 435: return (ciabta - ciabta_passed) >> 8;
1.1.1.7 root 436: case 6:
1.1.1.10 root 437: return (ciabtb - ciabtb_passed) & 0xff;
1.1.1.7 root 438: case 7:
1.1.1.10 root 439: return (ciabtb - ciabtb_passed) >> 8;
1.1.1.7 root 440: case 8:
1.1 root 441: if (ciabtlatch) {
442: ciabtlatch = 0;
443: return ciabtol & 0xff;
1.1.1.3 root 444: } else
445: return ciabtod & 0xff;
1.1.1.7 root 446: case 9:
1.1.1.3 root 447: if (ciabtlatch)
448: return (ciabtol >> 8) & 0xff;
449: else
450: return (ciabtod >> 8) & 0xff;
1.1.1.7 root 451: case 10:
1.1.1.3 root 452: ciabtlatch = 1;
453: ciabtol = ciabtod;
1.1 root 454: return (ciabtol >> 16) & 0xff;
1.1.1.7 root 455: case 12:
1.1 root 456: return ciabsdr;
1.1.1.7 root 457: case 13:
1.1 root 458: tmp = ciabicr; ciabicr = 0; RethinkICRB();
459: return tmp;
1.1.1.7 root 460: case 14:
1.1 root 461: return ciabcra;
1.1.1.7 root 462: case 15:
1.1 root 463: return ciabcrb;
464: }
465: return 0;
466: }
467:
1.1.1.10 root 468: static void WriteCIAA (uae_u16 addr,uae_u8 val)
1.1 root 469: {
1.1.1.3 root 470: int oldled, oldovl;
1.1.1.10 root 471: switch (addr & 0xf) {
1.1.1.7 root 472: case 0:
1.1.1.3 root 473: oldovl = ciaapra & 1;
1.1 root 474: oldled = ciaapra & 2;
1.1.1.11 root 475: ciaapra = (ciaapra & ~0x3) | (val & 0x3);
476: LED(ciaapra & 0x2);
1.1.1.3 root 477: gui_ledstate &= ~1;
478: gui_ledstate |= ((~ciaapra & 2) >> 1);
1.1.1.12 root 479: gui_data.powerled = ((~ciaapra & 2) >> 1);
1.1 root 480: if ((ciaapra & 2) != oldled)
481: gui_led (0, !(ciaapra & 2));
1.1.1.3 root 482: if ((ciaapra & 1) != oldovl) {
1.1.1.11 root 483: int i = (allocated_chipmem>>16) > 32 ? allocated_chipmem >> 16 : 32;
484:
485: if (oldovl || ersatzkickfile) {
486: map_banks (&chipmem_bank, 0, i, allocated_chipmem);
487: } else {
488: /* Is it OK to do this for more than 2M of chip? */
489: map_banks (&kickmem_bank, 0, i, 0x80000);
490: }
1.1.1.3 root 491: }
1.1 root 492: break;
1.1.1.7 root 493: case 1:
1.1 root 494: ciaaprb = val;
495: if (prtopen==1) {
496: #ifndef __DOS__
1.1.1.4 root 497: fprintf (prttmp, "%c",val);
1.1 root 498: #else
499: fputc (val, prttmp);
500: fflush (prttmp);
501: #endif
502: if (val==0x04) {
1.1.1.2 root 503: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1 root 504: pclose (prttmp);
505: #else
506: fclose (prttmp);
507: #endif
508: prtopen = 0;
509: }
1.1.1.3 root 510: } else {
1.1.1.2 root 511: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1.1.6 root 512: prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w");
1.1 root 513: #else
1.1.1.6 root 514: prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb");
1.1 root 515: #endif
516: if (prttmp != NULL) {
517: prtopen = 1;
518: #ifndef __DOS__
519: fprintf (prttmp,"%c",val);
520: #else
521: fputc (val, prttmp);
522: fflush (prttmp);
523: #endif
524: }
1.1.1.3 root 525: }
1.1 root 526: ciaaicr |= 0x10;
527: break;
1.1.1.7 root 528: case 2:
1.1.1.17! root 529: ciaadra = val;
! 530: break;
1.1.1.7 root 531: case 3:
1.1.1.17! root 532: ciaadrb = val;
! 533: break;
1.1.1.7 root 534: case 4:
1.1.1.10 root 535: CIA_update ();
1.1 root 536: ciaala = (ciaala & 0xff00) | val;
1.1.1.10 root 537: CIA_calctimers ();
1.1 root 538: break;
1.1.1.7 root 539: case 5:
1.1.1.10 root 540: CIA_update ();
1.1 root 541: ciaala = (ciaala & 0xff) | (val << 8);
542: if ((ciaacra & 1) == 0)
543: ciaata = ciaala;
1.1.1.3 root 544: if (ciaacra & 8) {
545: ciaata = ciaala;
546: ciaacra |= 1;
1.1 root 547: }
1.1.1.10 root 548: CIA_calctimers ();
1.1 root 549: break;
1.1.1.7 root 550: case 6:
1.1.1.10 root 551: CIA_update ();
1.1 root 552: ciaalb = (ciaalb & 0xff00) | val;
1.1.1.10 root 553: CIA_calctimers ();
1.1 root 554: break;
1.1.1.7 root 555: case 7:
1.1.1.10 root 556: CIA_update ();
1.1 root 557: ciaalb = (ciaalb & 0xff) | (val << 8);
558: if ((ciaacrb & 1) == 0)
559: ciaatb = ciaalb;
1.1.1.3 root 560: if (ciaacrb & 8) {
1.1 root 561: ciaatb = ciaalb;
1.1.1.3 root 562: ciaacrb |= 1;
1.1 root 563: }
1.1.1.10 root 564: CIA_calctimers ();
1.1 root 565: break;
1.1.1.7 root 566: case 8:
1.1.1.5 root 567: if (ciaacrb & 0x80) {
1.1 root 568: ciaaalarm = (ciaaalarm & ~0xff) | val;
569: } else {
570: ciaatod = (ciaatod & ~0xff) | val;
571: ciaatodon = 1;
572: }
573: break;
1.1.1.7 root 574: case 9:
1.1.1.5 root 575: if (ciaacrb & 0x80) {
1.1 root 576: ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
577: } else {
578: ciaatod = (ciaatod & ~0xff00) | (val << 8);
579: ciaatodon = 0;
580: }
581: break;
1.1.1.7 root 582: case 10:
1.1.1.5 root 583: if (ciaacrb & 0x80) {
1.1 root 584: ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
585: } else {
586: ciaatod = (ciaatod & ~0xff0000) | (val << 16);
587: ciaatodon = 0;
588: }
589: break;
1.1.1.7 root 590: case 12:
1.1.1.17! root 591: ciaasdr = val;
! 592: break;
1.1.1.7 root 593: case 13:
1.1.1.17! root 594: setclr(&ciaaimask,val);
! 595: break;
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: }
1.1.1.17! root 603: if (ciaacra & 0x40)
1.1 root 604: kback = 1;
1.1.1.10 root 605: CIA_calctimers ();
1.1 root 606: break;
1.1.1.7 root 607: case 15:
1.1.1.10 root 608: CIA_update ();
1.1.1.3 root 609: ciaacrb = val;
1.1.1.5 root 610: if (ciaacrb & 0x10) {
1.1 root 611: ciaacrb &= ~0x10;
612: ciaatb = ciaalb;
613: }
1.1.1.10 root 614: CIA_calctimers ();
1.1 root 615: break;
616: }
617: }
618:
1.1.1.10 root 619: static void WriteCIAB (uae_u16 addr,uae_u8 val)
1.1 root 620: {
1.1.1.3 root 621: int oldval;
1.1.1.10 root 622: switch (addr & 0xf) {
1.1.1.7 root 623: case 0:
1.1.1.3 root 624: if (currprefs.use_serial) {
1.1.1.7 root 625: oldval = ciabpra;
626: ciabpra = serial_writestatus(oldval,val);
1.1.1.3 root 627: } else
1.1.1.7 root 628: ciabpra = val;
1.1.1.3 root 629: break;
1.1.1.7 root 630: case 1:
1.1 root 631: ciabprb = val; DISK_select(val); break;
1.1.1.7 root 632: case 2:
1.1 root 633: ciabdra = val; break;
1.1.1.7 root 634: case 3:
1.1 root 635: ciabdrb = val; break;
1.1.1.7 root 636: case 4:
1.1.1.10 root 637: CIA_update ();
1.1 root 638: ciabla = (ciabla & 0xff00) | val;
1.1.1.10 root 639: CIA_calctimers ();
1.1 root 640: break;
1.1.1.7 root 641: case 5:
1.1.1.10 root 642: CIA_update ();
1.1 root 643: ciabla = (ciabla & 0xff) | (val << 8);
1.1.1.3 root 644: if ((ciabcra & 1) == 0)
1.1 root 645: ciabta = ciabla;
646: if (ciabcra & 8) {
1.1.1.3 root 647: ciabta = ciabla;
648: ciabcra |= 1;
649: }
1.1.1.10 root 650: CIA_calctimers ();
1.1 root 651: break;
1.1.1.7 root 652: case 6:
1.1.1.10 root 653: CIA_update ();
1.1 root 654: ciablb = (ciablb & 0xff00) | val;
1.1.1.10 root 655: CIA_calctimers ();
1.1 root 656: break;
1.1.1.7 root 657: case 7:
1.1.1.10 root 658: CIA_update ();
1.1 root 659: ciablb = (ciablb & 0xff) | (val << 8);
660: if ((ciabcrb & 1) == 0)
661: ciabtb = ciablb;
662: if (ciabcrb & 8) {
663: ciabtb = ciablb;
664: ciabcrb |= 1;
665: }
1.1.1.10 root 666: CIA_calctimers ();
1.1 root 667: break;
1.1.1.7 root 668: case 8:
1.1.1.5 root 669: if (ciabcrb & 0x80) {
1.1 root 670: ciabalarm = (ciabalarm & ~0xff) | val;
671: } else {
672: ciabtod = (ciabtod & ~0xff) | val;
673: ciabtodon = 1;
674: }
675: break;
1.1.1.7 root 676: case 9:
1.1.1.5 root 677: if (ciabcrb & 0x80) {
1.1 root 678: ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
679: } else {
680: ciabtod = (ciabtod & ~0xff00) | (val << 8);
681: ciabtodon = 0;
682: }
683: break;
1.1.1.7 root 684: case 10:
1.1.1.5 root 685: if (ciabcrb & 0x80) {
1.1 root 686: ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
687: } else {
688: ciabtod = (ciabtod & ~0xff0000) | (val << 16);
689: ciabtodon = 0;
690: }
691: break;
1.1.1.7 root 692: case 12:
1.1.1.3 root 693: ciabsdr = val;
1.1 root 694: break;
1.1.1.7 root 695: case 13:
1.1.1.3 root 696: setclr(&ciabimask,val);
1.1 root 697: break;
1.1.1.7 root 698: case 14:
1.1.1.10 root 699: CIA_update ();
1.1 root 700: ciabcra = val;
1.1.1.5 root 701: if (ciabcra & 0x10) {
1.1 root 702: ciabcra &= ~0x10;
703: ciabta = ciabla;
704: }
1.1.1.10 root 705: CIA_calctimers ();
1.1 root 706: break;
1.1.1.7 root 707: case 15:
1.1.1.10 root 708: CIA_update ();
1.1.1.3 root 709: ciabcrb = val;
1.1.1.5 root 710: if (ciabcrb & 0x10) {
1.1 root 711: ciabcrb &= ~0x10;
712: ciabtb = ciablb;
713: }
1.1.1.10 root 714: CIA_calctimers ();
1.1 root 715: break;
716: }
717: }
718:
1.1.1.10 root 719: void CIA_reset (void)
1.1 root 720: {
721: kback = 1;
722: kbstate = 0;
1.1.1.3 root 723:
1.1.1.11 root 724: if (!savestate_state) {
725: ciaatlatch = ciabtlatch = 0;
726: ciaapra = 3;
727: ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
728: ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
729: ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
730: ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
731: ciabpra = 0x8C;
1.1.1.13 root 732: div10 = 0;
1.1.1.11 root 733: }
1.1.1.10 root 734: CIA_calctimers ();
1.1.1.14 root 735: if (! ersatzkickfile) {
736: int i = allocated_chipmem > 0x200000 ? allocated_chipmem >> 16 : 32;
737: map_banks (&kickmem_bank, 0, i, 0x80000);
738: }
1.1.1.3 root 739:
1.1.1.11 root 740: if (currprefs.use_serial && !savestate_state)
741: serial_dtr_off (); /* Drop DTR at reset */
742:
743: if (savestate_state) {
744: /* Reset oldovl and oldled */
745: uae_u8 v = ReadCIAA (0);
746: WriteCIAA (0,3);
747: WriteCIAA (0,0);
748: WriteCIAA (0,v);
749: /* select drives */
750: DISK_select (ciabprb);
751: }
1.1 root 752: }
753:
1.1.1.10 root 754: void dumpcia (void)
1.1 root 755: {
1.1.1.13 root 756: printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n",
1.1.1.3 root 757: (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod,
1.1.1.13 root 758: ciaatlatch ? "L" : "", ciaata, ciaala, ciaatb, ciaalb);
759: printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n",
1.1.1.3 root 760: (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod,
1.1.1.13 root 761: ciabtlatch ? "L" : "", ciabta, ciabla, ciabtb, ciablb);
1.1 root 762: }
763:
764: /* CIA memory access */
765:
1.1.1.3 root 766: static uae_u32 cia_lget (uaecptr) REGPARAM;
767: static uae_u32 cia_wget (uaecptr) REGPARAM;
768: static uae_u32 cia_bget (uaecptr) REGPARAM;
769: static void cia_lput (uaecptr, uae_u32) REGPARAM;
770: static void cia_wput (uaecptr, uae_u32) REGPARAM;
771: static void cia_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 772:
773: addrbank cia_bank = {
774: cia_lget, cia_wget, cia_bget,
775: cia_lput, cia_wput, cia_bput,
1.1.1.11 root 776: default_xlate, default_check, NULL
1.1 root 777: };
778:
1.1.1.15 root 779: static void cia_wait (void)
1.1 root 780: {
1.1.1.15 root 781: if (!div10)
782: return;
783: do_cycles (DIV10 - div10 + CYCLE_UNIT);
784: CIA_handler ();
785: }
786:
787: uae_u32 REGPARAM2 cia_bget (uaecptr addr)
788: {
789: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 790: special_mem |= S_READ;
1.1.1.15 root 791: cia_wait ();
792: switch ((addr >> 12) & 3)
793: {
794: case 0:
795: return (addr & 1) ? ReadCIAA (r) : ReadCIAB (r);
796: case 1:
797: return (addr & 1) ? 0xff : ReadCIAB (r);
798: case 2:
799: return (addr & 1) ? ReadCIAA (r) : 0xff;
800: }
801: return 0xff;
1.1 root 802: }
803:
1.1.1.3 root 804: uae_u32 REGPARAM2 cia_wget (uaecptr addr)
1.1 root 805: {
1.1.1.15 root 806: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 807: special_mem |= S_READ;
1.1.1.15 root 808: cia_wait ();
809: switch ((addr >> 12) & 3)
810: {
811: case 0:
812: return (ReadCIAB (r) << 8) | ReadCIAA (r);
813: case 1:
814: return (ReadCIAB (r) << 8) | 0xff;
815: case 2:
816: return (0xff << 8) | ReadCIAA (r);
817: }
818: return 0xffff;
1.1 root 819: }
820:
1.1.1.15 root 821: uae_u32 REGPARAM2 cia_lget (uaecptr addr)
1.1 root 822: {
1.1.1.15 root 823: uae_u32 v;
1.1.1.9 root 824: special_mem |= S_READ;
1.1.1.15 root 825: v = cia_wget (addr) << 16;
826: v |= cia_wget (addr + 2);
827: return v;
1.1 root 828: }
829:
1.1.1.15 root 830: void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
1.1 root 831: {
1.1.1.15 root 832: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 833: special_mem |= S_WRITE;
1.1.1.15 root 834: cia_wait ();
835: if ((addr & 0x2000) == 0)
836: WriteCIAB (r, value);
837: if ((addr & 0x1000) == 0)
838: WriteCIAA (r, value);
1.1 root 839: }
840:
1.1.1.3 root 841: void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
1.1 root 842: {
1.1.1.15 root 843: int r = (addr & 0xf00) >> 8;
1.1.1.9 root 844: special_mem |= S_WRITE;
1.1.1.15 root 845: cia_wait ();
846: if ((addr & 0x2000) == 0)
847: WriteCIAB (r, value >> 8);
848: if ((addr & 0x1000) == 0)
849: WriteCIAA (r, value & 0xff);
1.1 root 850: }
851:
1.1.1.15 root 852: void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
1.1 root 853: {
1.1.1.9 root 854: special_mem |= S_WRITE;
1.1.1.15 root 855: cia_wput (addr, value >> 16);
856: cia_wput (addr + 2, value & 0xffff);
1.1 root 857: }
858:
859: /* battclock memory access */
860:
1.1.1.3 root 861: static uae_u32 clock_lget (uaecptr) REGPARAM;
862: static uae_u32 clock_wget (uaecptr) REGPARAM;
863: static uae_u32 clock_bget (uaecptr) REGPARAM;
864: static void clock_lput (uaecptr, uae_u32) REGPARAM;
865: static void clock_wput (uaecptr, uae_u32) REGPARAM;
866: static void clock_bput (uaecptr, uae_u32) REGPARAM;
1.1 root 867:
868: addrbank clock_bank = {
869: clock_lget, clock_wget, clock_bget,
870: clock_lput, clock_wput, clock_bput,
1.1.1.11 root 871: default_xlate, default_check, NULL
1.1 root 872: };
873:
1.1.1.3 root 874: uae_u32 REGPARAM2 clock_lget (uaecptr addr)
1.1 root 875: {
1.1.1.9 root 876: special_mem |= S_READ;
877: return clock_bget (addr + 3);
1.1 root 878: }
879:
1.1.1.3 root 880: uae_u32 REGPARAM2 clock_wget (uaecptr addr)
1.1 root 881: {
1.1.1.9 root 882: special_mem |= S_READ;
883: return clock_bget (addr + 1);
1.1 root 884: }
885:
1.1.1.3 root 886: uae_u32 REGPARAM2 clock_bget (uaecptr addr)
1.1 root 887: {
1.1.1.9 root 888: time_t t = time(0);
1.1 root 889: struct tm *ct;
1.1.1.9 root 890:
891: ct = localtime (&t);
892: special_mem |= S_READ;
893:
1.1.1.7 root 894: switch (addr & 0x3f) {
895: case 0x03: return ct->tm_sec % 10;
896: case 0x07: return ct->tm_sec / 10;
897: case 0x0b: return ct->tm_min % 10;
898: case 0x0f: return ct->tm_min / 10;
899: case 0x13: return ct->tm_hour % 10;
900: case 0x17: return ct->tm_hour / 10;
901: case 0x1b: return ct->tm_mday % 10;
902: case 0x1f: return ct->tm_mday / 10;
903: case 0x23: return (ct->tm_mon+1) % 10;
904: case 0x27: return (ct->tm_mon+1) / 10;
905: case 0x2b: return ct->tm_year % 10;
906: case 0x2f: return ct->tm_year / 10;
907:
908: case 0x33: return ct->tm_wday; /*Hack by -=SR=- */
909: case 0x37: return clock_control_d;
910: case 0x3b: return clock_control_e;
911: case 0x3f: return clock_control_f;
1.1 root 912: }
913: return 0;
914: }
915:
1.1.1.3 root 916: void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
1.1 root 917: {
1.1.1.9 root 918: special_mem |= S_WRITE;
1.1 root 919: /* No way */
920: }
921:
1.1.1.3 root 922: void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
1.1 root 923: {
1.1.1.9 root 924: special_mem |= S_WRITE;
1.1 root 925: /* No way */
926: }
927:
1.1.1.3 root 928: void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
1.1 root 929: {
1.1.1.9 root 930: special_mem |= S_WRITE;
1.1.1.7 root 931: switch (addr & 0x3f) {
1.1.1.9 root 932: case 0x37: clock_control_d = value; break;
933: case 0x3b: clock_control_e = value; break;
934: case 0x3f: clock_control_f = value; break;
1.1 root 935: }
936: }
1.1.1.11 root 937:
938: /* CIA-A and CIA-B save/restore code */
939:
940: uae_u8 *restore_cia (int num, uae_u8 *src)
941: {
942: uae_u8 b;
943: uae_u16 w;
944: uae_u32 l;
945:
946: /* CIA registers */
947: b = restore_u8 (); /* 0 PRA */
948: if (num) ciabpra = b; else ciaapra = b;
949: b = restore_u8 (); /* 1 PRB */
950: if (num) ciabprb = b; else ciaaprb = b;
951: b = restore_u8 (); /* 2 DDRA */
952: if (num) ciabdra = b; else ciaadra = b;
953: b = restore_u8 (); /* 3 DDRB */
954: if (num) ciabdrb = b; else ciaadrb = b;
955: w = restore_u16 (); /* 4 TA */
956: if (num) ciabta = w; else ciaata = w;
957: w = restore_u16 (); /* 6 TB */
958: if (num) ciabtb = w; else ciaatb = w;
959: l = restore_u8 (); /* 8/9/A TOD */
960: l |= restore_u8 () << 8;
961: l |= restore_u8 () << 16;
962: if (num) ciabtod = l; else ciaatod = l;
963: restore_u8 (); /* B unused */
964: b = restore_u8 (); /* C SDR */
965: if (num) ciabsdr = b; else ciaasdr = b;
966: b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
967: if (num) ciabicr = b; else ciaaicr = b;
968: b = restore_u8 (); /* E CRA */
969: if (num) ciabcra = b; else ciaacra = b;
970: b = restore_u8 (); /* F CRB */
971: if (num) ciabcrb = b; else ciaacrb = b;
972:
973: /* CIA internal data */
974:
975: b = restore_u8 (); /* ICR MASK */
976: if (num) ciabimask = b; else ciaaimask = b;
977: w = restore_u8 (); /* timer A latch */
978: w |= restore_u8 () << 8;
1.1.1.13 root 979: if (num) ciabla = w; else ciaala = w;
1.1.1.11 root 980: w = restore_u8 (); /* timer B latch */
981: w |= restore_u8 () << 8;
982: if (num) ciablb = w; else ciaalb = w;
983: w = restore_u8 (); /* TOD latched value */
984: w |= restore_u8 () << 8;
985: w |= restore_u8 () << 16;
986: if (num) ciabtol = w; else ciaatol = w;
987: l = restore_u8 (); /* alarm */
988: l |= restore_u8 () << 8;
989: l |= restore_u8 () << 16;
990: if (num) ciabalarm = l; else ciaaalarm = l;
991: b = restore_u8 ();
992: if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
993: if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
994: if (num) {
995: div10 = CYCLE_UNIT * restore_u8 ();
996: }
997: return src;
998: }
999:
1000: uae_u8 *save_cia (int num, int *len)
1001: {
1002: uae_u8 *dstbak,*dst, b;
1003: uae_u16 t;
1004:
1005: dstbak = dst = malloc (16 + 12 + 1);
1006:
1007: compute_passed_time ();
1008:
1009: /* CIA registers */
1010:
1011: b = num ? ciabpra : ciaapra; /* 0 PRA */
1012: save_u8 (b);
1013: b = num ? ciabprb : ciaaprb; /* 1 PRB */
1014: save_u8 (b);
1015: b = num ? ciabdra : ciaadra; /* 2 DDRA */
1016: save_u8 (b);
1017: b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
1018: save_u8 (b);
1019: t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
1020: save_u16 (t);
1021: t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 8 TB */
1022: save_u16 (t);
1023: b = (num ? ciabtod : ciaatod); /* 8 TODL */
1024: save_u8 (b);
1025: b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
1026: save_u8 (b);
1027: b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
1028: save_u8 (b);
1029: save_u8 (0); /* B unused */
1030: b = num ? ciabsdr : ciaasdr; /* C SDR */
1031: save_u8 (b);
1032: b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
1033: save_u8 (b);
1034: b = num ? ciabcra : ciaacra; /* E CRA */
1035: save_u8 (b);
1036: b = num ? ciabcrb : ciaacrb; /* F CRB */
1037: save_u8 (b);
1038:
1039: /* CIA internal data */
1040:
1041: save_u8 (num ? ciabimask : ciaaimask); /* ICR */
1042: b = (num ? ciabla : ciaala); /* timer A latch LO */
1043: save_u8 (b);
1044: b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
1045: save_u8 (b);
1046: b = (num ? ciablb : ciaalb); /* timer B latch LO */
1047: save_u8 (b);
1048: b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
1049: save_u8 (b);
1050: b = (num ? ciabtol : ciaatol); /* latched TOD LO */
1051: save_u8 (b);
1052: b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
1053: save_u8 (b);
1054: b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
1055: save_u8 (b);
1056: b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
1057: save_u8 (b);
1058: b = (num ? ciabalarm >> 8 : ciaaalarm >>8 ); /* alarm MED */
1059: save_u8 (b);
1060: b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
1061: save_u8 (b);
1062: b = 0;
1063: if (num)
1064: b |= ciabtlatch ? 1 : 0;
1065: else
1066: b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
1067: if (num)
1068: b |= ciabtodon ? 2 : 0;
1069: else
1070: b |= ciaatodon ? 2 : 0; /* TOD stopped? */
1071: save_u8 (b);
1072: if (num) {
1073: /* Save extra state with CIAB. */
1074: save_u8 (div10 / CYCLE_UNIT);
1075: }
1076: *len = dst - dstbak;
1077: return dstbak;
1078: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.