--- uae/src/cia.c 2018/04/24 16:58:20 1.1.1.10 +++ uae/src/cia.c 2018/04/24 17:16:34 1.1.1.19 @@ -11,9 +11,8 @@ #include "sysdeps.h" #include -#include "config.h" #include "options.h" -#include "threaddep/penguin.h" +#include "threaddep/thread.h" #include "events.h" #include "memory.h" #include "custom.h" @@ -21,8 +20,10 @@ #include "serial.h" #include "disk.h" #include "xwin.h" +#include "inputdevice.h" #include "keybuf.h" #include "gui.h" +#include "savestate.h" #define DIV10 (5*CYCLE_UNIT) /* Yes, a bad identifier. */ @@ -44,30 +45,31 @@ static unsigned int clock_control_d = RT static unsigned int clock_control_e = 0; static unsigned int clock_control_f = RTC_F_24_12; -unsigned int ciaaicr,ciaaimask,ciabicr,ciabimask; -unsigned int ciaacra,ciaacrb,ciabcra,ciabcrb; +static unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask; +static unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb; /* Values of the CIA timers. */ -unsigned long ciaata,ciaatb,ciabta,ciabtb; +static unsigned long ciaata, ciaatb, ciabta, ciabtb; /* Computed by compute_passed_time. */ -unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; +static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; -unsigned long ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm; -int ciaatlatch,ciabtlatch; +static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm; +static int ciaatlatch, ciabtlatch; -unsigned int ciabpra; +static unsigned int ciabpra; unsigned int gui_ledstate; -static unsigned long ciaala,ciaalb,ciabla,ciablb; +static unsigned long ciaala, ciaalb, ciabla, ciablb; static int ciaatodon, ciabtodon; -static unsigned int ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr; -static unsigned int ciabprb,ciabdra,ciabdrb,ciabsdr; +static unsigned int ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr; +static unsigned int ciabprb, ciabdra, ciabdrb, ciabsdr; static int div10; static int kbstate, kback, ciaasdr_unread = 0; static int prtopen; static FILE *prttmp; +static int warned = 10; static void setclr (unsigned int *p, unsigned int val) { @@ -82,7 +84,7 @@ static void RethinkICRA (void) { if (ciaaimask & ciaaicr) { ciaaicr |= 0x80; - custom_bank.wput(0xDFF09C,0x8008); + INTREQ_0 (0x8000 | 0x0008); } else { ciaaicr &= 0x7F; /* custom_bank.wput(0xDFF09C,0x0008);*/ @@ -91,20 +93,20 @@ static void RethinkICRA (void) static void RethinkICRB (void) { -#if 0 /* ??? What's this then? */ - if (ciabicr & 0x10) { - custom_bank.wput(0xDFF09C,0x9000); - } -#endif if (ciabimask & ciabicr) { ciabicr |= 0x80; - custom_bank.wput(0xDFF09C,0xA000); + INTREQ_0 (0x8000 | 0x2000); } else { ciabicr &= 0x7F; -/* custom_bank.wput(0xDFF09C,0x2000);*/ } } +void rethink_cias (void) +{ + RethinkICRA (); + RethinkICRB (); +} + /* Figure out how many CIA timer cycles have passed for each timer since the last call of CIA_calctimers. */ @@ -155,14 +157,16 @@ static void CIA_update (void) if ((ciaata+1) == ciaclocks) { aovfla = 1; if ((ciaacrb & 0x61) == 0x41) { - if (ciaatb-- == 0) aovflb = 1; + if (ciaatb-- == 0) + aovflb = 1; } } ciaata -= ciaclocks; } if ((ciaacrb & 0x61) == 0x01) { assert ((ciaatb+1) >= ciaclocks); - if ((ciaatb+1) == ciaclocks) aovflb = 1; + if ((ciaatb+1) == ciaclocks) + aovflb = 1; ciaatb -= ciaclocks; } @@ -172,14 +176,16 @@ static void CIA_update (void) if ((ciabta+1) == ciaclocks) { bovfla = 1; if ((ciabcrb & 0x61) == 0x41) { - if (ciabtb-- == 0) bovflb = 1; + if (ciabtb-- == 0) + bovflb = 1; } } ciabta -= ciaclocks; } if ((ciabcrb & 0x61) == 0x01) { assert ((ciabtb+1) >= ciaclocks); - if ((ciabtb+1) == ciaclocks) bovflb = 1; + if ((ciabtb+1) == ciaclocks) + bovflb = 1; ciabtb -= ciaclocks; } if (aovfla) { @@ -208,10 +214,9 @@ static void CIA_update (void) static void CIA_calctimers (void) { - long ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1; + long int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1; eventtab[ev_cia].oldcycles = get_cycles (); - if ((ciaacra & 0x21) == 0x01) { ciaatimea = (DIV10 - div10) + DIV10 * ciaata; } @@ -222,7 +227,11 @@ static void CIA_calctimers (void) * 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. */ +#if 0 ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; +#endif } } } @@ -240,7 +249,9 @@ static void CIA_calctimers (void) * one pulse, it will not underflow. */ if (ciabtb == 0 || (ciabcra & 0x8) == 0) { /* Otherwise, we can determine the time of the underflow. */ +#if 0 ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; +#endif } } } @@ -288,7 +299,7 @@ void CIA_hsync_handler (void) if (doreadser) doreadser = SERDATS(); - if (keys_available() && kback && (++keytime & 15) == 0) { + if (keys_available() && kback && (ciaacra & 0x40) == 0 && (++keytime & 15) == 0) { /* * This hack lets one possible ciaaicr cycle go by without any key * being read, for every cycle in which a key is pulled out of the @@ -301,9 +312,9 @@ void CIA_hsync_handler (void) * or no lossage, and the mouse doesn't get stuck. The tradeoff is * that the total slowness of typing appearing on screen is worse. */ - if (ciaasdr_unread == 2) + if (ciaasdr_unread == 2) { ciaasdr_unread = 0; - else if (ciaasdr_unread == 0) { + } else if (ciaasdr_unread == 0) { switch (kbstate) { case 0: ciaasdr = (uae_s8)~0xFB; /* aaarghh... stupid compiler */ @@ -321,8 +332,9 @@ void CIA_hsync_handler (void) ciaaicr |= 8; RethinkICRA(); sleepyhead = 0; - } else if (!(++sleepyhead & 15)) + } else if (!(++sleepyhead & 15)) { ciaasdr_unread = 0; /* give up on this key event after unread for a long time */ + } } } @@ -345,18 +357,19 @@ static uae_u8 ReadCIAA (unsigned int add unsigned int tmp; 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) && !buttonstate[0]) - || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1))) - tmp |= 0x40; - if (!(joy1button & 1)) - tmp |= 0x80; + tmp |= handle_joystick_buttons (ciaadra); + tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03; + if (ciaadra & 0x40) + tmp = (tmp & ~0x40) | (ciaapra & 0x40); + if (ciaadra & 0x80) + tmp = (tmp & ~0x80) | (ciaapra & 0x80); return tmp; case 1: /* Returning 0xFF is necessary for Tie Break - otherwise its joystick @@ -390,10 +403,12 @@ static uae_u8 ReadCIAA (unsigned int add ciaatol = ciaatod; /* ??? only if not already latched? */ return (ciaatol >> 16) & 0xff; case 12: - if (ciaasdr == 1) ciaasdr_unread = 2; + if (ciaasdr_unread == 1) + ciaasdr_unread = 2; return ciaasdr; case 13: - tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp; + tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); + return tmp; case 14: return ciaacra; case 15: @@ -464,13 +479,22 @@ static void WriteCIAA (uae_u16 addr,uae_ case 0: oldovl = ciaapra & 1; oldled = ciaapra & 2; - ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2); + ciaapra = (ciaapra & ~0x3) | (val & 0x3); + LED(ciaapra & 0x2); gui_ledstate &= ~1; gui_ledstate |= ((~ciaapra & 2) >> 1); + gui_data.powerled = ((~ciaapra & 2) >> 1); if ((ciaapra & 2) != oldled) gui_led (0, !(ciaapra & 2)); if ((ciaapra & 1) != oldovl) { - map_banks(oldovl || ersatzkickfile ? &chipmem_bank : &kickmem_bank, 0, 32); + int i = (allocated_chipmem>>16) > 32 ? allocated_chipmem >> 16 : 32; + + if (oldovl || ersatzkickfile) { + map_banks (&chipmem_bank, 0, i, allocated_chipmem); + } else { + /* Is it OK to do this for more than 2M of chip? */ + map_banks (&kickmem_bank, 0, i, 0x80000); + } } break; case 1: @@ -509,9 +533,11 @@ static void WriteCIAA (uae_u16 addr,uae_ ciaaicr |= 0x10; break; case 2: - ciaadra = val; break; + ciaadra = val; + break; case 3: - ciaadrb = val; break; + ciaadrb = val; + break; case 4: CIA_update (); ciaala = (ciaala & 0xff00) | val; @@ -569,9 +595,11 @@ static void WriteCIAA (uae_u16 addr,uae_ } break; case 12: - ciaasdr = val; break; + ciaasdr = val; + break; case 13: - setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */ + setclr(&ciaaimask,val); + break; case 14: CIA_update (); ciaacra = val; @@ -579,9 +607,8 @@ static void WriteCIAA (uae_u16 addr,uae_ ciaacra &= ~0x10; ciaata = ciaala; } - if (ciaacra & 0x40) { + if (ciaacra & 0x40) kback = 1; - } CIA_calctimers (); break; case 15: @@ -701,30 +728,44 @@ void CIA_reset (void) kback = 1; kbstate = 0; - ciaatlatch = ciabtlatch = 0; - ciaapra = 3; - ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0; - ciaaicr = ciabicr = ciaaimask = ciabimask = 0; - ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */ - ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF; - div10 = 0; + if (!savestate_state) { + ciaatlatch = ciabtlatch = 0; + ciaapra = 3; + ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0; + ciaaicr = ciabicr = ciaaimask = ciabimask = 0; + ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */ + ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF; + ciabpra = 0x8C; + div10 = 0; + } CIA_calctimers (); - ciabpra = 0x8C; - if (! ersatzkickfile) - map_banks (&kickmem_bank, 0, 32); - - if (currprefs.use_serial) - serial_dtr_off(); /* Drop DTR at reset */ + if (! ersatzkickfile) { + int i = allocated_chipmem > 0x200000 ? allocated_chipmem >> 16 : 32; + map_banks (&kickmem_bank, 0, i, 0x80000); + } + + if (currprefs.use_serial && !savestate_state) + serial_dtr_off (); /* Drop DTR at reset */ + + if (savestate_state) { + /* Reset oldovl and oldled */ + uae_u8 v = ReadCIAA (0); + WriteCIAA (0,3); + WriteCIAA (0,0); + WriteCIAA (0,v); + /* select drives */ + DISK_select (ciabprb); + } } void dumpcia (void) { - printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n", + printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n", (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod, - ciaatlatch ? " latched" : "", ciaata, ciaatb); - printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n", + ciaatlatch ? "L" : "", ciaata, ciaala, ciaatb, ciaalb); + printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx (%04lx), TB: %04lx (%04lx)\n", (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod, - ciabtlatch ? " latched" : "", ciabta, ciabtb); + ciabtlatch ? "L" : "", ciabta, ciabla, ciabtb, ciablb); } /* CIA memory access */ @@ -739,50 +780,108 @@ static void cia_bput (uaecptr, uae_u32) addrbank cia_bank = { cia_lget, cia_wget, cia_bget, cia_lput, cia_wput, cia_bput, - default_xlate, default_check + default_xlate, default_check, NULL }; -uae_u32 REGPARAM2 cia_lget (uaecptr addr) +static void cia_wait (void) { + if (!div10) + return; + do_cycles (DIV10 - div10 + CYCLE_UNIT); + CIA_handler (); +} + +uae_u32 REGPARAM2 cia_bget (uaecptr addr) +{ + int r = (addr & 0xf00) >> 8; + uae_u8 v; + special_mem |= S_READ; - return cia_bget (addr + 3); + cia_wait (); + v = 0xff; + switch ((addr >> 12) & 3) + { + case 0: + v = (addr & 1) ? ReadCIAA (r) : ReadCIAB (r); + break; + case 1: + v = (addr & 1) ? 0xff : ReadCIAB (r); + break; + case 2: + v = (addr & 1) ? ReadCIAA (r) : 0xff; + break; +#if 0 + case 3: + if (currprefs.cpu_level == 0 && currprefs.cpu_compatible) + v = (addr & 1) ? regs.irc : regs.irc >> 8; + if (warned > 0) { + write_log ("cia_bget: unknown CIA address %x PC=%x\n", addr, m68k_getpc()); + warned--; + } + break; +#endif + } + return v; } uae_u32 REGPARAM2 cia_wget (uaecptr addr) { + int r = (addr & 0xf00) >> 8; + uae_u16 v; special_mem |= S_READ; - return cia_bget (addr + 1); + cia_wait (); + v = 0xffff; + switch ((addr >> 12) & 3) + { + case 0: + v = (ReadCIAB (r) << 8) | ReadCIAA (r); + break; + case 1: + v = (ReadCIAB (r) << 8) | 0xff; + break; + case 2: + v = (0xff << 8) | ReadCIAA (r); + break; + } + return v; } -uae_u32 REGPARAM2 cia_bget (uaecptr addr) +uae_u32 REGPARAM2 cia_lget (uaecptr addr) { + uae_u32 v; special_mem |= S_READ; - if ((addr & 0x3001) == 0x2001) - return ReadCIAA((addr & 0xF00) >> 8); - if ((addr & 0x3001) == 0x1000) - return ReadCIAB((addr & 0xF00) >> 8); - return 0; + v = cia_wget (addr) << 16; + v |= cia_wget (addr + 2); + return v; } -void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value) +void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value) { + int r = (addr & 0xf00) >> 8; special_mem |= S_WRITE; - cia_bput (addr + 3, value); /* FIXME ? */ + cia_wait (); + if ((addr & 0x2000) == 0) + WriteCIAB (r, value); + if ((addr & 0x1000) == 0) + WriteCIAA (r, value); } void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value) { + int r = (addr & 0xf00) >> 8; special_mem |= S_WRITE; - cia_bput (addr + 1, value); + cia_wait (); + if ((addr & 0x2000) == 0) + WriteCIAB (r, value >> 8); + if ((addr & 0x1000) == 0) + WriteCIAA (r, value & 0xff); } -void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value) +void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value) { special_mem |= S_WRITE; - if ((addr & 0x3001) == 0x2001) - WriteCIAA ((addr & 0xF00) >> 8, value); - if ((addr & 0x3001) == 0x1000) - WriteCIAB ((addr & 0xF00) >> 8, value); + cia_wput (addr, value >> 16); + cia_wput (addr + 2, value & 0xffff); } /* battclock memory access */ @@ -797,7 +896,7 @@ static void clock_bput (uaecptr, uae_u32 addrbank clock_bank = { clock_lget, clock_wget, clock_bget, clock_lput, clock_wput, clock_bput, - default_xlate, default_check + default_xlate, default_check, NULL }; uae_u32 REGPARAM2 clock_lget (uaecptr addr) @@ -863,3 +962,148 @@ void REGPARAM2 clock_bput (uaecptr addr, case 0x3f: clock_control_f = value; break; } } + +/* CIA-A and CIA-B save/restore code */ + +const uae_u8 *restore_cia (int num, const uae_u8 *src) +{ + 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; + +/* 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) { + div10 = CYCLE_UNIT * restore_u8 (); + } + return src; +} + +uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak,*dst, b; + uae_u16 t; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = malloc (16 + 12 + 1); + + compute_passed_time (); + + /* 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);/* 8 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); + + /* 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); + 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? */ + save_u8 (b); + if (num) { + /* Save extra state with CIAB. */ + save_u8 (div10 / CYCLE_UNIT); + } + *len = dst - dstbak; + return dstbak; +}