]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
2700b4
authorToni Wilen <twilen@winuae.net>
Wed, 31 Jul 2013 16:52:15 +0000 (19:52 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 31 Jul 2013 16:52:15 +0000 (19:52 +0300)
29 files changed:
blkdev.cpp
blkdev_cdimage.cpp
cfgfile.cpp
cia.cpp
cia_old.cpp [new file with mode: 0644]
custom.cpp
debug.cpp
expansion.cpp
gencpu.cpp
gfxboard.cpp
include/cia.h
include/cpu_prefetch.h
include/debug.h
include/events.h
include/gfxboard.h
include/memory.h
include/newcpu.h
include/uae.h
memory.cpp
newcpu.cpp
od-win32/avioutput.cpp
od-win32/direct3d.cpp
od-win32/hardfile_win32.cpp
od-win32/picasso96_win.cpp
od-win32/win32.cpp
od-win32/win32.h
od-win32/win32gui.cpp
qemuvga/cirrus_vga.cpp
qemuvga/qemuuaeglue.h

index 79236da1e927f75a2b5e53e6921ae6485b29bb84..2d73639bfab6bf06bfbe73ceb79e06d6d59638c2 100644 (file)
@@ -30,7 +30,8 @@ int log_scsiemu = 0;
 
 struct blkdevstate
 {
-       int scsiemu;
+       bool scsiemu;
+       int type;
        struct device_functions *device_func;
        int isopen;
        int waspaused;
@@ -159,6 +160,7 @@ static void install_driver (int flags)
        for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
                struct blkdevstate *st = &state[i];
                st->scsiemu = false;
+               st->type = -1;
                st->device_func = NULL;
        }
        if (flags > 0) {
@@ -968,6 +970,8 @@ struct device_info *sys_command_info_session (int unitnum, struct device_info *d
        if (st->device_func->info == NULL)
                return 0;
        struct device_info *di2 = st->device_func->info (unitnum, di, quick, -1);
+       if (di2)
+               st->type = di2->type;
        if (di2 && st->delayed)
                di2->media_inserted = 0;
        freesem (unitnum);
@@ -2031,7 +2035,7 @@ static int execscsicmd_direct (int unitnum, int type, struct amigascsi *as)
 int sys_command_scsi_direct_native (int unitnum, int type, struct amigascsi *as)
 {
        struct blkdevstate *st = &state[unitnum];
-       if (st->scsiemu || type >= 0) {
+       if (st->scsiemu || (type >= 0 && st->type != type)) {
                return execscsicmd_direct (unitnum, type, as);
        } else {
                if (!st->device_func->exec_direct)
index d2ff27c4252614bcac4a0b568a5f436b55a21912..c73528f2b2af2ea76c878f84b10f0411e0447f78 100644 (file)
@@ -416,8 +416,11 @@ static void *cdda_play_func (void *v)
                        sector = cdu->cd_last_pos = cdda_pos;
                        t = findtoc (cdu, &sector);
                        if (!t) {
-                               write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
-                               setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
+                               t = findtoc (cdu, &sector + 2 * 75);
+                               if (!t) {
+                                       write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
+                                       setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
+                               }
                        } else {
                                write_log (_T("IMAGE CDDA: playing from %d to %d, track %d ('%s', offset %lld, secoffset %d (%d))\n"),
                                        cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector, t->index1);
@@ -1553,7 +1556,7 @@ static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
                                        if (index0 >= 0) {
                                                t->index1 = tn - index0;
                                        }
-                                       if (lastpregap) {
+                                       if (lastpregap && !secoffset) {
                                                t->index1 = lastpregap;
                                        }
                                        int blockoffset = t->address - t->index1;
index f3bd368beee0e791f1a85a22b493baca193114a4..77cb6f295eda2869e1275f7390b46917d25188b9 100644 (file)
@@ -241,6 +241,158 @@ static int match_string (const TCHAR *table[], const TCHAR *str)
        return -1;
 }
 
+// escape config file separators and control characters
+static TCHAR *cfgfile_escape (const TCHAR *s, const TCHAR *escstr, bool quote)
+{
+       bool doquote = false;
+       int cnt = 0;
+       for (int i = 0; s[i]; i++) {
+               TCHAR c = s[i];
+               if (c == 0)
+                       break;
+               if (c < 32 || c == '\\' || c == '\"' || c == '\'') {
+                       cnt++;
+               }
+               for (int j = 0; escstr && escstr[j]; j++) {
+                       if (c == escstr[j]) {
+                               cnt++;
+                               if (quote) {
+                                       doquote = true;
+                                       cnt++;
+                               }
+                       }
+               }
+       }
+       TCHAR *s2 = xmalloc (TCHAR, _tcslen (s) + cnt * 4 + 1);
+       TCHAR *p = s2;
+       if (doquote)
+               *p++ = '\"';
+       for (int i = 0; s[i]; i++) {
+               TCHAR c = s[i];
+               if (c == 0)
+                       break;
+               if (c == '\\' || c == '\"' || c == '\'') {
+                       *p++ = '\\';
+                       *p++ = c;
+               } else if (c >= 32 && !quote) {
+                       bool escaped = false;
+                       for (int j = 0; escstr && escstr[j]; j++) {
+                               if (c == escstr[j]) {
+                                       *p++ = '\\';
+                                       *p++ = c;
+                                       escaped = true;
+                                       break;
+                               }
+                       }
+                       if (!escaped)
+                               *p++ = c;
+               } else if (c < 32) {
+                       *p++ = '\\';
+                       switch (c)
+                       {
+                               case '\t':
+                               *p++ = 't';
+                               break;
+                               case '\n':
+                               *p++ = 'n';
+                               break;
+                               case '\r':
+                               *p++ = 'r';
+                               break;
+                               default:
+                               *p++ = 'x';
+                               *p++ = (c >> 4) >= 10 ? (c >> 4) + 'a' : (c >> 4) + '0';
+                               *p++ = (c & 15) >= 10 ? (c & 15) + 'a' : (c & 15) + '0';
+                               break;
+                       }
+               } else {
+                       *p++ = c;
+               }
+       }
+       if (doquote)
+               *p++ = '\"';
+       *p = 0;
+       return s2;
+}
+static TCHAR *cfgfile_unescape (const TCHAR *s, const TCHAR **endpos, TCHAR separator)
+{
+       bool quoted = false;
+       TCHAR *s2 = xmalloc (TCHAR, _tcslen (s) + 1);
+       TCHAR *p = s2;
+       if (s[0] == '\"') {
+               s++;
+               quoted = true;
+       }
+       int i;
+       for (i = 0; s[i]; i++) {
+               TCHAR c = s[i];
+               if (quoted && c == '\"') {
+                       i++;
+                       break;
+               }
+               if (c == separator) {
+                       i++;
+                       break;
+               }
+               if (c == '\\') {
+                       char v = 0;
+                       TCHAR c2;
+                       c = s[i + 1];
+                       switch (c)
+                       {
+                               case 'X':
+                               case 'x':
+                               c2 = _totupper (s[i + 2]);
+                               v = ((c2 >= 'A') ? c2 - 'A' : c2 - '0') << 4;
+                               c2 = _totupper (s[i + 3]);
+                               v |= (c2 >= 'A') ? c2 - 'A' : c2 - '0';
+                               *p++ = c2;
+                               i += 2;
+                               break;
+                               case 'r':
+                               *p++ = '\r';
+                               break;
+                               case '\n':
+                               *p++ = '\n';
+                               break;
+                               default:
+                               *p++ = c;
+                               break;
+                       }
+                       i++;
+               } else {
+                       *p++ = c;
+               }
+       }
+       *p = 0;
+       if (endpos)
+               *endpos = &s[i];
+       return s2;
+}
+static TCHAR *cfgfile_unescape (const TCHAR *s, const TCHAR **endpos)
+{
+       return cfgfile_unescape (s, endpos, 0);
+}
+
+static TCHAR *getnextentry (const TCHAR **valuep, const TCHAR separator)
+{
+       TCHAR *s;
+       const TCHAR *value = *valuep;
+       if (value[0] == '\"') {
+               s = cfgfile_unescape (value, valuep);
+               value = *valuep;
+               if (*value != 0 && *value != separator) {
+                       xfree (s);
+                       return NULL;
+               }
+               value++;
+               *valuep = value;
+       } else {
+               s = cfgfile_unescape (value, valuep, separator);
+       }
+       return s;
+}
+
 static TCHAR *cfgfile_subst_path2 (const TCHAR *path, const TCHAR *subst, const TCHAR *file)
 {
        /* @@@ use strcasecmp for some targets.  */
@@ -526,7 +678,7 @@ static void cfgfile_dwrite_path (struct zfile *f, struct multipath *mp, const TC
 static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
 {
        int i;
-       TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH];
+       TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH], tmp3[MAX_DPATH];
        TCHAR *hdcontrollers[] = { _T("uae"),
                _T("ide0"), _T("ide1"), _T("ide2"), _T("ide3"),
                _T("scsi0"), _T("scsi1"), _T("scsi2"), _T("scsi3"), _T("scsi4"), _T("scsi5"), _T("scsi6"),
@@ -535,14 +687,32 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
        for (i = 0; i < p->mountitems; i++) {
                struct uaedev_config_data *uci = &p->mountconfig[i];
                struct uaedev_config_info *ci = &uci->ci;
-               TCHAR *str;
+               TCHAR *str1, *str2, *str1b, *str2b;
                int bp = ci->bootpri;
 
-               str = cfgfile_put_multipath (&p->path_hardfile, ci->rootdir);
+               str2 = _T("");
+               if (ci->rootdir[0] == ':') {
+                       TCHAR *ptr;
+                       // separate harddrive names
+                       str1 = my_strdup (ci->rootdir);
+                       ptr = _tcschr (str1 + 1, ':');
+                       if (ptr) {
+                               *ptr++ = 0;
+                               str2 = ptr;
+                               ptr = _tcschr (str2, ',');
+                               if (ptr)
+                                       *ptr = 0;
+                       }
+               } else {
+                       str1 = cfgfile_put_multipath (&p->path_hardfile, ci->rootdir);
+               }
+               str1b = cfgfile_escape (str1, _T(":,"), true);
+               str2b = cfgfile_escape (str2, _T(":,"), true);
                if (ci->type == UAEDEV_DIR) {
                        _stprintf (tmp, _T("%s,%s:%s:%s,%d"), ci->readonly ? _T("ro") : _T("rw"),
-                               ci->devname ? ci->devname : _T(""), ci->volname, str, bp);
+                               ci->devname ? ci->devname : _T(""), ci->volname, str1, bp);
                        cfgfile_write_str (f, _T("filesystem2"), tmp);
+                       _tcscpy (tmp3, tmp);
 #if 0
                        _stprintf (tmp2, _T("filesystem=%s,%s:%s"), uci->readonly ? _T("ro") : _T("rw"),
                                uci->volname, str);
@@ -551,16 +721,23 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                } else if (ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD || ci->type == UAEDEV_TAPE) {
                        _stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"),
                                ci->readonly ? _T("ro") : _T("rw"),
-                               ci->devname ? ci->devname : _T(""), str,
+                               ci->devname ? ci->devname : _T(""), str1,
+                               ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
+                               bp, ci->filesys ? ci->filesys : _T(""), hdcontrollers[ci->controller]);
+                       _stprintf (tmp3, _T("%s,%s:%s%s%s,%d,%d,%d,%d,%d,%s,%s"),
+                               ci->readonly ? _T("ro") : _T("rw"),
+                               ci->devname ? ci->devname : _T(""), str1b, str2b[0] ? _T(":") : _T(""), str2b,
                                ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
                                bp, ci->filesys ? ci->filesys : _T(""), hdcontrollers[ci->controller]);
                        if (ci->highcyl) {
                                TCHAR *s = tmp + _tcslen (tmp);
-                               _stprintf (s, _T(",%d"), ci->highcyl);
+                               TCHAR *s2 = s;
+                               _stprintf (s2, _T(",%d"), ci->highcyl);
                                if (ci->pcyls && ci->pheads && ci->psecs) {
                                        TCHAR *s = tmp + _tcslen (tmp);
                                        _stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs);
                                }
+                               _tcscat (tmp3, s2);
                        }
                        if (ci->type == UAEDEV_HDF)
                                cfgfile_write_str (f, _T("hardfile2"), tmp);
@@ -577,9 +754,12 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                } else if (ci->type == UAEDEV_TAPE) {
                        cfgfile_write (f, tmp2, _T("tape%d,%s"), ci->device_emu_unit, tmp);
                } else {
-                       cfgfile_write (f, tmp2, _T("%s,%s"), ci->type == UAEDEV_HDF ? _T("hdf") : _T("dir"), tmp);
+                       cfgfile_write (f, tmp2, _T("%s,%s"), ci->type == UAEDEV_HDF ? _T("hdf") : _T("dir"), tmp3);
                }
-               xfree (str);
+               xfree (str1b);
+               xfree (str2b);
+               xfree (str1);
+               
        }
 }
 
@@ -2681,6 +2861,42 @@ bool get_hd_geometry (struct uaedev_config_info *uci)
        return false;
 }
 
+static int cfgfile_parse_partial_newfilesys (struct uae_prefs *p, int nr, int type, const TCHAR *value, int unit, bool uaehfentry)
+{
+       TCHAR *tmpp;
+       TCHAR *name = NULL, *path = NULL;
+
+       // read only harddrive name
+       if (!uaehfentry)
+               return 0;
+       if (type != 1)
+               return 0;
+       tmpp = getnextentry (&value, ',');
+       if (!tmpp)
+               return 0;
+       xfree (tmpp);
+       tmpp = getnextentry (&value, ':');
+       if (!tmpp)
+               return 0;
+       xfree (tmpp);
+       name = getnextentry (&value, ':');
+       if (name && _tcslen (name) > 0) {
+               path = getnextentry (&value, ',');
+               if (path && _tcslen (path) > 0) {
+                       for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
+                               struct uaedev_config_info *uci = &p->mountconfig[i].ci;
+                               if (_tcsicmp (uci->rootdir, name) == 0) {
+                                       _tcscat (uci->rootdir, _T(":"));
+                                       _tcscat (uci->rootdir, path);
+                               }
+                       }
+               }
+       }
+       xfree (path);
+       xfree (name);
+       return 1;
+}
+
 static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHAR *value, int unit, bool uaehfentry)
 {
        struct uaedev_config_info uci;
@@ -2818,7 +3034,8 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                                *tmpp++ = 0;
                                if (_tcsicmp (value, _T("hdf")) == 0) {
                                        type = 1;
-                                       return 1; /* ignore for now */
+                                       cfgfile_parse_partial_newfilesys (p, -1, type, tmpp, unit, true);
+                                       return 1;
                                } else if (_tcsnicmp (value, _T("cd"), 2) == 0 && (value[2] == 0 || value[3] == 0)) {
                                        unit = 0;
                                        if (value[2] > 0)
@@ -2838,7 +3055,7 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                                        return 1;  /* ignore for now */
                                }
                                if (type >= 0)
-                                       return cfgfile_parse_newfilesys (p, -1, type, tmpp, unit, true);
+                                       cfgfile_parse_newfilesys (p, -1, type, tmpp, unit, true);
                                return 1;
                        }
                        return 1;
diff --git a/cia.cpp b/cia.cpp
index 02961f203f58beb8a0dd96c8b7303a2b64729378..30a1a35ff8d9f98444045dcc884cee66a99a54d0 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -106,53 +106,61 @@ static void setclr (unsigned int *p, unsigned int val)
        }
 }
 
-static void ICRA(uae_u32 data)
+static void ICR (uae_u32 data)
 {
-       if (ciaaimask & ciaaicr) {
-               ciaaicr |= 0x80;
-               INTREQ_0 (0x8000 | data);
-       }
-       ciaaicr_reg |= ciaaicr;
+       INTREQ_0 (0x8000 | data);
 }
