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