--- uae/src/cia.c 2018/04/24 16:42:07 1.1.1.4 +++ uae/src/cia.c 2018/04/24 16:58:20 1.1.1.10 @@ -24,7 +24,7 @@ #include "keybuf.h" #include "gui.h" -#define DIV10 5 /* Yes, a bad identifier. */ +#define DIV10 (5*CYCLE_UNIT) /* Yes, a bad identifier. */ /* battclock stuff */ #define RTC_D_ADJ 8 @@ -46,7 +46,12 @@ static unsigned int clock_control_f = RT unsigned int ciaaicr,ciaaimask,ciabicr,ciabimask; unsigned int ciaacra,ciaacrb,ciabcra,ciabcrb; + +/* Values of the CIA timers. */ unsigned long ciaata,ciaatb,ciabta,ciabtb; +/* Computed by compute_passed_time. */ +unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; + unsigned long ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm; int ciaatlatch,ciabtlatch; @@ -64,7 +69,7 @@ static int kbstate, kback, ciaasdr_unrea static int prtopen; static FILE *prttmp; -static void setclr(unsigned int *p, unsigned int val) +static void setclr (unsigned int *p, unsigned int val) { if (val & 0x80) { *p |= val & 0x7F; @@ -73,7 +78,7 @@ static void setclr(unsigned int *p, unsi } } -static void RethinkICRA(void) +static void RethinkICRA (void) { if (ciaaimask & ciaaicr) { ciaaicr |= 0x80; @@ -84,7 +89,7 @@ static void RethinkICRA(void) } } -static void RethinkICRB(void) +static void RethinkICRB (void) { #if 0 /* ??? What's this then? */ if (ciabicr & 0x10) { @@ -100,21 +105,53 @@ static void RethinkICRB(void) } } -static int lastdiv10; +/* Figure out how many CIA timer cycles have passed for each timer since the + last call of CIA_calctimers. */ -static void CIA_update(void) +static void compute_passed_time (void) { - unsigned long int ccount = cycles - eventtab[ev_cia].oldcycles + lastdiv10; + unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10); + unsigned long int ciaclocks = ccount / DIV10; + + ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0; + + /* CIA A timers */ + if ((ciaacra & 0x21) == 0x01) { + assert ((ciaata+1) >= ciaclocks); + ciaata_passed = ciaclocks; + } + if ((ciaacrb & 0x61) == 0x01) { + assert ((ciaatb+1) >= ciaclocks); + ciaatb_passed = ciaclocks; + } + + /* CIA B timers */ + if ((ciabcra & 0x21) == 0x01) { + assert ((ciabta+1) >= ciaclocks); + ciabta_passed = ciaclocks; + } + if ((ciabcrb & 0x61) == 0x01) { + assert ((ciabtb+1) >= ciaclocks); + ciabtb_passed = ciaclocks; + } +} + +/* 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 void CIA_update (void) +{ + unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10); unsigned long int ciaclocks = ccount / DIV10; int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0; - lastdiv10 = div10; div10 = ccount % DIV10; /* CIA A timers */ if ((ciaacra & 0x21) == 0x01) { - assert((ciaata+1) >= ciaclocks); + assert ((ciaata+1) >= ciaclocks); if ((ciaata+1) == ciaclocks) { aovfla = 1; if ((ciaacrb & 0x61) == 0x41) { @@ -124,14 +161,14 @@ static void CIA_update(void) ciaata -= ciaclocks; } if ((ciaacrb & 0x61) == 0x01) { - assert((ciaatb+1) >= ciaclocks); + assert ((ciaatb+1) >= ciaclocks); if ((ciaatb+1) == ciaclocks) aovflb = 1; ciaatb -= ciaclocks; } /* CIA B timers */ if ((ciabcra & 0x21) == 0x01) { - assert((ciabta+1) >= ciaclocks); + assert ((ciabta+1) >= ciaclocks); if ((ciabta+1) == ciaclocks) { bovfla = 1; if ((ciabcrb & 0x61) == 0x41) { @@ -167,14 +204,16 @@ static void CIA_update(void) } } -static void CIA_calctimers(void) +/* Call this only after CIA_update has been called in the same cycle. */ + +static void CIA_calctimers (void) { - int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1; + long ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1; - eventtab[ev_cia].oldcycles = cycles; + eventtab[ev_cia].oldcycles = get_cycles (); if ((ciaacra & 0x21) == 0x01) { - ciaatimea = (DIV10-div10) + DIV10*ciaata; + ciaatimea = (DIV10 - div10) + DIV10 * ciaata; } if ((ciaacrb & 0x61) == 0x41) { /* Timer B will not get any pulses if Timer A is off. */ @@ -188,11 +227,11 @@ static void CIA_calctimers(void) } } if ((ciaacrb & 0x61) == 0x01) { - ciaatimeb = (DIV10-div10) + DIV10*ciaatb; + ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb; } if ((ciabcra & 0x21) == 0x01) { - ciabtimea = (DIV10-div10) + DIV10*ciabta; + ciabtimea = (DIV10 - div10) + DIV10 * ciabta; } if ((ciabcrb & 0x61) == 0x41) { /* Timer B will not get any pulses if Timer A is off. */ @@ -206,7 +245,7 @@ static void CIA_calctimers(void) } } if ((ciabcrb & 0x61) == 0x01) { - ciabtimeb = (DIV10-div10) + DIV10*ciabtb; + ciabtimeb = (DIV10 - div10) + DIV10 * ciabtb; } eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1 || ciabtimea != -1 || ciabtimeb != -1); @@ -216,27 +255,24 @@ static void CIA_calctimers(void) if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb; if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea; if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb; - eventtab[ev_cia].evtime = ciatime + cycles; + eventtab[ev_cia].evtime = ciatime + get_cycles (); } events_schedule(); } -void CIA_handler(void) +void CIA_handler (void) { - CIA_update(); - CIA_calctimers(); + CIA_update (); + CIA_calctimers (); } -void diskindex_handler(void) +void cia_diskindex (void) { - eventtab[ev_diskindex].evtime += cycles - eventtab[ev_diskindex].oldcycles; - eventtab[ev_diskindex].oldcycles = cycles; -/* printf(".\n");*/ ciabicr |= 0x10; RethinkICRB(); } -void CIA_hsync_handler(void) +void CIA_hsync_handler (void) { static unsigned int keytime = 0, sleepyhead = 0; @@ -290,7 +326,7 @@ void CIA_hsync_handler(void) } } -void CIA_vsync_handler() +void CIA_vsync_handler () { if (ciaatodon) ciaatod++; @@ -304,120 +340,128 @@ void CIA_vsync_handler() serial_flush_buffer(); } -static uae_u8 ReadCIAA(unsigned int addr) +static uae_u8 ReadCIAA (unsigned int addr) { unsigned int tmp; - switch(addr & 0xf){ - case 0: + compute_passed_time (); + + switch (addr & 0xf) { + case 0: if (currprefs.use_serial && (serstat < 0)) /* Only read status when needed */ serstat=serial_readstatus(); /* and only once per frame */ tmp = (DISK_status() & 0x3C); - if ((JSEM_ISMOUSE (0, currprefs.fake_joystick) && !buttonstate[0]) - || (!JSEM_ISMOUSE (0, currprefs.fake_joystick) && !(joy0button & 1))) + if ((JSEM_ISMOUSE (0, &currprefs) && !buttonstate[0]) + || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1))) tmp |= 0x40; if (!(joy1button & 1)) tmp |= 0x80; return tmp; - case 1: - return ciaaprb; - case 2: + case 1: + /* Returning 0xFF is necessary for Tie Break - otherwise its joystick + code won't work. */ + return prtopen ? ciaaprb : 0xFF; + case 2: return ciaadra; - case 3: + case 3: return ciaadrb; - case 4: - return ciaata & 0xff; - case 5: - return ciaata >> 8; - case 6: - return ciaatb & 0xff; - case 7: - return ciaatb >> 8; - case 8: + case 4: + return (ciaata - ciaata_passed) & 0xff; + case 5: + return (ciaata - ciaata_passed) >> 8; + case 6: + return (ciaatb - ciaatb_passed) & 0xff; + case 7: + return (ciaatb - ciaatb_passed) >> 8; + case 8: if (ciaatlatch) { ciaatlatch = 0; return ciaatol & 0xff; } else return ciaatod & 0xff; - case 9: + case 9: if (ciaatlatch) return (ciaatol >> 8) & 0xff; else return (ciaatod >> 8) & 0xff; - case 10: + case 10: ciaatlatch = 1; ciaatol = ciaatod; /* ??? only if not already latched? */ return (ciaatol >> 16) & 0xff; - case 12: + case 12: if (ciaasdr == 1) ciaasdr_unread = 2; return ciaasdr; - case 13: + case 13: tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp; - case 14: + case 14: return ciaacra; - case 15: + case 15: return ciaacrb; } return 0; } -static uae_u8 ReadCIAB(unsigned int addr) +static uae_u8 ReadCIAB (unsigned int addr) { unsigned int tmp; - switch(addr & 0xf){ - case 0: + compute_passed_time (); + + switch (addr & 0xf) { + case 0: if (currprefs.use_serial && serstat < 0) /* Only read status when needed */ serstat=serial_readstatus(); /* and only once per frame */ - return ciabpra; - case 1: + /* Returning some 1 bits is necessary for Tie Break - otherwise its joystick + code won't work. */ + return ciabpra | (prtopen ? 0 : 3); + case 1: return ciabprb; - case 2: + case 2: return ciabdra; - case 3: + case 3: return ciabdrb; - case 4: - return ciabta & 0xff; - case 5: - return ciabta >> 8; - case 6: - return ciabtb & 0xff; - case 7: - return ciabtb >> 8; - case 8: + case 4: + return (ciabta - ciabta_passed) & 0xff; + case 5: + return (ciabta - ciabta_passed) >> 8; + case 6: + return (ciabtb - ciabtb_passed) & 0xff; + case 7: + return (ciabtb - ciabtb_passed) >> 8; + case 8: if (ciabtlatch) { ciabtlatch = 0; return ciabtol & 0xff; } else return ciabtod & 0xff; - case 9: + case 9: if (ciabtlatch) return (ciabtol >> 8) & 0xff; else return (ciabtod >> 8) & 0xff; - case 10: + case 10: ciabtlatch = 1; ciabtol = ciabtod; return (ciabtol >> 16) & 0xff; - case 12: + case 12: return ciabsdr; - case 13: + case 13: tmp = ciabicr; ciabicr = 0; RethinkICRB(); return tmp; - case 14: + case 14: return ciabcra; - case 15: + case 15: return ciabcrb; } return 0; } -static void WriteCIAA(uae_u16 addr,uae_u8 val) +static void WriteCIAA (uae_u16 addr,uae_u8 val) { int oldled, oldovl; - switch(addr & 0xf){ - case 0: + switch (addr & 0xf) { + case 0: oldovl = ciaapra & 1; oldled = ciaapra & 2; ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2); @@ -429,7 +473,7 @@ static void WriteCIAA(uae_u16 addr,uae_u map_banks(oldovl || ersatzkickfile ? &chipmem_bank : &kickmem_bank, 0, 32); } break; - case 1: + case 1: ciaaprb = val; if (prtopen==1) { #ifndef __DOS__ @@ -448,9 +492,9 @@ static void WriteCIAA(uae_u16 addr,uae_u } } else { #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__) - prttmp = (FILE *)popen ((const char *)prtname, "w"); + prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w"); #else - prttmp = (FILE *)fopen ((const char *)prtname, "wb"); + prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb"); #endif if (prttmp != NULL) { prtopen = 1; @@ -464,17 +508,17 @@ static void WriteCIAA(uae_u16 addr,uae_u } ciaaicr |= 0x10; break; - case 2: + case 2: ciaadra = val; break; - case 3: + case 3: ciaadrb = val; break; - case 4: - CIA_update(); + case 4: + CIA_update (); ciaala = (ciaala & 0xff00) | val; - CIA_calctimers(); + CIA_calctimers (); break; - case 5: - CIA_update(); + case 5: + CIA_update (); ciaala = (ciaala & 0xff) | (val << 8); if ((ciaacra & 1) == 0) ciaata = ciaala; @@ -482,15 +526,15 @@ static void WriteCIAA(uae_u16 addr,uae_u ciaata = ciaala; ciaacra |= 1; } - CIA_calctimers(); + CIA_calctimers (); break; - case 6: - CIA_update(); + case 6: + CIA_update (); ciaalb = (ciaalb & 0xff00) | val; - CIA_calctimers(); + CIA_calctimers (); break; - case 7: - CIA_update(); + case 7: + CIA_update (); ciaalb = (ciaalb & 0xff) | (val << 8); if ((ciaacrb & 1) == 0) ciaatb = ciaalb; @@ -498,84 +542,84 @@ static void WriteCIAA(uae_u16 addr,uae_u ciaatb = ciaalb; ciaacrb |= 1; } - CIA_calctimers(); + CIA_calctimers (); break; - case 8: - if (ciaacrb & 0x80){ + case 8: + if (ciaacrb & 0x80) { ciaaalarm = (ciaaalarm & ~0xff) | val; } else { ciaatod = (ciaatod & ~0xff) | val; ciaatodon = 1; } break; - case 9: - if (ciaacrb & 0x80){ + case 9: + if (ciaacrb & 0x80) { ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8); } else { ciaatod = (ciaatod & ~0xff00) | (val << 8); ciaatodon = 0; } break; - case 10: - if (ciaacrb & 0x80){ + case 10: + if (ciaacrb & 0x80) { ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16); } else { ciaatod = (ciaatod & ~0xff0000) | (val << 16); ciaatodon = 0; } break; - case 12: + case 12: ciaasdr = val; break; - case 13: + case 13: setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */ - case 14: - CIA_update(); + case 14: + CIA_update (); ciaacra = val; - if (ciaacra & 0x10){ + if (ciaacra & 0x10) { ciaacra &= ~0x10; ciaata = ciaala; } if (ciaacra & 0x40) { kback = 1; } - CIA_calctimers(); + CIA_calctimers (); break; - case 15: - CIA_update(); + case 15: + CIA_update (); ciaacrb = val; - if (ciaacrb & 0x10){ + if (ciaacrb & 0x10) { ciaacrb &= ~0x10; ciaatb = ciaalb; } - CIA_calctimers(); + CIA_calctimers (); break; } } -static void WriteCIAB(uae_u16 addr,uae_u8 val) +static void WriteCIAB (uae_u16 addr,uae_u8 val) { int oldval; - switch(addr & 0xf){ - case 0: + switch (addr & 0xf) { + case 0: if (currprefs.use_serial) { - oldval = ciabpra; - ciabpra = serial_writestatus(oldval,val); + oldval = ciabpra; + ciabpra = serial_writestatus(oldval,val); } else - ciabpra = val; + ciabpra = val; break; - case 1: + case 1: ciabprb = val; DISK_select(val); break; - case 2: + case 2: ciabdra = val; break; - case 3: + case 3: ciabdrb = val; break; - case 4: - CIA_update(); + case 4: + CIA_update (); ciabla = (ciabla & 0xff00) | val; - CIA_calctimers(); + CIA_calctimers (); break; - case 5: - CIA_update(); + case 5: + CIA_update (); ciabla = (ciabla & 0xff) | (val << 8); if ((ciabcra & 1) == 0) ciabta = ciabla; @@ -583,15 +627,15 @@ static void WriteCIAB(uae_u16 addr,uae_u ciabta = ciabla; ciabcra |= 1; } - CIA_calctimers(); + CIA_calctimers (); break; - case 6: - CIA_update(); + case 6: + CIA_update (); ciablb = (ciablb & 0xff00) | val; - CIA_calctimers(); + CIA_calctimers (); break; - case 7: - CIA_update(); + case 7: + CIA_update (); ciablb = (ciablb & 0xff) | (val << 8); if ((ciabcrb & 1) == 0) ciabtb = ciablb; @@ -599,60 +643,60 @@ static void WriteCIAB(uae_u16 addr,uae_u ciabtb = ciablb; ciabcrb |= 1; } - CIA_calctimers(); + CIA_calctimers (); break; - case 8: - if (ciabcrb & 0x80){ + case 8: + if (ciabcrb & 0x80) { ciabalarm = (ciabalarm & ~0xff) | val; } else { ciabtod = (ciabtod & ~0xff) | val; ciabtodon = 1; } break; - case 9: - if (ciabcrb & 0x80){ + case 9: + if (ciabcrb & 0x80) { ciabalarm = (ciabalarm & ~0xff00) | (val << 8); } else { ciabtod = (ciabtod & ~0xff00) | (val << 8); ciabtodon = 0; } break; - case 10: - if (ciabcrb & 0x80){ + case 10: + if (ciabcrb & 0x80) { ciabalarm = (ciabalarm & ~0xff0000) | (val << 16); } else { ciabtod = (ciabtod & ~0xff0000) | (val << 16); ciabtodon = 0; } break; - case 12: + case 12: ciabsdr = val; break; - case 13: + case 13: setclr(&ciabimask,val); break; - case 14: - CIA_update(); + case 14: + CIA_update (); ciabcra = val; - if (ciabcra & 0x10){ + if (ciabcra & 0x10) { ciabcra &= ~0x10; ciabta = ciabla; } - CIA_calctimers(); + CIA_calctimers (); break; - case 15: - CIA_update(); + case 15: + CIA_update (); ciabcrb = val; - if (ciabcrb & 0x10){ + if (ciabcrb & 0x10) { ciabcrb &= ~0x10; ciabtb = ciablb; } - CIA_calctimers(); + CIA_calctimers (); break; } } -void CIA_reset(void) +void CIA_reset (void) { kback = 1; kbstate = 0; @@ -664,16 +708,16 @@ void CIA_reset(void) ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */ ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF; div10 = 0; - lastdiv10 = 0; - CIA_calctimers(); + CIA_calctimers (); ciabpra = 0x8C; if (! ersatzkickfile) - map_banks(&kickmem_bank, 0, 32); + map_banks (&kickmem_bank, 0, 32); - if (currprefs.use_serial) serial_dtr_off(); /* Drop DTR at reset */ + if (currprefs.use_serial) + serial_dtr_off(); /* Drop DTR at reset */ } -void dumpcia(void) +void dumpcia (void) { printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n", (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod, @@ -700,16 +744,19 @@ addrbank cia_bank = { uae_u32 REGPARAM2 cia_lget (uaecptr addr) { - return cia_bget(addr+3); + special_mem |= S_READ; + return cia_bget (addr + 3); } uae_u32 REGPARAM2 cia_wget (uaecptr addr) { - return cia_bget(addr+1); + special_mem |= S_READ; + return cia_bget (addr + 1); } uae_u32 REGPARAM2 cia_bget (uaecptr addr) { + special_mem |= S_READ; if ((addr & 0x3001) == 0x2001) return ReadCIAA((addr & 0xF00) >> 8); if ((addr & 0x3001) == 0x1000) @@ -719,20 +766,23 @@ uae_u32 REGPARAM2 cia_bget (uaecptr addr void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value) { - cia_bput(addr+3,value); /* FIXME ? */ + special_mem |= S_WRITE; + cia_bput (addr + 3, value); /* FIXME ? */ } void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value) { - cia_bput(addr+1,value); + special_mem |= S_WRITE; + cia_bput (addr + 1, value); } void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value) { + special_mem |= S_WRITE; if ((addr & 0x3001) == 0x2001) - WriteCIAA((addr & 0xF00) >> 8,value); + WriteCIAA ((addr & 0xF00) >> 8, value); if ((addr & 0x3001) == 0x1000) - WriteCIAB((addr & 0xF00) >> 8,value); + WriteCIAB ((addr & 0xF00) >> 8, value); } /* battclock memory access */ @@ -752,58 +802,64 @@ addrbank clock_bank = { uae_u32 REGPARAM2 clock_lget (uaecptr addr) { - return clock_bget(addr+3); + special_mem |= S_READ; + return clock_bget (addr + 3); } uae_u32 REGPARAM2 clock_wget (uaecptr addr) { - return clock_bget(addr+1); + special_mem |= S_READ; + return clock_bget (addr + 1); } uae_u32 REGPARAM2 clock_bget (uaecptr addr) { - time_t t=time(0); + time_t t = time(0); struct tm *ct; - ct=localtime(&t); - switch (addr & 0x3f) - { - case 0x03: return ct->tm_sec % 10; - case 0x07: return ct->tm_sec / 10; - case 0x0b: return ct->tm_min % 10; - case 0x0f: return ct->tm_min / 10; - case 0x13: return ct->tm_hour % 10; - case 0x17: return ct->tm_hour / 10; - case 0x1b: return ct->tm_mday % 10; - case 0x1f: return ct->tm_mday / 10; - case 0x23: return (ct->tm_mon+1) % 10; - case 0x27: return (ct->tm_mon+1) / 10; - case 0x2b: return ct->tm_year % 10; - case 0x2f: return ct->tm_year / 10; - - case 0x33: return ct->tm_wday; /*Hack by -=SR=- */ - case 0x37: return clock_control_d; - case 0x3b: return clock_control_e; - case 0x3f: return clock_control_f; + + ct = localtime (&t); + special_mem |= S_READ; + + switch (addr & 0x3f) { + case 0x03: return ct->tm_sec % 10; + case 0x07: return ct->tm_sec / 10; + case 0x0b: return ct->tm_min % 10; + case 0x0f: return ct->tm_min / 10; + case 0x13: return ct->tm_hour % 10; + case 0x17: return ct->tm_hour / 10; + case 0x1b: return ct->tm_mday % 10; + case 0x1f: return ct->tm_mday / 10; + case 0x23: return (ct->tm_mon+1) % 10; + case 0x27: return (ct->tm_mon+1) / 10; + case 0x2b: return ct->tm_year % 10; + case 0x2f: return ct->tm_year / 10; + + case 0x33: return ct->tm_wday; /*Hack by -=SR=- */ + case 0x37: return clock_control_d; + case 0x3b: return clock_control_e; + case 0x3f: return clock_control_f; } return 0; } void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value) { + special_mem |= S_WRITE; /* No way */ } void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value) { + special_mem |= S_WRITE; /* No way */ } void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value) { - switch (addr & 0x3f) - { - case 0x37: clock_control_d=value; break; - case 0x3b: clock_control_e=value; break; - case 0x3f: clock_control_f=value; break; + special_mem |= S_WRITE; + switch (addr & 0x3f) { + case 0x37: clock_control_d = value; break; + case 0x3b: clock_control_e = value; break; + case 0x3f: clock_control_f = value; break; } }