-static void ICRB(uae_u32 data)
+static void ICR(uae_u32 data)
 {
-       if (ciabimask & ciabicr) {
-               ciabicr |= 0x80;
-               INTREQ_0 (0x8000 | data);
-       }
-       ciabicr_reg |= ciabicr;
+       ICR (data);
+       ciaaicr |= 0x40;
+}
+static void ICRB (uae_u32 data)
+{
+       ICR (data);
+       ciabicr |= 0x40;
 }
 
 static void RethinkICRA (void)
 {
-       if (ciaaicr) {
+       if (ciaaicr & ciaaimask) {
 #if CIAA_DEBUG_IRQ
                write_log (_T("CIAA IRQ %02X\n"), ciaaicr);
 #endif
-               if (currprefs.cpu_cycle_exact)
-                       event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x0008, ICRA);
-               else
-                       ICRA (0x0008);
+               if (!(ciaaicr & 0x80)) {
+                       ciaaicr |= 0x80;
+                       ciaaicr_reg |= 0x80;
+                       if (currprefs.cpu_cycle_exact)
+                               event2_newevent_xx (-1, DIV10 + 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x0008, ICRA);
+                       else
+                               ICRA (0x0008);
+               }
        }
 }
 
 static void RethinkICRB (void)
 {
-       if (ciabicr) {
+       if (ciabicr & ciabimask) {
 #if CIAB_DEBUG_IRQ
                write_log (_T("CIAB IRQ %02X\n"), ciabicr);
 #endif
-               if (currprefs.cpu_cycle_exact)
-                       event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x2000, ICRB);
-               else
-                       ICRB (0x2000);
+               if (!(ciabicr & 0x80)) {
+                       ciabicr |= 0x80;
+                       ciabicr_reg |= 0x80;
+                       if (currprefs.cpu_cycle_exact)
+                               event2_newevent_xx (-1, DIV10 + 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x2000, ICRB);
+                       else
+                               ICRB (0x2000);
+               }
        }
 }
 
 void rethink_cias (void)
 {
-       RethinkICRA ();
-       RethinkICRB ();
+       if (ciaaicr & 0x40)
+               ICRA (0x0008);
+       if (ciabicr & 0x40)
+               ICRB (0x2000);
 }
 
 /* Figure out how many CIA timer cycles have passed for each timer since the
@@ -348,6 +356,8 @@ static int CIA_update_check (void)
        if (bsp) {
                ciabicr |= 8; icr |= 2;
        }
+       ciaaicr_reg |= ciaaicr;
+       ciabicr_reg |= ciabicr;
        return icr;
 }
 static void CIA_update (void)
@@ -436,11 +446,13 @@ void CIA_handler (void)
 
 void cia_diskindex (void)
 {
+       ciabicr_reg |= 0x10;
        ciabicr |= 0x10;
        RethinkICRB ();
 }
 void cia_parallelack (void)
 {
+       ciaaicr_reg |= 0x10;
        ciaaicr |= 0x10;
        RethinkICRA ();
 }
@@ -451,9 +463,6 @@ static int checkalarm (unsigned long tod, unsigned long alarm, bool inc)
                return 1;
        if (!inc)
                return 0;
-       /* Amix workaround */
-       if (currprefs.mmu_model)
-               return 0;
        /* emulate buggy TODMED counter.
        * it counts: .. 29 2A 2B 2C 2D 2E 2F 20 30 31 32 ..
        * (2F->20->30 only takes couple of cycles but it will trigger alarm..
@@ -461,7 +470,7 @@ static int checkalarm (unsigned long tod, unsigned long alarm, bool inc)
        if (tod & 0x000fff)
                return 0;
        if (((tod - 1) & 0xfff000) == alarm)
-               return 1;
+               return -1;
        return 0;
 }
 
@@ -476,11 +485,13 @@ STATIC_INLINE bool ciab_checkalarm (bool inc, bool irq)
                if (ciabtod == 0 && ciabalarm == 0)
                        return false;
        }
-       if (checkalarm (ciabtod, ciabalarm, inc)) {
+       int v = checkalarm (ciabtod, ciabalarm, inc);
+       if (v > 0) {
 #if CIAB_DEBUG_IRQ
                write_log (_T("CIAB tod %08x %08x\n"), ciabtod, ciabalarm);
 #endif
                if (irq) {
+                       ciabicr_reg |= 4;
                        ciabicr |= 4;
                        RethinkICRB ();
                }
@@ -491,10 +502,12 @@ STATIC_INLINE bool ciab_checkalarm (bool inc, bool irq)
 
 STATIC_INLINE void ciaa_checkalarm (bool inc)
 {
-       if (checkalarm (ciaatod, ciaaalarm, inc)) {
+       int v = checkalarm (ciaatod, ciaaalarm, inc);
+       if (v > 0) {
 #if CIAA_DEBUG_IRQ
                write_log (_T("CIAA tod %08x %08x\n"), ciaatod, ciaaalarm);
 #endif
+               ciaaicr_reg |= 4;
                ciaaicr |= 4;
                RethinkICRA ();
        }
@@ -592,6 +605,7 @@ static void sendrw (void)
        ciaasdr = kbcode;
        kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
        ciaaicr |= 8;
+       ciaaicr_reg |= 8;
        RethinkICRA ();
        write_log (_T("KB: sent reset warning code (phase=%d)\n"), resetwarning_phase);
 }
@@ -662,6 +676,7 @@ static void keyreq (void)
        ciaasdr = kbcode;
        kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
        ciaaicr |= 8;
+       ciaaicr_reg |= 8;
        RethinkICRA ();
 }
 
@@ -672,6 +687,9 @@ static void keyreq (void)
 
 static int ciab_tod_hoffset;
 static int ciab_tod_event_state;
+// TOD increase has extra 14-16 E-clock delay
+// Possibly TICK input pin has built-in debounce circuit
+#define TOD_INC_DELAY (14 * (ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) / 2)
 
 static void CIAB_tod_inc (uae_u32 v)
 {
@@ -702,7 +720,7 @@ void CIAB_tod_handler (int hoffset)
 {
        uae_u32 v;
 
-       ciab_tod_hoffset = hoffset;
+       ciab_tod_hoffset = hoffset + TOD_INC_DELAY;
        if (!ciabtodon)
                return;
        ciab_tod_event_state = 1; // TOD inc needed
@@ -714,7 +732,7 @@ void CIAB_tod_handler (int hoffset)
        if (irq) {
                // causes interrupt on this line, add event
                ciab_tod_event_state = 2; // event active
-               event2_newevent_xx (-1, hoffset, 0, CIAB_tod_inc);
+               event2_newevent_xx (-1, ciab_tod_hoffset, 0, CIAB_tod_inc);
        }
 }
 
@@ -822,17 +840,22 @@ void CIA_vsync_prehandler (void)
        }
 }
 
-void CIAA_tod_handler (void)
+static void CIAA_tod_handler (uae_u32 v)
+{
+       ciaatod++;
+       ciaatod &= 0xFFFFFF;
+       ciaa_checkalarm (true);
+}
+
+void CIAA_tod_inc (int cycles)
 {
 #ifdef TOD_HACK
        if (currprefs.tod_hack && tod_hack_enabled == 1)
                return;
 #endif
-       if (ciaatodon) {
-               ciaatod++;
-               ciaatod &= 0xFFFFFF;
-               ciaa_checkalarm (true);
-       }
+       if (!ciaatodon)
+               return;
+       event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
 }
 
 static void bfe001_change (void)
@@ -982,10 +1005,10 @@ static uae_u8 ReadCIAA (unsigned int addr)
 #endif
                return ciaasdr;
        case 13:
-               tmp = ciaaicr_reg;
-               ciaaicr &= ~ciaaicr_reg;
+               tmp = ciaaicr_reg & ~0x40;
+               ciaaicr = 0;
                ciaaicr_reg = 0;
-               RethinkICRA ();
+               //RethinkICRA ();
                return tmp;
        case 14:
                return ciaacra;
@@ -1095,10 +1118,10 @@ static uae_u8 ReadCIAB (unsigned int addr)
        case 12:
                return ciabsdr;
        case 13:
-               tmp = ciabicr_reg;
-               ciabicr &= ~ciabicr_reg;
+               tmp = ciabicr_reg & ~0x40;
+               ciabicr = 0;
                ciabicr_reg = 0;
-               RethinkICRB ();
+               //RethinkICRB ();
                return tmp;
        case 14:
                //write_log (_T("CIABCRA READ %d %x\n"), ciabcra, M68K_GETPC);
@@ -1289,7 +1312,7 @@ static void WriteCIAB (uae_u16 addr, uae_u8 val)
        int reg = addr & 15;
 
 #if CIAB_DEBUG_W > 0
-       if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_W > 1)
+       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);
 #endif
 #ifdef ACTION_REPLAY
@@ -1469,7 +1492,7 @@ void CIA_reset (void)
                ciaatlatch = ciabtlatch = 0;
                ciaapra = 0; ciaadra = 0;
                ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
-               ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
+               ciaaicr = ciaaicr_reg = ciabicr = ciabicr_reg = ciaaimask = ciabimask = 0;
                ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
                ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
                ciaaalarm = ciabalarm = 0;
diff --git a/cia_old.cpp b/cia_old.cpp
new file mode 100644 (file)
index 0000000..c1361af
--- /dev/null
@@ -0,0 +1,2245 @@
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* CIA chip support
+*
+* Copyright 1995 Bernd Schmidt, Alessandro Bissacco
+* Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
+*/
+
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include <assert.h>
+
+#include "options.h"
+#include "events.h"
+#include "memory.h"
+#include "custom.h"
+#include "newcpu.h"
+#include "cia.h"
+#include "serial.h"
+#include "disk.h"
+#include "xwin.h"
+#include "keybuf.h"
+#include "gui.h"
+#include "savestate.h"
+#include "inputdevice.h"
+#include "zfile.h"
+#include "ar.h"
+#include "parallel.h"
+#include "akiko.h"
+#include "cdtv.h"
+#include "debug.h"
+#include "arcadia.h"
+#include "audio.h"
+#include "keyboard.h"
+#include "uae.h"
+#include "amax.h"
+#include "sampler.h"
+#include "dongle.h"
+#include "inputrecord.h"
+#include "autoconf.h"
+
+#define CIAA_DEBUG_R 0
+#define CIAA_DEBUG_W 0
+#define CIAA_DEBUG_IRQ 0
+
+#define CIAB_DEBUG_R 0
+#define CIAB_DEBUG_W 0
+#define CIAB_DEBUG_IRQ 0
+
+#define DONGLE_DEBUG 0
+#define KB_DEBUG 0
+#define CLOCK_DEBUG 0
+
+#define TOD_HACK
+
+/* e-clock is 10 CPU cycles, 4 cycles high, 6 low
+* data transfer happens during 4 high cycles
+*/
+#define ECLOCK_DATA_CYCLE 4
+#define ECLOCK_WAIT_CYCLE 6
+
+#define DIV10 ((ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) * CYCLE_UNIT / 2) /* Yes, a bad identifier. */
+#define CIASTARTCYCLESHI 3
+#define CIASTARTCYCLESCRA 2
+
+static unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask;
+static unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb;
+static unsigned int ciaastarta, ciaastartb, ciabstarta, ciabstartb;
+static unsigned int ciaaicr_reg, ciabicr_reg;
+
+/* Values of the CIA timers.  */
+static unsigned long ciaata, ciaatb, ciabta, ciabtb;
+/* Computed by compute_passed_time.  */
+static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
+
+static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
+static int ciaatlatch, ciabtlatch;
+static bool oldled, oldovl, oldcd32mute;
+static bool led;
+static int led_old_brightness;
+static unsigned long led_cycles_on, led_cycles_off, led_cycle;
+
+unsigned int ciabpra;
+
+static unsigned long ciaala, ciaalb, ciabla, ciablb;
+static int ciaatodon, ciabtodon;
+static unsigned int ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr, ciaasdr_cnt;
+static unsigned int ciabprb, ciabdra, ciabdrb, ciabsdr, ciabsdr_cnt;
+static int div10;
+static int kbstate, kblostsynccnt;
+static uae_u8 kbcode;
+
+static uae_u8 serbits;
+static int warned = 10;
+static int rtc_delayed_write;
+
+
+static void setclr (unsigned int *p, unsigned int val)
+{
+       if (val & 0x80) {
+               *p |= val & 0x7F;
+       } else {
+               *p &= ~val;
+       }
+}
+
+static void ICRA(uae_u32 data)
+{
+       if (ciaaimask & ciaaicr) {
+               ciaaicr |= 0x80;
+               INTREQ_0 (0x8000 | data);
+       }
+       ciaaicr_reg |= ciaaicr;
+}
+static void ICRB(uae_u32 data)
+{
+       if (ciabimask & ciabicr) {
+               ciabicr |= 0x80;
+               INTREQ_0 (0x8000 | data);
+       }
+       ciabicr_reg |= ciabicr;
+}
+
+static void RethinkICRA (void)
+{
+       if (ciaaicr) {
+#if CIAA_DEBUG_IRQ
+               write_log (_T("CIAA IRQ %02X\n"), ciaaicr);
+#endif
+               if (currprefs.cpu_cycle_exact)
+                       event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x0008, ICRA);
+               else
+                       ICRA (0x0008);
+       }
+}
+
+static void RethinkICRB (void)
+{
+       if (ciabicr) {
+#if CIAB_DEBUG_IRQ
+               write_log (_T("CIAB IRQ %02X\n"), ciabicr);
+#endif
+               if (currprefs.cpu_cycle_exact)
+                       event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x2000, ICRB);
+               else
+                       ICRB (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.  */
+
+static void compute_passed_time (void)
+{
+       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) {
+               unsigned long int cc = ciaclocks;
+               if (cc > ciaastarta)
+                       cc -= ciaastarta;
+               else
+                       cc = 0;
+               assert ((ciaata + 1) >= cc);
+               ciaata_passed = cc;
+       }
+       if ((ciaacrb & 0x61) == 0x01) {
+               unsigned long int cc = ciaclocks;
+               if (cc > ciaastartb)
+                       cc -= ciaastartb;
+               else
+                       cc = 0;
+               assert ((ciaatb + 1) >= cc);
+               ciaatb_passed = cc;
+       }
+
+       /* CIA B timers */
+       if ((ciabcra & 0x21) == 0x01) {
+               unsigned long int cc = ciaclocks;
+               if (cc > ciabstarta)
+                       cc -= ciabstarta;
+               else
+                       cc = 0;
+               assert ((ciabta + 1) >= cc);
+               ciabta_passed = cc;
+       }
+       if ((ciabcrb & 0x61) == 0x01) {
+               unsigned long int cc = ciaclocks;
+               if (cc > ciabstartb)
+                       cc -= ciabstartb;
+               else
+                       cc = 0;
+               assert ((ciabtb + 1) >= cc);
+               ciabtb_passed = cc;
+       }
+}
+
+/* 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)
+{
+       unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
+       unsigned long int ciaclocks = ccount / DIV10;
+
+       int aovfla = 0, aovflb = 0, asp = 0, bovfla = 0, bovflb = 0, bsp = 0;
+       int icr = 0;
+
+       div10 = ccount % DIV10;
+
+       /* CIA A timers */
+       if ((ciaacra & 0x21) == 0x01) {
+               bool check = true;
+               unsigned long int cc = ciaclocks;
+               if (ciaastarta > 0) {
+                       if (cc > ciaastarta) {
+                               cc -= ciaastarta;
+                               ciaastarta = 0;
+                       } else {
+                               ciaastarta -= cc;
+                               check = false;
+                       }
+               }
+               if (check) {
+                       assert ((ciaata + 1) >= cc);
+                       if ((ciaata + 1) == cc) {
+                               if ((ciaacra & 0x48) == 0x40 && ciaasdr_cnt > 0 && --ciaasdr_cnt == 0)
+                                       asp = 1;
+                               aovfla = 1;
+                               if ((ciaacrb & 0x61) == 0x41 || (ciaacrb & 0x61) == 0x61) {
+                                       if (ciaatb-- == 0)
+                                               aovflb = 1;
+                               }
+                       }
+                       ciaata -= cc;
+               }
+       }
+       if ((ciaacrb & 0x61) == 0x01) {
+               bool check = true;
+               unsigned long int 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;
+               }
+       }
+
+       /* CIA B timers */
+       if ((ciabcra & 0x21) == 0x01) {
+               bool check = true;
+               unsigned long int cc = ciaclocks;
+               if (ciabstarta > 0) {
+                       if (cc > ciabstarta) {
+                               cc -= ciabstarta;
+                               ciabstarta = 0;
+                       } else {
+                               ciabstarta -= cc;
+                               check = false;
+                       }
+               }
+               if (check) {
+                       assert ((ciabta + 1) >= cc);
+                       if ((ciabta + 1) == cc) {
+                               if ((ciabcra & 0x48) == 0x40 && ciabsdr_cnt > 0 && --ciabsdr_cnt == 0)
+                                       bsp = 1;
+                               bovfla = 1;
+                               if ((ciabcrb & 0x61) == 0x41 || (ciabcrb & 0x61) == 0x61) {
+                                       if (ciabtb-- == 0)
+                                               bovflb = 1;
+                               }
+                       }
+                       ciabta -= cc;
+               }
+       }
+       if ((ciabcrb & 0x61) == 0x01) {
+               bool check = true;
+               unsigned long int 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 (aovflb) {
+               ciaaicr |= 2; icr = 1;
+               ciaatb = ciaalb;
+               if (ciaacrb & 0x8) {
+                       ciaacrb &= ~1;
+               }
+       }
+       if (asp) {
+               ciaaicr |= 8; icr = 1;
+       }
+       if (bovfla) {
+               ciabicr |= 1; icr |= 2;
+               ciabta = ciabla;
+               if (ciabcra & 0x8) {
+                       ciabcra &= ~1;
+               }
+       }
+       if (bovflb) {
+               ciabicr |= 2; icr |= 2;
+               ciabtb = ciablb;
+               if (ciabcrb & 0x8) {
+                       ciabcrb &= ~1;
+               }
+       }
+       if (bsp) {
+               ciabicr |= 8; icr |= 2;
+       }
+       return icr;
+}
+static void CIA_update (void)
+{
+       int icr = CIA_update_check ();
+       if (icr & 1)
+               RethinkICRA ();
+       if (icr & 2)
+               RethinkICRB ();
+}
+
+
+/* Call this only after CIA_update has been called in the same cycle.  */
+
+static void CIA_calctimers (void)
+{
+       long int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
+       int div10diff = DIV10 - div10;
+
+       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; */
+                       }
+               }
+       }
+#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; */
+                       }
+               }
+       }
+#endif
+       if ((ciabcrb & 0x61) == 0x01) {
+               ciabtimeb = div10diff + DIV10 * (ciabtb + ciabstartb);
+       }
+
+       eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
+               || ciabtimea != -1 || ciabtimeb != -1);
+       if (eventtab[ev_cia].active) {
+               unsigned long int ciatime = ~0L;
+               if (ciaatimea != -1)
+                       ciatime = ciaatimea;
+               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 + get_cycles ();
+       }
+       events_schedule();
+}
+
+void CIA_handler (void)
+{
+       CIA_update ();
+       CIA_calctimers ();
+}
+
+void cia_diskindex (void)
+{
+       ciabicr |= 0x10;
+       RethinkICRB ();
+}
+void cia_parallelack (void)
+{
+       ciaaicr |= 0x10;
+       RethinkICRA ();
+}
+
+static int checkalarm (unsigned long tod, unsigned long alarm, bool inc)
+{
+       if (tod == alarm)
+               return 1;
+       if (!inc)
+               return 0;
+       /* Amix workaround */
+       if (currprefs.mmu_model)
+               return 0;
+       /* emulate buggy TODMED counter.
+       * it counts: .. 29 2A 2B 2C 2D 2E 2F 20 30 31 32 ..
+       * (2F->20->30 only takes couple of cycles but it will trigger alarm..
+       */
+       if (tod & 0x000fff)
+               return 0;
+       if (((tod - 1) & 0xfff000) == alarm)
+               return 1;
+       return 0;
+}
+
+STATIC_INLINE bool ciab_checkalarm (bool inc, bool irq)
+{
+       // 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 ((munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000) {
+               if (ciabtod == 0 && ciabalarm == 0)
+                       return false;
+       }
+       if (checkalarm (ciabtod, ciabalarm, inc)) {
+#if CIAB_DEBUG_IRQ
+               write_log (_T("CIAB tod %08x %08x\n"), ciabtod, ciabalarm);
+#endif
+               if (irq) {
+                       ciabicr |= 4;
+                       RethinkICRB ();
+               }
+               return true;
+       }
+       return false;
+}
+
+STATIC_INLINE void ciaa_checkalarm (bool inc)
+{
+       if (checkalarm (ciaatod, ciaaalarm, inc)) {
+#if CIAA_DEBUG_IRQ
+               write_log (_T("CIAA tod %08x %08x\n"), ciaatod, ciaaalarm);
+#endif
+               ciaaicr |= 4;
+               RethinkICRA ();
+       }
+}
+
+#ifdef TOD_HACK
+static uae_u64 tod_hack_tv, tod_hack_tod, tod_hack_tod_last;
+static int tod_hack_enabled;
+#define TOD_HACK_TIME 312 * 50 * 10
+static void tod_hack_reset (void)
+{
+       struct timeval tv;
+       gettimeofday (&tv, NULL);
+       tod_hack_tv = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
+       tod_hack_tod = ciaatod;
+       tod_hack_tod_last = tod_hack_tod;
+}
+#endif
+
+static int heartbeat_cnt;
+void cia_heartbeat (void)
+{
+       heartbeat_cnt = 10;
+}
+
+static void do_tod_hack (int dotod)
+{
+       struct timeval tv;
+       static int oldrate;
+       uae_u64 t;
+       int rate;
+       int docount = 0;
+
+       if (tod_hack_enabled == 0)
+               return;
+       if (!heartbeat_cnt) {
+               if (tod_hack_enabled > 0)
+                       tod_hack_enabled = -1;
+               return;
+       }
+       if (tod_hack_enabled < 0) {
+               tod_hack_enabled = TOD_HACK_TIME;
+               return;
+       }
+       if (tod_hack_enabled > 1) {
+               tod_hack_enabled--;
+               if (tod_hack_enabled == 1) {
+                       //write_log (_T("TOD HACK enabled\n"));
+                       tod_hack_reset ();
+               }
+               return;
+       }
+
+       if (currprefs.cs_ciaatod == 0)
+               rate = (int)(vblank_hz + 0.5);
+       else if (currprefs.cs_ciaatod == 1)
+               rate = 50;
+       else
+               rate = 60;
+       if (rate <= 0)
+               return;
+       if (rate != oldrate || ciaatod != tod_hack_tod_last) {
+               //if (ciaatod != 0)
+               //      write_log (_T("TOD HACK reset %d,%d %d,%d\n"), rate, oldrate, ciaatod, tod_hack_tod_last);
+               tod_hack_reset ();
+               oldrate = rate;
+               docount = 1;
+       }
+       if (!dotod && currprefs.cs_ciaatod == 0)
+               return;
+       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;
+               docount = 1;
+       }
+       if (docount) {
+               ciaatod++;
+               ciaatod &= 0x00ffffff;
+               tod_hack_tod_last = ciaatod;
+               ciaa_checkalarm (false);
+       }
+}
+
+static int resetwarning_phase, resetwarning_timer;
+
+static void setcode (uae_u8 keycode)
+{
+       kbcode = ~((keycode << 1) | (keycode >> 7));
+}
+
+static void sendrw (void)
+{
+       setcode (AK_RESETWARNING);
+       ciaasdr = 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);
+}
+
+int resetwarning_do (int canreset)
+{
+       if (resetwarning_phase) {
+               /* just force reset if second reset happens during resetwarning */
+               if (canreset) {
+                       resetwarning_phase = 0;
+                       resetwarning_timer = 0;
+               }
+               return 0;
+       }
+       resetwarning_phase = 1;
+       resetwarning_timer = maxvpos_nom * 5;
+       write_log (_T("KB: reset warning triggered\n"));
+       sendrw ();
+       return 1;
+}
+
+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);
+                       resetwarning_phase = -1;
+                       kblostsynccnt = 0;
+                       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"));
+                       resetwarning_phase = 2;
+                       resetwarning_timer = maxvpos_nom * 5;
+                       sendrw ();
+               }
+       } else if (resetwarning_phase == 2) {
+               if (ciaacra & 0x40) { /* second AK_RESETWARNING handshake active */
+                       resetwarning_phase = 3;
+                       write_log (_T("KB: reset warning SP = output\n"));
+                       /* System won't reset until handshake signal becomes inactive or 10s has passed */
+                       resetwarning_timer = 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"));
+                       resetwarning_phase = -1;
+                       kblostsynccnt = 0;
+                       send_internalevent (INTERNALEVENT_KBRESET);
+                       uae_reset (0, 1);
+               }
+       }
+}
+
+void CIA_hsync_prehandler (void)
+{
+}
+
+static void keyreq (void)
+{
+#if KB_DEBUG
+       write_log (_T("code=%x\n"), kbcode);
+#endif
+       ciaasdr = kbcode;
+       kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
+       ciaaicr |= 8;
+       RethinkICRA ();
+}
+
+/* All this complexity to lazy evaluate TOD increase.
+ * Only increase it cycle-exactly if it is visible to running program:
+ * causes interrupt or program is reading or writing TOD registers
+ */
+
+static int ciab_tod_hoffset;
+static int ciab_tod_event_state;
+// TOD increase has extra 14-16 E-clock delay
+// Possibly TICK input pin has built-in debounce circuit
+#define TOD_INC_DELAY (14 * (ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) / 2)
+
+static void CIAB_tod_inc (uae_u32 v)
+{
+       ciab_tod_event_state = 3; // done
+       ciabtod++;
+       ciabtod &= 0xFFFFFF;
+       ciab_checkalarm (true, true);
+}
+
+// Someone reads or writes TOD registers, sync TOD increase
+static void CIAB_tod_check (void)
+{
+       if (ciab_tod_event_state != 1 || !ciabtodon)
+               return;
+       int hpos = current_hpos ();
+       hpos -= ciab_tod_hoffset;
+       if (hpos >= 0 || currprefs.m68k_speed < 0) {
+               // Program should see the changed TOD
+               CIAB_tod_inc (0);
+               return;
+       }
+       // Not yet, add event to guarantee exact TOD inc position
+       ciab_tod_event_state = 2; // event active
+       event2_newevent_xx (-1, -hpos, 0, CIAB_tod_inc);
+}
+
+void CIAB_tod_handler (int hoffset)
+{
+       uae_u32 v;
+
+       ciab_tod_hoffset = hoffset + TOD_INC_DELAY;
+       if (!ciabtodon)
+               return;
+       ciab_tod_event_state = 1; // TOD inc needed
+       v = ciabtod;
+       ciabtod++;
+       ciabtod &= 0xFFFFFF;
+       bool irq = ciab_checkalarm (false, false);
+       ciabtod = v;
+       if (irq) {
+               // causes interrupt on this line, add event
+               ciab_tod_event_state = 2; // event active
+               event2_newevent_xx (-1, ciab_tod_hoffset, 0, CIAB_tod_inc);
+       }
+}
+
+void CIA_hsync_posthandler (bool dotod)
+{
+       // Previous line was supposed to increase TOD but
+       // no one cared. Do it now at the start of next line.
+       if (ciab_tod_event_state == 1)
+               CIAB_tod_inc (0);
+       ciab_tod_event_state = 0;
+
+       if (currprefs.tod_hack && ciaatodon)
+               do_tod_hack (dotod);
+
+       if (resetwarning_phase) {
+               resetwarning_check ();
+               while (keys_available ())
+                       get_next_key ();
+       } else if ((keys_available () || kbstate < 3) && !kblostsynccnt && (hsync_counter & 15) == 0) {
+               switch (kbstate)
+               {
+                       case 0:
+                               kbcode = 0; /* powerup resync */
+                               kbstate++;
+                               break;
+                       case 1:
+                               setcode (AK_INIT_POWERUP);
+                               kbstate++;
+                               break;
+                       case 2:
+                               setcode (AK_TERM_POWERUP);
+                               kbstate++;
+                               break;
+                       case 3:
+                               kbcode = ~get_next_key ();
+                               break;
+               }
+               keyreq ();
+       }
+}
+
+static void calc_led (int old_led)
+{
+       unsigned long c = get_cycles ();
+       unsigned long t = (c - led_cycle) / CYCLE_UNIT;
+       if (old_led)
+               led_cycles_on += t;
+       else
+               led_cycles_off += t;
+       led_cycle = c;
+}
+
+static void led_vsync (void)
+{
+       int v;
+
+       calc_led (led);
+       if (led_cycles_on && !led_cycles_off)
+               v = 255;
+       else if (led_cycles_off && !led_cycles_on)
+               v = 0;
+       else if (led_cycles_off)
+               v = led_cycles_on * 255 / (led_cycles_on + led_cycles_off);
+       else
+               v = 255;
+       if (v < 0)
+               v = 0;
+       if (v > 255)
+               v = 255;
+       gui_data.powerled_brightness = v;
+       led_cycles_on = 0;
+       led_cycles_off = 0;
+       if (led_old_brightness != gui_data.powerled_brightness) {
+               gui_data.powerled = gui_data.powerled_brightness > 127;
+               gui_led (LED_POWER, gui_data.powerled);
+               led_filter_audio ();
+       }
+       led_old_brightness = gui_data.powerled_brightness;
+       led_cycle = get_cycles ();
+}
+
+static void write_battclock (void);
+void CIA_vsync_prehandler (void)
+{
+       if (heartbeat_cnt > 0)
+               heartbeat_cnt--;
+       if (rtc_delayed_write < 0) {
+               rtc_delayed_write = 50;
+       } else if (rtc_delayed_write > 0) {
+               rtc_delayed_write--;
+               if (rtc_delayed_write == 0)
+                       write_battclock ();
+       }
+       led_vsync ();
+       CIA_handler ();
+       if (kblostsynccnt > 0) {
+               kblostsynccnt -= maxvpos;
+               if (kblostsynccnt <= 0) {
+                       kblostsynccnt = 0;
+                       keyreq ();
+#if KB_DEBUG
+                       write_log (_T("lostsync\n"));
+#endif
+               }
+       }
+}
+
+static void CIAA_tod_handler (uae_u32 v)
+{
+       ciaatod++;
+       ciaatod &= 0xFFFFFF;
+       ciaa_checkalarm (true);
+}
+
+void CIAA_tod_inc (int cycles)
+{
+#ifdef TOD_HACK
+       if (currprefs.tod_hack && tod_hack_enabled == 1)
+               return;
+#endif
+       if (!ciaatodon)
+               return;
+       event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
+}
+
+static void bfe001_change (void)
+{
+       uae_u8 v = ciaapra;
+       bool led2;
+
+       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;
+       }
+       if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
+               oldovl = v & 1;
+               if (!oldovl) {
+                       map_overlay (1);
+               } else {
+                       //activate_debugger ();
+                       map_overlay (0);
+               }
+       }
+       if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) {
+               oldcd32mute = v & 1;
+               akiko_mute (oldcd32mute ? 0 : 1);
+       }
+}
+
+static uae_u8 ReadCIAA (unsigned int addr)
+{
+       unsigned int tmp;
+       int reg = addr & 15;
+
+       compute_passed_time ();
+
+#if CIAA_DEBUG_R > 0
+       write_log (_T("R_CIAA: bfe%x01 %08X\n"), reg, M68K_GETPC);
+#endif
+
+       switch (reg) {
+       case 0:
+#ifdef ACTION_REPLAY
+               action_replay_ciaread ();
+#endif
+               tmp = DISK_status() & 0x3c;
+               tmp |= handle_joystick_buttons (ciaapra, ciaadra);
+               tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03;
+               tmp = dongle_cia_read (0, reg, tmp);
+#if DONGLE_DEBUG > 0
+               if (notinrom())
+                       write_log (_T("BFE001 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+
+               if (inputrecord_debug & 2) {
+                       if (input_record > 0)
+                               inprec_recorddebug_cia (tmp, div10, m68k_getpc ());
+                       else if (input_play > 0)
+                               inprec_playdebug_cia (tmp, div10, m68k_getpc ());
+               }
+
+               return tmp;
+       case 1:
+#ifdef PARALLEL_PORT
+               if (isprinter () > 0) {
+                       tmp = ciaaprb;
+               } 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);
+#endif
+               } else if (currprefs.win32_samplersoundcard >= 0) {
+
+                       tmp = sampler_getsample ((ciabpra & 4) ? 1 : 0);
+
+               } else
+#endif
+
+               {
+                       tmp = handle_parport_joystick (0, ciaaprb, ciaadrb);
+                       tmp = dongle_cia_read (1, reg, tmp);
+#if DONGLE_DEBUG > 0
+                       if (notinrom())
+                               write_log (_T("BFE101 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+               }
+               if (ciaacrb & 2) {
+                       int pb7 = 0;
+                       if (ciaacrb & 4)
+                               pb7 = ciaacrb & 1;
+                       tmp &= ~0x80;
+                       tmp |= pb7 ? 0x80 : 00;
+               }
+               if (ciaacra & 2) {
+                       int pb6 = 0;
+                       if (ciaacra & 4)
+                               pb6 = ciaacra & 1;
+                       tmp &= ~0x40;
+                       tmp |= pb6 ? 0x40 : 00;
+               }
+               return tmp;
+       case 2:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFE201 R %02X %s\n"), ciaadra, debuginfo(0));
+#endif
+               return ciaadra;
+       case 3:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFE301 R %02X %s\n"), ciaadrb, debuginfo(0));
+#endif
+               return ciaadrb;
+       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 (uae_u8)ciaatol;
+               } else
+                       return (uae_u8)ciaatod;
+       case 9:
+               if (ciaatlatch)
+                       return (uae_u8)(ciaatol >> 8);
+               else
+                       return (uae_u8)(ciaatod >> 8);
+       case 10:
+               if (!ciaatlatch) { /* only if not already latched. A1200 confirmed. (TW) */
+                       /* no latching if ALARM is set */
+                       if (!(ciaacrb & 0x80))
+                               ciaatlatch = 1;
+                       ciaatol = ciaatod;
+               }
+               return (uae_u8)(ciaatol >> 16);
+       case 12:
+#if KB_DEBUG
+               write_log (_T("CIAA serial port: %02x %08x\n"), ciaasdr, M68K_GETPC);
+#endif
+               return ciaasdr;
+       case 13:
+               tmp = ciaaicr_reg;
+               ciaaicr &= ~ciaaicr_reg;
+               ciaaicr_reg = 0;
+               RethinkICRA ();
+               return tmp;
+       case 14:
+               return ciaacra;
+       case 15:
+               return ciaacrb;
+       }
+       return 0;
+}
+
+static uae_u8 ReadCIAB (unsigned int addr)
+{
+       unsigned int tmp;
+       int reg = addr & 15;
+
+#if CIAB_DEBUG_R > 0
+       if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_R > 1)
+               write_log (_T("R_CIAB: bfd%x00 %08X\n"), reg, M68K_GETPC);
+#endif
+
+       compute_passed_time ();
+
+       switch (reg) {
+       case 0:
+               tmp = 0;
+#ifdef SERIAL_PORT
+               if (currprefs.use_serial)
+                       tmp = serial_readstatus(ciabdra);
+#endif
+#ifdef PARALLEL_PORT
+               if (isprinter () > 0) {
+                       //tmp |= ciabpra & (0x04 | 0x02 | 0x01);
+                       tmp &= ~3; // clear BUSY and PAPEROUT
+                       tmp |= 4; // set SELECT
+               } else if (isprinter () < 0) {
+                       uae_u8 v;
+                       parallel_direct_read_status (&v);
+                       tmp |= v & 7;
+               } else {
+                       tmp |= handle_parport_joystick (1, ciabpra, ciabdra);
+               }
+#endif
+               tmp = dongle_cia_read (1, reg, tmp);
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD000 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+               return tmp;
+       case 1:
+#ifdef ACTION_REPLAY
+               action_replay_ciaread ();
+#endif
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD100 R %02X %s\n"), ciabprb, debuginfo(0));
+#endif
+               tmp = ciabprb;
+               tmp = dongle_cia_read (1, reg, tmp);
+               if (ciabcrb & 2) {
+                       int pb7 = 0;
+                       if (ciabcrb & 4)
+                               pb7 = ciabcrb & 1;
+                       tmp &= ~0x80;
+                       tmp |= pb7 ? 0x80 : 00;
+               }
+               if (ciabcra & 2) {
+                       int pb6 = 0;
+                       if (ciabcra & 4)
+                               pb6 = ciabcra & 1;
+                       tmp &= ~0x40;
+                       tmp |= pb6 ? 0x40 : 00;
+               }
+               return tmp;
+       case 2:
+               return ciabdra;
+       case 3:
+               return ciabdrb;
+       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 (uae_u8)ciabtol;
+               } else
+                       return (uae_u8)ciabtod;
+       case 9:
+               CIAB_tod_check ();
+               if (ciabtlatch)
+                       return (uae_u8)(ciabtol >> 8);
+               else
+                       return (uae_u8)(ciabtod >> 8);
+       case 10:
+               CIAB_tod_check ();
+               if (!ciabtlatch) {
+                       /* no latching if ALARM is set */
+                       if (!(ciabcrb & 0x80))
+                               ciabtlatch = 1;
+                       ciabtol = ciabtod;
+               }
+               return (uae_u8)(ciabtol >> 16);
+       case 12:
+               return ciabsdr;
+       case 13:
+               tmp = ciabicr_reg;
+               ciabicr &= ~ciabicr_reg;
+               ciabicr_reg = 0;
+               RethinkICRB ();
+               return tmp;
+       case 14:
+               //write_log (_T("CIABCRA READ %d %x\n"), ciabcra, M68K_GETPC);
+               return ciabcra;
+       case 15:
+               return ciabcrb;
+       }
+       return 0;
+}
+
+static void WriteCIAA (uae_u16 addr, uae_u8 val)
+{
+       int reg = addr & 15;
+
+#if CIAA_DEBUG_W > 0
+       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);
+               oldovl = 0;
+       }
+       switch (reg) {
+       case 0:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       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, val);
+#ifdef AMAX
+               if (currprefs.amaxromfile[0])
+                       amax_bfe001_write (val, ciaadra);
+#endif
+               break;
+       case 1:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFE101 W %02X %s\n"), val, debuginfo(0));
+#endif
+               ciaaprb = val;
+               dongle_cia_write (0, reg, val);
+#ifdef PARALLEL_PORT
+               if (isprinter() > 0) {
+                       doprinter (val);
+                       cia_parallelack ();
+               } else if (isprinter() < 0) {
+                       parallel_direct_write_data (val, ciaadrb);
+                       cia_parallelack ();
+#ifdef ARCADIA
+               } else if (arcadia_bios) {
+                       arcadia_parport (1, ciaaprb, ciaadrb);
+#endif
+               }
+#endif
+               break;
+       case 2:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFE201 W %02X %s\n"), val, debuginfo(0));
+#endif
+               ciaadra = val;
+               dongle_cia_write (0, reg, val);
+               bfe001_change ();
+               break;
+       case 3:
+               ciaadrb = val;
+               dongle_cia_write (0, reg, val);
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFE301 W %02X %s\n"), val, debuginfo(0));
+#endif
+#ifdef ARCADIA
+               if (arcadia_bios)
+                       arcadia_parport (1, ciaaprb, ciaadrb);
+#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) {
+                       ciaaalarm = (ciaaalarm & ~0xff) | val;
+               } else {
+                       ciaatod = (ciaatod & ~0xff) | val;
+                       ciaatodon = 1;
+                       ciaa_checkalarm (false);
+               }
+               break;
+       case 9:
+               if (ciaacrb & 0x80) {
+                       ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
+               } else {
+                       ciaatod = (ciaatod & ~0xff00) | (val << 8);
+               }
+               break;
+       case 10:
+               if (ciaacrb & 0x80) {
+                       ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
+               } else {
+                       ciaatod = (ciaatod & ~0xff0000) | (val << 16);
+                       ciaatodon = 0;
+               }
+               break;
+       case 12:
+               CIA_update ();
+               ciaasdr = val;
+               if ((ciaacra & 0x41) == 0x41 && ciaasdr_cnt == 0)
+                       ciaasdr_cnt = 8 * 2;
+#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);
+               break;
+       case 14:
+               CIA_update ();
+               val &= 0x7f; /* bit 7 is unused */
+               if ((val & 1) && !(ciaacra & 1))
+                       ciaastarta = CIASTARTCYCLESCRA;
+               if ((val & 0x40) == 0 && (ciaacra & 0x40) != 0) {
+                       /* todo: check if low to high or high to low only */
+                       kblostsynccnt = 0;
+#if KB_DEBUG
+                       write_log (_T("KB_ACK %02x->%02x\n"), ciaacra, val);
+#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 ();
+               break;
+       }
+}
+
+static void WriteCIAB (uae_u16 addr, uae_u8 val)
+{
+       int reg = addr & 15;
+
+#if CIAB_DEBUG_W > 0
+       if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_W > 1)
+               write_log (_T("W_CIAB: bfd%x00 %02X %08X\n"), reg, val, M68K_GETPC);
+#endif
+#ifdef ACTION_REPLAY
+       ar_ciab[reg] = val;
+#endif
+       switch (reg) {
+       case 0:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD000 W %02X %s\n"), val, debuginfo(0));
+#endif
+               dongle_cia_write (1, reg, val);
+               ciabpra = val;
+#ifdef SERIAL_PORT
+               if (currprefs.use_serial)
+                       serial_writestatus(ciabpra, ciabdra);
+#endif
+#ifdef PARALLEL_PORT
+               if (isprinter () < 0)
+                       parallel_direct_write_status (val, ciabdra);
+#endif
+               break;
+       case 1:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD100 W %02X %s\n"), val, debuginfo(0));
+#endif
+               dongle_cia_write (1, reg, val);
+               ciabprb = val;
+               DISK_select (val);
+               break;
+       case 2:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD200 W %02X %s\n"), val, debuginfo(0));
+#endif
+               dongle_cia_write (1, reg, val);
+               ciabdra = val;
+#ifdef SERIAL_PORT
+               if (currprefs.use_serial)
+                       serial_writestatus (ciabpra, ciabdra);
+#endif
+               break;
+       case 3:
+#if DONGLE_DEBUG > 0
+               if (notinrom ())
+                       write_log (_T("BFD300 W %02X %s\n"), val, debuginfo(0));
+#endif
+               dongle_cia_write (1, reg, val);
+               ciabdrb = 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) {
+                       ciabalarm = (ciabalarm & ~0xff) | val;
+               } else {
+                       ciabtod = (ciabtod & ~0xff) | val;
+                       ciabtodon = 1;
+                       ciab_checkalarm (false, true);
+               }
+               break;
+       case 9:
+               CIAB_tod_check ();
+               if (ciabcrb & 0x80) {
+                       ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
+               } else {
+                       ciabtod = (ciabtod & ~0xff00) | (val << 8);
+               }
+               break;
+       case 10:
+               CIAB_tod_check ();
+               if (ciabcrb & 0x80) {
+                       ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
+               } else {
+                       ciabtod = (ciabtod & ~0xff0000) | (val << 16);
+                       ciabtodon = 0;
+               }
+               break;
+       case 12:
+               CIA_update ();
+               ciabsdr = val;
+               if ((ciabcra & 0x40) == 0)
+                       ciabsdr_cnt = 0;
+               if ((ciabcra & 0x41) == 0x41 && ciabsdr_cnt == 0)
+                       ciabsdr_cnt = 8 * 2;
+               CIA_calctimers ();
+               break;
+       case 13:
+               setclr (&ciabimask, val);
+               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 ();
+               break;
+       }
+}
+
+void cia_set_overlay (bool overlay)
+{
+       oldovl = overlay;
+}
+
+void CIA_reset (void)
+{
+#ifdef TOD_HACK
+       tod_hack_tv = 0;
+       tod_hack_tod = 0;
+       tod_hack_enabled = 0;
+       if (currprefs.tod_hack)
+               tod_hack_enabled = TOD_HACK_TIME;
+#endif
+
+       kblostsynccnt = 0;
+       serbits = 0;
+       oldcd32mute = 1;
+       oldled = true;
+       resetwarning_phase = resetwarning_timer = 0;
+       heartbeat_cnt = 0;
+       ciab_tod_event_state = 0;
+
+       if (!savestate_state) {
+               oldovl = true;
+               kbstate = 0;
+               ciaatlatch = ciabtlatch = 0;
+               ciaapra = 0; ciaadra = 0;
+               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;
+               ciaaalarm = ciabalarm = 0;
+               ciabpra = 0x8C; ciabdra = 0;
+               div10 = 0;
+               ciaasdr_cnt = 0; ciaasdr = 0;
+               ciabsdr_cnt = 0; ciabsdr = 0;
+               ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
+               CIA_calctimers ();
+               DISK_select_set (ciabprb);
+       }
+       map_overlay (0);
+#ifdef SERIAL_PORT
+       if (currprefs.use_serial && !savestate_state)
+               serial_dtr_off (); /* Drop DTR at reset */
+#endif
+       if (savestate_state) {
+               if (currprefs.cs_ciaoverlay) {
+                       oldovl = true;
+               }
+               bfe001_change ();
+               if (!currprefs.cs_ciaoverlay) {
+                       map_overlay (oldovl ? 0 : 1);
+               }
+       }
+#ifdef CD32
+       if (!isrestore ()) {
+               akiko_reset ();
+               if (!akiko_init ())
+                       currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = 0;
+       }
+#endif
+}
+
+void dumpcia (void)
+{
+       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 ());
+       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);
+       console_out_f (_T("TOD %06x (%06x) ALARM %06x %c%c CLK=%d\n"),
+               ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S', div10 / CYCLE_UNIT);
+}
+
+/* CIA memory access */
+
+static uae_u32 REGPARAM3 cia_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_bget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_lgeti (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_wgeti (uaecptr) REGPARAM;
+static void REGPARAM3 cia_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 cia_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 cia_bput (uaecptr, uae_u32) REGPARAM;
+
+addrbank cia_bank = {
+       cia_lget, cia_wget, cia_bget,
+       cia_lput, cia_wput, cia_bput,
+       default_xlate, default_check, NULL, _T("CIA"),
+       cia_lgeti, cia_wgeti, ABFLAG_IO, 0x3f00, 0xbfc000
+};
+
+// Gayle or Fat Gary does not enable CIA /CS lines if both CIAs are selected
+// Old Gary based Amigas enable both CIAs in this situation
+
+STATIC_INLINE bool issinglecia (void)
+{
+       return currprefs.cs_ide || currprefs.cs_pcmcia || currprefs.cs_mbdmac;
+}
+STATIC_INLINE bool isgayle (void)
+{
+       return currprefs.cs_ide || currprefs.cs_pcmcia;
+}
+
+static void cia_wait_pre (void)
+{
+       if (currprefs.cachesize)
+               return;
+
+#ifndef CUSTOM_SIMPLE
+       int div = (get_cycles () - eventtab[ev_cia].oldcycles) % DIV10;
+       int cycles;
+
+       if (div >= DIV10 * ECLOCK_DATA_CYCLE / 10) {
+               cycles = DIV10 - div;
+               cycles += DIV10 * ECLOCK_DATA_CYCLE / 10;
+       } else if (div) {
+               cycles = DIV10 + DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
+       } else {
+               cycles = DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
+       }
+
+       if (cycles) {
+               if (currprefs.cpu_cycle_exact)
+                       x_do_cycles_pre (cycles);
+               else
+                       do_cycles (cycles);
+       }
+#endif
+}
+
+static void cia_wait_post (uae_u32 value)
+{
+       if (currprefs.cachesize) {
+               do_cycles (8 * CYCLE_UNIT /2);
+       } else {
+               int c = 6 * CYCLE_UNIT / 2;
+               if (currprefs.cpu_cycle_exact)
+                       x_do_cycles_post (c, value);
+               else
+                       do_cycles (c);
+       }
+}
+
+static bool isgaylenocia (uaecptr addr)
+{
+       // gayle CIA region is only 4096 bytes at 0xbfd000 and 0xbfe000
+       if (!isgayle ())
+               return true;
+       uaecptr mask = addr & 0xf000;
+       bool cia = mask == 0xe000 || mask == 0xd000;
+       return cia;
+}
+
+static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
+{
+       int r = (addr & 0xf00) >> 8;
+       uae_u8 v = 0xff;
+
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+
+       if (!isgaylenocia (addr))
+               return v;
+
+       cia_wait_pre ();
+       switch ((addr >> 12) & 3) {
+       case 0:
+               if (!issinglecia ())
+                       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;
+       case 3:
+               if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+                       v = (addr & 1) ? regs.irc : regs.irc >> 8;
+               if (warned > 0 || currprefs.illegal_mem) {
+                       write_log (_T("cia_bget: unknown CIA address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC);
+                       warned--;
+               }
+               break;
+       }
+       cia_wait_post (v);
+
+       return v;
+}
+
+static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
+{
+       int r = (addr & 0xf00) >> 8;
+       uae_u16 v = 0xffff;
+
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+
+       if (!isgaylenocia (addr))
+               return v;
+
+       cia_wait_pre ();
+       switch ((addr >> 12) & 3)
+       {
+       case 0:
+               if (!issinglecia ())
+                       v = (ReadCIAB (r) << 8) | ReadCIAA (r);
+               break;
+       case 1:
+               v = (ReadCIAB (r) << 8) | 0xff;
+               break;
+       case 2:
+               v = (0xff << 8) | ReadCIAA (r);
+               break;
+       case 3:
+               if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+                       v = regs.irc;
+               if (warned > 0 || currprefs.illegal_mem) {
+                       write_log (_T("cia_wget: unknown CIA address %08X=%04X PC=%08X\n"), addr, v & 0xffff, M68K_GETPC);
+                       warned--;
+               }
+               break;
+       }
+       cia_wait_post (v);
+       return v;
+}
+
+static uae_u32 REGPARAM2 cia_lget (uaecptr addr)
+{
+       uae_u32 v;
+       v = cia_wget (addr) << 16;
+       v |= cia_wget (addr + 2);
+       return v;
+}
+
+static uae_u32 REGPARAM2 cia_wgeti (uaecptr addr)
+{
+       if (currprefs.cpu_model >= 68020)
+               return dummy_wgeti (addr);
+       return cia_wget (addr);
+}
+static uae_u32 REGPARAM2 cia_lgeti (uaecptr addr)
+{
+       if (currprefs.cpu_model >= 68020)
+               return dummy_lgeti (addr);
+       return cia_lget (addr);
+}
+
+static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
+{
+       int r = (addr & 0xf00) >> 8;
+
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+
+       if (!isgaylenocia (addr))
+               return;
+
+       cia_wait_pre ();
+       if (!issinglecia () || (addr & 0x3000) != 0) {
+               if ((addr & 0x2000) == 0)
+                       WriteCIAB (r, value);
+               if ((addr & 0x1000) == 0)
+                       WriteCIAA (r, value);
+               if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
+                       write_log (_T("cia_bput: unknown CIA address %08X=%082X PC=%08X\n"), addr, value & 0xff, M68K_GETPC);
+                       warned--;
+               }
+       }
+       cia_wait_post (value);
+}
+
+static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
+{
+       int r = (addr & 0xf00) >> 8;
+
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+
+       if (!isgaylenocia (addr))
+               return;
+
+       cia_wait_pre ();
+       if (!issinglecia () || (addr & 0x3000) != 0) {
+               if ((addr & 0x2000) == 0)
+                       WriteCIAB (r, value >> 8);
+               if ((addr & 0x1000) == 0)
+                       WriteCIAA (r, value & 0xff);
+               if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
+                       write_log (_T("cia_wput: unknown CIA address %08X=%04X %08X\n"), addr, value & 0xffff, M68K_GETPC);
+                       warned--;
+               }
+       }
+       cia_wait_post (value);
+}
+
+static void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
+{
+       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;
+
+addrbank clock_bank = {
+       clock_lget, clock_wget, clock_bget,
+       clock_lput, clock_wput, clock_bput,
+       default_xlate, default_check, NULL, _T("Battery backed up clock (none)"),
+       dummy_lgeti, dummy_wgeti, ABFLAG_IO, 0x3f, 0xd80000
+};
+
+static unsigned int clock_control_d;
+static unsigned int clock_control_e;
+static unsigned int clock_control_f;
+
+#define RF5C01A_RAM_SIZE 16
+static uae_u8 rtc_memory[RF5C01A_RAM_SIZE], rtc_alarm[RF5C01A_RAM_SIZE];
+
+static uae_u8 getclockreg (int addr, struct tm *ct)
+{
+       uae_u8 v = 0;
+
+       if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
+               switch (addr) {
+               case 0x0: v = ct->tm_sec % 10; break;
+               case 0x1: v = ct->tm_sec / 10; break;
+               case 0x2: v = ct->tm_min % 10; break;
+               case 0x3: v = ct->tm_min / 10; break;
+               case 0x4: v = ct->tm_hour % 10; break;
+               case 0x5:
+                       if (clock_control_f & 4) {
+                               v = ct->tm_hour / 10; // 24h
+                       } else {
+                               v = (ct->tm_hour % 12) / 10; // 12h
+                               v |= ct->tm_hour >= 12 ? 4 : 0; // AM/PM bit
+                       }
+                       break;
+               case 0x6: v = ct->tm_mday % 10; break;
+               case 0x7: v = ct->tm_mday / 10; break;
+               case 0x8: v = (ct->tm_mon + 1) % 10; break;
+               case 0x9: v = (ct->tm_mon + 1) / 10; break;
+               case 0xA: v = ct->tm_year % 10; break;
+               case 0xB: v = (ct->tm_year / 10) & 0x0f;  break;
+               case 0xC: v = ct->tm_wday; break;
+               case 0xD: v = clock_control_d; break;
+               case 0xE: v = clock_control_e; break;
+               case 0xF: v = clock_control_f; break;
+               }
+       } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+               int bank = clock_control_d & 3;
+               /* memory access */
+               if (bank >= 2 && addr < 0x0d)
+                       return (rtc_memory[addr] >> ((bank == 2) ? 0 : 4)) & 0x0f;
+               /* alarm */
+               if (bank == 1 && addr < 0x0d) {
+                       v = rtc_alarm[addr];
+#if CLOCK_DEBUG
+                       write_log (_T("CLOCK ALARM R %X: %X\n"), addr, v);
+#endif
+                       return v;
+               }
+               switch (addr) {
+               case 0x0: v = ct->tm_sec % 10; break;
+               case 0x1: v = ct->tm_sec / 10; break;
+               case 0x2: v = ct->tm_min % 10; break;
+               case 0x3: v = ct->tm_min / 10; break;
+               case 0x4: v = ct->tm_hour % 10; break;
+               case 0x5:
+                       if (rtc_alarm[10] & 1)
+                               v = ct->tm_hour / 10; // 24h
+                       else
+                               v = ((ct->tm_hour % 12) / 10) | (ct->tm_hour >= 12 ? 2 : 0); // 12h
+               break;
+               case 0x6: v = ct->tm_wday; break;
+               case 0x7: v = ct->tm_mday % 10; break;
+               case 0x8: v = ct->tm_mday / 10; break;
+               case 0x9: v = (ct->tm_mon + 1) % 10; break;
+               case 0xA: v = (ct->tm_mon + 1) / 10; break;
+               case 0xB: v = (ct->tm_year % 100) % 10; break;
+               case 0xC: v = (ct->tm_year % 100) / 10; break;
+               case 0xD: v = clock_control_d; break;
+               /* E and F = write-only, reads as zero */
+               case 0xE: v = 0; break;
+               case 0xF: v = 0; break;
+               }
+       }
+#if CLOCK_DEBUG
+       write_log(_T("CLOCK R: %X = %X, PC=%08x\n"), addr, v, M68K_GETPC);
+#endif
+       return v;
+}
+
+static void write_battclock (void)
+{
+       if (!currprefs.rtcfile[0] || currprefs.cs_rtc == 0)
+               return;
+       struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("wb"));
+       if (f) {
+               uae_u8 zero[13] = { 0 };
+               struct tm *ct;
+               time_t t = time (0);
+               t += currprefs.cs_rtc_adjust;
+               ct = localtime (&t);
+               uae_u8 od = clock_control_d;
+               if (currprefs.cs_rtc == 2)
+                       clock_control_d &= ~3;
+               for (int i = 0; i < 13; i++) {
+                       uae_u8 v = getclockreg (i, ct);
+                       zfile_fwrite (&v, 1, 1, f);
+               }
+               clock_control_d = od;
+               zfile_fwrite (&clock_control_d, 1, 1, f);
+               zfile_fwrite (&clock_control_e, 1, 1, f);
+               zfile_fwrite (&clock_control_f, 1, 1, f);
+               if (currprefs.cs_rtc == 2) {
+                       zfile_fwrite (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fwrite (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+               }
+               zfile_fclose (f);
+       }
+}
+
+void rtc_hardreset (void)
+{
+       rtc_delayed_write = 0;
+       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)");
+               clock_control_d = 0x1;
+               clock_control_e = 0;
+               clock_control_f = 0x4; /* 24/12 */
+       } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+               clock_bank.name = _T("Battery backed up clock (RF5C01A)");
+               clock_control_d = 0x8; /* Timer EN */
+               clock_control_e = 0;
+               clock_control_f = 0;
+               memset (rtc_memory, 0, RF5C01A_RAM_SIZE);
+               memset (rtc_alarm, 0, RF5C01A_RAM_SIZE);
+               rtc_alarm[10] = 1; /* 24H mode */
+       }
+       if (currprefs.rtcfile[0]) {
+               struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("rb"));
+               if (f) {
+                       uae_u8 empty[13];
+                       zfile_fread (empty, 13, 1, f);
+                       zfile_fread (&clock_control_d, 1, 1, f);
+                       zfile_fread (&clock_control_e, 1, 1, f);
+                       zfile_fread (&clock_control_f, 1, 1, f);
+                       zfile_fread (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fread (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+                       zfile_fclose (f);
+               }
+       }
+}
+
+static uae_u32 REGPARAM2 clock_lget (uaecptr addr)
+{
+       return (clock_wget (addr) << 16) | clock_wget (addr + 2);
+}
+
+static uae_u32 REGPARAM2 clock_wget (uaecptr addr)
+{
+       return (clock_bget (addr) << 8) | clock_bget (addr + 1);
+}
+
+static uae_u32 REGPARAM2 clock_bget (uaecptr addr)
+{
+       time_t t;
+       struct tm *ct;
+       uae_u8 v = 0;
+
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+#ifdef CDTV
+       if (currprefs.cs_cdtvram && addr >= 0xdc8000)
+               return cdtv_battram_read (addr);
+#endif
+       addr &= 0x3f;
+       if ((addr & 3) == 2 || (addr & 3) == 0 || currprefs.cs_rtc == 0) {
+               if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+                       v = regs.irc >> 8;
+               return v;
+       }
+       t = time (0);
+       t += currprefs.cs_rtc_adjust;
+       ct = localtime (&t);
+       addr >>= 2;
+       return getclockreg (addr, ct);
+}
+
+static void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
+{
+       clock_wput (addr, value >> 16);
+       clock_wput (addr + 2, value);
+}
+
+static void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
+{
+       clock_bput (addr, value >> 8);
+       clock_bput (addr + 1, value);
+}
+
+static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
+{
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+//     write_log(_T("W: %x (%x): %x, PC=%08x\n"), addr, (addr & 0xff) >> 2, value & 0xff, M68K_GETPC);
+#ifdef CDTV
+       if (currprefs.cs_cdtvram && addr >= 0xdc8000) {
+               cdtv_battram_write (addr, value);
+               return;
+       }
+#endif
+       addr &= 0x3f;
+       if ((addr & 1) != 1 || currprefs.cs_rtc == 0)
+               return;
+       addr >>= 2;
+       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);
+#endif
+               switch (addr)
+               {
+               case 0xD: clock_control_d = value & (1|8); break;
+               case 0xE: clock_control_e = value; break;
+               case 0xF: clock_control_f = value; break;
+               }
+       } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+               int bank = clock_control_d & 3;
+               /* memory access */
+               if (bank >= 2 && addr < 0x0d) {
+                       uae_u8 ov = rtc_memory[addr];
+                       rtc_memory[addr] &= ((bank == 2) ? 0xf0 : 0x0f);
+                       rtc_memory[addr] |= value << ((bank == 2) ? 0 : 4);
+                       if (rtc_memory[addr] != ov)
+                               rtc_delayed_write = -1;
+                       return;
+               }
+               /* alarm */
+               if (bank == 1 && addr < 0x0d) {
+#if CLOCK_DEBUG
+                       write_log (_T("CLOCK ALARM W %X: %X\n"), addr, value);
+#endif
+                       uae_u8 ov = rtc_alarm[addr];
+                       rtc_alarm[addr] = value;
+                       rtc_alarm[0] = rtc_alarm[1] = rtc_alarm[9] = rtc_alarm[12] = 0;
+                       rtc_alarm[3] &= ~0x8;
+                       rtc_alarm[5] &= ~0xc;
+                       rtc_alarm[6] &= ~0x8;
+                       rtc_alarm[8] &= ~0xc;
+                       rtc_alarm[10] &= ~0xe;
+                       rtc_alarm[11] &= ~0xc;
+                       if (rtc_alarm[addr] != ov)
+                               rtc_delayed_write = -1;
+                       return;
+               }
+#if CLOCK_DEBUG
+               write_log (_T("CLOCK W %X: %X\n"), addr, value);
+#endif
+               switch (addr)
+               {
+               case 0xD: clock_control_d = value; break;
+               case 0xE: clock_control_e = value; break;
+               case 0xF: clock_control_f = value; break;
+               }
+       }
+       rtc_delayed_write = -1;
+}
+
+#ifdef SAVESTATE
+
+/* CIA-A and CIA-B save/restore code */
+
+static void save_cia_prepare (void)
+{
+       CIA_update_check ();
+       CIA_calctimers ();
+       compute_passed_time ();
+}
+
+void restore_cia_start (void)
+{
+       /* Fixes very old statefiles without keyboard state */
+       kbstate = 3;
+       setcapslockstate (0);
+       kblostsynccnt = 0;
+}
+
+void restore_cia_finish (void)
+{
+       eventtab[ev_cia].oldcycles = get_cycles ();
+       CIA_update ();
+       CIA_calctimers ();
+       compute_passed_time ();
+       eventtab[ev_cia].oldcycles -= div10;
+       //dumpcia ();
+       DISK_select_set (ciabprb);
+}
+
+uae_u8 *restore_cia (int num, 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? */
+       b = restore_u8 ();
+       if (num)
+               div10 = CYCLE_UNIT * b;
+       b = restore_u8 ();
+       if (num) ciabsdr_cnt = b; else ciaasdr_cnt = b;
+       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 = xmalloc (uae_u8, 1000);
+
+       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);
+
+       /* 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);
+       save_u8 (num ? div10 / CYCLE_UNIT : 0);
+       save_u8 (num ? ciabsdr_cnt : ciaasdr_cnt);
+       *len = dst - dstbak;
+       return dstbak;
+}
+
+uae_u8 *save_keyboard (int *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);
+       *len = dst - dstbak;
+       return dstbak;
+}
+
+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 ();
+       if (!(v & 1)) {
+               kbstate = 3;
+               kblostsynccnt = 0;
+       }
+       return src;
+}
+
+#endif /* SAVESTATE */
index 3afb2a3bab1791cd0ec2b5276d2f618afab4c965..2a7d340267194ef12f9cf34fc613fefe2087090b 100644 (file)
@@ -3547,7 +3547,7 @@ static bool hsyncdelay (void)
 
 // DFF006 = 0.W must be valid result but better do this only in 68000 modes (whdload black screen!)
 
