From: Toni Wilen Date: Wed, 31 Jul 2013 16:52:15 +0000 (+0300) Subject: 2700b4 X-Git-Tag: 2700~14 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=a887c62e17a76d4ece6e1a70f6313a9055ad3bd3;p=francis%2Fwinuae.git 2700b4 --- diff --git a/blkdev.cpp b/blkdev.cpp index 79236da1..2d73639b 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -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) diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index d2ff27c4..c73528f2 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -416,8 +416,11 @@ static void *cdda_play_func (void *v) sector = cdu->cd_last_pos = cdda_pos; t = findtoc (cdu, §or); if (!t) { - write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start); - setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + t = findtoc (cdu, §or + 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; diff --git a/cfgfile.cpp b/cfgfile.cpp index f3bd368b..77cb6f29 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -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 02961f20..30a1a35f 100644 --- 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 ICRA (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 index 00000000..c1361afe --- /dev/null +++ b/cia_old.cpp @@ -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 + +#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 */ diff --git a/custom.cpp b/custom.cpp index 3afb2a3b..2a7d3402 100644 --- a/custom.cpp +++ b/custom.cpp @@ -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 (); diff --git a/debug.cpp b/debug.cpp index 593122d5..39ca7c44 100644 --- 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; } diff --git a/expansion.cpp b/expansion.cpp index c516a9f8..909172f9 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -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; diff --git a/gencpu.cpp b/gencpu.cpp index 63e462c9..4a74c41e 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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++) diff --git a/gfxboard.cpp b/gfxboard.cpp index b14c0f5e..89e1c443 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -13,12 +13,13 @@ #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" @@ -44,12 +45,19 @@ #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; diff --git a/include/cia.h b/include/cia.h index 9cc1b81d..3dae1157 100644 --- a/include/cia.h +++ b/include/cia.h @@ -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); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index bd7c68fc..b71c61db 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -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; diff --git a/include/debug.h b/include/debug.h index 06a9193b..98b8307b 100644 --- a/include/debug.h +++ b/include/debug.h @@ -100,6 +100,7 @@ struct dma_rec uae_u32 addr; uae_u16 evt; int type; + uae_s8 intlev; }; #define DMA_EVENT_BLITIRQ 1 diff --git a/include/events.h b/include/events.h index 66b2308e..73df5264 100644 --- a/include/events.h +++ b/include/events.h @@ -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); diff --git a/include/gfxboard.h b/include/gfxboard.h index c4b2336d..9930be90 100644 --- a/include/gfxboard.h +++ b/include/gfxboard.h @@ -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 diff --git a/include/memory.h b/include/memory.h index b10d3987..204a6539 100644 --- a/include/memory.h +++ b/include/memory.h @@ -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) \ diff --git a/include/newcpu.h b/include/newcpu.h index 9a9bf476..8f647a2d 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -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 diff --git a/include/uae.h b/include/uae.h index f02342b5..a402be73 100644 --- a/include/uae.h +++ b/include/uae.h @@ -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); diff --git a/memory.cpp b/memory.cpp index 6a9294ff..c5214aca 100644 --- a/memory.cpp +++ b/memory.cpp @@ -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++) diff --git a/newcpu.cpp b/newcpu.cpp index d2663eed..543ba6fb 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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 = ®s; + 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 = ®s; @@ -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); + } +} diff --git a/od-win32/avioutput.cpp b/od-win32/avioutput.cpp index 7551b62a..2f987d2b 100644 --- a/od-win32/avioutput.cpp +++ b/od-win32/avioutput.cpp @@ -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)); diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index 9a8971af..e303987e 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -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; diff --git a/od-win32/hardfile_win32.cpp b/od-win32/hardfile_win32.cpp index eb21d02a..1a135be7 100644 --- a/od-win32/hardfile_win32.cpp +++ b/od-win32/hardfile_win32.cpp @@ -33,6 +33,8 @@ #include 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; diff --git a/od-win32/picasso96_win.cpp b/od-win32/picasso96_win.cpp index 3ca906c2..704dcae3 100644 --- a/od-win32/picasso96_win.cpp +++ b/od-win32/picasso96_win.cpp @@ -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); diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 7f181a3f..ca829e89 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -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; diff --git a/od-win32/win32.h b/od-win32/win32.h index 8a554391..043c9300 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,11 +19,11 @@ #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") diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 43d046f8..a3df6e2a 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -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, ¤t_hfdlg.ci.blocksize, NULL)); + _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, ¤t_hfdlg.ci.blocksize, NULL)); } } } else if (LOWORD (wParam) == IDC_HDF_CONTROLLER) { diff --git a/qemuvga/cirrus_vga.cpp b/qemuvga/cirrus_vga.cpp index f310091f..f504a262 100644 --- a/qemuvga/cirrus_vga.cpp +++ b/qemuvga/cirrus_vga.cpp @@ -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; diff --git a/qemuvga/qemuuaeglue.h b/qemuvga/qemuuaeglue.h index 9a41de4e..fb72a076 100644 --- a/qemuvga/qemuuaeglue.h +++ b/qemuvga/qemuuaeglue.h @@ -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;