struct blkdevstate
{
- int scsiemu;
+ bool scsiemu;
+ int type;
struct device_functions *device_func;
int isopen;
int waspaused;
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) {
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);
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)
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);
if (index0 >= 0) {
t->index1 = tn - index0;
}
- if (lastpregap) {
+ if (lastpregap && !secoffset) {
t->index1 = lastpregap;
}
int blockoffset = t->address - t->index1;
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. */
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"),
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);
} 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);
} 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);
+
}
}
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;
*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)
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;
}
}
-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
if (bsp) {
ciabicr |= 8; icr |= 2;
}
+ ciaaicr_reg |= ciaaicr;
+ ciabicr_reg |= ciabicr;
return icr;
}
static void CIA_update (void)
void cia_diskindex (void)
{
+ ciabicr_reg |= 0x10;
ciabicr |= 0x10;
RethinkICRB ();
}
void cia_parallelack (void)
{
+ ciaaicr_reg |= 0x10;
ciaaicr |= 0x10;
RethinkICRA ();
}
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 -1;
return 0;
}
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 ();
}
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 ();
}
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);
}
ciaasdr = kbcode;
kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
ciaaicr |= 8;
+ ciaaicr_reg |= 8;
RethinkICRA ();
}
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)
{
{
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
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);
}
}
}
}
-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)
#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;
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);
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
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;
--- /dev/null
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* CIA chip support
+*
+* Copyright 1995 Bernd Schmidt, Alessandro Bissacco
+* Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
+*/
+
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include <assert.h>
+
+#include "options.h"
+#include "events.h"
+#include "memory.h"
+#include "custom.h"
+#include "newcpu.h"
+#include "cia.h"
+#include "serial.h"
+#include "disk.h"
+#include "xwin.h"
+#include "keybuf.h"
+#include "gui.h"
+#include "savestate.h"
+#include "inputdevice.h"
+#include "zfile.h"
+#include "ar.h"
+#include "parallel.h"
+#include "akiko.h"
+#include "cdtv.h"
+#include "debug.h"
+#include "arcadia.h"
+#include "audio.h"
+#include "keyboard.h"
+#include "uae.h"
+#include "amax.h"
+#include "sampler.h"
+#include "dongle.h"
+#include "inputrecord.h"
+#include "autoconf.h"
+
+#define CIAA_DEBUG_R 0
+#define CIAA_DEBUG_W 0
+#define CIAA_DEBUG_IRQ 0
+
+#define CIAB_DEBUG_R 0
+#define CIAB_DEBUG_W 0
+#define CIAB_DEBUG_IRQ 0
+
+#define DONGLE_DEBUG 0
+#define KB_DEBUG 0
+#define CLOCK_DEBUG 0
+
+#define TOD_HACK
+
+/* e-clock is 10 CPU cycles, 4 cycles high, 6 low
+* data transfer happens during 4 high cycles
+*/
+#define ECLOCK_DATA_CYCLE 4
+#define ECLOCK_WAIT_CYCLE 6
+
+#define DIV10 ((ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) * CYCLE_UNIT / 2) /* Yes, a bad identifier. */
+#define CIASTARTCYCLESHI 3
+#define CIASTARTCYCLESCRA 2
+
+static unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask;
+static unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb;
+static unsigned int ciaastarta, ciaastartb, ciabstarta, ciabstartb;
+static unsigned int ciaaicr_reg, ciabicr_reg;
+
+/* Values of the CIA timers. */
+static unsigned long ciaata, ciaatb, ciabta, ciabtb;
+/* Computed by compute_passed_time. */
+static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
+
+static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
+static int ciaatlatch, ciabtlatch;
+static bool oldled, oldovl, oldcd32mute;
+static bool led;
+static int led_old_brightness;
+static unsigned long led_cycles_on, led_cycles_off, led_cycle;
+
+unsigned int ciabpra;
+
+static unsigned long ciaala, ciaalb, ciabla, ciablb;
+static int ciaatodon, ciabtodon;
+static unsigned int ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr, ciaasdr_cnt;
+static unsigned int ciabprb, ciabdra, ciabdrb, ciabsdr, ciabsdr_cnt;
+static int div10;
+static int kbstate, kblostsynccnt;
+static uae_u8 kbcode;
+
+static uae_u8 serbits;
+static int warned = 10;
+static int rtc_delayed_write;
+
+
+static void setclr (unsigned int *p, unsigned int val)
+{
+ if (val & 0x80) {
+ *p |= val & 0x7F;
+ } else {
+ *p &= ~val;
+ }
+}
+
+static void ICRA(uae_u32 data)
+{
+ if (ciaaimask & ciaaicr) {
+ ciaaicr |= 0x80;
+ INTREQ_0 (0x8000 | data);
+ }
+ ciaaicr_reg |= ciaaicr;
+}
+static void ICRB(uae_u32 data)
+{
+ if (ciabimask & ciabicr) {
+ ciabicr |= 0x80;
+ INTREQ_0 (0x8000 | data);
+ }
+ ciabicr_reg |= ciabicr;
+}
+
+static void RethinkICRA (void)
+{
+ if (ciaaicr) {
+#if CIAA_DEBUG_IRQ
+ write_log (_T("CIAA IRQ %02X\n"), ciaaicr);
+#endif
+ if (currprefs.cpu_cycle_exact)
+ event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x0008, ICRA);
+ else
+ ICRA (0x0008);
+ }
+}
+
+static void RethinkICRB (void)
+{
+ if (ciabicr) {
+#if CIAB_DEBUG_IRQ
+ write_log (_T("CIAB IRQ %02X\n"), ciabicr);
+#endif
+ if (currprefs.cpu_cycle_exact)
+ event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x2000, ICRB);
+ else
+ ICRB (0x2000);
+ }
+}
+
+void rethink_cias (void)
+{
+ RethinkICRA ();
+ RethinkICRB ();
+}
+
+/* Figure out how many CIA timer cycles have passed for each timer since the
+last call of CIA_calctimers. */
+
+static void compute_passed_time (void)
+{
+ unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
+ unsigned long int ciaclocks = ccount / DIV10;
+
+ ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
+
+ /* CIA A timers */
+ if ((ciaacra & 0x21) == 0x01) {
+ unsigned long int cc = ciaclocks;
+ if (cc > ciaastarta)
+ cc -= ciaastarta;
+ else
+ cc = 0;
+ assert ((ciaata + 1) >= cc);
+ ciaata_passed = cc;
+ }
+ if ((ciaacrb & 0x61) == 0x01) {
+ unsigned long int cc = ciaclocks;
+ if (cc > ciaastartb)
+ cc -= ciaastartb;
+ else
+ cc = 0;
+ assert ((ciaatb + 1) >= cc);
+ ciaatb_passed = cc;
+ }
+
+ /* CIA B timers */
+ if ((ciabcra & 0x21) == 0x01) {
+ unsigned long int cc = ciaclocks;
+ if (cc > ciabstarta)
+ cc -= ciabstarta;
+ else
+ cc = 0;
+ assert ((ciabta + 1) >= cc);
+ ciabta_passed = cc;
+ }
+ if ((ciabcrb & 0x61) == 0x01) {
+ unsigned long int cc = ciaclocks;
+ if (cc > ciabstartb)
+ cc -= ciabstartb;
+ else
+ cc = 0;
+ assert ((ciabtb + 1) >= cc);
+ ciabtb_passed = cc;
+ }
+}
+
+/* Called to advance all CIA timers to the current time. This expects that
+one of the timer values will be modified, and CIA_calctimers will be called
+in the same cycle. */
+
+static int CIA_update_check (void)
+{
+ unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
+ unsigned long int ciaclocks = ccount / DIV10;
+
+ int aovfla = 0, aovflb = 0, asp = 0, bovfla = 0, bovflb = 0, bsp = 0;
+ int icr = 0;
+
+ div10 = ccount % DIV10;
+
+ /* CIA A timers */
+ if ((ciaacra & 0x21) == 0x01) {
+ bool check = true;
+ unsigned long int cc = ciaclocks;
+ if (ciaastarta > 0) {
+ if (cc > ciaastarta) {
+ cc -= ciaastarta;
+ ciaastarta = 0;
+ } else {
+ ciaastarta -= cc;
+ check = false;
+ }
+ }
+ if (check) {
+ assert ((ciaata + 1) >= cc);
+ if ((ciaata + 1) == cc) {
+ if ((ciaacra & 0x48) == 0x40 && ciaasdr_cnt > 0 && --ciaasdr_cnt == 0)
+ asp = 1;
+ aovfla = 1;
+ if ((ciaacrb & 0x61) == 0x41 || (ciaacrb & 0x61) == 0x61) {
+ if (ciaatb-- == 0)
+ aovflb = 1;
+ }
+ }
+ ciaata -= cc;
+ }
+ }
+ if ((ciaacrb & 0x61) == 0x01) {
+ bool check = true;
+ unsigned long int cc = ciaclocks;
+ if (ciaastartb > 0) {
+ if (cc > ciaastartb) {
+ cc -= ciaastartb;
+ ciaastartb = 0;
+ } else {
+ ciaastartb -= cc;
+ check = false;
+ }
+ }
+ if (check) {
+ assert ((ciaatb + 1) >= cc);
+ if ((ciaatb + 1) == cc)
+ aovflb = 1;
+ ciaatb -= cc;
+ }
+ }
+
+ /* CIA B timers */
+ if ((ciabcra & 0x21) == 0x01) {
+ bool check = true;
+ unsigned long int cc = ciaclocks;
+ if (ciabstarta > 0) {
+ if (cc > ciabstarta) {
+ cc -= ciabstarta;
+ ciabstarta = 0;
+ } else {
+ ciabstarta -= cc;
+ check = false;
+ }
+ }
+ if (check) {
+ assert ((ciabta + 1) >= cc);
+ if ((ciabta + 1) == cc) {
+ if ((ciabcra & 0x48) == 0x40 && ciabsdr_cnt > 0 && --ciabsdr_cnt == 0)
+ bsp = 1;
+ bovfla = 1;
+ if ((ciabcrb & 0x61) == 0x41 || (ciabcrb & 0x61) == 0x61) {
+ if (ciabtb-- == 0)
+ bovflb = 1;
+ }
+ }
+ ciabta -= cc;
+ }
+ }
+ if ((ciabcrb & 0x61) == 0x01) {
+ bool check = true;
+ unsigned long int cc = ciaclocks;
+ if (ciabstartb > 0) {
+ if (cc > ciabstartb) {
+ cc -= ciabstartb;
+ ciabstartb = 0;
+ } else {
+ ciabstartb -= cc;
+ check = false;
+ }
+ }
+ if (check) {
+ assert ((ciabtb + 1) >= cc);
+ if ((ciabtb + 1) == cc)
+ bovflb = 1;
+ ciabtb -= cc;
+ }
+ }
+
+ if (aovfla) {
+ ciaaicr |= 1; icr = 1;
+ ciaata = ciaala;
+ if (ciaacra & 0x8) {
+ ciaacra &= ~1;
+ }
+ }
+ if (aovflb) {
+ ciaaicr |= 2; icr = 1;
+ ciaatb = ciaalb;
+ if (ciaacrb & 0x8) {
+ ciaacrb &= ~1;
+ }
+ }
+ if (asp) {
+ ciaaicr |= 8; icr = 1;
+ }
+ if (bovfla) {
+ ciabicr |= 1; icr |= 2;
+ ciabta = ciabla;
+ if (ciabcra & 0x8) {
+ ciabcra &= ~1;
+ }
+ }
+ if (bovflb) {
+ ciabicr |= 2; icr |= 2;
+ ciabtb = ciablb;
+ if (ciabcrb & 0x8) {
+ ciabcrb &= ~1;
+ }
+ }
+ if (bsp) {
+ ciabicr |= 8; icr |= 2;
+ }
+ return icr;
+}
+static void CIA_update (void)
+{
+ int icr = CIA_update_check ();
+ if (icr & 1)
+ RethinkICRA ();
+ if (icr & 2)
+ RethinkICRB ();
+}
+
+
+/* Call this only after CIA_update has been called in the same cycle. */
+
+static void CIA_calctimers (void)
+{
+ long int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
+ int div10diff = DIV10 - div10;
+
+ eventtab[ev_cia].oldcycles = get_cycles ();
+
+ if ((ciaacra & 0x21) == 0x01) {
+ ciaatimea = div10diff + DIV10 * (ciaata + ciaastarta);
+ }
+#if 0
+ if ((ciaacrb & 0x61) == 0x41) {
+ /* Timer B will not get any pulses if Timer A is off. */
+ if (ciaatimea >= 0) {
+ /* If Timer A is in one-shot mode, and Timer B needs more than
+ * one pulse, it will not underflow. */
+ if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
+ /* Otherwise, we can determine the time of the underflow. */
+ /* This may overflow, however. So just ignore this timer and
+ use the fact that we'll call CIA_handler for the A timer. */
+ /* ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; */
+ }
+ }
+ }
+#endif
+ if ((ciaacrb & 0x61) == 0x01) {
+ ciaatimeb = div10diff + DIV10 * (ciaatb + ciaastartb);
+ }
+
+ if ((ciabcra & 0x21) == 0x01) {
+ ciabtimea = div10diff + DIV10 * (ciabta + ciabstarta);
+ }
+#if 0
+ if ((ciabcrb & 0x61) == 0x41) {
+ /* Timer B will not get any pulses if Timer A is off. */
+ if (ciabtimea >= 0) {
+ /* If Timer A is in one-shot mode, and Timer B needs more than
+ * one pulse, it will not underflow. */
+ if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
+ /* Otherwise, we can determine the time of the underflow. */
+ /* ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; */
+ }
+ }
+ }
+#endif
+ if ((ciabcrb & 0x61) == 0x01) {
+ ciabtimeb = div10diff + DIV10 * (ciabtb + ciabstartb);
+ }
+
+ eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
+ || ciabtimea != -1 || ciabtimeb != -1);
+ if (eventtab[ev_cia].active) {
+ unsigned long int ciatime = ~0L;
+ if (ciaatimea != -1)
+ ciatime = ciaatimea;
+ if (ciaatimeb != -1 && ciaatimeb < ciatime)
+ ciatime = ciaatimeb;
+ if (ciabtimea != -1 && ciabtimea < ciatime)
+ ciatime = ciabtimea;
+ if (ciabtimeb != -1 && ciabtimeb < ciatime)
+ ciatime = ciabtimeb;
+ eventtab[ev_cia].evtime = ciatime + get_cycles ();
+ }
+ events_schedule();
+}
+
+void CIA_handler (void)
+{
+ CIA_update ();
+ CIA_calctimers ();
+}
+
+void cia_diskindex (void)
+{
+ ciabicr |= 0x10;
+ RethinkICRB ();
+}
+void cia_parallelack (void)
+{
+ ciaaicr |= 0x10;
+ RethinkICRA ();
+}
+
+static int checkalarm (unsigned long tod, unsigned long alarm, bool inc)
+{
+ if (tod == alarm)
+ return 1;
+ if (!inc)
+ return 0;
+ /* Amix workaround */
+ if (currprefs.mmu_model)
+ return 0;
+ /* emulate buggy TODMED counter.
+ * it counts: .. 29 2A 2B 2C 2D 2E 2F 20 30 31 32 ..
+ * (2F->20->30 only takes couple of cycles but it will trigger alarm..
+ */
+ if (tod & 0x000fff)
+ return 0;
+ if (((tod - 1) & 0xfff000) == alarm)
+ return 1;
+ return 0;
+}
+
+STATIC_INLINE bool ciab_checkalarm (bool inc, bool irq)
+{
+ // hack: do not trigger alarm interrupt if KS code and both
+ // tod and alarm == 0. This incorrectly triggers on non-cycle exact
+ // modes. Real hardware value written to ciabtod by KS is always
+ // at least 1 or larger due to bus cycle delays when reading
+ // old value.
+ if ((munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000) {
+ if (ciabtod == 0 && ciabalarm == 0)
+ return false;
+ }
+ if (checkalarm (ciabtod, ciabalarm, inc)) {
+#if CIAB_DEBUG_IRQ
+ write_log (_T("CIAB tod %08x %08x\n"), ciabtod, ciabalarm);
+#endif
+ if (irq) {
+ ciabicr |= 4;
+ RethinkICRB ();
+ }
+ return true;
+ }
+ return false;
+}
+
+STATIC_INLINE void ciaa_checkalarm (bool inc)
+{
+ if (checkalarm (ciaatod, ciaaalarm, inc)) {
+#if CIAA_DEBUG_IRQ
+ write_log (_T("CIAA tod %08x %08x\n"), ciaatod, ciaaalarm);
+#endif
+ ciaaicr |= 4;
+ RethinkICRA ();
+ }
+}
+
+#ifdef TOD_HACK
+static uae_u64 tod_hack_tv, tod_hack_tod, tod_hack_tod_last;
+static int tod_hack_enabled;
+#define TOD_HACK_TIME 312 * 50 * 10
+static void tod_hack_reset (void)
+{
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ tod_hack_tv = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
+ tod_hack_tod = ciaatod;
+ tod_hack_tod_last = tod_hack_tod;
+}
+#endif
+
+static int heartbeat_cnt;
+void cia_heartbeat (void)
+{
+ heartbeat_cnt = 10;
+}
+
+static void do_tod_hack (int dotod)
+{
+ struct timeval tv;
+ static int oldrate;
+ uae_u64 t;
+ int rate;
+ int docount = 0;
+
+ if (tod_hack_enabled == 0)
+ return;
+ if (!heartbeat_cnt) {
+ if (tod_hack_enabled > 0)
+ tod_hack_enabled = -1;
+ return;
+ }
+ if (tod_hack_enabled < 0) {
+ tod_hack_enabled = TOD_HACK_TIME;
+ return;
+ }
+ if (tod_hack_enabled > 1) {
+ tod_hack_enabled--;
+ if (tod_hack_enabled == 1) {
+ //write_log (_T("TOD HACK enabled\n"));
+ tod_hack_reset ();
+ }
+ return;
+ }
+
+ if (currprefs.cs_ciaatod == 0)
+ rate = (int)(vblank_hz + 0.5);
+ else if (currprefs.cs_ciaatod == 1)
+ rate = 50;
+ else
+ rate = 60;
+ if (rate <= 0)
+ return;
+ if (rate != oldrate || ciaatod != tod_hack_tod_last) {
+ //if (ciaatod != 0)
+ // write_log (_T("TOD HACK reset %d,%d %d,%d\n"), rate, oldrate, ciaatod, tod_hack_tod_last);
+ tod_hack_reset ();
+ oldrate = rate;
+ docount = 1;
+ }
+ if (!dotod && currprefs.cs_ciaatod == 0)
+ return;
+ gettimeofday (&tv, NULL);
+ t = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
+ if (t - tod_hack_tv >= 1000000 / rate) {
+ tod_hack_tv += 1000000 / rate;
+ docount = 1;
+ }
+ if (docount) {
+ ciaatod++;
+ ciaatod &= 0x00ffffff;
+ tod_hack_tod_last = ciaatod;
+ ciaa_checkalarm (false);
+ }
+}
+
+static int resetwarning_phase, resetwarning_timer;
+
+static void setcode (uae_u8 keycode)
+{
+ kbcode = ~((keycode << 1) | (keycode >> 7));
+}
+
+static void sendrw (void)
+{
+ setcode (AK_RESETWARNING);
+ ciaasdr = kbcode;
+ kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
+ ciaaicr |= 8;
+ RethinkICRA ();
+ write_log (_T("KB: sent reset warning code (phase=%d)\n"), resetwarning_phase);
+}
+
+int resetwarning_do (int canreset)
+{
+ if (resetwarning_phase) {
+ /* just force reset if second reset happens during resetwarning */
+ if (canreset) {
+ resetwarning_phase = 0;
+ resetwarning_timer = 0;
+ }
+ return 0;
+ }
+ resetwarning_phase = 1;
+ resetwarning_timer = maxvpos_nom * 5;
+ write_log (_T("KB: reset warning triggered\n"));
+ sendrw ();
+ return 1;
+}
+
+static void resetwarning_check (void)
+{
+ if (resetwarning_timer > 0) {
+ resetwarning_timer--;
+ if (resetwarning_timer <= 0) {
+ write_log (_T("KB: reset warning forced reset. Phase=%d\n"), resetwarning_phase);
+ resetwarning_phase = -1;
+ kblostsynccnt = 0;
+ send_internalevent (INTERNALEVENT_KBRESET);
+ uae_reset (0, 1);
+ }
+ }
+ if (resetwarning_phase == 1) {
+ if (!kblostsynccnt) { /* first AK_RESETWARNING handshake received */
+ write_log (_T("KB: reset warning second phase..\n"));
+ resetwarning_phase = 2;
+ resetwarning_timer = maxvpos_nom * 5;
+ sendrw ();
+ }
+ } else if (resetwarning_phase == 2) {
+ if (ciaacra & 0x40) { /* second AK_RESETWARNING handshake active */
+ resetwarning_phase = 3;
+ write_log (_T("KB: reset warning SP = output\n"));
+ /* System won't reset until handshake signal becomes inactive or 10s has passed */
+ resetwarning_timer = 10 * maxvpos_nom * vblank_hz;
+ }
+ } else if (resetwarning_phase == 3) {
+ if (!(ciaacra & 0x40)) { /* second AK_RESETWARNING handshake disabled */
+ write_log (_T("KB: reset warning end by software. reset.\n"));
+ resetwarning_phase = -1;
+ kblostsynccnt = 0;
+ send_internalevent (INTERNALEVENT_KBRESET);
+ uae_reset (0, 1);
+ }
+ }
+}
+
+void CIA_hsync_prehandler (void)
+{
+}
+
+static void keyreq (void)
+{
+#if KB_DEBUG
+ write_log (_T("code=%x\n"), kbcode);
+#endif
+ ciaasdr = kbcode;
+ kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
+ ciaaicr |= 8;
+ RethinkICRA ();
+}
+
+/* All this complexity to lazy evaluate TOD increase.
+ * Only increase it cycle-exactly if it is visible to running program:
+ * causes interrupt or program is reading or writing TOD registers
+ */
+
+static int ciab_tod_hoffset;
+static int ciab_tod_event_state;
+// TOD increase has extra 14-16 E-clock delay
+// Possibly TICK input pin has built-in debounce circuit
+#define TOD_INC_DELAY (14 * (ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) / 2)
+
+static void CIAB_tod_inc (uae_u32 v)
+{
+ ciab_tod_event_state = 3; // done
+ ciabtod++;
+ ciabtod &= 0xFFFFFF;
+ ciab_checkalarm (true, true);
+}
+
+// Someone reads or writes TOD registers, sync TOD increase
+static void CIAB_tod_check (void)
+{
+ if (ciab_tod_event_state != 1 || !ciabtodon)
+ return;
+ int hpos = current_hpos ();
+ hpos -= ciab_tod_hoffset;
+ if (hpos >= 0 || currprefs.m68k_speed < 0) {
+ // Program should see the changed TOD
+ CIAB_tod_inc (0);
+ return;
+ }
+ // Not yet, add event to guarantee exact TOD inc position
+ ciab_tod_event_state = 2; // event active
+ event2_newevent_xx (-1, -hpos, 0, CIAB_tod_inc);
+}
+
+void CIAB_tod_handler (int hoffset)
+{
+ uae_u32 v;
+
+ ciab_tod_hoffset = hoffset + TOD_INC_DELAY;
+ if (!ciabtodon)
+ return;
+ ciab_tod_event_state = 1; // TOD inc needed
+ v = ciabtod;
+ ciabtod++;
+ ciabtod &= 0xFFFFFF;
+ bool irq = ciab_checkalarm (false, false);
+ ciabtod = v;
+ if (irq) {
+ // causes interrupt on this line, add event
+ ciab_tod_event_state = 2; // event active
+ event2_newevent_xx (-1, ciab_tod_hoffset, 0, CIAB_tod_inc);
+ }
+}
+
+void CIA_hsync_posthandler (bool dotod)
+{
+ // Previous line was supposed to increase TOD but
+ // no one cared. Do it now at the start of next line.
+ if (ciab_tod_event_state == 1)
+ CIAB_tod_inc (0);
+ ciab_tod_event_state = 0;
+
+ if (currprefs.tod_hack && ciaatodon)
+ do_tod_hack (dotod);
+
+ if (resetwarning_phase) {
+ resetwarning_check ();
+ while (keys_available ())
+ get_next_key ();
+ } else if ((keys_available () || kbstate < 3) && !kblostsynccnt && (hsync_counter & 15) == 0) {
+ switch (kbstate)
+ {
+ case 0:
+ kbcode = 0; /* powerup resync */
+ kbstate++;
+ break;
+ case 1:
+ setcode (AK_INIT_POWERUP);
+ kbstate++;
+ break;
+ case 2:
+ setcode (AK_TERM_POWERUP);
+ kbstate++;
+ break;
+ case 3:
+ kbcode = ~get_next_key ();
+ break;
+ }
+ keyreq ();
+ }
+}
+
+static void calc_led (int old_led)
+{
+ unsigned long c = get_cycles ();
+ unsigned long t = (c - led_cycle) / CYCLE_UNIT;
+ if (old_led)
+ led_cycles_on += t;
+ else
+ led_cycles_off += t;
+ led_cycle = c;
+}
+
+static void led_vsync (void)
+{
+ int v;
+
+ calc_led (led);
+ if (led_cycles_on && !led_cycles_off)
+ v = 255;
+ else if (led_cycles_off && !led_cycles_on)
+ v = 0;
+ else if (led_cycles_off)
+ v = led_cycles_on * 255 / (led_cycles_on + led_cycles_off);
+ else
+ v = 255;
+ if (v < 0)
+ v = 0;
+ if (v > 255)
+ v = 255;
+ gui_data.powerled_brightness = v;
+ led_cycles_on = 0;
+ led_cycles_off = 0;
+ if (led_old_brightness != gui_data.powerled_brightness) {
+ gui_data.powerled = gui_data.powerled_brightness > 127;
+ gui_led (LED_POWER, gui_data.powerled);
+ led_filter_audio ();
+ }
+ led_old_brightness = gui_data.powerled_brightness;
+ led_cycle = get_cycles ();
+}
+
+static void write_battclock (void);
+void CIA_vsync_prehandler (void)
+{
+ if (heartbeat_cnt > 0)
+ heartbeat_cnt--;
+ if (rtc_delayed_write < 0) {
+ rtc_delayed_write = 50;
+ } else if (rtc_delayed_write > 0) {
+ rtc_delayed_write--;
+ if (rtc_delayed_write == 0)
+ write_battclock ();
+ }
+ led_vsync ();
+ CIA_handler ();
+ if (kblostsynccnt > 0) {
+ kblostsynccnt -= maxvpos;
+ if (kblostsynccnt <= 0) {
+ kblostsynccnt = 0;
+ keyreq ();
+#if KB_DEBUG
+ write_log (_T("lostsync\n"));
+#endif
+ }
+ }
+}
+
+static void CIAA_tod_handler (uae_u32 v)
+{
+ ciaatod++;
+ ciaatod &= 0xFFFFFF;
+ ciaa_checkalarm (true);
+}
+
+void CIAA_tod_inc (int cycles)
+{
+#ifdef TOD_HACK
+ if (currprefs.tod_hack && tod_hack_enabled == 1)
+ return;
+#endif
+ if (!ciaatodon)
+ return;
+ event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
+}
+
+static void bfe001_change (void)
+{
+ uae_u8 v = ciaapra;
+ bool led2;
+
+ v |= ~ciaadra; /* output is high when pin's direction is input */
+ led2 = (v & 2) ? 0 : 1;
+ if (led2 != led) {
+ calc_led (led);
+ led = led2;
+ led_old_brightness = -1;
+ }
+ if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
+ oldovl = v & 1;
+ if (!oldovl) {
+ map_overlay (1);
+ } else {
+ //activate_debugger ();
+ map_overlay (0);
+ }
+ }
+ if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) {
+ oldcd32mute = v & 1;
+ akiko_mute (oldcd32mute ? 0 : 1);
+ }
+}
+
+static uae_u8 ReadCIAA (unsigned int addr)
+{
+ unsigned int tmp;
+ int reg = addr & 15;
+
+ compute_passed_time ();
+
+#if CIAA_DEBUG_R > 0
+ write_log (_T("R_CIAA: bfe%x01 %08X\n"), reg, M68K_GETPC);
+#endif
+
+ switch (reg) {
+ case 0:
+#ifdef ACTION_REPLAY
+ action_replay_ciaread ();
+#endif
+ tmp = DISK_status() & 0x3c;
+ tmp |= handle_joystick_buttons (ciaapra, ciaadra);
+ tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03;
+ tmp = dongle_cia_read (0, reg, tmp);
+#if DONGLE_DEBUG > 0
+ if (notinrom())
+ write_log (_T("BFE001 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+
+ if (inputrecord_debug & 2) {
+ if (input_record > 0)
+ inprec_recorddebug_cia (tmp, div10, m68k_getpc ());
+ else if (input_play > 0)
+ inprec_playdebug_cia (tmp, div10, m68k_getpc ());
+ }
+
+ return tmp;
+ case 1:
+#ifdef PARALLEL_PORT
+ if (isprinter () > 0) {
+ tmp = ciaaprb;
+ } else if (isprinter () < 0) {
+ uae_u8 v;
+ parallel_direct_read_data (&v);
+ tmp = v;
+#ifdef ARCADIA
+ } else if (arcadia_bios) {
+ tmp = arcadia_parport (0, ciaaprb, ciaadrb);
+#endif
+ } else if (currprefs.win32_samplersoundcard >= 0) {
+
+ tmp = sampler_getsample ((ciabpra & 4) ? 1 : 0);
+
+ } else
+#endif
+
+ {
+ tmp = handle_parport_joystick (0, ciaaprb, ciaadrb);
+ tmp = dongle_cia_read (1, reg, tmp);
+#if DONGLE_DEBUG > 0
+ if (notinrom())
+ write_log (_T("BFE101 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+ }
+ if (ciaacrb & 2) {
+ int pb7 = 0;
+ if (ciaacrb & 4)
+ pb7 = ciaacrb & 1;
+ tmp &= ~0x80;
+ tmp |= pb7 ? 0x80 : 00;
+ }
+ if (ciaacra & 2) {
+ int pb6 = 0;
+ if (ciaacra & 4)
+ pb6 = ciaacra & 1;
+ tmp &= ~0x40;
+ tmp |= pb6 ? 0x40 : 00;
+ }
+ return tmp;
+ case 2:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE201 R %02X %s\n"), ciaadra, debuginfo(0));
+#endif
+ return ciaadra;
+ case 3:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE301 R %02X %s\n"), ciaadrb, debuginfo(0));
+#endif
+ return ciaadrb;
+ case 4:
+ return (uae_u8)((ciaata - ciaata_passed) & 0xff);
+ case 5:
+ return (uae_u8)((ciaata - ciaata_passed) >> 8);
+ case 6:
+ return (uae_u8)((ciaatb - ciaatb_passed) & 0xff);
+ case 7:
+ return (uae_u8)((ciaatb - ciaatb_passed) >> 8);
+ case 8:
+ if (ciaatlatch) {
+ ciaatlatch = 0;
+ return (uae_u8)ciaatol;
+ } else
+ return (uae_u8)ciaatod;
+ case 9:
+ if (ciaatlatch)
+ return (uae_u8)(ciaatol >> 8);
+ else
+ return (uae_u8)(ciaatod >> 8);
+ case 10:
+ if (!ciaatlatch) { /* only if not already latched. A1200 confirmed. (TW) */
+ /* no latching if ALARM is set */
+ if (!(ciaacrb & 0x80))
+ ciaatlatch = 1;
+ ciaatol = ciaatod;
+ }
+ return (uae_u8)(ciaatol >> 16);
+ case 12:
+#if KB_DEBUG
+ write_log (_T("CIAA serial port: %02x %08x\n"), ciaasdr, M68K_GETPC);
+#endif
+ return ciaasdr;
+ case 13:
+ tmp = ciaaicr_reg;
+ ciaaicr &= ~ciaaicr_reg;
+ ciaaicr_reg = 0;
+ RethinkICRA ();
+ return tmp;
+ case 14:
+ return ciaacra;
+ case 15:
+ return ciaacrb;
+ }
+ return 0;
+}
+
+static uae_u8 ReadCIAB (unsigned int addr)
+{
+ unsigned int tmp;
+ int reg = addr & 15;
+
+#if CIAB_DEBUG_R > 0
+ if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_R > 1)
+ write_log (_T("R_CIAB: bfd%x00 %08X\n"), reg, M68K_GETPC);
+#endif
+
+ compute_passed_time ();
+
+ switch (reg) {
+ case 0:
+ tmp = 0;
+#ifdef SERIAL_PORT
+ if (currprefs.use_serial)
+ tmp = serial_readstatus(ciabdra);
+#endif
+#ifdef PARALLEL_PORT
+ if (isprinter () > 0) {
+ //tmp |= ciabpra & (0x04 | 0x02 | 0x01);
+ tmp &= ~3; // clear BUSY and PAPEROUT
+ tmp |= 4; // set SELECT
+ } else if (isprinter () < 0) {
+ uae_u8 v;
+ parallel_direct_read_status (&v);
+ tmp |= v & 7;
+ } else {
+ tmp |= handle_parport_joystick (1, ciabpra, ciabdra);
+ }
+#endif
+ tmp = dongle_cia_read (1, reg, tmp);
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD000 R %02X %s\n"), tmp, debuginfo(0));
+#endif
+ return tmp;
+ case 1:
+#ifdef ACTION_REPLAY
+ action_replay_ciaread ();
+#endif
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD100 R %02X %s\n"), ciabprb, debuginfo(0));
+#endif
+ tmp = ciabprb;
+ tmp = dongle_cia_read (1, reg, tmp);
+ if (ciabcrb & 2) {
+ int pb7 = 0;
+ if (ciabcrb & 4)
+ pb7 = ciabcrb & 1;
+ tmp &= ~0x80;
+ tmp |= pb7 ? 0x80 : 00;
+ }
+ if (ciabcra & 2) {
+ int pb6 = 0;
+ if (ciabcra & 4)
+ pb6 = ciabcra & 1;
+ tmp &= ~0x40;
+ tmp |= pb6 ? 0x40 : 00;
+ }
+ return tmp;
+ case 2:
+ return ciabdra;
+ case 3:
+ return ciabdrb;
+ case 4:
+ return (uae_u8)((ciabta - ciabta_passed) & 0xff);
+ case 5:
+ return (uae_u8)((ciabta - ciabta_passed) >> 8);
+ case 6:
+ return (uae_u8)((ciabtb - ciabtb_passed) & 0xff);
+ case 7:
+ return (uae_u8)((ciabtb - ciabtb_passed) >> 8);
+ case 8:
+ CIAB_tod_check ();
+ if (ciabtlatch) {
+ ciabtlatch = 0;
+ return (uae_u8)ciabtol;
+ } else
+ return (uae_u8)ciabtod;
+ case 9:
+ CIAB_tod_check ();
+ if (ciabtlatch)
+ return (uae_u8)(ciabtol >> 8);
+ else
+ return (uae_u8)(ciabtod >> 8);
+ case 10:
+ CIAB_tod_check ();
+ if (!ciabtlatch) {
+ /* no latching if ALARM is set */
+ if (!(ciabcrb & 0x80))
+ ciabtlatch = 1;
+ ciabtol = ciabtod;
+ }
+ return (uae_u8)(ciabtol >> 16);
+ case 12:
+ return ciabsdr;
+ case 13:
+ tmp = ciabicr_reg;
+ ciabicr &= ~ciabicr_reg;
+ ciabicr_reg = 0;
+ RethinkICRB ();
+ return tmp;
+ case 14:
+ //write_log (_T("CIABCRA READ %d %x\n"), ciabcra, M68K_GETPC);
+ return ciabcra;
+ case 15:
+ return ciabcrb;
+ }
+ return 0;
+}
+
+static void WriteCIAA (uae_u16 addr, uae_u8 val)
+{
+ int reg = addr & 15;
+
+#if CIAA_DEBUG_W > 0
+ write_log (_T("W_CIAA: bfe%x01 %02X %08X\n"), reg, val, M68K_GETPC);
+#endif
+#ifdef ACTION_REPLAY
+ ar_ciaa[reg] = val;
+#endif
+ if (!currprefs.cs_ciaoverlay && oldovl) {
+ map_overlay (1);
+ oldovl = 0;
+ }
+ switch (reg) {
+ case 0:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE001 W %02X %s\n"), val, debuginfo(0));
+#endif
+ ciaapra = (ciaapra & ~0xc3) | (val & 0xc3);
+ bfe001_change ();
+ handle_cd32_joystick_cia (ciaapra, ciaadra);
+ dongle_cia_write (0, reg, val);
+#ifdef AMAX
+ if (currprefs.amaxromfile[0])
+ amax_bfe001_write (val, ciaadra);
+#endif
+ break;
+ case 1:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE101 W %02X %s\n"), val, debuginfo(0));
+#endif
+ ciaaprb = val;
+ dongle_cia_write (0, reg, val);
+#ifdef PARALLEL_PORT
+ if (isprinter() > 0) {
+ doprinter (val);
+ cia_parallelack ();
+ } else if (isprinter() < 0) {
+ parallel_direct_write_data (val, ciaadrb);
+ cia_parallelack ();
+#ifdef ARCADIA
+ } else if (arcadia_bios) {
+ arcadia_parport (1, ciaaprb, ciaadrb);
+#endif
+ }
+#endif
+ break;
+ case 2:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE201 W %02X %s\n"), val, debuginfo(0));
+#endif
+ ciaadra = val;
+ dongle_cia_write (0, reg, val);
+ bfe001_change ();
+ break;
+ case 3:
+ ciaadrb = val;
+ dongle_cia_write (0, reg, val);
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFE301 W %02X %s\n"), val, debuginfo(0));
+#endif
+#ifdef ARCADIA
+ if (arcadia_bios)
+ arcadia_parport (1, ciaaprb, ciaadrb);
+#endif
+ break;
+ case 4:
+ CIA_update ();
+ ciaala = (ciaala & 0xff00) | val;
+ CIA_calctimers ();
+ break;
+ case 5:
+ CIA_update ();
+ ciaala = (ciaala & 0xff) | (val << 8);
+ if ((ciaacra & 1) == 0)
+ ciaata = ciaala;
+ if (ciaacra & 8) {
+ ciaata = ciaala;
+ ciaacra |= 1;
+ ciaastarta = CIASTARTCYCLESHI;
+ }
+ CIA_calctimers ();
+ break;
+ case 6:
+ CIA_update ();
+ ciaalb = (ciaalb & 0xff00) | val;
+ CIA_calctimers ();
+ break;
+ case 7:
+ CIA_update ();
+ ciaalb = (ciaalb & 0xff) | (val << 8);
+ if ((ciaacrb & 1) == 0)
+ ciaatb = ciaalb;
+ if (ciaacrb & 8) {
+ ciaatb = ciaalb;
+ ciaacrb |= 1;
+ ciaastartb = CIASTARTCYCLESHI;
+ }
+ CIA_calctimers ();
+ break;
+ case 8:
+ if (ciaacrb & 0x80) {
+ ciaaalarm = (ciaaalarm & ~0xff) | val;
+ } else {
+ ciaatod = (ciaatod & ~0xff) | val;
+ ciaatodon = 1;
+ ciaa_checkalarm (false);
+ }
+ break;
+ case 9:
+ if (ciaacrb & 0x80) {
+ ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
+ } else {
+ ciaatod = (ciaatod & ~0xff00) | (val << 8);
+ }
+ break;
+ case 10:
+ if (ciaacrb & 0x80) {
+ ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
+ } else {
+ ciaatod = (ciaatod & ~0xff0000) | (val << 16);
+ ciaatodon = 0;
+ }
+ break;
+ case 12:
+ CIA_update ();
+ ciaasdr = val;
+ if ((ciaacra & 0x41) == 0x41 && ciaasdr_cnt == 0)
+ ciaasdr_cnt = 8 * 2;
+#if KB_DEBUG
+ write_log (_T("CIAA serial port write: %02x cnt=%d PC=%08x\n"), ciaasdr, ciaasdr_cnt, M68K_GETPC);
+#endif
+ CIA_calctimers ();
+ break;
+ case 13:
+ setclr (&ciaaimask,val);
+ break;
+ case 14:
+ CIA_update ();
+ val &= 0x7f; /* bit 7 is unused */
+ if ((val & 1) && !(ciaacra & 1))
+ ciaastarta = CIASTARTCYCLESCRA;
+ if ((val & 0x40) == 0 && (ciaacra & 0x40) != 0) {
+ /* todo: check if low to high or high to low only */
+ kblostsynccnt = 0;
+#if KB_DEBUG
+ write_log (_T("KB_ACK %02x->%02x\n"), ciaacra, val);
+#endif
+ }
+ ciaacra = val;
+ if (ciaacra & 0x10) {
+ ciaacra &= ~0x10;
+ ciaata = ciaala;
+ }
+ CIA_calctimers ();
+ break;
+ case 15:
+ CIA_update ();
+ if ((val & 1) && !(ciaacrb & 1))
+ ciaastartb = CIASTARTCYCLESCRA;
+ ciaacrb = val;
+ if (ciaacrb & 0x10) {
+ ciaacrb &= ~0x10;
+ ciaatb = ciaalb;
+ }
+ CIA_calctimers ();
+ break;
+ }
+}
+
+static void WriteCIAB (uae_u16 addr, uae_u8 val)
+{
+ int reg = addr & 15;
+
+#if CIAB_DEBUG_W > 0
+ if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_W > 1)
+ write_log (_T("W_CIAB: bfd%x00 %02X %08X\n"), reg, val, M68K_GETPC);
+#endif
+#ifdef ACTION_REPLAY
+ ar_ciab[reg] = val;
+#endif
+ switch (reg) {
+ case 0:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD000 W %02X %s\n"), val, debuginfo(0));
+#endif
+ dongle_cia_write (1, reg, val);
+ ciabpra = val;
+#ifdef SERIAL_PORT
+ if (currprefs.use_serial)
+ serial_writestatus(ciabpra, ciabdra);
+#endif
+#ifdef PARALLEL_PORT
+ if (isprinter () < 0)
+ parallel_direct_write_status (val, ciabdra);
+#endif
+ break;
+ case 1:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD100 W %02X %s\n"), val, debuginfo(0));
+#endif
+ dongle_cia_write (1, reg, val);
+ ciabprb = val;
+ DISK_select (val);
+ break;
+ case 2:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD200 W %02X %s\n"), val, debuginfo(0));
+#endif
+ dongle_cia_write (1, reg, val);
+ ciabdra = val;
+#ifdef SERIAL_PORT
+ if (currprefs.use_serial)
+ serial_writestatus (ciabpra, ciabdra);
+#endif
+ break;
+ case 3:
+#if DONGLE_DEBUG > 0
+ if (notinrom ())
+ write_log (_T("BFD300 W %02X %s\n"), val, debuginfo(0));
+#endif
+ dongle_cia_write (1, reg, val);
+ ciabdrb = val;
+ break;
+ case 4:
+ CIA_update ();
+ ciabla = (ciabla & 0xff00) | val;
+ CIA_calctimers ();
+ break;
+ case 5:
+ CIA_update ();
+ ciabla = (ciabla & 0xff) | (val << 8);
+ if ((ciabcra & 1) == 0)
+ ciabta = ciabla;
+ if (ciabcra & 8) {
+ ciabta = ciabla;
+ ciabcra |= 1;
+ ciabstarta = CIASTARTCYCLESHI;
+ }
+ CIA_calctimers ();
+ break;
+ case 6:
+ CIA_update ();
+ ciablb = (ciablb & 0xff00) | val;
+ CIA_calctimers ();
+ break;
+ case 7:
+ CIA_update ();
+ ciablb = (ciablb & 0xff) | (val << 8);
+ if ((ciabcrb & 1) == 0)
+ ciabtb = ciablb;
+ if (ciabcrb & 8) {
+ ciabtb = ciablb;
+ ciabcrb |= 1;
+ ciabstartb = CIASTARTCYCLESHI;
+ }
+ CIA_calctimers ();
+ break;
+ case 8:
+ CIAB_tod_check ();
+ if (ciabcrb & 0x80) {
+ ciabalarm = (ciabalarm & ~0xff) | val;
+ } else {
+ ciabtod = (ciabtod & ~0xff) | val;
+ ciabtodon = 1;
+ ciab_checkalarm (false, true);
+ }
+ break;
+ case 9:
+ CIAB_tod_check ();
+ if (ciabcrb & 0x80) {
+ ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
+ } else {
+ ciabtod = (ciabtod & ~0xff00) | (val << 8);
+ }
+ break;
+ case 10:
+ CIAB_tod_check ();
+ if (ciabcrb & 0x80) {
+ ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
+ } else {
+ ciabtod = (ciabtod & ~0xff0000) | (val << 16);
+ ciabtodon = 0;
+ }
+ break;
+ case 12:
+ CIA_update ();
+ ciabsdr = val;
+ if ((ciabcra & 0x40) == 0)
+ ciabsdr_cnt = 0;
+ if ((ciabcra & 0x41) == 0x41 && ciabsdr_cnt == 0)
+ ciabsdr_cnt = 8 * 2;
+ CIA_calctimers ();
+ break;
+ case 13:
+ setclr (&ciabimask, val);
+ break;
+ case 14:
+ CIA_update ();
+ val &= 0x7f; /* bit 7 is unused */
+ if ((val & 1) && !(ciabcra & 1))
+ ciabstarta = CIASTARTCYCLESCRA;
+ ciabcra = val;
+ if (ciabcra & 0x10) {
+ ciabcra &= ~0x10;
+ ciabta = ciabla;
+ }
+ CIA_calctimers ();
+ break;
+ case 15:
+ CIA_update ();
+ if ((val & 1) && !(ciabcrb & 1))
+ ciabstartb = CIASTARTCYCLESCRA;
+ ciabcrb = val;
+ if (ciabcrb & 0x10) {
+ ciabcrb &= ~0x10;
+ ciabtb = ciablb;
+ }
+ CIA_calctimers ();
+ break;
+ }
+}
+
+void cia_set_overlay (bool overlay)
+{
+ oldovl = overlay;
+}
+
+void CIA_reset (void)
+{
+#ifdef TOD_HACK
+ tod_hack_tv = 0;
+ tod_hack_tod = 0;
+ tod_hack_enabled = 0;
+ if (currprefs.tod_hack)
+ tod_hack_enabled = TOD_HACK_TIME;
+#endif
+
+ kblostsynccnt = 0;
+ serbits = 0;
+ oldcd32mute = 1;
+ oldled = true;
+ resetwarning_phase = resetwarning_timer = 0;
+ heartbeat_cnt = 0;
+ ciab_tod_event_state = 0;
+
+ if (!savestate_state) {
+ oldovl = true;
+ kbstate = 0;
+ ciaatlatch = ciabtlatch = 0;
+ ciaapra = 0; ciaadra = 0;
+ ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
+ ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
+ ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
+ ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
+ ciaaalarm = ciabalarm = 0;
+ ciabpra = 0x8C; ciabdra = 0;
+ div10 = 0;
+ ciaasdr_cnt = 0; ciaasdr = 0;
+ ciabsdr_cnt = 0; ciabsdr = 0;
+ ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
+ CIA_calctimers ();
+ DISK_select_set (ciabprb);
+ }
+ map_overlay (0);
+#ifdef SERIAL_PORT
+ if (currprefs.use_serial && !savestate_state)
+ serial_dtr_off (); /* Drop DTR at reset */
+#endif
+ if (savestate_state) {
+ if (currprefs.cs_ciaoverlay) {
+ oldovl = true;
+ }
+ bfe001_change ();
+ if (!currprefs.cs_ciaoverlay) {
+ map_overlay (oldovl ? 0 : 1);
+ }
+ }
+#ifdef CD32
+ if (!isrestore ()) {
+ akiko_reset ();
+ if (!akiko_init ())
+ currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = 0;
+ }
+#endif
+}
+
+void dumpcia (void)
+{
+ console_out_f (_T("A: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
+ ciaacra, ciaacrb, ciaaicr, ciaaimask, ciaata, ciaala, ciaatb, ciaalb);
+ console_out_f (_T("TOD %06x (%06x) ALARM %06x %c%c CYC=%08X\n"),
+ ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S', get_cycles ());
+ console_out_f (_T("B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
+ ciabcra, ciabcrb, ciabicr, ciabimask, ciabta, ciabla, ciabtb, ciablb);
+ console_out_f (_T("TOD %06x (%06x) ALARM %06x %c%c CLK=%d\n"),
+ ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S', div10 / CYCLE_UNIT);
+}
+
+/* CIA memory access */
+
+static uae_u32 REGPARAM3 cia_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_bget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_lgeti (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 cia_wgeti (uaecptr) REGPARAM;
+static void REGPARAM3 cia_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 cia_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 cia_bput (uaecptr, uae_u32) REGPARAM;
+
+addrbank cia_bank = {
+ cia_lget, cia_wget, cia_bget,
+ cia_lput, cia_wput, cia_bput,
+ default_xlate, default_check, NULL, _T("CIA"),
+ cia_lgeti, cia_wgeti, ABFLAG_IO, 0x3f00, 0xbfc000
+};
+
+// Gayle or Fat Gary does not enable CIA /CS lines if both CIAs are selected
+// Old Gary based Amigas enable both CIAs in this situation
+
+STATIC_INLINE bool issinglecia (void)
+{
+ return currprefs.cs_ide || currprefs.cs_pcmcia || currprefs.cs_mbdmac;
+}
+STATIC_INLINE bool isgayle (void)
+{
+ return currprefs.cs_ide || currprefs.cs_pcmcia;
+}
+
+static void cia_wait_pre (void)
+{
+ if (currprefs.cachesize)
+ return;
+
+#ifndef CUSTOM_SIMPLE
+ int div = (get_cycles () - eventtab[ev_cia].oldcycles) % DIV10;
+ int cycles;
+
+ if (div >= DIV10 * ECLOCK_DATA_CYCLE / 10) {
+ cycles = DIV10 - div;
+ cycles += DIV10 * ECLOCK_DATA_CYCLE / 10;
+ } else if (div) {
+ cycles = DIV10 + DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
+ } else {
+ cycles = DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
+ }
+
+ if (cycles) {
+ if (currprefs.cpu_cycle_exact)
+ x_do_cycles_pre (cycles);
+ else
+ do_cycles (cycles);
+ }
+#endif
+}
+
+static void cia_wait_post (uae_u32 value)
+{
+ if (currprefs.cachesize) {
+ do_cycles (8 * CYCLE_UNIT /2);
+ } else {
+ int c = 6 * CYCLE_UNIT / 2;
+ if (currprefs.cpu_cycle_exact)
+ x_do_cycles_post (c, value);
+ else
+ do_cycles (c);
+ }
+}
+
+static bool isgaylenocia (uaecptr addr)
+{
+ // gayle CIA region is only 4096 bytes at 0xbfd000 and 0xbfe000
+ if (!isgayle ())
+ return true;
+ uaecptr mask = addr & 0xf000;
+ bool cia = mask == 0xe000 || mask == 0xd000;
+ return cia;
+}
+
+static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
+{
+ int r = (addr & 0xf00) >> 8;
+ uae_u8 v = 0xff;
+
+#ifdef JIT
+ special_mem |= S_READ;
+#endif
+
+ if (!isgaylenocia (addr))
+ return v;
+
+ cia_wait_pre ();
+ switch ((addr >> 12) & 3) {
+ case 0:
+ if (!issinglecia ())
+ v = (addr & 1) ? ReadCIAA (r) : ReadCIAB (r);
+ break;
+ case 1:
+ v = (addr & 1) ? 0xff : ReadCIAB (r);
+ break;
+ case 2:
+ v = (addr & 1) ? ReadCIAA (r) : 0xff;
+ break;
+ case 3:
+ if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+ v = (addr & 1) ? regs.irc : regs.irc >> 8;
+ if (warned > 0 || currprefs.illegal_mem) {
+ write_log (_T("cia_bget: unknown CIA address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC);
+ warned--;
+ }
+ break;
+ }
+ cia_wait_post (v);
+
+ return v;
+}
+
+static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
+{
+ int r = (addr & 0xf00) >> 8;
+ uae_u16 v = 0xffff;
+
+#ifdef JIT
+ special_mem |= S_READ;
+#endif
+
+ if (!isgaylenocia (addr))
+ return v;
+
+ cia_wait_pre ();
+ switch ((addr >> 12) & 3)
+ {
+ case 0:
+ if (!issinglecia ())
+ v = (ReadCIAB (r) << 8) | ReadCIAA (r);
+ break;
+ case 1:
+ v = (ReadCIAB (r) << 8) | 0xff;
+ break;
+ case 2:
+ v = (0xff << 8) | ReadCIAA (r);
+ break;
+ case 3:
+ if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+ v = regs.irc;
+ if (warned > 0 || currprefs.illegal_mem) {
+ write_log (_T("cia_wget: unknown CIA address %08X=%04X PC=%08X\n"), addr, v & 0xffff, M68K_GETPC);
+ warned--;
+ }
+ break;
+ }
+ cia_wait_post (v);
+ return v;
+}
+
+static uae_u32 REGPARAM2 cia_lget (uaecptr addr)
+{
+ uae_u32 v;
+ v = cia_wget (addr) << 16;
+ v |= cia_wget (addr + 2);
+ return v;
+}
+
+static uae_u32 REGPARAM2 cia_wgeti (uaecptr addr)
+{
+ if (currprefs.cpu_model >= 68020)
+ return dummy_wgeti (addr);
+ return cia_wget (addr);
+}
+static uae_u32 REGPARAM2 cia_lgeti (uaecptr addr)
+{
+ if (currprefs.cpu_model >= 68020)
+ return dummy_lgeti (addr);
+ return cia_lget (addr);
+}
+
+static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
+{
+ int r = (addr & 0xf00) >> 8;
+
+#ifdef JIT
+ special_mem |= S_WRITE;
+#endif
+
+ if (!isgaylenocia (addr))
+ return;
+
+ cia_wait_pre ();
+ if (!issinglecia () || (addr & 0x3000) != 0) {
+ if ((addr & 0x2000) == 0)
+ WriteCIAB (r, value);
+ if ((addr & 0x1000) == 0)
+ WriteCIAA (r, value);
+ if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
+ write_log (_T("cia_bput: unknown CIA address %08X=%082X PC=%08X\n"), addr, value & 0xff, M68K_GETPC);
+ warned--;
+ }
+ }
+ cia_wait_post (value);
+}
+
+static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
+{
+ int r = (addr & 0xf00) >> 8;
+
+#ifdef JIT
+ special_mem |= S_WRITE;
+#endif
+
+ if (!isgaylenocia (addr))
+ return;
+
+ cia_wait_pre ();
+ if (!issinglecia () || (addr & 0x3000) != 0) {
+ if ((addr & 0x2000) == 0)
+ WriteCIAB (r, value >> 8);
+ if ((addr & 0x1000) == 0)
+ WriteCIAA (r, value & 0xff);
+ if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
+ write_log (_T("cia_wput: unknown CIA address %08X=%04X %08X\n"), addr, value & 0xffff, M68K_GETPC);
+ warned--;
+ }
+ }
+ cia_wait_post (value);
+}
+
+static void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
+{
+ cia_wput (addr, value >> 16);
+ cia_wput (addr + 2, value & 0xffff);
+}
+
+/* battclock memory access */
+
+static uae_u32 REGPARAM3 clock_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 clock_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 clock_bget (uaecptr) REGPARAM;
+static void REGPARAM3 clock_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 clock_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 clock_bput (uaecptr, uae_u32) REGPARAM;
+
+addrbank clock_bank = {
+ clock_lget, clock_wget, clock_bget,
+ clock_lput, clock_wput, clock_bput,
+ default_xlate, default_check, NULL, _T("Battery backed up clock (none)"),
+ dummy_lgeti, dummy_wgeti, ABFLAG_IO, 0x3f, 0xd80000
+};
+
+static unsigned int clock_control_d;
+static unsigned int clock_control_e;
+static unsigned int clock_control_f;
+
+#define RF5C01A_RAM_SIZE 16
+static uae_u8 rtc_memory[RF5C01A_RAM_SIZE], rtc_alarm[RF5C01A_RAM_SIZE];
+
+static uae_u8 getclockreg (int addr, struct tm *ct)
+{
+ uae_u8 v = 0;
+
+ if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
+ switch (addr) {
+ case 0x0: v = ct->tm_sec % 10; break;
+ case 0x1: v = ct->tm_sec / 10; break;
+ case 0x2: v = ct->tm_min % 10; break;
+ case 0x3: v = ct->tm_min / 10; break;
+ case 0x4: v = ct->tm_hour % 10; break;
+ case 0x5:
+ if (clock_control_f & 4) {
+ v = ct->tm_hour / 10; // 24h
+ } else {
+ v = (ct->tm_hour % 12) / 10; // 12h
+ v |= ct->tm_hour >= 12 ? 4 : 0; // AM/PM bit
+ }
+ break;
+ case 0x6: v = ct->tm_mday % 10; break;
+ case 0x7: v = ct->tm_mday / 10; break;
+ case 0x8: v = (ct->tm_mon + 1) % 10; break;
+ case 0x9: v = (ct->tm_mon + 1) / 10; break;
+ case 0xA: v = ct->tm_year % 10; break;
+ case 0xB: v = (ct->tm_year / 10) & 0x0f; break;
+ case 0xC: v = ct->tm_wday; break;
+ case 0xD: v = clock_control_d; break;
+ case 0xE: v = clock_control_e; break;
+ case 0xF: v = clock_control_f; break;
+ }
+ } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+ int bank = clock_control_d & 3;
+ /* memory access */
+ if (bank >= 2 && addr < 0x0d)
+ return (rtc_memory[addr] >> ((bank == 2) ? 0 : 4)) & 0x0f;
+ /* alarm */
+ if (bank == 1 && addr < 0x0d) {
+ v = rtc_alarm[addr];
+#if CLOCK_DEBUG
+ write_log (_T("CLOCK ALARM R %X: %X\n"), addr, v);
+#endif
+ return v;
+ }
+ switch (addr) {
+ case 0x0: v = ct->tm_sec % 10; break;
+ case 0x1: v = ct->tm_sec / 10; break;
+ case 0x2: v = ct->tm_min % 10; break;
+ case 0x3: v = ct->tm_min / 10; break;
+ case 0x4: v = ct->tm_hour % 10; break;
+ case 0x5:
+ if (rtc_alarm[10] & 1)
+ v = ct->tm_hour / 10; // 24h
+ else
+ v = ((ct->tm_hour % 12) / 10) | (ct->tm_hour >= 12 ? 2 : 0); // 12h
+ break;
+ case 0x6: v = ct->tm_wday; break;
+ case 0x7: v = ct->tm_mday % 10; break;
+ case 0x8: v = ct->tm_mday / 10; break;
+ case 0x9: v = (ct->tm_mon + 1) % 10; break;
+ case 0xA: v = (ct->tm_mon + 1) / 10; break;
+ case 0xB: v = (ct->tm_year % 100) % 10; break;
+ case 0xC: v = (ct->tm_year % 100) / 10; break;
+ case 0xD: v = clock_control_d; break;
+ /* E and F = write-only, reads as zero */
+ case 0xE: v = 0; break;
+ case 0xF: v = 0; break;
+ }
+ }
+#if CLOCK_DEBUG
+ write_log(_T("CLOCK R: %X = %X, PC=%08x\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static void write_battclock (void)
+{
+ if (!currprefs.rtcfile[0] || currprefs.cs_rtc == 0)
+ return;
+ struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("wb"));
+ if (f) {
+ uae_u8 zero[13] = { 0 };
+ struct tm *ct;
+ time_t t = time (0);
+ t += currprefs.cs_rtc_adjust;
+ ct = localtime (&t);
+ uae_u8 od = clock_control_d;
+ if (currprefs.cs_rtc == 2)
+ clock_control_d &= ~3;
+ for (int i = 0; i < 13; i++) {
+ uae_u8 v = getclockreg (i, ct);
+ zfile_fwrite (&v, 1, 1, f);
+ }
+ clock_control_d = od;
+ zfile_fwrite (&clock_control_d, 1, 1, f);
+ zfile_fwrite (&clock_control_e, 1, 1, f);
+ zfile_fwrite (&clock_control_f, 1, 1, f);
+ if (currprefs.cs_rtc == 2) {
+ zfile_fwrite (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+ zfile_fwrite (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+ }
+ zfile_fclose (f);
+ }
+}
+
+void rtc_hardreset (void)
+{
+ rtc_delayed_write = 0;
+ if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
+ clock_bank.name = currprefs.cs_rtc == 1 ? _T("Battery backed up clock (MSM6242B)") : _T("Battery backed up clock A2000 (MSM6242B)");
+ clock_control_d = 0x1;
+ clock_control_e = 0;
+ clock_control_f = 0x4; /* 24/12 */
+ } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+ clock_bank.name = _T("Battery backed up clock (RF5C01A)");
+ clock_control_d = 0x8; /* Timer EN */
+ clock_control_e = 0;
+ clock_control_f = 0;
+ memset (rtc_memory, 0, RF5C01A_RAM_SIZE);
+ memset (rtc_alarm, 0, RF5C01A_RAM_SIZE);
+ rtc_alarm[10] = 1; /* 24H mode */
+ }
+ if (currprefs.rtcfile[0]) {
+ struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("rb"));
+ if (f) {
+ uae_u8 empty[13];
+ zfile_fread (empty, 13, 1, f);
+ zfile_fread (&clock_control_d, 1, 1, f);
+ zfile_fread (&clock_control_e, 1, 1, f);
+ zfile_fread (&clock_control_f, 1, 1, f);
+ zfile_fread (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
+ zfile_fread (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
+ zfile_fclose (f);
+ }
+ }
+}
+
+static uae_u32 REGPARAM2 clock_lget (uaecptr addr)
+{
+ return (clock_wget (addr) << 16) | clock_wget (addr + 2);
+}
+
+static uae_u32 REGPARAM2 clock_wget (uaecptr addr)
+{
+ return (clock_bget (addr) << 8) | clock_bget (addr + 1);
+}
+
+static uae_u32 REGPARAM2 clock_bget (uaecptr addr)
+{
+ time_t t;
+ struct tm *ct;
+ uae_u8 v = 0;
+
+#ifdef JIT
+ special_mem |= S_READ;
+#endif
+#ifdef CDTV
+ if (currprefs.cs_cdtvram && addr >= 0xdc8000)
+ return cdtv_battram_read (addr);
+#endif
+ addr &= 0x3f;
+ if ((addr & 3) == 2 || (addr & 3) == 0 || currprefs.cs_rtc == 0) {
+ if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
+ v = regs.irc >> 8;
+ return v;
+ }
+ t = time (0);
+ t += currprefs.cs_rtc_adjust;
+ ct = localtime (&t);
+ addr >>= 2;
+ return getclockreg (addr, ct);
+}
+
+static void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
+{
+ clock_wput (addr, value >> 16);
+ clock_wput (addr + 2, value);
+}
+
+static void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
+{
+ clock_bput (addr, value >> 8);
+ clock_bput (addr + 1, value);
+}
+
+static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
+{
+#ifdef JIT
+ special_mem |= S_WRITE;
+#endif
+// write_log(_T("W: %x (%x): %x, PC=%08x\n"), addr, (addr & 0xff) >> 2, value & 0xff, M68K_GETPC);
+#ifdef CDTV
+ if (currprefs.cs_cdtvram && addr >= 0xdc8000) {
+ cdtv_battram_write (addr, value);
+ return;
+ }
+#endif
+ addr &= 0x3f;
+ if ((addr & 1) != 1 || currprefs.cs_rtc == 0)
+ return;
+ addr >>= 2;
+ value &= 0x0f;
+ if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
+#if CLOCK_DEBUG
+ write_log (_T("CLOCK W %X: %X\n"), addr, value);
+#endif
+ switch (addr)
+ {
+ case 0xD: clock_control_d = value & (1|8); break;
+ case 0xE: clock_control_e = value; break;
+ case 0xF: clock_control_f = value; break;
+ }
+ } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
+ int bank = clock_control_d & 3;
+ /* memory access */
+ if (bank >= 2 && addr < 0x0d) {
+ uae_u8 ov = rtc_memory[addr];
+ rtc_memory[addr] &= ((bank == 2) ? 0xf0 : 0x0f);
+ rtc_memory[addr] |= value << ((bank == 2) ? 0 : 4);
+ if (rtc_memory[addr] != ov)
+ rtc_delayed_write = -1;
+ return;
+ }
+ /* alarm */
+ if (bank == 1 && addr < 0x0d) {
+#if CLOCK_DEBUG
+ write_log (_T("CLOCK ALARM W %X: %X\n"), addr, value);
+#endif
+ uae_u8 ov = rtc_alarm[addr];
+ rtc_alarm[addr] = value;
+ rtc_alarm[0] = rtc_alarm[1] = rtc_alarm[9] = rtc_alarm[12] = 0;
+ rtc_alarm[3] &= ~0x8;
+ rtc_alarm[5] &= ~0xc;
+ rtc_alarm[6] &= ~0x8;
+ rtc_alarm[8] &= ~0xc;
+ rtc_alarm[10] &= ~0xe;
+ rtc_alarm[11] &= ~0xc;
+ if (rtc_alarm[addr] != ov)
+ rtc_delayed_write = -1;
+ return;
+ }
+#if CLOCK_DEBUG
+ write_log (_T("CLOCK W %X: %X\n"), addr, value);
+#endif
+ switch (addr)
+ {
+ case 0xD: clock_control_d = value; break;
+ case 0xE: clock_control_e = value; break;
+ case 0xF: clock_control_f = value; break;
+ }
+ }
+ rtc_delayed_write = -1;
+}
+
+#ifdef SAVESTATE
+
+/* CIA-A and CIA-B save/restore code */
+
+static void save_cia_prepare (void)
+{
+ CIA_update_check ();
+ CIA_calctimers ();
+ compute_passed_time ();
+}
+
+void restore_cia_start (void)
+{
+ /* Fixes very old statefiles without keyboard state */
+ kbstate = 3;
+ setcapslockstate (0);
+ kblostsynccnt = 0;
+}
+
+void restore_cia_finish (void)
+{
+ eventtab[ev_cia].oldcycles = get_cycles ();
+ CIA_update ();
+ CIA_calctimers ();
+ compute_passed_time ();
+ eventtab[ev_cia].oldcycles -= div10;
+ //dumpcia ();
+ DISK_select_set (ciabprb);
+}
+
+uae_u8 *restore_cia (int num, uae_u8 *src)
+{
+ uae_u8 b;
+ uae_u16 w;
+ uae_u32 l;
+
+ /* CIA registers */
+ b = restore_u8 (); /* 0 PRA */
+ if (num) ciabpra = b; else ciaapra = b;
+ b = restore_u8 (); /* 1 PRB */
+ if (num) ciabprb = b; else ciaaprb = b;
+ b = restore_u8 (); /* 2 DDRA */
+ if (num) ciabdra = b; else ciaadra = b;
+ b = restore_u8 (); /* 3 DDRB */
+ if (num) ciabdrb = b; else ciaadrb = b;
+ w = restore_u16 (); /* 4 TA */
+ if (num) ciabta = w; else ciaata = w;
+ w = restore_u16 (); /* 6 TB */
+ if (num) ciabtb = w; else ciaatb = w;
+ l = restore_u8 (); /* 8/9/A TOD */
+ l |= restore_u8 () << 8;
+ l |= restore_u8 () << 16;
+ if (num) ciabtod = l; else ciaatod = l;
+ restore_u8 (); /* B unused */
+ b = restore_u8 (); /* C SDR */
+ if (num) ciabsdr = b; else ciaasdr = b;
+ b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
+ if (num) ciabicr = b; else ciaaicr = b;
+ b = restore_u8 (); /* E CRA */
+ if (num) ciabcra = b; else ciaacra = b;
+ b = restore_u8 (); /* F CRB */
+ if (num) ciabcrb = b; else ciaacrb = b;
+
+ /* CIA internal data */
+
+ b = restore_u8 (); /* ICR MASK */
+ if (num) ciabimask = b; else ciaaimask = b;
+ w = restore_u8 (); /* timer A latch */
+ w |= restore_u8 () << 8;
+ if (num) ciabla = w; else ciaala = w;
+ w = restore_u8 (); /* timer B latch */
+ w |= restore_u8 () << 8;
+ if (num) ciablb = w; else ciaalb = w;
+ w = restore_u8 (); /* TOD latched value */
+ w |= restore_u8 () << 8;
+ w |= restore_u8 () << 16;
+ if (num) ciabtol = w; else ciaatol = w;
+ l = restore_u8 (); /* alarm */
+ l |= restore_u8 () << 8;
+ l |= restore_u8 () << 16;
+ if (num) ciabalarm = l; else ciaaalarm = l;
+ b = restore_u8 ();
+ if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
+ if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
+ b = restore_u8 ();
+ if (num)
+ div10 = CYCLE_UNIT * b;
+ b = restore_u8 ();
+ if (num) ciabsdr_cnt = b; else ciaasdr_cnt = b;
+ return src;
+}
+
+uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dstbak,*dst, b;
+ uae_u16 t;
+
+ if (dstptr)
+ dstbak = dst = dstptr;
+ else
+ dstbak = dst = xmalloc (uae_u8, 1000);
+
+ save_cia_prepare ();
+
+ /* CIA registers */
+
+ b = num ? ciabpra : ciaapra; /* 0 PRA */
+ save_u8 (b);
+ b = num ? ciabprb : ciaaprb; /* 1 PRB */
+ save_u8 (b);
+ b = num ? ciabdra : ciaadra; /* 2 DDRA */
+ save_u8 (b);
+ b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
+ save_u8 (b);
+ t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
+ save_u16 (t);
+ t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 6 TB */
+ save_u16 (t);
+ b = (num ? ciabtod : ciaatod); /* 8 TODL */
+ save_u8 (b);
+ b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
+ save_u8 (b);
+ b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
+ save_u8 (b);
+ save_u8 (0); /* B unused */
+ b = num ? ciabsdr : ciaasdr; /* C SDR */
+ save_u8 (b);
+ b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
+ save_u8 (b);
+ b = num ? ciabcra : ciaacra; /* E CRA */
+ save_u8 (b);
+ b = num ? ciabcrb : ciaacrb; /* F CRB */
+ save_u8 (b);
+
+ /* CIA internal data */
+
+ save_u8 (num ? ciabimask : ciaaimask); /* ICR */
+ b = (num ? ciabla : ciaala); /* timer A latch LO */
+ save_u8 (b);
+ b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
+ save_u8 (b);
+ b = (num ? ciablb : ciaalb); /* timer B latch LO */
+ save_u8 (b);
+ b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
+ save_u8 (b);
+ b = (num ? ciabtol : ciaatol); /* latched TOD LO */
+ save_u8 (b);
+ b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
+ save_u8 (b);
+ b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
+ save_u8 (b);
+ b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
+ save_u8 (b);
+ b = (num ? ciabalarm >> 8 : ciaaalarm >> 8);/* alarm MED */
+ save_u8 (b);
+ b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
+ save_u8 (b);
+ b = 0;
+ if (num)
+ b |= ciabtlatch ? 1 : 0;
+ else
+ b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
+ if (num)
+ b |= ciabtodon ? 2 : 0;
+ else
+ b |= ciaatodon ? 2 : 0; /* TOD stopped? */
+ save_u8 (b);
+ save_u8 (num ? div10 / CYCLE_UNIT : 0);
+ save_u8 (num ? ciabsdr_cnt : ciaasdr_cnt);
+ *len = dst - dstbak;
+ return dstbak;
+}
+
+uae_u8 *save_keyboard (int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dst, *dstbak;
+ if (dstptr)
+ dstbak = dst = dstptr;
+ else
+ dstbak = dst = xmalloc (uae_u8, 4 + 4 + 1 + 1 + 1 + 1 + 1 + 2);
+ save_u32 (getcapslockstate () ? 1 : 0);
+ save_u32 (1);
+ save_u8 (kbstate);
+ save_u8 (0);
+ save_u8 (0);
+ save_u8 (0);
+ save_u8 (kbcode);
+ save_u16 (kblostsynccnt);
+ *len = dst - dstbak;
+ return dstbak;
+}
+
+uae_u8 *restore_keyboard (uae_u8 *src)
+{
+ setcapslockstate (restore_u32 () & 1);
+ uae_u32 v = restore_u32 ();
+ kbstate = restore_u8 ();
+ restore_u8 ();
+ restore_u8 ();
+ restore_u8 ();
+ kbcode = restore_u8 ();
+ kblostsynccnt = restore_u16 ();
+ if (!(v & 1)) {
+ kbstate = 3;
+ kblostsynccnt = 0;
+ }
+ return src;
+}
+
+#endif /* SAVESTATE */
// 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)
{
#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;
#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 {
// 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);
}
}
}
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;
int hpos;
struct dma_rec *dr;
+ sync_ce020 ();
hpos = dma_cycle ();
x_do_cycles_pre (CYCLE_UNIT);
if (debug_dma)
dr->dat = v;
#endif
+ x_do_cycles_post (CYCLE_UNIT, v);
- regs.ce020memcycles -= CYCLE_UNIT;
return v;
}
{
int hpos;
+ sync_ce020 ();
hpos = dma_cycle ();
x_do_cycles_pre (CYCLE_UNIT);
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);
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 ();
{
static uaecptr old;
uaecptr paddr = addr;
- int next;
+ int next = last;
if (last && 0) {
if (addr >= last)
return 0xffffffff;
}
}
-#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;
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;
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);
}
dr->dat = dat;
dr->addr = addr;
dr->type = type;
+ dr->intlev = regs.intmask;
return dr;
}
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);
}
#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;
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)
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) {
}
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)
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, ...)
}
start_brace ();
+
switch (mode) {
case Dreg:
if (movem)
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);
default:
abort ();
}
+ addcycles_ce020 (2);
if (!(flags & GF_APDI)) {
addcycles000 (2);
insn_n_cycles += 2;
}
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)
}
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) {
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;
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;
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);
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);
case imm2:
if (getv != 1)
abort ();
+ addcycles_ce020 (4);
gen_nextilong ("uae_s32", name, flags);
count_read_ea += 2;
syncmovepc (getv, flags);
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;
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);
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);
} 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++;
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)
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";
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";
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) {
if (curi->smode == imm || curi->smode == Dreg)
c += 2;
}
+ if (curi->dmode != Dreg)
+ addcycles_ce020 (4);
fill_prefetch_next ();
if (c > 0)
addcycles000 (c);
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 ? '^' : '|');
if (curi->size == sz_byte) {
printf ("\tsrc |= 0xFF00;\n");
}
+ addcycles_ce020 (12);
addcycles000 (8);
fill_prefetch_next ();
printf ("\tregs.sr &= src;\n");
if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
c += 2;
}
+ } else {
+ addcycles_ce020 (4);
}
fill_prefetch_next ();
if (c > 0)
if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
c += 2;
}
+ } else {
+ addcycles_ce020 (4);
}
fill_prefetch_next ();
if (c > 0)
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");
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");
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");
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;
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", "", "");
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");
// 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
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;
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)
// 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");
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");
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:
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;
break;
case i_NOP:
fill_prefetch_next ();
+ addcycles_ce020 (2);
if (using_ce020)
printf ("\t%s (6);\n", do_cycles);
break;
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 ();
} 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);
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");
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)
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");
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");
}
}
count_write += 2;
+ fill_prefetch_full_020 ();
fill_prefetch_next ();
break;
case i_JMP:
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");
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) {
}
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");
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;
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))
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");
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;
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) {
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.. */
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");
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 ();
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;
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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");
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");
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");
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");
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) {
}
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;
}
} 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++)
#define MEMDEBUG 0
#define MEMDEBUGMASK 0x7fffff
#define MEMDEBUGTEST 0x280000
-
+#define PICASSOIV_DEBUG_IO 0
#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
+#include "uae.h"
#include "memory.h"
#include "debug.h"
#include "custom.h"
#define BOARD_MODEL_REGISTERS_PICASSOIV 23
#define PICASSOIV_REG 0x00600000
#define PICASSOIV_IO 0x00200000
-#define PICASSOIV_VRAM 0x01000000
+#define PICASSOIV_VRAM1 0x01000000
+#define PICASSOIV_VRAM2 0x00800000
#define PICASSOIV_ROM_OFFSET 0x0200
#define PICASSOIV_FLASH_OFFSET 0x8000
#define PICASSOIV_FLASH_BANK 0x8000
#define PICASSOIV_MAX_FLASH (GFXBOARD_AUTOCONFIG_SIZE - 32768)
+#define PICASSOIV_BANK_UNMAPFLASH 2
+#define PICASSOIV_BANK_MAPRAM 4
+#define PICASSOIV_BANK_FLASHBANK 128
+
+#define PICASSOIV_INT_VBLANK 128
+
#define BOARD_MANUFACTURER_PICCOLO 2195
#define BOARD_MODEL_MEMORY_PICCOLO 5
#define BOARD_MODEL_REGISTERS_PICCOLO 6
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[] =
{
{
_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"),
{
_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
}
};
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;
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;
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;
}
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);
+ }
}
}
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;
}
vgaram = ops;
} else if (!stricmp (name, "cirrus-low-memory")) {
vgalowram = ops;
+ } else if (!stricmp (name, "cirrus-mmio")) {
+ vgammio = ops;
}
}
return board->swap;
}
-
static uaecptr fixaddr (uaecptr addr, int mask)
{
#ifdef JIT
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);
}
}
-
static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b)
{
#ifdef JIT
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;
}
#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)
{
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)
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 ();
}
}
-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) {
modechanged = false;
gfxboard_vblank = false;
gfxboard_intena = false;
+ picassoiv_bank = 0;
if (board) {
if (board->z3)
gfxboard_bank_memory.wput = gfxboard_wput_mem_autoconfig;
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;
}
#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];
}
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)
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)
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) {
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;
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);
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;
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);
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;
}
}
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)
{
return r;
}
-
-
STATIC_INLINE void m68k_do_bsr_ce020 (uaecptr oldpc, uae_s32 offset)
{
m68k_areg (regs, 7) -= 4;
m68k_areg (regs, 7) += 4;
}
+extern uae_u32 get_word_ce040_prefetch (int);
+
#endif
#ifdef CPUEMU_12
{
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;
{
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;
{
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;
{
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;
{
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;
uae_u32 addr;
uae_u16 evt;
int type;
+ uae_s8 intlev;
};
#define DMA_EVENT_BLITIRQ 1
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);
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);
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
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) \
#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
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;
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;
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
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);
{
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);
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++)
{
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)
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;
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;
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;
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;
prefs_changed_cpu ();
if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
- fill_prefetch_quick ();
+ fill_prefetch ();
build_cpufunctbl ();
changed = true;
}
{
uae_u16 dp = next_iword_020ce ();
int reg = (dp >> 12) & 15;
- int cycles = 0;
uae_u32 v;
uae_s32 regd = regs.regs[reg];
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;
}
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)
#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;
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);
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);
inprec_playdebug_cpu (1);
}
- docodece020 (opcode);
+ (*cpufunctbl[opcode])(opcode);
cont:
if (r->spcflags || time_for_interrupt ()) {
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)
}
}
-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)
{
x_do_cycles (cpu_cycles);
opcode = get_word_020_prefetch (0);
-
count_instr (opcode);
cpu_cycles = (*cpufunctbl[opcode])(opcode);
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
#define CPUTYPE_EC 1
#define CPUMODE_HALT 1
-
-
uae_u8 *restore_cpu (uae_u8 *src)
{
int i, flags, model;
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++) {
}
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 ();
}
}
init_m68k ();
m68k_setpc (regs.pc);
doint ();
- fill_prefetch_quick ();
+ fill_prefetch ();
set_cycles (start_cycles);
events_schedule ();
if (regs.stopped)
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 */
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++) {
}
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;
}
// 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;
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);
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)
{
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
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
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];
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];
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)
}
}
+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);
+ }
+}
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));
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;
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;
}
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;
}
- 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;
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)
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)
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);
}
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);
}
}
+ 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;
#include <stddef.h>
static int usefloppydrives = 0;
+static int num_drives;
+static bool drives_enumerated;
struct hardfilehandle
{
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;
}
#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;
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),
}
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);
#endif
-
-
-static int num_drives;
-
static int hdf_init2 (int force)
{
#ifdef WINDDK
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);
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;
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);
{
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;
#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")
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) {
}
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"));
_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*"));
_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;
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;
if(width > listview_column_width[7] )
listview_column_width[7] = width;
}
+ xfree (rootdir);
}
#endif
}
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
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) {
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);
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) {
* - optimize bitblt functions
*/
+//#define DEBUG_VGA
//#define DEBUG_CIRRUS
//#define DEBUG_VGA_REG
//#define DEBUG_BITBLT
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;
* 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
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
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
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);
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;
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;
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;
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;