-#define HPOS_OFFSET (currprefs.cpu_model < 68020 ? 3 : 0)
+#define HPOS_OFFSET ((currprefs.cpu_model < 68020 || (currprefs.cpu_model == 68020 && currprefs.cpu_cycle_exact)) ? 3 : 0)
 
 static uae_u16 VPOSR (void)
 {
@@ -6491,11 +6491,6 @@ static void hsync_handler_pre (bool onvsync)
 #endif
 }
 
-static void CIAA_tod_inc (uae_u32 v)
-{
-       CIAA_tod_handler ();
-}
-
 STATIC_INLINE bool is_last_line (void)
 {
        return vpos + 1 == maxvpos + lof_store;
@@ -6535,7 +6530,7 @@ static void hsync_handler_post (bool onvsync)
 #else
                static int cia_hsync;
                if (cia_hsync < maxhpos) {
-                       event2_newevent_xx (-1, cia_hsync, 1, CIAA_tod_inc);
+                       CIAA_tod_inc (cia_hsync);
                        int newcount = (vblank_hz * MAXVPOS_PAL * MAXHPOS_PAL) / (currprefs.cs_ciaatod == 2 ? 60 : 50);
                        cia_hsync += newcount;
                } else {
@@ -6546,10 +6541,10 @@ static void hsync_handler_post (bool onvsync)
                // CIA-A TOD counter increases when vsync pulse ends
                if (beamcon0 & 0x80) {
                        if (vpos == vsstop)
-                               event2_newevent_xx (-1, lof_store ? hsstop : hsstop + hcenter, 0, CIAA_tod_inc);
+                               CIAA_tod_inc (lof_store ? hsstop : hsstop + hcenter);
                } else {
                        if (vpos == (currprefs.ntscmode ? VSYNC_ENDLINE_NTSC : VSYNC_ENDLINE_PAL)) {
-                               event2_newevent_xx (-1, lof_store ? 132 : 18, 0, CIAA_tod_inc);
+                               CIAA_tod_inc (lof_store ? 132 : 18);
                        }
                }
        }
@@ -8318,6 +8313,19 @@ STATIC_INLINE void checknasty (int hpos, int vpos)
                record_dma_event (DMA_EVENT_BLITNASTY, hpos, vpos);
 }
 
+static void sync_ce020 (void)
+{
+       unsigned long c;
+       int extra;
+
+       c = get_cycles ();
+       extra = c & (CYCLE_UNIT - 1);
+       if (extra) {
+               extra = CYCLE_UNIT - extra;
+               do_cycles (extra);
+       }
+}
+
 uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode)
 {
        uae_u32 v = 0;
@@ -8362,6 +8370,7 @@ uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
        int hpos;
        struct dma_rec *dr;
 
+       sync_ce020 ();
        hpos = dma_cycle ();
        x_do_cycles_pre (CYCLE_UNIT);
 
@@ -8389,8 +8398,8 @@ uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
        if (debug_dma)
                dr->dat = v;
 #endif
+       x_do_cycles_post (CYCLE_UNIT, v);
 
-       regs.ce020memcycles -= CYCLE_UNIT;
        return v;
 }
 
@@ -8429,6 +8438,7 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
 {
        int hpos;
 
+       sync_ce020 ();
        hpos = dma_cycle ();
        x_do_cycles_pre (CYCLE_UNIT);
 
@@ -8453,14 +8463,41 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
        else if (mode == 0)
                put_byte (addr, v);
 
-       regs.ce020memcycles -= CYCLE_UNIT;
+       x_do_cycles_post (CYCLE_UNIT, v);
 }
 
 void do_cycles_ce (unsigned long cycles)
 {
-       unsigned long c;
+       while (cycles >= CYCLE_UNIT) {
+               int hpos = current_hpos () + 1;
+               sync_copper (hpos);
+               decide_line (hpos);
+               decide_fetch_ce (hpos);
+               if (bltstate != BLT_done)
+                       decide_blitter (hpos);
+               do_cycles (1 * CYCLE_UNIT);
+               cycles -= CYCLE_UNIT;
+       }
+}
 
-       c = cycles + extra_cycle;
+void do_cycles_ce020 (unsigned long cycles)
+{
+       unsigned long c;
+       int extra;
+
+       sync_ce020 ();
+       c = get_cycles ();
+       extra = c & (CYCLE_UNIT - 1);
+       if (extra) {
+               extra = CYCLE_UNIT - extra;
+               if (extra >= cycles) {
+                       do_cycles (cycles);
+                       return;
+               }
+               do_cycles (extra);
+               cycles -= extra;
+       }
+       c = cycles;
        while (c >= CYCLE_UNIT) {
                int hpos = current_hpos () + 1;
                sync_copper (hpos);
@@ -8471,9 +8508,11 @@ void do_cycles_ce (unsigned long cycles)
                do_cycles (1 * CYCLE_UNIT);
                c -= CYCLE_UNIT;
        }
-       extra_cycle = c;
+       if (c > 0)
+               do_cycles (c);
 }
 
+
 int is_cycle_ce (void)
 {
        int hpos = current_hpos ();
index 593122d5483386be816332939da5aa47407347ee..39ca7c44d02349d8f96c7e38c8769af7e560abbc 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -761,7 +761,7 @@ static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *end)
 {
        static uaecptr old;
        uaecptr paddr = addr;
-       int next;
+       int next = last;
        if (last && 0) {
                if (addr >= last)
                        return 0xffffffff;
@@ -1028,7 +1028,10 @@ STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8)
        }
 }
 
