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