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