-#define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL);
+#define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL)
+
+static uae_u32 intlevc[] = { 0x000000, 0x444444, 0x008800, 0xffff00, 0x000088, 0x880000, 0xff0000, 0xffffff };
+
 void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
 {
        int y, x, xx, dx, xplus, yplus;
@@ -1068,6 +1071,7 @@ void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, u
        cc[DMARECORD_SPRITE] = lc(0xff00ff);
        cc[DMARECORD_DISK] = lc(0xffffff);
 
+       uae_s8 intlev = 0;
        for (x = 0; x < maxhpos; x++) {
                uae_u32 c = cc[0];
                xx = x * xplus + dx;
@@ -1075,10 +1079,16 @@ void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, u
                if (dr->reg != 0xffff) {
                        c = cc[dr->type];           
                }
-               putpixel (buf, bpp, xx, c);
+               if (dr->intlev > intlev)
+                       intlev = dr->intlev;
+               putpixel (buf, bpp, xx + 4, c);
                if (xplus)
-                       putpixel (buf, bpp, xx + 1, c);
+                       putpixel (buf, bpp, xx + 4 + 1, c);
        }
+       putpixel (buf, bpp, dx + 0, 0);
+       putpixel (buf, bpp, dx + 1, lc(intlevc[intlev]));
+       putpixel (buf, bpp, dx + 2, lc(intlevc[intlev]));
+       putpixel (buf, bpp, dx + 3, 0);
 }
 
 
@@ -1117,6 +1127,7 @@ struct dma_rec *record_dma (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos, in
        dr->dat = dat;
        dr->addr = addr;
        dr->type = type;
+       dr->intlev = regs.intmask;
        return dr;
 }
 
index c516a9f8da74fb035523ae46ffb72681627032ff..909172f9b12e8894b4fea58fd46d787a3e3316d2 100644 (file)
@@ -839,21 +839,21 @@ static void expamem_init_filesys (void)
        expamem_write (0x24, 0x01); /* ser.no. Byte 3 */
 
        /* er_InitDiagVec */
-       expamem_write (0x28, 0x10); /* Rom-Offset hi */
+       expamem_write (0x28, 0x20); /* Rom-Offset hi */
        expamem_write (0x2c, 0x00); /* ROM-Offset lo */
 
        expamem_write (0x40, 0x00); /* Ctrl/Statusreg.*/
 
        /* Build a DiagArea */
-       memcpy (expamem + 0x1000, diagarea, sizeof diagarea);
+       memcpy (expamem + 0x2000, diagarea, sizeof diagarea);
 
        /* Call DiagEntry */
-       do_put_mem_word ((uae_u16 *)(expamem + 0x1100), 0x4EF9); /* JMP */
-       do_put_mem_long ((uae_u32 *)(expamem + 0x1102), ROM_filesys_diagentry);
+       do_put_mem_word ((uae_u16 *)(expamem + 0x2100), 0x4EF9); /* JMP */
+       do_put_mem_long ((uae_u32 *)(expamem + 0x2102), ROM_filesys_diagentry);
 
        /* What comes next is a plain bootblock */
-       do_put_mem_word ((uae_u16 *)(expamem + 0x1106), 0x4EF9); /* JMP */
-       do_put_mem_long ((uae_u32 *)(expamem + 0x1108), EXPANSION_bootcode);
+       do_put_mem_word ((uae_u16 *)(expamem + 0x2106), 0x4EF9); /* JMP */
+       do_put_mem_long ((uae_u32 *)(expamem + 0x2108), EXPANSION_bootcode);
 
        memcpy (filesysory, expamem, 0x3000);
 }
@@ -1348,9 +1348,14 @@ void expamem_reset (void)
 #endif
 #ifdef GFXBOARD
        if (currprefs.rtgmem_type >= GFXBOARD_HARDWARE && !gfxboard_is_z3 (currprefs.rtgmem_type)) {
-               card_name[cardno] = _T ("Gfxboard VRAM Zorro II");
+               card_name[cardno] = _T("Gfxboard VRAM Zorro II");
                card_init[cardno] = expamem_init_gfxboard_memory;
                card_map[cardno++] = NULL;
+               if (gfxboard_num_boards (currprefs.rtgmem_type) == 3) {
+                       card_name[cardno] = _T("Gfxboard VRAM Zorro II Extra");
+                       card_init[cardno] = gfxboard_init_memory_p4_z2;
+                       card_map[cardno++] = NULL;
+               }
                if (gfxboard_is_registers (currprefs.rtgmem_type)) {
                        card_name[cardno] = _T ("Gfxboard Registers");
                        card_init[cardno] = expamem_init_gfxboard_registers;
index 63e462c94afb079c204a299645ee35f3e633ffcb..4a74c41e59604d893f71c2a6c4bc4bf8c5bc0dea 100644 (file)
@@ -165,7 +165,7 @@ static void addcycles_ce020 (int cycles)
        if (!using_ce020)
                return;
        if (cycles > 0)
-               printf ("\tregs.ce020memcycles += %d * cpucycleunit;\n", cycles);
+               printf ("\tusecycles_ce020 (%d * cpucycleunit);\n", cycles);
        count_cycles += cycles;
 }
 static void addcycles000 (int cycles)
@@ -340,7 +340,7 @@ static const char *gen_nextibyte (int flags)
        int r = m68k_pc_offset;
        m68k_pc_offset += 2;
 
-       if (using_ce020) {
+       if (using_ce020 || using_prefetch_020) {
                sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r);
                count_read++;
        } else if (using_ce) {
@@ -400,21 +400,45 @@ static void fill_prefetch_2 (void)
 }
 
 static void fill_prefetch_1 (int o)
+{
+       if (using_prefetch) {
+               printf ("\t%s (%d);\n", prefetch_word, o);
+               did_prefetch = 1;
+               ir2irc = 0;
+               count_read++;
+               insn_n_cycles += 4;
+       }
+}
+
+static void fill_prefetch_full (void)
+{
+       if (using_prefetch) {
+               fill_prefetch_1 (0);
+               irc2ir ();
+               fill_prefetch_1 (2);
+       } else if (using_prefetch_020) {
+               did_prefetch = 1;
+               if (cpu_level >= 3)
+                       printf ("\tfill_prefetch_0x0 ();\n");
+               else if (cpu_level == 2)
+                       printf ("\tfill_prefetch_020 ();\n");
+       }
+}
+
+// 68000 and 68010 only
+static void fill_prefetch_full_000 (void)
 {
        if (!using_prefetch)
                return;
-       printf ("\t%s (%d);\n", prefetch_word, o);
-       did_prefetch = 1;
-       ir2irc = 0;
-       count_read++;
-       insn_n_cycles += 4;
+       fill_prefetch_full ();
 }
 
-static void fill_prefetch_full (void)
+// 68020+
+static void fill_prefetch_full_020 (void)
 {
-       fill_prefetch_1 (0);
-       irc2ir ();
-       fill_prefetch_1 (2);
+       if (!using_prefetch_020)
+               return;
+       fill_prefetch_full ();
 }
 
 static void fill_prefetch_0 (void)
@@ -446,14 +470,27 @@ static void fill_prefetch_next_1 (void)
 
 static void fill_prefetch_next (void)
 {
-       fill_prefetch_next_1 ();
+       if (using_prefetch) {
+               fill_prefetch_next_1 ();
+       }
+//     if (using_prefetch_020) {
+//             printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset);
+//             did_prefetch = 1;
+//     }
 }
 
 static void fill_prefetch_finish (void)
 {
-       if (did_prefetch || !using_prefetch)
+       if (did_prefetch)
                return;
-       fill_prefetch_1 (m68k_pc_offset);
+       if (using_prefetch) {
+               fill_prefetch_1 (m68k_pc_offset);
+       }
+       if (using_prefetch_020) {
+               if (count_cycles == 0)
+                       addcycles_ce020 (2);
+               did_prefetch = 1;
+       }
 }
 
 static void setpc (const char *format, ...)
@@ -570,6 +607,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
        }
 
        start_brace ();
+
        switch (mode) {
        case Dreg:
                if (movem)
@@ -616,11 +654,13 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                syncmovepc (getv, flags);
                return;
        case Aind: // (An)
+               addcycles_ce020 (2);
                printf ("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg);
                break;
        case Aipi: // (An)+
+               addcycles_ce020 (2);
                printf ("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg);
@@ -644,6 +684,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                default:
                        abort ();
                }
+               addcycles_ce020 (2);
                if (!(flags & GF_APDI)) {
                        addcycles000 (2);
                        insn_n_cycles += 2;
@@ -651,12 +692,14 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                }
                break;
        case Ad16: // (d16,An)
+               addcycles_ce020 (2);
                printf ("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf ("\t%sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags));
                count_read_ea++; 
                break;
        case Ad8r: // (d8,An,Xn)
+               addcycles_ce020 (4);
                printf ("\tuaecptr %sa;\n", name);
                if (cpu_level > 1) {
                        if (next_cpu_level < 1)
@@ -678,12 +721,14 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                }
                break;
        case PC16: // (d16,PC,Xn)
+               addcycles_ce020 (2);
                printf ("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf ("\t%sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
                printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
                break;
        case PC8r: // (d8,PC,Xn)
+               addcycles_ce020 (4);
                printf ("\tuaecptr tmppc;\n");
                printf ("\tuaecptr %sa;\n", name);
                if (cpu_level > 1) {
@@ -708,11 +753,13 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
 
                break;
        case absw:
+               addcycles_ce020 (4);
                printf ("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf ("\t%sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
                break;
        case absl:
+               addcycles_ce020 (4);
                gen_nextilong2 ("uaecptr", namea, flags, movem);
                count_read_ea += 2;
                break;
@@ -722,14 +769,17 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                insn_n_cycles020++;
                switch (size) {
                case sz_byte:
+                       addcycles_ce020 (2);
                        printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
                        count_read_ea++;
                        break;
                case sz_word:
+                       addcycles_ce020 (2);
                        printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
                        count_read_ea++;
                        break;
                case sz_long:
+                       addcycles_ce020 (4);
                        gen_nextilong ("uae_s32", name, flags);
                        count_read_ea += 2;
                        break;
@@ -741,6 +791,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
        case imm0:
                if (getv != 1)
                        abort ();
+               addcycles_ce020 (2);
                printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
                count_read_ea++;
                syncmovepc (getv, flags);
@@ -748,6 +799,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
        case imm1:
                if (getv != 1)
                        abort ();
+               addcycles_ce020 (2);
                printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
                count_read_ea++;
                syncmovepc (getv, flags);
@@ -755,6 +807,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
        case imm2:
                if (getv != 1)
                        abort ();
+               addcycles_ce020 (4);
                gen_nextilong ("uae_s32", name, flags);
                count_read_ea += 2;
                syncmovepc (getv, flags);
@@ -800,7 +853,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
 
        if (getv == 1) {
                start_brace ();
-               if (using_ce020) {
+               if (using_ce020 || using_prefetch_020) {
                        switch (size) {
                        case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
                        case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break;
@@ -930,7 +983,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha
        case PC8r:
                if (!(flags & GF_NOFAULTPC))
                        gen_set_fault_pc ();
-               if (using_ce020) {
+               if (using_ce020 || using_prefetch_020) {
                        switch (size) {
                        case sz_byte:
                                printf ("\t%s (%sa, %s);\n", dstb, to, from);
@@ -1248,6 +1301,7 @@ static void genmovemel (uae_u16 opcode)
        printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
        printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
        genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0);
+       addcycles_ce020 (8);
        start_brace ();
        if (using_mmu == 68030) {
                movem_mmu030 (getcode, size, false, table68k[opcode].dmode == Aipi, false);
@@ -1256,10 +1310,14 @@ static void genmovemel (uae_u16 opcode)
        } else if (using_mmu == 68040) {
                movem_mmu040 (getcode, size, false, table68k[opcode].dmode == Aipi, false, opcode);
        } else {
-               printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
-                       getcode, size);
-               printf ("\twhile (amask) { m68k_areg (regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n",
-                       getcode, size);
+               printf ("\twhile (dmask) {\n");
+               printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask];\n", getcode, size);
+               addcycles_ce020 (1);
+               printf ("\t}\n");
+               printf ("\twhile (amask) {\n");
+               printf ("\t\tm68k_areg (regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask];\n", getcode, size);
+               addcycles_ce020 (1);
+               printf ("\t}\n");
                if (table68k[opcode].dmode == Aipi) {
                        printf ("\tm68k_areg (regs, dstreg) = srca;\n");
                        count_read++;
@@ -1312,6 +1370,7 @@ static void genmovemle (uae_u16 opcode)
 
        printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
        genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0);
+       addcycles_ce020 (4);
        start_brace ();
        if (using_mmu >= 68030) {
                if (table68k[opcode].dmode == Apdi)
@@ -1769,6 +1828,7 @@ static void resetvars (void)
                        nextl = "next_ilong_020ce";
                } else if (using_ce020 == 2) {
                        // 68030/40/60 CE
+                       disp020 = "x_get_disp_ea_ce020";
                        prefetch_long = "get_long_ce030_prefetch";
                        prefetch_word = "get_word_ce030_prefetch";
                        srcli = "x_get_ilong";
@@ -1783,6 +1843,7 @@ static void resetvars (void)
                        nextw = "next_iword_030ce";
                        nextl = "next_ilong_030ce";
                } else if (using_prefetch_020) {
+                       disp020 = "x_get_disp_ea_020";
                        prefetch_word = "get_word_020_prefetch";
                        prefetch_long = "get_long_020_prefetch";
                        srcli = "x_get_ilong";
@@ -1794,8 +1855,8 @@ static void resetvars (void)
                        dstw = "x_put_word";
                        srcb = "x_get_byte";
                        dstb = "x_put_byte";
-                       nextw = "next_iword_020";
-                       nextl = "next_ilong_020";
+                       nextw = "next_iword_020_prefetch";
+                       nextl = "next_ilong_020_prefetch";
                }
 #if 0
        } else if (using_ce020) {
@@ -2010,6 +2071,8 @@ static void gen_opcode (unsigned long int opcode)
                        if (curi->smode == imm || curi->smode == Dreg)
                                c += 2;
                }
+               if (curi->dmode != Dreg)
+                       addcycles_ce020 (4);
                fill_prefetch_next ();
                if (c > 0)
                        addcycles000 (c);
@@ -2025,6 +2088,7 @@ static void gen_opcode (unsigned long int opcode)
                if (curi->size == sz_byte) {
                        printf ("\tsrc &= 0xFF;\n");
                }
+               addcycles_ce020 (12);
                addcycles000 (8);
                fill_prefetch_next ();
                printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
@@ -2037,6 +2101,7 @@ static void gen_opcode (unsigned long int opcode)
                if (curi->size == sz_byte) {
                        printf ("\tsrc |= 0xFF00;\n");
                }
+               addcycles_ce020 (12);
                addcycles000 (8);
                fill_prefetch_next ();
                printf ("\tregs.sr &= src;\n");
@@ -2053,6 +2118,8 @@ static void gen_opcode (unsigned long int opcode)
                                if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
                                        c += 2;
                        }
+               } else {
+                       addcycles_ce020 (4);
                }
                fill_prefetch_next ();
                if (c > 0)
@@ -2137,6 +2204,8 @@ static void gen_opcode (unsigned long int opcode)
                                if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
                                        c += 2;
                        }
+               } else {
+                       addcycles_ce020 (4);
                }
                fill_prefetch_next ();
                if (c > 0)
@@ -2217,6 +2286,7 @@ static void gen_opcode (unsigned long int opcode)
                fill_prefetch_next ();
                if (isreg (curi->smode) && curi->size == sz_long)
                        addcycles000 (2);
+               addcycles_ce020 (isreg (curi->smode) ? 2 : 4);
                start_brace ();
                genflags (flag_sub, curi->size, "dst", "src", "0");
                genastore_rev ("dst", curi->smode, "srcreg", curi->size, "src");
@@ -2226,6 +2296,7 @@ static void gen_opcode (unsigned long int opcode)
                fill_prefetch_next ();
                if (isreg (curi->smode) && curi->size == sz_long)
                        addcycles000 (2);
+               addcycles_ce020 (isreg (curi->smode) ? 2 : 4);
                start_brace ();
                printf ("\tuae_u32 newv = 0 - src - (GET_XFLG () ? 1 : 0);\n");
                genflags (flag_subx, curi->size, "newv", "src", "0");
@@ -2236,6 +2307,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW);
                if (isreg (curi->smode))
                        addcycles000 (2);
+               addcycles_ce020 (6);
                fill_prefetch_next ();
                start_brace ();
                printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n");
@@ -2265,6 +2337,7 @@ static void gen_opcode (unsigned long int opcode)
                fill_prefetch_next ();
                if (isreg (curi->smode) && curi->size == sz_long)
                        addcycles000 (2);
+               addcycles_ce020 (isreg (curi->smode) ? 2 : 4);
                genflags (flag_logical, curi->size, "0", "", "");
                genastore_rev ("0", curi->smode, "srcreg", curi->size, "src");
                break;
@@ -2273,6 +2346,7 @@ static void gen_opcode (unsigned long int opcode)
                fill_prefetch_next ();
                if (isreg (curi->smode) && curi->size == sz_long)
                        addcycles000 (2);
+               addcycles_ce020 (isreg (curi->smode) ? 2 : 4);
                start_brace ();
                printf ("\tuae_u32 dst = ~src;\n");
                genflags (flag_logical, curi->size, "dst", "", "");
@@ -2280,12 +2354,14 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_TST:
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+               addcycles_ce020 (2);
                fill_prefetch_next ();
                genflags (flag_logical, curi->size, "src", "", "");
                break;
        case i_BTST:
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_IR2IRC);
+               addcycles_ce020 (4);
                fill_prefetch_next ();
                bsetcycles (curi);
                printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
@@ -2296,9 +2372,10 @@ static void gen_opcode (unsigned long int opcode)
                // on 68000 these have weird side-effect, if EA points to write-only custom register
                //during instruction's read access CPU data lines appear as zero to outside world,
                // (normally previously fetched data appears in data lines if reading write-only register)
-               // this allows stupid things like bset #2,$dff002 to work "correctly"
+               // this allows stupid things like bset #2,$dff096 to work "correctly"
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_IR2IRC | GF_RMW);
+               addcycles_ce020 (4);
                fill_prefetch_next ();
                bsetcycles (curi);
                // bclr needs 1 extra cycle
@@ -2337,7 +2414,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0);
                fill_prefetch_next ();
-               addcycles000 (2);
+               addcycles000 (4);
                start_brace ();
                genflags (flag_cmp, sz_long, "newv", "src", "dst");
                break;
@@ -2397,7 +2474,7 @@ static void gen_opcode (unsigned long int opcode)
                        genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
                        sync_m68k_pc ();
                        if (dualprefetch) {
-                               fill_prefetch_full ();
+                               fill_prefetch_full_000 ();
                                prefetch_done = 1;
                        }
                        if (!prefetch_done)
@@ -2421,11 +2498,13 @@ static void gen_opcode (unsigned long int opcode)
                        // MOVE TO CCR
                        dummy_prefetch ();
                        addcycles000 (4);
+                       addcycles_ce020 (4);
                        printf ("\tMakeSR ();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
                } else {
                        // MOVE TO SR
                        dummy_prefetch ();
                        addcycles000 (4);
+                       addcycles_ce020 (8);
                        printf ("\tregs.sr = src;\n");
                }
                printf ("\tMakeFromSR ();\n");
@@ -2435,6 +2514,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", sz_long, "src", 1, 0, 0);
                fill_prefetch_next ();
                start_brace ();
+               addcycles_ce020 (4);
                printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
                genflags (flag_logical, sz_long, "dst", "", "");
                genastore ("dst", curi->smode, "srcreg", sz_long, "src");
@@ -2489,11 +2569,13 @@ static void gen_opcode (unsigned long int opcode)
        case i_MVR2USP:
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                fill_prefetch_next ();
+               addcycles_ce020 (2);
                printf ("\tregs.usp = src;\n");
                break;
        case i_MVUSP2R:
                genamode (curi->smode, "srcreg", curi->size, "src", 2, 0, 0);
                fill_prefetch_next ();
+               addcycles_ce020 (2);
                genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
                break;
        case i_RESET:
@@ -2501,6 +2583,7 @@ static void gen_opcode (unsigned long int opcode)
                printf ("\tcpureset ();\n");
                sync_m68k_pc ();
                addcycles000 (128);
+               addcycles_ce020 (518);
                if (using_prefetch) {
                        printf ("\t%s (2);\n", prefetch_word);
                        m68k_pc_offset = 0;
@@ -2508,6 +2591,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_NOP:
                fill_prefetch_next ();
+               addcycles_ce020 (2);
                if (using_ce020)
                        printf ("\t%s (6);\n", do_cycles);
                break;
@@ -2519,6 +2603,7 @@ static void gen_opcode (unsigned long int opcode)
                        genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                        printf ("\tregs.sr = src;\n");
                }
+               addcycles_ce020 (8);
                printf ("\tMakeFromSR ();\n");
                printf ("\tm68k_setstopped ();\n");
                sync_m68k_pc ();
@@ -2604,6 +2689,7 @@ static void gen_opcode (unsigned long int opcode)
                } else {
                        genamode (Aipi, "7", sz_long, "pc", 1, 0, 0);
                        genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0, 0);
+                       addcycles_ce020 (10);
                        printf ("\tm68k_areg (regs, 7) += offs;\n");
                        printf ("\tif (pc & 1) {\n");
                        printf ("\t\texception3i (0x%04X, pc);\n", opcode);
@@ -2634,6 +2720,7 @@ static void gen_opcode (unsigned long int opcode)
                        genamode (Apdi, "7", sz_long, "old", 2, 0, GF_AA);
                        genamode (curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
                        genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
+                       addcycles_ce020 (5);
                        genastore ("src", Apdi, "7", sz_long, "old");
                        genastore ("m68k_areg (regs, 7)", curi->smode, "srcreg", sz_long, "src");
                        printf ("\tm68k_areg (regs, 7) += offs;\n");
@@ -2651,12 +2738,14 @@ static void gen_opcode (unsigned long int opcode)
                        genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                        printf ("\tm68k_areg (regs, 7) = src;\n");
                        genamode (Aipi, "7", sz_long, "old", 1, 0, 0);
+                       addcycles_ce020 (6);
                        fill_prefetch_next ();
                        genastore ("old", curi->smode, "srcreg", curi->size, "src");
                }
                break;
        case i_RTS:
                printf ("\tuaecptr pc = m68k_getpc ();\n");
+               addcycles_ce020 (10);
                if (using_ce020 == 1)
                        printf ("\tm68k_do_rts_ce020 ();\n");
                else if (using_ce020 == 2)
@@ -2690,6 +2779,7 @@ static void gen_opcode (unsigned long int opcode)
                printf ("\tMakeSR ();\n");
                genamode (Aipi, "7", sz_word, "sr", 1, 0, 0);
                genamode (Aipi, "7", sz_long, "pc", 1, 0, 0);
+               addcycles_ce020 (10);
                printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
                printf ("\tregs.sr |= sr;\n");
                setpc ("pc");
@@ -2705,6 +2795,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_JSR: // TODO: check stack write order
                genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL);
                start_brace ();
+               addcycles_ce020 (5);
                printf ("\tuaecptr oldpc = m68k_getpc () + %d;\n", m68k_pc_offset);
                if (using_exception_3) {
                        printf ("\tif (srca & 1) {\n");
@@ -2735,6 +2826,7 @@ static void gen_opcode (unsigned long int opcode)
                        }
                }
                count_write += 2;
+               fill_prefetch_full_020 ();
                fill_prefetch_next ();
                break;
        case i_JMP:
@@ -2746,6 +2838,7 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t}\n");
                        need_endlabel = 1;
                }
+               addcycles_ce020 (4);
                if (curi->smode == Ad16 || curi->smode == Ad8r || curi->smode == absw || curi->smode == PC16 || curi->smode == PC8r)
                        addcycles000 (2);
                setpc ("srca");
@@ -2773,6 +2866,7 @@ static void gen_opcode (unsigned long int opcode)
                        need_endlabel = 1;
                }
                addcycles000 (2);
+               addcycles_ce020 (7);
                if (using_ce020 == 1) {
                        printf ("\tm68k_do_bsr_ce020 (m68k_getpc () + %d, s);\n", m68k_pc_offset);
                } else if (using_ce020 == 2) {
@@ -2820,13 +2914,15 @@ static void gen_opcode (unsigned long int opcode)
                }
                if (using_prefetch) {
                        incpc ("(uae_s32)src + 2");
-                       fill_prefetch_full ();
+                       fill_prefetch_full_000 ();
                        if (using_ce)
                                printf ("\treturn;\n");
                        else
                                printf ("\treturn 10 * CYCLE_UNIT / 2;\n");
                } else {
                        incpc ("(uae_s32)src + 2");
+                       addcycles_ce020 (6);
+                       fill_prefetch_full_020 ();
                        returncycles ("\t", 10);
                }
                printf ("didnt_jump:;\n");
@@ -2835,12 +2931,15 @@ static void gen_opcode (unsigned long int opcode)
                if (curi->size == sz_byte) {
                        addcycles000 (2);
                        irc2ir ();
+                       addcycles_ce020 (4);
                        fill_prefetch_2 ();
                } else if (curi->size == sz_word) {
                        addcycles000 (2);
-                       fill_prefetch_full ();
+                       addcycles_ce020 (6);
+                       fill_prefetch_full_000 ();
                } else {
-                       fill_prefetch_full ();
+                       addcycles_ce020 (6);
+                       fill_prefetch_full_000 ();
                }
                insn_n_cycles = curi->size == sz_byte ? 8 : 12;
                break;
@@ -2852,11 +2951,13 @@ static void gen_opcode (unsigned long int opcode)
                fill_prefetch_next ();
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000 (2);
+               addcycles_ce020 (2);
                genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
                break;
        case i_PEA:
                genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
                genamode (Apdi, "7", sz_long, "dst", 2, 0, GF_AA);
+               addcycles_ce020 (5);
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000 (2);
                if (!(curi->smode == absw || curi->smode == absl))
@@ -2874,11 +2975,12 @@ static void gen_opcode (unsigned long int opcode)
                addcycles000 (2);
                printf ("\tif (!cctrue (%d)) {\n", curi->cc);
                incpc ("(uae_s32)offs + 2");
-               printf ("\t"); fill_prefetch_1 (0);
-               printf ("\t"); genastore ("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+               printf ("\t");
+               fill_prefetch_1 (0);
+               printf ("\t");
+               genastore ("(src - 1)", curi->smode, "srcreg", curi->size, "src");
 
                printf ("\t\tif (src) {\n");
-               addcycles_ce020 (4);
                if (using_exception_3) {
                        printf ("\t\t\tif (offs & 1) {\n");
                        printf ("\t\t\t\texception3i (opcode, m68k_getpc () + 2 + (uae_s32)offs + 2);\n");
@@ -2887,19 +2989,22 @@ static void gen_opcode (unsigned long int opcode)
                        need_endlabel = 1;
                }
                irc2ir ();
+               addcycles_ce020 (6);
                fill_prefetch_1 (2);
+               fill_prefetch_full_020 ();
                returncycles ("\t\t\t", 12);
                if (using_ce)
                        printf ("\t\t\treturn;\n");
                printf ("\t\t}\n");
-               addcycles_ce020 (8);
+               addcycles_ce020 (10);
                printf ("\t} else {\n");
+               // cc == true
                addcycles000_2 ("\t\t", 2);
-               addcycles_ce020 (4);
+               addcycles_ce020 (6);
                printf ("\t}\n");
                setpc ("oldpc + %d", m68k_pc_offset);
                m68k_pc_offset = 0;
-               fill_prefetch_full ();
+               fill_prefetch_full_000 ();
                insn_n_cycles = 12;
                need_endlabel = 1;
                break;
@@ -2908,6 +3013,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
                start_brace ();
                fill_prefetch_next();
+               addcycles_ce020 (isreg (curi->smode) ? 4 : 6);
                start_brace ();
                printf ("\tint val = cctrue (%d) ? 0xff : 0;\n", curi->cc);
                if (using_ce) {
@@ -2937,7 +3043,7 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t\tint cycles = (getDivu68kCycles((uae_u32)dst, (uae_u16)src));\n");
                        addcycles000_3 ("\t\t");
                } else if (using_ce020) {
-                       addcycles_ce020 (36);
+                       addcycles_ce020 (44);
                }
                /* The N flag appears to be set each time there is an overflow.
                * Weird. but 68020 only sets N when dst is negative.. */
@@ -2977,7 +3083,7 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src));\n");
                        addcycles000_3 ("\t\t");
                } else if (using_ce020) {
-                       addcycles_ce020 (46);
+                       addcycles_ce020 (56);
                }
                printf ("\tif (dst == 0x80000000 && src == -1) {\n");
                printf ("\t\tSET_VFLG (1);\n");
