]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CIA emulation big rewrite
authorToni Wilen <twilen@winuae.net>
Sat, 28 May 2022 18:21:51 +0000 (21:21 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 28 May 2022 18:21:51 +0000 (21:21 +0300)
cfgfile.cpp
cia.cpp
custom.cpp
debug.cpp
include/cia.h
include/debug.h
include/options.h
od-win32/keyboard_win32.cpp

index 1e36ec04a233be2e9b148094836ddfb20eed61e7..7b62214634205da6b58d14fde4b998c1619f1637 100644 (file)
@@ -2556,7 +2556,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_dwrite_str(f, _T("ciab_type"), ciatype[p->cs_ciatype[1]]);
        cfgfile_dwrite_str(f, _T("unmapped_address_space"), unmapped[p->cs_unmapped_space]);
        cfgfile_dwrite(f, _T("keyboard_handshake"), _T("%d"), currprefs.cs_kbhandshake);
-       cfgfile_dwrite (f, _T("chipset_hacks"), _T("0x%x"), p->cs_hacks);
+       cfgfile_dwrite(f, _T("chipset_hacks"), _T("0x%x"), p->cs_hacks);
+       cfgfile_dwrite(f, _T("eclockphase"), _T("%d"), p->cs_eclockphase);
 
        if (is_board_enabled(p, ROMTYPE_CD32CART, 0)) {
                cfgfile_dwrite_bool(f, _T("cd32fmv"), true);
@@ -5663,6 +5664,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || cfgfile_intval(option, value, _T("genlock_scale"), &p->genlock_scale, 1)
                || cfgfile_intval(option, value, _T("genlock_mix"), &p->genlock_mix, 1)
                || cfgfile_intval(option, value, _T("keyboard_handshake"), &p->cs_kbhandshake, 1)
+               || cfgfile_intval(option, value, _T("eclockphase"), &p->cs_eclockphase, 1)
                || cfgfile_intval(option, value, _T("chipset_rtc_adjust"), &p->cs_rtc_adjust, 1))
                return 1;
 
diff --git a/cia.cpp b/cia.cpp
index 73294f5a73ab42966c8ee2df1f9d36e1b4457d51..26327c11e31e4a2a0cc1435cb54b22cb22447d6b 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -5,6 +5,7 @@
 *
 * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
 * Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
+* Copyright 2022 Toni Wilen
 */
 
 
 #define DONGLE_DEBUG 0
 #define KB_DEBUG 0
 #define CLOCK_DEBUG 0
+#define CIA_EVERY_CYCLE_DEBUG 0
 
 #define TOD_HACK
 
+#define CIA_IRQ_PROCESS_DELAY 0
+
+#define CR_START 1
+#define CR_PBON 2
+#define CR_OUTMODE 4
+#define CR_RUNMODE 8
+#define CR_LOAD 0x10
+#define CR_INMODE 0x20
+#define CR_INMODE1 0x40
+#define CR_SPMODE 0x40
+#define CR_ALARM 0x80
+
+#define ICR_A 1
+#define ICR_B 2
+#define ICR_ALARM 4
+#define ICR_SP 8
+#define ICR_FLAG 0x10
+#define ICR_MASK 0x1f
+
+#define CIA_PIPE_ALL_BITS 2
+#define CIA_PIPE_ALL_MASK ((1 << CIA_PIPE_ALL_BITS) - 1)
+#define CIA_PIPE_INPUT 2
+#define CIA_PIPE_CLR1 1
+#define CIA_PIPE_CLR2 3
+#define CIA_PIPE_OUTPUT 1
+
 /* Akiko internal CIA differences:
 
 - BFE101 and BFD100: reads 3F if data direction is in.
 
  */
 
-/* e-clock is 10 CPU cycles, 6 cycles low, 4 high
-* data transfer happens during 4 high cycles
-*/
-#define ECLOCK_WAIT_CYCLE 6
-#define ECLOCK_DATA_CYCLE 4
+#define E_CLOCK_SYNC 2
+#define E_CLOCK_1 4
+#define E_CLOCK_2 6
+
+#define E_CLOCK_LENGTH (E_CLOCK_1 + E_CLOCK_2)
+#define E_CYCLE_UNIT (CYCLE_UNIT / 2)
+#define DIV10 ((E_CLOCK_LENGTH) * E_CYCLE_UNIT) /* Yes, a bad identifier. */
 
-#define DIV10 ((ECLOCK_WAIT_CYCLE + ECLOCK_DATA_CYCLE) * CYCLE_UNIT / 2) /* Yes, a bad identifier. */
-#define CIASTARTCYCLESHI 2
-#define CIASTARTCYCLESCRA 1
 
-static uae_u32 ciaaicr, ciaaimask, ciabicr, ciabimask;
-static uae_u32 ciaacra, ciaacrb, ciabcra, ciabcrb;
-static uae_u32 ciaastarta, ciaastartb, ciabstarta, ciabstartb;
+struct CIATimer
+{
+       uae_u16 timer;
+       uae_u16 latch;
+       uae_u32 passed;
+       uae_u16 inputpipe;
+       uae_u32 loaddelay;
+       uae_u8 cr;
+};
 
-/* Values of the CIA timers.  */
-static uae_u32 ciaata, ciaatb, ciabta, ciabtb;
-/* Computed by compute_passed_time.  */
-static uae_u32 ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
+struct CIA
+{
+       uae_u8 pra, prb;
+       uae_u8 dra, drb;
+       struct CIATimer t[2];
+       uae_u32 tod;
+       uae_u32 tol;
+       uae_u32 alarm;
+       uae_u32 tlatch;
+       uae_u8 todon;
+       int tod_event_state;
+       int tod_offset;
+       uae_u8 icr1, icr2;
+       bool icr_change;
+       uae_u8 imask;
+       uae_u8 sdr;
+       uae_u8 sdr_buf;
+       uae_u8 sdr_load;
+       uae_u8 sdr_cnt;
+};
+
+static struct CIA cia[2];
 
-static uae_u32 ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
-static int ciaatlatch, ciabtlatch;
 static bool oldovl;
 static bool led;
 static int led_old_brightness;
 static evt_t led_cycles_on, led_cycles_off, led_cycle;
 
-uae_u32 ciabpra;
-
-static uae_u32 ciaala, ciaalb, ciabla, ciablb;
-static int ciaatodon, ciabtodon;
-static uae_u32 ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr, ciaasdr_buf, ciaasdr_load, ciaasdr_cnt;
-static uae_u32 ciabprb, ciabdra, ciabdrb, ciabsdr, ciabsdr_buf, ciabsdr_load, ciabsdr_cnt;
 static int kbstate, kblostsynccnt;
 static evt_t kbhandshakestart;
 static uae_u8 kbcode;
 
 static uae_u8 serbits;
-static int warned = 10;
+static int warned = 100;
 
 static struct rtc_msm_data rtc_msm;
 static struct rtc_ricoh_data rtc_ricoh;
 
-static void setclr (uae_u32 *p, uae_u32 val)
+static bool acc_mode(void)
+{
+       return currprefs.m68k_speed >= 0 && currprefs.cpu_compatible;
+}
+
+int blop;
+// temporary e-clock phase shortcut
+static evt_t get_e_cycles(void)
+{
+       if (blop > 4) {
+               blop = 0;
+       }
+
+       evt_t c = get_cycles();
+       c += currprefs.cs_eclockphase * E_CYCLE_UNIT;
+       c += blop * 2 * E_CYCLE_UNIT;
+       return c;
+}
+
+static void setclr(uae_u8 *p, uae_u8 val)
 {
        if (val & 0x80) {
                *p |= val & 0x7F;
@@ -117,396 +179,457 @@ static void setclr (uae_u32 *p, uae_u32 val)
        }
 }
 
+#if CIA_IRQ_PROCESS_DELAY
 /* delay interrupt after current CIA register access if
  * interrupt would have triggered mid access
  */
 static int cia_interrupt_disabled;
 static int cia_interrupt_delay;
+#endif
 
-static void ICR (uae_u32 data)
+static void ICRIRQ(uae_u32 data)
 {
        safe_interrupt_set(IRQ_SOURCE_CIA, 0, (data & 0x2000) != 0);
 }
 
-static void ICRA (uae_u32 dummy)
+static void ICR(uae_u32 num)
 {
-       if (ciaaicr & 0x80)
-               ciaaicr |= 0x40;
-#if 1
-       if (currprefs.cpu_memory_cycle_exact && !(ciaaicr & 0x20) && (cia_interrupt_disabled & 1)) {
-               cia_interrupt_delay |= 1;
-#if CIAB_DEBUG_IRQ
-               write_log(_T("ciab interrupt disabled ICR=%02X PC=%x\n"), ciabicr, M68K_GETPC);
-#endif
-               return;
-       }
-#endif
-       ciaaicr |= 0x20;
-       ICR (0x0008);
-}
+       struct CIA *c = &cia[num];
 
-static void ICRB (uae_u32 dummy)
-{
-       if (ciabicr & 0x80)
-               ciabicr |= 0x40;
-#if 1
-       if (currprefs.cpu_memory_cycle_exact && !(ciabicr & 0x20) && (cia_interrupt_disabled & 2)) {
-               cia_interrupt_delay |= 2;
+#if CIA_IRQ_PROCESS_DELAY
+       if (currprefs.cpu_memory_cycle_exact && !(c->icr & 0x20) && (cia_interrupt_disabled & (1 << num))) {
+               c->cia_interrupt_delay |= 1 << num;
 #if CIAB_DEBUG_IRQ
-               write_log(_T("ciab interrupt disabled ICR=%02X PC=%x\n"), ciabicr, M68K_GETPC);
+               write_log(_T("cia%c interrupt disabled ICR=%02X PC=%x\n"), num ? 'b' : 'a', c->icr, M68K_GETPC);
 #endif
                return;
        }
 #endif
-       ciabicr |= 0x20;
-       if (currprefs.cs_compatible == CP_VELVET) {
-               // Both CIAs in Velvet are connected to level 2.
-               ICR (0x0008);
+       c->icr1 |= 0x20;
+       if (num && currprefs.cs_compatible != CP_VELVET) {
+               ICRIRQ(0x2000);
        } else {
-               ICR (0x2000);
+               ICRIRQ(0x0008);
        }
 }
 
-static void RethinkICRA (void)
+static void RethinkICR(int num)
 {
-       if (ciaaicr & ciaaimask) {
+       struct CIA *c = &cia[num];
+
+       if (c->icr1 & c->imask & ICR_MASK) {
 #if CIAA_DEBUG_IRQ
-               write_log (_T("CIAA IRQ %02X\n"), ciaaicr);
+               write_log(_T("CIA%c IRQ %02X\n"), num ? 'B' : 'A', c->icr);
 #endif
-               if (!(ciaaicr & 0x80)) {
-                       ciaaicr |= 0x80;
-                       if (currprefs.cpu_memory_cycle_exact) {
-                               event2_newevent_xx (-1, DIV10 + 2 * CYCLE_UNIT + CYCLE_UNIT / 2 + 4 * CYCLE_UNIT, 0, ICRA);
-                       } else {
-                               ICRA (0);
+               if (!(c->icr1 & 0x80)) {
+                       c->icr1 |= 0x80 | 0x40;
+                       if (debug_dma) {
+                               record_dma_event(num ? DMA_EVENT_CIAB_IRQ : DMA_EVENT_CIAA_IRQ, current_hpos(), vpos);
                        }
+                       ICR(num);
                }
        }
+
 }
 
-static void RethinkICRB (void)
+void rethink_cias(void)
 {
-       if (ciabicr & ciabimask) {
-#if CIAB_DEBUG_IRQ
-               write_log (_T("CIAB IRQ %02X\n"), ciabicr);
-#endif
-               if (!(ciabicr & 0x80)) {
-                       ciabicr |= 0x80;
-                       if (currprefs.cpu_memory_cycle_exact) {
-                               event2_newevent_xx (-1, DIV10 + 2 * CYCLE_UNIT + CYCLE_UNIT / 2 + 4 * CYCLE_UNIT, 0, ICRB);
-                       } else {
-                               ICRB (0);
-                       }
+       if (cia[0].icr1 & 0x40) {
+               ICRIRQ(0x0008);
+       }
+       if (cia[1].icr1 & 0x40) {
+               if (currprefs.cs_compatible == CP_VELVET) {
+                       ICRIRQ(0x0008);
+               } else {
+                       ICRIRQ(0x2000);
                }
        }
 }
 
-void rethink_cias (void)
+static uae_u16 bitstodelay(uae_u16 v)
 {
-       if (ciaaicr & 0x40)
-               ICRA (0);
-       if (ciabicr & 0x40)
-               ICRB (0);
+       switch (v)
+       {
+       case 0:
+               return CIA_PIPE_ALL_BITS - 0;
+       case 1:
+       case 2:
+#if CIA_PIPE_ALL_BITS > 2
+       case 4:
+#endif
+               return CIA_PIPE_ALL_BITS - 1;
+       case 3:
+#if CIA_PIPE_ALL_BITS > 2
+       case 5:
+       case 6:
+#endif
+               return CIA_PIPE_ALL_BITS - 2;
+#if CIA_PIPE_ALL_BITS > 2
+       case 7:
+               return CIA_PIPE_ALL_BITS - 3;
+#endif
+       default:
+               abort();
+               break;
+       }
 }
 
 /* Figure out how many CIA timer cycles have passed for each timer since the
 last call of CIA_calctimers.  */
 
-static void compute_passed_time (void)
+static void compute_passed_time_cia(int num, uae_u32 ciaclocks)
 {
-       evt_t ccount = get_cycles() - eventtab[ev_cia].oldcycles;
-       if (ccount > MAXINT) {
-               ccount = MAXINT;
-       }
-       uae_u32 ciaclocks = (uae_u32)(ccount / DIV10);
+       struct CIA *c = &cia[num];
 
-       ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
+       c->t[0].passed = 0;
+       c->t[1].passed = 0;
 
-       /* CIA A timers */
-       if ((ciaacra & 0x21) == 0x01) {
+       if ((c->t[0].cr & (CR_INMODE | CR_START)) == CR_START) {
                uae_u32 cc = ciaclocks;
-               if (cc > ciaastarta)
-                       cc -= ciaastarta;
-               else
+               int pipe = bitstodelay(c->t[0].inputpipe);
+               if (cc > pipe) {
+                       cc -= pipe;
+               } else {
                        cc = 0;
-               assert ((ciaata + 1) >= cc);
-               ciaata_passed = cc;
+               }
+               c->t[0].passed = cc;
+               assert(cc < 65536);
        }
-       if ((ciaacrb & 0x61) == 0x01) {
+       if ((c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == CR_START) {
                uae_u32 cc = ciaclocks;
-               if (cc > ciaastartb)
-                       cc -= ciaastartb;
-               else
+               int pipe = bitstodelay(c->t[1].inputpipe);
+               if (cc > pipe) {
+                       cc -= pipe;
+               } else {
                        cc = 0;
-               assert ((ciaatb + 1) >= cc);
-               ciaatb_passed = cc;
+               }
+               c->t[1].passed = cc;
+               assert(cc < 65536);
        }
+}
 
-       /* CIA B timers */
-       if ((ciabcra & 0x21) == 0x01) {
-               uae_u32 cc = ciaclocks;
-               if (cc > ciabstarta)
-                       cc -= ciabstarta;
-               else
-                       cc = 0;
-               assert ((ciabta + 1) >= cc);
-               ciabta_passed = cc;
+static void compute_passed_time(void)
+{
+       evt_t ccount = get_cycles() - eventtab[ev_cia].oldcycles;
+       if (ccount > MAXINT) {
+               ccount = MAXINT;
        }
-       if ((ciabcrb & 0x61) == 0x01) {
-               uae_u32 cc = ciaclocks;
-               if (cc > ciabstartb)
-                       cc -= ciabstartb;
-               else
-                       cc = 0;
-               assert ((ciabtb + 1) >= cc);
-               ciabtb_passed = cc;
+       uae_u32 ciaclocks = (uae_u32)ccount / DIV10;
+
+       compute_passed_time_cia(0, ciaclocks);
+       compute_passed_time_cia(1, ciaclocks);
+}
+
+static void timer_reset(struct CIATimer *t)
+{
+       t->timer = t->latch;
+       if (t->cr & CR_RUNMODE) {
+               t->inputpipe &= ~CIA_PIPE_CLR1;
+       } else {
+               t->inputpipe &= ~CIA_PIPE_CLR2;
        }
 }
 
+static uae_u8 cia_inmode_cnt(int num)
+{
+       struct CIA *c = &cia[num];
+       uae_u8 icr = 0;
+       bool decb = false;
+
+       // A INMODE=1 (count CNT pulses)
+       if ((c->t[0].cr & (CR_INMODE | CR_START)) == (CR_INMODE | CR_START)) {
+               c->t[0].timer--;
+               if (c->t[0].timer == 0) {
+                       icr |= ICR_A;
+                       timer_reset(&c->t[0]);
+                       if (c->t[0].cr & CR_RUNMODE) {
+                               c->t[0].cr &= ~CR_START;
+                       }
+                       // B INMODE = 1x (count A undeflows)
+                       if ((c->t[1].cr & (CR_INMODE1 | CR_START)) == (CR_INMODE1 | CR_START)) {
+                               decb = true;
+                       }
+               }
+       }
+       // B INMODE=01 (count CNT pulses)
+       if ((c->t[1].cr & (CR_INMODE1 | CR_INMODE | CR_START)) == (CR_INMODE | CR_START)) {
+               decb = 1;
+       }
+
+       if (decb) {
+               c->t[1].timer--;
+               if (c->t[1].timer == 0) {
+                       icr |= ICR_B;
+                       timer_reset(&c->t[1]);
+                       if (c->t[1].cr & CR_RUNMODE) {
+                               c->t[1].cr &= ~CR_START;
+                       }
+               }
+       }
+       return icr;
+}
+
+static int process_pipe(struct CIATimer *t, int cc, uae_u8 crmask, int *ovfl)
+{
+       int ccout = cc;
+
+       if (cc == 1) {
+               int out = t->inputpipe & CIA_PIPE_OUTPUT;
+               t->inputpipe >>= 1;
+               if ((t->cr & crmask) == CR_START) {
+                       t->inputpipe |= CIA_PIPE_INPUT;
+               }
+               // interrupt 1 cycle early if timer is already zero
+               if (t->timer == 0 && (t->inputpipe & CIA_PIPE_OUTPUT)) {
+                       *ovfl = 1;
+               }
+               return out;
+       }
+
+       while (t->inputpipe != CIA_PIPE_ALL_MASK && cc > 0) {
+               if (!(t->inputpipe & CIA_PIPE_OUTPUT)) {
+                       ccout--;
+               }
+               t->inputpipe >>= 1;
+               if ((t->cr & crmask) == CR_START) {
+                       t->inputpipe |= CIA_PIPE_INPUT;
+               }
+               cc--;
+       }
+
+       return ccout;
+}
+
 /* Called to advance all CIA timers to the current time.  This expects that
 one of the timer values will be modified, and CIA_calctimers will be called
 in the same cycle.  */
 
-static int CIA_update_check (void)
+static void CIA_update_check(void)
 {
        evt_t ccount = get_cycles() - eventtab[ev_cia].oldcycles;
        if (ccount > MAXINT) {
                ccount = MAXINT;
        }
-       uae_u32 ciaclocks = (uae_u32)(ccount / DIV10);
+       int ciaclocks = (uae_u32)(ccount / DIV10);
+       if (!ciaclocks) {
+               return;
+       }
 
-       int aovfla = 0, aovflb = 0, asp = 0, bovfla = 0, bovflb = 0, bsp = 0;
-       int icr = 0;
+       uae_u8 icr = 0;
+       for (int num = 0; num < 2; num++) {
+               struct CIA *c = &cia[num];
+               int ovfl[2], sp;
+               bool loaded[2], loaded2[2];
 
-       /* CIA A timers */
-       // A INMODE=0
-       if ((ciaacra & 0x21) == 0x01) {
-               bool check = true;
-               uae_u32 cc = ciaclocks;
-               if (ciaastarta > 0) {
-                       if (cc > ciaastarta) {
-                               cc -= ciaastarta;
-                               ciaastarta = 0;
-                       } else {
-                               ciaastarta -= cc;
-                               check = false;
+               c->icr1 |= c->icr2;
+               c->icr2 = 0;
+               c->icr_change = false;
+
+
+               ovfl[0] = 0;
+               ovfl[1] = 0;
+               sp = 0;
+
+               for (int tn = 0; tn < 2; tn++) {
+                       struct CIATimer *t = &c->t[tn];
+                       
+                       loaded[tn] = false;
+                       loaded2[tn] = false;
+
+                       // CIA special cases
+                       if (t->loaddelay) {
+                               if (ciaclocks > 1) {
+                                       abort();
+                               }
+                               if (t->loaddelay & 1) {
+                                       t->timer = t->latch;
+                                       t->inputpipe &= ~CIA_PIPE_CLR1;
+                               }
+                               if ((t->loaddelay & 0x0100) && t->timer != 0) {
+                                       loaded2[tn] = true;
+                               }
+                               if ((t->loaddelay & 0x010000)) {
+                                       if ((t->timer != 1 || t->latch != 1) && (t->inputpipe & CIA_PIPE_OUTPUT)) {
+                                               loaded2[tn] = true;
+                                       }
+                               }
+                               if ((t->loaddelay & 0x01000000)) {
+                                       loaded[tn] = true;
+                                       if (t->timer == 0) {
+                                               ovfl[tn] = true;
+                                       }
+                               }
+
+                               t->loaddelay >>= 1;
+                               t->loaddelay &= 0x7f7f7f7f;
                        }
+
                }
-               if (check) {
-                       assert ((ciaata + 1) >= cc);
-                       if ((ciaata + 1) == cc) {
-                               // SP in output mode (data sent can be ignored)
-                               if ((ciaacra & 0x48) == 0x40 && ciaasdr_cnt > 0) {
-                                       ciaasdr_cnt--;
-                                       if (ciaasdr_cnt == 0) {
-                                               asp = 1;
-                                               if (ciaasdr_load) {
-                                                       ciaasdr_load = 0;
-                                                       ciaasdr_buf = ciaasdr;
-                                                       ciaasdr_cnt = 8 * 2;
+
+               // Timer A
+               int cc = 0;
+               if ((c->t[0].cr& (CR_INMODE | CR_START)) == CR_START || c->t[0].inputpipe) {
+                       cc = process_pipe(&c->t[0], ciaclocks, CR_INMODE | CR_START, &ovfl[0]);
+               }
+               if (cc > 0) {
+                       c->t[0].timer -= cc;
+                       if (c->t[0].timer == 0) {
+                               // SP in output mode (data sent can be ignored if CIA-A)
+                               if ((c->t[0].cr & (CR_SPMODE | CR_RUNMODE)) == CR_SPMODE && c->sdr_cnt > 0) {
+                                       c->sdr_cnt--;
+                                       if (c->sdr_cnt == 0) {
+                                               sp = 1;
+                                               if (c->sdr_load) {
+                                                       c->sdr_load = 0;
+                                                       c->sdr_buf = c->sdr;
+                                                       c->sdr_cnt = 8 * 2;
                                                }
                                        }
                                }
-                               aovfla = 1;
+                               ovfl[0] = 1;
                                // B INMODE=10 or 11
-                               if ((ciaacrb & 0x61) == 0x41 || (ciaacrb & 0x61) == 0x61) {
-                                       if (ciaatb-- == 0)
-                                               aovflb = 1;
+                               if ((c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == (CR_INMODE1 | CR_START) || (c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == (CR_INMODE | CR_INMODE1 | CR_START)) {
+                                       c->t[1].inputpipe |= CIA_PIPE_INPUT;
                                }
                        }
-                       ciaata -= cc;
                }
-       }
-       // A INMODE=00
-       if ((ciaacrb & 0x61) == 0x01) {
-               bool check = true;
-               uae_u32 cc = ciaclocks;
-               if (ciaastartb > 0) {
-                       if (cc > ciaastartb) {
-                               cc -= ciaastartb;
-                               ciaastartb = 0;
-                       } else {
-                               ciaastartb -= cc;
-                               check = false;
-                       }
-               }
-               if (check) {
-                       assert ((ciaatb + 1) >= cc);
-                       if ((ciaatb + 1) == cc)
-                               aovflb = 1;
-                       ciaatb -= cc;
-               }
-       }
+               assert(c->t[0].timer < 0x10000);
 
-       /* CIA B timers */
-       // A INMODE=0
-       if ((ciabcra & 0x21) == 0x01) {
-               bool check = true;
-               uae_u32 cc = ciaclocks;
-               if (ciabstarta > 0) {
-                       if (cc > ciabstarta) {
-                               cc -= ciabstarta;
-                               ciabstarta = 0;
-                       } else {
-                               ciabstarta -= cc;
-                               check = false;
+               // Timer B
+               cc = 0;
+               if ((c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == CR_START || c->t[1].inputpipe) {
+                       cc = process_pipe(&c->t[1], ciaclocks, CR_INMODE | CR_INMODE1 | CR_START, &ovfl[1]);
+               }
+               if (cc > 0) {
+                       c->t[1].timer -= cc;
+                       if (c->t[1].timer == 0) {
+                               ovfl[1] = 1;
                        }
                }
-               if (check) {
-                       assert ((ciabta + 1) >= cc);
-                       if ((ciabta + 1) == cc) {
-                               // SP in output mode
-                               if ((ciabcra & 0x48) == 0x40 && ciabsdr_cnt > 0) {
-                                       ciaasdr_cnt--;
-                                       if (!(ciaasdr_cnt & 1)) {
-                                               ciabsdr_buf <<= 1;
-                                       }
-                                       if (ciabsdr_cnt == 0) {
-                                               bsp = 1;
-                                               if (ciabsdr_load) {
-                                                       ciabsdr_load = 0;
-                                                       ciabsdr_buf = ciabsdr;
-                                                       ciabsdr_cnt = 8 * 2;
+               assert(c->t[1].timer < 0x10000);
+
+               for (int tn = 0; tn < 2; tn++) {
+                       struct CIATimer *t = &c->t[tn];
+
+                       if (ovfl[tn]) {
+                               c->icr2 |= tn ? ICR_B : ICR_A;
+                               t->timer = t->latch;
+                               if (!loaded[tn]) {
+                                       if (t->cr & CR_RUNMODE) {
+                                               // if oneshot timer expires exactly when
+                                               // CR is written with START and ONESHOT set:
+                                               // timer does not stop.
+                                               if (!loaded2[tn]) {
+                                                       t->cr &= ~CR_START;
                                                }
+                                               t->inputpipe &= ~CIA_PIPE_CLR2;
+                                       } else {
+                                               t->inputpipe &= ~CIA_PIPE_CLR1;
                                        }
                                }
-                               bovfla = 1;
-                               // B INMODE=10 or 11
-                               if ((ciabcrb & 0x61) == 0x41 || (ciabcrb & 0x61) == 0x61) {
-                                       if (ciabtb-- == 0)
-                                               bovflb = 1;
-                               }
+                               icr |= 1 << num;
                        }
-                       ciabta -= cc;
                }
-       }
-       // B INMODE=00
-       if ((ciabcrb & 0x61) == 0x01) {
-               bool check = true;
-               uae_u32 cc = ciaclocks;
-               if (ciabstartb > 0) {
-                       if (cc > ciabstartb) {
-                               cc -= ciabstartb;
-                               ciabstartb = 0;
-                       } else {
-                               ciabstartb -= cc;
-                               check = false;
-                       }
-               }
-               if (check) {
-                       assert ((ciabtb + 1) >= cc);
-                       if ((ciabtb + 1) == cc)
-                               bovflb = 1;
-                       ciabtb -= cc;
-               }
-       }
 
-       if (aovfla) {
-               ciaaicr |= 1; icr = 1;
-               ciaata = ciaala;
-               if (ciaacra & 0x8) {
-                       ciaacra &= ~1;
+               if (sp) {
+                       c->icr2 |= ICR_SP;
+                       icr |= 1 << num;
                }
-       }
-       if (aovflb) {
-               ciaaicr |= 2; icr = 1;
-               ciaatb = ciaalb;
-               if (ciaacrb & 0x8) {
-                       ciaacrb &= ~1;
+
+               if (!acc_mode()) {
+                       c->icr1 |= c->icr2;
+                       c->icr2 = 0;
                }
-       }
-       if (asp) {
-               ciaaicr |= 8; icr = 1;
-       }
-       if (bovfla) {
-               ciabicr |= 1; icr |= 2;
-               ciabta = ciabla;
-               if (ciabcra & 0x8) {
-                       ciabcra &= ~1;
+               if (icr) {
+                       c->icr_change = true;
                }
        }
-       if (bovflb) {
-               ciabicr |= 2; icr |= 2;
-               ciabtb = ciablb;
-               if (ciabcrb & 0x8) {
-                       ciabcrb &= ~1;
-               }
+}
+
+static void CIA_check_ICR(void)
+{
+       if (cia[0].icr1 & ICR_MASK) {
+               RethinkICR(0);
        }
-       if (bsp) {
-               ciabicr |= 8; icr |= 2;
+       if (cia[1].icr1 & ICR_MASK) {
+               RethinkICR(1);
        }
-       return icr;
 }
-static void CIA_update (void)
+
+static void CIA_update(void)
 {
-       int icr = CIA_update_check ();
-       if (icr & 1)
-               RethinkICRA ();
-       if (icr & 2)
-               RethinkICRB ();
+       CIA_update_check();
+       CIA_check_ICR();
 }
 
-
 /* Call this only after CIA_update has been called in the same cycle.  */
-
-static void CIA_calctimers (void)
+static void CIA_calctimers(void)
 {
-       uae_s32 ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
-       int div10diff = DIV10;
+       uae_s32 timevals[4];
+
+       timevals[0] = -1;
+       timevals[1] = -1;
+       timevals[2] = -1;
+       timevals[3] = -1;
 
        eventtab[ev_cia].oldcycles = get_cycles();
 
-       if ((ciaacra & 0x21) == 0x01) {
-               ciaatimea = div10diff + DIV10 * (ciaata + ciaastarta);
-       }
-#if 0
-       if ((ciaacrb & 0x61) == 0x41) {
-               /* Timer B will not get any pulses if Timer A is off. */
-               if (ciaatimea >= 0) {
-                       /* If Timer A is in one-shot mode, and Timer B needs more than
-                       * one pulse, it will not underflow. */
-                       if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
-                               /* Otherwise, we can determine the time of the underflow. */
-                               /* This may overflow, however.  So just ignore this timer and
-                               use the fact that we'll call CIA_handler for the A timer.  */
-                               /* ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; */
+       for (int num = 0; num < 2; num++) {
+               struct CIA *c = &cia[num];
+               int idx = num * 2;
+
+               if ((c->t[0].cr & (CR_INMODE | CR_START)) == CR_START) {
+                       int pipe = bitstodelay(c->t[0].inputpipe);
+                       timevals[idx + 0] = DIV10 * (c->t[0].timer + pipe);
+                       if (!timevals[idx + 0]) {
+                               timevals[idx + 0] = DIV10;
                        }
                }
-       }
-#endif
-       if ((ciaacrb & 0x61) == 0x01) {
-               ciaatimeb = div10diff + DIV10 * (ciaatb + ciaastartb);
-       }
 
-       if ((ciabcra & 0x21) == 0x01) {
-               ciabtimea = div10diff + DIV10 * (ciabta + ciabstarta);
-       }
-#if 0
-       if ((ciabcrb & 0x61) == 0x41) {
-               /* Timer B will not get any pulses if Timer A is off. */
-               if (ciabtimea >= 0) {
-                       /* If Timer A is in one-shot mode, and Timer B needs more than
-                       * one pulse, it will not underflow. */
-                       if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
-                               /* Otherwise, we can determine the time of the underflow. */
-                               /* ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; */
+               if ((c->t[1].cr & (CR_INMODE | CR_INMODE1 | CR_START)) == CR_START) {
+                       int pipe = bitstodelay(c->t[1].inputpipe);
+                       timevals[idx + 1] = DIV10 * (c->t[1].timer + pipe);
+                       if (!timevals[idx + 1]) {
+                               timevals[idx + 1] = DIV10;
                        }
                }
-       }
+
+               for (int tn = 0; tn < 2; tn++) {
+                       struct CIATimer *t = &c->t[tn];
+                       bool timerspecial = t->loaddelay != 0;
+                       if (t->cr & CR_START) {
+                               if (t->inputpipe != CIA_PIPE_ALL_MASK) {
+                                       timerspecial = true;
+                               }
+                       } else {
+                               if (t->inputpipe != 0) {
+                                       timerspecial = true;
+                               }
+                       }
+                       if (timerspecial && (timevals[idx] < 0 || timevals[idx] > DIV10)) {
+                               timevals[idx + tn] = DIV10;
+                       }
+               }
+
+               if (c->icr_change && (timevals[idx] < 0 || timevals[idx] > DIV10)) {
+                       timevals[idx] = DIV10;
+               }
+
+#if CIA_EVERY_CYCLE_DEBUG              
+               timevals[idx] = DIV10;
 #endif
-       if ((ciabcrb & 0x61) == 0x01) {
-               ciabtimeb = div10diff + DIV10 * (ciabtb + ciabstartb);
+
        }
 
        uae_s32 ciatime = INT_MAX;
-       if (ciaatimea > 0)
-               ciatime = ciaatimea;
-       if (ciaatimeb > 0 && ciaatimeb < ciatime)
-               ciatime = ciaatimeb;
-       if (ciabtimea > 0 && ciabtimea < ciatime)
-               ciatime = ciabtimea;
-       if (ciabtimeb > 0 && ciabtimeb < ciatime)
-               ciatime = ciabtimeb;
+       if (timevals[0] >= 0)
+               ciatime = timevals[0];
+       if (timevals[1] >= 0 && timevals[1] < ciatime)
+               ciatime = timevals[1];
+       if (timevals[2] >= 0 && timevals[2] < ciatime)
+               ciatime = timevals[2];
+       if (timevals[3] >= 0 && timevals[3] < ciatime)
+               ciatime = timevals[3];
        if (ciatime < INT_MAX) {
                eventtab[ev_cia].evtime = get_cycles() + ciatime;
                eventtab[ev_cia].active = true;
@@ -517,29 +640,59 @@ static void CIA_calctimers (void)
        events_schedule();
 }
 
-void CIA_handler (void)
+void CIA_handler(void)
 {
-       CIA_update ();
-       CIA_calctimers ();
+       CIA_update();
+       CIA_calctimers();
 }
 
-void cia_diskindex (void)
+static void CIA_synced_interrupt(uae_u32 v)
 {
-       ciabicr |= 0x10;
-       RethinkICRB ();
+       CIA_update();
+       CIA_calctimers();
 }
-void cia_parallelack (void)
+
+static void CIA_sync_interrupt(int num, uae_u8 icr)
 {
-       ciaaicr |= 0x10;
-       RethinkICRA ();
+       struct CIA *c = &cia[num];
+
+       if (acc_mode()) {
+               c->icr2 |= icr;
+               if ((c->icr1 & ICR_MASK) == (c->icr2 & ICR_MASK)) {
+                       return;
+               }
+               if (!(icr & c->imask)) {
+                       c->icr1 |= icr;
+                       return;
+               }
+               c->icr_change = true;
+               evt_t evt = get_e_cycles();
+               int div10 = evt % DIV10;
+               int delay = 0;
+               if (div10 > 0) {
+                       delay += DIV10 - div10;
+               }
+               event2_newevent_xx(-1, DIV10 + delay, num, CIA_synced_interrupt);
+       } else {
+               c->icr1 |= icr;
+               c->icr_change = true;
+               CIA_check_ICR();
+       }
 }
 
-static bool checkalarm (uae_u32 tod, uae_u32 alarm, bool inc, int ab)
+void cia_diskindex(void)
+{
+       CIA_sync_interrupt(1, ICR_FLAG);
+}
+void cia_parallelack(void)
+{
+       CIA_sync_interrupt(0, ICR_FLAG);
+}
+
+static bool checkalarm(uae_u32 tod, uae_u32 alarm, bool inc, int ab)
 {
        if (tod == alarm)
                return true;
-//     if (!ab)
-//             return false;
        if (!currprefs.cs_ciatodbug)
                return false;
        if (!inc)
@@ -555,40 +708,55 @@ static bool checkalarm (uae_u32 tod, uae_u32 alarm, bool inc, int ab)
        return false;
 }
 
-static bool ciab_checkalarm (bool inc, bool irq)
+static bool ciab_checkalarm(bool inc, bool irq)
 {
+       struct CIA *c = &cia[1];
+
        // hack: do not trigger alarm interrupt if KS code and both
        // tod and alarm == 0. This incorrectly triggers on non-cycle exact
        // modes. Real hardware value written to ciabtod by KS is always
        // at least 1 or larger due to bus cycle delays when reading
        // old value.
 #if 1
-       if ((munge24 (m68k_getpc ()) & 0xFFF80000) != 0xF80000) {
-               if (ciabtod == 0 && ciabalarm == 0)
+       if (!currprefs.cpu_compatible && (munge24(m68k_getpc()) & 0xFFF80000) != 0xF80000) {
+               if (c->tod == 0 && c->alarm == 0)
                        return false;
        }
 #endif
-       if (checkalarm (ciabtod, ciabalarm, inc, 1)) {
+       if (checkalarm(c->tod, c->alarm, inc, 1)) {
 #if CIAB_DEBUG_IRQ
-               write_log (_T("CIAB tod %08x %08x\n"), ciabtod, ciabalarm);
+               write_log(_T("CIAB tod %08x %08x\n"), c->tod, c->alarm);
 #endif
                if (irq) {
-                       ciabicr |= 4;
-                       RethinkICRB ();
+                       CIA_sync_interrupt(1, ICR_ALARM);
                }
                return true;
        }
        return false;
 }
 
-static void ciaa_checkalarm (bool inc)
+static void ciaa_checkalarm(bool inc)
 {
-       if (checkalarm (ciaatod, ciaaalarm, inc, 0)) {
+       struct CIA *c = &cia[0];
+
+       if (checkalarm(c->tod, c->alarm, inc, 0)) {
 #if CIAA_DEBUG_IRQ
-               write_log (_T("CIAA tod %08x %08x\n"), ciaatod, ciaaalarm);
+               write_log(_T("CIAA tod %08x %08x\n"), c->tod, c->alarm);
 #endif
-               ciaaicr |= 4;
-               RethinkICRA ();
+               CIA_sync_interrupt(0, ICR_ALARM);
+       }
+}
+
+static void cia_checkalarm(int num, bool inc)
+{
+       switch (num)
+       {
+       case 0:
+               ciaa_checkalarm(inc);
+               break;
+       case 1:
+               ciab_checkalarm(inc, true);
+               break;
        }
 }
 
@@ -599,24 +767,25 @@ static int tod_hack_delay;
 static int tod_diff_cnt;
 #define TOD_HACK_DELAY 50
 #define TOD_HACK_TIME 312 * 50 * 10
-static void tod_hack_reset (void)
+
+static void tod_hack_reset(void)
 {
        struct timeval tv;
-       gettimeofday (&tv, NULL);
+       gettimeofday(&tv, NULL);
        tod_hack_tv = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
-       tod_hack_tod = ciaatod;
+       tod_hack_tod = cia[0].tod;
        tod_hack_tod_last = tod_hack_tod;
        tod_diff_cnt = 0;
 }
 #endif
 
 static int heartbeat_cnt;
-void cia_heartbeat (void)
+void cia_heartbeat(void)
 {
        heartbeat_cnt = 10;
 }
 
-static void do_tod_hack (int dotod)
+static void do_tod_hack(int dotod)
 {
        struct timeval tv;
        static int oldrate;
@@ -638,8 +807,8 @@ static void do_tod_hack (int dotod)
        if (tod_hack_enabled > 1) {
                tod_hack_enabled--;
                if (tod_hack_enabled == 1) {
-                       //write_log (_T("TOD HACK enabled\n"));
-                       tod_hack_reset ();
+                       //write_log(_T("TOD HACK enabled\n"));
+                       tod_hack_reset();
                }
                return;
        }
@@ -657,9 +826,9 @@ static void do_tod_hack (int dotod)
        }
        if (rate <= 0)
                return;
-       if (rate != oldrate || (ciaatod & 0xfff) != (tod_hack_tod_last & 0xfff)) {
-               write_log (_T("TOD HACK reset %d,%d %ld,%lld\n"), rate, oldrate, ciaatod, tod_hack_tod_last);
-               tod_hack_reset ();
+       if (rate != oldrate || (cia[0].tod & 0xfff) != (tod_hack_tod_last & 0xfff)) {
+               write_log(_T("TOD HACK reset %d,%d %ld,%lld\n"), rate, oldrate, cia[0].tod, tod_hack_tod_last);
+               tod_hack_reset();
                oldrate = rate;
                docount = 1;
        }
@@ -674,7 +843,7 @@ static void do_tod_hack (int dotod)
                tod_hack_delay = TOD_HACK_DELAY;
        }
 
-       gettimeofday (&tv, NULL);
+       gettimeofday(&tv, NULL);
        t = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
        if (t - tod_hack_tv >= 1000000 / rate) {
                tod_hack_tv += 1000000 / rate;
@@ -684,31 +853,30 @@ static void do_tod_hack (int dotod)
                docount = 1;
        }
        if (docount) {
-               ciaatod++;
-               ciaatod &= 0x00ffffff;
-               tod_hack_tod_last = ciaatod;
-               ciaa_checkalarm (false);
+               cia[0].tod++;
+               cia[0].tod &= 0x00ffffff;
+               tod_hack_tod_last = cia[0].tod;
+               ciaa_checkalarm(false);
        }
 }
 
 static int resetwarning_phase, resetwarning_timer;
 
-static void setcode (uae_u8 keycode)
+static void setcode(uae_u8 keycode)
 {
        kbcode = ~((keycode << 1) | (keycode >> 7));
 }
 
-static void sendrw (void)
+static void sendrw(void)
 {
-       setcode (AK_RESETWARNING);
-       ciaasdr = kbcode;
+       setcode(AK_RESETWARNING);
+       cia[0].sdr = kbcode;
        kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
-       ciaaicr |= 8;
-       RethinkICRA ();
-       write_log (_T("KB: sent reset warning code (phase=%d)\n"), resetwarning_phase);
+       CIA_sync_interrupt(0, ICR_SP);
+       write_log(_T("KB: sent reset warning code (phase=%d)\n"), resetwarning_phase);
 }
 
-int resetwarning_do (int canreset)
+int resetwarning_do(int canreset)
 {
        if (!currprefs.keyboard_connected)
                return 0;
@@ -722,44 +890,44 @@ int resetwarning_do (int canreset)
        }
        resetwarning_phase = 1;
        resetwarning_timer = maxvpos_nom * 5;
-       write_log (_T("KB: reset warning triggered\n"));
-       sendrw ();
+       write_log(_T("KB: reset warning triggered\n"));
+       sendrw();
        return 1;
 }
 
-static void resetwarning_check (void)
+static void resetwarning_check(void)
 {
        if (resetwarning_timer > 0) {
                resetwarning_timer--;
                if (resetwarning_timer <= 0) {
-                       write_log (_T("KB: reset warning forced reset. Phase=%d\n"), resetwarning_phase);
+                       write_log(_T("KB: reset warning forced reset. Phase=%d\n"), resetwarning_phase);
                        resetwarning_phase = -1;
                        kblostsynccnt = 0;
-                       send_internalevent (INTERNALEVENT_KBRESET);
-                       uae_reset (0, 1);
+                       send_internalevent(INTERNALEVENT_KBRESET);
+                       uae_reset(0, 1);
                }
        }
        if (resetwarning_phase == 1) {
                if (!kblostsynccnt) { /* first AK_RESETWARNING handshake received */
-                       write_log (_T("KB: reset warning second phase..\n"));
+                       write_log(_T("KB: reset warning second phase..\n"));
                        resetwarning_phase = 2;
                        resetwarning_timer = maxvpos_nom * 5;
-                       sendrw ();
+                       sendrw();
                }
        } else if (resetwarning_phase == 2) {
-               if (ciaacra & 0x40) { /* second AK_RESETWARNING handshake active */
+               if (cia[0].t[0].cr & CR_SPMODE) { /* second AK_RESETWARNING handshake active */
                        resetwarning_phase = 3;
-                       write_log (_T("KB: reset warning SP = output\n"));
+                       write_log(_T("KB: reset warning SP = output\n"));
                        /* System won't reset until handshake signal becomes inactive or 10s has passed */
                        resetwarning_timer = (int)(10 * maxvpos_nom * vblank_hz);
                }
        } else if (resetwarning_phase == 3) {
-               if (!(ciaacra & 0x40)) { /* second AK_RESETWARNING handshake disabled */
-                       write_log (_T("KB: reset warning end by software. reset.\n"));
+               if (!(cia[0].t[0].cr & CR_SPMODE)) { /* second AK_RESETWARNING handshake disabled */
+                       write_log(_T("KB: reset warning end by software. reset.\n"));
                        resetwarning_phase = -1;
                        kblostsynccnt = 0;
-                       send_internalevent (INTERNALEVENT_KBRESET);
-                       uae_reset (0, 1);
+                       send_internalevent(INTERNALEVENT_KBRESET);
+                       uae_reset(0, 1);
                }
        }
 }
@@ -771,48 +939,79 @@ void CIA_hsync_prehandler (void)
 static void keyreq (void)
 {
 #if KB_DEBUG
-       write_log (_T("code=%02x (%02x)\n"), kbcode, (uae_u8)(~((kbcode >> 1) | (kbcode << 7))));
+       write_log(_T("code=%02x (%02x)\n"), kbcode, (uae_u8)(~((kbcode >> 1) | (kbcode << 7))));
 #endif
-       ciaasdr = kbcode;
+       cia[0].sdr = kbcode;
        kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
-       ciaaicr |= 8;
-       RethinkICRA ();
+       CIA_sync_interrupt(0, ICR_SP);
 }
 
-/* All this complexity to lazy evaluate TOD increase.
+/* All this complexity to lazy evaluate CIA-B TOD increase.
  * Only increase it cycle-exactly if it is visible to running program:
- * causes interrupt or program is reading or writing TOD registers
+ * causes interrupt (ALARM) or program is reading or writing TOD registers
  */
 
-static int ciab_tod_hoffset;
-static int ciab_tod_event_state;
-// TOD increase has extra delay
-#define TOD_INC_DELAY (13 * DIV10)
+// TOD increase has extra delay. CCKs.
+#define TOD_INC_DELAY (12 * E_CLOCK_LENGTH / 2)
+
+static int tod_inc_delay(int hoffset)
+{
+       int hoff = hoffset + 1; // 1 = HSYNC Agnus pin output is delayed by 1 CCK
+       evt_t c = get_e_cycles() + 2 * E_CYCLE_UNIT + hoff * CYCLE_UNIT;
+       int offset = hoff;
+       offset += TOD_INC_DELAY;
+       int unit = (E_CLOCK_LENGTH * 4) / 2; // 4 E-clocks
+       int div10 = (c / CYCLE_UNIT) % unit;
+       offset += unit - div10;
+       return offset;
+}
+
+static void CIAA_tod_inc(uae_u32 v)
+{
+       if (!cia[0].todon)
+               return;
+       cia[0].tod++;
+       cia[0].tod &= 0xFFFFFF;
+       ciaa_checkalarm(true);
+}
+
+void CIAA_tod_handler(int hoffset)
+{
+#ifdef TOD_HACK
+       if (currprefs.tod_hack && tod_hack_enabled == 1)
+               return;
+#endif
+       if (!cia[0].todon)
+               return;
+       int delay = tod_inc_delay(hoffset);
+       event2_newevent_xx(-1, delay * CYCLE_UNIT, 0, CIAA_tod_inc);
+}
 
 static void CIAB_tod_inc(bool irq)
 {
-       ciab_tod_event_state = 3; // done
-       if (!ciabtodon)
+       cia[1].tod_event_state = 3; // done
+       if (!cia[1].todon)
                return;
-       ciabtod++;
-       ciabtod &= 0xFFFFFF;
+       cia[1].tod++;
+       cia[1].tod &= 0xFFFFFF;
        ciab_checkalarm(true, irq);
 }
 
 static void CIAB_tod_inc_event(uae_u32 v)
 {
-       if (ciab_tod_event_state != 2)
+       int hpos = current_hpos();
+       if (cia[1].tod_event_state != 2)
                return;
        CIAB_tod_inc(true);
 }
 
 static void CIAB_tod_event_check(void)
 {
-       if (ciab_tod_event_state == 1) {
+       if (cia[1].tod_event_state == 1) {
                int hpos = current_hpos();
-               if (hpos >= ciab_tod_hoffset) {
+               if (hpos >= cia[1].tod_offset) {
                        CIAB_tod_inc(false);
-                       ciab_tod_event_state = 0;
+                       cia[1].tod_event_state = 0;
                }
        }
 }
@@ -821,32 +1020,39 @@ static void CIAB_tod_event_check(void)
 static void CIAB_tod_check(void)
 {
        CIAB_tod_event_check();
-       if (!ciabtodon)
+       if (!cia[1].todon || cia[1].tod_event_state > 1 || cia[1].tod_offset < 0)
                return;
        int hpos = current_hpos();
-       hpos -= ciab_tod_hoffset;
+       hpos -= cia[1].tod_offset;
        if (hpos >= 0 || currprefs.m68k_speed < 0) {
                // Program should see the changed TOD
                CIAB_tod_inc(true);
                return;
        }
        // Not yet, add event to guarantee exact TOD inc position
-       ciab_tod_event_state = 2; // event active
+       cia[1].tod_event_state = 2; // event active
        event2_newevent_xx(-1, -hpos * CYCLE_UNIT, 0, CIAB_tod_inc_event);
 }
 
 void CIAB_tod_handler(int hoffset)
 {
-       if (!ciabtodon || ciab_tod_event_state)
+       cia[1].tod_event_state = 0;
+       cia[1].tod_offset = tod_inc_delay(hoffset);
+       if (cia[1].tod_offset >= maxhpos) {
                return;
-       ciab_tod_hoffset = hoffset;
-       ciab_tod_hoffset += TOD_INC_DELAY / CYCLE_UNIT;
-       //ciab_tod_hoffset += ((total_ciaclocks % 4) * DIV10) / CYCLE_UNIT;
-       ciab_tod_event_state = 1; // TOD inc needed
-       if (checkalarm ((ciabtod + 1) & 0xffffff, ciabalarm, true, 1)) {
+       }
+       cia[1].tod_event_state = 1; // TOD inc needed
+       if (checkalarm((cia[1].tod + 1) & 0xffffff, cia[1].alarm, true, 1)) {
                // causes interrupt on this line, add event
-               ciab_tod_event_state = 2; // event active
-               event2_newevent_xx (-1, ciab_tod_hoffset * CYCLE_UNIT, 0, CIAB_tod_inc_event);
+               cia[1].tod_event_state = 2; // event active
+               event2_newevent_xx(-1, cia[1].tod_offset * CYCLE_UNIT, 0, CIAB_tod_inc_event);
+       }
+}
+
+static void CIA_tod_check(int num)
+{
+       if (num == 1) {
+               CIAB_tod_check();
        }
 }
 
@@ -865,7 +1071,7 @@ void keyboard_connected(bool connect)
 static void check_keyboard(void)
 {
        if (currprefs.keyboard_connected) {
-               if ((keys_available () || kbstate < 3) && !kblostsynccnt ) {
+               if ((keys_available() || kbstate < 3) && !kblostsynccnt ) {
                        switch (kbstate)
                        {
                                case 0:
@@ -873,18 +1079,18 @@ static void check_keyboard(void)
                                        kbstate++;
                                        break;
                                case 1:
-                                       setcode (AK_INIT_POWERUP);
+                                       setcode(AK_INIT_POWERUP);
                                        kbstate++;
                                        break;
                                case 2:
-                                       setcode (AK_TERM_POWERUP);
+                                       setcode(AK_TERM_POWERUP);
                                        kbstate++;
                                        break;
                                case 3:
-                                       kbcode = ~get_next_key ();
+                                       kbcode = ~get_next_key();
                                        break;
                        }
-                       keyreq ();
+                       keyreq();
                }
        } else {
                while (keys_available()) {
@@ -896,20 +1102,20 @@ static void check_keyboard(void)
 void CIA_hsync_posthandler (bool ciahsync, bool dotod)
 {
        if (ciahsync) {
-               // cia hsync
-               // Previous line was supposed to increase TOD but
-               // no one cared. Do it now.
-               if (ciab_tod_event_state == 1)
-                       CIAB_tod_inc (false);
-               ciab_tod_event_state = 0;
-               if (currprefs.tod_hack && ciaatodon)
-                       do_tod_hack (dotod);
+               // CIA HSync pulse
+               // Delayed previous line TOD increase.
+               if (cia[1].tod_event_state == 1)
+                       CIAB_tod_inc(false);
+               cia[1].tod_event_state = 0;
+               cia[1].tod_offset = -1;
+               if (currprefs.tod_hack && cia[0].todon)
+                       do_tod_hack(dotod);
        } else if (currprefs.keyboard_connected) {
                // custom hsync
                if (resetwarning_phase) {
-                       resetwarning_check ();
-                       while (keys_available ())
-                               get_next_key ();
+                       resetwarning_check();
+                       while (keys_available())
+                               get_next_key();
                } else {
                        if ((hsync_counter & 15) == 0)
                                check_keyboard();
@@ -921,9 +1127,9 @@ void CIA_hsync_posthandler (bool ciahsync, bool dotod)
        }
 }
 
-static void calc_led (int old_led)
+static void calc_led(int old_led)
 {
-       evt_t c = get_cycles ();
+       evt_t c = get_cycles();
        evt_t t = (c - led_cycle) / CYCLE_UNIT;
        if (old_led)
                led_cycles_on += t;
@@ -932,11 +1138,11 @@ static void calc_led (int old_led)
        led_cycle = c;
 }
 
-static void led_vsync (void)
+static void led_vsync(void)
 {
        int v;
 
-       calc_led (led);
+       calc_led(led);
        if (led_cycles_on && !led_cycles_off)
                v = 255;
        else if (led_cycles_off && !led_cycles_on)
@@ -957,14 +1163,14 @@ static void led_vsync (void)
        if (led_old_brightness != gui_data.powerled_brightness) {
                gui_data.powerled = gui_data.powerled_brightness > 96;
                gui_led (LED_POWER, gui_data.powerled, gui_data.powerled_brightness);
-               led_filter_audio ();
+               led_filter_audio();
        }
        led_old_brightness = gui_data.powerled_brightness;
-       led_cycle = get_cycles ();
+       led_cycle = get_cycles();
 }
 
-static void write_battclock (void);
-void CIA_vsync_prehandler (void)
+static void write_battclock(void);
+void CIA_vsync_prehandler(void)
 {
        if (heartbeat_cnt > 0)
                heartbeat_cnt--;
@@ -974,119 +1180,365 @@ void CIA_vsync_prehandler (void)
        } else if (rtc_msm.delayed_write > 0) {
                rtc_msm.delayed_write--;
                if (rtc_msm.delayed_write == 0)
-                       write_battclock ();
+                       write_battclock();
        }
        if (rtc_ricoh.delayed_write < 0) {
                rtc_ricoh.delayed_write = 50;
        } else if (rtc_ricoh.delayed_write > 0) {
                rtc_ricoh.delayed_write--;
                if (rtc_ricoh.delayed_write == 0)
-                       write_battclock ();
+                       write_battclock();
        }
 
-       led_vsync ();
+       led_vsync();
        keybuf_vsync();
        if (kblostsynccnt > 0) {
                kblostsynccnt -= maxvpos;
                if (kblostsynccnt <= 0) {
                        kblostsynccnt = 0;
                        kbcode = 0;
-                       keyreq ();
+                       keyreq();
 #if KB_DEBUG
-                       write_log (_T("lostsync\n"));
+                       write_log(_T("lostsync\n"));
 #endif
                }
        }
 }
 
-static void CIAA_tod_handler (uae_u32 v)
+static void check_led(void)
 {
-       ciaatod++;
-       ciaatod &= 0xFFFFFF;
-       ciaa_checkalarm (true);
+       uae_u8 v = cia[0].pra;
+       bool led2;
+
+       v |= ~cia[0].dra; /* output is high when pin's direction is input */
+       led2 = (v & 2) ? 0 : 1;
+       if (led2 != led) {
+               calc_led(led);
+               led = led2;
+               led_old_brightness = -1;
+       }
 }
 
-void CIAA_tod_inc (int cycles)
+static void bfe001_change(void)
 {
-#ifdef TOD_HACK
-       if (currprefs.tod_hack && tod_hack_enabled == 1)
+       uae_u8 v = cia[0].pra;
+       v |= ~cia[0].dra; /* output is high when pin's direction is input */
+       check_led();
+       if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
+               oldovl = v & 1;
+               if (!oldovl) {
+                       map_overlay(1);
+               } else {
+                       map_overlay(0);
+               }
+       }
+       akiko_mute((v & 1) == 0);
+}
+
+static uae_u32 getciatod(uae_u32 tod)
+{
+       if (!currprefs.cs_cia6526)
+               return tod;
+       uae_u32 bcdtod = 0;
+       for (int i = 0; i < 4; i++) {
+               int val = tod % 10;
+               bcdtod *= 16;
+               bcdtod += val;
+               tod /= 10;
+       }
+       return bcdtod;
+}
+static void setciatod(uae_u32 *tod, uae_u32 v)
+{
+       if (!currprefs.cs_cia6526) {
+               *tod = v;
                return;
+       }
+       uae_u32 bintod = 0;
+       for (int i = 0; i < 4; i++) {
+               int val = v / 16;
+               bintod *= 10;
+               bintod += val;
+               v /= 16;
+       }
+       *tod = bintod;
+}
+
+// E-clock count mode?
+static bool CIA_timer_02(int num, uae_u8 cr)
+{
+       if (num) {
+               return (cr & (CR_INMODE | CR_INMODE1)) == 0;
+       }
+       return (cr & CR_INMODE) == 0;
+}
+
+static uae_u8 ReadCIAReg(int num, int reg)
+{
+       struct CIA *c = &cia[num];
+       uae_u8 tmp;
+       int tnum = 0;
+
+       switch (reg)
+       {
+       case 6:
+       case 7:
+       case 15:
+               tnum = 1;
+               break;
+       }
+
+       struct CIATimer *t = &c->t[tnum];
+
+       switch (reg)
+       {
+       case 4:
+       case 6:
+       case 5:
+       case 7:
+       {
+               uae_u16 tval = t->timer - t->passed;
+               if (reg == 4 || reg == 6) {
+                       return tval & 0xff;
+               }
+               return tval >> 8;
+       }
+       case 8:
+               CIA_tod_check(num);
+               if (c->tlatch) {
+                       c->tlatch = 0;
+                       return getciatod(c->tol);
+               } else {
+                       return getciatod(c->tod);
+               }
+       case 9:
+               CIA_tod_check(num);
+               if (c->tlatch) {
+                       return getciatod(c->tol) >> 8;
+               } else {
+                       return getciatod(c->tod) >> 8;
+               }
+       case 10:
+               CIA_tod_check(num);
+               /* only if not already latched. A1200 confirmed. (TW) */
+               if (!currprefs.cs_cia6526) {
+                       if (!c->tlatch) {
+                               /* no latching if ALARM is set */
+                               if (!(c->t[1].cr & CR_ALARM)) {
+                                       c->tlatch = 1;
+                               }
+                               c->tol = c->tod;
+                       }
+                       return getciatod(c->tol) >> 16;
+               } else {
+                       if (c->tlatch)
+                               return getciatod(c->tol) >> 16;
+                       else
+                               return getciatod(c->tod) >> 16;
+               }
+               break;
+       case 11:
+               CIA_tod_check(num);
+               if (currprefs.cs_cia6526) {
+                       if (!c->tlatch) {
+                               if (!(c->t[1].cr & CR_ALARM)) {
+                                       c->tlatch = 1;
+                               }
+                               c->tol = c->tod;
+                       }
+                       if (c->tlatch) {
+                               return getciatod(c->tol) >> 24;
+                       } else{
+                               return getciatod(c->tod) >> 24;
+                       }
+               } else {
+                       return 0xff;
+               }
+               break;
+       case 12:
+#if KB_DEBUG
+               write_log(_T("CIAA serial port: %02x %08x\n"), c->sdr, M68K_GETPC);
 #endif
-       if (!ciaatodon)
-               return;
-       event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
+               return c->sdr;
+       case 13:
+               tmp = c->icr1 & ~(0x40 | 0x20);
+               c->icr1 = 0;
+               return tmp;
+       case 14:
+       case 15:
+               return t->cr;
+       }
+       return 0xff;
 }
 
-static void check_led(void)
+static void CIA_thi_write(int num, int tnum, uae_u8 val)
 {
-       uae_u8 v = ciaapra;
-       bool led2;
+       struct CIA *c = &cia[num];
+       struct CIATimer *t = &c->t[tnum];
 
-       v |= ~ciaadra; /* output is high when pin's direction is input */
-       led2 = (v & 2) ? 0 : 1;
-       if (led2 != led) {
-               calc_led(led);
-               led = led2;
-               led_old_brightness = -1;
+       uae_u16 latch_old = t->latch;
+       t->latch = (t->latch & 0xff) | (val << 8);
+
+       t->loaddelay |= 1 << 2;
+       if (!(t->cr & CR_START)) {
+               t->loaddelay |= 1 << 1;
+       }
+
+       if (t->cr & CR_RUNMODE) {
+               t->cr |= CR_START;
+               t->loaddelay |= 0x01000000 << 1;
        }
 }
 
-static void bfe001_change(void)
+static void CIA_cr_write(int num, int tnum, uae_u8 val)
 {
-       uae_u8 v = ciaapra;
-       v |= ~ciaadra; /* output is high when pin's direction is input */
-       check_led();
-       if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
-               oldovl = v & 1;
-               if (!oldovl) {
-                       map_overlay(1);
-               } else {
-                       //activate_debugger();
-                       map_overlay(0);
+       struct CIA *c = &cia[num];
+       struct CIATimer *t = &c->t[tnum];
+
+       if (!tnum) {
+               val &= 0x7f; /* bit 7 is unused */
+       }
+
+       if (val & CR_LOAD) {
+               val &= ~CR_LOAD;
+               t->loaddelay |= 0x0001 << 2;
+               t->loaddelay |= 0x0100 << 0;
+               if (!(t->cr & CR_START)) {
+                       t->loaddelay |= 0x0001 << 1;
+               }
+       } else {
+               if ((val & CR_START)) {
+                       t->loaddelay |= 0x010000 << 0;
                }
        }
-       akiko_mute((v & 1) == 0);
+
+       if (!(val & CR_START)) {
+               t->inputpipe &= ~CIA_PIPE_CLR1;
+       }
+
+       t->cr = val;
 }
 
-static uae_u32 getciatod(uae_u32 tod)
+static void WriteCIAReg(int num, int reg, uae_u8 val)
 {
-       if (!currprefs.cs_cia6526)
-               return tod;
-       uae_u32 bcdtod = 0;
-       for (int i = 0; i < 4; i++) {
-               int val = tod % 10;
-               bcdtod *= 16;
-               bcdtod += val;
-               tod /= 10;
+       struct CIA *c = &cia[num];
+       int tnum = 0;
+
+       switch (reg)
+       {
+       case 6:
+       case 7:
+       case 15:
+               tnum = 1;
+               break;
+       }
+
+       struct CIATimer *t = &c->t[tnum];
+
+       switch (reg) {
+       case 4:
+       case 6:
+               t->latch = (t->latch & 0xff00) | val;
+               break;
+       case 5:
+       case 7:
+               CIA_thi_write(num, tnum, val);
+               break;
+       case 8:
+               CIA_tod_check(num);
+               if (c->t[1].cr & CR_ALARM) {
+                       setciatod(&c->alarm, (getciatod(c->alarm) & ~0xff) | val);
+               } else {
+                       setciatod(&c->tod, (getciatod(c->tod) & ~0xff) | val);
+                       c->todon = 1;
+                       cia_checkalarm(num, false);
+                       CIA_tod_check(num);
+               }
+               break;
+       case 9:
+               CIA_tod_check(num);
+               if (c->t[1].cr & CR_ALARM) {
+                       setciatod(&c->alarm, (getciatod(c->alarm) & ~0xff00) | (val << 8));
+               } else {
+                       setciatod(&c->tod, (getciatod(c->tod) & ~0xff00) | (val << 8));
+               }
+               break;
+       case 10:
+               CIA_tod_check(num);
+               if (c->t[1].cr & CR_ALARM) {
+                       setciatod(&c->alarm, (getciatod(c->alarm) & ~0xff0000) | (val << 16));
+               } else {
+                       setciatod(&c->tod, (getciatod(c->tod) & ~0xff0000) | (val << 16));
+                       if (!currprefs.cs_cia6526) {
+                               c->todon = 0;
+                       }
+               }
+               break;
+       case 11:
+               CIA_tod_check(num);
+               if (currprefs.cs_cia6526) {
+                       if (c->t[1].cr & CR_ALARM) {
+                               setciatod(&c->alarm, (getciatod(c->alarm) & ~0xff000000) | (val << 24));
+                       } else {
+                               setciatod(&c->tod, (getciatod(c->tod) & ~0xff000000) | (val << 24));
+                               c->todon = 0;
+                       }
+               }
+               break;
+       case 12:
+               c->sdr = val;
+               if ((c->t[0].cr & (CR_INMODE1 | CR_START)) == (CR_INMODE1 | CR_START)) {
+                       c->sdr_load = 1;
+                       if (c->sdr_cnt == 0) {
+                               c->sdr_cnt = 8 * 2;
+                               c->sdr_load = 0;
+                               c->sdr_buf = c->sdr;
+                       }
+               }
+               break;
+       case 13:
+               setclr(&c->imask, val);
+               RethinkICR(num);
+               break;
+       case 14:
+       case 15:
+               CIA_cr_write(num, tnum, val);
+               break;
        }
-       return bcdtod;
 }
-static void setciatod(uae_u32 *tod, uae_u32 v)
+
+static uae_u8 CIA_PBON(struct CIA *c, uae_u8 v)
 {
-       if (!currprefs.cs_cia6526) {
-               *tod = v;
-               return;
+       // A PBON
+       if (c->t[0].cr & CR_PBON) {
+               int pb6 = 0;
+               if (c->t[0].cr & CR_OUTMODE)
+                       pb6 = c->t[0].cr & CR_START;
+               v &= ~0x40;
+               v |= pb6 ? 0x40 : 00;
        }
-       uae_u32 bintod = 0;
-       for (int i = 0; i < 4; i++) {
-               int val = v / 16;
-               bintod *= 10;
-               bintod += val;
-               v /= 16;
+       // B PBON
+       if (c->t[1].cr & CR_PBON) {
+               int pb7 = 0;
+               if (c->t[1].cr & CR_OUTMODE)
+                       pb7 = c->t[1].cr & CR_START;
+               v &= ~0x80;
+               v |= pb7 ? 0x80 : 00;
        }
-       *tod = bintod;
+       return v;
 }
 
-static uae_u8 ReadCIAA (uae_u32 addr, uae_u32 *flags)
+static uae_u8 ReadCIAA(uae_u32 addr, uae_u32 *flags)
 {
+       struct CIA *c = &cia[0];
        uae_u32 tmp;
        int reg = addr & 15;
 
-       compute_passed_time ();
+       compute_passed_time();
 
 #if CIAA_DEBUG_R > 0
        if (CIAA_DEBUG_R > 1 || (munge24 (M68K_GETPC) & 0xFFF80000) != 0xF80000)
-               write_log (_T("R_CIAA: bfe%x01 %08X\n"), reg, M68K_GETPC);
+               write_log(_T("R_CIAA: bfe%x01 %08X\n"), reg, M68K_GETPC);
 #endif
 
        switch (reg) {
@@ -1094,188 +1546,119 @@ static uae_u8 ReadCIAA (uae_u32 addr, uae_u32 *flags)
        {
                *flags |= 1;
                uae_u8 v = DISK_status_ciaa() & 0x3c;
-               v |= handle_joystick_buttons (ciaapra, ciaadra);
-               v |= (ciaapra | (ciaadra ^ 3)) & 0x03;
-               v = dongle_cia_read (0, reg, ciaadra, v);
-               v = alg_joystick_buttons(ciaapra, ciaadra, v);
+               v |= handle_joystick_buttons(c->pra, c->dra);
+               v |= (c->pra | (c->dra ^ 3)) & 0x03;
+               v = dongle_cia_read(0, reg, c->dra, v);
+               v = alg_joystick_buttons(c->pra, c->dra, v);
 
                // 391078-01 CIA: output mode bits always return PRA contents
                if (currprefs.cs_ciatype[0]) {
-                       v &= ~ciaadra;
-                       v |= ciaapra & ciaadra;
+                       v &= ~c->dra;
+                       v |= c->pra & c->dra;
                }
 
 #if DONGLE_DEBUG > 0
                if (notinrom())
-                       write_log (_T("BFE001 R %02X %s\n"), v, debuginfo(0));
+                       write_log(_T("BFE001 R %02X %s\n"), v, debuginfo(0));
 #endif
 
                if (inputrecord_debug & 2) {
                        if (input_record > 0)
-                               inprec_recorddebug_cia (v, 0, m68k_getpc ());
+                               inprec_recorddebug_cia(v, 0, m68k_getpc ());
                        else if (input_play > 0)
-                               inprec_playdebug_cia (v, 0, m68k_getpc ());
+                               inprec_playdebug_cia(v, 0, m68k_getpc ());
                }
 
                return v;
        }
        case 1:
-               tmp = (ciaaprb & ciaadrb) | (ciaadrb ^ 0xff);
+               tmp = (c->prb & c->drb) | (c->drb ^ 0xff);
 #ifdef PARALLEL_PORT
                if (isprinter() > 0) {
-                       tmp = ciaaprb;
+                       tmp = c->prb;
                } else if (isprinter() < 0) {
                        uae_u8 v;
                        parallel_direct_read_data(&v);
                        tmp = v;
 #ifdef ARCADIA
                } else if (arcadia_bios) {
-                       tmp = arcadia_parport(0, ciaaprb, ciaadrb);
+                       tmp = arcadia_parport(0, c->prb, c->drb);
 #endif
                } else if (currprefs.win32_samplersoundcard >= 0) {
 
-                       tmp = sampler_getsample((ciabpra & 4) ? 1 : 0);
+                       tmp = sampler_getsample((c->pra & 4) ? 1 : 0);
 #endif
 
                } else if (parallel_port_scsi) {
 
-                       tmp = parallel_port_scsi_read(0, ciaaprb, ciaadrb);
+                       tmp = parallel_port_scsi_read(0, c->prb, c->drb);
 
                } else {
                        tmp = handle_parport_joystick (0, tmp);
-                       tmp = dongle_cia_read (1, reg, ciaadrb, tmp);
+                       tmp = dongle_cia_read (1, reg, c->drb, tmp);
 #if DONGLE_DEBUG > 0
                        if (notinrom())
-                               write_log (_T("BFE101 R %02X %s\n"), tmp, debuginfo(0));
+                               write_log(_T("BFE101 R %02X %s\n"), tmp, debuginfo(0));
 #endif
                }
-               // PBON
-               if (ciaacrb & 2) {
-                       int pb7 = 0;
-                       // OUTMODE
-                       if (ciaacrb & 4) {
-                               pb7 = ciaacrb & 1;
-                       }
-                       tmp &= ~0x80;
-                       tmp |= pb7 ? 0x80 : 00;
-               }
-               if (ciaacra & 2) {
-                       int pb6 = 0;
-                       // OUTMODE
-                       if (ciaacra & 4) {
-                               pb6 = ciaacra & 1;
-                       }
-                       tmp &= ~0x40;
-                       tmp |= pb6 ? 0x40 : 00;
-               }
-
+               tmp = CIA_PBON(c, tmp);
                if (currprefs.cs_ciatype[0]) {
-                       tmp &= ~ciaadrb;
-                       tmp |= ciaaprb & ciaadrb;
+                       tmp &= ~c->drb;
+                       tmp |= c->prb & c->drb;
                }
 
                return tmp;
        case 2:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFE201 R %02X %s\n"), ciaadra, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFE201 R %02X %s\n"), c->dra, debuginfo(0));
 #endif
-               return ciaadra;
+               return c->dra;
        case 3:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFE301 R %02X %s\n"), ciaadrb, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFE301 R %02X %s\n"), c->drb, debuginfo(0));
 #endif
-               return ciaadrb;
+               return c->drb;
        case 4:
-               return (uae_u8)((ciaata - ciaata_passed) & 0xff);
        case 5:
-               return (uae_u8)((ciaata - ciaata_passed) >> 8);
        case 6:
-               return (uae_u8)((ciaatb - ciaatb_passed) & 0xff);
        case 7:
-               return (uae_u8)((ciaatb - ciaatb_passed) >> 8);
        case 8:
-               if (ciaatlatch) {
-                       ciaatlatch = 0;
-                       return getciatod(ciaatol);
-               } else
-                       return getciatod(ciaatod);
        case 9:
-               if (ciaatlatch)
-                       return getciatod(ciaatol) >> 8;
-               else
-                       return getciatod(ciaatod) >> 8;
        case 10:
-               /* only if not already latched. A1200 confirmed. (TW) */
-               if (!currprefs.cs_cia6526) {
-                       if (!ciaatlatch) {
-                               /* no latching if ALARM is set */
-                               if (!(ciaacrb & 0x80))
-                                       ciaatlatch = 1;
-                               ciaatol = ciaatod;
-                       }
-                       return getciatod(ciaatol) >> 16;
-               } else {
-                       if (ciaatlatch)
-                               return getciatod(ciaatol) >> 16;
-                       else
-                               return getciatod(ciaatod) >> 16;
-               }
-               break;
        case 11:
-               if (currprefs.cs_cia6526) {
-                       if (!ciaatlatch) {
-                               if (!(ciaacrb & 0x80))
-                                       ciaatlatch = 1;
-                               ciaatol = ciaatod;
-                       }
-                       if (ciaatlatch)
-                               return getciatod(ciaatol) >> 24;
-                       else
-                               return getciatod(ciaatod) >> 24;
-               } else {
-                       return 0xff;
-               }
-               break;
        case 12:
-#if KB_DEBUG
-               write_log (_T("CIAA serial port: %02x %08x\n"), ciaasdr, M68K_GETPC);
-#endif
-               return ciaasdr;
        case 13:
-               tmp = ciaaicr & ~(0x40 | 0x20);
-               ciaaicr = 0;
-               return tmp;
        case 14:
-               return ciaacra;
        case 15:
-               return ciaacrb;
+               return ReadCIAReg(0, reg);
        }
        return 0;
 }
 
-static uae_u8 ReadCIAB (uae_u32 addr, uae_u32 *flags)
+static uae_u8 ReadCIAB(uae_u32 addr, uae_u32 *flags)
 {
+       struct CIA *c = &cia[1];
        uae_u32 tmp;
        int reg = addr & 15;
 
 #if CIAB_DEBUG_R > 0
        if (CIAB_DEBUG_R > 1 || (munge24 (M68K_GETPC) & 0xFFF80000) != 0xF80000) {
                if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_R > 1)
-                       write_log (_T("R_CIAB: bfd%x00 %08X\n"), reg, M68K_GETPC);
+                       write_log(_T("R_CIAB: bfd%x00 %08X\n"), reg, M68K_GETPC);
        }
 #endif
 
-       compute_passed_time ();
+       compute_passed_time();
 
        switch (reg) {
        case 0:
-               tmp = (ciabpra & ciabdra) | (ciabdra ^ 0xff);
+               tmp = (c->pra & c->dra) | (c->dra ^ 0xff);
 #ifdef SERIAL_PORT
                if (currprefs.use_serial) {
                        tmp &= 7;
-                       tmp |= serial_readstatus(ciabdra) & 0xf8;
+                       tmp |= serial_readstatus(c->dra) & 0xf8;
                }
 #endif
 #ifdef PARALLEL_PORT
@@ -1288,421 +1671,229 @@ static uae_u8 ReadCIAB (uae_u32 addr, uae_u32 *flags)
                        parallel_direct_read_status(&v);
                        tmp |= v & 7;
                } else if (parallel_port_scsi) {
-                       tmp = parallel_port_scsi_read(1, ciabpra, ciabdra);
+                       tmp = parallel_port_scsi_read(1, c->pra, c->dra);
                } else {
                        // serial port in output mode
-                       if (ciabcra & 0x40) {
+                       if (c->t[0].cr & 0x40) {
                                tmp &= ~3;
-                               tmp |= (ciabsdr_cnt & 1) ? 2 : 0; // clock
-                               tmp |= (ciabsdr_buf & 0x80) ? 1 : 0; // data
+                               tmp |= (c->sdr_cnt & 1) ? 2 : 0; // clock
+                               tmp |= (c->sdr_buf & 0x80) ? 1 : 0; // data
                        }
                        tmp = handle_parport_joystick(1, tmp);
                }
 #endif
-               tmp = dongle_cia_read(1, reg, ciabpra, tmp);
+               tmp = dongle_cia_read(1, reg, c->pra, tmp);
 #if DONGLE_DEBUG > 0
                if (notinrom())
                        write_log(_T("BFD000 R %02X %s\n"), tmp, debuginfo(0));
 #endif
 
                if (currprefs.cs_ciatype[1]) {
-                       tmp &= ~ciabdra;
-                       tmp |= ciabpra & ciabdra;
+                       tmp &= ~c->dra;
+                       tmp |= c->pra & c->dra;
                }
 
                return tmp;
        case 1:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFD100 R %02X %s\n"), ciabprb, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFD100 R %02X %s\n"), c->prb, debuginfo(0));
 #endif
-               tmp = ciabprb;
+               tmp = c->prb;
                tmp = DISK_status_ciab(tmp);
-               tmp = dongle_cia_read (1, reg, ciabprb, tmp);
-               // A PBON
-               if (ciabcrb & 2) {
-                       int pb7 = 0;
-                       if (ciabcrb & 4)
-                               pb7 = ciabcrb & 1;
-                       tmp &= ~0x80;
-                       tmp |= pb7 ? 0x80 : 00;
-               }
-               // B PBON
-               if (ciabcra & 2) {
-                       int pb6 = 0;
-                       if (ciabcra & 4)
-                               pb6 = ciabcra & 1;
-                       tmp &= ~0x40;
-                       tmp |= pb6 ? 0x40 : 00;
-               }
-
+               tmp = dongle_cia_read(1, reg, c->prb, tmp);
+               tmp = CIA_PBON(c, tmp);
                if (currprefs.cs_ciatype[1]) {
-                       tmp &= ~ciabdrb;
-                       tmp |= ciabprb & ciabdrb;
+                       tmp &= ~c->drb;
+                       tmp |= c->prb & c->drb;
                }
 
                return tmp;
        case 2:
-               return ciabdra;
+               return c->dra;
        case 3:
-               return ciabdrb;
+               return c->drb;
        case 4:
-               return (uae_u8)((ciabta - ciabta_passed) & 0xff);
        case 5:
-               return (uae_u8)((ciabta - ciabta_passed) >> 8);
        case 6:
-               return (uae_u8)((ciabtb - ciabtb_passed) & 0xff);
        case 7:
-               return (uae_u8)((ciabtb - ciabtb_passed) >> 8);
        case 8:
-               CIAB_tod_check ();
-               if (ciabtlatch) {
-                       ciabtlatch = 0;
-                       return getciatod(ciabtol);
-               } else
-                       return getciatod(ciabtod);
        case 9:
-               CIAB_tod_check ();
-               if (ciabtlatch)
-                       return getciatod(ciabtol) >> 8;
-               else
-                       return getciatod(ciabtod) >> 8;
        case 10:
-               CIAB_tod_check ();
-               if (!currprefs.cs_cia6526) {
-                       if (!ciabtlatch) {
-                               /* no latching if ALARM is set */
-                               if (!(ciabcrb & 0x80))
-                                       ciabtlatch = 1;
-                               ciabtol = ciabtod;
-                       }
-                       return getciatod(ciabtol) >> 16;
-               } else {
-                       if (ciabtlatch)
-                               return getciatod(ciabtol) >> 16;
-                       else
-                               return getciatod(ciabtod) >> 16;
-               }
        case 11:
-               if (currprefs.cs_cia6526) {
-                       if (!ciabtlatch) {
-                               if (!(ciabcrb & 0x80))
-                                       ciabtlatch = 1;
-                               ciabtol = ciabtod;
-                       }
-                       if (ciabtlatch)
-                               return getciatod(ciabtol) >> 24;
-                       else
-                               return getciatod(ciabtod) >> 24;
-               } else {
-                       return 0xff;
-               }
-               break;
        case 12:
-               return ciabsdr;
        case 13:
-#if CIAB_DEBUG_IRQ
-               if (ciabicr & (0x80 | 0x40))
-                       write_log (_T("CIAB IRQ cleared PC=%x\n"), M68K_GETPC);
-#endif
-               tmp = ciabicr & ~(0x40 | 0x20);
-               ciabicr = 0;
-               return tmp;
        case 14:
-               //write_log (_T("CIABCRA READ %d %x\n"), ciabcra, M68K_GETPC);
-               return ciabcra;
        case 15:
-               return ciabcrb;
+               return ReadCIAReg(1, reg);
        }
        return 0;
 }
 
-static void WriteCIAA (uae_u16 addr, uae_u8 val, uae_u32 *flags)
+static void WriteCIAA(uae_u16 addr, uae_u8 val, uae_u32 *flags)
 {
+       struct CIA *c = &cia[0];
        int reg = addr & 15;
 
 #if CIAA_DEBUG_W > 0
-       write_log (_T("W_CIAA: bfe%x01 %02X %08X\n"), reg, val, M68K_GETPC);
+       write_log(_T("W_CIAA: bfe%x01 %02X %08X\n"), reg, val, M68K_GETPC);
 #endif
 #ifdef ACTION_REPLAY
        ar_ciaa[reg] = val;
 #endif
        if (!currprefs.cs_ciaoverlay && oldovl) {
-               map_overlay (1);
+               map_overlay(1);
                oldovl = 0;
        }
        switch (reg) {
        case 0:
 #if DONGLE_DEBUG > 0
                if (notinrom ())
-                       write_log (_T("BFE001 W %02X %s\n"), val, debuginfo(0));
+                       write_log(_T("BFE001 W %02X %s\n"), val, debuginfo(0));
 #endif
-               ciaapra = (ciaapra & ~0xc3) | (val & 0xc3);
-               bfe001_change ();
-               handle_cd32_joystick_cia (ciaapra, ciaadra);
-               dongle_cia_write (0, reg, ciaadra, val);
+               c->pra = (c->pra & ~0xc3) | (val & 0xc3);
+               bfe001_change();
+               handle_cd32_joystick_cia(c->pra, c->dra);
+               dongle_cia_write(0, reg, c->dra, val);
 #ifdef AMAX
                if (is_device_rom(&currprefs, ROMTYPE_AMAX, 0) > 0)
-                       amax_bfe001_write (val, ciaadra);
+                       amax_bfe001_write(val, c->dra);
 #endif
                break;
        case 1:
 #if DONGLE_DEBUG > 0
                if (notinrom ())
-                       write_log (_T("BFE101 W %02X %s\n"), val, debuginfo(0));
+                       write_log(_T("BFE101 W %02X %s\n"), val, debuginfo(0));
 #endif
-               ciaaprb = val;
-               dongle_cia_write (0, reg, ciaadrb, val);
+               c->prb = val;
+               dongle_cia_write(0, reg, c->drb, val);
 #ifdef PARALLEL_PORT
                if (isprinter()) {
                        if (isprinter() > 0) {
                                doprinter(val);
                                cia_parallelack();
                        } else if (isprinter() < 0) {
-                               parallel_direct_write_data(val, ciaadrb);
+                               parallel_direct_write_data(val, c->drb);
                                cia_parallelack();
                        }
                }
 #endif
 #ifdef ARCADIA
                if (!isprinter() && arcadia_bios) {
-                       arcadia_parport(1, ciaaprb, ciaadrb);
+                       arcadia_parport(1, c->prb, c->drb);
                }
 #endif
                if (!isprinter() && parallel_port_scsi) {
-                       parallel_port_scsi_write(0, ciaaprb, ciaadrb);
+                       parallel_port_scsi_write(0, c->prb, c->drb);
                }
                break;
        case 2:
 #if DONGLE_DEBUG > 0
                if (notinrom ())
-                       write_log (_T("BFE201 W %02X %s\n"), val, debuginfo(0));
+                       write_log(_T("BFE201 W %02X %s\n"), val, debuginfo(0));
 #endif
-               ciaadra = val;
-               dongle_cia_write (0, reg, ciaapra, val);
-               bfe001_change ();
+               c->dra = val;
+               dongle_cia_write(0, reg, c->pra, val);
+               bfe001_change();
                break;
        case 3:
-               ciaadrb = val;
-               dongle_cia_write (0, reg, ciaaprb, val);
+               c->drb = val;
+               dongle_cia_write(0, reg, c->prb, val);
 #if DONGLE_DEBUG > 0
                if (notinrom ())
-                       write_log (_T("BFE301 W %02X %s\n"), val, debuginfo(0));
+                       write_log(_T("BFE301 W %02X %s\n"), val, debuginfo(0));
 #endif
 #ifdef ARCADIA
                if (arcadia_bios)
-                       arcadia_parport (1, ciaaprb, ciaadrb);
+                       arcadia_parport(1, c->prb, c->drb);
 #endif
                break;
        case 4:
-               CIA_update ();
-               ciaala = (ciaala & 0xff00) | val;
-               CIA_calctimers ();
-               break;
        case 5:
-               CIA_update ();
-               ciaala = (ciaala & 0xff) | (val << 8);
-               if ((ciaacra & 1) == 0)
-                       ciaata = ciaala;
-               if (ciaacra & 8) {
-                       ciaata = ciaala;
-                       ciaacra |= 1;
-                       ciaastarta = CIASTARTCYCLESHI;
-               }
-               CIA_calctimers ();
-               break;
        case 6:
-               CIA_update ();
-               ciaalb = (ciaalb & 0xff00) | val;
-               CIA_calctimers ();
-               break;
        case 7:
-               CIA_update ();
-               ciaalb = (ciaalb & 0xff) | (val << 8);
-               if ((ciaacrb & 1) == 0)
-                       ciaatb = ciaalb;
-               if (ciaacrb & 8) {
-                       ciaatb = ciaalb;
-                       ciaacrb |= 1;
-                       ciaastartb = CIASTARTCYCLESHI;
-               }
-               CIA_calctimers ();
-               break;
        case 8:
-               if (ciaacrb & 0x80) {
-                       setciatod(&ciaaalarm , (getciatod(ciaaalarm) & ~0xff) | val);
-               } else {
-                       setciatod(&ciaatod, (getciatod(ciaatod) & ~0xff) | val);
-                       ciaatodon = 1;
-                       ciaa_checkalarm (false);
-               }
-               break;
        case 9:
-               if (ciaacrb & 0x80) {
-                       setciatod(&ciaaalarm, (getciatod(ciaaalarm) & ~0xff00) | (val << 8));
-               } else {
-                       setciatod(&ciaatod, (getciatod(ciaatod) & ~0xff00) | (val << 8));
-               }
-               break;
        case 10:
-               if (ciaacrb & 0x80) {
-                       setciatod(&ciaaalarm, (getciatod(ciaaalarm) & ~0xff0000) | (val << 16));
-               } else {
-                       setciatod(&ciaatod, (getciatod(ciaatod) & ~0xff0000) | (val << 16));
-                       if (!currprefs.cs_cia6526)
-                               ciaatodon = 0;
-               }
-               break;
        case 11:
-               if (currprefs.cs_cia6526) {
-                       if (ciaacrb & 0x80) {
-                               setciatod(&ciaaalarm, (getciatod(ciaaalarm) & ~0xff000000) | (val << 24));
-                       } else {
-                               setciatod(&ciaatod, (getciatod(ciaatod) & ~0xff000000) | (val << 24));
-                               ciaatodon = 0;
-                       }
-               }
-               break;
        case 12:
-               CIA_update ();
-               ciaasdr = val;
-               if ((ciaacra & 0x41) == 0x41) {
-                       ciaasdr_load = 1;
-                       if (ciaasdr_cnt == 0) {
-                               ciaasdr_cnt = 8 * 2;
-                               ciaasdr_load = 0;
-                               ciaasdr_buf = ciaasdr;
-                       }
-               }
-#if KB_DEBUG
-               write_log (_T("CIAA serial port write: %02x cnt=%d PC=%08x\n"), ciaasdr, ciaasdr_cnt, M68K_GETPC);
-#endif
-               CIA_calctimers ();
-               break;
        case 13:
-               setclr (&ciaaimask,val);
-               RethinkICRA ();
+       case 15:
+               CIA_update();
+               WriteCIAReg(0, reg, val);
+               CIA_calctimers();
                break;
        case 14:
-               CIA_update ();
-               val &= 0x7f; /* bit 7 is unused */
-               if ((val & 1) && !(ciaacra & 1))
-                       ciaastarta = CIASTARTCYCLESCRA;
-               if (currprefs.cpuboard_type != 0 && (val & 0x40) != (ciaacra & 0x40)) {
+               CIA_update();
+               // keyboard handshake handling
+               if (currprefs.cpuboard_type != 0 && (val & 0x40) != (c->t[0].cr & 0x40)) {
                        /* bleh, Phase5 CPU timed early boot key check fix.. */
                        if (m68k_getpc() >= 0xf00000 && m68k_getpc() < 0xf80000)
                                check_keyboard();
                }
-               if ((val & 0x40) != 0 && (ciaacra & 0x40) == 0) {
+               if ((val & CR_INMODE1) != 0 && (c->t[0].cr & CR_INMODE1) == 0) {
                        // handshake start
                        if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
                                kbhandshakestart = get_cycles();
                        }
 #if KB_DEBUG
-                       write_log(_T("KB_ACK_START %02x->%02x %08x\n"), ciaacra, val, M68K_GETPC);
+                       write_log(_T("KB_ACK_START %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
 #endif
-               } else if ((val & 0x40) == 0 && (ciaacra & 0x40) != 0) {
+               } else if ((val & CR_INMODE1) == 0 && (c->t[0].cr & CR_INMODE1) != 0) {
                        // handshake end
                        /* todo: check if low to high or high to low only */
                        if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
-                               int len = (int)get_cycles() - (int)kbhandshakestart;
+                               evt_t len = get_cycles() - kbhandshakestart;
                                if (len < currprefs.cs_kbhandshake * CYCLE_UNIT) {
                                        write_log(_T("Keyboard handshake pulse length %d < %d (CCKs)\n"), len / CYCLE_UNIT, currprefs.cs_kbhandshake);
                                }
                        }
                        kblostsynccnt = 0;
 #if KB_DEBUG
-                       write_log (_T("KB_ACK_END %02x->%02x %08x\n"), ciaacra, val, M68K_GETPC);
+                       write_log(_T("KB_ACK_END %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
 #endif
                }
-               ciaacra = val;
-               if (ciaacra & 0x10) {
-                       ciaacra &= ~0x10;
-                       ciaata = ciaala;
-               }
-               CIA_calctimers ();
-               break;
-       case 15:
-               CIA_update ();
-               if ((val & 1) && !(ciaacrb & 1))
-                       ciaastartb = CIASTARTCYCLESCRA;
-               ciaacrb = val;
-               if (ciaacrb & 0x10) {
-                       ciaacrb &= ~0x10;
-                       ciaatb = ciaalb;
-               }
-               CIA_calctimers ();
+               WriteCIAReg(0, reg, val);
+               CIA_calctimers();
                break;
        }
 }
 
 static void write_ciab_serial(uae_u8 ndata, uae_u8 odata, uae_u8 ndir, uae_u8 odir)
 {
+       struct CIA *c = &cia[1];
        uae_u8 val = ndata & ndir;
+       uae_u8 icr = 0;
+
        // CNT 0->1?
        if ((val & 2) && !((odata & odir) & 2)) {
-               int icr = 0;
                // CIA-B SP in input mode
-               if (!(ciabcra & 0x40)) {
-                       ciabsdr_buf <<= 1;
-                       ciabsdr_buf |= (val & 1) ? 0x01 : 0x00;
-                       ciabsdr_cnt++;
-                       if (ciabsdr_cnt >= 8) {
+               if (!(c->t[0].cr & CR_SPMODE)) {
+                       c->sdr_buf <<= 1;
+                       c->sdr_buf |= (val & 1) ? 0x01 : 0x00;
+                       c->sdr_cnt++;
+                       if (c->sdr_cnt >= 8) {
                                // Data received
-                               ciabsdr = ciabsdr_buf;
-                               ciabicr |= 8;
-                               icr = 1;
-                               ciabsdr_cnt = 0;
-                       }
-               }
-               // A INMODE=1 (count CNT pulses)
-               if ((ciabcra & 0x21) == 0x21) {
-                       ciabta--;
-                       if (ciabta == 0) {
-                               ciabicr |= 1;
-                               ciabta = ciabla;
-                               if (ciabcra & 0x8) {
-                                       ciabcra &= ~1;
-                               }
-                               // B INMODE = 10 or 11 (count A undeflows)
-                               if ((ciabcrb & 0x41) == 0x41) {
-                                       ciabtb--;
-                                       if (ciabtb == 0) {
-                                               ciabicr |= 2;
-                                               ciabtb = ciablb;
-                                               if (ciabcrb & 0x8) {
-                                                       ciabcrb &= ~1;
-                                               }
-                                       }
-                               }
-                               icr = 1;
+                               c->sdr = c->sdr_buf;
+                               icr |= ICR_SP;
+                               c->sdr_cnt = 0;
                        }
                }
-               // B INMODE=01 (count CNT pulses)
-               if ((ciabcrb & 0x61) == 0x21) {
-                       ciabtb--;
-                       if (ciabtb == 0) {
-                               ciabicr |= 2;
-                               ciabtb = ciablb;
-                               if (ciabcrb & 0x8) {
-                                       ciabcrb &= ~1;
-                               }
-                               icr = 1;
-                       }
-               }
-               if (icr) {
-                       RethinkICRB();
-               }
+               icr |= cia_inmode_cnt(1);
+       }
+       if (icr) {
+               CIA_sync_interrupt(1, icr);
        }
 }
 
-static void WriteCIAB (uae_u16 addr, uae_u8 val, uae_u32 *flags)
+static void WriteCIAB(uae_u16 addr, uae_u8 val, uae_u32 *flags)
 {
+       struct CIA *c = &cia[1];
        int reg = addr & 15;
 
 #if CIAB_DEBUG_W > 0
        if (((addr >= 8 && addr <= 10) || addr == 15) || CIAB_DEBUG_W > 1)
-               write_log (_T("W_CIAB: bfd%x00 %02X %08X\n"), reg, val, M68K_GETPC);
+               write_log(_T("W_CIAB: bfd%x00 %02X %08X\n"), reg, val, M68K_GETPC);
 #endif
 #ifdef ACTION_REPLAY
        ar_ciab[reg] = val;
@@ -1710,195 +1901,82 @@ static void WriteCIAB (uae_u16 addr, uae_u8 val, uae_u32 *flags)
        switch (reg) {
        case 0:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFD000 W %02X %s\n"), val, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFD000 W %02X %s\n"), val, debuginfo(0));
 #endif
-               dongle_cia_write (1, reg, ciabdra, val);
-               write_ciab_serial(val, ciabpra, ciabdra, ciabdra);
-               ciabpra = val;
+               dongle_cia_write(1, reg, c->dra, val);
+               write_ciab_serial(val, c->pra, c->dra, c->dra);
+               c->pra = val;
 #ifdef SERIAL_PORT
                if (currprefs.use_serial)
-                       serial_writestatus(ciabpra, ciabdra);
+                       serial_writestatus(c->pra, c->dra);
 #endif
 #ifdef PARALLEL_PORT
-               if (isprinter () < 0) {
-                       parallel_direct_write_status (val, ciabdra);
-               } else if (parallel_port_scsi) {
-                       parallel_port_scsi_write(1, ciabpra, ciabdra);
+               if (isprinter() < 0) {
+                       parallel_direct_write_status(val, c->dra);
+               }
+               else if (parallel_port_scsi) {
+                       parallel_port_scsi_write(1, c->pra, c->dra);
                }
 #endif
                break;
        case 1:
                *flags |= 2;
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFD100 W %02X %s\n"), val, debuginfo(0));
-#endif
-               dongle_cia_write (1, ciabdrb, reg, val);
-               ciabprb = val;
-               // PBON overrides PB6 and PB7
-               if (ciabcrb & 2) {
-                       int pb7 = 0;
-                       // OUTMODE
-                       if (ciabcrb & 4) {
-                               pb7 = ciabcrb & 1;
-                       }
-                       val &= ~0x80;
-                       val |= pb7 ? 0x80 : 00;
-               }
-               if (ciabcra & 2) {
-                       int pb6 = 0;
-                       // OUTMODE
-                       if (ciabcra & 4) {
-                               pb6 = ciabcra & 1;
-                       }
-                       val &= ~0x40;
-                       val |= pb6 ? 0x40 : 00;
-               }
-               DISK_select (val);
+               if (notinrom())
+                       write_log(_T("BFD100 W %02X %s\n"), val, debuginfo(0));
+#endif
+               dongle_cia_write(1, c->drb, reg, val);
+               c->prb = val;
+               val = CIA_PBON(c, val);
+               DISK_select(val);
                break;
        case 2:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFD200 W %02X %s\n"), val, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFD200 W %02X %s\n"), val, debuginfo(0));
 #endif
-               dongle_cia_write (1, reg, ciabpra, val);
-               write_ciab_serial(ciabpra, ciabpra, val, ciabdra);
-               ciabdra = val;
+               dongle_cia_write(1, reg, c->pra, val);
+               write_ciab_serial(c->pra, c->pra, val, c->dra);
+               c->dra = val;
 #ifdef SERIAL_PORT
                if (currprefs.use_serial)
-                       serial_writestatus (ciabpra, ciabdra);
+                       serial_writestatus(c->pra, c->dra);
 #endif
                break;
        case 3:
 #if DONGLE_DEBUG > 0
-               if (notinrom ())
-                       write_log (_T("BFD300 W %02X %s\n"), val, debuginfo(0));
+               if (notinrom())
+                       write_log(_T("BFD300 W %02X %s\n"), val, debuginfo(0));
 #endif
-               dongle_cia_write (1, reg, ciabprb, val);
-               ciabdrb = val;
+               dongle_cia_write(1, reg, c->prb, val);
+               c->drb = val;
                break;
        case 4:
-               CIA_update ();
-               ciabla = (ciabla & 0xff00) | val;
-               CIA_calctimers ();
-               break;
        case 5:
-               CIA_update ();
-               ciabla = (ciabla & 0xff) | (val << 8);
-               if ((ciabcra & 1) == 0)
-                       ciabta = ciabla;
-               if (ciabcra & 8) {
-                       ciabta = ciabla;
-                       ciabcra |= 1;
-                       ciabstarta = CIASTARTCYCLESHI;
-               }
-               CIA_calctimers ();
-               break;
        case 6:
-               CIA_update ();
-               ciablb = (ciablb & 0xff00) | val;
-               CIA_calctimers ();
-               break;
        case 7:
-               CIA_update ();
-               ciablb = (ciablb & 0xff) | (val << 8);
-               if ((ciabcrb & 1) == 0)
-                       ciabtb = ciablb;
-               if (ciabcrb & 8) {
-                       ciabtb = ciablb;
-                       ciabcrb |= 1;
-                       ciabstartb = CIASTARTCYCLESHI;
-               }
-               CIA_calctimers ();
-               break;
        case 8:
-               CIAB_tod_check ();
-               if (ciabcrb & 0x80) {
-                       setciatod(&ciabalarm, (getciatod(ciabalarm) & ~0xff) | val);
-               } else {
-                       setciatod(&ciabtod, (getciatod(ciabtod) & ~0xff) | val);
-                       ciabtodon = 1;
-                       ciab_checkalarm (false, true);
-               }
-               break;
        case 9:
-               CIAB_tod_check ();
-               if (ciabcrb & 0x80) {
-                       setciatod(&ciabalarm, (getciatod(ciabalarm) & ~0xff00) | (val << 8));
-               } else {
-                       setciatod(&ciabtod, (getciatod(ciabtod) & ~0xff00) | (val << 8));
-               }
-               break;
        case 10:
-               CIAB_tod_check ();
-               if (ciabcrb & 0x80) {
-                       setciatod(&ciabalarm, (getciatod(ciabalarm) & ~0xff0000) | (val << 16));
-               } else {
-                       setciatod(&ciabtod, (getciatod(ciabtod) & ~0xff0000) | (val << 16));
-                       if (!currprefs.cs_cia6526)
-                               ciabtodon = 0;
-               }
-               break;
        case 11:
-               if (currprefs.cs_cia6526) {
-                       CIAB_tod_check ();
-                       if (ciabcrb & 0x80) {
-                               setciatod(&ciabalarm, (getciatod(ciabalarm) & ~0xff000000) | (val << 24));
-                       } else {
-                               setciatod(&ciabtod, (getciatod(ciabtod) & ~0xff000000) | (val << 24));
-                               ciabtodon = 0;
-                       }
-               }
-               break;
        case 12:
-               CIA_update ();
-               ciabsdr = val;
-               if ((ciabcra & 0x41) == 0x41) {
-                       ciabsdr_load = 1;
-                       if (ciabsdr_cnt == 0) {
-                               ciabsdr_cnt = 8 * 2;
-                               ciabsdr_load = 0;
-                       }
-               }
-               CIA_calctimers ();
-               break;
        case 13:
-               setclr (&ciabimask, val);
-               RethinkICRB ();
-               break;
        case 14:
-               CIA_update ();
-               val &= 0x7f; /* bit 7 is unused */
-               if ((val & 1) && !(ciabcra & 1))
-                       ciabstarta = CIASTARTCYCLESCRA;
-               ciabcra = val;
-               if (ciabcra & 0x10) {
-                       ciabcra &= ~0x10;
-                       ciabta = ciabla;
-               }
-               CIA_calctimers ();
-               break;
        case 15:
-               CIA_update ();
-               if ((val & 1) && !(ciabcrb & 1))
-                       ciabstartb = CIASTARTCYCLESCRA;
-               ciabcrb = val;
-               if (ciabcrb & 0x10) {
-                       ciabcrb &= ~0x10;
-                       ciabtb = ciablb;
-               }
-               CIA_calctimers ();
+               CIA_update();
+               WriteCIAReg(1, reg, val);
+               CIA_calctimers();
                break;
        }
 }
 
-void cia_set_overlay (bool overlay)
+void cia_set_overlay(bool overlay)
 {
        oldovl = overlay;
 }
 
-void CIA_reset (void)
+void CIA_reset(void)
 {
 #ifdef TOD_HACK
        tod_hack_tv = 0;
@@ -1912,26 +1990,23 @@ void CIA_reset (void)
        serbits = 0;
        resetwarning_phase = resetwarning_timer = 0;
        heartbeat_cnt = 0;
-       ciab_tod_event_state = 0;
+       cia[1].tod_event_state = 0;
 
        if (!savestate_state) {
                oldovl = true;
                kbstate = 0;
-               ciaatlatch = ciabtlatch = 0;
-               ciaapra = 0; ciaadra = 0;
-               ciaaprb = 0; ciaadrb = 0;
-               ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
-               ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
-               ciaacra = ciaacrb = ciabcra = ciabcrb = 0;
-               ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
-               ciaaalarm = ciabalarm = 0;
-               ciabpra = 0x8C; ciabdra = 0;
-               ciabprb = 0; ciabdrb = 0;
-               ciaasdr_cnt = 0; ciaasdr = 0; ciaasdr_load = 0;
-               ciabsdr_cnt = 0; ciabsdr = 0; ciabsdr_buf = 0; ciabsdr_load = 0;
-               ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
+               memset(&cia, 0, sizeof(cia));
+               cia[0].t[0].timer = 0xffff;
+               cia[0].t[1].timer = 0xffff;
+               cia[1].t[0].timer = 0xffff;
+               cia[1].t[1].timer = 0xffff;
+               cia[0].t[0].latch = 0xffff;
+               cia[0].t[1].latch = 0xffff;
+               cia[1].t[0].latch = 0xffff;
+               cia[1].t[1].latch = 0xffff;
+               cia[1].pra = 0x8c;
                CIA_calctimers();
-               DISK_select_set(ciabprb);
+               DISK_select_set(cia[1].prb);
        }
        map_overlay(0);
        check_led();
@@ -1952,14 +2027,19 @@ void CIA_reset (void)
 
 void dumpcia(void)
 {
+       struct CIA *a = &cia[0];
+       struct CIA *b = &cia[1];
+
+       compute_passed_time();
+
        console_out_f(_T("A: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
-               ciaacra, ciaacrb, ciaaicr, ciaaimask, ciaata, ciaala, ciaatb, ciaalb);
-       console_out_f(_T("TOD %06x (%06x) ALARM %06x %c%c CYC=%08X\n"),
-               ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S', get_cycles());
+               a->t[0].cr, a->t[1].cr, a->icr1, a->imask, a->t[0].timer - a->t[0].passed, a->t[0].latch, a->t[1].timer - a->t[1].passed, a->t[1].latch);
+       console_out_f(_T("TOD %06x (%06x) ALARM %06x %c%c CYC=%016llX\n"),
+               a->tod, a->tol, a->alarm, a->tlatch ? 'L' : '-', a->todon ? '-' : 'S', get_cycles());
        console_out_f(_T("B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
-               ciabcra, ciabcrb, ciabicr, ciabimask, ciabta, ciabla, ciabtb, ciablb);
+               b->t[0].cr, b->t[1].cr, b->icr1, b->imask, b->t[0].timer - b->t[0].passed, b->t[0].latch, b->t[1].timer - b->t[1].passed, b->t[1].latch);
        console_out_f(_T("TOD %06x (%06x) ALARM %06x %c%c\n"),
-               ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S');
+               b->tod, b->tol, b->alarm, b->tlatch ? 'L' : '-', b->todon ? '-' : 'S');
 }
 
 /* CIA memory access */
@@ -1982,28 +2062,39 @@ static void cia_wait_pre(int cianummask)
                return;
 #endif
 
+#if CIA_IRQ_PROCESS_DELAY
        if (currprefs.cpu_memory_cycle_exact) {
                cia_interrupt_disabled |= cianummask;
        }
+#endif
 
 #ifndef CUSTOM_SIMPLE
-       evt_t c = get_cycles();
+       evt_t c = get_e_cycles();
        int div10 = c % DIV10;
        int add = 0;
-       if (div10 == 0) {
-               add = CYCLE_UNIT;
-       } else if (div10 > CYCLE_UNIT) {
-               add = DIV10 - div10;
-               add += CYCLE_UNIT;
+       int synccycle = E_CLOCK_SYNC * E_CYCLE_UNIT;
+       if (div10 < synccycle) {
+               add += synccycle - div10;
+       } else if (div10 > synccycle) {
+               add += DIV10 - div10;
+               add += synccycle;
        }
        // sync + 4 first cycles of E-clock
-       add += 4 * CYCLE_UNIT / 2;
+       add += E_CLOCK_1 * E_CYCLE_UNIT;
        x_do_cycles_pre(add);
 #endif
 }
 
-static void cia_wait_post (int cianummask, uae_u32 value)
+static void cia_wait_post(int cianummask, uaecptr addr, uae_u32 value, bool rw)
 {
+#ifdef DEBUGGER
+       if (currprefs.cpu_memory_cycle_exact && debug_dma) {
+               int r = (addr & 0xf00) >> 8;
+               int hpos = current_hpos();
+               record_cia_access(r, cianummask, value, rw, hpos, vpos);
+       }
+#endif
+
 #ifdef WITH_PPC
        if (ppc_state)
                return;
@@ -2011,10 +2102,11 @@ static void cia_wait_post (int cianummask, uae_u32 value)
        if (currprefs.cpu_thread)
                return;
        if (currprefs.cachesize) {
-               do_cycles (8 * CYCLE_UNIT /2);
+               do_cycles(8 * E_CYCLE_UNIT);
        } else {
-               // Last 4 cycles of E-clock
-               x_do_cycles_post(4 * CYCLE_UNIT / 2, value);
+               // Last 6 cycles of E-clock
+               x_do_cycles_post(E_CLOCK_2 * E_CYCLE_UNIT, value);
+#if CIA_IRQ_PROCESS_DELAY
                if (currprefs.cpu_memory_cycle_exact) {
                        cia_interrupt_disabled &= ~cianummask;
                        if ((cia_interrupt_delay & cianummask) & 1) {
@@ -2026,7 +2118,9 @@ static void cia_wait_post (int cianummask, uae_u32 value)
                                ICR(0x2000);
                        }
                }
+#endif
        }
+#if CIA_IRQ_PROCESS_DELAY
        if (!currprefs.cpu_memory_cycle_exact && cia_interrupt_delay) {
                int v = cia_interrupt_delay;
                cia_interrupt_delay = 0;
@@ -2035,6 +2129,7 @@ static void cia_wait_post (int cianummask, uae_u32 value)
                if (v & 2)
                        ICR(0x2000);
        }
+#endif
 }
 
 static void validate_cia(uaecptr addr, int write, uae_u8 val)
@@ -2107,7 +2202,7 @@ static int cia_chipselect(uaecptr addr)
        return cs;
 }
 
-static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
+static uae_u32 REGPARAM2 cia_bget(uaecptr addr)
 {
        int r = (addr & 0xf00) >> 8;
        uae_u8 v = 0;
@@ -2126,37 +2221,37 @@ static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
        switch (cia_chipselect(addr))
        {
        case 0:
-               if (!issinglecia ()) {
-                       cia_wait_pre (1 | 2);
-                       v = (addr & 1) ? ReadCIAA (r, &flags) : ReadCIAB (r, &flags);
-                       cia_wait_post (1 | 2, v);
+               if (!issinglecia()) {
+                       cia_wait_pre(1 | 2);
+                       v = (addr & 1) ? ReadCIAA(r, &flags) : ReadCIAB(r, &flags);
+                       cia_wait_post(1 | 2, addr, v, false);
                }
                break;
        case 1:
-               cia_wait_pre (2);
+               cia_wait_pre(2);
                if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
-                       v = (addr & 1) ? regs.irc : ReadCIAB (r, &flags);
+                       v = (addr & 1) ? regs.irc : ReadCIAB(r, &flags);
                } else {
-                       v = (addr & 1) ? dummy_get_safe(addr, 1, false, 0) : ReadCIAB (r, &flags);
+                       v = (addr & 1) ? dummy_get_safe(addr, 1, false, 0) : ReadCIAB(r, &flags);
                }
-               cia_wait_post (2, v);
+               cia_wait_post(2, addr, v, false);
                break;
        case 2:
-               cia_wait_pre (1);
+               cia_wait_pre(1);
                if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
-                       v = (addr & 1) ? ReadCIAA (r, &flags) : regs.irc >> 8;
+                       v = (addr & 1) ? ReadCIAA(r, &flags) : regs.irc >> 8;
                else
-                       v = (addr & 1) ? ReadCIAA (r, &flags) : dummy_get_safe(addr, 1, false, 0);
-               cia_wait_post (1, v);
+                       v = (addr & 1) ? ReadCIAA(r, &flags) : dummy_get_safe(addr, 1, false, 0);
+               cia_wait_post(1, addr, v, false);
                break;
        case 3:
                if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
-                       cia_wait_pre (0);
+                       cia_wait_pre(0);
                        v = (addr & 1) ? regs.irc : regs.irc >> 8;
-                       cia_wait_post (0, v);
+                       cia_wait_post(0, addr, v, false);
                }
                if (warned > 0 || currprefs.illegal_mem) {
-                       write_log (_T("cia_bget: unknown CIA address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC);
+                       write_log(_T("cia_bget: unknown CIA address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC);
                        warned--;
                }
                break;
@@ -2169,7 +2264,7 @@ static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
        return v;
 }
 
-static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
+static uae_u32 REGPARAM2 cia_wget(uaecptr addr)
 {
        int r = (addr & 0xf00) >> 8;
        uae_u16 v = 0;
@@ -2188,34 +2283,34 @@ static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
        switch (cia_chipselect(addr))
        {
        case 0:
-               if (!issinglecia ())
+               if (!issinglecia())
                {
-                       cia_wait_pre (1 | 2);
+                       cia_wait_pre(1 | 2);
                        v = ReadCIAB(r, &flags) << 8;
                        v |= ReadCIAA(r, &flags);
-                       cia_wait_post (1 | 2, v);
+                       cia_wait_post(1 | 2, addr, v, false);
                }
                break;
        case 1:
-               cia_wait_pre (2);
+               cia_wait_pre(2);
                v = ReadCIAB(r, &flags) << 8;
-               v |= dummy_get_safe(addr + 1, 1, false, 0);
-               cia_wait_post (2, v);
+               v |= dummy_get_safe(addr + 1, 1, false, 0) & 0xff;
+               cia_wait_post(2, addr, v, false);
                break;
        case 2:
-               cia_wait_pre (1);
+               cia_wait_pre(1);
                v = ReadCIAA(r, &flags);
                v |= dummy_get_safe(addr, 1, false, 0) << 8;
-               cia_wait_post (1, v);
+               cia_wait_post(1, addr, v, false);
                break;
        case 3:
                if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
-                       cia_wait_pre (0);
+                       cia_wait_pre(0);
                        v = regs.irc;
-                       cia_wait_post (0, v);
+                       cia_wait_post(0, addr, v, false);
                }
                if (warned > 0 || currprefs.illegal_mem) {
-                       write_log (_T("cia_wget: unknown CIA address %08X=%04X PC=%08X\n"), addr, v & 0xffff, M68K_GETPC);
+                       write_log(_T("cia_wget: unknown CIA address %08X=%04X PC=%08X\n"), addr, v & 0xffff, M68K_GETPC);
                        warned--;
                }
                break;
@@ -2230,25 +2325,25 @@ static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
        return v;
 }
 
-static uae_u32 REGPARAM2 cia_lget (uaecptr addr)
+static uae_u32 REGPARAM2 cia_lget(uaecptr addr)
 {
        uae_u32 v;
-       v = cia_wget (addr) << 16;
-       v |= cia_wget (addr + 2);
+       v = cia_wget(addr) << 16;
+       v |= cia_wget(addr + 2);
        return v;
 }
 
-static uae_u32 REGPARAM2 cia_wgeti (uaecptr addr)
+static uae_u32 REGPARAM2 cia_wgeti(uaecptr addr)
 {
        if (currprefs.cpu_model >= 68020)
-               return dummy_wgeti (addr);
-       return cia_wget (addr);
+               return dummy_wgeti(addr);
+       return cia_wget(addr);
 }
-static uae_u32 REGPARAM2 cia_lgeti (uaecptr addr)
+static uae_u32 REGPARAM2 cia_lgeti(uaecptr addr)
 {
        if (currprefs.cpu_model >= 68020)
-               return dummy_lgeti (addr);
-       return cia_lget (addr);
+               return dummy_lgeti(addr);
+       return cia_lget(addr);
 }
 
 
@@ -2263,7 +2358,7 @@ static bool cia_debug(uaecptr addr, uae_u32 value, int size)
        return false;
 }
 
-static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
+static void REGPARAM2 cia_bput(uaecptr addr, uae_u32 value)
 {
        int r = (addr & 0xf00) >> 8;
 
@@ -2275,7 +2370,7 @@ static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
                return;
        }
 
-       if (!isgaylenocia (addr))
+       if (!isgaylenocia(addr))
                return;
 
        if (memwatch_access_validator) {
@@ -2284,16 +2379,16 @@ static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
 
        int cs = cia_chipselect(addr);
 
-       if (!issinglecia () || (cs & 3) != 0) {
+       if (!issinglecia() || (cs & 3) != 0) {
                uae_u32 flags = 0;
-               cia_wait_pre (((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0));
+               cia_wait_pre(((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0));
                if ((cs & 2) == 0)
-                       WriteCIAB (r, value, &flags);
+                       WriteCIAB(r, value, &flags);
                if ((cs & 1) == 0)
-                       WriteCIAA (r, value, &flags);
-               cia_wait_post (((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0), value);
+                       WriteCIAA(r, value, &flags);
+               cia_wait_post(((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0), addr, value, true);
                if (((cs & 3) == 3) && (warned > 0 || currprefs.illegal_mem)) {
-                       write_log (_T("cia_bput: unknown CIA address %08X=%02X PC=%08X\n"), addr, value & 0xff, M68K_GETPC);
+                       write_log(_T("cia_bput: unknown CIA address %08X=%02X PC=%08X\n"), addr, value & 0xff, M68K_GETPC);
                        warned--;
                }
 #ifdef ACTION_REPLAY
@@ -2304,7 +2399,7 @@ static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
        }
 }
 
-static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 v)
+static void REGPARAM2 cia_wput(uaecptr addr, uae_u32 v)
 {
        int r = (addr & 0xf00) >> 8;
 
@@ -2316,7 +2411,7 @@ static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 v)
                return;
        }
 
-       if (!isgaylenocia (addr))
+       if (!isgaylenocia(addr))
                return;
 
        if (memwatch_access_validator) {
@@ -2328,16 +2423,16 @@ static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 v)
 
        int cs = cia_chipselect(addr);
 
-       if (!issinglecia () || (cs & 3) != 0) {
+       if (!issinglecia() || (cs & 3) != 0) {
                uae_u32 flags = 0;
-               cia_wait_pre (((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0));
+               cia_wait_pre(((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0));
                if ((cs & 2) == 0)
-                       WriteCIAB (r, v >> 8, &flags);
+                       WriteCIAB(r, v >> 8, &flags);
                if ((cs & 1) == 0)
-                       WriteCIAA (r, v & 0xff, &flags);
-               cia_wait_post (((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0), v);
+                       WriteCIAA(r, v & 0xff, &flags);
+               cia_wait_post(((cs & 2) == 0 ? 1 : 0) | ((cs & 1) == 0 ? 2 : 0), addr, v, true);
                if (((cs & 3) == 3) && (warned > 0 || currprefs.illegal_mem)) {
-                       write_log (_T("cia_wput: unknown CIA address %08X=%04X %08X\n"), addr, v & 0xffff, M68K_GETPC);
+                       write_log(_T("cia_wput: unknown CIA address %08X=%04X %08X\n"), addr, v & 0xffff, M68K_GETPC);
                        warned--;
                }
 #ifdef ACTION_REPLAY
@@ -2348,22 +2443,22 @@ static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 v)
        }
 }
 
-static void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
+static void REGPARAM2 cia_lput(uaecptr addr, uae_u32 value)
 {
        if (cia_debug(addr, value, sz_long))
                return;
-       cia_wput (addr, value >> 16);
-       cia_wput (addr + 2, value & 0xffff);
+       cia_wput(addr, value >> 16);
+       cia_wput(addr + 2, value & 0xffff);
 }
 
 /* battclock memory access */
 
-static uae_u32 REGPARAM3 clock_lget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 clock_wget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 clock_bget (uaecptr) REGPARAM;
-static void REGPARAM3 clock_lput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 clock_wput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 clock_bput (uaecptr, uae_u32) REGPARAM;
+static uae_u32 REGPARAM3 clock_lget(uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 clock_wget(uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 clock_bget(uaecptr) REGPARAM;
+static void REGPARAM3 clock_lput(uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 clock_wput(uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 clock_bput(uaecptr, uae_u32) REGPARAM;
 
 addrbank clock_bank = {
        clock_lget, clock_wget, clock_bget,
@@ -2373,7 +2468,7 @@ addrbank clock_bank = {
        ABFLAG_IO, S_READ, S_WRITE, NULL, 0x3f, 0xd80000
 };
 
-static uae_u8 getclockreg (int addr, struct tm *ct)
+static uae_u8 getclockreg(int addr, struct tm *ct)
 {
        uae_u8 v = 0;
 
@@ -2388,18 +2483,18 @@ static uae_u8 getclockreg (int addr, struct tm *ct)
        return v;
 }
 
-static void write_battclock (void)
+static void write_battclock(void)
 {
        if (!currprefs.rtcfile[0] || currprefs.cs_rtc == 0)
                return;
        TCHAR path[MAX_DPATH];
        cfgfile_resolve_path_out_load(currprefs.rtcfile, path, MAX_DPATH, PATH_ROM);
-       struct zfile *f = zfile_fopen (path, _T("wb"));
+       struct zfile *f = zfile_fopen(path, _T("wb"));
        if (f) {
                struct tm *ct;
-               time_t t = time (0);
+               time_t t = time(0);
                t += currprefs.cs_rtc_adjust;
-               ct = localtime (&t);
+               ct = localtime(&t);
                uae_u8 od;
                if (currprefs.cs_rtc == 2) {
                        od = rtc_ricoh.clock_control_d;
@@ -2408,29 +2503,29 @@ static void write_battclock (void)
                        od = rtc_msm.clock_control_d;
                }
                for (int i = 0; i < 13; i++) {
-                       uae_u8 v = getclockreg (i, ct);
-                       zfile_fwrite (&v, 1, 1, f);
+                       uae_u8 v = getclockreg(i, ct);
+                       zfile_fwrite(&v, 1, 1, f);
                }
                if (currprefs.cs_rtc == 2) {
                        rtc_ricoh.clock_control_d = od;
-                       zfile_fwrite (&rtc_ricoh.clock_control_d, 1, 1, f);
-                       zfile_fwrite (&rtc_ricoh.clock_control_e, 1, 1, f);
-                       zfile_fwrite (&rtc_ricoh.clock_control_f, 1, 1, f);
+                       zfile_fwrite(&rtc_ricoh.clock_control_d, 1, 1, f);
+                       zfile_fwrite(&rtc_ricoh.clock_control_e, 1, 1, f);
+                       zfile_fwrite(&rtc_ricoh.clock_control_f, 1, 1, f);
                } else {
                        rtc_msm.clock_control_d = od;
-                       zfile_fwrite (&rtc_msm.clock_control_d, 1, 1, f);
-                       zfile_fwrite (&rtc_msm.clock_control_e, 1, 1, f);
-                       zfile_fwrite (&rtc_msm.clock_control_f, 1, 1, f);
+                       zfile_fwrite(&rtc_msm.clock_control_d, 1, 1, f);
+                       zfile_fwrite(&rtc_msm.clock_control_e, 1, 1, f);
+                       zfile_fwrite(&rtc_msm.clock_control_f, 1, 1, f);
                }
                if (currprefs.cs_rtc == 2) {
-                       zfile_fwrite (rtc_ricoh.rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
-                       zfile_fwrite (rtc_ricoh.rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fwrite(rtc_ricoh.rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fwrite(rtc_ricoh.rtc_memory, RF5C01A_RAM_SIZE, 1, f);
                }
-               zfile_fclose (f);
+               zfile_fclose(f);
        }
 }
 
-void rtc_hardreset (void)
+void rtc_hardreset(void)
 {
        if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
                clock_bank.name = currprefs.cs_rtc == 1 ? _T("Battery backed up clock (MSM6242B)") : _T("Battery backed up clock A2000 (MSM6242B)");
@@ -2443,52 +2538,52 @@ void rtc_hardreset (void)
                rtc_ricoh.clock_control_d = 0x8; /* Timer EN */
                rtc_ricoh.clock_control_e = 0;
                rtc_ricoh.clock_control_f = 0;
-               memset (rtc_ricoh.rtc_memory, 0, RF5C01A_RAM_SIZE);
-               memset (rtc_ricoh.rtc_alarm, 0, RF5C01A_RAM_SIZE);
+               memset(rtc_ricoh.rtc_memory, 0, RF5C01A_RAM_SIZE);
+               memset(rtc_ricoh.rtc_alarm, 0, RF5C01A_RAM_SIZE);
                rtc_ricoh.rtc_alarm[10] = 1; /* 24H mode */
                rtc_ricoh.delayed_write = 0;
        }
        if (currprefs.rtcfile[0]) {
                TCHAR path[MAX_DPATH];
                cfgfile_resolve_path_out_load(currprefs.rtcfile, path, MAX_DPATH, PATH_ROM);
-               struct zfile *f = zfile_fopen (path, _T("rb"));
+               struct zfile *f = zfile_fopen(path, _T("rb"));
                if (f) {
                        uae_u8 empty[13];
-                       zfile_fread (empty, 13, 1, f);
+                       zfile_fread(empty, 13, 1, f);
                        uae_u8 v;
-                       zfile_fread (&v, 1, 1, f);
+                       zfile_fread(&v, 1, 1, f);
                        rtc_ricoh.clock_control_d = v;
                        rtc_msm.clock_control_d = v;
-                       zfile_fread (&v, 1, 1, f);
+                       zfile_fread(&v, 1, 1, f);
                        rtc_ricoh.clock_control_e = v;
                        rtc_msm.clock_control_d = v;
-                       zfile_fread (&v, 1, 1, f);
+                       zfile_fread(&v, 1, 1, f);
                        rtc_ricoh.clock_control_f = v;
                        rtc_msm.clock_control_d = v;
-                       zfile_fread (rtc_ricoh.rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
-                       zfile_fread (rtc_ricoh.rtc_memory, RF5C01A_RAM_SIZE, 1, f);
-                       zfile_fclose (f);
+                       zfile_fread(rtc_ricoh.rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fread(rtc_ricoh.rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fclose(f);
                }
        }
 }
 
-static uae_u32 REGPARAM2 clock_lget (uaecptr addr)
+static uae_u32 REGPARAM2 clock_lget(uaecptr addr)
 {
        if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0)
                return dummy_get(addr, 4, false, 0);
 
-       return (clock_wget (addr) << 16) | clock_wget (addr + 2);
+       return (clock_wget(addr) << 16) | clock_wget(addr + 2);
 }
 
-static uae_u32 REGPARAM2 clock_wget (uaecptr addr)
+static uae_u32 REGPARAM2 clock_wget(uaecptr addr)
 {
        if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0)
                return dummy_get(addr, 2, false, 0);
 
-       return (clock_bget (addr) << 8) | clock_bget (addr + 1);
+       return (clock_bget(addr) << 8) | clock_bget(addr + 1);
 }
 
-static uae_u32 REGPARAM2 clock_bget (uaecptr addr)
+static uae_u32 REGPARAM2 clock_bget(uaecptr addr)
 {
        struct tm *ct;
        uae_u8 v = 0;
@@ -2498,53 +2593,53 @@ static uae_u32 REGPARAM2 clock_bget (uaecptr addr)
 
 #ifdef CDTV
        if (currprefs.cs_cdtvram && (addr & 0xffff) >= 0x8000)
-               return cdtv_battram_read (addr);
+               return cdtv_battram_read(addr);
 #endif
 
        addr &= 0x3f;
        if ((addr & 3) == 2 || (addr & 3) == 0 || currprefs.cs_rtc == 0) {
                return dummy_get_safe(addr, 1, false, v);
        }
-       time_t t = time (0);
+       time_t t = time(0);
        t += currprefs.cs_rtc_adjust;
-       ct = localtime (&t);
+       ct = localtime(&t);
        addr >>= 2;
-       return getclockreg (addr, ct);
+       return getclockreg(addr, ct);
 }
 
 static void cputester_event(uae_u32 v)
 {
-       IRQ_forced(4, 64 / 2);
+       IRQ_forced(4, 28 / 2);
 }
 
-static void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
+static void REGPARAM2 clock_lput(uaecptr addr, uae_u32 value)
 {
        if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) {
                dummy_put(addr, 4, value);
                return;
        }
 
-       clock_wput (addr, value >> 16);
-       clock_wput (addr + 2, value);
+       clock_wput(addr, value >> 16);
+       clock_wput(addr + 2, value);
 }
 
-static void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
+static void REGPARAM2 clock_wput(uaecptr addr, uae_u32 value)
 {
        if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) {
                dummy_put(addr, 2, value);
                return;
        }
 
-       clock_bput (addr, value >> 8);
-       clock_bput (addr + 1, value);
+       clock_bput(addr, value >> 8);
+       clock_bput(addr + 1, value);
 }
 
-static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
+static void REGPARAM2 clock_bput(uaecptr addr, uae_u32 value)
 {
 //     write_log(_T("W: %x (%x): %x, PC=%08x\n"), addr, (addr & 0xff) >> 2, value & 0xff, M68K_GETPC);
 
        if (currprefs.cputester && (addr & 65535) == 0) {
-               event2_newevent_xx(-1, CYCLE_UNIT * (64 / 2), 0, cputester_event);
+               event2_newevent_xx(-1, CYCLE_UNIT * (62 / 2), 0, cputester_event);
        }
 
        if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) {
@@ -2554,7 +2649,7 @@ static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
 
 #ifdef CDTV
        if (currprefs.cs_cdtvram && (addr & 0xffff) >= 0x8000) {
-               cdtv_battram_write (addr, value);
+               cdtv_battram_write(addr, value);
                return;
        }
 #endif
@@ -2566,7 +2661,7 @@ static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
        value &= 0x0f;
        if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
 #if CLOCK_DEBUG
-               write_log (_T("CLOCK W %X: %X\n"), addr, value);
+               write_log(_T("CLOCK W %X: %X\n"), addr, value);
 #endif
                put_clock_msm(&rtc_msm, addr, value);
        } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
@@ -2578,211 +2673,201 @@ static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
 
 /* CIA-A and CIA-B save/restore code */
 
-static void save_cia_prepare (void)
+static void save_cia_prepare(void)
 {
-       CIA_update_check ();
-       CIA_calctimers ();
-       compute_passed_time ();
+       CIA_update_check();
+       CIA_calctimers();
+       compute_passed_time();
 }
 
-void restore_cia_start (void)
+void restore_cia_start(void)
 {
        /* Fixes very old statefiles without keyboard state */
        kbstate = 3;
-       setcapslockstate (0);
+       setcapslockstate(0);
        kblostsynccnt = 0;
 }
 
-void restore_cia_finish (void)
+void restore_cia_finish(void)
 {
-       eventtab[ev_cia].oldcycles = get_cycles ();
-       CIA_update ();
-       CIA_calctimers ();
-       compute_passed_time ();
+       eventtab[ev_cia].oldcycles = get_cycles();
+       CIA_update();
+       CIA_calctimers();
+       compute_passed_time();
        //dumpcia ();
-       DISK_select_set (ciabprb);
+       DISK_select_set(cia[1].prb);
 }
 
-uae_u8 *restore_cia (int num, uae_u8 *src)
+uae_u8 *restore_cia(int num, uae_u8 *src)
 {
+       struct CIA *c = &cia[num];
        uae_u8 b;
        uae_u16 w;
        uae_u32 l;
 
        /* CIA registers */
-       b = restore_u8 ();                                              /* 0 PRA */
-       if (num) ciabpra = b; else ciaapra = b;
-       b = restore_u8 ();                                              /* 1 PRB */
-       if (num) ciabprb = b; else ciaaprb = b;
-       b = restore_u8 ();                                              /* 2 DDRA */
-       if (num) ciabdra = b; else ciaadra = b;
-       b = restore_u8 ();                                              /* 3 DDRB */
-       if (num) ciabdrb = b; else ciaadrb = b;
-       w = restore_u16 ();                                             /* 4 TA */
-       if (num) ciabta = w; else ciaata = w;
-       w = restore_u16 ();                                             /* 6 TB */
-       if (num) ciabtb = w; else ciaatb = w;
-       l = restore_u8 ();                                              /* 8/9/A TOD */
-       l |= restore_u8 () << 8;
-       l |= restore_u8 () << 16;
-       if (num) ciabtod = l; else ciaatod = l;
-       restore_u8 ();                                                  /* B unused */
-       b = restore_u8 ();                                              /* C SDR */
-       if (num) ciabsdr = b; else ciaasdr = b;
-       b = restore_u8 ();                                              /* D ICR INFORMATION (not mask!) */
-       if (num) ciabicr = b; else ciaaicr = b;
-       b = restore_u8 ();                                              /* E CRA */
-       if (num) ciabcra = b; else ciaacra = b;
-       b = restore_u8 ();                                              /* F CRB */
-       if (num) ciabcrb = b; else ciaacrb = b;
+       c->pra = restore_u8();                          /* 0 PRA */
+       c->prb = restore_u8();                          /* 1 PRB */
+       c->dra = restore_u8();                          /* 2 DDRA */
+       c->drb = restore_u8();                          /* 3 DDRB */
+       c->t[0].timer = restore_u16();          /* 4 TA */
+       c->t[1].timer = restore_u16();          /* 6 TB */
+       l = restore_u8();                                       /* 8/9/A TOD */
+       l |= restore_u8() << 8;
+       l |= restore_u8() << 16;
+       c->tod = l;
+       restore_u8();                                           /* B unused */
+       c->sdr = restore_u8();                          /* C SDR */
+       c->icr2 = c->icr1 = restore_u8();       /* D ICR INFORMATION (not mask!) */
+       c->t[0].cr = restore_u8();                      /* E CRA */
+       c->t[1].cr = restore_u8();                      /* F CRB */
 
        /* CIA internal data */
 
-       b = restore_u8 ();                                              /* ICR MASK */
-       if (num) ciabimask = b; else ciaaimask = b;
-       w = restore_u8 ();                                              /* timer A latch */
-       w |= restore_u8 () << 8;
-       if (num) ciabla = w; else ciaala = w;
-       w = restore_u8 ();                                              /* timer B latch */
-       w |= restore_u8 () << 8;
-       if (num) ciablb = w; else ciaalb = w;
-       w = restore_u8 ();                                              /* TOD latched value */
-       w |= restore_u8 () << 8;
-       w |= restore_u8 () << 16;
-       if (num) ciabtol = w; else ciaatol = w;
-       l = restore_u8 ();                                              /* alarm */
-       l |= restore_u8 () << 8;
-       l |= restore_u8 () << 16;
-       if (num) ciabalarm = l; else ciaaalarm = l;
-       b = restore_u8 ();
-       if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1;   /* is TOD latched? */
-       if (num) ciabtodon = b & 2; else ciaatodon = b & 2;             /* is TOD stopped? */
-       if (num) ciaasdr_load = b & 4; else ciaasdr_load = b & 4; /* SP data pending */
-       b = restore_u8 ();
+       c->imask = restore_u8();                        /* ICR MASK */
+       w = restore_u8();                                       /* timer A latch */
+       w |= restore_u8() << 8;
+       c->t[0].latch = w;
+       w = restore_u8();                                       /* timer B latch */
+       w |= restore_u8() << 8;
+       c->t[1].latch = w;
+       l = restore_u8();                                       /* TOD latched value */
+       l |= restore_u8() << 8;
+       l |= restore_u8() << 16;
+       c->tol = w;
+       l = restore_u8();                                       /* alarm */
+       l |= restore_u8() << 8;
+       l |= restore_u8() << 16;
+       c->alarm = l;
+       b = restore_u8();
+       c->tlatch = (b & 1) != 0;                       /* flags */
+       c->todon = (b & 2) != 0;
+       c->sdr_load = (b & 4) != 0;
+       b = restore_u8();
 //     if (num)
 //             div10 = CYCLE_UNIT * b;
-       b = restore_u8 ();
-       if (num) ciabsdr_cnt = b; else ciaasdr_cnt = b;
-       b = restore_u8();
-       if (num) ciabsdr_buf = b; else ciaasdr_buf = b;
+       c->sdr_cnt = restore_u8();
+       c->sdr_buf = restore_u8();
+
+       // 4.9.2+
+       c->icr1 = c->icr2;
+       c->t[0].loaddelay = 0;
+       c->t[0].inputpipe = 0;
+       if (c->t[0].cr & CR_START) {
+               c->t[0].inputpipe = CIA_PIPE_ALL_MASK;
+       }
+       c->t[1].loaddelay = 0;
+       c->t[1].inputpipe = 0;
+       if (c->t[1].cr & CR_START) {
+               c->t[1].inputpipe = CIA_PIPE_ALL_MASK;
+       }
+       if (restore_u8() & 1) {
+               c->icr1 = restore_u8();
+               c->t[0].inputpipe = restore_u16();
+               c->t[1].inputpipe = restore_u16();
+               c->t[0].loaddelay = restore_u32();
+               c->t[1].loaddelay = restore_u32();
+
+       }
+
        return src;
 }
 
-uae_u8 *save_cia (int num, size_t *len, uae_u8 *dstptr)
+uae_u8 *save_cia(int num, size_t *len, uae_u8 *dstptr)
 {
+       struct CIA *c = &cia[num];
        uae_u8 *dstbak,*dst, b;
        uae_u16 t;
 
        if (dstptr)
                dstbak = dst = dstptr;
        else
-               dstbak = dst = xmalloc (uae_u8, 1000);
+               dstbak = dst = xmalloc(uae_u8, 1000);
 
-       save_cia_prepare ();
+       save_cia_prepare();
 
        /* CIA registers */
 
-       b = num ? ciabpra : ciaapra;                            /* 0 PRA */
-       save_u8 (b);
-       b = num ? ciabprb : ciaaprb;                            /* 1 PRB */
-       save_u8 (b);
-       b = num ? ciabdra : ciaadra;                            /* 2 DDRA */
-       save_u8 (b);
-       b = num ? ciabdrb : ciaadrb;                            /* 3 DDRB */
-       save_u8 (b);
-       t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
-       save_u16 (t);
-       t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 6 TB */
-       save_u16 (t);
-       b = (num ? ciabtod : ciaatod);                          /* 8 TODL */
-       save_u8 (b);
-       b = (num ? ciabtod >> 8 : ciaatod >> 8);        /* 9 TODM */
-       save_u8 (b);
-       b = (num ? ciabtod >> 16 : ciaatod >> 16);      /* A TODH */
-       save_u8 (b);
-       save_u8 (0);                                                            /* B unused */
-       b = num ? ciabsdr : ciaasdr;                            /* C SDR */
-       save_u8 (b);
-       b = num ? ciabicr : ciaaicr;                            /* D ICR INFORMATION (not mask!) */
-       save_u8 (b);
-       b = num ? ciabcra : ciaacra;                            /* E CRA */
-       save_u8 (b);
-       b = num ? ciabcrb : ciaacrb;                            /* F CRB */
-       save_u8 (b);
+       save_u8(c->pra);                                        /* 0 PRA */
+       save_u8(c->prb);                                        /* 1 PRB */
+       save_u8(c->dra);                                        /* 2 DDRA */
+       save_u8(c->drb);                                        /* 3 DDRB */
+       t = c->t[0].timer - c->t[0].passed;     /* 4 TA */
+       save_u16(t);
+       t = c->t[1].timer - c->t[1].passed;     /* 6 TB */
+       save_u16(t);
+       save_u8((uae_u8)c->tod);                        /* 8 TODL */
+       save_u8((uae_u8)(c->tod >> 8));         /* 9 TODM */
+       save_u8((uae_u8)(c->tod >> 16));        /* A TODH */
+       save_u8(0);                                                     /* B unused */
+       save_u8(c->sdr);                                        /* C SDR */
+       save_u8(c->icr2);                                       /* D ICR INFORMATION (not mask!) */
+       save_u8(c->t[0].cr);                            /* E CRA */
+       save_u8(c->t[1].cr);                            /* F CRB */
 
        /* CIA internal data */
 
-       save_u8 (num ? ciabimask : ciaaimask);          /* ICR */
-       b = (num ? ciabla : ciaala);                            /* timer A latch LO */
-       save_u8 (b);
-       b = (num ? ciabla >> 8 : ciaala >> 8);          /* timer A latch HI */
-       save_u8 (b);
-       b = (num ? ciablb : ciaalb);                            /* timer B latch LO */
-       save_u8 (b);
-       b = (num ? ciablb >> 8 : ciaalb >> 8);          /* timer B latch HI */
-       save_u8 (b);
-       b = (num ? ciabtol : ciaatol);                          /* latched TOD LO */
-       save_u8 (b);
-       b = (num ? ciabtol >> 8 : ciaatol >> 8);        /* latched TOD MED */
-       save_u8 (b);
-       b = (num ? ciabtol >> 16 : ciaatol >> 16);      /* latched TOD HI */
-       save_u8 (b);
-       b = (num ? ciabalarm : ciaaalarm);                      /* alarm LO */
-       save_u8 (b);
-       b = (num ? ciabalarm >> 8 : ciaaalarm >> 8);/* alarm MED */
-       save_u8 (b);
-       b = (num ? ciabalarm >> 16 : ciaaalarm >> 16);  /* alarm HI */
-       save_u8 (b);
+       save_u8(c->imask);                                      /* ICR */
+       save_u8((uae_u8)c->t[0].latch);         /* timer A latch LO */
+       save_u8(c->t[0].latch >> 8);            /* timer A latch HI */
+       save_u8((uae_u8)c->t[1].latch);         /* timer B latch LO */
+       save_u8(c->t[1].latch >> 8);            /* timer B latch HI */
+       save_u8(c->tol);                                        /* latched TOD LO */
+       save_u8(c->tol >> 8);                           /* latched TOD MED */
+       save_u8(c->tol >> 16);                          /* latched TOD HI */
+       save_u8(c->alarm);                                      /* alarm LO */
+       save_u8(c->alarm >> 8);                         /* alarm MED */
+       save_u8(c->alarm >> 16);                        /* alarm HI */
        b = 0;
-       if (num)
-               b |= ciabtlatch ? 1 : 0;
-       else
-               b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
-       if (num)
-               b |= ciabtodon ? 2 : 0;
-       else
-               b |= ciaatodon ? 2 : 0;   /* TOD stopped? */
-       if (num)
-               b |= ciabsdr_load ? 4 : 0;
-       else
-               b |= ciaasdr_load ? 2 : 0;   /* TOD stopped? */
+       b |= c->tlatch ? 1 : 0;                         /* is TOD latched? */
+       b |= c->todon ? 2 : 0;                          /* TOD stopped? */
+       b |= c->sdr_load ? 4 : 0;                       /* SDR loaded */
        save_u8(b);
        save_u8(0); // save_u8(num ? div10 / CYCLE_UNIT : 0);
-       save_u8(num ? ciabsdr_cnt : ciaasdr_cnt);
-       save_u8(num ? ciabsdr_buf : ciaasdr_buf);
+       save_u8(c->sdr_cnt);
+       save_u8(c->sdr_buf);
+
+       // 4.9.2+
+       save_u8(1);
+       save_u8(c->icr1);
+       save_u16(c->t[0].inputpipe);
+       save_u16(c->t[1].inputpipe);
+       save_u32(c->t[0].loaddelay);
+       save_u32(c->t[1].loaddelay);
+
        *len = dst - dstbak;
        return dstbak;
 }
 
-uae_u8 *save_keyboard (size_t *len, uae_u8 *dstptr)
+uae_u8 *save_keyboard(size_t *len, uae_u8 *dstptr)
 {
        uae_u8 *dst, *dstbak;
        if (dstptr)
                dstbak = dst = dstptr;
        else
-               dstbak = dst = xmalloc (uae_u8, 4 + 4 + 1 + 1 + 1 + 1 + 1 + 2);
-       save_u32 (getcapslockstate () ? 1 : 0);
-       save_u32 (1);
-       save_u8 (kbstate);
-       save_u8 (0);
-       save_u8 (0);
-       save_u8 (0);
-       save_u8 (kbcode);
-       save_u16 (kblostsynccnt);
+               dstbak = dst = xmalloc(uae_u8, 4 + 4 + 1 + 1 + 1 + 1 + 1 + 2);
+       save_u32(getcapslockstate() ? 1 : 0);
+       save_u32(1);
+       save_u8(kbstate);
+       save_u8(0);
+       save_u8(0);
+       save_u8(0);
+       save_u8(kbcode);
+       save_u16(kblostsynccnt);
        *len = dst - dstbak;
        return dstbak;
 }
 
-uae_u8 *restore_keyboard (uae_u8 *src)
+uae_u8 *restore_keyboard(uae_u8 *src)
 {
-       setcapslockstate (restore_u32 () & 1);
-       uae_u32 v = restore_u32 ();
-       kbstate = restore_u8 ();
-       restore_u8 ();
-       restore_u8 ();
-        restore_u8 ();
-       kbcode = restore_u8 ();
-       kblostsynccnt = restore_u16 ();
+       setcapslockstate(restore_u32() & 1);
+       uae_u32 v = restore_u32();
+       kbstate = restore_u8();
+       restore_u8();
+       restore_u8();
+       restore_u8();
+       kbcode = restore_u8();
+       kblostsynccnt = restore_u16();
        if (!(v & 1)) {
                kbstate = 3;
                kblostsynccnt = 0;
index 07e192540b819f5e52debbff1b81a148d5c1e6b7..58d505eb95d10002f2f0fc2fb75d0365d98ad939 100644 (file)
@@ -12155,7 +12155,7 @@ static void hsync_handler_post(bool onvsync)
        if (currprefs.cs_cd32cd) {
 
                if (cia_hsync < maxhpos) {
-                       CIAA_tod_inc(cia_hsync);
+                       CIAA_tod_handler(cia_hsync);
                        cia_hsync += (akiko_ntscmode() ? 262 : 313) * maxhpos;
                } else {
                        cia_hsync -= maxhpos;
@@ -12177,7 +12177,7 @@ static void hsync_handler_post(bool onvsync)
 #else
                if (cia_hsync < maxhpos) {
                        int newcount;
-                       CIAA_tod_inc(cia_hsync);
+                       CIAA_tod_handler(cia_hsync);
                        newcount = (int)((vblank_hz * (2 * maxvpos + (interlace_seen ? 1 : 0)) * (2 * maxhpos + (islinetoggle () ? 1 : 0))) / ((currprefs.cs_ciaatod == 2 ? 60 : 50) * 4));
                        cia_hsync += newcount;
                } else {
@@ -12188,11 +12188,11 @@ static void hsync_handler_post(bool onvsync)
                // CIA-A TOD counter increases when vsync pulse ends
                if (beamcon0 & BEAMCON0_VARVSYEN) {
                        if (vpos == vsstop && vs_state == true) {
-                               CIAA_tod_inc(lof_store ? hsstop : hsstop + hcenter);
+                               CIAA_tod_handler(lof_store ? hsstop : hsstop + hcenter);
                        }
                } else {
                        if (vpos == (currprefs.ntscmode ? VSYNC_ENDLINE_NTSC : VSYNC_ENDLINE_PAL)) {
-                               CIAA_tod_inc(lof_store ? 132 : 18);
+                               CIAA_tod_handler(lof_store ? 132 : 18);
                        }
                }
        }
index ad3cbc9a61099efc5cd4c371b9646f6e250192fe..ca527c220377dbfaec0129b3ad8bec67404d1a2a 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -1879,7 +1879,7 @@ void record_dma_hsync(void)
 #endif
 }
 
-void record_dma_event (uae_u32 evt, int hpos, int vpos)
+void record_dma_event(uae_u32 evt, int hpos, int vpos)
 {
        struct dma_rec *dr;
 
@@ -1997,10 +1997,8 @@ void record_dma_clear(int hpos, int vpos)
        dr->cf_reg = 0xffff;
 }
 
-void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra)
+static void dma_record_init(void)
 {
-       struct dma_rec *dr;
-
        if (!dma_record[0]) {
                dma_record[0] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
                dma_record[1] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
@@ -2009,6 +2007,31 @@ void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, in
                dma_record_frame[0] = -1;
                dma_record_frame[1] = -1;
        }
+}
+
+void record_cia_access(int r, int mask, uae_u16 value, bool rw, int hpos, int vpos)
+{
+       struct dma_rec* dr;
+
+       dma_record_init();
+
+       if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
+               return;
+
+       dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
+       dma_record_frame[dma_record_toggle] = timeframes;
+
+       dr->ciamask = mask;
+       dr->ciareg = r;
+       dr->ciavalue = value;
+       dr->ciarw = rw;
+}
+
+void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra)
+{
+       struct dma_rec *dr;
+
+       dma_record_init();
 
        if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
                return;
@@ -2033,7 +2056,7 @@ void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, in
        debug_mark_refreshed(dr->addr);
 }
 
-static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cycles, TCHAR *l1, TCHAR *l2, TCHAR *l3, TCHAR *l4, TCHAR *l5)
+static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cycles, TCHAR *l1, TCHAR *l2, TCHAR *l3, TCHAR *l4, TCHAR *l5, TCHAR *l6)
 {
        int longsize = dr->size;
        bool got = false;
@@ -2047,6 +2070,8 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy
        uae_u32 extraval;
        bool noval = false;
 
+       cycles += (vpos * maxhpos + hpos) * CYCLE_UNIT;
+
        if (l1)
                l1[0] = 0;
        if (l2)
@@ -2057,6 +2082,8 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy
                l4[0] = 0;
        if (l5)
                l5[0] = 0;
+       if (l6)
+               l6[0] = 0;
 
        if (dr->type != 0 || dr->reg != 0xffff || dr->evt)
                got = true;
@@ -2246,8 +2273,26 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy
                if (dr->evt & (DMA_EVENT_VB | DMA_EVENT_VS | DMA_EVENT_LOL | DMA_EVENT_LOF | DMA_EVENT_VDIW)) {
                        l3[cl2++] = 0;
                }
+
+               if (dr->evt & (DMA_EVENT_CIAA_IRQ | DMA_EVENT_CIAB_IRQ)) {
+                       l3[cl2++] = '#';
+               }
+               if (dr->evt & DMA_EVENT_CIAA_IRQ) {
+                       l3[cl2++] = 'A';
+               }
+               if (dr->evt & DMA_EVENT_CIAB_IRQ) {
+                       l3[cl2++] = 'B';
+               }
+
        }
        if (l5) {
+               if (dr->ciamask) {
+                       _stprintf(l5, _T("%c%s%X %04X"), dr->ciarw ? 'W' : 'R',
+                               dr->ciamask == 1 ? _T("A") : (dr->ciamask == 2 ? _T("B") : _T("X")),
+                               dr->ciareg, dr->ciavalue);
+               }
+       }
+       if (l6) {
                if (dr->addr != 0xffffffff) {
                        int ras, cas;
                        TCHAR xtra = ' ';
@@ -2255,14 +2300,14 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy
                        if (ret) {
                                xtra = '+';
                        }
-                       _stprintf(l5, _T("%c%03X %03X"), xtra, ras, cas);
+                       _stprintf(l6, _T("%c%03X %03X"), xtra, ras, cas);
                } else {
-                       l5[0] = 0;
+                       l6[0] = 0;
                }
                //_stprintf (l5, _T("%08X"), cycles + (vpos * maxhpos + hpos) * CYCLE_UNIT);
        }
        if (extra64) {
-               _tcscpy(l5, l4);
+               _tcscpy(l6, l4);
                _stprintf(l4, _T("%08X"), extraval);
        }
        return got;
@@ -2300,15 +2345,17 @@ static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
                TCHAR l3[200];
                TCHAR l4[200];
                TCHAR l5[200];
+               TCHAR l6[200];
                l1[0] = 0;
                l2[0] = 0;
                l3[0] = 0;
                l4[0] = 0;
                l5[0] = 0;
+               l6[0] = 0;
                for (i = 0; i < cols && h < maxh; i++, h++, dr++) {
-                       TCHAR l1l[16], l2l[16], l3l[16], l4l[16], l5l[16];
+                       TCHAR l1l[16], l2l[16], l3l[16], l4l[16], l5l[16], l6l[16];
 
-                       get_record_dma_info(dr, h, vpos, cycles, l1l, l2l, l3l, l4l, l5l);
+                       get_record_dma_info(dr, h, vpos, cycles, l1l, l2l, l3l, l4l, l5l, l6l);
                        if (dr_start[3 + 2].evt & DMA_EVENT_LOL) {
                                if (maxh == maxhpos_short) {
                                        maxh++;
@@ -2325,21 +2372,25 @@ static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
                        _stprintf(p, _T("%9s "), l4l);
                        p = l5 + _tcslen(l5);
                        _stprintf(p, _T("%9s "), l5l);
+                       p = l6 + _tcslen(l6);
+                       _stprintf(p, _T("%9s "), l6l);
                }
                if (logfile) {
-                       write_dlog (_T("%s\n"), l1);
-                       write_dlog (_T("%s\n"), l2);
-                       write_dlog (_T("%s\n"), l3);
-                       write_dlog (_T("%s\n"), l4);
-                       write_dlog (_T("%s\n"), l5);
-                       write_dlog (_T("\n"));
+                       write_dlog(_T("%s\n"), l1);
+                       write_dlog(_T("%s\n"), l2);
+                       write_dlog(_T("%s\n"), l3);
+                       write_dlog(_T("%s\n"), l4);
+                       write_dlog(_T("%s\n"), l5);
+                       write_dlog(_T("%s\n"), l6);
+                       write_dlog(_T("\n"));
                } else {
-                       console_out_f (_T("%s\n"), l1);
-                       console_out_f (_T("%s\n"), l2);
-                       console_out_f (_T("%s\n"), l3);
-                       console_out_f (_T("%s\n"), l4);
-                       console_out_f (_T("%s\n"), l5);
-                       console_out_f (_T("\n"));
+                       console_out_f(_T("%s\n"), l1);
+                       console_out_f(_T("%s\n"), l2);
+                       console_out_f(_T("%s\n"), l3);
+                       console_out_f(_T("%s\n"), l4);
+                       console_out_f(_T("%s\n"), l5);
+                       console_out_f(_T("%s\n"), l6);
+                       console_out_f(_T("\n"));
                }
        }
        if (logfile)
@@ -5791,7 +5842,7 @@ static void dma_disasm(int frames, int vp, int hp, int frames_end, int vp_end, i
                if (!dr)
                        return;
                TCHAR l1[16], l2[16], l3[16], l4[16];
-               if (get_record_dma_info(dr, hp, vp, 0, l1, l2, l3, l4, NULL)) {
+               if (get_record_dma_info(dr, hp, vp, 0, l1, l2, l3, l4, NULL, NULL)) {
                        console_out_f(_T(" - %02X %s %s %s\n"), hp, l2, l3, l4);
                }
                hp++;
index 46892d9d53ae7231a2b70322ec5801168aa94b16..4d41558cf9cdf7ada9bddaa13de97046e3116352 100644 (file)
 
 #include "uae/types.h"
 
-extern void CIA_reset (void);
-extern void CIA_vsync_prehandler (void);
-extern void CIA_hsync_prehandler (void);
-extern void CIA_hsync_posthandler (bool, bool);
-extern void CIA_handler (void);
-extern void CIAA_tod_inc (int);
-extern void CIAB_tod_handler (int);
-
-extern void diskindex_handler (void);
+extern void CIA_reset(void);
+extern void CIA_vsync_prehandler(void);
+extern void CIA_hsync_prehandler(void);
+extern void CIA_hsync_posthandler(bool, bool);
+extern void CIA_handler(void);
+extern void CIAA_tod_handler(int);
+extern void CIAB_tod_handler(int);
+
 extern void cia_parallelack (void);
 extern void cia_diskindex (void);
 
-extern void dumpcia (void);
-extern void rethink_cias (void);
-extern int resetwarning_do (int);
-extern void cia_set_overlay (bool);
-void cia_heartbeat (void);
+extern void dumpcia(void);
+extern void rethink_cias(void);
+extern int resetwarning_do(int);
+extern void cia_set_overlay(bool);
+void cia_heartbeat(void);
 
-extern int parallel_direct_write_data (uae_u8, uae_u8);
-extern int parallel_direct_read_data (uae_u8*);
-extern int parallel_direct_write_status (uae_u8, uae_u8);
-extern int parallel_direct_read_status (uae_u8*);
+extern int parallel_direct_write_data(uae_u8, uae_u8);
+extern int parallel_direct_read_data(uae_u8*);
+extern int parallel_direct_write_status(uae_u8, uae_u8);
+extern int parallel_direct_read_status(uae_u8*);
 
-extern void rtc_hardreset (void);
+extern void rtc_hardreset(void);
 
 extern void keyboard_connected(bool);
 
index 5c3e208ca17fdd9a2c57f3745a420627358ccc6b..965332a0108def75df9e6527310314d3fd42ac39 100644 (file)
@@ -225,6 +225,10 @@ struct dma_rec
        uae_u16 extra;
        uae_s8 intlev;
        uae_u16 cf_reg, cf_dat, cf_addr;
+       int ciareg;
+       int ciamask;
+       bool ciarw;
+       uae_u16 ciavalue;
 };
 
 extern struct dma_rec *last_dma_rec;
@@ -245,18 +249,19 @@ extern struct dma_rec *last_dma_rec;
 #define DMA_EVENT_DDFSTOP 8192
 #define DMA_EVENT_DDFSTOP2 16384
 #define DMA_EVENT_SPECIAL 32768
-#define DMA_EVENT_VB 0x10000
-#define DMA_EVENT_VS 0x20000
-#define DMA_EVENT_LOF 0x40000
-#define DMA_EVENT_LOL 0x80000
-#define DMA_EVENT_HBS 0x100000
-#define DMA_EVENT_HBE 0x200000
-#define DMA_EVENT_HDIWS 0x400000
-#define DMA_EVENT_HDIWE 0x800000
-#define DMA_EVENT_VDIW 0x1000000
-#define DMA_EVENT_HSS 0x2000000
-#define DMA_EVENT_HSE 0x4000000
-
+#define DMA_EVENT_VB           0x00010000
+#define DMA_EVENT_VS           0x00020000
+#define DMA_EVENT_LOF          0x00040000
+#define DMA_EVENT_LOL          0x00080000
+#define DMA_EVENT_HBS          0x00100000
+#define DMA_EVENT_HBE          0x00200000
+#define DMA_EVENT_HDIWS                0x00400000
+#define DMA_EVENT_HDIWE                0x00800000
+#define DMA_EVENT_VDIW         0x01000000
+#define DMA_EVENT_HSS          0x02000000
+#define DMA_EVENT_HSE          0x04000000
+#define DMA_EVENT_CIAA_IRQ     0x08000000
+#define DMA_EVENT_CIAB_IRQ     0x10000000
 
 #define DMARECORD_REFRESH 1
 #define DMARECORD_CPU 2
@@ -279,6 +284,7 @@ extern void record_dma_event(uae_u32 evt, int hpos, int vpos);
 extern void record_dma_clear(int hpos, int vpos);
 extern bool record_dma_check(int hpos, int vpos);
 extern void record_dma_hsync(void);
+extern void record_cia_access(int r, int mask, uae_u16 value, bool rw, int hpos, int vpos);
 extern void debug_mark_refreshed(uaecptr);
 extern void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors);
 
index 363401c5c7053a22fb42a3a2bb420fbd5f04f61b..bd917b358e8324abab0c26632b58add15c4c252e 100644 (file)
@@ -695,6 +695,7 @@ struct uae_prefs {
        int cs_ciatype[2];
        int cs_kbhandshake;
        int cs_hvcsync;
+       int cs_eclockphase;
 
        struct boardromconfig expansionboard[MAX_EXPANSION_BOARDS];
 
index 1a0540fe35d0f22209dcdc2e24a33ed52380b887..f73c3794fb55310f47c603ddb3423fe43787247f 100644 (file)
@@ -402,21 +402,21 @@ bool my_kbd_handler (int keyboard, int scancode, int newstate, bool alwaysreleas
        }
 #endif
 #if 0
-       if (scancode == DIK_F1) {
+       if (scancode == DIK_F8) {
                if (newstate) {
-                       extern void rp_test(void);
-                       rp_test();
+                       extern int blop2;
+                       blop2++;
                }
                return true;
        }
 #endif
-#if 0
-       if (scancode == DIK_F2) {
+#if 1
+       if (scancode == DIK_F9 && specialpressed()) {
                if (newstate) {
-                       extern int paska;
-                       paska--;
+                       extern int blop;
+                       blop++;
                }
-               return;
+               return true;
        }
 #endif