@@ -3019,7 +3125,7 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t\tif (src & 1) cycles += 2;\n");
                        addcycles000_3 ("\t");
                } else if (using_ce020) {
-                       addcycles_ce020 (20);
+                       addcycles_ce020 (27);
                }
                genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
                sync_m68k_pc ();
@@ -3044,7 +3150,7 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t\tif ((usrc & 3) == 1 || (usrc & 3) == 2) cycles += 2;\n");
                        addcycles000_3 ("\t");
                } else if (using_ce020) {
-                       addcycles_ce020 (20);
+                       addcycles_ce020 (27);
                }
                genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
                count_cycles += 38 - 4;
@@ -3099,6 +3205,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ASR:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (6);
                fill_prefetch_next();
                start_brace ();
                switch (curi->size) {
@@ -3135,6 +3242,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ASL:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (8);
                fill_prefetch_next();
                start_brace ();
                switch (curi->size) {
@@ -3174,6 +3282,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_LSR:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (source_is_imm1_8 (curi) ? 4 : 6);
                fill_prefetch_next();
                start_brace ();
                switch (curi->size) {
@@ -3206,6 +3315,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_LSL:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (source_is_imm1_8 (curi) ? 4 : 6);
                fill_prefetch_next();
                start_brace ();
                switch (curi->size) {
@@ -3238,6 +3348,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ROL:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (8);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3268,6 +3379,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ROR:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (8);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3298,6 +3410,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ROXL:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (12);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3331,6 +3444,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_ROXR:
                genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (12);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3366,6 +3480,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_ASRW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (5);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3384,6 +3499,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_ASLW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (6);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3399,12 +3515,12 @@ static void gen_opcode (unsigned long int opcode)
                printf ("\tsign2 = %s & val;\n", cmask (curi->size));
                printf ("\tSET_CFLG (sign != 0);\n");
                duplicate_carry (0);
-
                printf ("\tSET_VFLG (GET_VFLG () | (sign2 != sign));\n");
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
                break;
        case i_LSRW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (5);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3422,6 +3538,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_LSLW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (5);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3439,6 +3556,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_ROLW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (7);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3456,6 +3574,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_RORW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (7);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3473,6 +3592,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_ROXLW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (5);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3491,6 +3611,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_ROXRW:
                genamode (curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
+               addcycles_ce020 (5);
                fill_prefetch_next ();
                start_brace ();
                switch (curi->size) {
@@ -3510,6 +3631,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_MOVEC2:
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                fill_prefetch_next ();
+               addcycles_ce020 (6);
                start_brace ();
                printf ("\tint regno = (src >> 12) & 15;\n");
                printf ("\tuae_u32 *regp = regs.regs + regno;\n");
@@ -3518,6 +3640,7 @@ static void gen_opcode (unsigned long int opcode)
        case i_MOVE2C:
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                fill_prefetch_next ();
+               addcycles_ce020 (12);
                start_brace ();
                printf ("\tint regno = (src >> 12) & 15;\n");
                printf ("\tuae_u32 *regp = regs.regs + regno;\n");
@@ -3667,7 +3790,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
                if (using_ce020) {
-                       addcycles_ce020 (70);
+                       addcycles_ce020 (70 / 3);
                }
                sync_m68k_pc ();
                printf ("\tm68k_divl(opcode, dst, extra);\n");
@@ -3676,7 +3799,7 @@ static void gen_opcode (unsigned long int opcode)
                genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
                if (using_ce020) {
-                       addcycles_ce020 (40);
+                       addcycles_ce020 (40 / 3);
                }
                sync_m68k_pc ();
                printf ("\tm68k_mull(opcode, dst, extra);\n");
@@ -3816,6 +3939,7 @@ static void gen_opcode (unsigned long int opcode)
                genflags (flag_logical, curi->size, "src", "", "");
                if (!isreg (curi->smode))
                        addcycles000 (2);
+               addcycles_ce020 (isreg (curi->smode) ? 4 : 12);
                fill_prefetch_next ();
                printf ("\tsrc |= 0x80;\n");
                if (cpu_level >= 2 || curi->smode == Dreg || !using_ce) {
@@ -3977,8 +4101,8 @@ static void gen_opcode (unsigned long int opcode)
        }
        if (did_prefetch >= 0)
                fill_prefetch_finish ();
-       if (!count_cycles)
-               addcycles_ce020 (2);
+//     if (!count_cycles)
+//             addcycles_ce020 (2);
        sync_m68k_pc ();
        did_prefetch = 0;
 }
@@ -4339,12 +4463,14 @@ static void generate_cpu (int id, int mode)
        } else if (id == 21) { // 68020 cycle-exact
                cpu_level = 2;
                using_ce020 = 1;
+               using_prefetch_020 = 2;
                read_counts ();
                for (rp = 0; rp < nr_cpuop_funcs; rp++)
                        opcode_next_clev[rp] = cpu_level;
        } else if (id == 22 || id == 23 || id == 24) { // 68030/040/60 "cycle-exact"
                cpu_level = 3 + (24 - id);
                using_ce020 = 2;
+               using_prefetch_020 = 2;
                if (id == 22) {
                        read_counts ();
                        for (rp = 0; rp < nr_cpuop_funcs; rp++)
index b14c0f5e9875d7f06ee5f11a12cf9927c0f6ee31..89e1c4438e68651926cf0d3fb0c9341141cd7b0c 100644 (file)
 #define MEMDEBUG 0
 #define MEMDEBUGMASK 0x7fffff
 #define MEMDEBUGTEST 0x280000
-
+#define PICASSOIV_DEBUG_IO 0
 
 #include "sysconfig.h"
 #include "sysdeps.h"
 
 #include "options.h"
+#include "uae.h"
 #include "memory.h"
 #include "debug.h"
 #include "custom.h"
 #define BOARD_MODEL_REGISTERS_PICASSOIV 23
 #define PICASSOIV_REG  0x00600000
 #define PICASSOIV_IO   0x00200000
-#define PICASSOIV_VRAM 0x01000000
+#define PICASSOIV_VRAM1 0x01000000
+#define PICASSOIV_VRAM2 0x00800000
 #define PICASSOIV_ROM_OFFSET 0x0200
 #define PICASSOIV_FLASH_OFFSET 0x8000
 #define PICASSOIV_FLASH_BANK 0x8000
 #define PICASSOIV_MAX_FLASH (GFXBOARD_AUTOCONFIG_SIZE - 32768)
 
+#define PICASSOIV_BANK_UNMAPFLASH 2
+#define PICASSOIV_BANK_MAPRAM 4
+#define PICASSOIV_BANK_FLASHBANK 128
+
+#define PICASSOIV_INT_VBLANK 128
+
 #define BOARD_MANUFACTURER_PICCOLO 2195
 #define BOARD_MODEL_MEMORY_PICCOLO 5
 #define BOARD_MODEL_REGISTERS_PICCOLO 6
@@ -78,7 +86,10 @@ struct gfxboard
        bool swap;
 };
 
-#define PICASSOIV 11
+#define PICASSOIV_Z2 10
+#define PICASSOIV_Z3 11
+
+#define ISP4() (currprefs.rtgmem_type == PICASSOIV_Z2 || currprefs.rtgmem_type == PICASSOIV_Z3)
 
 static struct gfxboard boards[] =
 {
@@ -95,12 +106,12 @@ static struct gfxboard boards[] =
        {
                _T("Piccolo Zorro II"),
                BOARD_MANUFACTURER_PICCOLO, BOARD_MODEL_MEMORY_PICCOLO, BOARD_MODEL_REGISTERS_PICCOLO,
-               0x00000000, 0x00100000, 0x00200000, 0x00400000, CIRRUS_ID_CLGD5426, false, 6, true
+               0x00000000, 0x00100000, 0x00200000, 0x00200000, CIRRUS_ID_CLGD5426, false, 6, true
        },
        {
                _T("Piccolo Zorro III"),
                BOARD_MANUFACTURER_PICCOLO, BOARD_MODEL_MEMORY_PICCOLO, BOARD_MODEL_REGISTERS_PICCOLO,
-               0x00000000, 0x00100000, 0x00200000, 0x00400000, CIRRUS_ID_CLGD5426, true, 6, true
+               0x00000000, 0x00100000, 0x00200000, 0x00200000, CIRRUS_ID_CLGD5426, true, 6, true
        },
        {
                _T("Piccolo SD64 Zorro II"),
@@ -120,18 +131,18 @@ static struct gfxboard boards[] =
        {
                _T("Spectrum 28/24 Zorro III"),
                BOARD_MANUFACTURER_SPECTRUM, BOARD_MODEL_MEMORY_SPECTRUM, BOARD_MODEL_REGISTERS_SPECTRUM,
-               0x00000000, 0x00100000, 0x00200000, 0x01000000, CIRRUS_ID_CLGD5428, true, 6, true
+               0x00000000, 0x00100000, 0x00200000, 0x00200000, CIRRUS_ID_CLGD5428, true, 6, true
        },
        {
                _T("Picasso IV Zorro II"),
                BOARD_MANUFACTURER_PICASSO, BOARD_MODEL_MEMORY_PICASSOIV, BOARD_MODEL_REGISTERS_PICASSOIV,
-               0x00000000, 0x00400000, 0x00400000, 0x00400000, CIRRUS_ID_CLGD5446, false, 6, true
+               0x00000000, 0x00400000, 0x00400000, 0x00400000, CIRRUS_ID_CLGD5446, false, 2, false
        },
        {
                // REG:00600000 IO:00200000 VRAM:01000000
                _T("Picasso IV Zorro III"),
                BOARD_MANUFACTURER_PICASSO, BOARD_MODEL_MEMORY_PICASSOIV, 0,
-               0x00000000, 0x00400000, 0x00400000, 0x04000000, CIRRUS_ID_CLGD5446, true, 6, true
+               0x00000000, 0x00400000, 0x00400000, 0x04000000, CIRRUS_ID_CLGD5446, true, 2, false
        }
 };
 
@@ -141,7 +152,14 @@ static struct gfxboard *board;
 static uae_u32 memory_mask;
 
 static uae_u8 *automemory;
-static int picassoiv_bank;
+
+static uae_u8 picassoiv_bank, picassoiv_flifi;
+static uae_u8 p4autoconfig[256];
+static struct zfile *p4rom;
+static bool p4z2;
+static uae_u32 p4_mmiobase;
+static uae_u32 p4_special_mask;
+
 static CirrusVGAState vga;
 static uae_u8 *vram;
 static uae_u32 gfxboardmem_start;
@@ -157,16 +175,14 @@ static hwaddr vram_offset[2];
 
 static uae_u32 vgaioregionptr, vgavramregionptr, vgabank0regionptr, vgabank1regionptr;
 
-static const MemoryRegionOps *vgaio, *vgaram, *vgalowram;
+static const MemoryRegionOps *vgaio, *vgaram, *vgalowram, *vgammio;
 static MemoryRegion vgaioregion, vgavramregion;
 
 static void init_board (void)
 {
-       int vramsize = board->vrammax;
+       int vramsize = currprefs.rtgmem_size;
        xfree (fakesurface_surface);
        fakesurface_surface = xmalloc (uae_u8, 4 * 10000);
-       if (currprefs.rtgmem_type == PICASSOIV)
-               vramsize = 16 * 1024 * 1024;
        vram_offset[0] = vram_offset[1] = 0;
        vram_enabled = true;
        vram_offset_enabled = false;
@@ -191,9 +207,13 @@ bool gfxboard_toggle (int mode)
                picasso_requested_on = 0;
                return true;
        } else {
-               monswitch = true;
-               picasso_requested_on = 1;
-               return true;
+               int width, height;
+               vga.vga.get_resolution (&vga.vga, &width, &height);
+               if (width > 16 && height > 16) {
+                       monswitch = true;
+                       picasso_requested_on = 1;
+                       return true;
+               }
        }
        return false;
 }
@@ -344,13 +364,15 @@ void gfxboard_vsync_handler (void)
                gfx_unlock_picasso (true);
        gfxboard_surface = NULL;
 
-       // Vertical Sync End Register, 0x10 = Clear Vertical Interrupt.
-       if (board->irq && gfxboard_intena && (vga.vga.cr[0x11] & 0x10)) {
-               gfxboard_vblank = true;
-               if (board->irq == 2)
-                       INTREQ (0x8000 | 0x0008);
-               else
-                       INTREQ (0x8000 | 0x2000);
+       // Vertical Sync End Register, 0x20 = Disable Vertical Intgerrupt, 0x10 = Clear Vertical Interrupt.
+       if (board->irq && (!(vga.vga.cr[0x11] & 0x20) && (vga.vga.cr[0x11] & 0x10) && !(vga.vga.gr[0x17] & 4))) {
+               if (gfxboard_intena) {
+                       gfxboard_vblank = true;
+                       if (board->irq == 2)
+                               INTREQ (0x8000 | 0x0008);
+                       else
+                               INTREQ (0x8000 | 0x2000);
+               }
        }
 
 }
@@ -457,30 +479,48 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
        reset_func (reset_parm);
 }
 
+static void picassoiv_checkswitch (void)
+{
+       if (ISP4()) {
+               monswitch = (picassoiv_flifi & 1) == 0 && (vga.vga.cr[0x51] & 8) == 0;
+       }
+}
+
 static void bput_regtest (uaecptr addr, uae_u8 v)
 {
        addr += 0x3b0;
-       if ((addr == 0x3b5 || addr == 0x3c5) && vga.vga.cr_index == 0x11) {
-               if (!(vga.vga.cr[0x11] & 0x10))
-                       gfxboard_vblank = false;
+       if (addr == 0x3d5) { // CRxx
+               if (vga.vga.cr_index == 0x11) {
+                       if (!(vga.vga.cr[0x11] & 0x10)) {
+                               gfxboard_vblank = false;
+                       }
+               }
        }
        if (!(vga.vga.sr[0x07] & 0x01) && vram_enabled) {
                remap_vram (vram_offset[0], vram_offset[1], false);
        }
+       picassoiv_checkswitch ();
 }
 
 static uae_u8 bget_regtest (uaecptr addr, uae_u8 v)
 {
        addr += 0x3b0;
-       if (gfxboard_vblank) {
-               // Input Status 0
-               if (addr == 0x3c2) {
+       // Input Status 0
+       if (addr == 0x3c2) {
+               if (gfxboard_vblank) {
                        // Disable Vertical Interrupt == 0?
                        // Clear Vertical Interrupt == 1
-                       if (!(vga.vga.cr[0x11] & 0x20) && (vga.vga.cr[0x11] & 0x10)) {
-                               v |= 0x80; // interrupt pending
+                       // GR17 bit 2 = INTR disable
+                       if (!(vga.vga.cr[0x11] & 0x20) && (vga.vga.cr[0x11] & 0x10) && !(vga.vga.gr[0x17] & 4)) {
+                               v |= 0x80; // VGA Interrupt Pending
                        }
                }
+               v |= 0x10; // DAC sensing
+       }
+       if (addr == 0x3c5) {
+               if (vga.vga.sr_index == 8) {
+                       // TODO: DDC
+               }
        }
        return v;
 }
@@ -514,6 +554,8 @@ void memory_region_init_io(MemoryRegion *mr,
                vgaram = ops;
        } else if (!stricmp (name, "cirrus-low-memory")) {
                vgalowram = ops;
+       } else if (!stricmp (name, "cirrus-mmio")) {
+               vgammio = ops;
        }
 }
 
@@ -522,7 +564,6 @@ int is_surface_bgr(DisplaySurface *surface)
        return board->swap;
 }
 
-
 static uaecptr fixaddr (uaecptr addr, int mask)
 {
 #ifdef JIT
@@ -714,11 +755,14 @@ static void REGPARAM2 gfxboard_wput_mem_autoconfig (uaecptr addr, uae_u32 b)
                gfxboard_bank_memory.bget = gfxboard_bget_mem;
                gfxboard_bank_memory.bput = gfxboard_bput_mem;
                gfxboard_bank_memory.wput = gfxboard_wput_mem;
-               if (currprefs.rtgmem_type == PICASSOIV) {
-                       map_banks (&gfxboard_bank_memory, (gfxmem_bank.start + PICASSOIV_VRAM) >> 16, (board->banksize - PICASSOIV_VRAM) >> 16, currprefs.rtgmem_size);
-                       map_banks (&gfxboard_bank_registers, (gfxmem_bank.start + PICASSOIV_REG) >> 16, BOARD_REGISTERS_SIZE >> 16, BOARD_REGISTERS_SIZE);
-                       map_banks (&gfxboard_bank_special, gfxmem_bank.start >> 16, (PICASSOIV_FLASH_BANK * 4) >> 16, PICASSOIV_FLASH_BANK * 4);
+               if (ISP4()) {
+                       map_banks (&gfxboard_bank_memory, (gfxmem_bank.start + PICASSOIV_VRAM1) >> 16, currprefs.rtgmem_size >> 16, currprefs.rtgmem_size);
+                       map_banks (&gfxboard_bank_memory, (gfxmem_bank.start + PICASSOIV_VRAM2) >> 16, currprefs.rtgmem_size >> 16, currprefs.rtgmem_size);
+                       map_banks (&gfxboard_bank_registers, (gfxmem_bank.start + PICASSOIV_REG) >> 16, 0x200000 >> 16, BOARD_REGISTERS_SIZE);
+                       map_banks (&gfxboard_bank_special, gfxmem_bank.start >> 16, PICASSOIV_REG >> 16, PICASSOIV_REG);
                        picassoiv_bank = 0;
+                       picassoiv_flifi = 1;
+                       configured_regs = gfxmem_bank.start >> 16;
                        init_board ();
                } else {
                        map_banks (&gfxboard_bank_memory, gfxmem_bank.start >> 16, board->banksize >> 16, currprefs.rtgmem_size);
@@ -737,7 +781,6 @@ static void REGPARAM2 gfxboard_wput_mem_autoconfig (uaecptr addr, uae_u32 b)
        }
 }
 
-
 static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b)
 {
 #ifdef JIT
@@ -747,13 +790,24 @@ static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b)
        addr &= 65535;
        if (addr == 0x48) {
                if (!board->z3) {
-                       gfxboard_bank_memory.bget = gfxboard_bget_mem;
-                       gfxboard_bank_memory.bput = gfxboard_bput_mem;
-                       map_banks (&gfxboard_bank_memory, b, board->banksize >> 16, currprefs.rtgmem_size);
-                       write_log (_T("%s autoconfigured at 0x00%02X0000\n"), gfxboard_bank_memory.name, b);
-                       configured_mem = b;
-                       gfxboardmem_start = b << 16;
+                       if (ISP4()) {
+                               map_banks (&gfxboard_bank_memory, b, 0x00200000 >> 16, 0x00200000);
+                               if (configured_mem == 0) {
+                                       configured_mem = b;
+                                       gfxboardmem_start = b << 16;
+                               } else {
+                                       gfxboard_bank_memory.bget = gfxboard_bget_mem;
+                                       gfxboard_bank_memory.bput = gfxboard_bput_mem;
+                               }
+                       } else {
+                               gfxboard_bank_memory.bget = gfxboard_bget_mem;
+                               gfxboard_bank_memory.bput = gfxboard_bput_mem;
+                               map_banks (&gfxboard_bank_memory, b, board->banksize >> 16, currprefs.rtgmem_size);
+                               configured_mem = b;
+                               gfxboardmem_start = b << 16;
+                       }
                        expamem_next ();
+                       write_log (_T("%s autoconfigured at 0x00%02X0000\n"), gfxboard_bank_memory.name, b);
                }
                return;
        }
@@ -858,8 +912,16 @@ static void REGPARAM2 gfxboard_lput_regs (uaecptr addr, uae_u32 l)
 #endif
        //write_log (_T("GFX LONG PUT IO %04X = %04X\n"), addr & 65535, l);
        addr = mungeaddr (addr, true);
-       if (addr)
-               vgaio->write (&vga, addr, l, 4);
+       if (addr) {
+               vgaio->write (&vga, addr + 0, (l >> 24) & 0xff, 1);
+               bput_regtest (addr + 0, (l >> 24));
+               vgaio->write (&vga, addr + 1, (l >> 16) & 0xff, 1);
+               bput_regtest (addr + 0, (l >> 16));
+               vgaio->write (&vga, addr + 2, (l >>  8) & 0xff, 1);
+               bput_regtest (addr + 0, (l >>  8));
+               vgaio->write (&vga, addr + 3, (l >>  0) & 0xff, 1);
+               bput_regtest (addr + 0, (l >>  0));
+       }
 }
 static void REGPARAM2 gfxboard_wput_regs (uaecptr addr, uae_u32 w)
 {
@@ -870,9 +932,9 @@ static void REGPARAM2 gfxboard_wput_regs (uaecptr addr, uae_u32 w)
        addr = mungeaddr (addr, true);
        if (addr) {
                vgaio->write (&vga, addr + 0, (w >> 8) & 0xff, 1);
-               bput_regtest (addr + 0, (w >> 8) & 0xff);
+               bput_regtest (addr + 0, (w >> 8));
                vgaio->write (&vga, addr + 1, (w >> 0) & 0xff, 1);
-               bput_regtest (addr + 1, (w >> 0) & 0xff);
+               bput_regtest (addr + 1, (w >> 0));
        }
 }
 static void REGPARAM2 gfxboard_bput_regs (uaecptr addr, uae_u32 b)
@@ -934,7 +996,11 @@ static void REGPARAM2 gfxboard_bput_regs_autoconfig (uaecptr addr, uae_u32 b)
        if (addr == 0x48) {
                gfxboard_bank_registers.bget = gfxboard_bget_regs;
                gfxboard_bank_registers.bput = gfxboard_bput_regs;
-               map_banks (&gfxboard_bank_registers, b, BOARD_REGISTERS_SIZE >> 16, BOARD_REGISTERS_SIZE);
+               if (p4z2) {
+                       map_banks (&gfxboard_bank_special, b, gfxboard_bank_special.allocated >> 16, gfxboard_bank_special.allocated);
+               } else {
+                       map_banks (&gfxboard_bank_registers, b, gfxboard_bank_registers.allocated >> 16, gfxboard_bank_registers.allocated);
+               }
                write_log (_T("%s autoconfigured at 0x00%02X0000\n"), gfxboard_bank_registers.name, b);
                configured_regs = b;
                init_board ();
@@ -949,18 +1015,6 @@ static void REGPARAM2 gfxboard_bput_regs_autoconfig (uaecptr addr, uae_u32 b)
        }
 }
 
-static void ew (int addr, uae_u32 value)
-{
-       addr &= 0xffff;
-       if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
-               automemory[addr] = (value & 0xf0);
-               automemory[addr + 2] = (value & 0x0f) << 4;
-       } else {
-               automemory[addr] = ~(value & 0xf0);
-               automemory[addr + 2] = ~((value & 0x0f) << 4);
-       }
-}
-
 void gfxboard_reset (void)
 {
        if (currprefs.rtgmem_type >= GFXBOARD_HARDWARE) {
@@ -981,6 +1035,7 @@ void gfxboard_reset (void)
        modechanged = false;
        gfxboard_vblank = false;
        gfxboard_intena = false;
+       picassoiv_bank = 0;
        if (board) {
                if (board->z3)
                        gfxboard_bank_memory.wput = gfxboard_wput_mem_autoconfig;
@@ -1006,17 +1061,51 @@ addrbank gfxboard_bank_registers = {
 
 static uae_u32 REGPARAM2 gfxboards_lget_regs (uaecptr addr)
 {
-       uae_u32 v = 0xffffffff;
+       uae_u32 v = 0;
 #ifdef JIT
        special_mem |= S_READ;
+#endif
+       addr &= p4_special_mask;
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       v  = vgammio->read(&vga, addr2 + 0, 1) << 24;
+                       v |= vgammio->read(&vga, addr2 + 1, 1) << 16;
+                       v |= vgammio->read(&vga, addr2 + 2, 1) <<  8;
+                       v |= vgammio->read(&vga, addr2 + 3, 1) <<  0;
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO LGET %08x %08x\n"), addr, v);
+#endif
+                       return v;
+               }
+       }
+#if PICASSOIV_DEBUG_IO
+       write_log (_T("PicassoIV LGET %08x %08x\n"), addr, v);
 #endif
        return v;
 }
 static uae_u32 REGPARAM2 gfxboards_wget_regs (uaecptr addr)
 {
-       uae_u16 v = 0xffff;
+       uae_u16 v = 0;
 #ifdef JIT
        special_mem |= S_READ;
+#endif
+       addr &= p4_special_mask;
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       v  = vgammio->read(&vga, addr2 + 0, 1) << 8;
+                       v |= vgammio->read(&vga, addr2 + 1, 1) << 0;
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO WGET %08x %04x\n"), addr, v & 0xffff);
+#endif
+                       return v;
+               }
+       }
+#if PICASSOIV_DEBUG_IO
+       write_log (_T("PicassoIV WGET %04x %04x\n"), addr, v);
 #endif
        return v;
 }
@@ -1026,10 +1115,57 @@ static uae_u32 REGPARAM2 gfxboards_bget_regs (uaecptr addr)
 #ifdef JIT
        special_mem |= S_READ;
 #endif
-       addr &= 0x1ffff;
-       if (picassoiv_bank) {
-               write_log (_T("PicassoIV bget %08x\n"), addr);
-               return 0;
+       addr &= p4_special_mask;
+
+       // pci config
+       if (addr >= 0x400000 || (p4z2 && (picassoiv_bank & PICASSOIV_BANK_UNMAPFLASH) && ((addr >= 0x800 && addr < 0xc00) || (addr >= 0x1000 && addr < 0x2000)))) {
+               v = 0;
+               addr &= 0xffff;
+               if (addr == 0x802)
+                       v = 2; // ???
+               if (addr == 0x808)
+                       v = 4; // bridge revision
+#if PICASSOIV_DEBUG_IO
+               write_log (_T("PicassoIV PCI BGET %08x %02x\n"), addr, v);
+#endif
+               return v;
+       }
+
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       v = vgammio->read(&vga, addr2, 1);
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO BGET %08x %02x\n"), addr, v & 0xff);
+#endif
+                       return v;
+               }
+       }
+       if (addr == 0) {
+               v = picassoiv_bank;
+               return v;
+       }
+       if (picassoiv_bank & PICASSOIV_BANK_UNMAPFLASH) {
+               v = 0;
+               if (addr == 0x404) {
+                       v = 0x7c; // FLIFI revision
+               } else if (addr == 0x408) {
+                       v = gfxboard_vblank ? 0x80 : 0;
+               } else if (p4z2 && addr >= 0x10000) {
+                       addr -= 0x10000;
+                       uaecptr addr2 = mungeaddr (addr, true);
+                       if (addr2) {
+                               v = vgaio->read (&vga, addr2, 1);
+                               v = bget_regtest (addr2, v);
+                       }
+                       //write_log (_T("PicassoIV IO %08x %02x\n"), addr, v);
+                       return v;
+               }
+#if PICASSOIV_DEBUG_IO
+               if (addr != 0x408)
+                       write_log (_T("PicassoIV BGET %08x %02x\n"), addr, v);
+#endif
        } else {
                if (addr < PICASSOIV_FLASH_OFFSET) {
                        v = automemory[addr];
@@ -1037,35 +1173,117 @@ static uae_u32 REGPARAM2 gfxboards_bget_regs (uaecptr addr)
                }
                addr -= PICASSOIV_FLASH_OFFSET;
                addr /= 2;
-               v = automemory[addr + PICASSOIV_FLASH_OFFSET];
-               return v;
+               v = automemory[addr + PICASSOIV_FLASH_OFFSET + ((picassoiv_bank & PICASSOIV_BANK_FLASHBANK) ? 0x8000 : 0)];
        }
+       return v;
 }
 static void REGPARAM2 gfxboards_lput_regs (uaecptr addr, uae_u32 l)
 {
 #ifdef JIT
        special_mem |= S_WRITE;
+#endif
+       addr &= p4_special_mask;
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO LPUT %08x %08x\n"), addr, l);
+#endif
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       vgammio->write(&vga, addr2 + 0, l >> 24, 1);
+                       vgammio->write(&vga, addr2 + 1, l >> 16, 1);
+                       vgammio->write(&vga, addr2 + 2, l >>  8, 1);
+                       vgammio->write(&vga, addr2 + 3, l >>  0, 1);
+                       return;
+               }
+       }
+#if PICASSOIV_DEBUG_IO
+       write_log (_T("PicassoIV LPUT %08x %08x\n"), addr, l);
 #endif
 }
 static void REGPARAM2 gfxboards_wput_regs (uaecptr addr, uae_u32 w)
 {
 #ifdef JIT
        special_mem |= S_WRITE;
+#endif
+       addr &= p4_special_mask;
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO LPUT %08x %08x\n"), addr, w & 0xffff);
+#endif
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       vgammio->write(&vga, addr2 + 0, w >>  8, 1);
+                       vgammio->write(&vga, addr2 + 1, w >>  0, 1);
+                       return;
+               }
+       }
+       if (p4z2 && addr >= 0x10000) {
+               addr -= 0x10000;
+               addr = mungeaddr (addr, true);
+               if (addr) {
+                       vgaio->write (&vga, addr + 0, (w >> 8) & 0xff, 1);
+                       bput_regtest (addr + 0, w >> 8);
+                       vgaio->write (&vga, addr + 1, (w >> 0) & 0xff, 1);
+                       bput_regtest (addr + 1, w >> 0);
+               }
+               return;
+       }
+#if PICASSOIV_DEBUG_IO
+       write_log (_T("PicassoIV WPUT %08x %04x\n"), addr, w & 0xffff);
 #endif
 }
+
 static void REGPARAM2 gfxboards_bput_regs (uaecptr addr, uae_u32 b)
 {
 #ifdef JIT
        special_mem |= S_WRITE;
 #endif
-       write_log (_T("PicassoIV bput %08x %02X\n"), addr, b & 0xff);
-       if ((addr & 65535) == 0)
+       addr &= p4_special_mask;
+       if (addr >= 0x400000 || (p4z2 && (picassoiv_bank & PICASSOIV_BANK_UNMAPFLASH) && ((addr >= 0x800 && addr < 0xc00) || (addr >= 0x1000 && addr < 0x2000)))) {
+#if PICASSOIV_DEBUG_IO
+               write_log (_T("PicassoIV PCI BPUT %08x %02X\n"), addr, b & 0xff);
+#endif
+               return;
+       }
+       if (picassoiv_bank & PICASSOIV_BANK_UNMAPFLASH) {
+               if (addr == 0x404) {
+                       picassoiv_flifi = b;
+                       picassoiv_checkswitch ();
+               }
+       }
+       if (picassoiv_bank & PICASSOIV_BANK_MAPRAM) {
+               // memory mapped io
+               if (addr >= p4_mmiobase && addr < p4_mmiobase + 0x8000) {
+#if PICASSOIV_DEBUG_IO
+                       write_log (_T("PicassoIV MMIO BPUT %08x %08x\n"), addr, b & 0xff);
+#endif
+                       uae_u32 addr2 = addr - p4_mmiobase;
+                       vgammio->write(&vga, addr2, b, 1);
+                       return;
+               }
+       }
+       if (p4z2 && addr >= 0x10000) {
+               addr -= 0x10000;
+               addr = mungeaddr (addr, true);
+               if (addr) {
+                       vgaio->write (&vga, addr, b & 0xff, 1);
+                       bput_regtest (addr, b);
+               }
+               return;
+       }
+#if PICASSOIV_DEBUG_IO
+       write_log (_T("PicassoIV BPUT %08x %02X\n"), addr, b & 0xff);
+#endif
+       if (addr == 0) {
                picassoiv_bank = b;
+       }
 }
 addrbank gfxboard_bank_special = {
        gfxboards_lget_regs, gfxboards_wget_regs, gfxboards_bget_regs,
        gfxboards_lput_regs, gfxboards_wput_regs, gfxboards_bput_regs,
-       default_xlate, default_check, NULL, _T("Picasso IV Flash"),
+       default_xlate, default_check, NULL, _T("Picasso IV"),
        dummy_lgeti, dummy_wgeti, ABFLAG_IO | ABFLAG_SAFE
 };
 bool gfxboard_is_z3 (int type)
@@ -1111,11 +1329,75 @@ bool gfxboard_is_registers (int type)
        return board->model_registers != 0;
 }
 
+int gfxboard_num_boards (int type)
+{
+       if (type < 2)
+               return 1;
+       board = &boards[type - 2];
+       if (type == PICASSOIV_Z2)
+               return 3;
+       if (board->model_registers == 0)
+               return 1;
+       return 2;
+}
+
+
 static void gfxboard_init (void)
 {
        if (!automemory)
                automemory = xmalloc (uae_u8, GFXBOARD_AUTOCONFIG_SIZE);
        memset (automemory, 0xff, GFXBOARD_AUTOCONFIG_SIZE);
+       p4z2 = false;
+       zfile_fclose (p4rom);
+       p4rom = NULL;
+}
+
+static void copyp4autoconfig (int startoffset)
+{
+       int size = 0;
+       int offset = 0;
+       memset (automemory, 0xff, 64);
+       while (size < 32) {
+               uae_u8 b = p4autoconfig[size + startoffset];
+               automemory[offset] = b;
+               offset += 2;
+               size++;
+       }
+}
+
+static void loadp4rom (void)
+{
+       int size, offset;
+       uae_u8 b;
+       // rom loader code
+       zfile_fseek (p4rom, 256, SEEK_SET);
+       offset = PICASSOIV_ROM_OFFSET;
+       size = 0;
+       while (size < 4096 - 256) {
+               if (!zfile_fread (&b, 1, 1, p4rom))
+                       break;
+               automemory[offset] = b;
+               offset += 2;
+               size++;
+       }
+       // main flash code
+       zfile_fseek (p4rom, 16384, SEEK_SET);
+       zfile_fread (&automemory[PICASSOIV_FLASH_OFFSET], 1, PICASSOIV_MAX_FLASH, p4rom);
+       zfile_fclose (p4rom);
+       p4rom = NULL;
+       write_log (_T("PICASSOIV: flash rom loaded\n"));
+}
+
+static void ew (int addr, uae_u32 value)
+{
+       addr &= 0xffff;
+       if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
+               automemory[addr] = (value & 0xf0);
+               automemory[addr + 2] = (value & 0x0f) << 4;
+       } else {
+               automemory[addr] = ~(value & 0xf0);
+               automemory[addr + 2] = ~((value & 0x0f) << 4);
+       }
 }
 
 void gfxboard_init_memory (void)
@@ -1127,8 +1409,8 @@ void gfxboard_init_memory (void)
 
        memset (automemory, 0xff, GFXBOARD_AUTOCONFIG_SIZE);
        
-       z2_flags = 0x05;
-       z3_flags = 0x06;
+       z2_flags = 0x05; // 1M
+       z3_flags = 0x06; // 1M
        bank = board->banksize;
        bank /= 0x00100000;
        while (bank > 1) {
@@ -1152,41 +1434,34 @@ void gfxboard_init_memory (void)
        ew (0x20, ser >>  8); /* ser.no. Byte 2 */
        ew (0x24, ser >>  0); /* ser.no. Byte 3 */
 
-       if (currprefs.rtgmem_type == PICASSOIV) {
-               struct zfile *rom;
-               rom = read_rom_name (_T("roms/picasso_iv_boot.rom"));
-               if (rom) {
-                       uae_u8 b;
-                       int size = 0;
-                       int offset = PICASSOIV_ROM_OFFSET;
-                       /* rom vector */
-                       type |= 0x10;
-                       ew (0x28, PICASSOIV_ROM_OFFSET >> 8);
-                       ew (0x2c, PICASSOIV_ROM_OFFSET);
-                       while (zfile_fread (&b, 1, 1, rom)) {
-                               automemory[offset] = b;
-                               automemory[offset + 2] = b << 4;
-                               offset += 4;
-                               size++;
+       ew (0x00, type);
+
+       if (ISP4()) {
+               TCHAR path[MAX_DPATH];
+               fetch_rompath (path, sizeof path / sizeof (TCHAR));
+               _tcscat (path, _T("picasso_iv_flash.rom"));
+               p4rom = read_rom_name (path);
+               if (!p4rom)
+                       p4rom = read_rom_name (_T("picasso_iv_flash.rom"));
+               if (p4rom) {
+                       zfile_fread (p4autoconfig, sizeof p4autoconfig, 1, p4rom);
+                       copyp4autoconfig (board->z3 ? 192 : 0);
+                       if (board->z3) {
+                               loadp4rom ();
+                               p4_mmiobase = 0x200000;
+                               p4_special_mask = 0x7fffff;
+                       } else {
+                               p4z2 = true;
+                               p4_mmiobase = 0x8000;
+                               p4_special_mask = 0x1ffff;
                        }
-                       zfile_fclose (rom);
-                       write_log (_T("PICASSOIV: %d byte boot rom loaded\n"), size);
+                       gfxboard_intena = true;
                } else {
-                       write_log (_T("PICASSOIV: boot rom not found\n"));
-               }
-               rom = read_rom_name (_T("roms/picasso_iv_flash_7.4.rom"));
-               if (rom) {
-                       int size;
-                       size = zfile_fread (&automemory[PICASSOIV_FLASH_OFFSET], 1, PICASSOIV_MAX_FLASH, rom);
-                       zfile_fclose (rom);
-                       write_log (_T("PICASSOIV: %d byte flash rom loaded\n"), size);
-               } else {
-                       write_log (_T("PICASSOIV: flash rom not found\n"));
+                       write_log (_T("PICASSOIV: '%s' flash rom image not found\n"), path);
+                       gui_message (_T("Couldn't load Picasso IV flash rom image:\n%s"), path);
                }
        }
 
-       ew (0x00, type);
-
        gfxboard_bank_memory.name = board->name;
        gfxboard_bank_registers.name = board->name;
 
@@ -1196,10 +1471,22 @@ void gfxboard_init_memory (void)
        map_banks (&gfxboard_bank_memory, 0xe80000 >> 16, 0x10000 >> 16, 0x10000);
 }
 
+void gfxboard_init_memory_p4_z2 (void)
+{
+       if (board->z3) {
+               expamem_next ();
+               return;
+       }
+       copyp4autoconfig (64);
+       map_banks (&gfxboard_bank_memory, 0xe80000 >> 16, 0x10000 >> 16, 0x10000);
+}
+
 void gfxboard_init_registers (void)
 {
-       if (!board->model_registers)
+       if (!board->model_registers) {
+               expamem_next ();
                return;
+       }
        memset (automemory, 0xff, GFXBOARD_AUTOCONFIG_SIZE);
        ew (0x00, 0xc0 | 0x01); // 64k Z2
        ew (0x04, board->model_registers);
@@ -1212,6 +1499,16 @@ void gfxboard_init_registers (void)
        ew (0x20, ser >>  8); /* ser.no. Byte 2 */
        ew (0x24, ser >>  0); /* ser.no. Byte 3 */
 
+       gfxboard_bank_registers.allocated = BOARD_REGISTERS_SIZE;
+
+       if (ISP4()) {
+               uae_u8 v;
+               copyp4autoconfig (128);
+               loadp4rom ();
+               v = (((automemory[0] & 0xf0) | (automemory[2] >> 4)) & 3) - 1;
+               gfxboard_bank_special.allocated = 0x10000 << v;
+       }
+
        gfxboard_bank_registers.bget = gfxboard_bget_regs_autoconfig;
        gfxboard_bank_registers.bput = gfxboard_bput_regs_autoconfig;
 
index 9cc1b81d76fb95b520ad4a546a3d78b2d8fa5f72..3dae1157363459b3c9561c453801347741d53ac2 100644 (file)
@@ -11,7 +11,7 @@ extern void CIA_vsync_prehandler (void);
 extern void CIA_hsync_prehandler (void);
 extern void CIA_hsync_posthandler (bool);
 extern void CIA_handler (void);
-extern void CIAA_tod_handler (void);
+extern void CIAA_tod_inc (int);
 extern void CIAB_tod_handler (int);
 
 extern void diskindex_handler (void);
index bd7c68fc44a3bb5326a5a34ecff9cc4b9297b310..b71c61dbddce34eeb196b967e085af6e9cecdbc6 100644 (file)
@@ -16,16 +16,16 @@ STATIC_INLINE uae_u32 get_long_prefetch (int o)
 
 extern uae_u32 get_word_020_prefetch (int);
 
-STATIC_INLINE uae_u32 next_iword_020 (void)
+STATIC_INLINE uae_u32 next_iword_020_prefetch (void)
 {
        uae_u32 r = get_word_020_prefetch (0);
        m68k_incpc (2);
        return r;
 }
-STATIC_INLINE uae_u32 next_ilong_020 (void)
+STATIC_INLINE uae_u32 next_ilong_020_prefetch (void)
 {
-       uae_u32 r = next_iword_020 () << 16;
-       r |= next_iword_020 ();
+       uae_u32 r = next_iword_020_prefetch () << 16;
+       r |= next_iword_020_prefetch ();
        return r;
 }
 
@@ -46,207 +46,23 @@ STATIC_INLINE void do_cycles_ce020 (int clocks)
 }
 STATIC_INLINE void do_cycles_ce020_mem (int clocks, uae_u32 val)
 {
-       regs.ce020memcycles -= clocks * cpucycleunit;
        x_do_cycles_post (clocks * cpucycleunit, val);
 }
 
-STATIC_INLINE void checkcycles_ce020 (void)
-{
-       if (regs.ce020memcycles > 0)
-               x_do_cycles_pre (regs.ce020memcycles);
-       regs.ce020memcycles = 0;
-}
-
-STATIC_INLINE uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
-{
-       uae_u32 v;
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               if ((addr & 3) != 0) {
-                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
-                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
-                       return v;
-               } else {
-                       return wait_cpu_cycle_read_ce020 (addr, -1);
-               }
-       case CE_MEMBANK_FAST:
-               v = get_long (addr);
-               if ((addr & 3) != 0)
-                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               else
-                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return v;
-       case CE_MEMBANK_FAST16BIT:
-               v = get_long (addr);
-               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               return v;
-       }
-       return get_long (addr);
-}
-
-STATIC_INLINE uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
-{
-       uae_u32 v;
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               if ((addr & 3) != 0) {
-                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
-                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
-                       return v;
-               } else {
-                       return wait_cpu_cycle_read_ce020 (addr, -1);
-               }
-       case CE_MEMBANK_FAST:
-               v = get_longi (addr);
-               if ((addr & 3) != 0)
-                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               else
-                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return v;
-       case CE_MEMBANK_FAST16BIT:
-               v = get_longi (addr);
-               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               return v;
-       }
-       return get_longi (addr);
-}
-
-STATIC_INLINE uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
-{
-       uae_u32 v;
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               if ((addr & 3) == 3) {
-                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
-                       v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
-                       return v;
-               } else {
-                       return wait_cpu_cycle_read_ce020 (addr, 1);
-               }
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
-               v = get_word (addr);
-               if ((addr & 3) == 3)
-                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               else
-                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return v;
-       }
-       return get_word (addr);
-}
-
-STATIC_INLINE uae_u32 mem_access_delay_wordi_read_ce020 (uaecptr addr)
-{
-       uae_u32 v;
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               return wait_cpu_cycle_read_ce020 (addr, 1);
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
-               v = get_wordi (addr);
-               do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return v;
-       }
-       return get_wordi (addr);
-}
+extern void usecycles_ce020 (int cycles);
 
-STATIC_INLINE uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
+STATIC_INLINE void resetcycles_ce020 (void)
 {
-       uae_u32 v;
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               return wait_cpu_cycle_read_ce020 (addr, 0);
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
-               v = get_byte (addr);
-               do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return v;
-
-       }
-       return get_byte (addr);
-}
-
-STATIC_INLINE void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
-{
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               wait_cpu_cycle_write_ce020 (addr, 0, v);
-               return;
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
-               put_byte (addr, v);
-               do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return;
-       }
-       put_byte (addr, v);
-}
-
-STATIC_INLINE void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
-{
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               if ((addr & 3) == 3) {
-                       wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
-                       wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
-               } else {
-                       wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
-               }
-               return;
-               break;
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
-               put_word (addr, v);
-               if ((addr & 3) == 3)
-                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               else
-                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return;
-       }
-       put_word (addr, v);
+       regs.ce020memcycles = 0;
 }
 
-STATIC_INLINE void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
-{
-       checkcycles_ce020 ();
-       switch (ce_banktype[addr >> 16])
-       {
-       case CE_MEMBANK_CHIP:
-               if ((addr & 3) == 3) {
-                       wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
-                       wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
-               } else {
-                       wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
-               }
-               return;
-               break;
-       case CE_MEMBANK_FAST:
-               put_long (addr, v);
-               if ((addr & 3) != 0)
-                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               else
-                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
-               return;
-       case CE_MEMBANK_FAST16BIT:
-               put_long (addr, v);
-               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
-               return;
-       }
-       put_long (addr, v);
-}
+void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v);
+void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v);
+void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v);
+uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr);
+uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr);
+uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr);
+uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr);
 
 STATIC_INLINE uae_u32 get_long_ce020 (uaecptr addr)
 {
@@ -297,8 +113,6 @@ STATIC_INLINE uae_u32 next_ilong_020ce (void)
        return r;
 }
 
-
-
 STATIC_INLINE void m68k_do_bsr_ce020 (uaecptr oldpc, uae_s32 offset)
 {
        m68k_areg (regs, 7) -= 4;
@@ -381,6 +195,8 @@ STATIC_INLINE void m68k_do_rts_ce030 (void)
        m68k_areg (regs, 7) += 4;
 }
 
+extern uae_u32 get_word_ce040_prefetch (int);
+
 #endif
 
 #ifdef CPUEMU_12
@@ -399,10 +215,11 @@ STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr)
 {
        switch (ce_banktype[addr >> 16])
        {
-       case CE_MEMBANK_CHIP:
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
                return wait_cpu_cycle_read (addr, 1);
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
                uae_u32 v = get_word (addr);
                x_do_cycles_post (4 * cpucycleunit, v);
                return v;
@@ -413,10 +230,11 @@ STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr)
 {
        switch (ce_banktype[addr >> 16])
        {
-       case CE_MEMBANK_CHIP:
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
                return wait_cpu_cycle_read (addr, 1);
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
                uae_u32 v = get_wordi (addr);
                x_do_cycles_post (4 * cpucycleunit, v);
                return v;
@@ -428,10 +246,11 @@ STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr)
 {
        switch (ce_banktype[addr >> 16])
        {
-       case CE_MEMBANK_CHIP:
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
                return wait_cpu_cycle_read (addr, 0);
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
                uae_u32 v = get_byte (addr);
                x_do_cycles_post (4 * cpucycleunit, v);
                return v;
@@ -442,11 +261,12 @@ STATIC_INLINE void mem_access_delay_byte_write (uaecptr addr, uae_u32 v)
 {
        switch (ce_banktype[addr >> 16])
        {
-       case CE_MEMBANK_CHIP:
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
                wait_cpu_cycle_write (addr, 0, v);
                return;
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
                put_byte (addr, v);
                x_do_cycles_post (4 * cpucycleunit, v);
                return;
@@ -457,11 +277,12 @@ STATIC_INLINE void mem_access_delay_word_write (uaecptr addr, uae_u32 v)
 {
        switch (ce_banktype[addr >> 16])
        {
-       case CE_MEMBANK_CHIP:
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
                wait_cpu_cycle_write (addr, 1, v);
                return;
-       case CE_MEMBANK_FAST:
-       case CE_MEMBANK_FAST16BIT:
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
                put_word (addr, v);
                x_do_cycles_post (4 * cpucycleunit, v);
                return;
index 06a9193b1790924d47b8c0a5f8defb861bae002d..98b8307b00d09607265ff08df1bfd816a526857f 100644 (file)
@@ -100,6 +100,7 @@ struct dma_rec
     uae_u32 addr;
     uae_u16 evt;
     int type;
+       uae_s8 intlev;
 };
 
 #define DMA_EVENT_BLITIRQ 1
index 66b2308e36645229fea2dec0655815aede001d4c..73df5264751343cffa23c2d31aba1c790a0f8990 100644 (file)
@@ -25,6 +25,7 @@ extern unsigned long start_cycles;
 extern void compute_vsynctime (void);
 extern void init_eventtab (void);
 extern void do_cycles_ce (unsigned long cycles);
+extern void do_cycles_ce020 (unsigned long cycles);
 extern void events_schedule (void);
 extern void do_cycles_slow (unsigned long cycles_to_add);
 extern void do_cycles_fast (unsigned long cycles_to_add);
index c4b2336d0e75a588ebb0a834a0785d055194f3d2..9930be903f50be82eb927bee97d0336197e87cd1 100644 (file)
@@ -3,6 +3,7 @@ extern addrbank gfxboard_bank_memory;
 extern addrbank gfxboard_bank_registers;
 
 extern void gfxboard_init_memory (void);
+extern void gfxboard_init_memory_p4_z2 (void);
 extern void gfxboard_init_registers (void);
 extern void gfxboard_free (void);
 extern void gfxboard_reset (void);
@@ -15,6 +16,7 @@ extern bool gfxboard_need_byteswap (int type);
 extern double gfxboard_get_vsync (void);
 extern void gfxboard_refresh (void);
 extern bool gfxboard_toggle (int mode);
+extern int gfxboard_num_boards (int type);
 
 #define GFXBOARD_UAE_Z2 0
 #define GFXBOARD_UAE_Z3 1
index b10d39874ada4f4ad181af2f401ab7a184e3dbfb..204a65399a3094d1a12e4d107181cc683994a784 100644 (file)
@@ -92,10 +92,11 @@ typedef struct {
        uae_u32 allocated;
 } addrbank;
 
-#define CE_MEMBANK_FAST 0
-#define CE_MEMBANK_CHIP 1
-#define CE_MEMBANK_CIA 2
-#define CE_MEMBANK_FAST16BIT 3
+#define CE_MEMBANK_FAST32 0
+#define CE_MEMBANK_CHIP16 1
+#define CE_MEMBANK_CHIP32 2
+#define CE_MEMBANK_CIA 3
+#define CE_MEMBANK_FAST16 4
 extern uae_u8 ce_banktype[65536], ce_cachable[65536];
 
 #define MEMORY_LGET(name) \
index 9a9bf4764056478067cc3ed3f068e31e75b6ab1a..8f647a2d3b90f9b1452e34eb5e4883592a13f395 100644 (file)
@@ -87,7 +87,7 @@ typedef double fptype;
 
 #define MAX68020CYCLES 4
 
-#define CPU_PIPELINE_MAX 3
+#define CPU_PIPELINE_MAX 4
 #define CPU000_MEM_CYCLE 4
 #define CPU000_CLOCK_MULT 2
 #define CPU020_MEM_CYCLE 3
@@ -178,12 +178,11 @@ struct regstruct
        uae_u8 panic;
        uae_u32 panic_pc, panic_addr;
 
-       uae_u16 prefetch020[CPU_PIPELINE_MAX];
+       uae_u32 prefetch020[CPU_PIPELINE_MAX];
        uae_u32 prefetch020addr;
        uae_u32 cacheholdingdata020;
        uae_u32 cacheholdingaddr020;
        int ce020memcycles;
-       int ce020tmpcycles;
 };
 
 extern struct regstruct regs;
@@ -205,7 +204,7 @@ struct cputracestruct
 
        uae_u32 msp, vbr;
        uae_u32 cacr, caar;
-       uae_u16 prefetch020[CPU_PIPELINE_MAX];
+       uae_u32 prefetch020[CPU_PIPELINE_MAX];
        uae_u32 prefetch020addr;
        uae_u32 cacheholdingdata020;
        uae_u32 cacheholdingaddr020;
@@ -439,6 +438,10 @@ extern void cpureset (void);
 extern void cpu_halt (int id);
 
 extern void fill_prefetch (void);
+extern void fill_prefetch_020 (void);
+extern void fill_prefetch_030 (void);
+extern void fill_prefetch_040 (void);
+extern void fill_prefetch_0x0 (void);
 
 #define CPU_OP_NAME(a) op ## a
 
index f02342b514d730dd2411825b1d30e2a92dad4f4a..a402be73f0d4504f780c0c9b953bdd0b502db5f0 100644 (file)
@@ -71,6 +71,7 @@ extern void fetch_ripperpath (TCHAR *out, int size);
 extern void fetch_statefilepath (TCHAR *out, int size);
 extern void fetch_inputfilepath (TCHAR *out, int size);
 extern void fetch_datapath (TCHAR *out, int size);
+extern void fetch_rompath (TCHAR *out, int size);
 extern uae_u32 uaerand (void);
 extern uae_u32 uaesrand (uae_u32 seed);
 extern uae_u32 uaerandgetseed (void);
index 6a9294ff95dd6db04a3660352f7aca84b6500ee9..c5214aca7147d85b10e3a271279383ab387db212 100644 (file)
@@ -1788,7 +1788,7 @@ static void fill_ce_banks (void)
 {
        int i;
 
-       memset (ce_banktype, CE_MEMBANK_FAST, sizeof ce_banktype);
+       memset (ce_banktype, CE_MEMBANK_FAST32, sizeof ce_banktype);
        // data cachable regions
        memset (ce_cachable, 0, sizeof ce_cachable);
        memset (ce_cachable + (0x00200000 >> 16), 1, currprefs.fastmem_size >> 16);
@@ -1797,30 +1797,31 @@ static void fill_ce_banks (void)
        memset (ce_cachable + (z3fastmem2_bank.start >> 16), 1, currprefs.z3fastmem2_size >> 16);
 
        if (&get_mem_bank (0) == &chipmem_bank) {
-               for (i = 0; i < (0x200000 >> 16); i++)
-                       ce_banktype[i] = CE_MEMBANK_CHIP;
+               for (i = 0; i < (0x200000 >> 16); i++) {
+                       ce_banktype[i] = (currprefs.cs_mbdmac || (currprefs.chipset_mask & CSMASK_AGA)) ? CE_MEMBANK_CHIP32 : CE_MEMBANK_CHIP16;
+               }
        }
        if (!currprefs.cs_slowmemisfast) {
                for (i = (0xc00000 >> 16); i < (0xe00000 >> 16); i++)
-                       ce_banktype[i] = CE_MEMBANK_CHIP;
+                       ce_banktype[i] = ce_banktype[0];
        }
        for (i = (0xd00000 >> 16); i < (0xe00000 >> 16); i++)
-               ce_banktype[i] = CE_MEMBANK_CHIP;
+               ce_banktype[i] = CE_MEMBANK_CHIP16;
        for (i = (0xa00000 >> 16); i < (0xc00000 >> 16); i++) {
                addrbank *b;
                ce_banktype[i] = CE_MEMBANK_CIA;
                b = &get_mem_bank (i << 16);
                if (b != &cia_bank) {
-                       ce_banktype[i] = CE_MEMBANK_FAST;
+                       ce_banktype[i] = CE_MEMBANK_FAST32;
                        ce_cachable[i] = 1;
                }
        }
        // CD32 ROM is 16-bit
        if (currprefs.cs_cd32cd) {
                for (i = (0xe00000 >> 16); i < (0xe80000 >> 16); i++)
-                       ce_banktype[i] = CE_MEMBANK_FAST16BIT;
+                       ce_banktype[i] = CE_MEMBANK_FAST16;
                for (i = (0xf80000 >> 16); i <= (0xff0000 >> 16); i++)
-                       ce_banktype[i] = CE_MEMBANK_FAST16BIT;
+                       ce_banktype[i] = CE_MEMBANK_FAST16;
        }
        if (currprefs.address_space_24) {
                for (i = 1; i < 256; i++)
index d2663eed0903a7b4d7eb824ad241954bcbdeeec7..543ba6fbf58c62278263ede953874da13acff241 100644 (file)
@@ -679,6 +679,10 @@ static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
 {
        do_cycles_ce (cycles);
 }
+static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
+{
+       do_cycles_ce020 (cycles);
+}
 
 // indirect memory access functions
 static void set_x_funcs (void)
@@ -784,22 +788,63 @@ static void set_x_funcs (void)
                        x_do_cycles_post = do_cycles_post;
                }
        } else if (!currprefs.cpu_cycle_exact) {
-               x_prefetch = NULL;
-               x_prefetch_long = NULL;
-               x_get_ilong = get_ilong;
-               x_get_iword = get_iword;
-               x_get_ibyte = get_ibyte;
-               x_next_iword = next_iword;
-               x_next_ilong = next_ilong;
-               x_put_long = put_long;
-               x_put_word = put_word;
-               x_put_byte = put_byte;
-               x_get_long = get_long;
-               x_get_word = get_word;
-               x_get_byte = get_byte;
-               x_do_cycles = do_cycles;
-               x_do_cycles_pre = do_cycles;
-               x_do_cycles_post = do_cycles_post;
+               // 68020+ no ce
+               if (currprefs.cpu_compatible) {
+                       if (currprefs.cpu_model == 68020) {
+                               x_prefetch = get_word_prefetch;
+                               x_prefetch_long = get_long_prefetch;
+                               x_get_ilong = get_long_020_prefetch;
+                               x_get_iword = get_word_020_prefetch;
+                               x_get_ibyte = NULL;
+                               x_next_iword = next_iword_020_prefetch;
+                               x_next_ilong = next_ilong_020_prefetch;
+                               x_put_long = put_long;
+                               x_put_word = put_word;
+                               x_put_byte = put_byte;
+                               x_get_long = get_long;
+                               x_get_word = get_word;
+                               x_get_byte = get_byte;
+                               x_do_cycles = do_cycles;
+                               x_do_cycles_pre = do_cycles;
+                               x_do_cycles_post = do_cycles_post;
+                       } else {
+                               // 68030+ does not have real prefetch only emulation
+                               x_prefetch = NULL;
+                               x_prefetch_long = NULL;
+                               x_get_ilong = get_ilong;
+                               x_get_iword = get_iword;
+                               x_get_ibyte = get_ibyte;
+                               x_next_iword = next_iword;
+                               x_next_ilong = next_ilong;
+                               x_put_long = put_long;
+                               x_put_word = put_word;
+                               x_put_byte = put_byte;
+                               x_get_long = get_long;
+                               x_get_word = get_word;
+                               x_get_byte = get_byte;
+                               x_do_cycles = do_cycles;
+                               x_do_cycles_pre = do_cycles;
+                               x_do_cycles_post = do_cycles_post;
+                       }
+               } else {
+                       x_prefetch = NULL;
+                       x_prefetch_long = NULL;
+                       x_get_ilong = get_ilong;
+                       x_get_iword = get_iword;
+                       x_get_ibyte = get_ibyte;
+                       x_next_iword = next_iword;
+                       x_next_ilong = next_ilong;
+                       x_put_long = put_long;
+                       x_put_word = put_word;
+                       x_put_byte = put_byte;
+                       x_get_long = get_long;
+                       x_get_word = get_word;
+                       x_get_byte = get_byte;
+                       x_do_cycles = do_cycles;
+                       x_do_cycles_pre = do_cycles;
+                       x_do_cycles_post = do_cycles_post;
+               }
+               // 68020+ cycle exact
        } else if (currprefs.cpu_model == 68020) {
                x_prefetch = get_word_ce020_prefetch;
                x_prefetch_long = NULL;
@@ -814,9 +859,9 @@ static void set_x_funcs (void)
                x_get_long = get_long_ce020;
                x_get_word = get_word_ce020;
                x_get_byte = get_byte_ce020;
-               x_do_cycles = do_cycles_ce;
-               x_do_cycles_pre = do_cycles_ce;
-               x_do_cycles_post = do_cycles_ce_post;
+               x_do_cycles = do_cycles_ce020;
+               x_do_cycles_pre = do_cycles_ce020;
+               x_do_cycles_post = do_cycles_ce020_post;
        } else {
                x_prefetch = get_word_ce030_prefetch;
                x_prefetch_long = NULL;
@@ -831,9 +876,9 @@ static void set_x_funcs (void)
                x_get_long = get_long_ce030;
                x_get_word = get_word_ce030;
                x_get_byte = get_byte_ce030;
-               x_do_cycles = do_cycles_ce;
-               x_do_cycles_pre = do_cycles_ce;
-               x_do_cycles_post = do_cycles_ce_post;
+               x_do_cycles = do_cycles_ce020;
+               x_do_cycles_pre = do_cycles_ce020;
+               x_do_cycles_post = do_cycles_ce020_post;
        }
        x2_prefetch = x_prefetch;
        x2_prefetch_long = x_prefetch_long;
@@ -1168,21 +1213,6 @@ static void build_cpufunctbl (void)
        set_cpu_caches ();
 }
 
-void fill_prefetch (void)
-{
-       if (currprefs.cpu_model >= 68020)
-               return;
-       regs.ir = x_get_word (m68k_getpc ());
-       regs.irc = x_get_word (m68k_getpc () + 2);
-}
-static void fill_prefetch_quick (void)
-{
-       if (currprefs.cpu_model >= 68020)
-               return;
-       regs.ir = get_word (m68k_getpc ());
-       regs.irc = get_word (m68k_getpc () + 2);
-}
-
 #define CYCLES_DIV 8192
 static unsigned long cycles_mult;
 
@@ -1265,7 +1295,7 @@ void check_prefs_changed_cpu (void)
 
                        prefs_changed_cpu ();
                        if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
-                               fill_prefetch_quick ();
+                               fill_prefetch ();
                        build_cpufunctbl ();
                        changed = true;
        }
@@ -1954,7 +1984,6 @@ uae_u32 REGPARAM2 x_get_disp_ea_ce020 (uae_u32 base, int idx)
 {
        uae_u16 dp = next_iword_020ce ();
        int reg = (dp >> 12) & 15;
-       int cycles = 0;
        uae_u32 v;
 
        uae_s32 regd = regs.regs[reg];
@@ -1970,40 +1999,31 @@ uae_u32 REGPARAM2 x_get_disp_ea_ce020 (uae_u32 base, int idx)
 
                if ((dp & 0x30) == 0x20) {
                        base += (uae_s32)(uae_s16) next_iword_020ce ();
-                       cycles++;
                }
                if ((dp & 0x30) == 0x30) {
                        base += next_ilong_020ce ();
-                       cycles++;
                }
 
                if ((dp & 0x3) == 0x2) {
                        outer = (uae_s32)(uae_s16) next_iword_020ce ();
-                       cycles++;
                }
                if ((dp & 0x3) == 0x3) {
                        outer = next_ilong_020ce ();
-                       cycles++;
                }
 
                if ((dp & 0x4) == 0) {
                        base += regd;
-                       cycles++;
                }
                if (dp & 0x3) {
                        base = x_get_long (base);
-                       cycles++;
                }
                if (dp & 0x4) {
                        base += regd;
-                       cycles++;
                }
                v = base + outer;
        } else {
                v = base + (uae_s32)((uae_s8)dp) + regd;
        }
-       if (cycles && currprefs.cpu_cycle_exact)
-               x_do_cycles (cycles * cpucycleunit);
        return v;
 }
 
@@ -3364,9 +3384,8 @@ static void m68k_reset (bool hardreset)
                if (kickstart_rom)
                        regs.pcr |= 2; /* disable FPU */
        }
-       regs.ce020tmpcycles = MAX68020CYCLES;
        regs.ce020memcycles = 0;
-       fill_prefetch_quick ();
+       fill_prefetch ();
 }
 
 void REGPARAM2 op_unimpl (uae_u16 opcode)
@@ -4537,18 +4556,36 @@ insretry:
 #endif
 
 
-/* "cycle exact" 68020/030  */
+/* "cycle exact" 68040+ */
 
-STATIC_INLINE void docodece020 (uae_u32 opcode)
+static void m68k_run_3ce (void)
 {
-       (*cpufunctbl[opcode])(opcode);
-       if (regs.ce020memcycles > 0) {
-               regs.ce020tmpcycles = CYCLE_UNIT * MAX68020CYCLES;
-               x_do_cycles (regs.ce020memcycles);
-               regs.ce020memcycles = 0;
+       struct regstruct *r = &regs;
+       uae_u16 opcode;
+       bool exit = false;
+
+       for (;;) {
+               r->instruction_pc = m68k_getpc ();
+               opcode = get_word_ce040_prefetch (0);
+
+               (*cpufunctbl[opcode])(opcode);
+
+cont:
+               if (r->spcflags || time_for_interrupt ()) {
+                       if (do_specialties (0))
+                               exit = true;
+               }
+
+               regs.ipl = regs.ipl_pin;
+
+               if (exit)
+                       return;
        }
 }
 
+/* "cycle exact" 68020/030  */
+
+
 static void m68k_run_2ce (void)
 {
        struct regstruct *r = &regs;
@@ -4580,7 +4617,7 @@ static void m68k_run_2ce (void)
                        if (cputrace.state > 1)
                                Exception (cputrace.state);
                        else if (cputrace.state == 1)
-                               docodece020 (cputrace.opcode);
+                               (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                }
                if (regs.stopped)
                        set_special (SPCFLAG_STOP);
@@ -4592,8 +4629,10 @@ static void m68k_run_2ce (void)
 
        for (;;) {
                r->instruction_pc = m68k_getpc ();
-               opcode = get_word_ce020_prefetch (0);
 
+               opcode = currprefs.cpu_model == 68020 ? get_word_ce020_prefetch (0) : get_word_ce030_prefetch (0);
+
+               //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
 
 #if DEBUG_CD32CDTVIO
                out_cd32io (r->instruction_pc);
@@ -4638,7 +4677,7 @@ static void m68k_run_2ce (void)
                                inprec_playdebug_cpu (1);
                }
 
-               docodece020 (opcode);
+               (*cpufunctbl[opcode])(opcode);
 
 cont:
                if (r->spcflags || time_for_interrupt ()) {
@@ -4646,11 +4685,6 @@ cont:
                                exit = true;
                }
 
-               regs.ce020tmpcycles -= cpucycleunit;
-               if (regs.ce020tmpcycles <= 0) {
-                       x_do_cycles (1 * CYCLE_UNIT);
-                       regs.ce020tmpcycles = CYCLE_UNIT * MAX68020CYCLES;;
-               }
                regs.ipl = regs.ipl_pin;
 
                if (exit)
@@ -4689,26 +4723,6 @@ static void m68k_run_2pf (void)
        }
 }
 
-uae_u32 get_word_020_prefetch (int o)
-{
-       uae_u32 pc = m68k_getpc () + o;
-
-       if (pc == regs.prefetch020addr) {
-               uae_u32 v = regs.prefetch020[0];
-               regs.prefetch020[0] = regs.prefetch020[1];
-               regs.prefetch020[1] = regs.prefetch020[2];
-               regs.prefetch020[2] = x_get_word (pc + 6);
-               regs.prefetch020addr += 2;
-               return v;
-       } else {
-               regs.prefetch020addr = pc + 2;
-               regs.prefetch020[0] = x_get_word (pc + 2);
-               regs.prefetch020[1] = x_get_word (pc + 4);
-               regs.prefetch020[2] = x_get_word (pc + 6);
-               return x_get_word (pc);
-       }
-}
-
 // full prefetch 020+
 static void m68k_run_2p (void)
 {
@@ -4726,7 +4740,6 @@ static void m68k_run_2p (void)
                x_do_cycles (cpu_cycles);
 
                opcode = get_word_020_prefetch (0);
-
                count_instr (opcode);
 
                cpu_cycles = (*cpufunctbl[opcode])(opcode);
@@ -4955,6 +4968,7 @@ void m68k_go (int may_quit)
                                currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
                                currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
                                currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
+                               currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
                                currprefs.cpu_compatible ? (currprefs.cpu_model <= 68020 ? m68k_run_2p : m68k_run_2pf) : m68k_run_2;
 #if 0
@@ -5447,8 +5461,6 @@ void m68k_dumpstate (uaecptr *nextpc)
 #define CPUTYPE_EC 1
 #define CPUMODE_HALT 1
 
-
-
 uae_u8 *restore_cpu (uae_u8 *src)
 {
        int i, flags, model;
@@ -5527,8 +5539,14 @@ uae_u8 *restore_cpu (uae_u8 *src)
                        regs.prefetch020addr = restore_u32 ();
                        regs.cacheholdingaddr020 = restore_u32 ();
                        regs.cacheholdingdata020 = restore_u32 ();
-                       for (int i = 0; i < CPU_PIPELINE_MAX; i++)
-                               regs.prefetch020[i] = restore_u16 ();
+                       if (flags & 0x20000000) {
+                               // 2.7.0 new
+                               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                                       regs.prefetch020[i] = restore_u32 ();
+                       } else {
+                               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                                       regs.prefetch020[i] = restore_u16 ();
+                       }
                } else if (model == 68030) {
                        for (int i = 0; i < CACHELINES030; i++) {
                                for (int j = 0; j < 4; j++) {
@@ -5544,10 +5562,12 @@ uae_u8 *restore_cpu (uae_u8 *src)
                                }
                                dcaches030[i].tag = restore_u32 ();
                        }
+                       for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                               regs.prefetch020[i] = restore_u32 ();
                }
                if (model >= 68020) {
                        regs.ce020memcycles = restore_u32 ();
-                       regs.ce020tmpcycles = restore_u32 ();
+                       restore_u32 ();
                }
        }
 
@@ -5562,7 +5582,7 @@ void restore_cpu_finish (void)
        init_m68k ();
        m68k_setpc (regs.pc);
        doint ();
-       fill_prefetch_quick ();
+       fill_prefetch ();
        set_cycles (start_cycles);
        events_schedule ();
        if (regs.stopped)
@@ -5753,7 +5773,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                dstbak = dst = xmalloc (uae_u8, 1000);
        model = currprefs.cpu_model;
        save_u32 (model);                                       /* MODEL */
-       save_u32 (0x80000000 | 0x40000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
+       save_u32 (0x80000000 | 0x40000000 | 0x20000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
        for (i = 0;i < 15; i++)
                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
        save_u32 (m68k_getpc ());                       /* PC */
@@ -5822,7 +5842,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                save_u32 (regs.cacheholdingaddr020);
                save_u32 (regs.cacheholdingdata020);
                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
-                       save_u16 (regs.prefetch020[i]);
+                       save_u32 (regs.prefetch020[i]);
        } else if (model == 68030) {
                for (int i = 0; i < CACHELINES030; i++) {
                        for (int j = 0; j < 4; j++) {
@@ -5838,10 +5858,15 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                        }
                        save_u32 (dcaches030[i].tag);
                }
+               save_u32 (regs.prefetch020addr);
+               save_u32 (regs.cacheholdingaddr020);
+               save_u32 (regs.cacheholdingdata020);
+               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                       save_u32 (regs.prefetch020[i]);
        }
        if (currprefs.cpu_model >= 68020) {
                save_u32 (regs.ce020memcycles);
-               save_u32 (regs.ce020tmpcycles);
+               save_u32 (0);
        }
        *len = dst - dstbak;
        return dstbak;
@@ -6190,7 +6215,7 @@ STATIC_INLINE void fill_cache040 (uae_u32 addr)
 }
 
 // this one is really simple and easy
-static void fill_icache020 (uae_u32 addr)
+static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
 {
        int index;
        uae_u32 tag;
@@ -6208,7 +6233,18 @@ static void fill_icache020 (uae_u32 addr)
                return;
        }
        // cache miss
-       data = x_get_long (addr);
+       // Prefetch apparently can be queued by bus controller
+       // even if bus controller is currently processing
+       // previous data access.
+       // Other combinations are not possible.
+       if (regs.ce020memcycles < 0)
+               regs.ce020memcycles = 0;
+       unsigned long cycs = get_cycles ();
+       data = fetch (addr);
+       // negative cycles = prefetch
+       // ce020memcycles was guaranteed zero or positive.
+       cycs = get_cycles () - cycs;
+       regs.ce020memcycles = -regs.ce020memcycles - cycs;
        if (!(regs.cacr & 2)) {
                c->tag = tag;
                c->valid = !!(regs.cacr & 1);
@@ -6221,31 +6257,281 @@ static void fill_icache020 (uae_u32 addr)
 uae_u32 get_word_ce020_prefetch (int o)
 {
        uae_u32 pc = m68k_getpc () + o;
+       uae_u32 v;
 
-       if (pc == regs.prefetch020addr) {
-               uae_u32 v = regs.prefetch020[0];
+       if (pc & 2) {
+               v = regs.prefetch020[0] & 0xffff;
                regs.prefetch020[0] = regs.prefetch020[1];
-               regs.prefetch020[1] = regs.prefetch020[2];
-               pc += 4 + 2;
-               if (regs.cacheholdingaddr020 != (pc & ~3))
-                       fill_icache020 (pc);
-               regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               regs.prefetch020addr += 2;
+               fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
+               regs.prefetch020[1] = regs.cacheholdingdata020;
+               return v;
+       }
+       v = regs.prefetch020[0] >> 16;
+       return v;
+}
+
+uae_u32 get_word_020_prefetch (int o)
+{
+       uae_u32 pc = m68k_getpc () + o;
+       uae_u32 v;
+
+       if (pc & 2) {
+               v = regs.prefetch020[0] & 0xffff;
+               regs.prefetch020[0] = regs.prefetch020[1];
+               fill_icache020 (pc + 2 + 4, get_longi);
+               regs.prefetch020[1] = regs.cacheholdingdata020;
                return v;
+       }
+       v = regs.prefetch020[0] >> 16;
+       return v;
+}
+
+void usecycles_ce020 (int cycles)
+{
+       if (regs.ce020memcycles < 0) {
+               if (regs.ce020memcycles <= -cycles) {
+                       regs.ce020memcycles += cycles;
+               } else {
+                       cycles -= -regs.ce020memcycles;
+                       regs.ce020memcycles = 0;
+                       x_do_cycles (cycles);
+               }
        } else {
-               regs.prefetch020addr = pc;
-               fill_icache020 (pc);
-               regs.prefetch020[0] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               pc += 2;
-               fill_icache020 (pc);
-               regs.prefetch020[1] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               pc += 2;
-               fill_icache020 (pc);
-               regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               return get_word_ce020_prefetch (o);
+               if (regs.ce020memcycles >= cycles) {
+                       regs.ce020memcycles -= cycles;
+               } else {
+                       cycles -= regs.ce020memcycles;
+                       regs.ce020memcycles = 0;
+                       x_do_cycles (cycles);
+               }
        }
 }
 
+#define RESET_CE020_CYCLES \
+       resetcycles_ce020 ()
+#define STORE_CE020_CYCLES \
+       unsigned long cycs = get_cycles ()
+#define ADD_CE020_CYCLES \
+       regs.ce020memcycles += get_cycles () - cycs
+
+uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
+{
+       uae_u32 v;
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+               v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) != 0) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, -1);
+               }
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_long (addr);
+               if ((addr & 3) != 0)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_long (addr);
+               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               v = get_long (addr);
+               break;
+       }
+       ADD_CE020_CYCLES;
+       return v;
+}
+
+uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
+{
+       uae_u32 v;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+               v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) != 0) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, -1);
+               }
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_longi (addr);
+               if ((addr & 3) != 0)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_longi (addr);
+               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               v = get_longi (addr);
+               break;
+       }
+       return v;
+}
+
+uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
+{
+       uae_u32 v;
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, 1);
+               }
+               break;
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
+               v = get_word (addr);
+               if ((addr & 3) == 3)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+                break;
+       default:
+                v = get_word (addr);
+               break;
+       }
+       ADD_CE020_CYCLES;
+       return v;
+}
+
+uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
+{
+       uae_u32 v;
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               v = wait_cpu_cycle_read_ce020 (addr, 0);
+               break;
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
+               v = get_byte (addr);
+               do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               v = get_byte (addr);
+               break;
+       }
+       ADD_CE020_CYCLES;
+       return v;
+}
+
+void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
+{
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               wait_cpu_cycle_write_ce020 (addr, 0, v);
+               break;
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
+               put_byte (addr, v);
+               do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               put_byte (addr, v);
+       break;
+       }
+       ADD_CE020_CYCLES;
+}
+
+void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
+{
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
+                       wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
+               } else {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
+               }
+               break;
+       case CE_MEMBANK_FAST16:
+       case CE_MEMBANK_FAST32:
+               put_word (addr, v);
+               if ((addr & 3) == 3)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               put_word (addr, v);
+       break;
+       }
+       ADD_CE020_CYCLES;
+}
+
+void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
+{
+       RESET_CE020_CYCLES;
+       STORE_CE020_CYCLES;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
+               wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
+                       wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
+               } else {
+                       wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
+               }
+               break;
+       case CE_MEMBANK_FAST32:
+               put_long (addr, v);
+               if ((addr & 3) != 0)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+               break;
+       case CE_MEMBANK_FAST16:
+               put_long (addr, v);
+               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               break;
+       default:
+               put_long (addr, v);
+               break;
+       }
+       ADD_CE020_CYCLES;
+}
+
+
 // 68030 caches aren't so simple as 68020 cache..
 STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
 {
@@ -6280,8 +6566,6 @@ STATIC_INLINE void fill_icache030 (uae_u32 addr)
        struct cache030 *c;
 
        addr &= ~3;
-       if (addr == regs.cacheholdingaddr020)
-               return;
        c = getcache030 (icaches030, addr, &tag, &lws);
        if (c->valid[lws] && c->tag == tag) {
                // cache hit
@@ -6290,7 +6574,16 @@ STATIC_INLINE void fill_icache030 (uae_u32 addr)
                return;
        }
        // cache miss
-       data = mem_access_delay_longi_read_ce020 (addr);
+       if (currprefs.cpu_cycle_exact) {
+               if (regs.ce020memcycles < 0)
+                       regs.ce020memcycles = 0;
+               unsigned long cycs = get_cycles ();
+               data = mem_access_delay_longi_read_ce020 (addr);
+               cycs = get_cycles () - cycs;
+               regs.ce020memcycles = -regs.ce020memcycles - cycs;
+       } else {
+               data = get_longi (addr);
+       }
        if ((regs.cacr & 3) == 1) { // not frozen and enabled
                update_cache030 (c, data, tag, lws);
 #if 0
@@ -6394,18 +6687,27 @@ uae_u32 read_dcache030 (uaecptr addr, int size)
        uae_u32 v1, v2;
 
        if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040 || !cancache030 (addr)) { // data cache disabled? shared with 68040 "ce"
-               if (size == 2)
-                       return mem_access_delay_long_read_ce020 (addr);
-               else if (size == 1)
-                       return mem_access_delay_word_read_ce020 (addr);
-               else
-                       return mem_access_delay_byte_read_ce020 (addr);
+               if (currprefs.cpu_cycle_exact) {
+                       if (size == 2)
+                               return mem_access_delay_long_read_ce020 (addr);
+                       else if (size == 1)
+                               return mem_access_delay_word_read_ce020 (addr);
+                       else
+                               return mem_access_delay_byte_read_ce020 (addr);
+               } else {
+                       if (size == 2)
+                               return get_long (addr);
+                       else if (size == 1)
+                               return get_word (addr);
+                       else
+                               return get_byte (addr);
+               }
        }
 
        c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
        addr &= ~3;
        if (!c1->valid[lws1] || c1->tag != tag1) {
-               v1 = mem_access_delay_long_read_ce020 (addr);
+               v1 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
                update_cache030 (c1, v1, tag1, lws1);
        } else {
                v1 = c1->data[lws1];
@@ -6429,7 +6731,7 @@ uae_u32 read_dcache030 (uaecptr addr, int size)
        addr += 4;
        c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
        if (!c2->valid[lws2] || c2->tag != tag2) {
-               v2 = mem_access_delay_long_read_ce020 (addr);
+               v2 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
                update_cache030 (c2, v2, tag2, lws2);
        } else {
                v2 = c2->data[lws2];
@@ -6455,29 +6757,51 @@ uae_u32 read_dcache030 (uaecptr addr, int size)
 uae_u32 get_word_ce030_prefetch (int o)
 {
        uae_u32 pc = m68k_getpc () + o;
+       uae_u32 v;
 
-       if (pc == regs.prefetch020addr) {
-               uae_u32 v = regs.prefetch020[0];
+       if (pc & 2) {
+               v = regs.prefetch020[0] & 0xffff;
+               regs.prefetch020[0] = regs.prefetch020[1];
+               fill_icache030 (pc + 2 + 4);
+               regs.prefetch020[1] = regs.cacheholdingdata020;
+               return v;
+       }
+       v = regs.prefetch020[0] >> 16;
+       return v;
+}
+
+STATIC_INLINE void fill_icache040 (uae_u32 addr)
+{
+       uae_u32 data;
+       addr &= ~3;
+       if (currprefs.cpu_cycle_exact)
+               data = mem_access_delay_longi_read_ce020 (addr);
+       else
+               data = get_longi (addr);
+       regs.cacheholdingaddr020 = addr;
+       regs.cacheholdingdata020 = data;
+}
+
+uae_u32 get_word_ce040_prefetch (int o)
+{
+       uae_u32 pc = m68k_getpc () + o;
+       uae_u32 v;
+
+       if (pc & 2) {
+               v = regs.prefetch020[0] & 0xffff;
                regs.prefetch020[0] = regs.prefetch020[1];
                regs.prefetch020[1] = regs.prefetch020[2];
-               pc += 4 + 2;
-               fill_icache030 (pc);
-               regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               regs.prefetch020addr += 2;
-               fill_icache030 (pc + 4);
+               regs.prefetch020[2] = regs.prefetch020[3];
+               fill_icache040 (pc + 2 + 4);
+               regs.prefetch020[1] = regs.cacheholdingdata020;
+               fill_icache040 (pc + 2 + 4 + 4);
+               regs.prefetch020[2] = regs.cacheholdingdata020;
+               fill_icache040 (pc + 2 + 4 + 4 + 4);
+               regs.prefetch020[3] = regs.cacheholdingdata020;
                return v;
-       } else {
-               regs.prefetch020addr = pc;
-               fill_icache030 (pc);
-               regs.prefetch020[0] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               pc += 2;
-               fill_icache030 (pc);
-               regs.prefetch020[1] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               pc += 2;
-               fill_icache030 (pc);
-               regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
-               return get_word_ce030_prefetch (o);
        }
+       v = regs.prefetch020[0] >> 16;
+       return v;
 }
 
 void flush_dcache (uaecptr addr, int size)
@@ -6494,3 +6818,60 @@ void flush_dcache (uaecptr addr, int size)
        }
 }
 
+void fill_prefetch_040 (void)
+{
+       uaecptr pc = m68k_getpc ();
+       pc &= ~3;
+       fill_icache040 (pc);
+       regs.prefetch020[0] = regs.cacheholdingdata020;
+       fill_icache040 (pc + 4);
+       regs.prefetch020[1] = regs.cacheholdingdata020;
+       fill_icache040 (pc + 4 + 4);
+       regs.prefetch020[2] = regs.cacheholdingdata020;
+       fill_icache040 (pc + 4 + 4  +4);
+       regs.prefetch020[3] = regs.cacheholdingdata020;
+}
+
+void fill_prefetch_030 (void)
+{
+       uaecptr pc = m68k_getpc ();
+       pc &= ~3;
+       fill_icache030 (pc);
+       regs.prefetch020[0] = regs.cacheholdingdata020;
+       fill_icache030 (pc + 4);
+       regs.prefetch020[1] = regs.cacheholdingdata020;
+}
+
+void fill_prefetch_020 (void)
+{
+       uaecptr pc = m68k_getpc ();
+       uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
+       pc &= ~3;
+       fill_icache020 (pc, fetch);
+       regs.prefetch020[0] = regs.cacheholdingdata020;
+       fill_icache020 (pc + 4, fetch);
+       regs.prefetch020[1] = regs.cacheholdingdata020;
+}
+
+void fill_prefetch_0x0 (void)
+{
+       if (currprefs.cpu_model >= 68040)
+               fill_prefetch_040 ();
+       else
+               fill_prefetch_030 ();
+}
+
+void fill_prefetch (void)
+{
+       uaecptr pc = m68k_getpc ();
+       if (currprefs.cpu_model == 68020) {
+               fill_prefetch_020 ();
+       } else if (currprefs.cpu_model >= 68030) {
+               fill_prefetch_030 ();
+       } else if (currprefs.cpu_model >= 68040) {
+               fill_prefetch_040 ();
+       } else if (currprefs.cpu_model <= 68010) {
+               regs.ir = x_get_word (pc);
+               regs.irc = x_get_word (pc + 2);
+       }
+}
index 7551b62a117ac75e451aacd3bcad145eef88234d..2f987d2b8d3d6bcfe6585b84292944c97c8936f9 100644 (file)
@@ -274,6 +274,8 @@ static int AVIOutput_AllocateAudio (void)
                gui_message (_T("acmMetrics() FAILED (%X)\n"), err);
                return 0;
        }
+       if (wfxMaxFmtSize < sizeof (WAVEFORMATEX)) // some systems return bogus zero value..
+               return 0;
 
        // set the source format
        memset (&wfxSrc, 0, sizeof (wfxSrc));
index 9a8971af6f3c6e95359a73ef823f67e9440f03c9..e303987efa419472eac01e6523d591bae7067526 100644 (file)
@@ -128,9 +128,9 @@ static uae_u8 *fakebitmap;
 static uae_thread_id fakemodetid;
 int fakemodewaitms = 0;
 
-static D3DXMATRIXA16 m_matProj, m_matProj2;
-static D3DXMATRIXA16 m_matWorld, m_matWorld2;
-static D3DXMATRIXA16 m_matView, m_matView2;
+static D3DXMATRIXA16 m_matProj, m_matProj2, m_matProj_out;
+static D3DXMATRIXA16 m_matWorld, m_matWorld2, m_matWorld_out;
+static D3DXMATRIXA16 m_matView, m_matView2, m_matView_out;
 static D3DXMATRIXA16 m_matPreProj;
 static D3DXMATRIXA16 m_matPreView;
 static D3DXMATRIXA16 m_matPreWorld;
@@ -1227,16 +1227,16 @@ static int createtexture (int ow, int oh, int win_w, int win_h)
                                if (!allocextratextures (&shaders[i], ow, oh))
                                        return 0;
                        } else {
-                               w2 = zw;
-                               h2 = zh;
+                               w2 = ow;
+                               h2 = oh;
                                w = ow;
                                h = oh;
                        }
                        if (FAILED (hr = d3ddev->CreateTexture (w2, h2, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &shaders[i].lpTempTexture, NULL))) {
-                               write_log (_T("%s: Failed to create working texture1: %s:%d\n"), D3DHEAD, D3D_ErrorString (hr), i);
+                               write_log (_T("%s: Failed to create working texture1: %s:%d:%d\n"), D3DHEAD, D3D_ErrorString (hr), i, shaders[i].type);
                                return 0;
                        }
-                       write_log (_T("%s: %d*%d temp texture:%d\n"), D3DHEAD, w2, h2, i);
+                       write_log (_T("%s: %d*%d temp texture:%d:%d\n"), D3DHEAD, w2, h2, i, shaders[i].type);
                        shaders[i].worktex_width = w;
                        shaders[i].worktex_height = h;
                }
@@ -1738,7 +1738,7 @@ static void setupscenecoords (void)
        fakesize.w = 1;
        fakesize.z = 1;
 
-       MatrixOrthoOffCenterLH (&m_matProj, 0, w + 0.05f, 0, h + 0.05f, 0.0f, 1.0f);
+       MatrixOrthoOffCenterLH (&m_matProj_out, 0, w + 0.05f, 0, h + 0.05f, 0.0f, 1.0f);
 
        float tx, ty;
        float sw, sh;
@@ -1786,9 +1786,9 @@ static void setupscenecoords (void)
 
        }
 
-       MatrixTranslation (&m_matView, tx, ty, 1.0f);
+       MatrixTranslation (&m_matView_out, tx, ty, 1.0f);
 
-       MatrixScaling (&m_matWorld, sw + 0.5f / sw, sh + 0.5f / sh, 1.0f);
+       MatrixScaling (&m_matWorld_out, sw + 0.5f / sw, sh + 0.5f / sh, 1.0f);
 
        cursor_offset_x = -zr.left;
        cursor_offset_y = -zr.top;
@@ -1809,8 +1809,8 @@ static void setupscenecoords (void)
        maskshift.y = 1.0f / maskmult_y;
 
        D3DXMATRIXA16 tmpmatrix;
-       D3DXMatrixMultiply (&tmpmatrix, &m_matWorld, &m_matView);
-       D3DXMatrixMultiply (&postproj, &tmpmatrix, &m_matProj);
+       D3DXMatrixMultiply (&tmpmatrix, &m_matWorld_out, &m_matView_out);
+       D3DXMatrixMultiply (&postproj, &tmpmatrix, &m_matProj_out);
 }
 
 uae_u8 *getfilterbuffer3d (struct vidbuffer *vb, int *widthp, int *heightp, int *pitch, int *depth)
@@ -1875,6 +1875,16 @@ static void createvertex (void)
                write_log (_T("%s: Vertexbuffer unlock failed: %s\n"), D3DHEAD, D3D_ErrorString (hr));
 }
 
+static void settransform_pre (struct shaderdata *s)
+{
+       // Projection is (0,0,0) -> (1,1,1)
+       MatrixOrthoOffCenterLH (&m_matProj, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
+       // Align texels with pixels
+       MatrixTranslation (&m_matView, -0.5f / tout_w, 0.5f / tout_h, 0.0f);
+       // Identity for world
+       D3DXMatrixIdentity (&m_matWorld);
+}
+
 static void settransform (struct shaderdata *s)
 {
        // Projection is (0,0,0) -> (1,1,1)
@@ -1890,6 +1900,7 @@ static void settransform (struct shaderdata *s)
        MatrixOrthoOffCenterLH (&m_matProj2, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
 
        MatrixTranslation (&m_matView2, 0.5f - 0.5f / tout_w, 0.5f + 0.5f / tout_h, 0.0f);
+
        D3DXMatrixIdentity (&m_matWorld2);
 }
 
@@ -2850,6 +2861,13 @@ static void D3D_render2 (void)
        if (shaderon > 0 && shaders[SHADER_POST].pEffect) {
                for (int i = 0; i < MAX_SHADERS; i++) {
                        struct shaderdata *s = &shaders[i];
+                       if (s->type == SHADERTYPE_BEFORE)
+                               settransform_pre (s);
+                       if (s->type == SHADERTYPE_MIDDLE) {
+                               m_matProj = m_matProj_out;
+                               m_matView = m_matView_out;
+                               m_matWorld = m_matWorld_out;
+                       }
                        if (s->type == SHADERTYPE_BEFORE || s->type == SHADERTYPE_MIDDLE) {
                                settransform (s);
                                srctex = processshader (srctex, s, true);
@@ -2859,6 +2877,10 @@ static void D3D_render2 (void)
                }
        }
 
+       m_matProj = m_matProj_out;
+       m_matView = m_matView_out;
+       m_matWorld = m_matWorld_out;
+
 #if TWOPASS
        if (shaderon > 0 && shaders[SHADER_POST].pEffect) {
                LPDIRECT3DSURFACE9 lpRenderTarget;
index eb21d02a98c656741336a3850be0274fc8533783..1a135be7439ea820e6fe26051b05e2c8c8d579f3 100644 (file)
@@ -33,6 +33,8 @@
 #include <stddef.h>
 
 static int usefloppydrives = 0;
+static int num_drives;
+static bool drives_enumerated;
 
 struct hardfilehandle
 {
@@ -47,8 +49,9 @@ struct uae_driveinfo {
        TCHAR product_id[128];
        TCHAR product_rev[128];
        TCHAR product_serial[128];
-       TCHAR device_name[2048];
-       TCHAR device_path[2048];
+       TCHAR device_name[1024];
+       TCHAR device_path[1024];
+       TCHAR device_full_path[2048];
        uae_u64 size;
        uae_u64 offset;
        int bytespersector;
@@ -408,12 +411,132 @@ static void queryidentifydevice (struct hardfiledata *hfd)
 }
 #endif
 
+static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_driveinfo *udi, int ignoreduplicates);
+
+static bool getdeviceinfo (HANDLE hDevice, struct uae_driveinfo *udi)
+{
+       DISK_GEOMETRY dg;
+       GET_LENGTH_INFORMATION gli;
+       DWORD returnedLength;
+       bool geom_ok = true, gli_ok;
+       UCHAR outBuf[20000];
+       DRIVE_LAYOUT_INFORMATION *dli;
+       STORAGE_PROPERTY_QUERY query;
+       DWORD status;
+       TCHAR devname[MAX_DPATH];
+       int amipart = -1;
+
+       udi->bytespersector = 512;
+
+       _tcscpy (devname, udi->device_name + 1);
+
+       if (devname[0] == ':' && devname[1] == 'P' && devname[2] == '#' &&
+               (devname[4] == '_' || devname[5] == '_')) {
+               TCHAR c1 = devname[3];
+               TCHAR c2 = devname[4];
+               if (c1 >= '0' && c1 <= '9') {
+                       amipart = c1 - '0';
+                       if (c2 != '_') {
+                               if (c2 >= '0' && c2 <= '9') {
+                                       amipart *= 10;
+                                       amipart += c2 - '0';
+                                       _tcscpy (devname, udi->device_name + 6);
+                               } else {
+                                       amipart = -1;
+                               }
+                       } else {
+                               _tcscpy (devname, udi->device_name + 5);
+                       }
+               }
+       }
+
+       udi->device_name[0] = 0;
+       memset (outBuf, 0, sizeof outBuf);
+       query.PropertyId = StorageDeviceProperty;
+       query.QueryType = PropertyStandardQuery;
+       status = DeviceIoControl(
+               hDevice,
+               IOCTL_STORAGE_QUERY_PROPERTY,
+               &query,
+               sizeof (STORAGE_PROPERTY_QUERY),
+               &outBuf,
+               sizeof outBuf,
+               &returnedLength,
+               NULL);
+       if (status) {
+               if (getstorageproperty (outBuf, returnedLength, udi, false) != -1)
+                       return false;
+       } else {
+               return false;
+       }
+
+       if (_tcsicmp (devname, udi->device_name) != 0) {
+               write_log (_T("Non-enumeration mount: mismatched device names\n"));
+               return false;
+       }
+
+       if (!DeviceIoControl (hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (void*)&dg, sizeof (dg), &returnedLength, NULL)) {
+               DWORD err = GetLastError();
+               if (isnomediaerr (err)) {
+                       udi->nomedia = 1;
+                       return true;
+               }
+               write_log (_T("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with error code %d.\n"), err);
+               geom_ok = false;
+       }
+       if (!DeviceIoControl (hDevice, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0, &returnedLength, NULL)) {
+               DWORD err = GetLastError ();
+               if (err == ERROR_WRITE_PROTECT)
+                       udi->readonly = 1;
+       }
+       gli_ok = true;
+       if (!DeviceIoControl (hDevice, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (void*)&gli, sizeof (gli), &returnedLength, NULL)) {
+               gli_ok = false;
+               write_log (_T("IOCTL_DISK_GET_LENGTH_INFO failed with error code %d.\n"), GetLastError());
+       } else {
+               write_log (_T("IOCTL_DISK_GET_LENGTH_INFO returned size: %I64d (0x%I64x)\n"), gli.Length.QuadPart, gli.Length.QuadPart);
+       }
+       if (geom_ok == 0 && gli_ok == 0) {
+               write_log (_T("Can't detect size of device\n"));
+               return false;
+       }
+       if (geom_ok && dg.BytesPerSector != udi->bytespersector)
+               return false;
+       udi->size = gli.Length.QuadPart;
+
+       // check for amithlon partitions, if any found = quick mount not possible
+       status = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL, 0,
+               &outBuf, sizeof (outBuf), &returnedLength, NULL);
+       if (!status)
+               return true;
+       dli = (DRIVE_LAYOUT_INFORMATION*)outBuf;
+       if (!dli->PartitionCount)
+               return true;
+       bool partfound = false;
+       for (int i = 0; i < dli->PartitionCount; i++) {
+               PARTITION_INFORMATION *pi = &dli->PartitionEntry[i];
+               if (pi->PartitionType == PARTITION_ENTRY_UNUSED)
+                       continue;
+               if (pi->RecognizedPartition == 0)
+                       continue;
+               if (pi->PartitionType != 0x76 && pi->PartitionType != 0x30)
+                       continue;
+               if (i == amipart) {
+                       udi->offset = pi->StartingOffset.QuadPart;
+                       udi->size = pi->PartitionLength.QuadPart;
+               }
+       }
+       if (amipart >= 0)
+               return false;
+       return true;
+}
+
 int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
 {
        HANDLE h = INVALID_HANDLE_VALUE;
        DWORD flags;
        int i;
-       struct uae_driveinfo *udi;
+       struct uae_driveinfo *udi = NULL, tmpudi;
        TCHAR *name = my_strdup (pname);
 
        hfd->flags = 0;
@@ -431,16 +554,47 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
        hfd->handle->h = INVALID_HANDLE_VALUE;
        hfd_log (_T("hfd attempting to open: '%s'\n"), name);
        if (name[0] == ':') {
-               hdf_init_target ();
-               i = isharddrive (name);
-               if (i >= 0) {
+               int drvnum = -1;
+               TCHAR *p = _tcschr (name + 1, ':');
+               if (p) {
+                       *p++ = 0;
+                       if (!drives_enumerated) {
+                               // do not scan for drives if open succeeds and it is a harddrive
+                               // to prevent spinup of sleeping drives
+                               h = CreateFile (p,
+                                       GENERIC_READ,
+                                       FILE_SHARE_READ,
+                                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
+                       }
+               }
+               if (h != INVALID_HANDLE_VALUE) {
+                       udi = &tmpudi;
+                       memset (udi, 0, sizeof (struct uae_driveinfo));
+                       _tcscpy (udi->device_full_path, name);
+                       _tcscat (udi->device_full_path, _T(":"));
+                       _tcscat (udi->device_full_path, p);
+                       _tcscpy (udi->device_name, name);
+                       _tcscpy (udi->device_path, p);
+                       if (!getdeviceinfo (h, udi))
+                               udi = NULL;
+                       CloseHandle (h);
+                       h = INVALID_HANDLE_VALUE;
+               }
+               if (udi == NULL) {
+                       hdf_init_target ();
+                       drvnum = isharddrive (name);
+                       if (drvnum >= 0)
+                               udi = &uae_drives[drvnum];
+               }
+               if (udi != NULL) {
                        DWORD r;
-                       udi = &uae_drives[i];
                        hfd->flags = HFD_FLAGS_REALDRIVE;
-                       if (udi->nomedia)
-                               hfd->drive_empty = -1;
-                       if (udi->readonly)
-                               hfd->ci.readonly = 1;
+                       if (udi) {
+                               if (udi->nomedia)
+                                       hfd->drive_empty = -1;
+                               if (udi->readonly)
+                                       hfd->ci.readonly = 1;
+                       }
                        flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS;
                        h = CreateFile (udi->device_path,
                                GENERIC_READ | (hfd->ci.readonly ? 0 : GENERIC_WRITE),
@@ -1333,6 +1487,7 @@ static BOOL GetDevicePropertyFromName(const TCHAR *DevicePath, DWORD Index, DWOR
        }
 amipartfound:
        _stprintf (udi->device_name, _T(":%s"), orgname);
+       _stprintf (udi->device_full_path, _T("%s:%s"), udi->device_name, udi->device_path);
        if (udiindex < 0) {
                int cnt = 1;
                int off = _tcslen (udi->device_name);
@@ -1467,10 +1622,6 @@ end:
 #endif
 
 
-
-
-static int num_drives;
-
 static int hdf_init2 (int force)
 {
 #ifdef WINDDK
@@ -1479,11 +1630,10 @@ static int hdf_init2 (int force)
        DWORD index = 0, index2 = 0, drive;
        uae_u8 *buffer;
        DWORD dwDriveMask;
-       static int done;
 
-       if (done && !force)
+       if (drives_enumerated && !force)
                return num_drives;
-       done = 1;
+       drives_enumerated = true;
        num_drives = 0;
 #ifdef WINDDK
        buffer = (uae_u8*)VirtualAlloc (NULL, 65536, MEM_COMMIT, PAGE_READWRITE);
@@ -1631,6 +1781,8 @@ TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangero
                        return name;
                }
        }
+       if (flags & 4)
+               return uae_drives[index].device_full_path;
        if (flags & 2)
                return uae_drives[index].device_path;
        return uae_drives[index].device_name;
index 3ca906c201ea7bb7e6c53034016def7ca1957284..704dcae3830adbf9ffcb01c9d43fcd0d2c9f910e 100644 (file)
@@ -2254,7 +2254,7 @@ static void picasso96_alloc2 (TrapContext *ctx)
 
 void picasso96_alloc (TrapContext *ctx)
 {
-       if (uaegfx_old)
+       if (uaegfx_old || currprefs.rtgmem_type >= GFXBOARD_HARDWARE)
                return;
        uaegfx_resname = ds (_T("uaegfx.card"));
        picasso96_alloc2 (ctx);
index 7f181a3f9f543d3e14e5e5df23d9dfe3de7cf5ee..ca829e893ef8b22235ac27460fa4658eeedc997d 100644 (file)
@@ -3500,7 +3500,10 @@ void fetch_datapath (TCHAR *out, int size)
 {
        fetch_path (NULL, out, size);
 }
-
+void fetch_rompath (TCHAR *out, int size)
+{
+       fetch_path (_T("KickstartPath"), out, size);
+}
 static int isfilesindir (const TCHAR *p)
 {
        WIN32_FIND_DATA fd;
index 8a554391992c6983054e5cd13c5daeb3c59c867d..043c93006477b124b8a643a237178924c7808fe2 100644 (file)
 #define LANG_DLL 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("3")
+#define WINUAEBETA _T("4")
 #else
 #define WINUAEBETA _T("")
 #endif
-#define WINUAEDATE MAKEBD(2013, 7, 21)
+#define WINUAEDATE MAKEBD(2013, 7, 31)
 #define WINUAEEXTRA _T("")
 //#define WINUAEEXTRA _T("AmiKit Preview")
 //#define WINUAEEXTRA _T("Amiga Forever Edition")
index 43d046f8aae165bca39a2887da00673afce04169..a3df6e2a4be5fedf9d641a3e6db55a0e51b1c90a 100644 (file)
@@ -4018,7 +4018,7 @@ void InitializeListView (HWND hDlg)
                        struct uaedev_config_info *ci = &uci->ci;
                        int nosize = 0, type;
                        struct mountedinfo mi;
-                       TCHAR *rootdir;
+                       TCHAR *rootdir, *rootdirp;
 
                        type = get_filesys_unitconfig (&workprefs, i, &mi);
                        if (type < 0) {
@@ -4027,7 +4027,16 @@ void InitializeListView (HWND hDlg)
                        }
                        if (mi.size < 0)
                                nosize = 1;
-                       rootdir = mi.rootdir;
+                       rootdir = my_strdup (mi.rootdir);
+                       rootdirp = rootdir;
+                       if (!_tcsncmp (rootdirp, _T("HD_"), 3))
+                               rootdirp += 3;
+                       if (rootdirp[0] == ':') {
+                               rootdirp++;
+                               TCHAR *p = _tcschr (rootdirp, ':');
+                               if (p)
+                                       *p = 0;
+                       }
 
                        if (nosize)
                                _tcscpy (size_str, _T("n/a"));
@@ -4068,8 +4077,6 @@ void InitializeListView (HWND hDlg)
                                _tcscpy (devname_str, _T("*UAE*"));
                                _tcscpy (volname_str, _T("n/a"));
                                _tcscpy (bootpri_str, _T("n/a"));
-                               if (!_tcsncmp (rootdir, _T("HD_"), 3))
-                                       rootdir += 3;
                        } else if (type == FILESYS_TAPE) {
                                _stprintf (blocksize_str, _T("%d"), ci->blocksize);
                                _tcscpy (devname_str, _T("*UAE*"));
@@ -4086,8 +4093,11 @@ void InitializeListView (HWND hDlg)
                                _tcscpy (blocksize_str, _T("n/a"));
                                _tcscpy (size_str, _T("n/a"));
                        }
-                       if (rootdir == NULL || rootdir[0] == 0)
-                               rootdir = _T("-");
+                       if (rootdirp[0] == 0) {
+                               xfree (rootdir);
+                               rootdir = my_strdup (_T("-"));
+                               rootdirp = rootdir;
+                       }
                        WIN32GUI_LoadUIString (ci->readonly ? IDS_NO : IDS_YES, readwrite_str, sizeof (readwrite_str) / sizeof (TCHAR));
 
                        lvstruct.mask     = LVIF_TEXT | LVIF_PARAM;
@@ -4113,8 +4123,8 @@ void InitializeListView (HWND hDlg)
                                        listview_column_width[2] = width;
 
                                listview_column_width[3] = 150;
-                               ListView_SetItemText(list, result, 3, rootdir);
-                               width = ListView_GetStringWidth(list, rootdir) + 10;
+                               ListView_SetItemText(list, result, 3, rootdirp);
+                               width = ListView_GetStringWidth(list, rootdirp) + 10;
                                if(width > listview_column_width[3])
                                        listview_column_width[3] = width;
 
@@ -4138,6 +4148,7 @@ void InitializeListView (HWND hDlg)
                                if(width > listview_column_width[7] )
                                        listview_column_width[7] = width;
                        }
+                       xfree (rootdir);
                }
 #endif
        }
@@ -7462,7 +7473,7 @@ static INT_PTR CALLBACK ExpansionDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP
                SendDlgItemMessage (hDlg, IDC_RTG_Z2Z3, CB_ADDSTRING, 0, (LPARAM)_T("Piccolo SD64 Zorro III"));
                SendDlgItemMessage (hDlg, IDC_RTG_Z2Z3, CB_ADDSTRING, 0, (LPARAM)_T("Spectrum28/24 Zorro II"));
                SendDlgItemMessage (hDlg, IDC_RTG_Z2Z3, CB_ADDSTRING, 0, (LPARAM)_T("Spectrum28/24 Zorro III"));
-#if 0
+#if 1
                SendDlgItemMessage (hDlg, IDC_RTG_Z2Z3, CB_ADDSTRING, 0, (LPARAM)_T("Picasso IV Zorro II"));
                SendDlgItemMessage (hDlg, IDC_RTG_Z2Z3, CB_ADDSTRING, 0, (LPARAM)_T("Picasso IV Zorro III"));
 #endif
@@ -10112,7 +10123,10 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                        index = -1;
                        for (i = 0; i < hdf_getnumharddrives (); i++) {
                                SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_ADDSTRING, 0, (LPARAM)hdf_getnameharddrive (i, 1, NULL, NULL));
-                               if (!_tcscmp (current_hfdlg.ci.rootdir, hdf_getnameharddrive (i, 0, NULL, NULL)))
+                               TCHAR *name1 = hdf_getnameharddrive (i, 4, NULL, NULL);
+                               TCHAR *name2 = hdf_getnameharddrive (i, 2, NULL, NULL);
+                               TCHAR *name3 = hdf_getnameharddrive (i, 0, NULL, NULL);
+                               if (!_tcscmp (current_hfdlg.ci.rootdir, name1) || !_tcscmp (current_hfdlg.ci.rootdir, name2) || !_tcscmp (current_hfdlg.ci.rootdir, name3))
                                        index = i;
                        }
                        if (index >= 0) {
@@ -10157,7 +10171,7 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                        BOOL ena;
                                        int dang = 1;
                                        hdf_getnameharddrive (posn, 1, NULL, &dang);
-                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 0, NULL, &dang));
+                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 4, NULL, &dang));
                                        ena = dang >= 0;
                                        ew (hDlg, IDC_HARDDRIVE_IMAGE, ena);
                                        ew (hDlg, IDOK, ena);
@@ -10173,7 +10187,7 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                        updatehdfinfo (hDlg, true, true);
                                        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_SETCURSEL, current_hfdlg.ci.controller, 0);
                                        CheckDlgButton(hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
-                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 0, &current_hfdlg.ci.blocksize, NULL));
+                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, &current_hfdlg.ci.blocksize, NULL));
                                }
                        }
                } else if (LOWORD (wParam) == IDC_HDF_CONTROLLER) {
index f310091fc61de486917739bbfad748537e1df161..f504a262427192786ddab1fd68c809313e8cdbe1 100644 (file)
@@ -43,6 +43,7 @@
  *    - optimize bitblt functions
  */
 
+//#define DEBUG_VGA
 //#define DEBUG_CIRRUS
 //#define DEBUG_VGA_REG
 //#define DEBUG_BITBLT
@@ -1021,6 +1022,9 @@ static void cirrus_get_offsets(VGACommonState *s1,
     line_compare = s->vga.cr[0x18] |
         ((s->vga.cr[0x07] & 0x10) << 4) |
         ((s->vga.cr[0x09] & 0x40) << 3);
+    /* interlace support */
+    if (s->vga.cr[0x1a] & 0x01)
+        line_compare <<= 1;
        /* multiply vertical registers by two. TW. */
        if (s->vga.cr[0x17] & 0x04)
                line_compare <<= 1;
@@ -1286,7 +1290,7 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val)
         * Probably it is a bug in CGX when using impossible
         * resolutions that real chip or monitor would not support.
         */
-       if (s->vga.cr[0x17] & 0x04)
+       if (s->device_id < CIRRUS_ID_CLGD5446 && (s->vga.cr[0x17] & 0x04))
                s->hw_cursor_y <<= 1;
        break;
     case 0x07:                 // Extended Sequencer Mode
@@ -1571,7 +1575,13 @@ cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
 
 static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index)
 {
-    switch (reg_index) {
+#if 0
+       if (reg_index >= 0x31) {
+               write_log ("READ  CR%02X = %02X\n", reg_index, s->vga.cr[s->vga.cr_index]);
+               return s->vga.cr[s->vga.cr_index];
+       }
+#endif
+       switch (reg_index) {
     case 0x00:                 // Standard VGA
     case 0x01:                 // Standard VGA
     case 0x02:                 // Standard VGA
@@ -1623,10 +1633,9 @@ static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index)
 static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value)
 {
 #if 0
-       if (s->vga.cr_index == 11)
-               write_log ("CR11 = %02X\n", reg_value & 0xff);
+       write_log ("WRITE CR%02X = %02X\n", s->vga.cr_index, reg_value);
 #endif
-    switch (s->vga.cr_index) {
+       switch (s->vga.cr_index) {
     case 0x00:                 // Standard VGA
     case 0x01:                 // Standard VGA
     case 0x02:                 // Standard VGA
@@ -1690,6 +1699,9 @@ static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value)
        break;
     case 0x25:                 // Part Status
     default:
+       s->vga.cr[s->vga.cr_index] = reg_value;
+
+
 #ifdef DEBUG_CIRRUS
        write_log("cirrus: outport cr_index %02x, cr_value %02x\n",
                s->vga.cr_index, reg_value);
@@ -2117,7 +2129,7 @@ STATIC_INLINE void cirrus_cursor_compute_yrange(CirrusVGAState *s)
     uint32_t content;
     int y, y_min, y_max;
 
-    src = s->vga.vram_ptr + s->real_vram_size - 16 * 1024;
+    src = s->vga.vram_ptr + s->total_vram_size - 16 * 1024;
     if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
         src += (s->vga.sr[0x13] & 0x3c) * 256;
         y_min = 64;
@@ -2221,7 +2233,7 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
         scr_y >= (s->hw_cursor_y + h))
         return;
 
-    src = s->vga.vram_ptr + s->real_vram_size - 16 * 1024;
+    src = s->vga.vram_ptr + s->total_vram_size - 16 * 1024;
     if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
         src += (s->vga.sr[0x13] & 0x3c) * 256;
         src += (scr_y - s->hw_cursor_y) * 16;
@@ -2927,8 +2939,8 @@ void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
     memory_region_set_flush_coalesced(&s->cirrus_mmio_io);
 
        // TW: CIRRUS_ID_CLGD5434 and newer has 4M support
-    s->real_vram_size =
-        (s->device_id == CIRRUS_ID_CLGD5434) ? 4096 * 1024 : 2048 * 1024;
+    s->total_vram_size = s->vga.vram_size_mb * 1024 * 1024;
+       s->real_vram_size = (s->device_id >= CIRRUS_ID_CLGD5434) ? 4096 * 1024 : 2048 * 1024;
 
     /* XXX: s->vga.vram_size must be a power of two */
     s->cirrus_addr_mask = s->real_vram_size - 1;
index 9a41de4ef33db7c9fb0c395ef6d9d8aacc98611f..fb72a0767868c962f2b15ec7391663f1771675ad 100644 (file)
@@ -271,6 +271,7 @@ typedef struct CirrusVGAState {
     int last_hw_cursor_y_start;
     int last_hw_cursor_y_end;
     int real_vram_size; /* XXX: suppress that */
+       int total_vram_size;
     int device_id;
     int bustype;
 } CirrusVGAState;