From 25309295d3f51c6945b20fd4bd921912c3da06ca Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 23 Oct 2010 14:29:45 +0300 Subject: [PATCH] 2310b1 --- a2065.cpp | 330 ++-- akiko.cpp | 7 +- ar.cpp | 6 +- audio.cpp | 47 +- blitter.cpp | 315 +++- blkdev.cpp | 34 +- cdtv.cpp | 19 +- cfgfile.cpp | 31 +- cia.cpp | 297 ++-- cpummu.cpp | 2 +- custom.cpp | 596 ++++--- debug.cpp | 91 +- disk.cpp | 310 ++-- drawing.cpp | 326 +--- ersatz.cpp | 4 +- expansion.cpp | 4 +- filesys.cpp | 363 ++++- filesys_bootrom.cpp | 653 ++++---- fpp.cpp | 2 +- gayle.cpp | 20 +- gencpu.cpp | 574 ++++--- include/blkdev.h | 3 + include/cia.h | 10 +- include/cpu_prefetch.h | 92 +- include/custom.h | 63 +- include/disk.h | 5 +- include/drawing.h | 1 + include/events.h | 7 +- include/events_jit.h | 16 +- include/fsdb.h | 22 +- include/gfxfilter.h | 1 + include/inputdevice.h | 41 +- include/inputrecord.h | 56 + include/keyboard.h | 3 +- include/newcpu.h | 73 +- include/options.h | 21 +- include/savestate.h | 62 +- include/statusline.h | 1 - include/uae.h | 8 +- include/xwin.h | 2 + include/zarchive.h | 1 + include/zfile.h | 4 +- inputdevice.cpp | 749 +++++---- inputevents.def | 6 +- inputrecord.cpp | 904 +++++++++++ keybuf.cpp | 29 +- main.cpp | 29 +- memory.cpp | 2 +- newcpu.cpp | 1441 +++++++++++++---- od-win32/blkdev_win32_aspi.cpp | 2 +- od-win32/blkdev_win32_ioctl.cpp | 37 +- od-win32/blkdev_win32_spti.cpp | 2 +- od-win32/caps/CapsAPI.h | 38 +- od-win32/caps/caps_win32.cpp | 36 +- od-win32/debug_win32.cpp | 2 +- od-win32/dinput.cpp | 35 + od-win32/keyboard_win32.cpp | 10 +- od-win32/registry.cpp | 6 +- od-win32/resources/resource | 20 +- od-win32/resources/winuae.rc | 101 +- od-win32/rp.cpp | 9 +- od-win32/sysconfig.h | 1 + od-win32/win32.cpp | 86 +- od-win32/win32.h | 6 +- od-win32/win32_scaler.cpp | 56 +- od-win32/win32_uaenet.cpp | 2 +- od-win32/win32gfx.cpp | 151 +- od-win32/win32gui.cpp | 228 +-- od-win32/winuae_msvc10/winuae_msvc.vcxproj | 2 + .../winuae_msvc10/winuae_msvc.vcxproj.filters | 6 + od-win32/winuaechangelog.txt | 81 + od-win32/writelog.cpp | 4 +- savestate.cpp | 717 ++++++-- statusline.cpp | 213 +++ traps.cpp | 6 +- uaeunp.cpp | 13 +- zfile.cpp | 74 +- zfile_archive.cpp | 2 +- 78 files changed, 6677 insertions(+), 2952 deletions(-) create mode 100644 include/inputrecord.h create mode 100644 inputrecord.cpp create mode 100644 statusline.cpp diff --git a/a2065.cpp b/a2065.cpp index c445f8e8..bc32c8ac 100644 --- a/a2065.cpp +++ b/a2065.cpp @@ -17,8 +17,13 @@ #include "a2065.h" #include "win32_uaenet.h" #include "crc32.h" +#include "savestate.h" +#include "autoconf.h" -static int a2065_log = 0; +int log_a2065 = 0; +static int log_transmit = 1; +static int log_receive = 1; +int a2065_promiscuous = 0; #define RAP 0x4002 #define RDP 0x4000 @@ -30,7 +35,7 @@ static int a2065_log = 0; static uae_u8 config[256]; static uae_u8 boardram[RAM_SIZE]; -static uae_u16 csr[4]; +static volatile uae_u16 csr[4]; static int rap; static int configured; @@ -38,13 +43,13 @@ static struct netdriverdata *td; static void *sysdata; static int am_initialized; -static int transmitnow; +static volatile int transmitnow; static uae_u16 am_mode; static uae_u64 am_ladrf; static uae_u32 am_rdr, am_rdr_rlen, am_rdr_rdra; static uae_u32 am_tdr, am_tdr_tlen, am_tdr_tdra; static int tdr_offset, rdr_offset; -static int byteswap, prom; +static int byteswap, prom, fakeprom; static uae_u8 fakemac[6], realmac[6]; static uae_u8 broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -142,7 +147,7 @@ static void dumppacket (TCHAR *n, uae_u8 *packet, int len) #define MAX_PACKET_SIZE 4000 static uae_u8 transmitbuffer[MAX_PACKET_SIZE]; -static int transmitlen; +static volatile int transmitlen; static int dofakemac (uae_u8 *packet) { @@ -225,23 +230,6 @@ static int mungepacket (uae_u8 *packet, int len) return ret; } -static int getfunc (struct s2devstruct *dev, uae_u8 *d, int *len) -{ - int tlen; - - tlen = transmitlen; - transmitlen = 0; - if (tlen > 0) { - if (tlen > *len) - return 0; - memcpy (d, transmitbuffer, tlen); - *len = tlen; - transmitnow = 1; - return 1; - } - return 0; -} - static int mcfilter (const uae_u8 *data) { if (am_ladrf == 0) // multicast filter completely disabled? @@ -249,7 +237,7 @@ static int mcfilter (const uae_u8 *data) return 1; // just allow everything } -static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len) +static void gotfunc (struct s2devstruct *dev, const uae_u8 *databuf, int len) { int i; int size, insize, first; @@ -258,44 +246,89 @@ static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len) uae_u16 rmd0, rmd1, rmd2, rmd3; uae_u32 crc32; uae_u8 tmp[MAX_PACKET_SIZE], *data; + const uae_u8 *dstmac, *srcmac; + + if (log_a2065 > 1 && log_receive) { + dstmac = databuf; + srcmac = databuf + 6; + write_log (L"A2065 1) + write_log (L"mc filtered\n"); return; + } } else { // !promiscuous and dst != me and dst != broadcast - if (!prom && (memcmp (data2, realmac, sizeof realmac) != 0 && memcmp (data2, broadcast, sizeof broadcast) != 0)) + if (!prom && (memcmp (dstmac, realmac, sizeof realmac) != 0 && memcmp (dstmac, broadcast, sizeof broadcast) != 0)) { + if (log_a2065 > 1) + write_log (L"not for me1\n"); return; + } } // src and dst = me? right, better drop it. - if (memcmp (data2, realmac, sizeof realmac) == 0 && memcmp (data2 + 6, realmac, sizeof realmac) == 0) + if (memcmp (dstmac, realmac, sizeof realmac) == 0 && memcmp (srcmac, realmac, sizeof realmac) == 0) { + if (log_a2065 > 1) + write_log (L"not for me2\n"); return; + } // dst = broadcast and src = me? no thanks. - if (memcmp (data2, broadcast, sizeof broadcast) == 0 && memcmp (data2 + 6, realmac, sizeof realmac) == 0) + if (memcmp (dstmac, broadcast, sizeof broadcast) == 0 && memcmp (srcmac, realmac, sizeof realmac) == 0) { + if (log_a2065 > 1) + write_log (L"not for me3\n"); return; + } - memcpy (tmp, data2, len); + memcpy (tmp, databuf, len); +#if 0 + FILE *f = fopen("s:\\d\\wireshark2.cap", "rb"); + fseek (f, 474, SEEK_SET); + fread (tmp, 342, 1, f); + fclose (f); + realmac[0] = 0xc8; + realmac[1] = 0x0a; + realmac[2] = 0xa9; + realmac[3] = 0x81; + realmac[4] = 0xff; + realmac[5] = 0x2f; + fakemac[3] = realmac[3]; + fakemac[4] = realmac[4]; + fakemac[5] = realmac[5]; +#endif d = tmp; - if (a2065_log) { - if (memcmp (d, realmac, sizeof realmac) == 0) { + dstmac = d; + srcmac = d + 6; + if (log_a2065 && log_receive) { + if (memcmp (dstmac, realmac, sizeof realmac) == 0) { write_log (L"A2065<-DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n", - d[0], d[1], d[2], d[3], d[4], d[5], - d[6], d[7], d[8], d[9], d[10], d[11], + dstmac[0], dstmac[1], dstmac[2], dstmac[3], dstmac[4], dstmac[5], + srcmac[6], srcmac[7], srcmac[8], srcmac[9], srcmac[10], srcmac[11], (d[12] << 8) | d[13], len); } } if (mungepacket (d, len)) { - if (a2065_log) { + if (log_a2065 && log_receive) { write_log (L"A2065<*DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n", - d[0], d[1], d[2], d[3], d[4], d[5], - d[6], d[7], d[8], d[9], d[10], d[11], + dstmac[0], dstmac[1], dstmac[2], dstmac[3], dstmac[4], dstmac[5], + srcmac[6], srcmac[7], srcmac[8], srcmac[9], srcmac[10], srcmac[11], (d[12] << 8) | d[13], len); } } @@ -323,6 +356,7 @@ static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len) addr &= RAM_MASK; if (!(rmd1 & RX_OWN)) { + write_log (L"A2065: RECEIVE BUFFER ERROR\n"); if (!first) { rmd1 |= RX_BUFF | RX_OFLO; csr[0] &= ~CSR0_RXON; @@ -331,6 +365,7 @@ static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len) } p[3] = rmd1 >> 8; p[2] = rmd1 >> 0; + rethink_a2065 (); return; } @@ -363,6 +398,22 @@ static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len) rethink_a2065 (); } +static int getfunc (struct s2devstruct *dev, uae_u8 *d, int *len) +{ + if (transmitlen <= 0) + return 0; + if (transmitlen > *len) { + write_log (L"A2065: too large packet transmission attempt %d > %d\n", transmitlen, *len); + transmitlen = 0; + return 0; + } + memcpy (d, transmitbuffer, transmitlen); + *len = transmitlen; + transmitlen = 0; + transmitnow = 1; + return 1; +} + static void do_transmit (void) { int i; @@ -379,8 +430,13 @@ static void do_transmit (void) tdr_offset %= am_tdr_tlen; p = boardram + ((am_tdr_tdra + tdr_offset * 8) & RAM_MASK); tmd1 = (p[3] << 8) | (p[2] << 0); - if (!(tmd1 & TX_OWN) || !(tmd1 & TX_STP)) + if (!(tmd1 & TX_OWN) || !(tmd1 & TX_STP)) { + tdr_offset++; return; + } + if (!(tmd1 & TX_ENP) && log_a2065 > 0) + write_log (L"A2065: chained transmit!?\n"); + add_fcs = tmd1 & TX_ADD_FCS; for (;;) { @@ -395,8 +451,9 @@ static void do_transmit (void) if (!(tmd1 & TX_OWN)) { tmd3 |= TX_BUFF | TX_UFLO; + tmd1 |= TX_ERR; csr[0] &= ~CSR0_TXON; - write_log (L"A2065: TRANSMIT BUFFER ERROR\n"); + write_log (L"A2065: TRANSMIT OWN NOT SET\n"); err = 1; } else { tmd1 &= ~TX_OWN; @@ -416,16 +473,21 @@ static void do_transmit (void) } if (outsize < 60) { tmd3 |= TX_BUFF | TX_UFLO; + tmd1 |= TX_ERR; csr[0] &= ~CSR0_TXON; - write_log (L"A2065: TRANSMIT SIZE %d\n", outsize); + write_log (L"A2065: TRANSMIT UNDERFLOW %d\n", outsize); err = 1; + p[3] = tmd1 >> 8; + p[2] = tmd1 >> 0; + p[7] = tmd3 >> 8; + p[6] = tmd3 >> 0; } if (!err) { uae_u8 *d = transmitbuffer; if ((am_mode & MODE_DTCR) && !add_fcs) outsize -= 4; // do not include checksum bytes - if (a2065_log) { + if (log_a2065 && log_transmit) { write_log (L"A2065->DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], @@ -433,7 +495,7 @@ static void do_transmit (void) } transmitlen = outsize; if (mungepacket (d, transmitlen)) { - if (a2065_log) { + if (log_a2065 && log_transmit) { write_log (L"A2065*>DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], @@ -441,9 +503,19 @@ static void do_transmit (void) } } uaenet_trigger (sysdata); - csr[0] |= CSR0_TINT; - rethink_a2065 (); } + csr[0] |= CSR0_TINT; + rethink_a2065 (); +} + +static void check_transmit (void) +{ + if (transmitlen > 0) + return; + if (!(csr[0] & CSR0_TXON)) + return; + transmitnow = 0; + do_transmit (); } void a2065_hsync_handler (void) @@ -452,31 +524,21 @@ void a2065_hsync_handler (void) cnt--; if (cnt < 0 || transmitnow) { - transmitnow = 0; - if ((csr[0] & CSR0_TXON) && transmitlen <= 0) - do_transmit (); + check_transmit (); cnt = 15; } } void rethink_a2065 (void) { - uae_u16 csr0 = csr[0]; - + uae_int_requested &= ~4; if (!configured) return; - if (csr0 & (CSR0_BABL | CSR0_MISS | CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IDON)) { - if (!(csr0 & CSR0_INTR)) { - csr0 |= CSR0_INTR; - if (csr0 & CSR0_INEA) { - INTREQ_0 (0x8000 | 0x0008); - } - } - } else { - csr0 &= ~CSR0_INTR; - } - - csr[0] = csr0; + csr[0] &= ~CSR0_INTR; + if (csr[0] & (CSR0_BABL | CSR0_MISS | CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IDON)) + csr[0] |= CSR0_INTR; + if ((csr[0] & (CSR0_INTR | CSR0_INEA)) == (CSR0_INTR | CSR0_INEA)) + uae_int_requested |= 4; } static void chip_init (void) @@ -484,6 +546,11 @@ static void chip_init (void) uae_u32 iaddr = ((csr[2] & 0xff) << 16) | csr[1]; uae_u8 *p = boardram + (iaddr & RAM_MASK); + write_log (L"A2065: Initialization block2:\n"); + for (int i = 0; i < 24; i++) + write_log (L".%02X", p[i]); + write_log (L"\n"); + am_mode = (p[0] << 8) | (p[1] << 0); am_ladrf = ((uae_u64)p[15] << 56) | ((uae_u64)p[14] << 48) | ((uae_u64)p[13] << 40) | ((uae_u64)p[12] << 32) | (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | (p[8] << 0); am_rdr = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | (p[16] << 0); @@ -495,7 +562,8 @@ static void chip_init (void) am_tdr_tdra = am_tdr & 0x00fffff8; prom = (am_mode & MODE_PROM) ? 1 : 0; - + fakeprom = a2065_promiscuous ? 1 : 0; + fakemac[0] = p[2]; fakemac[1] = p[3]; fakemac[2] = p[4]; @@ -503,8 +571,8 @@ static void chip_init (void) fakemac[4] = p[6]; fakemac[5] = p[7]; - write_log (L"A2065: %06X %d %d %d %06X %06X %02X:%02X:%02X:%02X:%02X:%02X\n", - iaddr, prom, am_rdr_rlen, am_tdr_tlen, am_rdr_rdra, am_tdr_tdra, + write_log (L"A2065: %04X %06X %d %d %d %d %06X %06X %02X:%02X:%02X:%02X:%02X:%02X\n", + am_mode, iaddr, prom, fakeprom, am_rdr_rlen, am_tdr_tlen, am_rdr_rdra, am_tdr_tdra, fakemac[0], fakemac[1], fakemac[2], fakemac[3], fakemac[4], fakemac[5]); @@ -516,7 +584,7 @@ static void chip_init (void) if (td != NULL) { if (!sysdata) sysdata = xcalloc (uae_u8, uaenet_getdatalenght()); - if (!uaenet_open (sysdata, td, NULL, gotfunc, getfunc, prom)) { + if (!uaenet_open (sysdata, td, NULL, gotfunc, getfunc, prom || fakeprom)) { write_log (L"A2065: failed to initialize winpcap driver\n"); } } @@ -532,7 +600,7 @@ static uae_u16 chip_wget (uaecptr addr) if (v & (CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR)) v |= CSR0_ERR; } - if (a2065_log > 2) + if (log_a2065 > 2) write_log (L"A2065_CHIPWGET: CSR%d=%04X PC=%08X\n", rap, v, M68K_GETPC); return v; } @@ -548,85 +616,84 @@ static void chip_wput (uaecptr addr, uae_u16 v) } else if (addr == RDP) { - uae_u16 reg = csr[rap]; - uae_u16 oreg = reg; + uae_u16 oreg = csr[rap]; uae_u16 t; - if (a2065_log > 2) + if (log_a2065 > 2) write_log (L"A2065_CHIPWPUT: CSR%d=%04X PC=%08X\n", rap, v & 0xffff, M68K_GETPC); switch (rap) { case 0: - reg &= ~CSR0_INEA; reg |= v & CSR0_INEA; + csr[0] &= ~CSR0_INEA; csr[0] |= v & CSR0_INEA; // bit = 1 -> set, bit = 0 -> nop t = v & (CSR0_INIT | CSR0_STRT | CSR0_STOP | CSR0_TDMD); - reg |= t; + csr[0] |= t; // bit = 1 -> clear, bit = 0 -> nop t = v & (CSR0_IDON | CSR0_TINT | CSR0_RINT | CSR0_MERR | CSR0_MISS | CSR0_CERR | CSR0_BABL); - reg &= ~t; - reg &= ~CSR0_ERR; + csr[0] &= ~t; + csr[0] &= ~CSR0_ERR; - if ((reg & (CSR0_STOP | CSR0_STRT | CSR0_INIT)) == (CSR0_STOP | CSR0_STRT | CSR0_INIT)) - reg &= ~(CSR0_STRT | CSR0_INIT); - if (reg & CSR0_INIT) - reg &= ~CSR0_STOP; + if ((csr[0] & (CSR0_STOP | CSR0_STRT | CSR0_INIT)) == (CSR0_STOP | CSR0_STRT | CSR0_INIT)) + csr[0] &= ~(CSR0_STRT | CSR0_INIT); + if (csr[0] & CSR0_INIT) + csr[0] &= ~CSR0_STOP; - if ((reg & CSR0_STRT) && !(oreg & CSR0_STRT)) { - reg &= ~CSR0_STOP; + if ((csr[0] & CSR0_STRT) && !(oreg & CSR0_STRT)) { + csr[0] &= ~CSR0_STOP; if (!(am_mode & MODE_DTX)) - reg |= CSR0_TXON; + csr[0] |= CSR0_TXON; if (!(am_mode & MODE_DRX)) - reg |= CSR0_RXON; - if (a2065_log) - write_log (L"A2065: START\n"); + csr[0] |= CSR0_RXON; + if (log_a2065) + write_log (L"A2065: START.\n"); } - if ((reg & CSR0_STOP) && !(oreg & CSR0_STOP)) { - reg = CSR0_STOP; - if (a2065_log) - write_log (L"A2065: STOP\n"); + if ((csr[0] & CSR0_STOP) && !(oreg & CSR0_STOP)) { + csr[0] = CSR0_STOP; + if (log_a2065) + write_log (L"A2065: STOP.\n"); csr[3] = 0; am_initialized = 0; } - if ((reg & CSR0_INIT) && am_initialized == 0) { - if (a2065_log) - write_log (L"A2065: INIT\n"); + if ((csr[0] & CSR0_INIT) && am_initialized == 0) { + if (log_a2065) + write_log (L"A2065: INIT.\n"); chip_init (); - reg |= CSR0_IDON; + csr[0] |= CSR0_IDON; am_initialized = 1; } - if ((reg & CSR0_STRT) && am_initialized) { - if (reg & CSR0_TDMD) - transmitnow = 1; + if ((csr[0] & CSR0_STRT) && am_initialized) { + if (csr[0] & CSR0_TDMD) + check_transmit (); } - reg &= ~CSR0_TDMD; + csr[0] &= ~CSR0_TDMD; + rethink_a2065 (); break; case 1: if (csr[0] & 4) { - reg = v; - reg &= ~1; + csr[1] = v; + csr[1] &= ~1; } break; case 2: if (csr[0] & 4) { - reg = v; - reg &= 0x00ff; + csr[2] = v; + csr[2] &= 0x00ff; } break; case 3: if (csr[0] & 4) { - reg = v; - reg &= 7; + csr[3] = v; + csr[3] &= 7; } - byteswap = (reg & CSR3_BSWP) ? 1 : 0; + byteswap = (csr[3] & CSR3_BSWP) ? 1 : 0; break; } - csr[rap] = reg; } } @@ -640,7 +707,7 @@ static uae_u32 a2065_bget2 (uaecptr addr) } else if (addr >= RAM_OFFSET) { v = boardram[(addr & RAM_MASK) ^ 1]; } - if (a2065_log > 2) + if (log_a2065 > 2) write_log (L"A2065_BGET: %08X -> %02X PC=%08X\n", addr, v & 0xff, M68K_GETPC); return v; } @@ -650,7 +717,7 @@ static void a2065_bput2 (uaecptr addr, uae_u32 v) if (addr >= RAM_OFFSET) { boardram[(addr & RAM_MASK) ^ 1] = v; } - if (a2065_log > 2) + if (log_a2065 > 2) write_log (L"A2065_BPUT: %08X <- %02X PC=%08X\n", addr, v & 0xff, M68K_GETPC); } @@ -731,13 +798,13 @@ static void REGPARAM2 a2065_bput (uaecptr addr, uae_u32 b) if (addr == 0x48 && !configured) { map_banks (&a2065_bank, b, 0x10000 >> 16, 0x10000); write_log (L"A2065 Z2 autoconfigured at %02X0000\n", b); - configured = 1; + configured = b; expamem_next (); return; } if (addr == 0x4c && !configured) { write_log (L"A2065 DMAC AUTOCONFIG SHUT-UP!\n"); - configured = 1; + configured = 0xff; expamem_next (); return; } @@ -773,10 +840,9 @@ static addrbank a2065_bank = { a2065_lgeti, a2065_wgeti, ABFLAG_IO }; -void a2065_init (void) +static void a2065_config (void) { memset (config, 0xff, sizeof config); - configured = 0; ew (0x00, 0xc0 | 0x01); // hardware id ew (0x04, 0x70); @@ -812,7 +878,49 @@ void a2065_init (void) fakemac[4] = realmac[4]; fakemac[5] = realmac[5]; - /* KS autoconfig handles the rest */ - map_banks (&a2065_bank, 0xe80000 >> 16, 0x10000 >> 16, 0x10000); + if (configured) { + if (configured != 0xff) + map_banks (&a2065_bank, configured, 0x10000 >> 16, 0x10000); + } else { + /* KS autoconfig handles the rest */ + map_banks (&a2065_bank, 0xe80000 >> 16, 0x10000 >> 16, 0x10000); + } +} +uae_u8 *save_a2065 (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak,*dst; + + if (currprefs.a2065name[0] == 0) + return NULL; + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = (uae_u8*)malloc (16); + save_u32 (0); + save_u8 (configured); + for (int i = 0; i < 6; i++) + save_u8 (realmac[i]); + *len = dst - dstbak; + return dstbak; +} +uae_u8 *restore_a2065 (uae_u8 *src) +{ + restore_u32 (); + configured = restore_u8 (); + for (int i = 0; i < 6; i++) + realmac[i] = restore_u8 (); + return src; +} + +void restore_a2065_finish (void) +{ + if (configured) + a2065_config (); +} + +void a2065_init (void) +{ + configured = 0; + a2065_config (); } diff --git a/akiko.cpp b/akiko.cpp index 9c19c45e..b937eefb 100644 --- a/akiko.cpp +++ b/akiko.cpp @@ -1702,7 +1702,7 @@ int akiko_init (void) #ifdef SAVESTATE -uae_u8 *save_akiko (int *len) +uae_u8 *save_akiko (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; int i; @@ -1710,7 +1710,10 @@ uae_u8 *save_akiko (int *len) if (!currprefs.cs_cd32cd) return NULL; - dstbak = dst = xmalloc (uae_u8, 1000); + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); save_u16 (0); save_u16 (0xCAFE); save_u32 (cdrom_intreq); diff --git a/ar.cpp b/ar.cpp index 2cd4387e..e3bf8eac 100644 --- a/ar.cpp +++ b/ar.cpp @@ -997,7 +997,7 @@ static void hrtmon_go (void) old = get_long ((uaecptr)(regs.vbr + 0x8)); put_word (hrtmem_start + 0xc0000, 4); put_long ((uaecptr)(regs.vbr + 8), get_long (hrtmem_start + 8)); - Exception (2, 0); + Exception (2); put_long ((uaecptr)(regs.vbr + 8), old); } else if (cart_type == CART_SUPER4) { uae_u32 v = get_long (hrtmem_start + 0x7c); @@ -1076,7 +1076,7 @@ void check_prefs_changed_carts (int in_memory_reset) void action_replay_reset (void) { if (hrtmemory) { - if (savestate_state == STATE_RESTORE) { + if (isrestore ()) { if (m68k_getpc () >= hrtmem_start && m68k_getpc () <= hrtmem_start + hrtmem_size) hrtmon_map_banks (); else @@ -1086,7 +1086,7 @@ void action_replay_reset (void) if (action_replay_flag == ACTION_REPLAY_INACTIVE) return; - if (savestate_state == STATE_RESTORE) { + if (isrestore ()) { if (m68k_getpc () >= arrom_start && m68k_getpc () <= arrom_start + arrom_size) { action_replay_flag = ACTION_REPLAY_ACTIVE; hide_cart (0); diff --git a/audio.cpp b/audio.cpp index 436a0c75..5cad8700 100644 --- a/audio.cpp +++ b/audio.cpp @@ -49,6 +49,7 @@ //#define TEST_AUDIO #define PERIOD_MIN 4 +#define PERIOD_MIN_NONCE 60 int audio_channel_mask = 15; @@ -1073,10 +1074,12 @@ static void audio_event_reset (void) { int i; - last_cycles = get_cycles () - 1; + last_cycles = get_cycles (); next_sample_evtime = scaled_sample_evtime; - for (i = 0; i < 4; i++) - zerostate (i); + if (!isrestore ()) { + for (i = 0; i < 4; i++) + zerostate (i); + } schedule_audio (); events_schedule (); samplecnt = 0; @@ -1180,23 +1183,23 @@ STATIC_INLINE void setdr (int nr) } } -static void loaddat (int nr) +static void loaddat (int nr, bool modper) { struct audio_channel_data *cdp = audio_channel + nr; int audav = adkcon & (0x01 << nr); int audap = adkcon & (0x10 << nr); - if (audav || audap) { - if (nr > 3) + if (audav || (modper && audap)) { + if (nr >= 3) return; - if (audav) { - cdp[1].vol = cdp->dat; - } else if (audap) { + if (modper && audap) { if (cdp->dat == 0) cdp[1].per = PERIOD_MAX; else if (cdp->dat > PERIOD_MIN) cdp[1].per = cdp->dat * CYCLE_UNIT; else cdp[1].per = PERIOD_MIN * CYCLE_UNIT; + } else if (audav) { + cdp[1].vol = cdp->dat; } } else { #ifdef TEST_AUDIO @@ -1210,6 +1213,10 @@ static void loaddat (int nr) cdp->dat2 = cdp->dat; } } +static void loaddat (int nr) +{ + loaddat (nr, false); +} STATIC_INLINE void loadper (int nr) { @@ -1353,7 +1360,7 @@ static void audio_state_channel2 (int nr, bool perfin) if (!perfin) return; if (audap) - loaddat (nr); + loaddat (nr, true); if (chan_ena) { if (audap) setdr (nr); @@ -1438,7 +1445,7 @@ void audio_reset (void) #endif reset_sound (); memset (sound_filter_state, 0, sizeof sound_filter_state); - if (savestate_state != STATE_RESTORE) { + if (!isrestore ()) { for (i = 0; i < 4; i++) { cdp = &audio_channel[i]; memset (cdp, 0, sizeof *audio_channel); @@ -1448,7 +1455,7 @@ void audio_reset (void) } } - last_cycles = get_cycles () - 1; + last_cycles = get_cycles (); next_sample_evtime = scaled_sample_evtime; schedule_audio (); events_schedule (); @@ -1563,7 +1570,7 @@ void set_audio (void) } } next_sample_evtime = scaled_sample_evtime; - last_cycles = get_cycles () - 1; + last_cycles = get_cycles (); compute_vsynctime (); } else { sound_volume (0); @@ -1659,7 +1666,7 @@ void update_audio (void) if (!isaudio ()) goto end; - if (savestate_state == STATE_RESTORE) + if (isrestore ()) goto end; if (!is_audio_active ()) goto end; @@ -1858,6 +1865,10 @@ void AUDxPER (int nr, uae_u16 v) /* smaller values would cause extremely high cpu usage */ per = PERIOD_MIN * CYCLE_UNIT; } + if (per < PERIOD_MIN_NONCE * CYCLE_UNIT && !currprefs.cpu_cycle_exact && (cdp->dmaenstore || cdp->state == 0)) { + /* DMAL emulation and low period can cause very very high cpu usage on slow performance PCs */ + per = PERIOD_MIN_NONCE * CYCLE_UNIT; + } if (cdp->per == PERIOD_MAX - 1 && per != PERIOD_MAX - 1) { cdp->evtime = CYCLE_UNIT; @@ -1966,11 +1977,19 @@ void audio_vsync (void) #endif } +void restore_audio_finish (void) +{ + last_cycles = get_cycles (); + schedule_audio (); + events_schedule (); +} + uae_u8 *restore_audio (int nr, uae_u8 *src) { struct audio_channel_data *acd = audio_channel + nr; uae_u16 p; + zerostate (nr); acd->state = restore_u8 (); acd->vol = restore_u8 (); acd->intreq2 = restore_u8 () ? true : false; diff --git a/blitter.cpp b/blitter.cpp index 3d4a7436..e8eaeaf4 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -30,6 +30,7 @@ /* we must not change ce-mode while blitter is running.. */ static int blitter_cycle_exact; +static int blt_statefile_type; uae_u16 bltcon0, bltcon1; uae_u32 bltapt, bltbpt, bltcpt, bltdpt; @@ -44,7 +45,6 @@ static int blitonedot, blitsign, blitlinepixel; static int blit_add; static int blit_modadda, blit_modaddb, blit_modaddc, blit_modaddd; static int blit_ch; -static int vblitsize, hblitsize; #ifdef BLITTER_DEBUG static int blitter_dontdo; @@ -98,7 +98,9 @@ same in both block and line modes number of cycles, initial cycle, main cycle */ -static const int blit_cycle_diagram[][10] = +#define DIAGSIZE 10 + +static const int blit_cycle_diagram[][DIAGSIZE] = { { 2, 0,0, 0,0 }, /* 0 */ { 2, 0,0, 0,4 }, /* 1 */ @@ -125,7 +127,7 @@ idle cycle added (still requires free bus cycle) */ -static const int blit_cycle_diagram_fill[][10] = +static const int blit_cycle_diagram_fill[][DIAGSIZE] = { { 0 }, /* 0 */ { 3, 0,0,0, 0,4,0 }, /* 1 */ @@ -188,6 +190,36 @@ static const int blit_cycle_diagram_finalld[] = 2, 0,0, 0,0 }; +static int get_cycle_diagram_type (const int *diag) +{ + for (int i = 0; i < 16; i++) { + if (diag == &blit_cycle_diagram[i][0]) + return i; + if (diag == &blit_cycle_diagram_fill[i][0]) + return i + 0x40; + } + if (diag == blit_cycle_diagram_line) + return 0x80; + if (diag == blit_cycle_diagram_finald) + return 0x81; + if (diag == blit_cycle_diagram_finalld) + return 0x82; + return 0xff; +} +static const int *set_cycle_diagram_type (uae_u8 diag) +{ + if (diag >= 0x00 && diag <= 0x0f) + return &blit_cycle_diagram[diag][0]; + if (diag >= 0x40 && diag <= 0x4f) + return &blit_cycle_diagram_fill[diag][0]; + if (diag == 0x80) + return blit_cycle_diagram_line; + if (diag == 0x81) + return blit_cycle_diagram_finald; + if (diag == 0x82) + return blit_cycle_diagram_finalld; + return NULL; +} void build_blitfilltable (void) { @@ -336,23 +368,23 @@ static void blitter_dofast (void) uae_u8 mt = bltcon0 & 0xFF; blit_masktable[0] = blt_info.bltafwm; - blit_masktable[hblitsize - 1] &= blt_info.bltalwm; + blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm; if (bltcon0 & 0x800) { bltadatptr = bltapt; - bltapt += (hblitsize * 2 + blt_info.bltamod) * vblitsize; + bltapt += (blt_info.hblitsize * 2 + blt_info.bltamod) * blt_info.vblitsize; } if (bltcon0 & 0x400) { bltbdatptr = bltbpt; - bltbpt += (hblitsize * 2 + blt_info.bltbmod) * vblitsize; + bltbpt += (blt_info.hblitsize * 2 + blt_info.bltbmod) * blt_info.vblitsize; } if (bltcon0 & 0x200) { bltcdatptr = bltcpt; - bltcpt += (hblitsize * 2 + blt_info.bltcmod) * vblitsize; + bltcpt += (blt_info.hblitsize * 2 + blt_info.bltcmod) * blt_info.vblitsize; } if (bltcon0 & 0x100) { bltddatptr = bltdpt; - bltdpt += (hblitsize * 2 + blt_info.bltdmod) * vblitsize; + bltdpt += (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize; } #ifdef SPEEDUP @@ -366,9 +398,9 @@ static void blitter_dofast (void) uaecptr dstp = 0; int dodst = 0; - for (j = 0; j < vblitsize; j++) { + for (j = 0; j < blt_info.vblitsize; j++) { blitfc = !!(bltcon1 & 0x4); - for (i = 0; i < hblitsize; i++) { + for (i = 0; i < blt_info.hblitsize; i++) { uae_u32 bltadat, blitahold; uae_u16 bltbdat; if (bltadatptr) { @@ -424,7 +456,7 @@ static void blitter_dofast (void) blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xFFFF; - blit_masktable[hblitsize - 1] = 0xFFFF; + blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; bltstate = BLT_done; } @@ -436,23 +468,23 @@ static void blitter_dofast_desc (void) uae_u8 mt = bltcon0 & 0xFF; blit_masktable[0] = blt_info.bltafwm; - blit_masktable[hblitsize - 1] &= blt_info.bltalwm; + blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm; if (bltcon0 & 0x800) { bltadatptr = bltapt; - bltapt -= (hblitsize*2 + blt_info.bltamod)*vblitsize; + bltapt -= (blt_info.hblitsize * 2 + blt_info.bltamod) * blt_info.vblitsize; } if (bltcon0 & 0x400) { bltbdatptr = bltbpt; - bltbpt -= (hblitsize*2 + blt_info.bltbmod)*vblitsize; + bltbpt -= (blt_info.hblitsize * 2 + blt_info.bltbmod) * blt_info.vblitsize; } if (bltcon0 & 0x200) { bltcdatptr = bltcpt; - bltcpt -= (hblitsize*2 + blt_info.bltcmod)*vblitsize; + bltcpt -= (blt_info.hblitsize * 2 + blt_info.bltcmod) * blt_info.vblitsize; } if (bltcon0 & 0x100) { bltddatptr = bltdpt; - bltdpt -= (hblitsize*2 + blt_info.bltdmod)*vblitsize; + bltdpt -= (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize; } #ifdef SPEEDUP if (blitfunc_dofast_desc[mt] && !blitfill) { @@ -465,9 +497,9 @@ static void blitter_dofast_desc (void) uaecptr dstp = 0; int dodst = 0; - for (j = 0; j < vblitsize; j++) { + for (j = 0; j < blt_info.vblitsize; j++) { blitfc = !!(bltcon1 & 0x4); - for (i = 0; i < hblitsize; i++) { + for (i = 0; i < blt_info.hblitsize; i++) { uae_u32 bltadat, blitahold; uae_u16 bltbdat; if (bltadatptr) { @@ -523,7 +555,7 @@ static void blitter_dofast_desc (void) blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xFFFF; - blit_masktable[hblitsize - 1] = 0xFFFF; + blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; bltstate = BLT_done; } @@ -633,7 +665,7 @@ static void blitter_line_proc (void) STATIC_INLINE void blitter_nxline (void) { blineb = (blineb << 1) | (blineb >> 15); - vblitsize--; + blt_info.vblitsize--; bltstate = BLT_read; } @@ -645,7 +677,7 @@ static int blitter_vcounter1, blitter_vcounter2; static void decide_blitter_line (int hsync, int hpos) { - if (blit_final && vblitsize) + if (blit_final && blt_info.vblitsize) blit_final = 0; while (last_blitter_hpos < hpos) { int c = channel_state (blit_cyclecounter); @@ -707,7 +739,7 @@ static void decide_blitter_line (int hsync, int hpos) record_dma_blit (0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); blitlinepixel = 0; } - if (vblitsize == 0) { + if (blt_info.vblitsize == 0) { bltdpt = bltcpt; blit_final = 1; blit_cyclecounter = 0; @@ -742,7 +774,7 @@ static void actually_do_blit (void) blitter_write (); blitlinepixel = 0; } - if (vblitsize == 0) + if (blt_info.vblitsize == 0) bltstate = BLT_done; } while (bltstate != BLT_done); bltdpt = bltcpt; @@ -798,7 +830,7 @@ STATIC_INLINE uae_u16 blitter_doblit (void) bltadat = blt_info.bltadat; if (blitter_hcounter1 == 0) bltadat &= blt_info.bltafwm; - if (blitter_hcounter1 == hblitsize - 1) + if (blitter_hcounter1 == blt_info.hblitsize - 1) bltadat &= blt_info.bltalwm; if (blitdesc) blitahold = (((uae_u32)bltadat << 16) | preva) >> blt_info.blitdownashift; @@ -851,7 +883,7 @@ STATIC_INLINE void blitter_doddma (int hpos) chipmem_agnus_wput2 (bltdpt, d); bltdpt += blit_add; blitter_hcounter2++; - if (blitter_hcounter2 == hblitsize) { + if (blitter_hcounter2 == blt_info.hblitsize) { blitter_hcounter2 = 0; bltdpt += blit_modaddd; blitter_vcounter2++; @@ -909,7 +941,7 @@ STATIC_INLINE void blitter_dodma (int ch, int hpos) if (bltcon0 & 0x100) ddat1use = 1; blitter_hcounter1++; - if (blitter_hcounter1 == hblitsize) { + if (blitter_hcounter1 == blt_info.hblitsize) { blitter_hcounter1 = 0; if (bltcon0 & 0x800) bltapt += blit_modadda; @@ -1049,14 +1081,14 @@ void decide_blitter (int hpos) blit_cyclecounter++; blit_totalcyclecounter++; } else { - if (blitter_vcounter1 < vblitsize) { + if (blitter_vcounter1 < blt_info.vblitsize) { blitter_dodma (c, last_blitter_hpos); } blit_cyclecounter++; blit_totalcyclecounter++; } - if (blitter_vcounter1 >= vblitsize && blitter_vcounter2 >= vblitsize) { + if (blitter_vcounter1 >= blt_info.vblitsize && blitter_vcounter2 >= blt_info.vblitsize) { if (!ddat1use && !ddat2use) { blitter_done (last_blitter_hpos); return; @@ -1065,7 +1097,7 @@ void decide_blitter (int hpos) break; } - if (!blit_final && blitter_vcounter1 == vblitsize && channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) { + if (!blit_final && blitter_vcounter1 == blt_info.vblitsize && channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) { blitter_interrupt (last_blitter_hpos, 0); blit_cyclecounter = 0; blit_final = 1; @@ -1130,9 +1162,9 @@ static void blit_bltset (int con) blitfill = !!(bltcon1 & 0x18); if (blitline) { - if (hblitsize != 2) - debugtest (DEBUGTEST_BLITTER, L"weird hblitsize in linemode: %d vsize=%d\n", - hblitsize, vblitsize); + if (blt_info.hblitsize != 2) + debugtest (DEBUGTEST_BLITTER, L"weird blt_info.hblitsize in linemode: %d vsize=%d\n", + blt_info.hblitsize, blt_info.vblitsize); blit_diag = blit_cycle_diagram_line; } else { if (con & 2) { @@ -1257,8 +1289,6 @@ static void do_blitter2 (int hpos, int copper) bltstate = BLT_done; - hblitsize = blt_info.hblitsize; - vblitsize = blt_info.vblitsize; blitter_cycle_exact = currprefs.blitter_cycle_exact; blt_info.blitzero = 1; preva = 0; @@ -1285,10 +1315,10 @@ static void do_blitter2 (int hpos, int copper) blitonedot = 0; blitlinepixel = 0; blitsing = bltcon1 & 0x2; - cycles = vblitsize; + cycles = blt_info.vblitsize; } else { - blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * hblitsize + cpu_cycles) * CYCLE_UNIT; - cycles = vblitsize * hblitsize; + blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * blt_info.hblitsize + cpu_cycles) * CYCLE_UNIT; + cycles = blt_info.vblitsize * blt_info.hblitsize; } if (cleanstart) { @@ -1310,7 +1340,7 @@ static void do_blitter2 (int hpos, int copper) if (blit_ch & 8) ch++; write_log (L"blitstart: %dx%d ch=%d %d*%d=%d d=%d f=%02X n=%d pc=%p l=%d dma=%04X\n", - hblitsize, vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, + blt_info.hblitsize, blt_info.vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, blitdesc ? 1 : 0, blitfill, dmaen (DMA_BLITPRI) ? 1 : 0, M68K_GETPC, blitline, dmacon); blitter_dump (); } @@ -1345,16 +1375,16 @@ static void do_blitter2 (int hpos, int copper) blitter_hcounter1 = blitter_hcounter2 = 0; blitter_vcounter1 = blitter_vcounter2 = 0; if (blit_nod) - blitter_vcounter2 = vblitsize; + blitter_vcounter2 = blt_info.vblitsize; blit_cyclecounter = -BLITTER_STARTUP_CYCLES; blit_waitcyclecounter = copper; blit_startcycles = 0; - blit_maxcyclecounter = hblitsize * vblitsize + 2; + blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2; #endif return; } - if (vblitsize == 0 || (blitline && hblitsize != 2)) { + if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) { blitter_done (hpos); return; } @@ -1466,10 +1496,32 @@ void blitter_slowdown (int ddfstrt, int ddfstop, int totalcycles, int freecycles #ifdef SAVESTATE +void restore_blitter_finish (void) +{ + record_dma_reset (); + record_dma_reset (); + if (blt_statefile_type == 0) { + blit_interrupt = 1; + if (bltstate == BLT_init) { + write_log (L"blitter was started but DMA was inactive during save\n"); + //do_blitter (0); + } + if (blt_delayed_irq < 0) { + if (intreq & 0x0040) + blt_delayed_irq = 3; + intreq &= 0x0040; + } + } else { + last_blitter_hpos = 0; + blit_modset (); + } +} + uae_u8 *restore_blitter (uae_u8 *src) { uae_u32 flags = restore_u32(); + blt_statefile_type = 0; blt_delayed_irq = 0; bltstate = BLT_done; if (flags & 4) { @@ -1486,22 +1538,6 @@ uae_u8 *restore_blitter (uae_u8 *src) return src; } -void restore_blitter_finish (void) -{ - record_dma_reset (); - record_dma_reset (); - blit_interrupt = 1; - if (bltstate == BLT_init) { - write_log (L"blitter was started but DMA was inactive during save\n"); - //do_blitter (0); - } - if (blt_delayed_irq < 0) { - if (intreq & 0x0040) - blt_delayed_irq = 3; - intreq &= 0x0040; - } -} - uae_u8 *save_blitter (int *len, uae_u8 *dstptr) { uae_u8 *dstbak,*dst; @@ -1524,4 +1560,169 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr) } +// totally non-real-blitter-like state save but better than nothing.. + +uae_u8 *restore_blitter_new (uae_u8 *src) +{ + uae_u8 state; + blt_statefile_type = 1; + blitter_cycle_exact = restore_u8 (); + state = restore_u8 (); + + blit_first_cycle = restore_u32 (); + blit_last_cycle = restore_u32 (); + blit_waitcyclecounter = restore_u32 (); + blit_startcycles = restore_u32 (); + blit_maxcyclecounter = restore_u32 (); + blit_firstline_cycles = restore_u32 (); + blit_cyclecounter = restore_u32 (); + blit_slowdown = restore_u32 (); + blit_misscyclecounter = restore_u32 (); + + blitter_hcounter1 = restore_u16 (); + blitter_hcounter2 = restore_u16 (); + blitter_vcounter1 = restore_u16 (); + blitter_vcounter2 = restore_u16 (); + blit_ch = restore_u8 (); + blit_dmacount = restore_u8 (); + blit_dmacount2 = restore_u8 (); + blit_nod = restore_u8 (); + blit_final = restore_u8 (); + blitfc = restore_u8 (); + blitife = restore_u8 (); + + blt_info.blitbshift = restore_u8 (); + blt_info.blitdownbshift = restore_u8 (); + blt_info.blitashift = restore_u8 (); + blt_info.blitdownashift = restore_u8 (); + + ddat1use = restore_u8 (); + ddat2use = restore_u8 (); + ddat1 = restore_u16 (); + ddat2 = restore_u16 (); + + blitline = restore_u8 (); + blitfill = restore_u8 (); + blinea = restore_u16 (); + blineb = restore_u16 (); + blinea_shift = restore_u8 (); + blitonedot = restore_u8 (); + blitlinepixel = restore_u8 (); + blitsing = restore_u8 (); + blitlinepixel = restore_u8 (); + blit_interrupt = restore_u8 (); + blt_delayed_irq = restore_u8 (); + blt_info.blitzero = restore_u8 (); + blt_info.got_cycle = restore_u8 (); + + blit_frozen = restore_u8 (); + blit_faulty = restore_u8 (); + original_ch = restore_u8 (); + original_fill = restore_u8 (); + original_line = restore_u8 (); + + blit_diag = set_cycle_diagram_type (restore_u8 ()); + + if (restore_u16 () != 0x1234) + write_log (L"error\n"); + + blitter_nasty = restore_u8 (); + + bltstate = BLT_done; + if (!blitter_cycle_exact) { + if (state > 0) + do_blitter (0, 0); + } else { + if (state == 1) + bltstate = BLT_init; + else if (state == 2) + bltstate = BLT_work; + } + return src; +} + +uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak,*dst; + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + + uae_u8 state; + save_u8 (blitter_cycle_exact ? 1 : 0); + if (bltstate == BLT_done) + state = 0; + else if (bltstate == BLT_init) + state = 1; + else + state = 2; + save_u8 (state); + + if (bltstate != BLT_done) { + write_log (L"BLITTER active while saving state\n"); + blitter_dump (); + } + + save_u32 (blit_first_cycle); + save_u32 (blit_last_cycle); + save_u32 (blit_waitcyclecounter); + save_u32 (blit_startcycles); + save_u32 (blit_maxcyclecounter); + save_u32 (blit_firstline_cycles); + save_u32 (blit_cyclecounter); + save_u32 (blit_slowdown); + save_u32 (blit_misscyclecounter); + + save_u16 (blitter_hcounter1); + save_u16 (blitter_hcounter2); + save_u16 (blitter_vcounter1); + save_u16 (blitter_vcounter2); + save_u8 (blit_ch); + save_u8 (blit_dmacount); + save_u8 (blit_dmacount2); + save_u8 (blit_nod); + save_u8 (blit_final); + save_u8 (blitfc); + save_u8 (blitife); + + save_u8 (blt_info.blitbshift); + save_u8 (blt_info.blitdownbshift); + save_u8 (blt_info.blitashift); + save_u8 (blt_info.blitdownashift); + + save_u8 (ddat1use); + save_u8 (ddat2use); + save_u16 (ddat1); + save_u16 (ddat2); + + save_u8 (blitline); + save_u8 (blitfill); + save_u16 (blinea); + save_u16 (blineb); + save_u8 (blinea_shift); + save_u8 (blitonedot); + save_u8 (blitlinepixel); + save_u8 (blitsing); + save_u8 (blitlinepixel); + save_u8 (blit_interrupt); + save_u8 (blt_delayed_irq); + save_u8 (blt_info.blitzero); + save_u8 (blt_info.got_cycle); + + save_u8 (blit_frozen); + save_u8 (blit_faulty); + save_u8 (original_ch); + save_u8 (original_fill); + save_u8 (original_line); + save_u8 (get_cycle_diagram_type (blit_diag)); + + save_u16 (0x1234); + + save_u8 (blitter_nasty); + + *len = dst - dstbak; + return dstbak; +} + #endif /* SAVESTATE */ diff --git a/blkdev.cpp b/blkdev.cpp index 8c549f59..68d988e9 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -35,6 +35,10 @@ static int delayed[MAX_TOTAL_SCSI_DEVICES]; static uae_sem_t unitsem[MAX_TOTAL_SCSI_DEVICES]; static int unitsem_cnt[MAX_TOTAL_SCSI_DEVICES]; +static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256]; +static int imagechangetime[MAX_TOTAL_SCSI_DEVICES]; +static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES], wasopen[MAX_TOTAL_SCSI_DEVICES]; + /* convert minutes, seconds and frames -> logical sector number */ int msf2lsn (int msf) { @@ -421,11 +425,17 @@ void blkdev_cd_change (int unitnum, const TCHAR *name) void device_func_reset (void) { + for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { + wasopen[i] = false; + waspaused[i] = false; + imagechangetime[i] = 0; + cdimagefileinuse[i] = false; + newimagefiles[i][0] = 0; + } } int device_func_init (int flags) { - device_func_reset (); blkdev_fix_prefs (&currprefs); install_driver (flags); return 1; @@ -455,12 +465,6 @@ void blkdev_exitgui (void) } } - - -static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256]; -static int imagechangetime[MAX_TOTAL_SCSI_DEVICES]; -static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES], wasopen[MAX_TOTAL_SCSI_DEVICES]; - static void check_changes (int unitnum) { bool changed = false; @@ -1038,6 +1042,19 @@ static int addtocentry (uae_u8 **dstp, int *len, int point, int newpoint, int ms return -1; } +static int scsiemudrv (int unitnum, uae_u8 *cmd) +{ + if (failunit (unitnum)) + return -1; + if (!getsem (unitnum)) + return 0; + int v = 0; + if (device_func[unitnum]->scsiemu) + v = device_func[unitnum]->scsiemu (unitnum, cmd); + freesem (unitnum); + return v; +} + static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di) { int msf = cmd[0] == 0xb9; @@ -1419,6 +1436,7 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, break; case 0x1b: // START/STOP sys_command_cd_stop (unitnum); + scsiemudrv (unitnum, cmdbuf); scsi_len = 0; break; case 0x1e: // PREVENT/ALLOW MEDIA REMOVAL @@ -1743,6 +1761,8 @@ uae_u8 *save_cd (int num, int *len) if (!currprefs.cdslots[num].inuse || num >= MAX_TOTAL_SCSI_DEVICES) return NULL; + if (!currprefs.cs_cd32cd && !currprefs.cs_cdtvcd && !currprefs.scsi) + return NULL; dstbak = dst = xmalloc (uae_u8, 4 + 256 + 4 + 4); save_u32 (4); save_string (currprefs.cdslots[num].name); diff --git a/cdtv.cpp b/cdtv.cpp index 308e965f..a83d99f6 100644 --- a/cdtv.cpp +++ b/cdtv.cpp @@ -324,7 +324,7 @@ static int play_cdtrack (uae_u8 *p) end = last_cd_position; start_found = end_found = 0; - for (j = 0; j < toc.points; j++) { + for (j = toc.first_track_offset; j <= toc.last_track_offset; j++) { struct cd_toc *s = &toc.toc[j]; if (track_start == s->track) { start_found++; @@ -1771,11 +1771,16 @@ void cdtv_check_banks (void) #ifdef SAVESTATE -uae_u8 *save_dmac (int *len) +uae_u8 *save_dmac (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; - dstbak = dst = xmalloc (uae_u8, 1000); + if (!currprefs.cs_cdtvcd) + return NULL; + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); // model (0=original,1=rev2,2=superdmac) save_u32 (1); @@ -1806,13 +1811,17 @@ uae_u8 *restore_dmac (uae_u8 *src) return src; } -uae_u8 *save_cdtv (int *len) +uae_u8 *save_cdtv (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; if (!currprefs.cs_cdtvcd) return NULL; - dstbak = dst = xmalloc (uae_u8, 1000); + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); save_u32 (1); diff --git a/cfgfile.cpp b/cfgfile.cpp index ea693cea..45d96300 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -165,8 +165,8 @@ static const TCHAR *maxhoriz[] = { L"lores", L"hires", L"superhires", 0 }; static const TCHAR *maxvert[] = { L"nointerlace", L"interlace", 0 }; static const TCHAR *abspointers[] = { L"none", L"mousehack", L"tablet", 0 }; static const TCHAR *magiccursors[] = { L"both", L"native", L"host", 0 }; -static const TCHAR *autoscale[] = { L"none", L"standard", L"max", L"scale", L"resize", L"center", 0 }; -static const TCHAR *joyportmodes[] = { L"", L"mouse", L"djoy", L"ajoy", L"cdtvjoy", L"cd32joy", L"lightpen", 0 }; +static const TCHAR *autoscale[] = { L"none", L"auto", L"standard", L"max", L"scale", L"resize", L"center", 0 }; +static const TCHAR *joyportmodes[] = { L"", L"mouse", L"djoy", L"gamepad", L"ajoy", L"cdtvjoy", L"cd32joy", L"lightpen", 0 }; static const TCHAR *joyaf[] = { L"none", L"normal", L"toggle", 0 }; static const TCHAR *epsonprinter[] = { L"none", L"ascii", L"epson_matrix_9pin", L"epson_matrix_24pin", L"epson_matrix_48pin", 0 }; static const TCHAR *aspects[] = { L"none", L"vga", L"tv", 0 }; @@ -190,7 +190,7 @@ static const TCHAR *obsolete[] = { L"kickstart_key_file", L"fast_copper", L"sound_adjust", L"serial_hardware_dtrdsr", L"gfx_filter_upscale", L"gfx_correct_aspect", L"gfx_autoscale", L"parallel_sampler", L"parallel_ascii_emulation", - L"avoid_vid", L"avoid_dga", L"z3chipmem_size", + L"avoid_vid", L"avoid_dga", L"z3chipmem_size", L"state_replay_buffer", L"state_replay", NULL }; @@ -888,9 +888,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) : p->keyboard_lang == KBD_LANG_IT ? L"it" : L"FOO")); - cfgfile_dwrite_str (f, L"state_replay", p->statecapture ? L"yes" : L"no"); cfgfile_dwrite (f, L"state_replay_rate", L"%d", p->statecapturerate); - cfgfile_dwrite (f, L"state_replay_buffer", L"%d", p->statecapturebuffersize); + cfgfile_dwrite (f, L"state_replay_buffers", L"%d", p->statecapturebuffersize); + cfgfile_dwrite_bool (f, L"state_replay_autoplay", p->inprec_autoplay); cfgfile_dwrite_bool (f, L"warp", p->turbo_emulation); #ifdef FILESYS @@ -1218,7 +1218,8 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) if (cfgfile_intval (option, value, L"sound_latency", &p->sound_latency, 1) || cfgfile_intval (option, value, L"sound_max_buff", &p->sound_maxbsiz, 1) || cfgfile_intval (option, value, L"state_replay_rate", &p->statecapturerate, 1) - || cfgfile_intval (option, value, L"state_replay_buffer", &p->statecapturebuffersize, 1) + || cfgfile_intval (option, value, L"state_replay_buffers", &p->statecapturebuffersize, 1) + || cfgfile_yesno (option, value, L"state_replay_autoplay", &p->inprec_autoplay) || cfgfile_intval (option, value, L"sound_frequency", &p->sound_freq, 1) || cfgfile_intval (option, value, L"sound_volume", &p->sound_volume, 1) || cfgfile_intval (option, value, L"sound_stereo_separation", &p->sound_stereo_separation, 1) @@ -1284,7 +1285,6 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) || cfgfile_yesno (option, value, L"sound_auto", &p->sound_auto) || cfgfile_yesno (option, value, L"sound_stereo_swap_paula", &p->sound_stereo_swap_paula) || cfgfile_yesno (option, value, L"sound_stereo_swap_ahi", &p->sound_stereo_swap_ahi) - || cfgfile_yesno (option, value, L"state_replay", &p->statecapture) || cfgfile_yesno (option, value, L"avoid_cmov", &p->avoid_cmov) || cfgfile_yesno (option, value, L"log_illegal_mem", &p->illegal_mem) || cfgfile_yesno (option, value, L"filesys_no_fsdb", &p->filesys_no_uaefsdb) @@ -3604,13 +3604,13 @@ void default_prefs (struct uae_prefs *p, int type) p->gfx_filter = 0; p->gfx_filtershader[0] = 0; p->gfx_filtermask[0] = 0; - p->gfx_filter_horiz_zoom_mult = 0; - p->gfx_filter_vert_zoom_mult = 0; + p->gfx_filter_horiz_zoom_mult = 1000; + p->gfx_filter_vert_zoom_mult = 1000; p->gfx_filter_bilinear = 0; p->gfx_filter_filtermode = 0; p->gfx_filter_scanlineratio = (1 << 4) | 1; p->gfx_filter_keep_aspect = 0; - p->gfx_filter_autoscale = 0; + p->gfx_filter_autoscale = AUTOSCALE_STATIC_AUTO; p->gfx_filteroverlay_overscan = 0; _tcscpy (p->floppyslots[0].df, L"df0.adf"); @@ -3672,9 +3672,9 @@ void default_prefs (struct uae_prefs *p, int type) p->dfxclickvolume = 33; p->dfxclickchannelmask = 0xffff; - p->statecapturebuffersize = 20 * 1024 * 1024; + p->statecapturebuffersize = 100; p->statecapturerate = 5 * 50; - p->statecapture = 0; + p->inprec_autoplay = true; #ifdef UAE_MINI default_prefs_mini (p, 0); @@ -4394,13 +4394,6 @@ int built_in_chipset_prefs (struct uae_prefs *p) void config_check_vsync (void) { - static int cnt = 0; - if (cnt == 0) { - /* resolution_check_change (); */ - DISK_check_change (); - cnt = 5; - } - cnt--; if (config_changed) { // if (config_changed == 1) // write_log (L"* configuration check trigger\n"); diff --git a/cia.cpp b/cia.cpp index 03d7fcdb..a2b16359 100644 --- a/cia.cpp +++ b/cia.cpp @@ -38,6 +38,7 @@ #include "ersatz.h" #include "sampler.h" #include "dongle.h" +#include "inputrecord.h" #define CIAA_DEBUG_R 0 #define CIAA_DEBUG_W 0 @@ -145,15 +146,19 @@ static void compute_passed_time (void) one of the timer values will be modified, and CIA_calctimers will be called in the same cycle. */ -static void CIA_update (void) +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; + if (!ciaclocks) + return 0; + /* CIA A timers */ if ((ciaacra & 0x21) == 0x01) { assert ((ciaata + 1) >= ciaclocks); @@ -170,7 +175,8 @@ static void CIA_update (void) } if ((ciaacrb & 0x61) == 0x01) { assert ((ciaatb + 1) >= ciaclocks); - if ((ciaatb + 1) == ciaclocks) aovflb = 1; + if ((ciaatb + 1) == ciaclocks) + aovflb = 1; ciaatb -= ciaclocks; } @@ -190,38 +196,53 @@ static void CIA_update (void) } if ((ciabcrb & 0x61) == 0x01) { assert ((ciabtb + 1) >= ciaclocks); - if ((ciabtb + 1) == ciaclocks) bovflb = 1; + if ((ciabtb + 1) == ciaclocks) + bovflb = 1; ciabtb -= ciaclocks; } if (aovfla) { - ciaaicr |= 1; RethinkICRA (); + ciaaicr |= 1; icr = 1; ciaata = ciaala; - if (ciaacra & 0x8) ciaacra &= ~1; + if (ciaacra & 0x8) + ciaacra &= ~1; } if (aovflb) { - ciaaicr |= 2; RethinkICRA (); + ciaaicr |= 2; icr = 1; ciaatb = ciaalb; - if (ciaacrb & 0x8) ciaacrb &= ~1; + if (ciaacrb & 0x8) + ciaacrb &= ~1; } if (asp) { - ciaaicr |= 8; RethinkICRA (); + ciaaicr |= 8; icr = 1; } if (bovfla) { - ciabicr |= 1; RethinkICRB (); + ciabicr |= 1; icr |= 2; ciabta = ciabla; - if (ciabcra & 0x8) ciabcra &= ~1; + if (ciabcra & 0x8) + ciabcra &= ~1; } if (bovflb) { - ciabicr |= 2; RethinkICRB (); + ciabicr |= 2; icr |= 2; ciabtb = ciablb; - if (ciabcrb & 0x8) ciabcrb &= ~1; + if (ciabcrb & 0x8) + ciabcrb &= ~1; } if (bsp) { - ciabicr |= 8; RethinkICRB (); + 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) @@ -232,6 +253,7 @@ static void CIA_calctimers (void) if ((ciaacra & 0x21) == 0x01) { ciaatimea = (DIV10 - div10) + DIV10 * ciaata; } +#if 0 if ((ciaacrb & 0x61) == 0x41) { /* Timer B will not get any pulses if Timer A is off. */ if (ciaatimea >= 0) { @@ -241,12 +263,11 @@ static void CIA_calctimers (void) /* Otherwise, we can determine the time of the underflow. */ /* This may overflow, however. So just ignore this timer and use the fact that we'll call CIA_handler for the A timer. */ -#if 0 - ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; -#endif + /* ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; */ } } } +#endif if ((ciaacrb & 0x61) == 0x01) { ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb; } @@ -254,6 +275,7 @@ static void CIA_calctimers (void) if ((ciabcra & 0x21) == 0x01) { ciabtimea = (DIV10 - div10) + DIV10 * ciabta; } +#if 0 if ((ciabcrb & 0x61) == 0x41) { /* Timer B will not get any pulses if Timer A is off. */ if (ciabtimea >= 0) { @@ -261,12 +283,11 @@ static void CIA_calctimers (void) * one pulse, it will not underflow. */ if (ciabtb == 0 || (ciabcra & 0x8) == 0) { /* Otherwise, we can determine the time of the underflow. */ -#if 0 - ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; -#endif + /* ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; */ } } } +#endif if ((ciabcrb & 0x61) == 0x01) { ciabtimeb = (DIV10 - div10) + DIV10 * ciabtb; } @@ -274,10 +295,14 @@ static void CIA_calctimers (void) || 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; + 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(); @@ -333,7 +358,6 @@ STATIC_INLINE void ciaa_checkalarm (int inc) } } - #ifdef TOD_HACK static uae_u64 tod_hack_tv, tod_hack_tod, tod_hack_tod_last; static int tod_hack_enabled; @@ -463,8 +487,13 @@ static void resetwarning_check (void) } } -void CIA_hsync_handler (int dotod) +void CIA_hsync_prehandler (void) { +} + +void CIA_hsync_posthandler (bool dotod) +{ + if (ciabtodon && dotod) { ciabtod++; ciabtod &= 0xFFFFFF; @@ -478,7 +507,7 @@ void CIA_hsync_handler (int dotod) resetwarning_check (); while (keys_available ()) get_next_key (); - } else if ((keys_available() || kbstate < 3) && kback && (ciaacra & 0x40) == 0 && (hsync_counter & 15) == 0) { + } else if ((keys_available () || kbstate < 3) && kback && (ciaacra & 0x40) == 0 && (hsync_counter & 15) == 0) { /* * This hack lets one possible ciaaicr cycle go by without any key * being read, for every cycle in which a key is pulled out of the @@ -548,7 +577,7 @@ static void led_vsync (void) else if (led_cycles_off && !led_cycles_on) v = 0; else if (led_cycles_off) - v = led_cycles_on * 255 / led_cycles_off; + v = led_cycles_on * 255 / (led_cycles_on + led_cycles_off); else v = 255; if (v < 0) @@ -567,9 +596,14 @@ static void led_vsync (void) led_cycle = get_cycles (); } -void CIA_vsync_handler (int dotod) +void CIA_vsync_prehandler (void) { led_vsync (); + CIA_handler (); +} + +void CIA_vsync_posthandler (bool dotod) +{ #ifdef TOD_HACK if (currprefs.tod_hack && tod_hack_enabled == 1) return; @@ -579,6 +613,12 @@ void CIA_vsync_handler (int dotod) ciaatod &= 0xFFFFFF; ciaa_checkalarm (1); } +#if 0 + if (vpos == 0) { + write_log (L"%d\n", vsync_counter); + dumpcia (); + } +#endif } static void bfe001_change (void) @@ -632,6 +672,14 @@ static uae_u8 ReadCIAA (unsigned int addr) if (notinrom()) write_log (L"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 @@ -1146,11 +1194,6 @@ static void WriteCIAB (uae_u16 addr, uae_u8 val) } } -void CIA_inprec_prepare (void) -{ - sleepyhead = 0; -} - void CIA_reset (void) { #ifdef TOD_HACK @@ -1160,9 +1203,8 @@ void CIA_reset (void) if (currprefs.tod_hack) tod_hack_enabled = 312 * 50 * 10; #endif + kback = 1; - kbstate = 3; - ciaasdr_unread = 0; serbits = 0; oldovl = 1; oldcd32mute = 1; @@ -1171,6 +1213,8 @@ void CIA_reset (void) if (!savestate_state) { kbstate = 0; + ciaasdr_unread = 0; + sleepyhead = 0; ciaatlatch = ciabtlatch = 0; ciaapra = 0; ciaadra = 0; ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0; @@ -1183,8 +1227,9 @@ void CIA_reset (void) 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); } - CIA_calctimers (); if (ersatzkickfile) ersatz_chipcopy (); else @@ -1199,11 +1244,9 @@ void CIA_reset (void) map_overlay (1); oldovl = false; } - /* select drives */ - DISK_select (ciabprb); } #ifdef CD32 - if (savestate_state != STATE_RESTORE && savestate_state != STATE_DORESTORE) { + if (!isrestore ()) { akiko_reset (); if (!akiko_init ()) currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = 0; @@ -1213,14 +1256,14 @@ void CIA_reset (void) void dumpcia (void) { - console_out_f (L"A: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n", + write_log (L"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 (L"TOD %06x (%06x) ALARM %06x %c%c\n", - ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S'); - console_out_f (L"B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n", + write_log (L"TOD %06x (%06x) ALARM %06x %c%c CYC=%08X\n", + ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S', get_cycles ()); + write_log (L"B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n", ciabcra, ciabcrb, ciaaicr, ciabimask, ciabta, ciabla, ciabtb, ciablb); - console_out_f (L"TOD %06x (%06x) ALARM %06x %c%c\n", - ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S'); + write_log (L"TOD %06x (%06x) ALARM %06x %c%c CLK=%d\n", + ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S', div10 / CYCLE_UNIT); } /* CIA memory access */ @@ -1241,6 +1284,8 @@ addrbank cia_bank = { cia_lgeti, cia_wgeti, ABFLAG_IO }; +// Gayle does not enable CIA /CS lines if both CIAs are selected +// Non-Gayle based Amigas enable both CIAs in this situation STATIC_INLINE int isgayle (void) { @@ -1255,23 +1300,40 @@ STATIC_INLINE int isgayle (void) static void cia_wait_pre (void) { + if (currprefs.cachesize) + return; + #ifndef CUSTOM_SIMPLE - int div10 = (get_cycles () - eventtab[ev_cia].oldcycles) % DIV10; + int div = (get_cycles () - eventtab[ev_cia].oldcycles) % DIV10; int cycles; - if (div10 > DIV10 * ECLOCK_DATA_CYCLE / 10) { - cycles = DIV10 - div10; + if (div > DIV10 * ECLOCK_DATA_CYCLE / 10) { + cycles = DIV10 - div; cycles += DIV10 * ECLOCK_DATA_CYCLE / 10; } else { - cycles = DIV10 * ECLOCK_DATA_CYCLE / 10 - div10; + cycles = DIV10 * ECLOCK_DATA_CYCLE / 10 - div; + } + + if (cycles > 0) { + if (currprefs.cpu_cycle_exact) + x_do_cycles_pre (cycles); + else + do_cycles (cycles); } - do_cycles (cycles); #endif } -static void cia_wait_post (void) +static void cia_wait_post (uae_u32 value) { - do_cycles (6 * CYCLE_UNIT / 2); + 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 uae_u32 REGPARAM2 cia_bget (uaecptr addr) @@ -1279,6 +1341,7 @@ static uae_u32 REGPARAM2 cia_bget (uaecptr addr) int r = (addr & 0xf00) >> 8; uae_u8 v; + #ifdef JIT special_mem |= S_READ; #endif @@ -1304,7 +1367,8 @@ static uae_u32 REGPARAM2 cia_bget (uaecptr addr) } break; } - cia_wait_post (); + cia_wait_post (v); + return v; } @@ -1339,16 +1403,13 @@ static uae_u32 REGPARAM2 cia_wget (uaecptr addr) } break; } - cia_wait_post (); + cia_wait_post (v); return v; } static uae_u32 REGPARAM2 cia_lget (uaecptr addr) { uae_u32 v; -#ifdef JIT - special_mem |= S_READ; -#endif v = cia_wget (addr) << 16; v |= cia_wget (addr + 2); return v; @@ -1357,14 +1418,14 @@ static uae_u32 REGPARAM2 cia_lget (uaecptr addr) static uae_u32 REGPARAM2 cia_wgeti (uaecptr addr) { if (currprefs.cpu_model >= 68020) - return dummy_wgeti(addr); - return cia_wget(addr); + 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); + return dummy_lgeti (addr); + return cia_lget (addr); } static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value) @@ -1385,7 +1446,7 @@ static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value) warned--; } } - cia_wait_post (); + cia_wait_post (value); } static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value) @@ -1406,14 +1467,11 @@ static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value) warned--; } } - cia_wait_post (); + cia_wait_post (value); } static void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value) { -#ifdef JIT - special_mem |= S_WRITE; -#endif cia_wput (addr, value >> 16); cia_wput (addr + 2, value & 0xffff); } @@ -1650,6 +1708,23 @@ static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value) /* 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_finish (void) +{ + eventtab[ev_cia].oldcycles = get_cycles (); + CIA_update (); + CIA_calctimers (); + compute_passed_time (); + //dumpcia (); + DISK_select_set (ciabprb); +} + uae_u8 *restore_cia (int num, uae_u8 *src) { uae_u8 b; @@ -1657,47 +1732,47 @@ uae_u8 *restore_cia (int num, uae_u8 *src) uae_u32 l; /* CIA registers */ - b = restore_u8 (); /* 0 PRA */ + b = restore_u8 (); /* 0 PRA */ if (num) ciabpra = b; else ciaapra = b; - b = restore_u8 (); /* 1 PRB */ + b = restore_u8 (); /* 1 PRB */ if (num) ciabprb = b; else ciaaprb = b; - b = restore_u8 (); /* 2 DDRA */ + b = restore_u8 (); /* 2 DDRA */ if (num) ciabdra = b; else ciaadra = b; - b = restore_u8 (); /* 3 DDRB */ + b = restore_u8 (); /* 3 DDRB */ if (num) ciabdrb = b; else ciaadrb = b; - w = restore_u16 (); /* 4 TA */ + w = restore_u16 (); /* 4 TA */ if (num) ciabta = w; else ciaata = w; - w = restore_u16 (); /* 6 TB */ + w = restore_u16 (); /* 6 TB */ if (num) ciabtb = w; else ciaatb = w; - l = restore_u8 (); /* 8/9/A TOD */ + 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 */ + restore_u8 (); /* B unused */ + b = restore_u8 (); /* C SDR */ if (num) ciabsdr = b; else ciaasdr = b; - b = restore_u8 (); /* D ICR INFORMATION (not mask!) */ + b = restore_u8 (); /* D ICR INFORMATION (not mask!) */ if (num) ciabicr = b; else ciaaicr = b; - b = restore_u8 (); /* E CRA */ + b = restore_u8 (); /* E CRA */ if (num) ciabcra = b; else ciaacra = b; - b = restore_u8 (); /* F CRB */ + b = restore_u8 (); /* F CRB */ if (num) ciabcrb = b; else ciaacrb = b; /* CIA internal data */ - b = restore_u8 (); /* ICR MASK */ + b = restore_u8 (); /* ICR MASK */ if (num) ciabimask = b; else ciaaimask = b; - w = restore_u8 (); /* timer A latch */ + 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 (); /* timer B latch */ w |= restore_u8 () << 8; if (num) ciablb = w; else ciaalb = w; - w = restore_u8 (); /* TOD latched value */ + 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 (); /* alarm */ l |= restore_u8 () << 8; l |= restore_u8 () << 16; if (num) ciabalarm = l; else ciaaalarm = l; @@ -1720,9 +1795,9 @@ uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr) if (dstptr) dstbak = dst = dstptr; else - dstbak = dst = (uae_u8*)malloc (16 + 12 + 1 + 1); + dstbak = dst = xmalloc (uae_u8, 1000); - compute_passed_time (); + save_cia_prepare (); /* CIA registers */ @@ -1738,13 +1813,13 @@ uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr) save_u16 (t); t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 6 TB */ save_u16 (t); - b = (num ? ciabtod : ciaatod); /* 8 TODL */ + b = (num ? ciabtod : ciaatod); /* 8 TODL */ save_u8 (b); - b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */ + b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */ save_u8 (b); - b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */ + b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */ save_u8 (b); - save_u8 (0); /* B unused */ + save_u8 (0); /* B unused */ b = num ? ciabsdr : ciaasdr; /* C SDR */ save_u8 (b); b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */ @@ -1756,24 +1831,24 @@ uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr) /* CIA internal data */ - save_u8 (num ? ciabimask : ciaaimask); /* ICR */ - b = (num ? ciabla : ciaala); /* timer A latch LO */ + 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 */ + 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 */ + b = (num ? ciabtol : ciaatol); /* latched TOD LO */ save_u8 (b); - b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */ + b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */ save_u8 (b); - b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */ + 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 */ + b = (num ? ciabalarm >> 8 : ciaaalarm >> 8);/* alarm MED */ save_u8 (b); b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */ save_u8 (b); @@ -1787,10 +1862,38 @@ uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr) else b |= ciaatodon ? 2 : 0; /* TOD stopped? */ save_u8 (b); - save_u8 (div10 / CYCLE_UNIT); + 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); + save_u32 (getcapslockstate () ? 1 : 0); + save_u32 (1); + save_u8 (kbstate); + save_u8 (ciaasdr_unread); + save_u8 (sleepyhead); + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_keyboard (uae_u8 *src) +{ + setcapslockstate (restore_u32 () & 1); + uae_u32 v = restore_u32 (); + kbstate = restore_u8 (); + ciaasdr_unread = restore_u8 (); + sleepyhead = restore_u8 (); + if (!(v & 1)) + kbstate = 3; + return src; +} + #endif /* SAVESTATE */ diff --git a/cpummu.cpp b/cpummu.cpp index 603bf0e8..cdc6bb04 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -401,7 +401,7 @@ static ALWAYS_INLINE bool mmu_fill_atc_l1(uaecptr addr, bool super, bool data, b mmu_fill_atc_l2(addr, super, data, write, l); } if (!(data ? l->valid_data : l->valid_inst)) { - D(bug(L"MMU: non-resident page (%x,%x,%x)!\n", addr, regs.pc, regs.fault_pc)); + D(bug(L"MMU: non-resident page (%x,%x,%x)!\n", addr, regs.pc, regs.instruction_pc)); goto fail; } if (write) { diff --git a/custom.cpp b/custom.cpp index f0444c61..5c771eb4 100644 --- a/custom.cpp +++ b/custom.cpp @@ -28,6 +28,7 @@ #include "blitter.h" #include "xwin.h" #include "inputdevice.h" +#include "inputrecord.h" #include "keybuf.h" #include "serial.h" #include "autoconf.h" @@ -122,6 +123,9 @@ unsigned long int event_cycles, nextevent, is_lastline, currcycle; long cycles_to_next_event; long max_cycles_to_next_event; long cycles_to_hsync_event; +unsigned long int vsync_cycles; +static int extra_cycle; +unsigned long start_cycles; static int rpt_did_reset; struct ev eventtab[ev_max]; @@ -174,7 +178,7 @@ int maxhpos = MAXHPOS_PAL; int maxhpos_short = MAXHPOS_PAL; int maxvpos = MAXVPOS_PAL; int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes) -int hsyncstartpos; +int hsyncendpos, hsyncstartpos; static int maxvpos_total = 511; int minfirstline = VBLANK_ENDLINE_PAL; int equ_vblank_endline = EQU_ENDLINE_PAL; @@ -318,7 +322,7 @@ static int cop_min_waittime; * Statistics */ unsigned long int frametime = 0, lastframetime = 0, timeframes = 0; -unsigned long hsync_counter = 0, vsync_counter = 0, ciavsync_counter = 0; +unsigned long hsync_counter = 0, vsync_counter = 0; unsigned long int idletime; int bogusframe; @@ -1952,7 +1956,7 @@ static void record_color_change (int hpos, int regno, unsigned long value) int vpos2 = autoscale_bordercolors ? minfirstline : vpos; if (first_planes_vpos == 0) first_planes_vpos = vpos2 - 2; - if (plffirstline_total == maxvpos) + if (plffirstline_total == current_maxvpos ()) plffirstline_total = vpos2 - 2; if (vpos2 > last_planes_vpos || vpos2 > plflastline_total) plflastline_total = last_planes_vpos = vpos2 + 3; @@ -2729,14 +2733,22 @@ static void dumpsync (void) write_log (L" HSSTRT=%04X VSSTRT=%04X HCENTER=%04X\n", hsstrt, vsstrt, hcenter); } +int current_maxvpos (void) +{ + return maxvpos + (lof_store ? 1 : 0); +} + /* set PAL/NTSC or custom timing variables */ -void init_hz (void) +void init_hz (bool fullinit) { int isntsc; int odbl = doublescan, omaxvpos = maxvpos; int ovblank = vblank_hz; int hzc = 0; + if (fullinit) + vpos_count = vpos_count_prev = 0; + if (vsync_switchmode (-1, 0)) currprefs.gfx_avsync = changed_prefs.gfx_avsync = vsync_switchmode (-1, 0) ? 2 : 0; @@ -2818,8 +2830,13 @@ void init_hz (void) hsyncstartpos = hbstrt; else hsyncstartpos = maxhpos + hbstrt; + if (hbstop > maxhpos) + hsyncendpos = hbstop; + else + hsyncendpos = maxhpos + hbstop; } else { hsyncstartpos = maxhpos_short + 13; + hsyncendpos = 24; } eventtab[ev_hsync].oldcycles = get_cycles (); eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; @@ -2851,15 +2868,24 @@ void init_hz (void) if (vblank_hz != ovblank) updatedisplayarea (); inputdevice_tablet_strobe (); - write_log (L"%s mode%s%s V=%dHz H=%dHz (%dx%d)\n", + write_log (L"%s mode%s%s V=%dHz H=%dHz (%dx%d+%d)\n", isntsc ? L"NTSC" : L"PAL", (bplcon0 & 4) ? L" interlaced" : L"", doublescan > 0 ? L" dblscan" : L"", vblank_hz, vblank_hz * maxvpos_nom, - maxhpos, maxvpos); + maxhpos, maxvpos, lof_store ? 1 : 0); config_changed = 1; } +void init_hz (void) +{ + init_hz (false); +} +void init_hz_full (void) +{ + init_hz (true); +} + static void calcdiw (void) { int hstrt = diwstrt & 0xFF; @@ -3063,8 +3089,11 @@ static void VPOSW (uae_u16 v) lof_changed = 1; lof_store = (v & 0x8000) ? 1 : 0; } - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) + if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { lol = (v & 0x0080) ? 1 : 0; + if (!islinetoggle ()) + lol = 0; + } if (lof_changed) return; vpos &= 0x00ff; @@ -3521,7 +3550,6 @@ static void ADKCON (int hpos, uae_u16 v) { if (currprefs.produce_sound > 0) update_audio (); - DISK_update_adkcon (hpos, v); setclr (&adkcon, v); audio_update_adkmasks (); @@ -4926,7 +4954,7 @@ static void init_hardware_frame (void) ddffirstword_total = max_diwlastword; ddflastword_total = 0; plflastline_total = 0; - plffirstline_total = maxvpos; + plffirstline_total = current_maxvpos (); autoscale_bordercolors = 0; for (i = 0; i < MAX_SPRITES; i++) spr[i].ptxhpos = MAXHPOS; @@ -5047,7 +5075,44 @@ static void fpscounter (void) } } -static void vsync_handler (void) +// vsync functions that are not hardware timing related +static void vsync_handler_pre (void) +{ + if (bogusframe > 0) + bogusframe--; + + handle_events (); + +#ifdef PICASSO96 + picasso_handle_vsync (); +#endif + audio_vsync (); + blkdev_vsync (); + DISK_vsync (); + CIA_vsync_prehandler (); + + if (quit_program > 0) { + /* prevent possible infinite loop at wait_cycles().. */ + framecnt = 0; + reset_decisions (); + return; + } + + config_check_vsync (); + if (timehack_alive > 0) + timehack_alive--; + + inputdevice_vsync (); + + filesys_vsync (); + + sampler_vsync (); + + vsync_handle_redraw (lof_store, lof_changed); +} + +// emulated hardware vsync +static void vsync_handler_post (void) { fpscounter (); @@ -5082,11 +5147,6 @@ static void vsync_handler (void) framewait (); } - if (bogusframe > 0) - bogusframe--; - - handle_events (); - #if CUSTOM_DEBUG > 1 if ((intreq & 0x0020) && (intena & 0x0020)) write_log (L"vblank interrupt not cleared\n"); @@ -5095,28 +5155,11 @@ static void vsync_handler (void) lof_store = lof_store ? 0 : 1; lof_current = lof_store; -#ifdef PICASSO96 - picasso_handle_vsync (); -#endif - audio_vsync (); - blkdev_vsync (); - - if (quit_program > 0) { - /* prevent possible infinite loop at wait_cycles().. */ - framecnt = 0; - reset_decisions (); - return; - } - - config_check_vsync (); - if (debug_copper) record_copper_reset (); if (debug_dma) record_dma_reset (); - vsync_handle_redraw (lof_store, lof_changed); - if (p96refresh_active) { vpos_count = p96refresh_active; vtotal = vpos_count; @@ -5131,14 +5174,9 @@ static void vsync_handler (void) COPJMP (1, 1); - if (timehack_alive > 0) - timehack_alive--; - inputdevice_vsync (); - filesys_vsync (); - sampler_vsync (); - init_hardware_frame (); + vsync_cycles = get_cycles (); } #ifdef JIT @@ -5187,27 +5225,6 @@ static void copper_check (int n) } } -static void CIA_vsync_prehandler (int dotod) -{ - CIA_vsync_handler (dotod); -#if 0 - if (input_recording > 0) { - inprec_rstart(INPREC_CIAVSYNC); - inprec_ru32(ciavsync_counter); - inprec_rend(); - } else if (input_recording < 0) { - uae_u32 v = -1; - while (inprec_pstart(INPREC_CIAVSYNC)) { - v = inprec_pu32(); - inprec_pend(); - } - if (v != ciavsync_counter) - write_log (L"INPREC: ciavsync sync error %d <> %d\n", v, ciavsync_counter); - } -#endif - ciavsync_counter++; -} - /* 0 0 - @@ -5298,7 +5315,7 @@ static uae_u16 dmal, dmal_hpos; static void dmal_emu (uae_u32 v) { // Disk and Audio DMA bits are ignored by Agnus, Agnus only checks DMAL and master bit - if (!(dmacon & 0x200)) + if (!(dmacon & DMA_MASTER)) return; int hpos = current_hpos (); if (v >= 6) { @@ -5391,13 +5408,34 @@ static void events_dmal_hsync (void) events_dmal (7); } -static void hsync_handler (void) +static bool is_vsync (void) +{ + int vp = vpos + 1; + int vpc = vpos_count + 1; + /* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */ + if (vp >= maxvpos_total) + vp = 0; + if (vp == maxvpos + lof_store || vp == maxvpos + lof_store + 1 || vpc >= MAXVPOS) { + // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely + return true; + } + return false; +} + +static void set_hpos (void) +{ + maxhpos = maxhpos_short + lol; + eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; + eventtab[ev_hsync].oldcycles = get_cycles (); +} + +// this finishes current line +static void hsync_handler_pre (bool isvsync) { int hpos = current_hpos (); if (!nocustom ()) { sync_copper_with_cpu (maxhpos, 0); - last_copper_hpos = 0; finish_decisions (); if (thisline_decision.plfleft != -1) { if (currprefs.collision_level > 1) @@ -5416,7 +5454,11 @@ static void hsync_handler (void) hpos_lpen = lightpen_cx; lightpen_triggered = 1; } + hardware_line_completed (next_lineno); + if (doflickerfix () && interlace_seen) + hsync_scandoubler (); } + #ifdef A2065 a2065_hsync_handler (); #endif @@ -5427,46 +5469,79 @@ static void hsync_handler (void) CDTV_hsync_handler (); #endif decide_blitter (-1); - DISK_hsync (); -#ifdef CPUEMU_12 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { - memset (cycle_line, 0, sizeof cycle_line); - } +#ifdef PICASSO96 + picasso_handle_hsync (); #endif + { + void ahi_hsync (void); + ahi_hsync (); + } + + DISK_hsync (); + if (currprefs.produce_sound) + audio_hsync (); + CIA_hsync_prehandler (); + + hsync_counter++; if (islinetoggle ()) lol ^= 1; - if (vpos == equ_vblank_endline + 1 && lof_current != lof_store) { - // argh, line=0 field decision was wrong, someone did - // something stupid and changed LOF - // lof_current = lof_store; - // don't really know what to do here exactly without corrupt display + else + lol = 0; + + vpos++; + vpos_count++; + if (vpos >= maxvpos_total) + vpos = 0; + if (isvsync) { + vpos = 0; + vsync_counter++; } + set_hpos (); +#if 0 + static int ppp = 1; + if (input_record && hsync_counter == 50 * 313 + 1) { + ppp--; + if (ppp == 0) + activate_debugger (); + } +#endif +} - maxhpos = maxhpos_short + lol; - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - eventtab[ev_hsync].oldcycles = get_cycles (); +// this prepares for new line +static void hsync_handler_post (bool isvsync) +{ + last_copper_hpos = 0; +#ifdef CPUEMU_12 + if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { + memset (cycle_line, 0, sizeof cycle_line); + } +#endif - CIA_hsync_handler (!(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock)); + bool ciasyncs = !(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock); + CIA_hsync_posthandler (ciasyncs); if (currprefs.cs_ciaatod > 0) { static int cia_hsync; cia_hsync -= 256; if (cia_hsync <= 0) { - CIA_vsync_prehandler (1); + CIA_vsync_posthandler (1); cia_hsync += ((MAXVPOS_PAL * MAXHPOS_PAL * 50 * 256) / (maxhpos * (currprefs.cs_ciaatod == 2 ? 60 : 50))); } + } else if (currprefs.cs_ciaatod == 0 && isvsync) { + CIA_vsync_posthandler (ciasyncs); } -#ifdef PICASSO96 - picasso_handle_hsync (); -#endif - { - void ahi_hsync (void); - ahi_hsync (); + if (vpos == equ_vblank_endline + 1 && lof_current != lof_store) { + // argh, line=0 field decision was wrong, someone did + // something stupid and changed LOF + // lof_current = lof_store; + // don't really know what to do here exactly without corrupt display } + inputdevice_hsync (); + last_custom_value1 = 0xffff; // refresh slots should set this to 0xffff if (!nocustom ()) { @@ -5475,17 +5550,9 @@ static void hsync_handler (void) cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)], cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)]); } - hardware_line_completed (next_lineno); - if (doflickerfix () && interlace_seen) - hsync_scandoubler (); } - /* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */ - vpos++; - vpos_count++; - if (vpos >= maxvpos_total) - vpos = 0; - if (vpos == maxvpos + lof_store || vpos == maxvpos + lof_store + 1 || vpos_count >= MAXVPOS) { + if (isvsync) { // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely if ((bplcon0 & 8) && !lightpen_triggered) { vpos_lpen = vpos - 1; @@ -5493,26 +5560,8 @@ static void hsync_handler (void) lightpen_triggered = 1; } vpos = 0; - vsync_handler (); + vsync_handler_post (); vpos_count = 0; -#if 0 - if (input_recording > 0) { - inprec_rstart (INPREC_VSYNC); - inprec_ru32 (vsync_counter); - inprec_rend (); - } else if (input_recording < 0) { - uae_u32 v = -1; - while (inprec_pstart(INPREC_VSYNC)) { - v = inprec_pu32(); - inprec_pend(); - } - if (v != vsync_counter) - write_log (L"INPREC: vsync sync error %d <> %d\n", v, vsync_counter); - } -#endif - vsync_counter++; - if (currprefs.cs_ciaatod == 0) - CIA_vsync_prehandler (!(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock)); } // DIP Agnus (8361): vblank interrupt is triggered on line 1! if (currprefs.cs_dipagnus) { @@ -5550,9 +5599,6 @@ static void hsync_handler (void) #endif - if (currprefs.produce_sound) - audio_hsync (); - events_dmal_hsync (); #ifdef JIT @@ -5630,27 +5676,9 @@ static void hsync_handler (void) do_sprites (0); #endif - while (input_recording < 0 && inprec_pstart (INPREC_KEY)) { - record_key_direct (inprec_pu8 ()); - inprec_pend (); - } - while (input_recording < 0 && inprec_pstart (INPREC_DISKREMOVE)) { - disk_eject (inprec_pu8 ()); - inprec_pend (); - } - while (input_recording < 0 && inprec_pstart (INPREC_DISKINSERT)) { - int drv = inprec_pu8 (); - inprec_pstr (currprefs.floppyslots[drv].df); - _tcscpy (changed_prefs.floppyslots[drv].df, currprefs.floppyslots[drv].df); - disk_insert_force (drv, currprefs.floppyslots[drv].df); - inprec_pend (); - } - - inputdevice_hsync (); gayle_hsync (); scsi_hsync (); - hsync_counter++; //copper_check (2); if (GET_PLANES (bplcon0) > 0 && dmaen (DMA_BITPLANE)) { @@ -5658,7 +5686,7 @@ static void hsync_handler (void) last_planes_vpos = vpos; if (vpos >= minfirstline && first_planes_vpos == 0) { first_planes_vpos = vpos; - } else if (vpos == maxvpos - 1) { + } else if (vpos == current_maxvpos () - 1) { last_planes_vpos = vpos - 1; } } @@ -5706,6 +5734,20 @@ static void hsync_handler (void) #endif } +static void hsync_handler (void) +{ + bool vs = is_vsync (); + hsync_handler_pre (vs); + if (vs) { + vsync_handler_pre (); + if (savestate_check ()) { + uae_reset (0); + return; + } + } + hsync_handler_post (vs); +} + void event2_remevent (int no) { eventtab2[no].active = 0; @@ -5716,10 +5758,9 @@ void init_eventtab (void) int i; nextevent = 0; - set_cycles (0); for (i = 0; i < ev_max; i++) { eventtab[i].active = 0; - eventtab[i].oldcycles = 0; + eventtab[i].oldcycles = get_cycles (); } for (i = 0; i < ev2_max; i++) { eventtab2[i].active = 0; @@ -5738,7 +5779,13 @@ void init_eventtab (void) events_schedule (); } -void customreset (int hardreset) +void custom_prepare (void) +{ + set_hpos (); + hsync_handler_post (true); +} + +void custom_reset (int hardreset) { int i; int zero = 0; @@ -5748,13 +5795,13 @@ void customreset (int hardreset) write_log (L"Reset at %08X\n", M68K_GETPC); memory_map_dump (); - hsync_counter = 0; - vsync_counter = 0; - ciavsync_counter = 0; lightpen_x = lightpen_y = -1; lightpen_triggered = 0; lightpen_cx = lightpen_cy = -1; if (!savestate_state) { + extra_cycle = 0; + hsync_counter = 0; + vsync_counter = 0; currprefs.chipset_mask = changed_prefs.chipset_mask; update_mirrors (); if (!aga_mode) { @@ -5797,6 +5844,8 @@ void customreset (int hardreset) setup_fmodes (0); sprite_width = GET_SPRITEWIDTH (fmode); beamcon0 = new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; + bltstate = BLT_done; + lof_store = lof_current = 1; } gayle_reset (hardreset); @@ -5833,17 +5882,15 @@ void customreset (int hardreset) memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels); memset (&spixstate, 0, sizeof spixstate); - bltstate = BLT_done; cop_state.state = COP_stop; diwstate = DIW_waiting_start; - set_cycles (0); dmal = 0; init_hz (); vpos_lpen = -1; audio_reset (); - if (savestate_state != STATE_RESTORE) { + if (!isrestore ()) { /* must be called after audio_reset */ adkcon = 0; serial_uartbreak (0); @@ -5859,7 +5906,7 @@ void customreset (int hardreset) bogusframe = 1; - if (savestate_state == STATE_RESTORE) { + if (isrestore ()) { uae_u16 v; uae_u32 vv; @@ -6166,10 +6213,13 @@ static uae_u32 REGPARAM2 custom_wget (uaecptr addr) static uae_u32 REGPARAM2 custom_bget (uaecptr addr) { + uae_u32 v; #ifdef JIT special_mem |= S_READ; #endif - return custom_wget2 (addr & ~1) >> (addr & 1 ? 0 : 8); + v = custom_wget2 (addr & ~1); + v >>= (addr & 1 ? 0 : 8); + return v; } static uae_u32 REGPARAM2 custom_lget (uaecptr addr) @@ -6486,8 +6536,8 @@ uae_u8 *restore_custom (uae_u8 *src) RW; /* 004 VPOSR */ RW; /* 006 VHPOSR */ RW; /* 008 DSKDATR (dummy register) */ - RW; /* 00A JOY0DAT */ - RW; /* 00C JOY1DAT */ + JOYSET(0, RW); /* 00A JOY0DAT */ + JOYSET(1, RW); /* 00C JOY1DAT */ clxdat = RW; /* 00E CLXDAT */ RW; /* 010 ADKCONR */ RW; /* 012 POT0DAT* */ @@ -6639,100 +6689,100 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full) dstbak = dst = xmalloc (uae_u8, 8 + 256 * 2); SL (currprefs.chipset_mask); - SW (0); /* 000 BLTDDAT */ - SW (dmacon); /* 002 DMACONR */ - SW (VPOSR ()); /* 004 VPOSR */ - SW (VHPOSR ()); /* 006 VHPOSR */ - SW (0); /* 008 DSKDATR */ - SW (JOY0DAT ()); /* 00A JOY0DAT */ - SW (JOY1DAT ()); /* 00C JOY1DAT */ + SW (0); /* 000 BLTDDAT */ + SW (dmacon); /* 002 DMACONR */ + SW (VPOSR ()); /* 004 VPOSR */ + SW (VHPOSR ()); /* 006 VHPOSR */ + SW (0); /* 008 DSKDATR */ + SW (JOYGET (0)); /* 00A JOY0DAT */ + SW (JOYGET (1)); /* 00C JOY1DAT */ SW (clxdat | 0x8000); /* 00E CLXDAT */ SW (ADKCONR ()); /* 010 ADKCONR */ SW (POT0DAT ()); /* 012 POT0DAT */ - SW (POT0DAT ()); /* 014 POT1DAT */ - SW (0) ; /* 016 POTINP * */ - SW (0); /* 018 SERDATR * */ - SW (dskbytr); /* 01A DSKBYTR */ + SW (POT1DAT ()); /* 014 POT1DAT */ + SW (0) ; /* 016 POTINP * */ + SW (0); /* 018 SERDATR * */ + SW (dskbytr); /* 01A DSKBYTR */ SW (INTENAR ()); /* 01C INTENAR */ SW (INTREQR ()); /* 01E INTREQR */ - SL (dskpt); /* 020-023 DSKPT */ - SW (dsklen); /* 024 DSKLEN */ - SW (0); /* 026 DSKDAT */ - SW (0); /* 028 REFPTR */ + SL (dskpt); /* 020-023 DSKPT */ + SW (dsklen); /* 024 DSKLEN */ + SW (0); /* 026 DSKDAT */ + SW (0); /* 028 REFPTR */ SW ((lof_store ? 0x8001 : 0) | (lol ? 0x0080 : 0));/* 02A VPOSW */ - SW (0); /* 02C VHPOSW */ - SW (copcon); /* 02E COPCON */ - SW (serper); /* 030 SERDAT * */ - SW (serdat); /* 032 SERPER * */ + SW (0); /* 02C VHPOSW */ + SW (copcon); /* 02E COPCON */ + SW (serper); /* 030 SERDAT * */ + SW (serdat); /* 032 SERPER * */ SW (potgo_value); /* 034 POTGO */ - SW (0); /* 036 JOYTEST * */ - SW (0); /* 038 STREQU */ - SW (0); /* 03A STRVBL */ - SW (0); /* 03C STRHOR */ - SW (0); /* 03E STRLONG */ - SW (bltcon0); /* 040 BLTCON0 */ - SW (bltcon1); /* 042 BLTCON1 */ + SW (0); /* 036 JOYTEST * */ + SW (0); /* 038 STREQU */ + SW (0); /* 03A STRVBL */ + SW (0); /* 03C STRHOR */ + SW (0); /* 03E STRLONG */ + SW (bltcon0); /* 040 BLTCON0 */ + SW (bltcon1); /* 042 BLTCON1 */ SW (blt_info.bltafwm); /* 044 BLTAFWM */ SW (blt_info.bltalwm); /* 046 BLTALWM */ - SL (bltcpt); /* 048-04B BLTCPT */ - SL (bltbpt); /* 04C-04F BLTCPT */ - SL (bltapt); /* 050-053 BLTCPT */ - SL (bltdpt); /* 054-057 BLTCPT */ - SW (0); /* 058 BLTSIZE */ - SW (0); /* 05A BLTCON0L (use BLTCON0 instead) */ - SW (blt_info.vblitsize); /* 05C BLTSIZV */ - SW (blt_info.hblitsize); /* 05E BLTSIZH */ + SL (bltcpt); /* 048-04B BLTCPT */ + SL (bltbpt); /* 04C-04F BLTCPT */ + SL (bltapt); /* 050-053 BLTCPT */ + SL (bltdpt); /* 054-057 BLTCPT */ + SW (0); /* 058 BLTSIZE */ + SW (0); /* 05A BLTCON0L (use BLTCON0 instead) */ + SW (blt_info.vblitsize);/* 05C BLTSIZV */ + SW (blt_info.hblitsize);/* 05E BLTSIZH */ SW (blt_info.bltcmod); /* 060 BLTCMOD */ SW (blt_info.bltbmod); /* 062 BLTBMOD */ SW (blt_info.bltamod); /* 064 BLTAMOD */ SW (blt_info.bltdmod); /* 066 BLTDMOD */ - SW (0); /* 068 ? */ - SW (0); /* 06A ? */ - SW (0); /* 06C ? */ - SW (0); /* 06E ? */ + SW (0); /* 068 ? */ + SW (0); /* 06A ? */ + SW (0); /* 06C ? */ + SW (0); /* 06E ? */ SW (blt_info.bltcdat); /* 070 BLTCDAT */ SW (blt_info.bltbdat); /* 072 BLTBDAT */ SW (blt_info.bltadat); /* 074 BLTADAT */ - SW (0); /* 076 ? */ - SW (0); /* 078 ? */ - SW (0); /* 07A ? */ + SW (0); /* 076 ? */ + SW (0); /* 078 ? */ + SW (0); /* 07A ? */ SW (DENISEID ()); /* 07C DENISEID/LISAID */ - SW (dsksync); /* 07E DSKSYNC */ - SL (cop1lc); /* 080-083 COP1LC */ - SL (cop2lc); /* 084-087 COP2LC */ - SW (0); /* 088 ? */ - SW (0); /* 08A ? */ - SW (0); /* 08C ? */ - SW (diwstrt); /* 08E DIWSTRT */ - SW (diwstop); /* 090 DIWSTOP */ - SW (ddfstrt); /* 092 DDFSTRT */ - SW (ddfstop); /* 094 DDFSTOP */ - SW (dmacon); /* 096 DMACON */ - SW (clxcon); /* 098 CLXCON */ - SW (intena); /* 09A INTENA */ - SW (intreq); /* 09C INTREQ */ - SW (adkcon); /* 09E ADKCON */ + SW (dsksync); /* 07E DSKSYNC */ + SL (cop1lc); /* 080-083 COP1LC */ + SL (cop2lc); /* 084-087 COP2LC */ + SW (0); /* 088 ? */ + SW (0); /* 08A ? */ + SW (0); /* 08C ? */ + SW (diwstrt); /* 08E DIWSTRT */ + SW (diwstop); /* 090 DIWSTOP */ + SW (ddfstrt); /* 092 DDFSTRT */ + SW (ddfstop); /* 094 DDFSTOP */ + SW (dmacon); /* 096 DMACON */ + SW (clxcon); /* 098 CLXCON */ + SW (intena); /* 09A INTENA */ + SW (intreq); /* 09C INTREQ */ + SW (adkcon); /* 09E ADKCON */ for (i = 0; full && i < 32; i++) SW (0); for (i = 0; i < 8; i++) SL (bplpt[i]); /* 0E0-0FE BPLxPT */ - SW (bplcon0); /* 100 BPLCON0 */ - SW (bplcon1); /* 102 BPLCON1 */ - SW (bplcon2); /* 104 BPLCON2 */ - SW (bplcon3); /* 106 BPLCON3 */ - SW (bpl1mod); /* 108 BPL1MOD */ - SW (bpl2mod); /* 10A BPL2MOD */ - SW (bplcon4); /* 10C BPLCON4 */ - SW (clxcon2); /* 10E CLXCON2 */ + SW (bplcon0); /* 100 BPLCON0 */ + SW (bplcon1); /* 102 BPLCON1 */ + SW (bplcon2); /* 104 BPLCON2 */ + SW (bplcon3); /* 106 BPLCON3 */ + SW (bpl1mod); /* 108 BPL1MOD */ + SW (bpl2mod); /* 10A BPL2MOD */ + SW (bplcon4); /* 10C BPLCON4 */ + SW (clxcon2); /* 10E CLXCON2 */ for (i = 0;i < 8; i++) SW (bplxdat[i]); /* 110 BPLxDAT */ if (full) { for (i = 0; i < 8; i++) { - SL (spr[i].pt); /* 120-13E SPRxPT */ - SW (sprpos[i]); /* 1x0 SPRxPOS */ - SW (sprctl[i]); /* 1x2 SPRxPOS */ - SW (sprdata[i][0]); /* 1x4 SPRxDATA */ - SW (sprdatb[i][0]); /* 1x6 SPRxDATB */ + SL (spr[i].pt); /* 120-13E SPRxPT */ + SW (sprpos[i]); /* 1x0 SPRxPOS */ + SW (sprctl[i]); /* 1x2 SPRxPOS */ + SW (sprdata[i][0]); /* 1x4 SPRxDATA */ + SW (sprdatb[i][0]); /* 1x6 SPRxDATB */ } } for ( i = 0; i < 32; i++) { @@ -6845,7 +6895,7 @@ uae_u8 *restore_custom_sprite (int num, uae_u8 *src) return src; } -uae_u8 *save_custom_sprite(int num, int *len, uae_u8 *dstptr) +uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; @@ -6871,9 +6921,11 @@ uae_u8 *save_custom_sprite(int num, int *len, uae_u8 *dstptr) uae_u8 *restore_custom_extra (uae_u8 *src) { - restore_u32 (); + uae_u32 v = restore_u32 (); - currprefs.cs_compatible = changed_prefs.cs_compatible = 0; + if (!(v & 1)) + v = 0; + currprefs.cs_compatible = changed_prefs.cs_compatible = v >> 24; currprefs.genlock = changed_prefs.genlock = RBB; currprefs.cs_rtc = changed_prefs.cs_rtc = RB; @@ -6925,7 +6977,7 @@ uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr) else dstbak = dst = xmalloc (uae_u8, 1000); - SL (0); + SL ((currprefs.cs_compatible << 24) | 1); SB (currprefs.genlock ? 1 : 0); SB (currprefs.cs_rtc); SL (currprefs.cs_rtc_adjust); @@ -6968,6 +7020,83 @@ uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr) return dstbak; } +uae_u8 *restore_custom_event_delay (uae_u8 *src) +{ + if (restore_u32 () != 1) + return src; + int cnt = restore_u8 (); + for (int i = 0; i < cnt; i++) { + uae_u8 type = restore_u8 (); + evt e = restore_u64 (); + uae_u32 data = restore_u32 (); + if (type == 1) + event2_newevent_xx (-1, e, data, send_interrupt_do); + } + return src; +} +uae_u8 *save_custom_event_delay (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + int cnt = 0; + + for (int i = ev2_misc; i < ev2_max; i++) { + struct ev2 *e = &eventtab2[i]; + if (e->active && e->handler == send_interrupt_do) { + cnt++; + } + } + if (cnt == 0) + return NULL; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + + save_u32 (1); + save_u8 (cnt); + for (int i = ev2_misc; i < ev2_max; i++) { + struct ev2 *e = &eventtab2[i]; + if (e->active && e->handler == send_interrupt_do) { + save_u8 (1); + save_u64 (e->evtime - get_cycles ()); + save_u32 (e->data); + + } + } + + *len = dst - dstbak; + return dstbak; +} + + +uae_u8 *save_cycles (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + save_u32 (1); + save_u32 (CYCLE_UNIT); + save_u64 (get_cycles ()); + save_u32 (extra_cycle); + write_log (L"SAVECYCLES %08X\n", get_cycles ()); + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_cycles (uae_u8 *src) +{ + if (restore_u32 () != 1) + return src; + restore_u32 (); + start_cycles = restore_u64 (); + extra_cycle = restore_u32 (); + write_log (L"RESTORECYCLES %08X\n", start_cycles); + return src; +} + #endif /* SAVESTATE */ void check_prefs_changed_custom (void) @@ -7032,7 +7161,7 @@ STATIC_INLINE void sync_copper (int hpos) STATIC_INLINE void decide_fetch_ce (int hpos) { - if ((ddf_change == vpos || ddf_change + 1 == vpos) && vpos < maxvpos) + if ((ddf_change == vpos || ddf_change + 1 == vpos) && vpos < current_maxvpos ()) decide_fetch (hpos); } @@ -7042,10 +7171,13 @@ STATIC_INLINE void decide_fetch_ce (int hpos) // at least 4 cycles (all DMA cycles count, not just blitter cycles, even // blitter idle cycles do count!) +extern int cpu_tracer; STATIC_INLINE int dma_cycle (void) { int hpos, hpos_old; + if (cpu_tracer < 0) + return current_hpos (); blitter_nasty = 1; for (;;) { int bpldma; @@ -7089,7 +7221,7 @@ uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) struct dma_rec *dr; hpos = dma_cycle (); - do_cycles_ce (CYCLE_UNIT); + x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER if (debug_dma) { @@ -7116,7 +7248,7 @@ uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) dr->dat = v; #endif - do_cycles_ce (CYCLE_UNIT); + x_do_cycles_post (CYCLE_UNIT, v); return v; } @@ -7127,7 +7259,7 @@ uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode) struct dma_rec *dr; hpos = dma_cycle (); - do_cycles_ce (CYCLE_UNIT); + x_do_cycles (CYCLE_UNIT); #ifdef DEBUGGER if (debug_dma) { @@ -7163,7 +7295,7 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) int hpos; hpos = dma_cycle (); - do_cycles_ce (CYCLE_UNIT); + x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER if (debug_dma) { @@ -7185,7 +7317,7 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) put_word (addr, v); else if (mode == 0) put_byte (addr, v); - do_cycles_ce (CYCLE_UNIT); + x_do_cycles_post (CYCLE_UNIT, v); } @@ -7194,7 +7326,7 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) int hpos; hpos = dma_cycle (); - do_cycles_ce (CYCLE_UNIT); + x_do_cycles (CYCLE_UNIT); #ifdef DEBUGGER if (debug_dma) { @@ -7220,12 +7352,12 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) regs.ce020memcycles -= CYCLE_UNIT; } -void do_cycles_ce (long cycles) +void do_cycles_ce (unsigned long cycles) { - static int extra_cycle; + unsigned long c; - cycles += extra_cycle; - while (cycles >= CYCLE_UNIT) { + c = cycles + extra_cycle; + while (c >= CYCLE_UNIT) { int hpos = current_hpos () + 1; sync_copper (hpos); decide_line (hpos); @@ -7233,9 +7365,9 @@ void do_cycles_ce (long cycles) if (bltstate != BLT_done) decide_blitter (hpos); do_cycles (1 * CYCLE_UNIT); - cycles -= CYCLE_UNIT; + c -= CYCLE_UNIT; } - extra_cycle = cycles; + extra_cycle = c; } int is_cycle_ce (void) diff --git a/debug.cpp b/debug.cpp index cbb05e57..0053316c 100644 --- a/debug.cpp +++ b/debug.cpp @@ -900,7 +900,7 @@ struct dma_rec *record_dma (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos, in static void decode_dma_record (int hpos, int vpos, int toggle) { struct dma_rec *dr; - int h, i, maxh; + int h, i, maxh, cnt; if (!dma_record[0]) return; @@ -911,6 +911,7 @@ static void decode_dma_record (int hpos, int vpos, int toggle) maxh = hpos + 80; if (maxh > maxhpos) maxh = maxhpos; + cnt = 0; while (h < maxh) { int col = 9; int cols = 8; @@ -918,6 +919,7 @@ static void decode_dma_record (int hpos, int vpos, int toggle) TCHAR l2[81]; TCHAR l3[81]; TCHAR l4[81]; + TCHAR l5[81]; for (i = 0; i < cols && h < maxh; i++, h++, dr++) { int cl = i * col, cl2; int r = dr->reg; @@ -975,17 +977,21 @@ static void decode_dma_record (int hpos, int vpos, int toggle) l3[cl2++] = 'I'; if (dr->evt & DMA_EVENT_INTREQ) l3[cl2++] = 'i'; + _stprintf (l5 + cl, L"%08X", vsync_cycles + (vpos * maxhpos + (hpos + cnt)) * CYCLE_UNIT); if (i < cols - 1 && h < maxh - 1) { l1[cl + col - 1] = 32; l2[cl + col - 1] = 32; l3[cl + col - 1] = 32; l4[cl + col - 1] = 32; + l5[cl + col - 1] = 32; } + cnt++; } console_out_f (L"%s\n", l1); console_out_f (L"%s\n", l2); console_out_f (L"%s\n", l3); console_out_f (L"%s\n", l4); + console_out_f (L"%s\n", l5); console_out_f (L"\n"); } } @@ -1642,6 +1648,71 @@ static void smc_detector (uaecptr addr, int rwi, int size, uae_u32 *valp) } } +uae_u8 *save_debug_memwatch (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + int total; + + total = 0; + for (int i = 0; i < MEMWATCH_TOTAL; i++) { + if (mwnodes[i].size > 0) + total++; + } + if (!total) + return NULL; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + save_u32 (1); + save_u8 (total); + for (int i = 0; i < MEMWATCH_TOTAL; i++) { + struct memwatch_node *m = &mwnodes[i]; + if (m->size <= 0) + continue; + save_store_pos (); + save_u8 (i); + save_u8 (m->modval_written); + save_u8 (m->mustchange); + save_u8 (m->frozen); + save_u8 (m->val_enabled); + save_u8 (m->rwi); + save_u32 (m->addr); + save_u32 (m->size); + save_u32 (m->modval); + save_u32 (m->val_mask); + save_u32 (m->val_size); + save_store_size (); + } + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_debug_memwatch (uae_u8 *src) +{ + if (restore_u32 () != 1) + return src; + int total = restore_u8 (); + for (int i = 0; i < total; i++) { + restore_store_pos (); + int idx = restore_u8 (); + struct memwatch_node *m = &mwnodes[idx]; + m->modval_written = restore_u8 (); + m->mustchange = restore_u8 (); + m->frozen = restore_u8 (); + m->val_enabled = restore_u8 (); + m->rwi = restore_u8 (); + m->addr = restore_u32 (); + m->size = restore_u32 (); + m->modval = restore_u32 (); + m->val_mask = restore_u32 (); + m->val_size = restore_u32 (); + restore_store_size (); + } + return src; +} + static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp) { int i, brk; @@ -2650,6 +2721,7 @@ static void searchmem (TCHAR **cc) static int staterecorder (TCHAR **cc) { +#if 0 TCHAR nc; if (!more_params (cc)) { @@ -2664,6 +2736,7 @@ static int staterecorder (TCHAR **cc) savestate_listrewind (); return 0; } +#endif return 0; } @@ -2970,7 +3043,7 @@ static void m68k_modify (TCHAR **inptr) regs.isp = v; } else if (!_tcscmp (parm, L"PC")) { m68k_setpc (v); - fill_prefetch_slow (); + fill_prefetch (); } else { for (i = 0; m2cregs[i].regname; i++) { if (!_tcscmp (parm, m2cregs[i].regname)) @@ -3148,7 +3221,7 @@ static void debug_1 (void) case 'g': if (more_params (&inptr)) { m68k_setpc (readhex (&inptr)); - fill_prefetch_slow (); + fill_prefetch (); } deactivate_debugger(); return; @@ -3292,19 +3365,19 @@ static void debug_1 (void) break; case 'U': if (currprefs.cpu_model && more_params (&inptr)) { - int super, data, i; + int i; uaecptr addrl = readhex (&inptr); uaecptr addrp; console_out_f (L"%08X translates to:\n", addrl); for (i = 0; i < 4; i++) { - super = (i & 2) ? 1 : 0; - data = (i & 1) ? 1 : 0; + bool super = (i & 2) != 0; + bool data = (i & 1) != 0; console_out_f (L"S%dD%d=", super, data); TRY(prb) { - addrp = mmu_translate (addrl, super, data, 0); + addrp = mmu_translate (addrl, super, data, false); console_out_f (L"%08X", addrp); TRY(prb2) { - addrp = mmu_translate (addrl, super, data, 1); + addrp = mmu_translate (addrl, super, data, true); console_out_f (L" RW"); } CATCH(prb2) { console_out_f (L" RO"); @@ -3576,7 +3649,7 @@ void mmu_do_hit (void) } MakeSR (); m68k_setpc (mmu_callback); - fill_prefetch_slow (); + fill_prefetch (); if (currprefs.cpu_model > 68000) { for (i = 0 ; i < 9; i++) { diff --git a/disk.cpp b/disk.cpp index d4c2830a..a552b2e8 100644 --- a/disk.cpp +++ b/disk.cpp @@ -14,6 +14,10 @@ #include "sysconfig.h" #include "sysdeps.h" +int disk_debug_logging = 0; +int disk_debug_mode = 0; +int disk_debug_track = -1; + #include "uae.h" #include "options.h" #include "memory.h" @@ -38,7 +42,7 @@ #include "caps/caps_win32.h" #endif #include "crc32.h" -#include "inputdevice.h" +#include "inputrecord.h" #include "amax.h" #ifdef RETROPLATFORM #include "rp.h" @@ -88,8 +92,8 @@ static uae_u8 writebuffer[544 * MAX_SECTORS]; #define DISK_WORDSYNC 2 #define DISK_REVOLUTION 4 /* 8,16,32,64 */ -#define DSKREADY_TIME 4 -#define DSKREADY_DOWN_TIME 10 +#define DSKREADY_UP_TIME 20 +#define DSKREADY_DOWN_TIME 50 static int dskdmaen, dsklength, dsklength2, dsklen; static uae_u16 dskbytr_val; @@ -102,9 +106,12 @@ static uae_u16 word, dsksync; static unsigned long dsksync_cycles; #define WORDSYNC_TIME 11 /* Always carried through to the next line. */ -static int disk_hpos; +int disk_hpos; static int disk_jitter; +static uae_u8 prev_data; +static int prev_step; + typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS, TRACK_DISKSPARE, TRACK_NONE } image_tracktype; typedef struct { uae_u16 len; @@ -155,13 +162,12 @@ typedef struct { int revolutions; int prevtracklen; int trackspeed; - int dmalen; int num_tracks, write_num_tracks, num_secs; int hard_num_cyls; bool dskchange; int dskchange_time; bool dskready; - int dskready_time; + int dskready_up_time; int dskready_down_time; int writtento; int steplimit; @@ -186,10 +192,6 @@ typedef struct { #endif } drive; -int disk_debug_logging; -int disk_debug_mode; -int disk_debug_track = -1; - #define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 250) static uae_u16 bigmfmbufw[0x4000 * DDHDMULT]; @@ -576,7 +578,7 @@ static void drive_image_free (drive *drv) drv->writediskfile = 0; } -static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname); +static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake); static void reset_drive_gui (int num) { @@ -614,6 +616,9 @@ static void reset_drive (int num) drv->amax = 0; drive_image_free (drv); drv->motoroff = 1; + drv->idbit = 0; + drv->drive_id = 0; + drv->drive_id_scnt = 0; disabled &= ~(1 << num); if (currprefs.floppyslots[num].dfxtype < 0) disabled |= 1 << num; @@ -626,13 +631,16 @@ static void reset_drive (int num) if (num == 0 && currprefs.floppyslots[num].dfxtype == 0) drv->indexhackmode = 1; drv->dskchange_time = 0; + drv->dskchange = 0; + drv->dskready_down_time = 0; + drv->dskready_up_time = 0; drv->buffered_cyl = -1; drv->buffered_side = -1; gui_led (num + LED_DF0, 0); drive_settype_id (drv); _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df); drv->newname[0] = 0; - if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df)) + if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df, false)) disk_eject (num); } @@ -666,7 +674,7 @@ int DISK_validate_filename (const TCHAR *fname, int leave_open, bool *wrprot, ua *zf = NULL; if (crc32) *crc32 = 0; - if (leave_open) { + if (leave_open || !zf) { struct zfile *f = zfile_fopen (fname, L"r+b", ZFD_NORMAL | ZFD_DISKHISTORY); if (f) { if (wrprot) @@ -875,7 +883,7 @@ static bool diskfile_iswriteprotect (const TCHAR *fname, int *needwritefile, dri return wrprot1; } -static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname) +static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake) { uae_u8 buffer[2 + 2 + 4 + 4]; trackid *tid; @@ -902,7 +910,7 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR } if (!drv->motoroff) { - drv->dskready_time = DSKREADY_TIME; + drv->dskready_up_time = DSKREADY_UP_TIME; drv->dskready_down_time = 0; } @@ -911,12 +919,8 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR return 0; } - if (input_recording > 0) { - inprec_rstart (INPREC_DISKINSERT); - inprec_ru8 (dnum); - inprec_rstr (fname); - inprec_rend (); - } + if (!fake) + inprec_recorddiskchange (dnum, fname, drv->wrprot); _tcsncpy (currprefs.floppyslots[dnum].df, fname, 255); currprefs.floppyslots[dnum].df[255] = 0; @@ -1246,7 +1250,7 @@ static void motordelay_func (uae_u32 v) static void drive_motor (drive * drv, bool off) { if (drv->motoroff && !off) { - drv->dskready_time = DSKREADY_TIME; + drv->dskready_up_time = DSKREADY_UP_TIME; rand_shifter (drv); #ifdef DRIVESOUND driveclick_motor (drv - floppy, drv->dskready_down_time == 0 ? 2 : 1); @@ -1273,7 +1277,9 @@ static void drive_motor (drive * drv, bool off) drv->motoroff = off; if (drv->motoroff) { drv->dskready = 0; - drv->dskready_time = 0; + drv->dskready_up_time = 0; + } else { + drv->dskready_down_time = 0; } #ifdef CATWEASEL if (drv->catweasel) @@ -2019,17 +2025,13 @@ static void drive_eject (drive * drv) drv->ddhd = 1; drv->dskchange_time = 0; drv->dskready = 0; - drv->dskready_time = 0; + drv->dskready_up_time = 0; drv->dskready_down_time = 0; drv->crc32 = 0; drive_settype_id (drv); /* Back to 35 DD */ if (disk_debug_logging > 0) write_log (L"eject drive %d\n", drv - &floppy[0]); - if (input_recording > 0) { - inprec_rstart (INPREC_DISKREMOVE); - inprec_ru8 (drv - floppy); - inprec_rend (); - } + inprec_recorddiskchange (drv - floppy, NULL, false); } /* We use this function if we have no Kickstart ROM. @@ -2192,8 +2194,8 @@ static void setdskchangetime (drive *drv, int dsktime) if (drv->dskchange_time > 0) return; for (i = 0; i < MAX_FLOPPY_DRIVES; i++) { - if (&floppy[i] != drv && floppy[i].dskchange_time > 0 && floppy[i].dskchange_time + 5 >= dsktime) { - dsktime = floppy[i].dskchange_time + 5; + if (&floppy[i] != drv && floppy[i].dskchange_time > 0 && floppy[i].dskchange_time + 1 >= dsktime) { + dsktime = floppy[i].dskchange_time + 1; } } drv->dskchange_time = dsktime; @@ -2204,7 +2206,7 @@ static void setdskchangetime (drive *drv, int dsktime) void DISK_reinsert (int num) { drive_eject (&floppy[num]); - setdskchangetime (&floppy[num], 20); + setdskchangetime (&floppy[num], 100); } int disk_setwriteprotect (int num, const TCHAR *name, bool writeprotected) @@ -2320,7 +2322,7 @@ static void disk_insert_2 (int num, const TCHAR *name, int forced) drive *drv = floppy + num; if (forced) { - drive_insert (drv, &currprefs, num, name); + drive_insert (drv, &currprefs, num, name, false); return; } if (!_tcscmp (currprefs.floppyslots[num].df, name)) @@ -2336,7 +2338,7 @@ static void disk_insert_2 (int num, const TCHAR *name, int forced) * called from DISK_check_change() after 2 second delay * this makes sure that all programs detect disk change correctly */ - setdskchangetime (drv, 20); + setdskchangetime (drv, 100); } else { setdskchangetime (drv, 1); } @@ -2348,20 +2350,17 @@ void disk_insert (int num, const TCHAR *name) target_addtorecent (name, 0); disk_insert_2 (num, name, 0); } -void disk_insert_force (int num, const TCHAR *name) +void disk_insert_force (int num, const TCHAR *name, bool writeprotected) { disk_insert_2 (num, name, 1); } -void DISK_check_change (void) +static void DISK_check_change (void) { - int i; - if (currprefs.floppy_speed != changed_prefs.floppy_speed) currprefs.floppy_speed = changed_prefs.floppy_speed; - for (i = 0; i < MAX_FLOPPY_DRIVES; i++) { + for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) { drive *drv = floppy + i; - gui_lock (); if (currprefs.floppyslots[i].dfxtype != changed_prefs.floppyslots[i].dfxtype) { currprefs.floppyslots[i].dfxtype = changed_prefs.floppyslots[i].dfxtype; reset_drive (i); @@ -2369,22 +2368,29 @@ void DISK_check_change (void) rp_floppydrive_change (i, currprefs.floppyslots[i].dfxtype >= 0 ? 1 : 0); #endif } + } +} + +void DISK_vsync (void) +{ + DISK_check_change (); + for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) { + drive *drv = floppy + i; if (drv->dskchange_time == 0 && _tcscmp (currprefs.floppyslots[i].df, changed_prefs.floppyslots[i].df)) disk_insert (i, changed_prefs.floppyslots[i].df); - gui_unlock (); if (drv->dskready_down_time > 0) drv->dskready_down_time--; /* emulate drive motor turn on time */ - if (drv->dskready_time > 0 && !drive_empty(drv)) { - drv->dskready_time--; - if (drv->dskready_time == 0) - drv->dskready = 1; + if (drv->dskready_up_time > 0 && !drive_empty(drv)) { + drv->dskready_up_time--; + if (drv->dskready_up_time == 0 && !drv->motoroff) + drv->dskready = true; } /* delay until new disk image is inserted */ if (drv->dskchange_time) { drv->dskchange_time--; if (drv->dskchange_time == 0) { - drive_insert (drv, &currprefs, i, drv->newname); + drive_insert (drv, &currprefs, i, drv->newname, false); if (disk_debug_logging > 0) write_log (L"delayed insert, drive %d, image '%s'\n", i, drv->newname); update_drive_gui (i); @@ -2409,11 +2415,15 @@ static TCHAR *tobin (uae_u8 v) return buf; } +void DISK_select_set (uae_u8 data) +{ + prev_data = data; + prev_step = 0; +} + void DISK_select (uae_u8 data) { int step_pulse, prev_selected, dr; - static uae_u8 prev_data; - static int prev_step; prev_selected = selected; @@ -2590,18 +2600,21 @@ void dumpdisk (void) console_out_f (L"Drive %d: motor %s cylinder %2d sel %s %s mfmpos %d/%d\n", i, drv->motoroff ? L"off" : L" on", drv->cyl, (selected & (1 << i)) ? L"no" : L"yes", drive_writeprotected(drv) ? L"ro" : L"rw", drv->mfmpos, drv->tracklen); - w = word; - for (j = 0; j < 15; j++) { - console_out_f (L"%04X ", w); - for (k = 0; k < 16; k++) { - w <<= 1; - w |= getonebit (drv->bigmfmbuf, drv->mfmpos + j * 16 + k); + if (drv->motoroff == 0) { + w = word; + for (j = 0; j < 15; j++) { + console_out_f (L"%04X ", w); + for (k = 0; k < 16; k++) { + w <<= 1; + w |= getonebit (drv->bigmfmbuf, drv->mfmpos + j * 16 + k); + } } + console_out (L"\n"); } - console_out (L"\n"); } } - console_out_f (L"side %d, dma %d, bitoffset %d, word %04X, dskbytr %04X adkcon %04X dsksync %04X\n", side, dskdmaen, bitoffset, word, dskbytr_val, adkcon, dsksync); + console_out_f (L"side %d dma %d off %d word %04X pt %08X len %04X bytr %04X adk %04X sync %04X\n", + side, dskdmaen, bitoffset, word, dskpt, dsklen, dskbytr_val, adkcon, dsksync); } static void disk_dmafinished (void) @@ -2776,7 +2789,7 @@ static void disk_doupdate_predict (int startcycle) tword <<= 1; if (!drive_empty (drv)) { if (unformatted (drv)) - tword |= (uaerand() & 0x1000) ? 1 : 0; + tword |= (uaerand () & 0x1000) ? 1 : 0; else tword |= getonebit (drv->bigmfmbuf, mfmpos); } @@ -2857,7 +2870,7 @@ static void disk_doupdate_read_nothing (int floppybits) { int j = 0, k = 1, l = 0; - while (floppybits >= get_floppy_speed()) { + while (floppybits >= get_floppy_speed ()) { word <<= 1; doreaddma (); if ((bitoffset & 7) == 7) { @@ -2866,7 +2879,7 @@ static void disk_doupdate_read_nothing (int floppybits) } bitoffset++; bitoffset &= 15; - floppybits -= get_floppy_speed(); + floppybits -= get_floppy_speed (); } } @@ -2898,7 +2911,7 @@ static void disk_doupdate_read (drive * drv, int floppybits) word <<= 1; if (!drive_empty (drv)) { if (unformatted (drv)) - word |= (uaerand() & 0x1000) ? 1 : 0; + word |= (uaerand () & 0x1000) ? 1 : 0; else word |= getonebit (drv->bigmfmbuf, drv->mfmpos); } @@ -2933,6 +2946,7 @@ static void disk_doupdate_read (drive * drv, int floppybits) bitoffset++; bitoffset &= 15; floppybits -= drv->trackspeed; + } } @@ -2983,7 +2997,7 @@ static void DISK_start (void) int dr; for (int i = 0; i < 3; i++) - fifo_inuse[0] = 0; + fifo_inuse[i] = false; fifo_filled = 0; for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { drive *drv = &floppy[dr]; @@ -2999,8 +3013,10 @@ static void DISK_start (void) } /* Ugh. A nasty hack. Assume ADF_EXT1 tracks are always read from the start. */ - if (ti->type == TRACK_RAW1) + if (ti->type == TRACK_RAW1) { drv->mfmpos = 0; + bitoffset = 0; + } if (drv->catweasel) drive_fill_bigbuf (drv, 1); } @@ -3034,6 +3050,11 @@ void DISK_update (int tohpos) int cycles; int startcycle = disk_hpos; + if (disk_hpos < 0) { + disk_hpos = - disk_hpos; + return; + } + cycles = (tohpos << 8) - disk_hpos; #if 0 if (tohpos == 228) @@ -3074,6 +3095,7 @@ void DISK_update (int tohpos) disk_doupdate_write (drv, drv->floppybitcounter); else disk_doupdate_read (drv, drv->floppybitcounter); + drv->floppybitcounter %= drv->trackspeed; didaccess = 1; } @@ -3383,7 +3405,7 @@ void DISK_init (void) drive *drv = &floppy[dr]; /* reset all drive types to 3.5 DD */ drive_settype_id (drv); - if (!drive_insert (drv, &currprefs, dr, currprefs.floppyslots[dr].df)) + if (!drive_insert (drv, &currprefs, dr, currprefs.floppyslots[dr].df, false)) disk_eject (dr); } if (disk_empty (0)) @@ -3420,7 +3442,7 @@ int DISK_examine_image (struct uae_prefs *p, int num, uae_u32 *crc32) drv->cyl = 0; side = 0; *crc32 = 0; - if (!drive_insert (drv, p, num, p->floppyslots[num].df)) + if (!drive_insert (drv, p, num, p->floppyslots[num].df, true)) return 1; if (!drv->diskfile) return 1; @@ -3481,7 +3503,7 @@ void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, if (pdskpt) *pdskpt = dskpt; if (pdsklength) - *pdsklength = dsklength; + *pdsklength = dsklen; if (pdsksync) *pdsksync = dsksync; if (pdskbytr) @@ -3490,18 +3512,41 @@ void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, #endif /* SAVESTATE || DEBUGGER */ +static uae_u32 getadfcrc (drive *drv) +{ + uae_u8 *b; + uae_u32 crc32; + int size; + + if (!drv->diskfile) + return 0; + zfile_fseek (drv->diskfile, 0, SEEK_END); + size = zfile_ftell (drv->diskfile); + b = xmalloc (uae_u8, size); + if (!b) + return 0; + zfile_fseek (drv->diskfile, 0, SEEK_SET); + zfile_fread (b, 1, size, drv->diskfile); + crc32 = get_crc32 (b, size); + free (b); + return crc32; +} + #ifdef SAVESTATE void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskbytr) { dskpt = pdskpt; - dsklength = pdsklength; + dsklen = pdsklength; dskbytr_val = pdskbytr; } void restore_disk_finish (void) { - setamax(); + DISK_check_change (); + setamax (); + if (dskdmaen) + dumpdisk (); } uae_u8 *restore_disk (int num,uae_u8 *src) @@ -3542,6 +3587,8 @@ uae_u8 *restore_disk (int num,uae_u8 *src) } changed_prefs.floppyslots[num].dfxtype = dfxtype; } + drv->dskchange = (state & 8) ? 1 : 0; + side = (state & 16) ? 1 : 0; drv->indexhackmode = 0; if (num == 0 && currprefs.floppyslots[num].dfxtype == 0) drv->indexhackmode = 1; @@ -3550,8 +3597,7 @@ uae_u8 *restore_disk (int num,uae_u8 *src) drv->cyl = restore_u8 (); drv->dskready = restore_u8 () != 0; drv->drive_id_scnt = restore_u8 (); - drv->mfmpos = restore_u32 (); - drv->dskchange = 0; + int mfmpos = restore_u32 (); drv->dskchange_time = 0; restore_u32 (); s = restore_string (); @@ -3560,62 +3606,105 @@ uae_u8 *restore_disk (int num,uae_u8 *src) xfree (s); newis = changed_prefs.floppyslots[num].df[0] ? 1 : 0; if (!(disabled & (1 << num))) { - if (!newis) { - drv->dskchange = 1; - } else { - drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df); + if (!newis && old[0]) { + *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0; + drv->dskchange = 0; + } else if (newis) { + drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false); if (drive_empty (floppy + num)) { if (newis && old[0]) { _tcscpy (changed_prefs.floppyslots[num].df, old); - drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df); + drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false); if (drive_empty (floppy + num)) drv->dskchange = 1; } } } } + drv->mfmpos = mfmpos; + drv->prevtracklen = drv->tracklen; reset_drive_gui (num); return src; } -static uae_u32 getadfcrc (drive *drv) +uae_u8 *restore_disk2 (int num,uae_u8 *src) { - uae_u8 *b; - uae_u32 crc32; - int size; - - if (!drv->diskfile) - return 0; - zfile_fseek (drv->diskfile, 0, SEEK_END); - size = zfile_ftell (drv->diskfile); - b = xmalloc (uae_u8, size); - if (!b) - return 0; - zfile_fseek (drv->diskfile, 0, SEEK_SET); - zfile_fread (b, 1, size, drv->diskfile); - crc32 = get_crc32 (b, size); - free (b); - return crc32; + drive *drv = &floppy[num]; + uae_u32 m = restore_u32 (); + if (m) { + drv->floppybitcounter = restore_u16 (); + drv->tracklen = restore_u32 (); + drv->trackspeed = restore_u16 (); + drv->skipoffset = restore_u32 (); + drv->indexoffset = restore_u32 (); + drv->buffered_cyl = drv->cyl; + drv->buffered_side = side; + for (int j = 0; j < (drv->tracklen + 15) / 16; j++) { + drv->bigmfmbuf[j] = restore_u16 (); + if (m & 2) + drv->tracktiming[j] = restore_u16 (); + } + drv->dskready_up_time = restore_u16 (); + drv->dskready_down_time = restore_u16 (); + } + return src; } -uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr) +uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr, bool usepath) { uae_u8 *dstbak,*dst; - drive *drv; + drive *drv = &floppy[num]; - drv = &floppy[num]; if (dstptr) dstbak = dst = dstptr; else - dstbak = dst = xmalloc (uae_u8, 2+1+1+1+1+4+4+256); + dstbak = dst = xmalloc (uae_u8, 2 + 1 + 1 + 1 + 1 + 4 + 4 + 256); save_u32 (drv->drive_id); /* drive type ID */ - save_u8 ((drv->motoroff ? 0:1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0)); - save_u8 (drv->cyl); /* cylinder */ + save_u8 ((drv->motoroff ? 0 : 1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0) | (side ? 16 : 0)); + save_u8 (drv->cyl); /* cylinder */ save_u8 (drv->dskready); /* dskready */ save_u8 (drv->drive_id_scnt); /* id mode position */ - save_u32 (drv->mfmpos); /* disk position */ + save_u32 (drv->mfmpos); /* disk position */ save_u32 (getadfcrc (drv)); /* CRC of disk image */ - save_string (currprefs.floppyslots[num].df);/* image name */ + save_string (usepath ? currprefs.floppyslots[num].df : L"");/* image name */ + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *save_disk2 (int num, int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak,*dst; + drive *drv = &floppy[num]; + + int m = 0; + int size = 0; + if (drv->motoroff == 0 && drv->buffered_side >= 0 && drv->tracklen > 0) { + m = 1; + if (drv->tracktiming[0]) + m |= 2; + size += ((drv->tracklen + 15) * 2) / 8; + } + if (!m) + return NULL; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 2 + 4 + 2 + 4 + 4 + size); + + save_u32 (m); + save_u16 (drv->floppybitcounter); + save_u32 (drv->tracklen); + save_u16 (drv->trackspeed); + save_u32 (drv->skipoffset); + save_u32 (drv->indexoffset); + for (int j = 0; j < (drv->tracklen + 15) / 16; j++) { + save_u16 (drv->bigmfmbuf[j]); + if (drv->tracktiming[0]) + save_u16 (drv->tracktiming[j]); + } + save_u16 (drv->dskready_up_time); + save_u16 (drv->dskready_down_time); *len = dst - dstbak; return dstbak; @@ -3628,39 +3717,38 @@ uae_u8 *restore_floppy (uae_u8 *src) word = restore_u16 (); bitoffset = restore_u8 (); dma_enable = restore_u8 (); - disk_hpos = restore_u8 () << 8; + disk_hpos = restore_u8 () & 0xff; dskdmaen = restore_u8 (); for (int i = 0; i < 3; i++) { fifo[i] = restore_u16 (); - fifo_inuse[i] = restore_u8 () != 0; + fifo_inuse[i] = restore_u8 (); if (dskdmaen == 0) fifo_inuse[i] = false; } + fifo_filled = fifo_inuse[0] || fifo_inuse[1] || fifo_inuse[2]; + dsklength = restore_u16 (); return src; } -uae_u8 *save_floppy(int *len, uae_u8 *dstptr) +uae_u8 *save_floppy (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; - /* flush dma buffer before saving */ -#if 0 - dodmafetch(); -#endif if (dstptr) dstbak = dst = dstptr; else dstbak = dst = xmalloc (uae_u8, 100); + save_u16 (word); /* shift register */ save_u8 (bitoffset); /* dma bit offset */ save_u8 (dma_enable); /* disk sync found */ - save_u8 (disk_hpos >> 8); /* next bit read position */ + save_u8 (disk_hpos & 0xff); /* next bit read position */ save_u8 (dskdmaen); /* dma status */ for (int i = 0; i < 3; i++) { save_u16 (fifo[i]); - save_u8 (fifo_inuse[i] ? 1 : 0); + save_u8 (fifo_inuse[i]); } - + save_u16 (dsklength); *len = dst - dstbak; return dstbak; } @@ -3838,3 +3926,7 @@ int disk_prevnext (int drive, int dir) } +int getdebug(void) +{ + return floppy[0].mfmpos; +} \ No newline at end of file diff --git a/drawing.cpp b/drawing.cpp index ca65de57..d414cbb2 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -97,7 +97,7 @@ static int dblpf_ind1[256], dblpf_ind2[256]; static int dblpf_2nd1[256], dblpf_2nd2[256]; -static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; +static const int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; static int sprite_offs[256]; @@ -212,7 +212,7 @@ static int bplres; static int plf1pri, plf2pri, bplxor; static uae_u32 plf_sprite_mask; static int sbasecol[2] = { 16, 16 }; -static int brdsprt, brdblank, brdblank_changed, hposendblank; +static int brdsprt, brdblank, brdblank_changed, hposblank; bool picasso_requested_on; bool picasso_on; @@ -677,10 +677,10 @@ STATIC_INLINE uae_u32 merge_2pixel32 (uae_u32 p1, uae_u32 p2) STATIC_INLINE xcolnr getbgc (void) { #if 0 - if (hposendblank) + if (hposblank) return xcolors[0xf00]; #endif - return (brdblank || hposendblank) ? 0 : colors_for_drawing.acolors[0]; + return (brdblank || hposblank) ? 0 : colors_for_drawing.acolors[0]; } static void fill_line_16 (uae_u8 *buf, unsigned int start, unsigned int stop) @@ -773,11 +773,11 @@ STATIC_INLINE void fill_line2 (int startpos, int len) static void fill_line (void) { int hs = coord_hw_to_window_x (hsyncstartpos * 2); - if (hs > visible_left_border + gfxvidinfo.width || hposendblank) { + if (hs >= gfxvidinfo.width || hposblank) { fill_line2 (visible_left_border, gfxvidinfo.width); } else { fill_line2 (visible_left_border, hs); - hposendblank = 1; + hposblank = 1; fill_line2 (visible_left_border + hs, gfxvidinfo.width - hs); } } @@ -1811,8 +1811,8 @@ static void pfield_expand_dp_bplcon (void) ecsshres = bplres == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA); #endif - if (bplres > 0) - frame_res = 1; + if (bplres > frame_res) + frame_res = bplres; if (bplres > 0) can_use_lores = 0; @@ -1861,7 +1861,7 @@ static bool isham (uae_u16 bplcon0) static void pfield_expand_dp_bplconx (int regno, int v) { if (regno == 0xffff) { - hposendblank = 1; + hposblank = 1; return; } regno -= 0x1000; @@ -2146,11 +2146,11 @@ static void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos) } else { - int tmp = hposendblank; - hposendblank = 1; + int tmp = hposblank; + hposblank = 1; fill_line (); do_flush_line (gfx_ypos); - hposendblank = tmp; + hposblank = tmp; } } @@ -2187,7 +2187,7 @@ static void center_image (void) visible_left_border = max_diwlastword - gfxvidinfo.width; } - if (currprefs.gfx_xcenter_pos >= 0) { + if (currprefs.gfx_xcenter_pos >= 0 && !currprefs.gfx_filter_autoscale) { int val = currprefs.gfx_xcenter_pos >> RES_MAX; #if 0 if (currprefs.gfx_xcenter_size > 0) { @@ -2230,7 +2230,7 @@ static void center_image (void) thisframe_y_adjust = prev_y_adjust; } } - if (currprefs.gfx_ycenter_pos >= 0) { + if (currprefs.gfx_ycenter_pos >= 0 && !currprefs.gfx_filter_autoscale) { thisframe_y_adjust = currprefs.gfx_ycenter_pos >> 1; #if 0 if (currprefs.gfx_ycenter_size > 0) { @@ -2267,7 +2267,7 @@ static void center_image (void) min_diwstart = 10000; } -#define FRAMES_UNTIL_RES_SWITCH 5 +#define FRAMES_UNTIL_RES_SWITCH 1 static int frame_res_cnt; static void init_drawing_frame (void) { @@ -2275,44 +2275,45 @@ static void init_drawing_frame (void) #if 1 static int frame_res_old; - if (FRAMES_UNTIL_RES_SWITCH > 0 && frame_res_old == frame_res * 2 + frame_res_lace) { - frame_res_cnt--; - if (frame_res_cnt == 0) { - int ar = currprefs.gfx_autoresolution; - int m = frame_res * 2 + frame_res_lace; - struct wh *dst = currprefs.gfx_afullscreen ? &changed_prefs.gfx_size_fs : &changed_prefs.gfx_size_win; - while (m < 4) { - struct wh *src = currprefs.gfx_afullscreen ? &currprefs.gfx_size_fs_xtra[m] : &currprefs.gfx_size_win_xtra[m]; - if ((src->width > 0 && src->height > 0) || (ar && currprefs.gfx_filter > 0)) { - int nr = (m & 2) == 0 ? 0 : 1; - int nl = (m & 1) == 0 ? 0 : 1; - if (changed_prefs.gfx_resolution != nr || changed_prefs.gfx_vresolution != nl) { - changed_prefs.gfx_resolution = nr; - changed_prefs.gfx_vresolution = nl; - write_log (L"RES -> %d LINE -> %d\n", nr, nl); - config_changed = 1; - if (ar) { - changed_prefs.gfx_filter_horiz_zoom_mult = (nr + 1) * 500; - changed_prefs.gfx_filter_vert_zoom_mult = (nl + 1) * 500; - } - } - if (src->width > 0 && src->height > 0) { - if (memcmp (dst, src, sizeof *dst)) { - *dst = *src; + if (currprefs.gfx_autoresolution && frame_res >= 0 && frame_res_lace >= 0) { + if (FRAMES_UNTIL_RES_SWITCH > 0 && frame_res_old == frame_res * 2 + frame_res_lace) { + frame_res_cnt--; + if (frame_res_cnt == 0) { + int m = frame_res * 2 + frame_res_lace; + struct wh *dst = currprefs.gfx_afullscreen ? &changed_prefs.gfx_size_fs : &changed_prefs.gfx_size_win; + while (m < 6) { + struct wh *src = currprefs.gfx_afullscreen ? &currprefs.gfx_size_fs_xtra[m] : &currprefs.gfx_size_win_xtra[m]; + if ((src->width > 0 && src->height > 0) || (currprefs.gfx_api || currprefs.gfx_filter > 0)) { + int nr = m >> 1; + int nl = (m & 1) == 0 ? 0 : 1; + if (nr > gfxvidinfo.gfx_resolution_reserved) + nr = gfxvidinfo.gfx_resolution_reserved; + if (nl > gfxvidinfo.gfx_vresolution_reserved) + nl = gfxvidinfo.gfx_vresolution_reserved; + if (changed_prefs.gfx_resolution != nr || changed_prefs.gfx_vresolution != nl) { + changed_prefs.gfx_resolution = nr; + changed_prefs.gfx_vresolution = nl; + write_log (L"RES -> %d LINE -> %d\n", nr, nl); config_changed = 1; } + if (src->width > 0 && src->height > 0) { + if (memcmp (dst, src, sizeof *dst)) { + *dst = *src; + config_changed = 1; + } + } + break; } - break; + m++; } - m++; + frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; } + } else { + frame_res_old = frame_res * 2 + frame_res_lace; frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; } - } else { - frame_res_old = frame_res * 2 + frame_res_lace; - frame_res_cnt = FRAMES_UNTIL_RES_SWITCH; } - frame_res = 0; + frame_res = -1; frame_res_lace = 0; if (can_use_lores > AUTO_LORES_FRAMES && 0) { @@ -2364,21 +2365,7 @@ static void init_drawing_frame (void) seen_sprites = -1; } -/* -* Some code to put status information on the screen. -*/ - -static const char *numbers = { /* ugly 0123456789CHD%+- */ - "+++++++--++++-+++++++++++++++++-++++++++++++++++++++++++++++++++++++++++++++-++++++-++++----++---+--------------" - "+xxxxx+--+xx+-+xxxxx++xxxxx++x+-+x++xxxxx++xxxxx++xxxxx++xxxxx++xxxxx++xxxx+-+x++x+-+xxx++-+xx+-+x---+----------" - "+x+++x+--++x+-+++++x++++++x++x+++x++x++++++x++++++++++x++x+++x++x+++x++x++++-+x++x+-+x++x+--+x++x+--+x+----+++--" - "+x+-+x+---+x+-+xxxxx++xxxxx++xxxxx++xxxxx++xxxxx+--++x+-+xxxxx++xxxxx++x+----+xxxx+-+x++x+----+x+--+xxx+--+xxx+-" - "+x+++x+---+x+-+x++++++++++x++++++x++++++x++x+++x+--+x+--+x+++x++++++x++x++++-+x++x+-+x++x+---+x+x+--+x+----+++--" - "+xxxxx+---+x+-+xxxxx++xxxxx+----+x++xxxxx++xxxxx+--+x+--+xxxxx++xxxxx++xxxx+-+x++x+-+xxx+---+x++xx--------------" - "+++++++---+++-++++++++++++++----+++++++++++++++++--+++--++++++++++++++++++++-++++++-++++------------------------" -}; - -STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq) +void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq) { if (x <= 0) return; @@ -2417,192 +2404,6 @@ STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq) } } -STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a) -{ - uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff]; - if (a) - v |= a[255 - ((c >> 24) & 0xff)]; - return v; -} - -static void write_tdnumber (uae_u8 *buf, int bpp, int x, int y, int num, uae_u32 c1, uae_u32 c2) -{ - int j; - const char *numptr; - - numptr = numbers + num * TD_NUM_WIDTH + NUMBERS_NUM * TD_NUM_WIDTH * y; - for (j = 0; j < TD_NUM_WIDTH; j++) { - if (*numptr == 'x') - putpixel (buf, bpp, x + j, c1, 1); - else if (*numptr == '+') - putpixel (buf, bpp, x + j, c2, 0); - numptr++; - } -} - -void draw_status_line_single (uae_u8 *buf, int bpp, int y, int totalwidth, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *alpha) -{ - int x_start, j, led, border; - uae_u32 c1, c2, cb; - - c1 = ledcolor (0x00ffffff, rc, gc, bc, alpha); - c2 = ledcolor (0x00000000, rc, gc, bc, alpha); - cb = ledcolor (TD_BORDER, rc, gc, bc, alpha); - - if (td_pos & TD_RIGHT) - x_start = totalwidth - TD_PADX - VISIBLE_LEDS * TD_WIDTH; - else - x_start = TD_PADX; - - for (led = 0; led < LED_MAX; led++) { - int side, pos, num1 = -1, num2 = -1, num3 = -1, num4 = -1; - int x, c, on = 0, am = 2; - xcolnr on_rgb, on_rgb2, off_rgb, pen_rgb; - int half = 0; - - pen_rgb = c1; - if (led >= LED_DF0 && led <= LED_DF3) { - int pled = led - LED_DF0; - int track = gui_data.drive_track[pled]; - pos = 6 + pled; - on_rgb = 0x00cc00; - on_rgb2 = 0x006600; - off_rgb = 0x003300; - if (!gui_data.drive_disabled[pled]) { - num1 = -1; - num2 = track / 10; - num3 = track % 10; - on = gui_data.drive_motor[pled]; - if (gui_data.drive_writing[pled]) { - on_rgb = 0xcc0000; - on_rgb2 = 0x880000; - } - half = gui_data.drive_side ? 1 : -1; - if (gui_data.df[pled][0] == 0) - pen_rgb = ledcolor (0x00aaaaaa, rc, gc, bc, alpha); - } - side = gui_data.drive_side; - } else if (led == LED_POWER) { - pos = 3; - on_rgb = ((gui_data.powerled_brightness * 10 / 16) + 0x33) << 16; - on = 1; - off_rgb = 0x330000; - } else if (led == LED_CD) { - pos = 5; - on = gui_data.cd & (LED_CD_AUDIO | LED_CD_ACTIVE); - on_rgb = (on & LED_CD_AUDIO) ? 0x00cc00 : 0x0000cc; - if ((gui_data.cd & LED_CD_ACTIVE2) && !(gui_data.cd & LED_CD_AUDIO)) { - on_rgb &= 0xfefefe; - on_rgb >>= 1; - } - off_rgb = 0x000033; - num1 = -1; - num2 = 10; - num3 = 12; - } else if (led == LED_HD) { - pos = 4; - on = gui_data.hd; - on_rgb = on == 2 ? 0xcc0000 : 0x0000cc; - off_rgb = 0x000033; - num1 = -1; - num2 = 11; - num3 = 12; - } else if (led == LED_FPS) { - int fps = (gui_data.fps + 5) / 10; - pos = 2; - on_rgb = 0x000000; - off_rgb = 0x000000; - if (fps > 999) - fps = 999; - num1 = fps / 100; - num2 = (fps - num1 * 100) / 10; - num3 = fps % 10; - am = 3; - if (num1 == 0) - am = 2; - } else if (led == LED_CPU) { - int idle = (gui_data.idle + 5) / 10; - pos = 1; - on = framecnt && !picasso_on; - on_rgb = 0xcc0000; - off_rgb = 0x000000; - num1 = idle / 100; - num2 = (idle - num1 * 100) / 10; - num3 = idle % 10; - num4 = num1 == 0 ? 13 : -1; - am = 3; - } else if (led == LED_SND) { - int snd = abs(gui_data.sndbuf + 5) / 10; - if (snd > 99) - snd = 99; - pos = 0; - on = gui_data.sndbuf_status; - if (on < 3) { - num1 = gui_data.sndbuf < 0 ? 15 : 14; - num2 = snd / 10; - num3 = snd % 10; - } - on_rgb = 0x000000; - if (on < 0) - on_rgb = 0xcccc00; // underflow - else if (on == 2) - on_rgb = 0xcc0000; // really big overflow - else if (on == 1) - on_rgb = 0x0000cc; // "normal" overflow - off_rgb = 0x000000; - am = 3; - } else if (led == LED_MD && gui_data.drive_disabled[3]) { - // DF3 reused as internal non-volatile ram led (cd32/cdtv) - pos = 6 + 3; - on = gui_data.md; - on_rgb = on == 2 ? 0xcc0000 : 0x00cc00; - off_rgb = 0x003300; - num1 = -1; - num2 = -1; - num3 = -1; - } else - return; - on_rgb |= 0x33000000; - off_rgb |= 0x33000000; - if (half > 0) { - c = ledcolor (on ? (y >= TD_TOTAL_HEIGHT / 2 ? on_rgb2 : on_rgb) : off_rgb, rc, gc, bc, alpha); - } else if (half < 0) { - c = ledcolor (on ? (y < TD_TOTAL_HEIGHT / 2 ? on_rgb2 : on_rgb) : off_rgb, rc, gc, bc, alpha); - } else { - c = ledcolor (on ? on_rgb : off_rgb, rc, gc, bc, alpha); - } - border = 0; - if (y == 0 || y == TD_TOTAL_HEIGHT - 1) { - c = ledcolor (TD_BORDER, rc, gc, bc, alpha); - border = 1; - } - - x = x_start + pos * TD_WIDTH; - if (!border) - putpixel (buf, bpp, x - 1, cb, 0); - for (j = 0; j < TD_LED_WIDTH; j++) - putpixel (buf, bpp, x + j, c, 0); - if (!border) - putpixel (buf, bpp, x + j, cb, 0); - - if (y >= TD_PADY && y - TD_PADY < TD_NUM_HEIGHT) { - if (num3 >= 0) { - x += (TD_LED_WIDTH - am * TD_NUM_WIDTH) / 2; - if (num1 > 0) { - write_tdnumber (buf, bpp, x, y - TD_PADY, num1, pen_rgb, c2); - x += TD_NUM_WIDTH; - } - write_tdnumber (buf, bpp, x, y - TD_PADY, num2, pen_rgb, c2); - x += TD_NUM_WIDTH; - write_tdnumber (buf, bpp, x, y - TD_PADY, num3, pen_rgb, c2); - x += TD_NUM_WIDTH; - if (num4 > 0) - write_tdnumber (buf, bpp, x, y - TD_PADY, num4, pen_rgb, c2); - } - } - } -} - static void draw_status_line (int line) { int bpp, y; @@ -2660,7 +2461,7 @@ static void draw_lightpen_cursor (int x, int y, int line, int onscreen) for (i = 0; i < LIGHTPEN_WIDTH; i++) { int xx = x + i - LIGHTPEN_WIDTH / 2; if (*p != '-' && xx >= 0 && xx < gfxvidinfo.width) - putpixel(xlinebuffer, gfxvidinfo.pixbytes, xx, *p == 'x' ? xcolors[color1] : xcolors[color2], 1); + putpixel (xlinebuffer, gfxvidinfo.pixbytes, xx, *p == 'x' ? xcolors[color1] : xcolors[color2], 1); p++; } } @@ -2737,7 +2538,7 @@ void finish_drawing_frame (void) if (where2 < 0) continue; - hposendblank = 0; + hposblank = 0; pfield_draw_line (line, where2, amiga2aspect_line_map[i1 + 1]); } @@ -2753,7 +2554,7 @@ void finish_drawing_frame (void) if (where2 < 0) continue; - hposendblank = i >= last_max_ypos + 16; + hposblank = i >= last_max_ypos + 16; xlinebuffer = gfxvidinfo.linemem; if (xlinebuffer == 0) @@ -2859,40 +2660,21 @@ void vsync_handle_redraw (int long_frame, int lof_changed) notice_screen_contents_lost (); } - /* At this point, we have finished both the hardware and the - * drawing frame. Essentially, we are outside of all loops and - * can do some things which would cause confusion if they were - * done at other times. - */ - -#ifdef SAVESTATE - if (savestate_state == STATE_DORESTORE) { - savestate_state = STATE_RESTORE; - reset_drawing (); - uae_reset (0); - } else if (savestate_state == STATE_DOREWIND) { - savestate_state = STATE_REWIND; - reset_drawing (); - uae_reset (0); - } -#endif - if (quit_program < 0) { +#ifdef SAVESTATE if (!savestate_state) { if (currprefs.quitstatefile[0]) { - savestate_initsave (currprefs.quitstatefile, 1, 1); + savestate_initsave (currprefs.quitstatefile, 1, 1, true); save_state (currprefs.quitstatefile, L""); } } +#endif quit_program = -quit_program; set_inhibit_frame (IHF_QUIT_PROGRAM); set_special (SPCFLAG_BRK); return; } -#ifdef SAVESTATE - savestate_capture (0); -#endif count_frame (); check_picasso (); @@ -3047,7 +2829,7 @@ void drawing_init (void) uae_sem_init (&gui_sem, 0, 1); #ifdef PICASSO96 - if (savestate_state != STATE_RESTORE) { + if (!isrestore ()) { InitPicasso96 (); picasso_on = 0; picasso_requested_on = 0; diff --git a/ersatz.cpp b/ersatz.cpp index fdb9297e..471f8e88 100644 --- a/ersatz.cpp +++ b/ersatz.cpp @@ -195,14 +195,14 @@ static void ersatz_init (void) disk_eject (0); m68k_setpc (0xFC0002); - fill_prefetch_slow (); + fill_prefetch (); uae_reset (0); ersatzkickfile = 0; return; } m68k_setpc (0x400C); - fill_prefetch_slow (); + fill_prefetch (); /* Init the hardware */ put_long (0x3000, 0xFFFFFFFEul); diff --git a/expansion.cpp b/expansion.cpp index 87dad465..581569d2 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -983,7 +983,7 @@ static void expamem_init_filesys (void) expamem_write (0x08, no_shutup); - expamem_write (0x04, 2); + expamem_write (0x04, 82); expamem_write (0x10, uae_id >> 8); expamem_write (0x14, uae_id & 0xff); @@ -1063,7 +1063,7 @@ static void expamem_init_z3fastmem_2 (addrbank *bank, uae_u32 start, uae_u32 siz expamem_write (0x08, care_addr | no_shutup | force_z3 | (allocated > 0x800000 ? ext_size : Z3_MEM_AUTO)); - expamem_write (0x04, 3); + expamem_write (0x04, 83); expamem_write (0x10, uae_id >> 8); expamem_write (0x14, uae_id & 0xff); diff --git a/filesys.cpp b/filesys.cpp index 69b0d358..458af87a 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -704,60 +704,57 @@ struct hardfiledata *get_hardfile_data (int nr) #define MAXFILESIZE32 (0x7fffffff) /* Passed as type to Lock() */ -#define SHARED_LOCK -2 /* File is readable by others */ -#define ACCESS_READ -2 /* Synonym */ +#define SHARED_LOCK -2 /* File is readable by others */ +#define ACCESS_READ -2 /* Synonym */ #define EXCLUSIVE_LOCK -1 /* No other access allowed */ #define ACCESS_WRITE -1 /* Synonym */ /* packet types */ -#define ACTION_CURRENT_VOLUME 7 -#define ACTION_LOCATE_OBJECT 8 -#define ACTION_RENAME_DISK 9 -#define ACTION_FREE_LOCK 15 +#define ACTION_CURRENT_VOLUME 7 +#define ACTION_LOCATE_OBJECT 8 +#define ACTION_RENAME_DISK 9 +#define ACTION_FREE_LOCK 15 #define ACTION_DELETE_OBJECT 16 #define ACTION_RENAME_OBJECT 17 -#define ACTION_MORE_CACHE 18 -#define ACTION_COPY_DIR 19 -#define ACTION_SET_PROTECT 21 -#define ACTION_CREATE_DIR 22 +#define ACTION_MORE_CACHE 18 +#define ACTION_COPY_DIR 19 +#define ACTION_SET_PROTECT 21 +#define ACTION_CREATE_DIR 22 #define ACTION_EXAMINE_OBJECT 23 -#define ACTION_EXAMINE_NEXT 24 -#define ACTION_DISK_INFO 25 -#define ACTION_INFO 26 -#define ACTION_FLUSH 27 -#define ACTION_SET_COMMENT 28 -#define ACTION_PARENT 29 -#define ACTION_SET_DATE 34 -#define ACTION_FIND_WRITE 1004 -#define ACTION_FIND_INPUT 1005 -#define ACTION_FIND_OUTPUT 1006 -#define ACTION_END 1007 -#define ACTION_SEEK 1008 +#define ACTION_EXAMINE_NEXT 24 +#define ACTION_DISK_INFO 25 +#define ACTION_INFO 26 +#define ACTION_FLUSH 27 +#define ACTION_SET_COMMENT 28 +#define ACTION_PARENT 29 +#define ACTION_SET_DATE 34 +#define ACTION_FIND_WRITE 1004 +#define ACTION_FIND_INPUT 1005 +#define ACTION_FIND_OUTPUT 1006 +#define ACTION_END 1007 +#define ACTION_SEEK 1008 #define ACTION_WRITE_PROTECT 1023 #define ACTION_IS_FILESYSTEM 1027 -#define ACTION_READ 'R' -#define ACTION_WRITE 'W' +#define ACTION_READ 'R' +#define ACTION_WRITE 'W' /* 2.0+ packet types */ -#define ACTION_INHIBIT 31 +#define ACTION_INHIBIT 31 #define ACTION_SET_FILE_SIZE 1022 -#define ACTION_LOCK_RECORD 2008 -#define ACTION_FREE_RECORD 2009 -#define ACTION_SAME_LOCK 40 -#define ACTION_CHANGE_MODE 1028 -#define ACTION_FH_FROM_LOCK 1026 -#define ACTION_COPY_DIR_FH 1030 -#define ACTION_PARENT_FH 1031 -#define ACTION_EXAMINE_ALL 1033 -#define ACTION_EXAMINE_FH 1034 +#define ACTION_LOCK_RECORD 2008 +#define ACTION_FREE_RECORD 2009 +#define ACTION_SAME_LOCK 40 +#define ACTION_CHANGE_MODE 1028 +#define ACTION_FH_FROM_LOCK 1026 +#define ACTION_COPY_DIR_FH 1030 +#define ACTION_PARENT_FH 1031 +#define ACTION_EXAMINE_ALL 1033 +#define ACTION_EXAMINE_FH 1034 #define ACTION_EXAMINE_ALL_END 1035 -#define ACTION_MAKE_LINK 1021 -#define ACTION_READ_LINK 1024 - -#define ACTION_FORMAT 1020 +#define ACTION_FORMAT 1020 #define ACTION_IS_FILESYSTEM 1027 -#define ACTION_ADD_NOTIFY 4097 +#define ACTION_ADD_NOTIFY 4097 #define ACTION_REMOVE_NOTIFY 4098 #define ACTION_CHANGE_FILE_POSITION64 8001 @@ -765,7 +762,11 @@ struct hardfiledata *get_hardfile_data (int nr) #define ACTION_CHANGE_FILE_SIZE64 8003 #define ACTION_GET_FILE_SIZE64 8004 -#define DISK_TYPE 0x444f5301 /* DOS\1 */ +/* not supported */ +#define ACTION_MAKE_LINK 1021 +#define ACTION_READ_LINK 1024 + +#define DISK_TYPE 0x444f5301 /* DOS\1 */ typedef struct { uae_u32 uniq; @@ -775,6 +776,17 @@ typedef struct { a_inode *curr_file; } ExamineKey; +struct lockrecord +{ + struct lockrecord *next; + uae_u32 packet; + uae_u32 pos; + uae_u32 len; + uae_u32 mode; + uae_u32 timeout; + uae_u32 msg; +}; + typedef struct key { struct key *next; a_inode *aino; @@ -784,6 +796,7 @@ typedef struct key { int dosmode; int createmode; int notifyactive; + struct lockrecord *record; } Key; typedef struct notify { @@ -843,6 +856,8 @@ typedef struct _unit { /* Keys */ struct key *keys; + struct lockrecord *waitingrecords; + a_inode rootnode; unsigned long aino_cache_size; a_inode *aino_hash[MAX_AINO_HASH]; @@ -1128,23 +1143,6 @@ int filesys_eject (int nr) return 1; } -void filesys_vsync (void) -{ - Unit *u; - - for (u = units; u; u = u->next) { - if (u->reinsertdelay > 0) { - u->reinsertdelay--; - if (u->reinsertdelay == 0) { - filesys_insert (u->unit, u->newvolume, u->newrootdir, u->newreadonly, u->newflags); - xfree (u->newvolume); - u->newvolume = NULL; - xfree (u->newrootdir); - u->newrootdir = NULL; - } - } - } -} static void filesys_delayed_change (Unit *u, int frames, const TCHAR *rootdir, const TCHAR *volume, bool readonly, int flags) { u->reinsertdelay = 50; @@ -2116,7 +2114,7 @@ static void filesys_start_thread (UnitInfo *ui, int nr) ui->unit_pipe = 0; ui->back_pipe = 0; ui->reset_state = FS_STARTUP; - if (savestate_state != STATE_RESTORE) { + if (!isrestore ()) { ui->startup = 0; ui->self = 0; } @@ -2129,7 +2127,7 @@ static void filesys_start_thread (UnitInfo *ui, int nr) uae_start_thread (L"filesys", filesys_thread, (void *)ui, &ui->tid); } #endif - if (savestate_state == STATE_RESTORE) + if (isrestore ()) startup_update_unit (ui->self, ui); } @@ -2291,6 +2289,12 @@ static void free_key (Unit *unit, Key *k) prev = k1; } + for (struct lockrecord *lr = k->record; lr;) { + struct lockrecord *next = lr->next; + xfree (lr); + lr = next; + } + if (k->fd != NULL) fs_close (k->fd); @@ -2883,6 +2887,189 @@ int get_native_path (uae_u32 lock, TCHAR *out) return -1; } + +#define REC_EXCLUSIVE 0 +#define REC_EXCLUSIVE_IMMED 1 +#define REC_SHARED 2 +#define REC_SHARED_IMMED 3 + +static struct lockrecord *new_record (uae_u32 packet, uae_u32 pos, uae_u32 len, uae_u32 mode, uae_u32 timeout, uae_u32 msg) +{ + struct lockrecord *lr = xcalloc (struct lockrecord, 1); + lr->packet = packet; + lr->pos = pos; + lr->len = len; + lr->mode = mode; + lr->timeout = timeout * vblank_hz / 50; + lr->msg = msg; + return lr; +} + +static bool record_hit (Unit *unit, Key *k, uae_u32 pos, uae_u32 len, uae_u32 mode) +{ + bool exclusive = mode == REC_EXCLUSIVE || mode == REC_EXCLUSIVE_IMMED; + for (Key *k2 = unit->keys; k2; k2 = k2->next) { + if (k2->aino->uniq == k->aino->uniq) { + if (k2 == k) + continue; + for (struct lockrecord *lr = k2->record; lr; lr = lr->next) { + bool exclusive2 = lr->mode == REC_EXCLUSIVE || lr->mode == REC_EXCLUSIVE_IMMED; + if (exclusive || exclusive2) { + uae_u32 a1 = pos; + uae_u32 a2 = pos + len; + uae_u32 b1 = lr->pos; + uae_u32 b2 = lr->pos + lr->len; + if (len && lr->len) { + bool hit = (a1 >= b1 && a1 < b2) || (a2 > b1 && a2 < b2) || (b1 >= a1 && b1 < a2) || (b2 > a1 && b2 < a2); + if (hit) + return true; + } + } + } + } + } + return false; +} + +static void record_timeout (Unit *unit) +{ + bool retry = true; + while (retry) { + retry = false; + struct lockrecord *prev = NULL; + for (struct lockrecord *lr = unit->waitingrecords; lr; lr = lr->next) { + lr->timeout--; + if (lr->timeout == 0) { + Key *k = lookup_key (unit, GET_PCK_ARG1 (lr->packet)); + PUT_PCK_RES1 (lr->packet, DOS_FALSE); + PUT_PCK_RES2 (lr->packet, ERROR_LOCK_TIMEOUT); + // mark packet as complete + put_long (lr->msg + 4, 0xfffffffe); + uae_Signal (get_long (unit->volume + 176 - 32), 1 << 13); + if (prev) + prev->next = lr->next; + else + unit->waitingrecords = lr->next; + write_log (L"queued record timed out '%s',%d,%d,%d,%d\n", k ? k->aino->nname : L"NULL", lr->pos, lr->len, lr->mode, lr->timeout); + xfree (lr); + retry = true; + break; + } + prev = lr; + } + } +} + +static void record_check_waiting (Unit *unit) +{ + bool retry = true; + while (retry) { + retry = false; + struct lockrecord *prev = NULL; + for (struct lockrecord *lr = unit->waitingrecords; lr; lr = lr->next) { + Key *k = lookup_key (unit, GET_PCK_ARG1 (lr->packet)); + if (!k || !record_hit (unit, k, lr->pos, lr->len, lr->mode)) { + if (prev) + prev->next = lr->next; + else + unit->waitingrecords = lr->next; + write_log (L"queued record released '%s',%d,%d,%d,%d\n", k->aino->nname, lr->pos, lr->len, lr->mode, lr->timeout); + // mark packet as complete + put_long (lr->msg + 4, 0xffffffff); + xfree (lr); + retry = true; + break; + } + prev = lr; + } + } +} + +static int action_lock_record (Unit *unit, dpacket packet, uae_u32 msg) +{ + Key *k = lookup_key (unit, GET_PCK_ARG1 (packet)); + uae_u32 pos = GET_PCK_ARG2 (packet); + uae_u32 len = GET_PCK_ARG3 (packet); + uae_u32 mode = GET_PCK_ARG4 (packet); + uae_u32 timeout = GET_PCK_ARG5 (packet); + + bool exclusive = mode == REC_EXCLUSIVE || mode == REC_EXCLUSIVE_IMMED; + + write_log (L"action_lock_record('%s',%d,%d,%d,%d)\n", k ? k->aino->nname : L"null", pos, len, mode, timeout); + + if (!k || mode > REC_SHARED_IMMED) { + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_OBJECT_WRONG_TYPE); + return 1; + } + + if (mode == REC_EXCLUSIVE_IMMED || mode == REC_SHARED_IMMED) + timeout = 0; + + if (record_hit (unit, k, pos, len, mode)) { + if (timeout && msg) { + // queue it and do not reply + struct lockrecord *lr = new_record (packet, pos, len, mode, timeout, msg); + if (unit->waitingrecords) { + lr->next = unit->waitingrecords; + unit->waitingrecords = lr; + } else { + unit->waitingrecords = lr; + } + write_log (L"-> collision, timeout queued\n"); + return -1; + } + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_LOCK_COLLISION); + write_log (L"-> ERROR_LOCK_COLLISION\n"); + return 1; + } + + struct lockrecord *lr = new_record (GET_PCK_ARG1 (packet), pos, len, mode, timeout, 0); + if (k->record) { + lr->next = k->record; + k->record = lr; + } else { + k->record = lr; + } + PUT_PCK_RES1 (packet, DOS_TRUE); + write_log (L"-> OK\n"); + return 1; +} + +static void action_free_record (Unit *unit, dpacket packet) +{ + Key *k = lookup_key (unit, GET_PCK_ARG1 (packet)); + uae_u32 pos = GET_PCK_ARG2 (packet); + uae_u32 len = GET_PCK_ARG3 (packet); + + write_log (L"action_free_record('%s',%d,%d)\n", k ? k->aino->nname : L"null", pos, len); + + if (!k) { + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_OBJECT_WRONG_TYPE); + return; + } + + struct lockrecord *prev = NULL; + for (struct lockrecord *lr = k->record; lr; lr = lr->next) { + if (lr->pos == pos && lr->len == len) { + if (prev) + prev->next = lr->next; + else + k->record = lr->next; + xfree (lr); + write_log (L"->OK\n"); + record_check_waiting (unit); + PUT_PCK_RES1 (packet, DOS_TRUE); + return; + } + } + write_log (L"-> ERROR_RECORD_NOT_LOCKED\n"); + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_RECORD_NOT_LOCKED); +} + #define EXALL_DEBUG 0 #define EXALL_END 0xde1111ad @@ -4824,12 +5011,12 @@ static uae_u32 REGPARAM2 exter_int_helper (TrapContext *context) return 0; } -static int handle_packet (Unit *unit, dpacket pck) +static int handle_packet (Unit *unit, dpacket pck, uae_u32 msg) { uae_s32 type = GET_PCK_TYPE (pck); PUT_PCK_RES2 (pck, 0); - if (unit->inhibited && filesys_isvolume(unit) + if (unit->inhibited && filesys_isvolume (unit) && type != ACTION_INHIBIT && type != ACTION_MORE_CACHE && type != ACTION_DISK_INFO) { PUT_PCK_RES1 (pck, DOS_FALSE); @@ -4839,7 +5026,7 @@ static int handle_packet (Unit *unit, dpacket pck) if (type != ACTION_INHIBIT && type != ACTION_CURRENT_VOLUME && type != ACTION_IS_FILESYSTEM && type != ACTION_MORE_CACHE && type != ACTION_WRITE_PROTECT - && !filesys_isvolume(unit)) { + && !filesys_isvolume (unit)) { PUT_PCK_RES1 (pck, DOS_FALSE); PUT_PCK_RES2 (pck, ERROR_NO_DISK); return 1; @@ -4887,6 +5074,8 @@ static int handle_packet (Unit *unit, dpacket pck) case ACTION_REMOVE_NOTIFY: action_remove_notify (unit, pck); break; case ACTION_EXAMINE_ALL: return action_examine_all (unit, pck); case ACTION_EXAMINE_ALL_END: return action_examine_all_end (unit, pck); + case ACTION_LOCK_RECORD: return action_lock_record (unit, pck, msg); break; + case ACTION_FREE_RECORD: action_free_record (unit, pck); break; /* OS4+ packet types */ case ACTION_CHANGE_FILE_POSITION64: action_change_file_position64 (unit, pck); break; @@ -4895,8 +5084,6 @@ static int handle_packet (Unit *unit, dpacket pck) case ACTION_GET_FILE_SIZE64: action_get_file_size64 (unit, pck); break; /* unsupported packets */ - case ACTION_LOCK_RECORD: - case ACTION_FREE_RECORD: case ACTION_MAKE_LINK: case ACTION_READ_LINK: case ACTION_FORMAT: @@ -4934,18 +5121,19 @@ static void *filesys_thread (void *unit_v) put_long (get_long (morelocks), get_long (ui->self->locklist)); put_long (ui->self->locklist, morelocks); - if (! handle_packet (ui->self, pck)) { + int ret = handle_packet (ui->self, pck, msg); + if (!ret) { PUT_PCK_RES1 (pck, DOS_FALSE); PUT_PCK_RES2 (pck, ERROR_ACTION_NOT_KNOWN); } - /* Mark the packet as processed for the list scan in the assembly code. */ - put_long (msg + 4, 0xffffffff); - /* Acquire the message lock, so that we know we can safely send the - * message. */ + if (ret >= 0) { + /* Mark the packet as processed for the list scan in the assembly code. */ + put_long (msg + 4, 0xffffffff); + } + /* Acquire the message lock, so that we know we can safely send the message. */ ui->self->cmds_sent++; - /* The message is sent by our interrupt handler, so make sure an interrupt - * happens. */ - do_uae_int_requested(); + /* The message is sent by our interrupt handler, so make sure an interrupt happens. */ + do_uae_int_requested (); /* Send back the locks. */ if (get_long (ui->self->locklist) != 0) write_comm_pipe_int (ui->back_pipe, (int)(get_long (ui->self->locklist)), 0); @@ -4992,7 +5180,7 @@ static uae_u32 REGPARAM2 filesys_handler (TrapContext *context) } #endif - if (! handle_packet (unit, packet_addr)) { + if (! handle_packet (unit, packet_addr, 0)) { error: PUT_PCK_RES1 (packet_addr, DOS_FALSE); PUT_PCK_RES2 (packet_addr, ERROR_ACTION_NOT_KNOWN); @@ -5045,6 +5233,12 @@ void filesys_free_handles (void) xfree (k1); } u->keys = NULL; + struct lockrecord *lrnext; + for (struct lockrecord *lr = u->waitingrecords; lr; lr = lrnext) { + lrnext = lr->next; + xfree (lr); + } + u->waitingrecords = NULL; free_all_ainos (u, &u->rootnode); u->rootnode.next = u->rootnode.prev = &u->rootnode; u->aino_cache_size = 0; @@ -5073,7 +5267,7 @@ static void filesys_reset2 (void) void filesys_reset (void) { - if (savestate_state == STATE_RESTORE) + if (isrestore ()) return; filesys_reset2 (); initialize_mountinfo (); @@ -5114,7 +5308,7 @@ static void filesys_prepare_reset2 (void) void filesys_prepare_reset (void) { - if (savestate_state == STATE_RESTORE) + if (isrestore ()) return; filesys_prepare_reset2 (); } @@ -5819,6 +6013,25 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *context) return 1; } +void filesys_vsync (void) +{ + Unit *u; + + for (u = units; u; u = u->next) { + if (u->reinsertdelay > 0) { + u->reinsertdelay--; + if (u->reinsertdelay == 0) { + filesys_insert (u->unit, u->newvolume, u->newrootdir, u->newreadonly, u->newflags); + xfree (u->newvolume); + u->newvolume = NULL; + xfree (u->newrootdir); + u->newrootdir = NULL; + } + } + record_timeout (u); + } +} + void filesys_install (void) { uaecptr loop; diff --git a/filesys_bootrom.cpp b/filesys_bootrom.cpp index bdf3d7ea..e43ae2ac 100644 --- a/filesys_bootrom.cpp +++ b/filesys_bootrom.cpp @@ -2,8 +2,8 @@ db(0x00); db(0x00); db(0x00); db(0x09); db(0x60); db(0x00); db(0x0a); db(0x4a); db(0x00); db(0x00); db(0x08); db(0x2c); db(0x00); db(0x00); db(0x00); db(0xd0); db(0x00); db(0x00); db(0x02); db(0x54); db(0x00); db(0x00); db(0x00); db(0x24); - db(0x00); db(0x00); db(0x03); db(0x10); db(0x00); db(0x00); db(0x0e); db(0x1c); - db(0x00); db(0x00); db(0x12); db(0xac); db(0x43); db(0xfa); db(0x17); db(0x86); + db(0x00); db(0x00); db(0x03); db(0x10); db(0x00); db(0x00); db(0x0e); db(0x26); + db(0x00); db(0x00); db(0x12); db(0xb6); db(0x43); db(0xfa); db(0x17); db(0x8e); db(0x4e); db(0xae); db(0xff); db(0xa0); db(0x20); db(0x40); db(0x20); db(0x28); db(0x00); db(0x16); db(0x20); db(0x40); db(0x4e); db(0x90); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0xe0); db(0xe2); db(0x2c); db(0x78); db(0x00); db(0x04); @@ -20,16 +20,16 @@ db(0x20); db(0x68); db(0x00); db(0x02); db(0x2f); db(0x08); db(0x4e); db(0x90); db(0x20); db(0x5f); db(0x58); db(0x8f); db(0x48); db(0xe7); db(0xff); db(0x7e); db(0x22); db(0x4e); db(0x20); db(0x08); db(0x30); db(0x7c); db(0xff); db(0xb8); - db(0x4e); db(0xae); db(0xfe); db(0x5c); db(0x61); db(0x00); db(0x11); db(0xfe); - db(0x61); db(0x00); db(0x15); db(0xb4); db(0x4c); db(0xdf); db(0x7e); db(0xff); + db(0x4e); db(0xae); db(0xfe); db(0x5c); db(0x61); db(0x00); db(0x12); db(0x08); + db(0x61); db(0x00); db(0x15); db(0xbc); db(0x4c); db(0xdf); db(0x7e); db(0xff); db(0x4e); db(0x75); db(0x00); db(0x00); db(0x08); db(0x00); db(0x00); db(0x02); db(0x67); db(0x06); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0x00); db(0x00); db(0x4e); db(0xf9); db(0x00); db(0xf0); db(0x00); db(0x00); db(0x00); db(0x00); db(0x48); db(0xe7); db(0xff); db(0xfe); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x30); db(0x3c); db(0xff); db(0xfc); db(0x61); db(0x00); db(0x0b); db(0xaa); - db(0x2a); db(0x50); db(0x43); db(0xfa); db(0x16); db(0xf7); db(0x70); db(0x24); + db(0x30); db(0x3c); db(0xff); db(0xfc); db(0x61); db(0x00); db(0x0b); db(0xb4); + db(0x2a); db(0x50); db(0x43); db(0xfa); db(0x16); db(0xff); db(0x70); db(0x24); db(0x7a); db(0x01); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x4a); db(0x80); - db(0x66); db(0x0c); db(0x43); db(0xfa); db(0x16); db(0xe7); db(0x70); db(0x00); + db(0x66); db(0x0c); db(0x43); db(0xfa); db(0x16); db(0xef); db(0x70); db(0x00); db(0x7a); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x28); db(0x40); db(0x4a); db(0xad); db(0x01); db(0x0c); db(0x67); db(0x5a); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x02); db(0x2c); db(0x22); db(0x3c); db(0x00); db(0x01); @@ -46,38 +46,38 @@ db(0x2c); db(0x78); db(0x00); db(0x04); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x62); db(0x78); db(0x03); db(0x0c); db(0x6e); db(0x00); db(0x24); db(0x00); db(0x14); db(0x65); db(0x04); db(0x00); db(0x44); db(0x01); db(0x00); - db(0x30); db(0x3c); db(0xff); db(0x80); db(0x61); db(0x00); db(0x0b); db(0x0a); + db(0x30); db(0x3c); db(0xff); db(0x80); db(0x61); db(0x00); db(0x0b); db(0x14); db(0x4e); db(0x90); db(0x22); db(0x04); db(0x74); db(0xf6); db(0x20); db(0x7c); db(0x00); db(0x20); db(0x00); db(0x00); db(0x90); db(0x88); db(0x65); db(0x08); db(0x67); db(0x06); db(0x93); db(0xc9); db(0x4e); db(0xae); db(0xfd); db(0x96); - db(0x30); db(0x3c); db(0xff); db(0x80); db(0x61); db(0x00); db(0x0a); db(0xea); + db(0x30); db(0x3c); db(0xff); db(0x80); db(0x61); db(0x00); db(0x0a); db(0xf4); db(0x4e); db(0x90); db(0x20); db(0x49); db(0x20); db(0x01); db(0x67); db(0x0c); - db(0x22); db(0x04); db(0x74); db(0xfb); db(0x43); db(0xfa); db(0x16); db(0x53); - db(0x4e); db(0xae); db(0xfd); db(0x96); db(0x41); db(0xfa); db(0x15); db(0xca); + db(0x22); db(0x04); db(0x74); db(0xfb); db(0x43); db(0xfa); db(0x16); db(0x5b); + db(0x4e); db(0xae); db(0xfd); db(0x96); db(0x41); db(0xfa); db(0x15); db(0xd2); db(0x43); db(0xfa); db(0x00); db(0x54); db(0x70); db(0x0a); db(0x61); db(0x00); - db(0x0b); db(0xa4); db(0x22); db(0x40); db(0x72); db(0x01); db(0x30); db(0x3c); - db(0xff); db(0x48); db(0x61); db(0x00); db(0x0a); db(0xbc); db(0x4e); db(0x90); + db(0x0b); db(0xae); db(0x22); db(0x40); db(0x72); db(0x01); db(0x30); db(0x3c); + db(0xff); db(0x48); db(0x61); db(0x00); db(0x0a); db(0xc6); db(0x4e); db(0x90); db(0x4c); db(0xdf); db(0x7f); db(0xff); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x38); db(0x22); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x24); db(0x00); db(0x28); db(0x01); db(0x26); db(0x09); db(0x24); db(0x48); db(0x43); db(0xfa); - db(0x15); db(0xc4); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); + db(0x15); db(0xcc); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x4a); db(0x80); db(0x67); db(0x14); db(0x2c); db(0x40); db(0x22); db(0x0a); db(0xe4); db(0x8b); db(0x4e); db(0xae); db(0xff); db(0x76); db(0x22); db(0x4e); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x4e); db(0xae); db(0xfe); db(0x62); db(0x4c); db(0xdf); db(0x44); db(0x1c); db(0x4e); db(0x75); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x70); db(0x00); db(0x08); db(0xc0); db(0x00); db(0x0d); - db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x41); db(0xfa); db(0x15); db(0x75); + db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x41); db(0xfa); db(0x15); db(0x7d); db(0x43); db(0xfa); db(0x00); db(0x16); db(0x70); db(0x0f); db(0x22); db(0x3c); db(0x00); db(0x00); db(0x1f); db(0x40); db(0x61); db(0x00); db(0xff); db(0xa8); db(0x60); db(0xdc); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x10); db(0x00); db(0x00); db(0x00); db(0x00); db(0x72); db(0x02); db(0x30); db(0x3c); - db(0xff); db(0x48); db(0x61); db(0x00); db(0x0a); db(0x44); db(0x4e); db(0x90); + db(0xff); db(0x48); db(0x61); db(0x00); db(0x0a); db(0x4e); db(0x4e); db(0x90); db(0x22); db(0x00); db(0x6b); db(0x04); db(0x61); db(0x00); db(0x07); db(0x8a); db(0x70); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x00); db(0x20); - db(0x30); db(0x3c); db(0xff); db(0x50); db(0x61); db(0x00); db(0x0a); db(0x2a); + db(0x30); db(0x3c); db(0xff); db(0x50); db(0x61); db(0x00); db(0x0a); db(0x34); db(0x70); db(0x00); db(0x4e); db(0x90); db(0x4a); db(0x80); db(0x67); db(0x00); db(0x00); db(0xa2); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x30); db(0x3c); - db(0xff); db(0x50); db(0x61); db(0x00); db(0x0a); db(0x14); db(0x70); db(0x02); + db(0xff); db(0x50); db(0x61); db(0x00); db(0x0a); db(0x1e); db(0x70); db(0x02); db(0x4e); db(0x90); db(0x0c); db(0x40); db(0x00); db(0x01); db(0x6d); db(0x00); db(0x00); db(0x7c); db(0x6e); db(0x06); db(0x4e); db(0xae); db(0xfe); db(0x92); db(0x60); db(0xe4); db(0x0c); db(0x40); db(0x00); db(0x02); db(0x6e); db(0x08); @@ -95,17 +95,17 @@ db(0x00); db(0x18); db(0x25); db(0x49); db(0x00); db(0x1a); db(0x20); db(0x69); db(0x00); db(0x10); db(0x22); db(0x4a); db(0x4e); db(0xae); db(0xfe); db(0x92); db(0x60); db(0x00); db(0xff); db(0x74); db(0x30); db(0x3c); db(0xff); db(0x50); - db(0x61); db(0x00); db(0x09); db(0x86); db(0x70); db(0x04); db(0x4e); db(0x90); + db(0x61); db(0x00); db(0x09); db(0x90); db(0x70); db(0x04); db(0x4e); db(0x90); db(0x70); db(0x01); db(0x4c); db(0xdf); db(0x04); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0xc0); db(0xc0); db(0x61); db(0x00); db(0xfd); db(0x22); db(0x70); db(0x1a); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40); db(0x41); db(0xfa); - db(0x14); db(0x49); db(0x23); db(0x48); db(0x00); db(0x0a); db(0x41); db(0xfa); + db(0x14); db(0x51); db(0x23); db(0x48); db(0x00); db(0x0a); db(0x41); db(0xfa); db(0xff); db(0x24); db(0x23); db(0x48); db(0x00); db(0x0e); db(0x41); db(0xfa); db(0xff); db(0x1c); db(0x23); db(0x48); db(0x00); db(0x12); db(0x33); db(0x7c); db(0x02); db(0x14); db(0x00); db(0x08); db(0x70); db(0x03); db(0x4e); db(0xae); - db(0xff); db(0x58); db(0x30); db(0x3a); db(0x0a); db(0xd0); db(0x67); db(0x04); - db(0x61); db(0x00); db(0x0a); db(0x6e); db(0x4c); db(0xdf); db(0x03); db(0x03); + db(0xff); db(0x58); db(0x30); db(0x3a); db(0x0a); db(0xda); db(0x67); db(0x04); + db(0x61); db(0x00); db(0x0a); db(0x78); db(0x4c); db(0xdf); db(0x03); db(0x03); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0xc0); db(0xf2); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x24); db(0x48); db(0x26); db(0x49); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x00); db(0xbe); db(0x22); db(0x3c); db(0x00); db(0x01); @@ -114,7 +114,7 @@ db(0x00); db(0x00); db(0x00); db(0x0e); db(0x52); db(0x40); db(0x0c); db(0x40); db(0x00); db(0x8c); db(0x66); db(0xf2); db(0x20); db(0x0a); db(0xe4); db(0x88); db(0x21); db(0x40); db(0x00); db(0x36); db(0x22); db(0x48); db(0x41); db(0xfa); - db(0x13); db(0xd9); db(0x23); db(0x48); db(0x00); db(0x0a); db(0x20); db(0x6b); + db(0x13); db(0xe1); db(0x23); db(0x48); db(0x00); db(0x0a); db(0x20); db(0x6b); db(0x01); db(0x98); db(0x41); db(0xe8); db(0x00); db(0x12); db(0x4e); db(0xae); db(0xff); db(0x10); db(0x4c); db(0xdf); db(0x4f); db(0x03); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x7f); db(0x7e); db(0x2c); db(0x78); db(0x00); db(0x04); @@ -151,13 +151,13 @@ db(0x60); db(0xf4); db(0x48); db(0xe7); db(0x40); db(0xe2); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x41); db(0xee); db(0x01); db(0x50); db(0x20); db(0x50); db(0x4a); db(0x90); db(0x67); db(0x1a); db(0x22); db(0x68); db(0x00); db(0x0a); - db(0x45); db(0xfa); db(0x13); db(0x2b); db(0x10); db(0x19); db(0x12); db(0x1a); + db(0x45); db(0xfa); db(0x13); db(0x33); db(0x10); db(0x19); db(0x12); db(0x1a); db(0xb0); db(0x01); db(0x66); db(0x06); db(0x4a); db(0x00); db(0x67); db(0x42); db(0x60); db(0xf2); db(0x20); db(0x50); db(0x60); db(0xe2); db(0x70); db(0x20); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x24); db(0x40); db(0x15); db(0x7c); db(0x00); db(0x08); - db(0x00); db(0x08); db(0x41); db(0xfa); db(0x13); db(0x01); db(0x25); db(0x48); - db(0x00); db(0x0a); db(0x41); db(0xfa); db(0x12); db(0x7d); db(0x25); db(0x48); + db(0x00); db(0x08); db(0x41); db(0xfa); db(0x13); db(0x09); db(0x25); db(0x48); + db(0x00); db(0x0a); db(0x41); db(0xfa); db(0x12); db(0x85); db(0x25); db(0x48); db(0x00); db(0x0e); db(0x41); db(0xea); db(0x00); db(0x12); db(0x20); db(0x88); db(0x58); db(0x90); db(0x21); db(0x48); db(0x00); db(0x08); db(0x41); db(0xee); db(0x01); db(0x50); db(0x22); db(0x4a); db(0x4e); db(0xae); db(0xff); db(0x0a); @@ -262,8 +262,8 @@ db(0x4c); db(0xdf); db(0x7c); db(0xfc); db(0x20); db(0x6c); db(0x00); db(0x24); db(0x4a); db(0x90); db(0x4e); db(0x75); db(0x61); db(0x00); db(0xfc); db(0x7c); db(0x21); db(0x40); db(0x01); db(0x98); db(0x2f); db(0x08); db(0x30); db(0x3c); - db(0xff); db(0xfc); db(0x61); db(0x00); db(0x04); db(0x4c); db(0x2a); db(0x50); - db(0x30); db(0x3c); db(0xff); db(0x28); db(0x61); db(0x00); db(0x04); db(0x42); + db(0xff); db(0xfc); db(0x61); db(0x00); db(0x04); db(0x56); db(0x2a); db(0x50); + db(0x30); db(0x3c); db(0xff); db(0x28); db(0x61); db(0x00); db(0x04); db(0x4c); db(0x22); db(0x48); db(0x20); db(0x5f); db(0x42); db(0xa8); db(0x01); db(0x90); db(0x42); db(0xa8); db(0x01); db(0x94); db(0x4e); db(0x91); db(0x26); db(0x00); db(0x0c); db(0x43); db(0xff); db(0xfe); db(0x67); db(0x00); db(0xf9); db(0x76); @@ -271,11 +271,11 @@ db(0x2f); db(0x08); db(0x72); db(0x01); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x20); db(0x5f); db(0x21); db(0x40); db(0x01); db(0x94); db(0x4a); db(0x83); db(0x6a); db(0x0e); db(0x22); db(0x48); - db(0x30); db(0x3c); db(0xff); db(0x20); db(0x61); db(0x00); db(0x04); db(0x02); + db(0x30); db(0x3c); db(0xff); db(0x20); db(0x61); db(0x00); db(0x04); db(0x0c); db(0x4e); db(0x90); db(0x60); db(0x26); db(0x2c); db(0x4c); db(0x2f); db(0x08); db(0x4e); db(0xae); db(0xff); db(0x70); db(0x20); db(0x5f); db(0x22); db(0x48); db(0x26); db(0x40); db(0x30); db(0x3c); db(0xff); db(0x20); db(0x61); db(0x00); - db(0x03); db(0xe8); db(0x4e); db(0x90); db(0x70); db(0x00); db(0x27); db(0x40); + db(0x03); db(0xf2); db(0x4e); db(0x90); db(0x70); db(0x00); db(0x27); db(0x40); db(0x00); db(0x08); db(0x27); db(0x40); db(0x00); db(0x10); db(0x27); db(0x40); db(0x00); db(0x20); db(0x4a); db(0xa9); db(0x01); db(0x94); db(0x67); db(0x28); db(0x20); db(0x69); db(0x01); db(0x94); db(0x61); db(0x00); db(0xfa); db(0xf2); @@ -284,7 +284,7 @@ db(0x4e); db(0xae); db(0xff); db(0x2e); db(0x4c); db(0xdf); db(0x03); db(0x01); db(0x4a); db(0x80); db(0x67); db(0x04); db(0x61); db(0x00); db(0xfa); db(0x7c); db(0x4a); db(0x83); db(0x6b); db(0x00); db(0xf8); db(0xf0); db(0x30); db(0x3c); - db(0xff); db(0x18); db(0x61); db(0x00); db(0x03); db(0x9c); db(0x4e); db(0x90); + db(0xff); db(0x18); db(0x61); db(0x00); db(0x03); db(0xa6); db(0x4e); db(0x90); db(0x20); db(0x03); db(0x16); db(0x29); db(0x00); db(0x4f); db(0x4a); db(0x80); db(0x66); db(0x1a); db(0x27); db(0x7c); db(0x00); db(0x00); db(0x17); db(0x70); db(0x00); db(0x14); db(0x41); db(0xfa); db(0xf6); db(0xf8); db(0x20); db(0x08); @@ -309,16 +309,16 @@ db(0x67); db(0x3a); db(0x20); db(0x52); db(0x24); db(0x40); db(0x22); db(0x4a); db(0x12); db(0xd8); db(0x66); db(0xfc); db(0x13); db(0x7c); db(0x00); db(0x3a); db(0xff); db(0xff); db(0x42); db(0x11); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x43); db(0xfa); db(0x0d); db(0xfa); db(0x70); db(0x00); db(0x4e); db(0xae); + db(0x43); db(0xfa); db(0x0e); db(0x02); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x2c); db(0x40); db(0x22); db(0x0a); db(0x4e); db(0xae); db(0xff); db(0x52); db(0x22); db(0x4e); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x4e); db(0xae); db(0xfe); db(0x62); db(0x22); db(0x4a); db(0x20); db(0x02); db(0x4e); db(0xae); db(0xff); db(0x2e); db(0x70); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x3f); db(0x3e); db(0x2c); db(0x01); db(0x7e); db(0x06); - db(0x2c); db(0x78); db(0x00); db(0x04); db(0x43); db(0xfa); db(0x0d); db(0xf5); + db(0x2c); db(0x78); db(0x00); db(0x04); db(0x43); db(0xfa); db(0x0d); db(0xfd); db(0x70); db(0x24); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x4a); db(0x80); db(0x66); db(0x0e); db(0x08); db(0x87); db(0x00); db(0x02); db(0x43); db(0xfa); - db(0x0d); db(0xe3); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); + db(0x0d); db(0xeb); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x28); db(0x40); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x02); db(0x2c); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x20); db(0x40); db(0x4a); db(0x80); db(0x67); db(0x2c); @@ -331,31 +331,31 @@ db(0xfe); db(0x62); db(0x4c); db(0xdf); db(0x7c); db(0xfc); db(0x4e); db(0x75); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x93); db(0xc9); db(0x4e); db(0xae); db(0xfe); db(0xda); db(0x20); db(0x40); db(0x4b); db(0xe8); db(0x00); db(0x5c); - db(0x43); db(0xfa); db(0x0d); db(0x4a); db(0x70); db(0x00); db(0x4e); db(0xae); + db(0x43); db(0xfa); db(0x0d); db(0x52); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x24); db(0x40); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x00); db(0xb9); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x26); db(0x40); db(0x7c); db(0x00); db(0x26); db(0x86); db(0x27); db(0x46); db(0x00); db(0x04); db(0x27); db(0x46); db(0x00); db(0x08); db(0x27); db(0x4a); db(0x00); db(0xa0); db(0x50); db(0xeb); db(0x00); db(0x9e); db(0x93); db(0xc9); db(0x4e); db(0xae); db(0xfe); db(0xda); - db(0x27); db(0x40); db(0x00); db(0xb0); db(0x41); db(0xfa); db(0x0c); db(0x32); - db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0x02); db(0x84); - db(0x27); db(0x40); db(0x00); db(0xa4); db(0x41); db(0xfa); db(0x0c); db(0x2f); - db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0x02); db(0x74); + db(0x27); db(0x40); db(0x00); db(0xb0); db(0x41); db(0xfa); db(0x0c); db(0x3a); + db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0x02); db(0x8e); + db(0x27); db(0x40); db(0x00); db(0xa4); db(0x41); db(0xfa); db(0x0c); db(0x37); + db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0x02); db(0x7e); db(0x27); db(0x40); db(0x00); db(0xa8); db(0x7a); db(0x00); db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x80); db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x8c); db(0x28); db(0x40); db(0x26); db(0x2c); db(0x00); db(0x0a); - db(0x30); db(0x3c); db(0xff); db(0x40); db(0x61); db(0x00); db(0x01); db(0xb2); + db(0x30); db(0x3c); db(0xff); db(0x40); db(0x61); db(0x00); db(0x01); db(0xbc); db(0x70); db(0x00); db(0x4e); db(0x90); db(0x24); db(0x00); db(0x70); db(0x01); db(0x61); db(0x00); db(0xfa); db(0x38); db(0x08); db(0x02); db(0x00); db(0x01); db(0x67); db(0x06); db(0x70); db(0x01); db(0x61); db(0x00); db(0xfb); db(0xa0); - db(0x60); db(0x00); db(0x00); db(0xf8); db(0x20); db(0x4d); db(0x4e); db(0xae); + db(0x60); db(0x00); db(0x01); db(0x02); db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x8c); db(0x28); db(0x40); db(0x4a); db(0x80); db(0x66); db(0x10); db(0x70); db(0x00); db(0x12); db(0x2d); db(0x00); db(0x0f); db(0x03); db(0xc0); db(0x08); db(0xc0); db(0x00); db(0x0d); db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x4a); db(0x2b); db(0x00); db(0xac); db(0x67); db(0x08); db(0x61); db(0x00); db(0xfc); db(0x4c); db(0x42); db(0x2b); db(0x00); db(0xac); db(0x20); db(0x0c); - db(0x67); db(0xd2); db(0x0c); db(0x6c); db(0x00); db(0x26); db(0x00); db(0x12); + db(0x67); db(0x54); db(0x0c); db(0x6c); db(0x00); db(0x26); db(0x00); db(0x12); db(0x66); db(0x4c); db(0x0c); db(0xac); db(0x40); db(0x00); db(0x00); db(0x00); db(0x00); db(0x14); db(0x66); db(0x42); db(0x0c); db(0x6c); db(0x12); db(0x34); db(0x00); db(0x18); db(0x66); db(0x3a); db(0x20); db(0x6c); db(0x00); db(0x1a); @@ -365,318 +365,319 @@ db(0x00); db(0x0c); db(0x20); db(0x68); db(0x00); db(0x10); db(0x22); db(0x4c); db(0x12); db(0xbc); db(0x00); db(0x08); db(0x4e); db(0xae); db(0xfe); db(0x92); db(0x60); db(0x8a); db(0x22); db(0x4c); db(0x70); db(0x26); db(0x4e); db(0xae); - db(0xff); db(0x2e); db(0x60); db(0x00); db(0xff); db(0x80); db(0x26); db(0x2c); - db(0x00); db(0x0a); db(0x66); db(0x3e); db(0x30); db(0x3c); db(0xff); db(0x50); - db(0x61); db(0x00); db(0x01); db(0x06); db(0x70); db(0x01); db(0x4e); db(0x90); + db(0xff); db(0x2e); db(0x60); db(0x00); db(0xff); db(0x80); db(0x74); db(0xfe); + db(0x20); db(0x0c); db(0x67); db(0x14); db(0x26); db(0x2c); db(0x00); db(0x0a); + db(0x66); db(0x42); db(0x74); db(0xff); db(0x30); db(0x3c); db(0xff); db(0x50); + db(0x61); db(0x00); db(0x01); db(0x08); db(0x70); db(0x01); db(0x4e); db(0x90); db(0x45); db(0xeb); db(0x00); db(0x04); db(0x20); db(0x52); db(0x20); db(0x08); - db(0x67); db(0x00); db(0xff); db(0x62); db(0x22); db(0x50); db(0x20); db(0x40); - db(0x20); db(0x28); db(0x00); db(0x04); db(0x6a); db(0x16); db(0x48); db(0xe7); - db(0x00); db(0xc0); db(0x28); db(0x68); db(0x00); db(0x0a); db(0x61); db(0x4a); - db(0x53); db(0x85); db(0x4c); db(0xdf); db(0x03); db(0x00); db(0x24); db(0x89); - db(0x20); db(0x49); db(0x60); db(0xda); db(0x24); db(0x48); db(0x20); db(0x49); - db(0x60); db(0xd4); db(0x0c); db(0x85); db(0x00); db(0x00); db(0x00); db(0x14); - db(0x65); db(0x00); db(0x00); db(0x0a); db(0x70); db(0x01); db(0x29); db(0x40); - db(0x00); db(0x04); db(0x60); db(0x12); db(0x61); db(0x5c); db(0x30); db(0x3c); - db(0xff); db(0x30); db(0x61); db(0x00); db(0x00); db(0xb4); db(0x4e); db(0x90); - db(0x4a); db(0x80); db(0x67); db(0x0e); db(0x52); db(0x85); db(0x28); db(0xab); - db(0x00); db(0x04); db(0x27); db(0x4c); db(0x00); db(0x04); db(0x60); db(0x00); - db(0xff); db(0x0c); db(0x28); db(0x43); db(0x61); db(0x04); db(0x60); db(0x00); - db(0xff); db(0x04); db(0x0c); db(0xac); db(0x00); db(0x00); db(0x00); db(0x1f); - db(0x00); db(0x08); db(0x66); db(0x04); db(0x61); db(0x00); db(0xfb); db(0x4c); - db(0x0c); db(0xac); db(0x00); db(0x00); db(0x04); db(0x09); db(0x00); db(0x08); - db(0x66); db(0x12); db(0x61); db(0x00); db(0xfb); db(0x7a); db(0x66); db(0x0c); - db(0x30); db(0x3c); db(0xff); db(0x58); db(0x61); db(0x00); db(0x00); db(0x72); - db(0x4e); db(0x90); db(0x60); db(0xee); db(0x22); db(0x54); db(0x20); db(0x6c); - db(0x00); db(0x04); db(0x29); db(0x4d); db(0x00); db(0x04); db(0x4e); db(0xee); - db(0xfe); db(0x92); db(0x2f); db(0x05); db(0x7a); db(0xfc); db(0x24); db(0x53); - db(0x2e); db(0x0a); db(0x22); db(0x0a); db(0x67); db(0x00); db(0x00); db(0x0c); - db(0x52); db(0x85); db(0x67); db(0x1e); db(0x22); db(0x4a); db(0x24); db(0x52); - db(0x60); db(0xf0); db(0x52); db(0x85); db(0x67); db(0x3c); db(0x24); db(0x47); - db(0x70); db(0x18); db(0x72); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); - db(0x52); db(0x46); db(0x24); db(0x40); db(0x24); db(0x87); db(0x2e); db(0x0a); - db(0x60); db(0xe8); db(0x20); db(0x12); db(0x67); db(0x24); db(0x20); db(0x40); - db(0x20); db(0x10); db(0x67); db(0x1e); db(0x20); db(0x40); db(0x20); db(0x10); - db(0x67); db(0x18); db(0x70); db(0x00); db(0x22); db(0x80); db(0x22); db(0x4a); - db(0x24); db(0x51); db(0x70); db(0x18); db(0x4e); db(0xae); db(0xff); db(0x2e); - db(0x06); db(0x86); db(0x00); db(0x01); db(0x00); db(0x00); db(0x20); db(0x0a); - db(0x66); db(0xec); db(0x26); db(0x87); db(0x2a); db(0x1f); db(0x4e); db(0x75); - db(0x41); db(0xfa); db(0xf3); db(0x6a); db(0x02); db(0x80); db(0x00); db(0x00); - db(0xff); db(0xff); db(0xd1); db(0xc0); db(0x4e); db(0x75); db(0x20); db(0x88); - db(0x58); db(0x90); db(0x42); db(0xa8); db(0x00); db(0x04); db(0x21); db(0x48); - db(0x00); db(0x08); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x20); db(0x22); - db(0x2c); db(0x78); db(0x00); db(0x04); db(0x70); db(0xff); db(0x4e); db(0xae); - db(0xfe); db(0xb6); db(0x91); db(0xc8); db(0x24); db(0x00); db(0x6b); db(0x32); - db(0x70); db(0x22); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); - db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x91); db(0xc8); db(0x24); db(0x40); - db(0x4a); db(0x80); db(0x67); db(0x1e); db(0x15); db(0x7c); db(0x00); db(0x04); - db(0x00); db(0x08); db(0x15); db(0x42); db(0x00); db(0x0f); db(0x93); db(0xc9); - db(0x4e); db(0xae); db(0xfe); db(0xda); db(0x25); db(0x40); db(0x00); db(0x10); - db(0x41); db(0xea); db(0x00); db(0x14); db(0x61); db(0x00); db(0xff); db(0xb0); - db(0x20); db(0x4a); db(0x20); db(0x08); db(0x4c); db(0xdf); db(0x44); db(0x04); - db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x20); db(0x22); db(0x2c); db(0x78); - db(0x00); db(0x04); db(0x4a); db(0x80); db(0x67); db(0x24); db(0x24); db(0x40); - db(0x24); db(0x01); db(0x66); db(0x02); db(0x74); db(0x30); db(0x20); db(0x02); - db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); - db(0xff); db(0x3a); db(0x20); db(0x40); db(0x11); db(0x7c); db(0x00); db(0x0a); - db(0x00); db(0x08); db(0x31); db(0x42); db(0x00); db(0x12); db(0x21); db(0x4a); - db(0x00); db(0x0e); db(0x4a); db(0x80); db(0x4c); db(0xdf); db(0x44); db(0x04); - db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x30); db(0x22); db(0x24); db(0x48); - db(0x24); db(0x00); db(0x26); db(0x01); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x61); db(0x00); db(0xff); db(0x6a); db(0x22); db(0x03); db(0x61); db(0x00); - db(0xff); db(0xb2); db(0x67); db(0x18); db(0x20); db(0x4a); db(0x22); db(0x40); - db(0x24); db(0x40); db(0x20); db(0x02); db(0x72); db(0x00); db(0x4e); db(0xae); - db(0xfe); db(0x44); db(0x22); db(0x00); db(0x70); db(0x00); db(0x4a); db(0x81); - db(0x66); db(0x02); db(0x20); db(0x0a); db(0x4a); db(0x80); db(0x4c); db(0xdf); - db(0x44); db(0x0c); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x38); db(0x32); - db(0x2c); db(0x78); db(0x00); db(0x04); db(0x28); db(0x00); db(0x24); db(0x08); - db(0x26); db(0x09); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x08); db(0x5c); - db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); - db(0xff); db(0x3a); db(0x4a); db(0x80); db(0x67); db(0x00); db(0x00); db(0x34); - db(0x24); db(0x40); db(0x15); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x08); - db(0x15); db(0x44); db(0x00); db(0x09); db(0x25); db(0x42); db(0x00); db(0x0a); - db(0x47); db(0xea); db(0x00); db(0x5c); db(0x25); db(0x4b); db(0x00); db(0x3a); - db(0x47); db(0xeb); db(0x08); db(0x00); db(0x25); db(0x4b); db(0x00); db(0x3e); - db(0x25); db(0x4b); db(0x00); db(0x36); db(0x22); db(0x4a); db(0x24); db(0x43); - db(0x97); db(0xcb); db(0x24); db(0x09); db(0x4e); db(0xae); db(0xfe); db(0xe6); - db(0x20); db(0x02); db(0x4c); db(0xdf); db(0x4c); db(0x1c); db(0x4e); db(0x75); - db(0x41); db(0xfa); db(0x09); db(0x9e); db(0x43); db(0xfa); db(0x01); db(0x5c); - db(0x70); db(0x13); db(0x61); db(0x00); db(0xff); db(0x98); db(0x4e); db(0x75); - db(0x22); db(0x6d); db(0x02); db(0x0c); db(0x33); db(0x7c); db(0x00); db(0x0a); - db(0x00); db(0x1c); db(0x13); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x1e); - db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x22); db(0x6d); db(0x02); db(0x0c); - db(0x25); db(0x69); db(0x00); db(0x20); db(0x00); db(0x0e); db(0x25); db(0x69); - db(0x00); db(0x24); db(0x00); db(0x12); db(0x22); db(0x6d); db(0x02); db(0x08); - db(0x13); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x1e); db(0x4e); db(0xae); - db(0xfe); db(0x38); db(0x4e); db(0x75); db(0x42); db(0xaa); db(0x00); db(0x0e); - db(0x42); db(0xaa); db(0x00); db(0x12); db(0x22); db(0x6d); db(0x02); db(0x08); - db(0x13); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x1e); db(0x4e); db(0xae); - db(0xfe); db(0x38); db(0x4e); db(0x75); db(0x00); db(0x00); db(0xff); db(0xff); - db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); + db(0x67); db(0x00); db(0xff); db(0x5a); db(0x22); db(0x50); db(0x20); db(0x40); + db(0x20); db(0x28); db(0x00); db(0x04); db(0xb4); db(0x80); db(0x66); db(0x16); + db(0x48); db(0xe7); db(0x00); db(0xc0); db(0x28); db(0x68); db(0x00); db(0x0a); + db(0x61); db(0x4a); db(0x53); db(0x85); db(0x4c); db(0xdf); db(0x03); db(0x00); + db(0x24); db(0x89); db(0x20); db(0x49); db(0x60); db(0xd8); db(0x24); db(0x48); + db(0x20); db(0x49); db(0x60); db(0xd2); db(0x0c); db(0x85); db(0x00); db(0x00); + db(0x00); db(0x14); db(0x65); db(0x00); db(0x00); db(0x0a); db(0x70); db(0x01); + db(0x29); db(0x40); db(0x00); db(0x04); db(0x60); db(0x12); db(0x61); db(0x5c); + db(0x30); db(0x3c); db(0xff); db(0x30); db(0x61); db(0x00); db(0x00); db(0xb4); + db(0x4e); db(0x90); db(0x4a); db(0x80); db(0x67); db(0x0e); db(0x52); db(0x85); + db(0x28); db(0xab); db(0x00); db(0x04); db(0x27); db(0x4c); db(0x00); db(0x04); + db(0x60); db(0x00); db(0xff); db(0x02); db(0x28); db(0x43); db(0x61); db(0x04); + db(0x60); db(0x00); db(0xfe); db(0xfa); db(0x0c); db(0xac); db(0x00); db(0x00); + db(0x00); db(0x1f); db(0x00); db(0x08); db(0x66); db(0x04); db(0x61); db(0x00); + db(0xfb); db(0x42); db(0x0c); db(0xac); db(0x00); db(0x00); db(0x04); db(0x09); + db(0x00); db(0x08); db(0x66); db(0x12); db(0x61); db(0x00); db(0xfb); db(0x70); + db(0x66); db(0x0c); db(0x30); db(0x3c); db(0xff); db(0x58); db(0x61); db(0x00); + db(0x00); db(0x72); db(0x4e); db(0x90); db(0x60); db(0xee); db(0x22); db(0x54); + db(0x20); db(0x6c); db(0x00); db(0x04); db(0x29); db(0x4d); db(0x00); db(0x04); + db(0x4e); db(0xee); db(0xfe); db(0x92); db(0x2f); db(0x05); db(0x7a); db(0xfc); + db(0x24); db(0x53); db(0x2e); db(0x0a); db(0x22); db(0x0a); db(0x67); db(0x00); + db(0x00); db(0x0c); db(0x52); db(0x85); db(0x67); db(0x1e); db(0x22); db(0x4a); + db(0x24); db(0x52); db(0x60); db(0xf0); db(0x52); db(0x85); db(0x67); db(0x3c); + db(0x24); db(0x47); db(0x70); db(0x18); db(0x72); db(0x01); db(0x4e); db(0xae); + db(0xff); db(0x3a); db(0x52); db(0x46); db(0x24); db(0x40); db(0x24); db(0x87); + db(0x2e); db(0x0a); db(0x60); db(0xe8); db(0x20); db(0x12); db(0x67); db(0x24); + db(0x20); db(0x40); db(0x20); db(0x10); db(0x67); db(0x1e); db(0x20); db(0x40); + db(0x20); db(0x10); db(0x67); db(0x18); db(0x70); db(0x00); db(0x22); db(0x80); + db(0x22); db(0x4a); db(0x24); db(0x51); db(0x70); db(0x18); db(0x4e); db(0xae); + db(0xff); db(0x2e); db(0x06); db(0x86); db(0x00); db(0x01); db(0x00); db(0x00); + db(0x20); db(0x0a); db(0x66); db(0xec); db(0x26); db(0x87); db(0x2a); db(0x1f); + db(0x4e); db(0x75); db(0x41); db(0xfa); db(0xf3); db(0x60); db(0x02); db(0x80); + db(0x00); db(0x00); db(0xff); db(0xff); db(0xd1); db(0xc0); db(0x4e); db(0x75); + db(0x20); db(0x88); db(0x58); db(0x90); db(0x42); db(0xa8); db(0x00); db(0x04); + db(0x21); db(0x48); db(0x00); db(0x08); db(0x4e); db(0x75); db(0x48); db(0xe7); + db(0x20); db(0x22); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x70); db(0xff); + db(0x4e); db(0xae); db(0xfe); db(0xb6); db(0x91); db(0xc8); db(0x24); db(0x00); + db(0x6b); db(0x32); db(0x70); db(0x22); db(0x22); db(0x3c); db(0x00); db(0x01); + db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x91); db(0xc8); + db(0x24); db(0x40); db(0x4a); db(0x80); db(0x67); db(0x1e); db(0x15); db(0x7c); + db(0x00); db(0x04); db(0x00); db(0x08); db(0x15); db(0x42); db(0x00); db(0x0f); + db(0x93); db(0xc9); db(0x4e); db(0xae); db(0xfe); db(0xda); db(0x25); db(0x40); + db(0x00); db(0x10); db(0x41); db(0xea); db(0x00); db(0x14); db(0x61); db(0x00); + db(0xff); db(0xb0); db(0x20); db(0x4a); db(0x20); db(0x08); db(0x4c); db(0xdf); + db(0x44); db(0x04); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x20); db(0x22); + db(0x2c); db(0x78); db(0x00); db(0x04); db(0x4a); db(0x80); db(0x67); db(0x24); + db(0x24); db(0x40); db(0x24); db(0x01); db(0x66); db(0x02); db(0x74); db(0x30); + db(0x20); db(0x02); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); + db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x20); db(0x40); db(0x11); db(0x7c); + db(0x00); db(0x0a); db(0x00); db(0x08); db(0x31); db(0x42); db(0x00); db(0x12); + db(0x21); db(0x4a); db(0x00); db(0x0e); db(0x4a); db(0x80); db(0x4c); db(0xdf); + db(0x44); db(0x04); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x30); db(0x22); + db(0x24); db(0x48); db(0x24); db(0x00); db(0x26); db(0x01); db(0x2c); db(0x78); + db(0x00); db(0x04); db(0x61); db(0x00); db(0xff); db(0x6a); db(0x22); db(0x03); + db(0x61); db(0x00); db(0xff); db(0xb2); db(0x67); db(0x18); db(0x20); db(0x4a); + db(0x22); db(0x40); db(0x24); db(0x40); db(0x20); db(0x02); db(0x72); db(0x00); + db(0x4e); db(0xae); db(0xfe); db(0x44); db(0x22); db(0x00); db(0x70); db(0x00); + db(0x4a); db(0x81); db(0x66); db(0x02); db(0x20); db(0x0a); db(0x4a); db(0x80); + db(0x4c); db(0xdf); db(0x44); db(0x0c); db(0x4e); db(0x75); db(0x48); db(0xe7); + db(0x38); db(0x32); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x28); db(0x00); + db(0x24); db(0x08); db(0x26); db(0x09); db(0x20); db(0x3c); db(0x00); db(0x00); + db(0x08); db(0x5c); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); + db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x4a); db(0x80); db(0x67); db(0x00); + db(0x00); db(0x34); db(0x24); db(0x40); db(0x15); db(0x7c); db(0x00); db(0x01); + db(0x00); db(0x08); db(0x15); db(0x44); db(0x00); db(0x09); db(0x25); db(0x42); + db(0x00); db(0x0a); db(0x47); db(0xea); db(0x00); db(0x5c); db(0x25); db(0x4b); + db(0x00); db(0x3a); db(0x47); db(0xeb); db(0x08); db(0x00); db(0x25); db(0x4b); + db(0x00); db(0x3e); db(0x25); db(0x4b); db(0x00); db(0x36); db(0x22); db(0x4a); + db(0x24); db(0x43); db(0x97); db(0xcb); db(0x24); db(0x09); db(0x4e); db(0xae); + db(0xfe); db(0xe6); db(0x20); db(0x02); db(0x4c); db(0xdf); db(0x4c); db(0x1c); + db(0x4e); db(0x75); db(0x41); db(0xfa); db(0x09); db(0x9c); db(0x43); db(0xfa); + db(0x01); db(0x5c); db(0x70); db(0x13); db(0x61); db(0x00); db(0xff); db(0x98); + db(0x4e); db(0x75); db(0x22); db(0x6d); db(0x02); db(0x0c); db(0x33); db(0x7c); + db(0x00); db(0x0a); db(0x00); db(0x1c); db(0x13); db(0x7c); db(0x00); db(0x01); + db(0x00); db(0x1e); db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x22); db(0x6d); + db(0x02); db(0x0c); db(0x25); db(0x69); db(0x00); db(0x20); db(0x00); db(0x0e); + db(0x25); db(0x69); db(0x00); db(0x24); db(0x00); db(0x12); db(0x22); db(0x6d); + db(0x02); db(0x08); db(0x13); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x1e); + db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x4e); db(0x75); db(0x42); db(0xaa); + db(0x00); db(0x0e); db(0x42); db(0xaa); db(0x00); db(0x12); db(0x22); db(0x6d); + db(0x02); db(0x08); db(0x13); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x1e); + db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x4e); db(0x75); db(0x00); db(0x00); + db(0xff); db(0xff); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); - db(0x48); db(0xe7); db(0xf8); db(0xfe); db(0x2a); db(0x48); db(0x95); db(0xca); - db(0x97); db(0xcb); db(0x99); db(0xcc); db(0x78); db(0x00); db(0x2c); db(0x6d); - db(0x00); db(0x18); db(0x20); db(0x6d); db(0x00); db(0x14); db(0x20); db(0x28); - db(0x00); db(0x3c); db(0x67); db(0x5c); db(0x20); db(0x40); db(0x41); db(0xe8); - db(0x00); db(0x2c); db(0x28); db(0x48); db(0x4e); db(0xae); db(0xfc); db(0xe8); - db(0x72); db(0xff); db(0x74); db(0xff); db(0xb2); db(0x80); db(0x67); db(0x48); - db(0x26); db(0x00); db(0x2c); db(0x6d); db(0x00); db(0x14); db(0x41); db(0xed); - db(0x00); db(0xc0); db(0x70); db(0x66); db(0x4e); db(0xae); db(0xff); db(0x7c); - db(0x41); db(0xed); db(0x00); db(0xc0); db(0x38); db(0x28); db(0x00); db(0x64); - db(0x2c); db(0x6d); db(0x00); db(0x18); db(0x91); db(0xc8); db(0x43); db(0xed); - db(0x00); db(0x38); db(0x70); db(0x00); db(0x30); db(0x3c); db(0x00); db(0x58); - db(0x22); db(0x3c); db(0x80); db(0x00); db(0x10); db(0x00); db(0x24); db(0x03); - db(0x4e); db(0xae); db(0xfd); db(0x0c); db(0x72); db(0xff); db(0x74); db(0xff); - db(0x4a); db(0x80); db(0x6b); db(0x0c); db(0x45); db(0xed); db(0x00); db(0x38); - db(0x22); db(0x2a); db(0x00); db(0x32); db(0x24); db(0x2a); db(0x00); db(0x36); - db(0x20); db(0x2c); db(0x00); db(0x1c); db(0xb8); db(0x6d); db(0x00); db(0x2c); - db(0x66); db(0x12); db(0xb0); db(0xad); db(0x00); db(0x28); db(0x66); db(0x0c); - db(0xb2); db(0xad); db(0x00); db(0x20); db(0x66); db(0x06); db(0xb4); db(0xad); - db(0x00); db(0x24); db(0x67); db(0x40); db(0x2b); db(0x40); db(0x00); db(0x28); - db(0x2b); db(0x41); db(0x00); db(0x20); db(0x2b); db(0x42); db(0x00); db(0x24); - db(0x3b); db(0x44); db(0x00); db(0x2c); db(0x91); db(0xc8); db(0x43); db(0xed); - db(0x00); db(0x90); db(0x70); db(0x00); db(0x30); db(0x3c); db(0x00); db(0x58); - db(0x22); db(0x3c); db(0x80); db(0x00); db(0x00); db(0x00); db(0x24); db(0x03); - db(0x4e); db(0xae); db(0xfd); db(0x0c); db(0x4a); db(0x80); db(0x6b); db(0x04); - db(0x47); db(0xed); db(0x00); db(0x90); db(0x34); db(0x2d); db(0x00); db(0x2c); - db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x01); db(0x61); db(0x00); - db(0xfd); db(0x70); db(0x4e); db(0x90); db(0x4c); db(0xdf); db(0x7f); db(0x1f); - db(0x4e); db(0x75); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x3e); db(0x2e); - db(0x00); db(0x14); db(0x70); db(0xff); db(0x4e); db(0xae); db(0xfe); db(0xb6); - db(0x7c); db(0x00); db(0x01); db(0xc6); db(0x93); db(0xc9); db(0x4e); db(0xae); - db(0xfe); db(0xda); db(0x28); db(0x40); db(0x70); db(0x14); db(0x22); db(0x4c); - db(0x4e); db(0xae); db(0xfe); db(0xd4); db(0x70); db(0x00); db(0x30); db(0x3c); - db(0x02); db(0x10); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); - db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x2a); db(0x40); db(0x47); db(0xed); - db(0x00); db(0x16); db(0x27); db(0x4e); db(0x00); db(0x10); db(0x27); db(0x4c); - db(0x00); db(0x08); db(0x27); db(0x46); db(0x00); db(0x0c); db(0x70); db(0xff); - db(0x37); db(0x40); db(0x00); db(0x00); db(0x43); db(0xed); db(0x00); db(0x00); - db(0x13); db(0x7c); db(0x00); db(0x02); db(0x00); db(0x08); db(0x13); db(0x7c); - db(0x00); db(0x05); db(0x00); db(0x09); db(0x41); db(0xfa); db(0x07); db(0xe2); - db(0x23); db(0x48); db(0x00); db(0x0a); db(0x41); db(0xfa); db(0x02); db(0xda); - db(0x23); db(0x48); db(0x00); db(0x12); db(0x23); db(0x4d); db(0x00); db(0x0e); - db(0x70); db(0x05); db(0x4e); db(0xae); db(0xff); db(0x58); db(0x20); db(0x06); - db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x70); db(0x00); db(0x53); db(0xab); - db(0x00); db(0x1c); db(0x6a); db(0x06); db(0x70); db(0x0a); db(0x27); db(0x40); - db(0x00); db(0x1c); db(0x4a); db(0xab); db(0x00); db(0x14); db(0x66); db(0x16); - db(0x4a); db(0xab); db(0x00); db(0x1c); db(0x66); db(0xe0); db(0x43); db(0xfa); - db(0x08); db(0x00); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); - db(0x27); db(0x40); db(0x00); db(0x14); db(0x67); db(0xd0); db(0x4a); db(0xab); - db(0x00); db(0x18); db(0x66); db(0x18); db(0x4a); db(0xab); db(0x00); db(0x1c); - db(0x66); db(0xc4); db(0x43); db(0xfa); db(0x07); db(0xf6); db(0x70); db(0x00); - db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x27); db(0x40); db(0x00); db(0x18); - db(0x67); db(0x00); db(0xff); db(0xb4); db(0x4a); db(0xad); db(0x02); db(0x08); - db(0x66); db(0x38); db(0x4a); db(0xab); db(0x00); db(0x1c); db(0x66); db(0xa6); - db(0x4e); db(0xae); db(0xff); db(0x7c); db(0x41); db(0xee); db(0x01); db(0x5e); - db(0x43); db(0xfa); db(0x06); db(0xd6); db(0x4e); db(0xae); db(0xfe); db(0xec); - db(0x24); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x76); db(0x4a); db(0x82); - db(0x67); db(0x8c); db(0x41); db(0xfa); db(0x06); db(0xc4); db(0x70); db(0x00); - db(0x72); db(0x00); db(0x61); db(0x00); db(0xfd); db(0x16); db(0x2b); db(0x40); - db(0x02); db(0x08); db(0x67); db(0x00); db(0x02); db(0x42); db(0x60); db(0x00); - db(0xff); db(0x76); db(0x4a); db(0xad); db(0x02); db(0x0c); db(0x66); db(0x48); - db(0x4a); db(0xab); db(0x00); db(0x1c); db(0x66); db(0x00); db(0xff); db(0x68); - db(0x4e); db(0xae); db(0xff); db(0x7c); db(0x41); db(0xee); db(0x01); db(0x5e); - db(0x43); db(0xfa); db(0x06); db(0xa3); db(0x4e); db(0xae); db(0xfe); db(0xec); - db(0x24); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x76); db(0x4a); db(0x82); - db(0x67); db(0x00); db(0xff); db(0x4c); db(0x41); db(0xfa); db(0x06); db(0x8f); - db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0xfc); db(0xd4); - db(0x2b); db(0x40); db(0x02); db(0x0c); db(0x67); db(0x00); db(0x02); db(0x00); - db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x00); db(0x61); db(0x00); - db(0xfc); db(0x20); db(0x4e); db(0x90); db(0x60); db(0x00); db(0xff); db(0x28); - db(0x0c); db(0x47); db(0x00); db(0x24); db(0x65); db(0x12); db(0x53); db(0xab); - db(0x00); db(0x34); db(0x6a); db(0x0c); db(0x20); db(0x4b); db(0x61); db(0x00); - db(0xfd); db(0xc8); db(0x70); db(0x32); db(0x27); db(0x40); db(0x00); db(0x34); - db(0x22); db(0x6d); db(0x02); db(0x08); db(0x45); db(0xed); db(0x01); db(0x3c); - db(0x33); db(0x7c); db(0x00); db(0x0b); db(0x00); db(0x1c); db(0x23); db(0x7c); - db(0x00); db(0x00); db(0x00); db(0x16); db(0x00); db(0x24); db(0x23); db(0x4a); - db(0x00); db(0x28); db(0x10); db(0x3a); db(0xfd); db(0x78); db(0x0c); db(0x47); - db(0x00); db(0x27); db(0x65); db(0x00); db(0x01); db(0x62); db(0x08); db(0x00); - db(0x00); db(0x01); db(0x67); db(0x00); db(0x01); db(0x5a); db(0x41); db(0xed); - db(0x01); db(0x68); db(0x25); db(0x48); db(0x00); db(0x0a); db(0x15); db(0x7c); - db(0x00); db(0x13); db(0x00); db(0x04); db(0x15); db(0x7c); db(0x00); db(0x03); - db(0x00); db(0x05); db(0x42); db(0x90); db(0x42); db(0xa8); db(0x00); db(0x04); - db(0x42); db(0x6a); db(0x00); db(0x06); db(0x42); db(0xa8); db(0x00); db(0x08); - db(0x42); db(0x68); db(0x00); db(0x0c); db(0x22); db(0x3a); db(0xfd); db(0x60); - db(0x02); db(0x41); db(0x00); db(0x07); db(0x70); db(0x07); db(0x90); db(0x41); - db(0xe1); db(0x48); db(0xe9); db(0x48); db(0x35); db(0x40); db(0x00); db(0x08); - db(0x31); db(0x7a); db(0xfd); db(0x34); db(0x00); db(0x0e); db(0x42); db(0x68); - db(0x00); db(0x10); db(0x31); db(0x7a); db(0xfd); db(0x2c); db(0x00); db(0x12); - db(0x42); db(0x68); db(0x00); db(0x14); db(0x31); db(0x7a); db(0xfd); db(0x1a); - db(0x00); db(0x16); db(0x42); db(0x68); db(0x00); db(0x18); db(0x31); db(0x7a); - db(0xfd); db(0x12); db(0x00); db(0x1a); db(0x43); db(0xed); db(0x01); db(0x88); - db(0x21); db(0x49); db(0x00); db(0x1c); db(0x22); db(0xfc); db(0x80); db(0x03); - db(0xa0); db(0x06); db(0x30); db(0x3a); db(0xfd); db(0x18); db(0x48); db(0xc0); - db(0xe1); db(0x80); db(0x22); db(0xc0); db(0x22); db(0xfc); db(0x80); db(0x03); - db(0xa0); db(0x07); db(0x22); db(0xfa); db(0xfd); db(0x0a); db(0x70); db(0x00); - db(0x30); db(0x3a); db(0xfc); db(0xf2); db(0x6b); db(0x08); db(0x22); db(0xfc); - db(0x80); db(0x03); db(0xa0); db(0x09); db(0x22); db(0xc0); db(0x30); db(0x3a); - db(0xfc); db(0xe6); db(0x6b); db(0x08); db(0x22); db(0xfc); db(0x80); db(0x03); - db(0xa0); db(0x0a); db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0xce); - db(0x6b); db(0x14); db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x02); - db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0xc6); db(0x22); db(0xfc); - db(0x80); db(0x03); db(0xa0); db(0x01); db(0x22); db(0xc0); db(0x30); db(0x3a); - db(0xfc); db(0xc0); db(0x6b); db(0x10); db(0x22); db(0xfc); db(0x80); db(0x03); - db(0xa0); db(0x03); db(0x30); db(0x3a); db(0xfc); db(0xba); db(0x48); db(0xc0); - db(0xe1); db(0x80); db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0xac); - db(0x6b); db(0x10); db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x04); - db(0x30); db(0x3a); db(0xfc); db(0xa6); db(0x48); db(0xc0); db(0xe1); db(0x80); - db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0x98); db(0x6b); db(0x10); - db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x05); db(0x30); db(0x3a); - db(0xfc); db(0x92); db(0x48); db(0xc0); db(0xe1); db(0x80); db(0x22); db(0xc0); - db(0x70); db(0x00); db(0x30); db(0x3a); db(0xfc); db(0x8e); db(0x6b); db(0x08); - db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x08); db(0x22); db(0xc0); - db(0x42); db(0x91); db(0x61); db(0x00); db(0xfc); db(0x40); db(0x36); db(0x3c); - db(0x00); db(0x68); db(0x74); db(0x01); db(0x28); db(0x3a); db(0xfc); db(0x70); - db(0x20); db(0x04); db(0xc0); db(0x82); db(0x22); db(0x2b); db(0x00); db(0x04); - db(0xc2); db(0x82); db(0xb2); db(0x80); db(0x67); db(0x22); db(0x42); db(0x92); - db(0x35); db(0x7c); db(0x02); db(0x00); db(0x00); db(0x04); db(0x42); db(0xaa); - db(0x00); db(0x0a); db(0x32); db(0x03); db(0x4a); db(0x00); db(0x66); db(0x04); - db(0x08); db(0xc1); db(0x00); db(0x07); db(0x35); db(0x41); db(0x00); db(0x06); - db(0x42); db(0x6a); db(0x00); db(0x08); db(0x61); db(0x00); db(0xfc); db(0x06); - db(0x52); db(0x43); db(0xd4); db(0x42); db(0x0c); db(0x42); db(0x00); db(0x08); - db(0x66); db(0xc6); db(0x27); db(0x44); db(0x00); db(0x04); db(0x10); db(0x3a); - db(0xfc); db(0x0c); db(0x08); db(0x00); db(0x00); db(0x00); db(0x67); db(0x00); - db(0xfd); db(0x7e); db(0x42); db(0x92); db(0x35); db(0x7c); db(0x04); db(0x00); - db(0x00); db(0x04); db(0x42); db(0x6a); db(0x00); db(0x06); db(0x42); db(0x6a); - db(0x00); db(0x08); db(0x20); db(0x6b); db(0x00); db(0x14); db(0x30); db(0x3a); - db(0xfc); db(0x14); db(0x32); db(0x28); db(0x00); db(0x30); db(0xd2); db(0x41); - db(0x90); db(0x41); db(0x6a); db(0x02); db(0x70); db(0x00); db(0x35); db(0x40); - db(0x00); db(0x0a); db(0x30); db(0x3a); db(0xfc); db(0x02); db(0x32); db(0x28); - db(0x00); db(0x2e); db(0xd2); db(0x41); db(0x90); db(0x41); db(0x6a); db(0x02); - db(0x70); db(0x00); db(0x35); db(0x40); db(0x00); db(0x0c); db(0x61); db(0x00); - db(0xfb); db(0x78); db(0x60); db(0x00); db(0xfd); db(0x3a); db(0x4e); db(0x75); - db(0x4a); db(0xa9); db(0x02); db(0x08); db(0x67); db(0x14); db(0x4a); db(0xa9); - db(0x02); db(0x0c); db(0x67); db(0x0e); db(0x30); db(0x3a); db(0xfb); db(0xb0); - db(0xb0); db(0x69); db(0x00); db(0x16); db(0x67); db(0x14); db(0x33); db(0x40); - db(0x00); db(0x16); db(0x2c); db(0x69); db(0x00); db(0x26); db(0x20); db(0x29); - db(0x00); db(0x22); db(0x22); db(0x69); db(0x00); db(0x1e); db(0x4e); db(0xae); - db(0xfe); db(0xbc); db(0x53); db(0x69); db(0x00); db(0x46); db(0x6a); db(0x12); - db(0x33); db(0x7c); db(0x00); db(0x32); db(0x00); db(0x46); db(0x30); db(0x3c); - db(0xff); db(0x38); db(0x72); db(0x02); db(0x61); db(0x00); db(0xf9); db(0xea); - db(0x4e); db(0x90); db(0x41); db(0xf9); db(0x00); db(0xdf); db(0xf0); db(0x00); - db(0x70); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x00); db(0x06); - db(0x2c); db(0x78); db(0x00); db(0x04); db(0x20); db(0x3c); db(0x00); db(0x00); - db(0x00); db(0x88); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); - db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x4a); db(0x80); db(0x67); db(0x00); - db(0x00); db(0x40); db(0x2a); db(0x40); db(0x2b); db(0x4e); db(0x00); db(0x14); - db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x0e); db(0x61); db(0x00); - db(0xf9); db(0xb0); db(0x20); db(0x0d); db(0x4e); db(0x90); db(0x41); db(0xfa); - db(0x04); db(0x6a); db(0x43); db(0xfa); db(0x01); db(0x14); db(0x70); db(0xf6); - db(0x22); db(0x3c); db(0x00); db(0x00); db(0x27); db(0x10); db(0x61); db(0x00); - db(0xee); db(0xe6); db(0x70); db(0x00); db(0x4c); db(0xdf); db(0x60); db(0x00); - db(0x4e); db(0x75); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x0a); - db(0x61); db(0x00); db(0xf9); db(0x86); db(0x4e); db(0x90); db(0x4e); db(0x75); - db(0x61); db(0xf0); db(0x20); db(0x0d); db(0x67); db(0x1c); db(0x2c); db(0x6d); - db(0x00); db(0x14); db(0x20); db(0x2d); db(0x00); db(0x18); db(0x67); db(0x06); - db(0x22); db(0x40); db(0x4e); db(0xae); db(0xfe); db(0x62); db(0x22); db(0x4d); - db(0x20); db(0x3c); db(0x00); db(0x00); db(0x00); db(0x88); db(0x4e); db(0xae); - db(0xff); db(0x2e); db(0x70); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); - db(0x38); db(0x3e); db(0x2c); db(0x6d); db(0x00); db(0x18); db(0x41); db(0xfa); - db(0x03); db(0xf8); db(0x22); db(0x08); db(0x24); db(0x3c); db(0x00); db(0x00); - db(0x03); db(0xed); db(0x4e); db(0xae); db(0xff); db(0xe2); db(0x28); db(0x00); - db(0x67); db(0x4c); db(0x45); db(0xed); db(0x00); db(0x68); db(0x42); db(0x92); - db(0x34); db(0xaa); db(0x00); db(0x02); db(0x24); db(0x0a); db(0x54); db(0x82); - db(0x76); db(0x02); db(0x22); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xd6); - db(0xb6); db(0x80); db(0x66); db(0x32); db(0x0c); db(0x92); db(0x50); db(0x4e); - db(0x54); db(0x52); db(0x66); db(0xe4); db(0x24); db(0x0a); db(0x76); db(0x04); - db(0x22); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xd6); db(0x24); db(0x0a); - db(0x76); db(0x20); db(0x22); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xd6); - db(0xb6); db(0x80); db(0x66); db(0x12); db(0x4a); db(0x6a); db(0x00); db(0x10); - db(0x66); db(0xc4); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x10); - db(0x61); db(0x00); db(0xf8); db(0xf6); db(0x4e); db(0x90); db(0x22); db(0x04); - db(0x67); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xdc); db(0x4c); db(0xdf); - db(0x7c); db(0x1c); db(0x4e); db(0x75); db(0x2c); db(0x6d); db(0x00); db(0x18); - db(0x41); db(0xfa); db(0x03); db(0x70); db(0x22); db(0x08); db(0x74); db(0xfe); - db(0x4e); db(0xae); db(0xff); db(0xac); db(0x22); db(0x00); db(0x67); db(0x34); - db(0x4e); db(0xae); db(0xff); db(0xa6); db(0x2c); db(0x6d); db(0x00); db(0x14); - db(0x45); db(0xed); db(0x00); db(0x38); db(0x70); db(0xff); db(0x4e); db(0xae); - db(0xfe); db(0xb6); db(0x15); db(0x40); db(0x00); db(0x14); db(0x41); db(0xfa); - db(0x03); db(0x60); db(0x24); db(0x88); db(0x25); db(0x7c); db(0x00); db(0x00); - db(0x00); db(0x12); db(0x00); db(0x0c); db(0x25); db(0x6d); db(0x00); db(0x08); - db(0x00); db(0x10); db(0x2c); db(0x6d); db(0x00); db(0x18); db(0x22); db(0x0a); - db(0x4e); db(0xae); db(0xfc); db(0x88); db(0x2c); db(0x6d); db(0x00); db(0x14); - db(0x4e); db(0x75); db(0x00); db(0x00); db(0x00); db(0x00); db(0x00); db(0x10); + db(0x00); db(0x00); db(0x48); db(0xe7); db(0xf8); db(0xfe); db(0x2a); db(0x48); + db(0x95); db(0xca); db(0x97); db(0xcb); db(0x99); db(0xcc); db(0x78); db(0x00); + db(0x2c); db(0x6d); db(0x00); db(0x18); db(0x20); db(0x6d); db(0x00); db(0x14); + db(0x20); db(0x28); db(0x00); db(0x3c); db(0x67); db(0x5c); db(0x20); db(0x40); + db(0x41); db(0xe8); db(0x00); db(0x2c); db(0x28); db(0x48); db(0x4e); db(0xae); + db(0xfc); db(0xe8); db(0x72); db(0xff); db(0x74); db(0xff); db(0xb2); db(0x80); + db(0x67); db(0x48); db(0x26); db(0x00); db(0x2c); db(0x6d); db(0x00); db(0x14); + db(0x41); db(0xed); db(0x00); db(0xc0); db(0x70); db(0x66); db(0x4e); db(0xae); + db(0xff); db(0x7c); db(0x41); db(0xed); db(0x00); db(0xc0); db(0x38); db(0x28); + db(0x00); db(0x64); db(0x2c); db(0x6d); db(0x00); db(0x18); db(0x91); db(0xc8); + db(0x43); db(0xed); db(0x00); db(0x38); db(0x70); db(0x00); db(0x30); db(0x3c); + db(0x00); db(0x58); db(0x22); db(0x3c); db(0x80); db(0x00); db(0x10); db(0x00); + db(0x24); db(0x03); db(0x4e); db(0xae); db(0xfd); db(0x0c); db(0x72); db(0xff); + db(0x74); db(0xff); db(0x4a); db(0x80); db(0x6b); db(0x0c); db(0x45); db(0xed); + db(0x00); db(0x38); db(0x22); db(0x2a); db(0x00); db(0x32); db(0x24); db(0x2a); + db(0x00); db(0x36); db(0x20); db(0x2c); db(0x00); db(0x1c); db(0xb8); db(0x6d); + db(0x00); db(0x2c); db(0x66); db(0x12); db(0xb0); db(0xad); db(0x00); db(0x28); + db(0x66); db(0x0c); db(0xb2); db(0xad); db(0x00); db(0x20); db(0x66); db(0x06); + db(0xb4); db(0xad); db(0x00); db(0x24); db(0x67); db(0x40); db(0x2b); db(0x40); + db(0x00); db(0x28); db(0x2b); db(0x41); db(0x00); db(0x20); db(0x2b); db(0x42); + db(0x00); db(0x24); db(0x3b); db(0x44); db(0x00); db(0x2c); db(0x91); db(0xc8); + db(0x43); db(0xed); db(0x00); db(0x90); db(0x70); db(0x00); db(0x30); db(0x3c); + db(0x00); db(0x58); db(0x22); db(0x3c); db(0x80); db(0x00); db(0x00); db(0x00); + db(0x24); db(0x03); db(0x4e); db(0xae); db(0xfd); db(0x0c); db(0x4a); db(0x80); + db(0x6b); db(0x04); db(0x47); db(0xed); db(0x00); db(0x90); db(0x34); db(0x2d); + db(0x00); db(0x2c); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x01); + db(0x61); db(0x00); db(0xfd); db(0x70); db(0x4e); db(0x90); db(0x4c); db(0xdf); + db(0x7f); db(0x1f); db(0x4e); db(0x75); db(0x2c); db(0x78); db(0x00); db(0x04); + db(0x3e); db(0x2e); db(0x00); db(0x14); db(0x70); db(0xff); db(0x4e); db(0xae); + db(0xfe); db(0xb6); db(0x7c); db(0x00); db(0x01); db(0xc6); db(0x93); db(0xc9); + db(0x4e); db(0xae); db(0xfe); db(0xda); db(0x28); db(0x40); db(0x70); db(0x14); + db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0xd4); db(0x70); db(0x00); + db(0x30); db(0x3c); db(0x02); db(0x10); db(0x22); db(0x3c); db(0x00); db(0x01); + db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x2a); db(0x40); + db(0x47); db(0xed); db(0x00); db(0x16); db(0x27); db(0x4e); db(0x00); db(0x10); + db(0x27); db(0x4c); db(0x00); db(0x08); db(0x27); db(0x46); db(0x00); db(0x0c); + db(0x70); db(0xff); db(0x37); db(0x40); db(0x00); db(0x00); db(0x43); db(0xed); + db(0x00); db(0x00); db(0x13); db(0x7c); db(0x00); db(0x02); db(0x00); db(0x08); + db(0x13); db(0x7c); db(0x00); db(0x05); db(0x00); db(0x09); db(0x41); db(0xfa); + db(0x07); db(0xe0); db(0x23); db(0x48); db(0x00); db(0x0a); db(0x41); db(0xfa); + db(0x02); db(0xda); db(0x23); db(0x48); db(0x00); db(0x12); db(0x23); db(0x4d); + db(0x00); db(0x0e); db(0x70); db(0x05); db(0x4e); db(0xae); db(0xff); db(0x58); + db(0x20); db(0x06); db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x70); db(0x00); + db(0x53); db(0xab); db(0x00); db(0x1c); db(0x6a); db(0x06); db(0x70); db(0x0a); + db(0x27); db(0x40); db(0x00); db(0x1c); db(0x4a); db(0xab); db(0x00); db(0x14); + db(0x66); db(0x16); db(0x4a); db(0xab); db(0x00); db(0x1c); db(0x66); db(0xe0); + db(0x43); db(0xfa); db(0x07); db(0xfe); db(0x70); db(0x00); db(0x4e); db(0xae); + db(0xfd); db(0xd8); db(0x27); db(0x40); db(0x00); db(0x14); db(0x67); db(0xd0); + db(0x4a); db(0xab); db(0x00); db(0x18); db(0x66); db(0x18); db(0x4a); db(0xab); + db(0x00); db(0x1c); db(0x66); db(0xc4); db(0x43); db(0xfa); db(0x07); db(0xf4); + db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x27); db(0x40); + db(0x00); db(0x18); db(0x67); db(0x00); db(0xff); db(0xb4); db(0x4a); db(0xad); + db(0x02); db(0x08); db(0x66); db(0x38); db(0x4a); db(0xab); db(0x00); db(0x1c); + db(0x66); db(0xa6); db(0x4e); db(0xae); db(0xff); db(0x7c); db(0x41); db(0xee); + db(0x01); db(0x5e); db(0x43); db(0xfa); db(0x06); db(0xd4); db(0x4e); db(0xae); + db(0xfe); db(0xec); db(0x24); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x76); + db(0x4a); db(0x82); db(0x67); db(0x8c); db(0x41); db(0xfa); db(0x06); db(0xc2); + db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); db(0xfd); db(0x16); + db(0x2b); db(0x40); db(0x02); db(0x08); db(0x67); db(0x00); db(0x02); db(0x42); + db(0x60); db(0x00); db(0xff); db(0x76); db(0x4a); db(0xad); db(0x02); db(0x0c); + db(0x66); db(0x48); db(0x4a); db(0xab); db(0x00); db(0x1c); db(0x66); db(0x00); + db(0xff); db(0x68); db(0x4e); db(0xae); db(0xff); db(0x7c); db(0x41); db(0xee); + db(0x01); db(0x5e); db(0x43); db(0xfa); db(0x06); db(0xa1); db(0x4e); db(0xae); + db(0xfe); db(0xec); db(0x24); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x76); + db(0x4a); db(0x82); db(0x67); db(0x00); db(0xff); db(0x4c); db(0x41); db(0xfa); + db(0x06); db(0x8d); db(0x70); db(0x00); db(0x72); db(0x00); db(0x61); db(0x00); + db(0xfc); db(0xd4); db(0x2b); db(0x40); db(0x02); db(0x0c); db(0x67); db(0x00); + db(0x02); db(0x00); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x00); + db(0x61); db(0x00); db(0xfc); db(0x20); db(0x4e); db(0x90); db(0x60); db(0x00); + db(0xff); db(0x28); db(0x0c); db(0x47); db(0x00); db(0x24); db(0x65); db(0x12); + db(0x53); db(0xab); db(0x00); db(0x34); db(0x6a); db(0x0c); db(0x20); db(0x4b); + db(0x61); db(0x00); db(0xfd); db(0xc8); db(0x70); db(0x32); db(0x27); db(0x40); + db(0x00); db(0x34); db(0x22); db(0x6d); db(0x02); db(0x08); db(0x45); db(0xed); + db(0x01); db(0x3c); db(0x33); db(0x7c); db(0x00); db(0x0b); db(0x00); db(0x1c); + db(0x23); db(0x7c); db(0x00); db(0x00); db(0x00); db(0x16); db(0x00); db(0x24); + db(0x23); db(0x4a); db(0x00); db(0x28); db(0x10); db(0x3a); db(0xfd); db(0x78); + db(0x0c); db(0x47); db(0x00); db(0x27); db(0x65); db(0x00); db(0x01); db(0x62); + db(0x08); db(0x00); db(0x00); db(0x01); db(0x67); db(0x00); db(0x01); db(0x5a); + db(0x41); db(0xed); db(0x01); db(0x68); db(0x25); db(0x48); db(0x00); db(0x0a); + db(0x15); db(0x7c); db(0x00); db(0x13); db(0x00); db(0x04); db(0x15); db(0x7c); + db(0x00); db(0x03); db(0x00); db(0x05); db(0x42); db(0x90); db(0x42); db(0xa8); + db(0x00); db(0x04); db(0x42); db(0x6a); db(0x00); db(0x06); db(0x42); db(0xa8); + db(0x00); db(0x08); db(0x42); db(0x68); db(0x00); db(0x0c); db(0x22); db(0x3a); + db(0xfd); db(0x60); db(0x02); db(0x41); db(0x00); db(0x07); db(0x70); db(0x07); + db(0x90); db(0x41); db(0xe1); db(0x48); db(0xe9); db(0x48); db(0x35); db(0x40); + db(0x00); db(0x08); db(0x31); db(0x7a); db(0xfd); db(0x34); db(0x00); db(0x0e); + db(0x42); db(0x68); db(0x00); db(0x10); db(0x31); db(0x7a); db(0xfd); db(0x2c); + db(0x00); db(0x12); db(0x42); db(0x68); db(0x00); db(0x14); db(0x31); db(0x7a); + db(0xfd); db(0x1a); db(0x00); db(0x16); db(0x42); db(0x68); db(0x00); db(0x18); + db(0x31); db(0x7a); db(0xfd); db(0x12); db(0x00); db(0x1a); db(0x43); db(0xed); + db(0x01); db(0x88); db(0x21); db(0x49); db(0x00); db(0x1c); db(0x22); db(0xfc); + db(0x80); db(0x03); db(0xa0); db(0x06); db(0x30); db(0x3a); db(0xfd); db(0x18); + db(0x48); db(0xc0); db(0xe1); db(0x80); db(0x22); db(0xc0); db(0x22); db(0xfc); + db(0x80); db(0x03); db(0xa0); db(0x07); db(0x22); db(0xfa); db(0xfd); db(0x0a); + db(0x70); db(0x00); db(0x30); db(0x3a); db(0xfc); db(0xf2); db(0x6b); db(0x08); + db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x09); db(0x22); db(0xc0); + db(0x30); db(0x3a); db(0xfc); db(0xe6); db(0x6b); db(0x08); db(0x22); db(0xfc); + db(0x80); db(0x03); db(0xa0); db(0x0a); db(0x22); db(0xc0); db(0x30); db(0x3a); + db(0xfc); db(0xce); db(0x6b); db(0x14); db(0x22); db(0xfc); db(0x80); db(0x03); + db(0xa0); db(0x02); db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0xc6); + db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x01); db(0x22); db(0xc0); + db(0x30); db(0x3a); db(0xfc); db(0xc0); db(0x6b); db(0x10); db(0x22); db(0xfc); + db(0x80); db(0x03); db(0xa0); db(0x03); db(0x30); db(0x3a); db(0xfc); db(0xba); + db(0x48); db(0xc0); db(0xe1); db(0x80); db(0x22); db(0xc0); db(0x30); db(0x3a); + db(0xfc); db(0xac); db(0x6b); db(0x10); db(0x22); db(0xfc); db(0x80); db(0x03); + db(0xa0); db(0x04); db(0x30); db(0x3a); db(0xfc); db(0xa6); db(0x48); db(0xc0); + db(0xe1); db(0x80); db(0x22); db(0xc0); db(0x30); db(0x3a); db(0xfc); db(0x98); + db(0x6b); db(0x10); db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x05); + db(0x30); db(0x3a); db(0xfc); db(0x92); db(0x48); db(0xc0); db(0xe1); db(0x80); + db(0x22); db(0xc0); db(0x70); db(0x00); db(0x30); db(0x3a); db(0xfc); db(0x8e); + db(0x6b); db(0x08); db(0x22); db(0xfc); db(0x80); db(0x03); db(0xa0); db(0x08); + db(0x22); db(0xc0); db(0x42); db(0x91); db(0x61); db(0x00); db(0xfc); db(0x40); + db(0x36); db(0x3c); db(0x00); db(0x68); db(0x74); db(0x01); db(0x28); db(0x3a); + db(0xfc); db(0x70); db(0x20); db(0x04); db(0xc0); db(0x82); db(0x22); db(0x2b); + db(0x00); db(0x04); db(0xc2); db(0x82); db(0xb2); db(0x80); db(0x67); db(0x22); + db(0x42); db(0x92); db(0x35); db(0x7c); db(0x02); db(0x00); db(0x00); db(0x04); + db(0x42); db(0xaa); db(0x00); db(0x0a); db(0x32); db(0x03); db(0x4a); db(0x00); + db(0x66); db(0x04); db(0x08); db(0xc1); db(0x00); db(0x07); db(0x35); db(0x41); + db(0x00); db(0x06); db(0x42); db(0x6a); db(0x00); db(0x08); db(0x61); db(0x00); + db(0xfc); db(0x06); db(0x52); db(0x43); db(0xd4); db(0x42); db(0x0c); db(0x42); + db(0x00); db(0x08); db(0x66); db(0xc6); db(0x27); db(0x44); db(0x00); db(0x04); + db(0x10); db(0x3a); db(0xfc); db(0x0c); db(0x08); db(0x00); db(0x00); db(0x00); + db(0x67); db(0x00); db(0xfd); db(0x7e); db(0x42); db(0x92); db(0x35); db(0x7c); + db(0x04); db(0x00); db(0x00); db(0x04); db(0x42); db(0x6a); db(0x00); db(0x06); + db(0x42); db(0x6a); db(0x00); db(0x08); db(0x20); db(0x6b); db(0x00); db(0x14); + db(0x30); db(0x3a); db(0xfc); db(0x14); db(0x32); db(0x28); db(0x00); db(0x30); + db(0xd2); db(0x41); db(0x90); db(0x41); db(0x6a); db(0x02); db(0x70); db(0x00); + db(0x35); db(0x40); db(0x00); db(0x0a); db(0x30); db(0x3a); db(0xfc); db(0x02); + db(0x32); db(0x28); db(0x00); db(0x2e); db(0xd2); db(0x41); db(0x90); db(0x41); + db(0x6a); db(0x02); db(0x70); db(0x00); db(0x35); db(0x40); db(0x00); db(0x0c); + db(0x61); db(0x00); db(0xfb); db(0x78); db(0x60); db(0x00); db(0xfd); db(0x3a); + db(0x4e); db(0x75); db(0x4a); db(0xa9); db(0x02); db(0x08); db(0x67); db(0x14); + db(0x4a); db(0xa9); db(0x02); db(0x0c); db(0x67); db(0x0e); db(0x30); db(0x3a); + db(0xfb); db(0xb0); db(0xb0); db(0x69); db(0x00); db(0x16); db(0x67); db(0x14); + db(0x33); db(0x40); db(0x00); db(0x16); db(0x2c); db(0x69); db(0x00); db(0x26); + db(0x20); db(0x29); db(0x00); db(0x22); db(0x22); db(0x69); db(0x00); db(0x1e); + db(0x4e); db(0xae); db(0xfe); db(0xbc); db(0x53); db(0x69); db(0x00); db(0x46); + db(0x6a); db(0x12); db(0x33); db(0x7c); db(0x00); db(0x32); db(0x00); db(0x46); + db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x02); db(0x61); db(0x00); + db(0xf9); db(0xea); db(0x4e); db(0x90); db(0x41); db(0xf9); db(0x00); db(0xdf); + db(0xf0); db(0x00); db(0x70); db(0x00); db(0x4e); db(0x75); db(0x48); db(0xe7); + db(0x00); db(0x06); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x20); db(0x3c); + db(0x00); db(0x00); db(0x00); db(0x88); db(0x22); db(0x3c); db(0x00); db(0x01); + db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x4a); db(0x80); + db(0x67); db(0x00); db(0x00); db(0x40); db(0x2a); db(0x40); db(0x2b); db(0x4e); + db(0x00); db(0x14); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x0e); + db(0x61); db(0x00); db(0xf9); db(0xb0); db(0x20); db(0x0d); db(0x4e); db(0x90); + db(0x41); db(0xfa); db(0x04); db(0x68); db(0x43); db(0xfa); db(0x01); db(0x12); + db(0x70); db(0xf6); db(0x22); db(0x3c); db(0x00); db(0x00); db(0x27); db(0x10); + db(0x61); db(0x00); db(0xee); db(0xdc); db(0x70); db(0x00); db(0x4c); db(0xdf); + db(0x60); db(0x00); db(0x4e); db(0x75); db(0x30); db(0x3c); db(0xff); db(0x38); + db(0x72); db(0x0a); db(0x61); db(0x00); db(0xf9); db(0x86); db(0x4e); db(0x90); + db(0x4e); db(0x75); db(0x61); db(0xf0); db(0x20); db(0x0d); db(0x67); db(0x1c); + db(0x2c); db(0x6d); db(0x00); db(0x14); db(0x20); db(0x2d); db(0x00); db(0x18); + db(0x67); db(0x06); db(0x22); db(0x40); db(0x4e); db(0xae); db(0xfe); db(0x62); + db(0x22); db(0x4d); db(0x20); db(0x3c); db(0x00); db(0x00); db(0x00); db(0x88); + db(0x4e); db(0xae); db(0xff); db(0x2e); db(0x70); db(0x00); db(0x4e); db(0x75); + db(0x48); db(0xe7); db(0x38); db(0x3e); db(0x2c); db(0x6d); db(0x00); db(0x18); + db(0x41); db(0xfa); db(0x03); db(0xf6); db(0x22); db(0x08); db(0x24); db(0x3c); + db(0x00); db(0x00); db(0x03); db(0xed); db(0x4e); db(0xae); db(0xff); db(0xe2); + db(0x28); db(0x00); db(0x67); db(0x4c); db(0x45); db(0xed); db(0x00); db(0x68); + db(0x42); db(0x92); db(0x34); db(0xaa); db(0x00); db(0x02); db(0x24); db(0x0a); + db(0x54); db(0x82); db(0x76); db(0x02); db(0x22); db(0x04); db(0x4e); db(0xae); + db(0xff); db(0xd6); db(0xb6); db(0x80); db(0x66); db(0x32); db(0x0c); db(0x92); + db(0x50); db(0x4e); db(0x54); db(0x52); db(0x66); db(0xe4); db(0x24); db(0x0a); + db(0x76); db(0x04); db(0x22); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xd6); + db(0x24); db(0x0a); db(0x76); db(0x20); db(0x22); db(0x04); db(0x4e); db(0xae); + db(0xff); db(0xd6); db(0xb6); db(0x80); db(0x66); db(0x12); db(0x4a); db(0x6a); + db(0x00); db(0x10); db(0x66); db(0xc4); db(0x30); db(0x3c); db(0xff); db(0x38); + db(0x72); db(0x10); db(0x61); db(0x00); db(0xf8); db(0xf6); db(0x4e); db(0x90); + db(0x22); db(0x04); db(0x67); db(0x04); db(0x4e); db(0xae); db(0xff); db(0xdc); + db(0x4c); db(0xdf); db(0x7c); db(0x1c); db(0x4e); db(0x75); db(0x2c); db(0x6d); + db(0x00); db(0x18); db(0x41); db(0xfa); db(0x03); db(0x6e); db(0x22); db(0x08); + db(0x74); db(0xfe); db(0x4e); db(0xae); db(0xff); db(0xac); db(0x22); db(0x00); + db(0x67); db(0x34); db(0x4e); db(0xae); db(0xff); db(0xa6); db(0x2c); db(0x6d); + db(0x00); db(0x14); db(0x45); db(0xed); db(0x00); db(0x38); db(0x70); db(0xff); + db(0x4e); db(0xae); db(0xfe); db(0xb6); db(0x15); db(0x40); db(0x00); db(0x14); + db(0x41); db(0xfa); db(0x03); db(0x5e); db(0x24); db(0x88); db(0x25); db(0x7c); + db(0x00); db(0x00); db(0x00); db(0x12); db(0x00); db(0x0c); db(0x25); db(0x6d); + db(0x00); db(0x08); db(0x00); db(0x10); db(0x2c); db(0x6d); db(0x00); db(0x18); + db(0x22); db(0x0a); db(0x4e); db(0xae); db(0xfc); db(0x88); db(0x2c); db(0x6d); + db(0x00); db(0x14); db(0x4e); db(0x75); db(0x00); db(0x00); db(0x00); db(0x10); db(0x00); db(0x00); db(0x00); db(0x00); db(0x30); db(0x3c); db(0xff); db(0x38); - db(0x72); db(0x0d); db(0x61); db(0x00); db(0xf8); db(0x84); db(0x4e); db(0x90); - db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0xfc); db(0x2a); db(0x40); + db(0x72); db(0x0d); db(0x61); db(0x00); db(0xf8); db(0x86); db(0x4e); db(0x90); + db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0xfe); db(0x2a); db(0x40); db(0x2c); db(0x6d); db(0x00); db(0x14); db(0x93); db(0xc9); db(0x4e); db(0xae); db(0xfe); db(0xda); db(0x2b); db(0x40); db(0x00); db(0x08); db(0x43); db(0xfa); db(0x03); db(0x8c); db(0x70); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); - db(0x2b); db(0x40); db(0x00); db(0x18); db(0x67); db(0x00); db(0xfe); db(0xda); + db(0x2b); db(0x40); db(0x00); db(0x18); db(0x67); db(0x00); db(0xfe); db(0xdc); db(0x2c); db(0x40); db(0x72); db(0x32); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x41); db(0xfa); db(0x02); db(0xc4); db(0x22); db(0x08); db(0x74); db(0xfe); db(0x4e); db(0xae); db(0xff); db(0xac); db(0x4a); db(0x80); db(0x67); db(0xea); db(0x22); db(0x00); db(0x4e); db(0xae); db(0xff); db(0xa6); db(0x72); db(0x32); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x41); db(0xfa); db(0x02); db(0xae); db(0x22); db(0x08); db(0x74); db(0xfe); db(0x4e); db(0xae); db(0xff); db(0xac); - db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0xa4); db(0x22); db(0x00); + db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0xa6); db(0x22); db(0x00); db(0x4e); db(0xae); db(0xff); db(0xa6); db(0x2c); db(0x6d); db(0x00); db(0x14); - db(0x61); db(0x00); db(0xf8); db(0x32); db(0x72); db(0x00); db(0x32); db(0x3c); - db(0x00); db(0x34); db(0x61); db(0x00); db(0xf8); db(0x76); db(0x28); db(0x40); - db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0x84); db(0x70); db(0x00); + db(0x61); db(0x00); db(0xf8); db(0x34); db(0x72); db(0x00); db(0x32); db(0x3c); + db(0x00); db(0x34); db(0x61); db(0x00); db(0xf8); db(0x78); db(0x28); db(0x40); + db(0x4a); db(0x80); db(0x67); db(0x00); db(0xfe); db(0x86); db(0x70); db(0x00); db(0x08); db(0xc0); db(0x00); db(0x0d); db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x72); db(0x00); db(0x20); db(0x2d); db(0x00); db(0x0c); db(0x41); db(0xfa); db(0x02); db(0x87); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x44); db(0x4a); db(0x80); db(0x66); db(0xe2); db(0x20); db(0x6c); db(0x00); db(0x14); db(0x0c); db(0x68); db(0x00); db(0x25); db(0x00); db(0x14); db(0x64); db(0x0c); - db(0x61); db(0x00); db(0xfe); db(0x48); db(0x70); db(0x00); db(0x4e); db(0xae); - db(0xfe); db(0xc2); db(0x60); db(0xf8); db(0x61); db(0x00); db(0xfe); db(0xe6); + db(0x61); db(0x00); db(0xfe); db(0x4a); db(0x70); db(0x00); db(0x4e); db(0xae); + db(0xfe); db(0xc2); db(0x60); db(0xf8); db(0x61); db(0x00); db(0xfe); db(0xe8); db(0x41); db(0xed); db(0x00); db(0x1c); db(0x29); db(0x48); db(0x00); db(0x28); db(0x70); db(0x01); db(0x29); db(0x40); db(0x00); db(0x24); db(0x39); db(0x7c); db(0x00); db(0x0c); db(0x00); db(0x1c); db(0x2b); db(0x4d); db(0x00); db(0x2c); db(0x41); db(0xfa); db(0x01); db(0x60); db(0x2b); db(0x48); db(0x00); db(0x24); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x30); db(0x3c); - db(0xff); db(0x38); db(0x72); db(0x0f); db(0x61); db(0x00); db(0xf7); db(0x9a); + db(0xff); db(0x38); db(0x72); db(0x0f); db(0x61); db(0x00); db(0xf7); db(0x9c); db(0x4e); db(0x90); db(0x4a); db(0xad); db(0x00); db(0x00); db(0x66); db(0x1c); db(0x70); db(0x00); db(0x74); db(0x00); db(0x14); db(0x2d); db(0x00); db(0x4c); db(0x05); db(0xc0); db(0x08); db(0xc0); db(0x00); db(0x0d); db(0x4e); db(0xae); db(0xfe); db(0xc2); db(0x05); db(0x00); db(0x67); db(0x06); db(0x61); db(0x00); - db(0xfe); db(0x1e); db(0x60); db(0xe4); db(0x20); db(0x2d); db(0x00); db(0x00); + db(0xfe); db(0x20); db(0x60); db(0xe4); db(0x20); db(0x2d); db(0x00); db(0x00); db(0x67); db(0x00); db(0x00); db(0x76); db(0x72); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x2b); db(0x40); db(0x00); db(0x04); db(0x30); db(0x3c); - db(0xff); db(0x38); db(0x72); db(0x0c); db(0x61); db(0x00); db(0xf7); db(0x5a); + db(0xff); db(0x38); db(0x72); db(0x0c); db(0x61); db(0x00); db(0xf7); db(0x5c); db(0x4e); db(0x90); db(0x4a); db(0x80); db(0x67); db(0x40); db(0x4a); db(0xad); db(0x00); db(0x04); db(0x67); db(0x3a); db(0x39); db(0x7c); db(0x00); db(0x03); db(0x00); db(0x1c); db(0x42); db(0x2c); db(0x00); db(0x1f); db(0x42); db(0xac); @@ -704,7 +705,7 @@ db(0x00); db(0x28); db(0x20); db(0x02); db(0x51); db(0x80); db(0x29); db(0x40); db(0x00); db(0x24); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x38); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x0b); db(0x61); db(0x00); - db(0xf6); db(0x80); db(0x20); db(0x2c); db(0x00); db(0x20); db(0x4e); db(0x90); + db(0xf6); db(0x82); db(0x20); db(0x2c); db(0x00); db(0x20); db(0x4e); db(0x90); db(0x22); db(0x4a); db(0x20); db(0x02); db(0x4e); db(0xae); db(0xff); db(0x2e); db(0x4a); db(0xac); db(0x00); db(0x20); db(0x67); db(0x00); db(0xfe); db(0xda); db(0x41); db(0xed); db(0x00); db(0x30); db(0x29); db(0x48); db(0x00); db(0x28); @@ -717,17 +718,17 @@ db(0x08); db(0xc0); db(0x00); db(0x0d); db(0x4e); db(0xae); db(0xfe); db(0xbc); db(0x2c); db(0x5f); db(0x70); db(0x00); db(0x4e); db(0x75); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x74); db(0xff); db(0x30); db(0x3c); db(0xff); db(0x38); - db(0x72); db(0x64); db(0x61); db(0x00); db(0xf6); db(0x14); db(0x4e); db(0x90); + db(0x72); db(0x64); db(0x61); db(0x00); db(0xf6); db(0x16); db(0x4e); db(0x90); db(0x4a); db(0x80); db(0x67); db(0x38); db(0x74); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x7c); db(0x41); db(0xee); db(0x01); db(0x5e); db(0x43); db(0xfa); db(0x00); db(0x62); db(0x4e); db(0xae); db(0xfe); db(0xec); db(0x4a); db(0x80); db(0x67); db(0x1e); db(0x20); db(0x40); db(0x43); db(0xfa); db(0x00); db(0x22); db(0x24); db(0x68); db(0xff); db(0xe4); db(0x21); db(0x49); db(0xff); db(0xe4); db(0x22); db(0x48); db(0x30); db(0x3c); db(0xff); db(0x38); db(0x72); db(0x65); - db(0x61); db(0x00); db(0xf5); db(0xde); db(0x4e); db(0x90); db(0x74); db(0x01); + db(0x61); db(0x00); db(0xf5); db(0xe0); db(0x4e); db(0x90); db(0x74); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x76); db(0x20); db(0x02); db(0x4e); db(0x75); db(0x59); db(0x8f); db(0x48); db(0xe7); db(0xc0); db(0x80); db(0x30); db(0x3c); - db(0xff); db(0x38); db(0x72); db(0x66); db(0x61); db(0x00); db(0xf5); db(0xc2); + db(0xff); db(0x38); db(0x72); db(0x66); db(0x61); db(0x00); db(0xf5); db(0xc4); db(0x4e); db(0x90); db(0x4c); db(0xdf); db(0x01); db(0x03); db(0x4e); db(0x75); db(0x69); db(0x6e); db(0x70); db(0x75); db(0x74); db(0x2e); db(0x64); db(0x65); db(0x76); db(0x69); db(0x63); db(0x65); db(0x00); db(0x74); db(0x69); db(0x6d); diff --git a/fpp.cpp b/fpp.cpp index 82980c99..e06432a2 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -851,7 +851,7 @@ void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra) fpu_op_illg (opcode, m68k_getpc () - oldpc); } if (cc) - Exception (7, oldpc - 2); + Exception (7); } void fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 extra) diff --git a/gayle.cpp b/gayle.cpp index 347bf6be..232467d5 100644 --- a/gayle.cpp +++ b/gayle.cpp @@ -155,7 +155,7 @@ read 1 byte to stop reset */ #define IDE_GAYLE 0 #define IDE_ADIDE 1 -#define MAX_IDE_MULTIPLE_SECTORS 128 +#define MAX_IDE_MULTIPLE_SECTORS 64 #define SECBUF_SIZE (512 * (MAX_IDE_MULTIPLE_SECTORS * 2)) struct ide_hdf @@ -286,7 +286,7 @@ static void gayle_cs_change (uae_u8 mask, int onoff) if (gayle_irq & GAYLE_IRQ_RESET) uae_reset (0); if (gayle_irq & GAYLE_IRQ_BERR) - Exception (2, 0); + Exception (2); } } } @@ -1904,7 +1904,7 @@ static void initide (void) int i; alloc_ide_mem (idedrive, 4); - if (savestate_state == STATE_RESTORE) + if (isrestore ()) return; ide_error = 1; ide_sector = ide_nsector = 1; @@ -1954,13 +1954,16 @@ uae_u8 *restore_gayle (uae_u8 *src) return src; } -uae_u8 *save_gayle (int *len) +uae_u8 *save_gayle (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; if (currprefs.cs_ide <= 0) return NULL; - dstbak = dst = xmalloc (uae_u8, 1000); + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); save_u8 (currprefs.cs_ide); save_u8 (gayle_int); save_u8 (gayle_irq); @@ -1971,7 +1974,7 @@ uae_u8 *save_gayle (int *len) return dstbak; } -uae_u8 *save_ide (int num, int *len) +uae_u8 *save_ide (int num, int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; struct ide_hdf *ide; @@ -1983,7 +1986,10 @@ uae_u8 *save_ide (int num, int *len) ide = idedrive[num]; if (ide->hdhfd.size == 0) return NULL; - dstbak = dst = xmalloc (uae_u8, 1000); + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); save_u32 (num); save_u64 (ide->hdhfd.size); save_string (ide->hdhfd.path); diff --git a/gencpu.cpp b/gencpu.cpp index 003d4c69..fa2313f6 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -35,6 +35,7 @@ static int using_prefetch, using_indirect, using_mmu; static int using_ce020; static int using_exception_3; static int using_ce; +static int using_tracer; static int cpu_level; static int count_read, count_write, count_cycles, count_ncycles; static int count_read_ea, count_write_ea, count_cycles_ea; @@ -69,6 +70,13 @@ static int fixupcnt; #define GENA_MOVEM_NO_INC 1 #define GENA_MOVEM_MOVE16 2 +static char *srcl, *dstl; +static char *srcw, *dstw; +static char *srcb, *dstb; +static char *prefetch_long, *prefetch_word; +static char *srcli, *srcwi, *srcbi, *nextl, *nextw, *nextb; +static char *do_cycles, *disp000, *disp020; + static void read_counts (void) { FILE *file; @@ -148,14 +156,14 @@ static void addcycles000 (int cycles) { if (!using_ce) return; - printf ("\tdo_cycles_ce000 (%d);\n", cycles); + printf ("\t%s (%d);\n", do_cycles, cycles); count_cycles += cycles; } static void addcycles000_2 (char *s, int cycles) { if (!using_ce) return; - printf ("%sdo_cycles_ce000 (%d);\n", s, cycles); + printf ("%s%s (%d);\n", s, do_cycles, cycles); count_cycles += cycles; } @@ -163,7 +171,7 @@ static void addcycles000_3 (char *s) { if (!using_ce) return; - printf ("%sif (cycles > 0) do_cycles_ce000 (cycles);\n", s); + printf ("%sif (cycles > 0) %s (cycles);\n", s, do_cycles); count_ncycles++; } @@ -221,56 +229,44 @@ static const char *bit_mask (int size) return 0; } -static char *srcl, *dstl; -static char *srcw, *dstw; -static char *srcb, *dstb; -static char *ce020_prefetch_long; -static char *ce020_prefetch_word; - static void gen_nextilong (char *type, char *name, int flags) { int r = m68k_pc_offset; m68k_pc_offset += 4; if (using_ce020) { - printf ("\t%s %s = %s (%d);\n", type, name, ce020_prefetch_long, r); + printf ("\t%s %s = %s (%d);\n", type, name, prefetch_long, r); count_read += 2; } else if (using_ce) { printf ("\t%s %s;\n", type, name); /* we must do this because execution order of (something | something2) is not defined */ if (flags & GF_NOREFILL) { - printf ("\t%s = get_word_ce_prefetch (%d) << 16;\n", name, r + 2); + printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2); count_read++; printf ("\t%s |= regs.irc;\n", name); } else { - printf ("\t%s = get_word_ce_prefetch (%d) << 16;\n", name, r + 2); + printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2); count_read++; - printf ("\t%s |= get_word_ce_prefetch (%d);\n", name, r + 4); + printf ("\t%s |= %s (%d);\n", name, prefetch_word, r + 4); count_read++; } } else { if (using_prefetch) { if (flags & GF_NOREFILL) { printf ("\t%s %s;\n", type, name); - printf ("\t%s = get_word_prefetch (%d) << 16;\n", name, r + 2); + printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2); count_read++; printf ("\t%s |= regs.irc;\n", name); insn_n_cycles += 4; } else { - printf ("\t%s %s = get_long_prefetch (%d);\n", type, name, r + 2); + printf ("\t%s %s = %s (%d);\n", type, name, prefetch_long, r + 2); count_read++; count_read++; insn_n_cycles += 8; } - } else if (using_indirect) { - insn_n_cycles += 8; - printf ("\t%s %s = get_ilongi (%d);\n", type, name, r); - } else if (using_mmu) { - insn_n_cycles += 8; - printf ("\t%s %s = get_ilong_mmu (%d);\n", type, name, r); } else { insn_n_cycles += 8; - printf ("\t%s %s = get_ilong (%d);\n", type, name, r); + printf ("\t%s %s = %s (%d);\n", type, name, prefetch_long, r); } } } @@ -282,13 +278,13 @@ static const char *gen_nextiword (int flags) m68k_pc_offset += 2; if (using_ce020) { - sprintf (buffer, "%s (%d)", ce020_prefetch_word, r); + sprintf (buffer, "%s (%d)", prefetch_word, r); count_read++; } else if (using_ce) { if (flags & GF_NOREFILL) { strcpy (buffer, "regs.irc"); } else { - sprintf (buffer, "get_word_ce_prefetch (%d)", r + 2); + sprintf (buffer, "%s (%d)", prefetch_word, r + 2); count_read++; } } else { @@ -296,18 +292,12 @@ static const char *gen_nextiword (int flags) if (flags & GF_NOREFILL) { sprintf (buffer, "regs.irc", r); } else { - sprintf (buffer, "get_word_prefetch (%d)", r + 2); + sprintf (buffer, "%s (%d)", prefetch_word, r + 2); count_read++; insn_n_cycles += 4; } - } else if (using_indirect) { - sprintf (buffer, "get_iwordi(%d)", r); - insn_n_cycles += 4; - } else if (using_mmu) { - sprintf (buffer, "get_iword_mmu (%d)", r); - insn_n_cycles += 4; } else { - sprintf (buffer, "get_iword (%d)", r); + sprintf (buffer, "%s (%d)", prefetch_word, r); insn_n_cycles += 4; } } @@ -321,13 +311,13 @@ static const char *gen_nextibyte (int flags) m68k_pc_offset += 2; if (using_ce020) { - sprintf (buffer, "(uae_u8)%s (%d)", ce020_prefetch_word, r); + sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r); count_read++; } else if (using_ce) { if (flags & GF_NOREFILL) { strcpy (buffer, "(uae_u8)regs.irc"); } else { - sprintf (buffer, "(uae_u8)get_word_ce_prefetch (%d)", r + 2); + sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r + 2); count_read++; } } else { @@ -336,18 +326,12 @@ static const char *gen_nextibyte (int flags) if (flags & GF_NOREFILL) { sprintf (buffer, "(uae_u8)regs.irc", r); } else { - sprintf (buffer, "(uae_u8)get_word_prefetch (%d)", r + 2); + sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r + 2); insn_n_cycles += 4; count_read++; } - } else if (using_indirect) { - sprintf (buffer, "get_ibytei (%d)", r); - insn_n_cycles += 4; - } else if (using_mmu) { - sprintf (buffer, "get_ibyte_mmu (%d)", r); - insn_n_cycles += 4; } else { - sprintf (buffer, "get_ibyte (%d)", r); + sprintf (buffer, "%s (%d)", srcbi, r); insn_n_cycles += 4; } } @@ -369,10 +353,7 @@ static void fill_prefetch_2 (void) { if (!using_prefetch) return; - if (using_ce) - printf ("\tget_word_ce_prefetch (%d);\n", m68k_pc_offset + 2); - else - printf ("\tget_word_prefetch (%d);\n", m68k_pc_offset + 2); + printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset + 2); did_prefetch = 1; count_read++; insn_n_cycles += 4; @@ -382,11 +363,7 @@ static void fill_prefetch_1 (int o) { if (!using_prefetch) return; - if (using_ce) { - printf ("\tget_word_ce_prefetch (%d);\n", o); - } else { - printf ("\tget_word_prefetch (%d);\n", o); - } + printf ("\t%s (%d);\n", prefetch_word, o); did_prefetch = 1; count_read++; insn_n_cycles += 4; @@ -403,10 +380,7 @@ static void fill_prefetch_0 (void) { if (!using_prefetch) return; - if (using_ce) - printf ("\tget_word_ce_prefetch (0);\n"); - else - printf ("\tget_word_prefetch (0);\n"); + printf ("\t%s (0);\n", prefetch_word); did_prefetch = 1; count_read++; insn_n_cycles += 4; @@ -417,11 +391,7 @@ static void dummy_prefetch (void) int o = m68k_pc_offset + 2; if (!using_prefetch) return; - if (using_ce) { - printf ("\tget_wordi_ce (m68k_getpc () + %d);\n", o); - } else { - printf ("\tget_wordi (m68k_getpc () + %d);\n", o); - } + printf ("\t%s (%d);\n", srcwi, o); count_read++; insn_n_cycles += 4; } @@ -437,27 +407,6 @@ static void fill_prefetch_next (void) fill_prefetch_next_1 (); } -#if 0 -static void fill_prefetch_next_delay (int extracycles) -{ - if (!using_prefetch) - return; - if (using_ce) { - if (extracycles > 0) { - printf("\t{\n"); - fill_prefetch_next (); - printf("\tif (%d > 0) do_cycles(%d * CYCLE_UNIT / 2);\n", - extracycles, extracycles); - printf("\t}\n"); - } else { - fill_prefetch_next (); - } - } else { - fill_prefetch_next (); - } -} -#endif - static void fill_prefetch_finish (void) { if (did_prefetch || !using_prefetch) @@ -508,7 +457,7 @@ static void gen_set_fault_pc (void) if (!using_mmu) return; sync_m68k_pc (); - printf ("\tregs.fault_pc = m68k_getpci ();\n"); + printf ("\tregs.instruction_pc = m68k_getpci ();\n"); m68k_pc_offset = 0; } @@ -631,17 +580,14 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g start_brace (); /* This would ordinarily be done in gen_nextiword, which we bypass. */ insn_n_cycles += 4; - if (using_ce020 || using_mmu) - printf ("\t%sa = x_get_disp_ea_020 (m68k_areg (regs, %s), x_next_iword ());\n", name, reg); - else - printf ("\t%sa = get_disp_ea_020 (m68k_areg (regs, %s), next_iword ());\n", name, reg); + printf ("\t%sa = %s (m68k_areg (regs, %s), %s ());\n", name, disp020, reg, nextw); } else { if (!(flags & GF_AD8R)) { addcycles000 (2); insn_n_cycles += 2; count_cycles_ea += 2; } - printf ("\t%sa = get_disp_ea_000 (m68k_areg (regs, %s), %s);\n", name, reg, gen_nextiword (flags)); + printf ("\t%sa = %s (m68k_areg (regs, %s), %s);\n", name, disp000, reg, gen_nextiword (flags)); count_read_ea++; } break; @@ -660,10 +606,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g /* This would ordinarily be done in gen_nextiword, which we bypass. */ insn_n_cycles += 4; printf ("\ttmppc = m68k_getpc ();\n"); - if (using_ce020 || using_mmu) - printf ("\t%sa = x_get_disp_ea_020 (tmppc, x_next_iword ());\n", name); - else - printf ("\t%sa = get_disp_ea_020 (tmppc, next_iword ());\n", name); + printf ("\t%sa = %s (tmppc, %s ());\n", name, disp020, nextw); } else { printf ("\ttmppc = m68k_getpc () + %d;\n", m68k_pc_offset); if (!(flags & GF_PC8R)) { @@ -671,7 +614,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g insn_n_cycles += 2; count_cycles_ea += 2; } - printf ("\t%sa = get_disp_ea_000 (tmppc, %s);\n", name, gen_nextiword (flags)); + printf ("\t%sa = %s (tmppc, %s);\n", name, disp000, gen_nextiword (flags)); } break; @@ -750,8 +693,8 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g offset = m68k_pc_offset_last; } printf ("\tif (%sa & 1) {\n", name); - printf ("\t\texception3 (opcode, m68k_getpc () + %d, %sa);\n", - offset, name); + incpc ("%d", offset); + printf ("\t\texception3 (opcode, %sa);\n", name); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -772,9 +715,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } } else if (using_ce) { switch (size) { - case sz_byte: printf ("\tuae_s8 %s = get_byte_ce (%sa);\n", name, name); count_read++; break; - case sz_word: printf ("\tuae_s16 %s = get_word_ce (%sa);\n", name, name); count_read++; break; - case sz_long: printf ("\tuae_s32 %s = get_word_ce (%sa) << 16; %s |= get_word_ce (%sa + 2);\n", name, name, name, name); count_read += 2; break; + case sz_byte: printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break; + case sz_word: printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break; + case sz_long: printf ("\tuae_s32 %s = %s (%sa) << 16; %s |= %s (%sa + 2);\n", name, srcw, name, name, srcw, name); count_read += 2; break; default: abort (); } } else if (using_mmu) { @@ -787,17 +730,17 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } } else { switch (size) { - case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = get_byte_mmu (%sa);\n", name, name); break; - case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = get_word_mmu (%sa);\n", name, name); break; - case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = get_long_mmu (%sa);\n", name, name); break; + case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); break; + case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); break; + case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); break; default: abort (); } } } else { switch (size) { - case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = get_byte (%sa);\n", name, name); count_read++; break; - case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = get_word (%sa);\n", name, name); count_read++; break; - case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = get_long (%sa);\n", name, name); count_read += 2; break; + 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 sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); count_read += 2; break; default: abort (); } } @@ -933,22 +876,22 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha } else if (using_ce) { switch (size) { case sz_byte: - printf ("\tput_byte_ce (%sa, %s);\n", to, from); + printf ("\tx_put_byte (%sa, %s);\n", to, from); count_write++; break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\tput_word_ce (%sa, %s);\n", to, from); + printf ("\tx_put_word (%sa, %s);\n", to, from); count_write++; break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); if (store_dir) - printf ("\tput_word_ce (%sa + 2, %s); put_word_ce (%sa, %s >> 16);\n", to, from, to, from); + printf ("\t%s (%sa + 2, %s); %s (%sa, %s >> 16);\n", dstw, to, from, dstw, to, from); else - printf ("\tput_word_ce (%sa, %s >> 16); put_word_ce (%sa + 2, %s);\n", to, from, to, from); + printf ("\t%s (%sa, %s >> 16); %s (%sa + 2, %s);\n", dstw, to, from, dstw, to, from); count_write += 2; break; default: @@ -961,7 +904,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc_put_byte (%sa, %s);\n", to, from); else - printf ("\tput_byte_mmu (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstb, to, from); break; case sz_word: insn_n_cycles += 4; @@ -970,7 +913,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc_put_word (%sa, %s);\n", to, from); else - printf ("\tput_word_mmu (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstw, to, from); break; case sz_long: insn_n_cycles += 8; @@ -979,7 +922,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc_put_long (%sa, %s);\n", to, from); else - printf ("\tput_long_mmu (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstl, to, from); break; default: abort (); @@ -988,21 +931,21 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha switch (size) { case sz_byte: insn_n_cycles += 4; - printf ("\tput_byte (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstb, to, from); count_write++; break; case sz_word: insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\tput_word (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstw, to, from); count_write++; break; case sz_long: insn_n_cycles += 8; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\tput_long (%sa, %s);\n", to, from); + printf ("\t%s (%sa, %s);\n", dstl, to, from); count_write += 2; break; default: @@ -1074,17 +1017,17 @@ static void genmovemel_ce (uae_u16 opcode) addcycles000 (2); start_brace (); if (table68k[opcode].size == sz_long) { - printf ("\twhile (dmask) { v = get_word_ce(srca) << 16; v |= get_word_ce(srca + 2); m68k_dreg (regs, movem_index1[dmask]) = v; srca += %d; dmask = movem_next[dmask]; }\n", - size); - printf ("\twhile (amask) { v = get_word_ce(srca) << 16; v |= get_word_ce(srca + 2); m68k_areg (regs, movem_index1[amask]) = v; srca += %d; amask = movem_next[amask]; }\n", - size); + printf ("\twhile (dmask) { v = %s (srca) << 16; v |= %s (srca + 2); m68k_dreg (regs, movem_index1[dmask]) = v; srca += %d; dmask = movem_next[dmask]; }\n", + srcw, srcw, size); + printf ("\twhile (amask) { v = %s (srca) << 16; v |= %s (srca + 2); m68k_areg (regs, movem_index1[amask]) = v; srca += %d; amask = movem_next[amask]; }\n", + srcw, srcw, size); } else { - printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word_ce(srca); srca += %d; dmask = movem_next[dmask]; }\n", - size); - printf ("\twhile (amask) { m68k_areg (regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word_ce(srca); srca += %d; amask = movem_next[amask]; }\n", - size); + printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = (uae_s32)(uae_s16)%s (srca); srca += %d; dmask = movem_next[dmask]; }\n", + srcw, size); + printf ("\twhile (amask) { m68k_areg (regs, movem_index1[amask]) = (uae_s32)(uae_s16)%s (srca); srca += %d; amask = movem_next[amask]; }\n", + srcw, size); } - printf ("\tget_word_ce (srca);\n"); // and final extra word fetch that goes nowhere.. + printf ("\t%s (srca);\n", srcw); // and final extra word fetch that goes nowhere.. count_read++; if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg (regs, dstreg) = srca;\n"); @@ -1110,7 +1053,7 @@ static void genmovemle (uae_u16 opcode) if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); if (!using_mmu) - printf ("\tint type = get_cpu_model() >= 68020;\n"); + printf ("\tint type = get_cpu_model () >= 68020;\n"); printf ("\twhile (amask) {\n"); printf ("\t\tsrca -= %d;\n", size); if (!using_mmu) @@ -1145,32 +1088,32 @@ static void genmovemle_ce (uae_u16 opcode) if (table68k[opcode].size == sz_long) { if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (amask) { srca -= %d; put_word_ce (srca, m68k_areg (regs, movem_index2[amask]) >> 16); put_word_ce (srca + 2, m68k_areg (regs, movem_index2[amask])); amask = movem_next[amask]; }\n", - size); - printf ("\twhile (dmask) { srca -= %d; put_word_ce (srca, m68k_dreg (regs, movem_index2[dmask]) >> 16); put_word_ce (srca + 2, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size); + printf ("\twhile (amask) { srca -= %d; %s (srca, m68k_areg (regs, movem_index2[amask]) >> 16); %s (srca + 2, m68k_areg (regs, movem_index2[amask])); amask = movem_next[amask]; }\n", + size, dstw, dstw); + printf ("\twhile (dmask) { srca -= %d; %s (srca, m68k_dreg (regs, movem_index2[dmask]) >> 16); %s (srca + 2, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", + size, dstw, dstw); printf ("\tm68k_areg (regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (dmask) { put_word_ce (srca, m68k_dreg (regs, movem_index1[dmask]) >> 16); put_word_ce (srca + 2, m68k_dreg (regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - size); - printf ("\twhile (amask) { put_word_ce (srca, m68k_areg (regs, movem_index1[amask]) >> 16); put_word_ce (srca + 2, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - size); + printf ("\twhile (dmask) { %s (srca, m68k_dreg (regs, movem_index1[dmask]) >> 16); %s (srca + 2, m68k_dreg (regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", + dstw, dstw, size); + printf ("\twhile (amask) { %s (srca, m68k_areg (regs, movem_index1[amask]) >> 16); %s (srca + 2, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", + dstw, dstw, size); } } else { if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (amask) { srca -= %d; put_word_ce (srca, m68k_areg (regs, movem_index2[amask])); amask = movem_next[amask]; }\n", - size); - printf ("\twhile (dmask) { srca -= %d; put_word_ce (srca, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size); + printf ("\twhile (amask) { srca -= %d; %s (srca, m68k_areg (regs, movem_index2[amask])); amask = movem_next[amask]; }\n", + size, dstw); + printf ("\twhile (dmask) { srca -= %d; %s (srca, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", + size, dstw); printf ("\tm68k_areg (regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (dmask) { put_word_ce (srca, m68k_dreg (regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - size); - printf ("\twhile (amask) { put_word_ce (srca, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - size); + printf ("\twhile (dmask) { %s (srca, m68k_dreg (regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", + dstw, size); + printf ("\twhile (amask) { %s (srca, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", + dstw, size); } } count_ncycles++; @@ -1471,7 +1414,7 @@ static void bsetcycles (struct instr *curi) if (isreg (curi->dmode)) { addcycles000 (2); if (curi->mnemo != i_BTST && using_ce) { - printf ("\tif (src > 15) do_cycles_ce000 (2);\n"); + printf ("\tif (src > 15) %s (2);\n", do_cycles); count_ncycles++; } } @@ -1489,10 +1432,56 @@ static void gen_opcode (unsigned long int opcode) insn_n_cycles = using_prefetch ? 0 : 4; - if (using_ce020) { + prefetch_long = NULL; + srcli = NULL; + srcbi = NULL; + disp000 = "get_disp_ea_000"; + disp020 = "get_disp_ea_020"; + nextw = NULL; + nextl = NULL; + do_cycles = "do_cycles"; + + if (using_indirect) { + // tracer + if (!using_ce020) { + prefetch_word = "get_word_ce000_prefetch"; + srcli = "x_get_ilong"; + srcwi = "x_get_iword"; + srcbi = "x_get_ibyte"; + srcl = "x_get_long"; + dstl = "x_put_long"; + srcw = "x_get_word"; + dstw = "x_put_word"; + srcb = "x_get_byte"; + dstb = "x_put_byte"; + do_cycles = "do_cycles_ce000"; + } else if (using_ce020) { + disp020 = "x_get_disp_ea_020"; + prefetch_long = "get_long_ce020_prefetch"; + prefetch_word = "get_word_ce020_prefetch"; + srcli = "x_get_ilong"; + srcwi = "x_get_iword"; + srcbi = "x_get_ibyte"; + srcl = "x_get_long"; + dstl = "x_put_long"; + srcw = "x_get_word"; + dstw = "x_put_word"; + srcb = "x_get_byte"; + dstb = "x_put_byte"; + do_cycles = "do_cycles_ce020"; + } + + } else if (using_ce020) { + disp020 = "x_get_disp_ea_020"; + do_cycles = "do_cycles_ce020"; if (using_ce020 == 2) { - ce020_prefetch_long = "get_long_ce030_prefetch"; - ce020_prefetch_word = "get_word_ce030_prefetch"; + // 68030 CE + prefetch_long = "get_long_ce030_prefetch"; + prefetch_word = "get_word_ce030_prefetch"; + nextw = "next_iword_030ce"; + nextl = "next_ilong_030ce"; + srcli = "get_word_ce030_prefetch"; + srcwi = "get_long_ce030_prefetch"; srcl = "get_long_ce030"; dstl = "put_long_ce030"; srcw = "get_word_ce030"; @@ -1500,8 +1489,13 @@ static void gen_opcode (unsigned long int opcode) srcb = "get_byte_ce030"; dstb = "put_byte_ce030"; } else { - ce020_prefetch_long = "get_long_ce020_prefetch"; - ce020_prefetch_word = "get_word_ce020_prefetch"; + // 68020 CE + prefetch_long = "get_long_ce020_prefetch"; + prefetch_word = "get_word_ce020_prefetch"; + nextw = "next_iword_020ce"; + nextl = "next_ilong_020ce"; + srcli = "get_word_ce020_prefetch"; + srcwi = "get_long_ce020_prefetch"; srcl = "get_long_ce020"; dstl = "put_long_ce020"; srcw = "get_word_ce020"; @@ -1510,6 +1504,15 @@ static void gen_opcode (unsigned long int opcode) dstb = "put_byte_ce020"; } } else if (using_mmu) { + // 68040 MMU + disp020 = "x_get_disp_ea_020"; + prefetch_long = "get_ilong_mmu"; + prefetch_word = "get_iword_mmu"; + nextw = "next_iword_mmu"; + nextl = "next_ilong_mmu"; + srcli = "get_ilong_mmu"; + srcwi = "get_iword_muu"; + srcbi = "get_ibyte_mmu"; srcl = "get_long_mmu"; dstl = "put_long_mmu"; srcw = "get_word_mmu"; @@ -1517,13 +1520,35 @@ static void gen_opcode (unsigned long int opcode) srcb = "get_byte_mmu"; dstb = "put_byte_mmu"; } else if (using_ce) { - srcl = "get_long_ce"; - dstl = "put_long_ce"; - srcw = "get_word_ce"; - dstw = "put_word_ce"; - srcb = "get_byte_ce"; - dstb = "put_byte_ce"; + // 68000 ce + prefetch_word = "get_word_ce000_prefetch"; + srcwi = "get_wordi_ce000"; + srcl = "get_long_ce000"; + dstl = "put_long_ce000"; + srcw = "get_word_ce000"; + dstw = "put_word_ce000"; + srcb = "get_byte_ce000"; + dstb = "put_byte_ce000"; + do_cycles = "do_cycles_ce000"; + } else if (using_prefetch) { + prefetch_word = "get_word_prefetch"; + prefetch_long = "get_long_prefetch"; + srcwi = "get_wordi"; + srcl = "get_long"; + dstl = "put_long"; + srcw = "get_word"; + dstw = "put_word"; + srcb = "get_byte"; + dstb = "put_byte"; } else { + // generic + prefetch_long = "get_ilong"; + prefetch_word = "get_iword"; + nextw = "next_iword"; + nextl = "next_ilong"; + srcli = "get_ilong"; + srcwi = "get_iword"; + srcbi = "get_ibyte"; srcl = "get_long"; dstl = "put_long"; srcw = "get_word"; @@ -1547,14 +1572,14 @@ static void gen_opcode (unsigned long int opcode) /* fall through */ case 2: /* priviledged */ - printf ("if (!regs.s) { Exception (8, 0); goto %s; }\n", endlabelstr); + printf ("if (!regs.s) { Exception (8); goto %s; }\n", endlabelstr); need_endlabel = 1; start_brace (); break; case 3: /* privileged if size == word */ if (curi->size == sz_byte) break; - printf ("if (!regs.s) { Exception (8, 0); goto %s; }\n", endlabelstr); + printf ("if (!regs.s) { Exception (8); goto %s; }\n", endlabelstr); need_endlabel = 1; start_brace (); break; @@ -2047,7 +2072,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); gen_set_fault_pc (); sync_m68k_pc (); - printf ("\tException (src + 32, 0);\n"); + printf ("\tException (src + 32);\n"); did_prefetch = 1; m68k_pc_offset = 0; break; @@ -2066,12 +2091,12 @@ static void gen_opcode (unsigned long int opcode) printf ("\tcpureset ();\n"); addcycles000 (128); if (using_prefetch) - printf ("\tregs.irc = get_iword (4);\n"); + printf ("\tregs.irc = %s (4);\n", srcwi); break; case i_NOP: fill_prefetch_next (); if (using_ce020) - printf ("\tdo_cycles_ce (6 * CYCLE_UNIT);\n"); + printf ("\t%s (6);\n", do_cycles); break; case i_STOP: if (using_prefetch) { @@ -2088,11 +2113,11 @@ static void gen_opcode (unsigned long int opcode) did_prefetch = -1; break; case i_LPSTOP: /* 68060 */ - printf ("\tuae_u16 sw = get_iword (2);\n"); + printf ("\tuae_u16 sw = x_get_iword (2);\n"); printf ("\tuae_u16 sr;\n"); - printf ("\tif (sw != (0x100|0x80|0x40)) { Exception (4, 0); goto %s; }\n", endlabelstr); - printf ("\tsr = get_iword (4);\n"); - printf ("\tif (!(sr & 0x8000)) { Exception (8, 0); goto %s; }\n", endlabelstr); + printf ("\tif (sw != (0x100|0x80|0x40)) { Exception (4); goto %s; }\n", endlabelstr); + printf ("\tsr = x_get_iword (4);\n"); + printf ("\tif (!(sr & 0x8000)) { Exception (8); goto %s; }\n", endlabelstr); printf ("\tregs.sr = sr;\n"); printf ("\tMakeFromSR ();\n"); printf ("\tm68k_setstopped();\n"); @@ -2130,12 +2155,12 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\telse if (frame == 0x9) { m68k_areg (regs, 7) += offset + 12; break; }\n"); printf ("\t\telse if (frame == 0xa) { m68k_areg (regs, 7) += offset + 24; break; }\n"); printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n"); - printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception (14, 0); goto %s; }\n", endlabelstr); + printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception (14); goto %s; }\n", endlabelstr); printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n"); pop_braces (old_brace_level); printf ("\tregs.sr = newsr; MakeFromSR ();\n"); printf ("\tif (newpc & 1) {\n"); - printf ("\t\texception3i (0x%04X, m68k_getpc (), newpc);\n", opcode); + printf ("\t\texception3i (0x%04X, newpc);\n", opcode); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); printf ("\t\tm68k_setpc (newpc);\n"); @@ -2156,12 +2181,12 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0, 0); printf ("\tm68k_areg (regs, 7) += offs;\n"); printf ("\tif (pc & 1) {\n"); - printf ("\t\texception3i (0x%04X, m68k_getpc (), pc);\n", opcode); + printf ("\t\texception3i (0x%04X, pc);\n", opcode); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); } printf ("\tif (pc & 1) {\n"); - printf ("\t\texception3i (0x%04X, m68k_getpc(), pc);\n", opcode); + printf ("\t\texception3i (0x%04X, pc);\n", opcode); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); setpc ("pc"); @@ -2212,8 +2237,6 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_do_rts_ce030 ();\n"); else if (using_ce) printf ("\tm68k_do_rts_ce ();\n"); - else if (using_indirect) - printf ("\tm68k_do_rtsi ();\n"); else if (using_mmu) printf ("\tm68k_do_rts_mmu ();\n"); else @@ -2221,24 +2244,23 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (m68k_getpc () & 1) {\n"); printf ("\t\tuaecptr faultpc = m68k_getpc ();\n"); printf ("\t\tm68k_setpc (pc);\n"); - printf ("\t\texception3i (0x%04X, pc, faultpc);\n", opcode); - printf ("\t\tgoto %s;\n", endlabelstr); + printf ("\t\texception3i (0x%04X, faultpc);\n", opcode); printf ("\t}\n"); count_read += 2; m68k_pc_offset = 0; fill_prefetch_full (); - need_endlabel = 1; break; case i_TRAPV: sync_m68k_pc (); fill_prefetch_next (); printf ("\tif (GET_VFLG ()) {\n"); - printf ("\t\tException (7, m68k_getpc ());\n"); + printf ("\t\tException (7);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; break; case i_RTR: + printf ("\tuaecptr oldpc = m68k_getpc ();\n"); printf ("\tMakeSR ();\n"); genamode_pre (Aipi, "7", sz_word, "sr", 1, 0, 0); genamode (Aipi, "7", sz_long, "pc", 1, 0, 0); @@ -2247,6 +2269,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tregs.sr |= sr;\n"); setpc ("pc"); printf ("\tMakeFromSR ();\n"); + printf ("\tif (m68k_getpc () & 1) {\n"); + printf ("\t\tuaecptr faultpc = m68k_getpc ();\n"); + printf ("\t\tm68k_setpc (oldpc);\n"); + printf ("\t\texception3i (0x%04X, faultpc);\n", opcode); + printf ("\t}\n"); m68k_pc_offset = 0; fill_prefetch_full (); break; @@ -2256,7 +2283,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuaecptr oldpc = m68k_getpc () + %d;\n", m68k_pc_offset); if (using_exception_3) { printf ("\tif (srca & 1) {\n"); - printf ("\t\texception3i (opcode, oldpc, srca);\n"); + printf ("\t\texception3i (opcode, srca);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -2276,8 +2303,8 @@ static void gen_opcode (unsigned long int opcode) addcycles000 (6); printf ("\tm68k_areg (regs, 7) -= 4;\n"); if (using_ce) { - printf ("\tput_word_ce (m68k_areg (regs, 7), oldpc >> 16);\n"); - printf ("\tput_word_ce (m68k_areg (regs, 7) + 2, oldpc);\n"); + printf ("\tx_put_word (m68k_areg (regs, 7), oldpc >> 16);\n"); + printf ("\tx_put_word (m68k_areg (regs, 7) + 2, oldpc);\n"); } else { printf ("\t%s (m68k_areg (regs, 7), oldpc);\n", dstl); } @@ -2289,7 +2316,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA | ((curi->smode == Ad8r || curi->smode == PC8r) ? 0 : GF_NOREFILL)); if (using_exception_3) { printf ("\tif (srca & 1) {\n"); - printf ("\t\texception3i (opcode, m68k_getpc () + 6, srca);\n"); + printf ("\t\texception3i (opcode, srca);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -2307,7 +2334,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\ts = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); - printf ("\t\texception3i (opcode, m68k_getpc () + 2, m68k_getpc () + s);\n"); + printf ("\t\texception3i (opcode, m68k_getpc () + s);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -2319,8 +2346,6 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_do_bsr_ce030 (m68k_getpc () + %d, s);\n", m68k_pc_offset); } else if (using_ce) { printf ("\tm68k_do_bsr_ce (m68k_getpc () + %d, s);\n", m68k_pc_offset); - } else if (using_indirect) { - printf ("\tm68k_do_bsri (m68k_getpc () + %d, s);\n", m68k_pc_offset); } else if (using_mmu) { printf ("\tm68k_do_bsr_mmu (m68k_getpc () + %d, s);\n", m68k_pc_offset); } else { @@ -2337,7 +2362,7 @@ static void gen_opcode (unsigned long int opcode) if (cpu_level < 2) { addcycles000 (2); printf ("\tif (cctrue (%d)) {\n", curi->cc); - printf ("\t\texception3i (opcode, m68k_getpc () + 2, m68k_getpc () + 1);\n"); + printf ("\t\texception3i (opcode, m68k_getpc () + 1);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); sync_m68k_pc (); @@ -2355,7 +2380,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (!cctrue (%d)) goto didnt_jump;\n", curi->cc); if (using_exception_3) { printf ("\tif (src & 1) {\n"); - printf ("\t\texception3i (opcode, m68k_getpc () + 2, m68k_getpc () + 2 + (uae_s32)src);\n"); + printf ("\t\texception3i (opcode, m68k_getpc () + 2 + (uae_s32)src);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -2423,7 +2448,7 @@ static void gen_opcode (unsigned long int opcode) addcycles_ce020 (4); if (using_exception_3) { printf ("\t\t\tif (offs & 1) {\n"); - printf ("\t\t\t\texception3i (opcode, m68k_getpc () + 2, m68k_getpc () + 2 + (uae_s32)offs + 2);\n"); + printf ("\t\t\t\texception3i (opcode, m68k_getpc () + 2 + (uae_s32)offs + 2);\n"); printf ("\t\t\t\tgoto %s;\n", endlabelstr); printf ("\t\t\t}\n"); need_endlabel = 1; @@ -2461,7 +2486,6 @@ static void gen_opcode (unsigned long int opcode) genastore ("val", curi->smode, "srcreg", curi->size, "src"); break; case i_DIVU: - printf ("\tuaecptr oldpc = m68k_getpc ();\n"); genamode (curi->smode, "srcreg", sz_word, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); printf ("\tCLEAR_CZNV ();\n"); @@ -2474,7 +2498,7 @@ static void gen_opcode (unsigned long int opcode) printf("\t\tif (dst < 0) SET_NFLG (1);\n"); } incpc ("%d", m68k_pc_offset); - printf ("\t\tException (5, oldpc);\n"); + printf ("\t\tException (5);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t} else {\n"); printf ("\t\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n"); @@ -2509,7 +2533,6 @@ static void gen_opcode (unsigned long int opcode) need_endlabel = 1; break; case i_DIVS: - printf ("\tuaecptr oldpc = m68k_getpc ();\n"); genamode (curi->smode, "srcreg", sz_word, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); printf ("\tCLEAR_CZNV ();\n"); @@ -2522,7 +2545,7 @@ static void gen_opcode (unsigned long int opcode) printf("\t\tSET_ZFLG (1);\n"); } incpc ("%d", m68k_pc_offset); - printf ("\t\tException (5, oldpc);\n"); + printf ("\t\tException (5);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t} else {\n"); printf ("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); @@ -2602,27 +2625,25 @@ static void gen_opcode (unsigned long int opcode) insn_n_cycles += (70 - 38) / 2 + 38; /* average */ break; case i_CHK: - printf ("\tuaecptr oldpc = m68k_getpc ();\n"); genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); sync_m68k_pc (); addcycles000 (4); printf ("\tif (dst > src) {\n"); printf ("\t\tSET_NFLG (0);\n"); - printf ("\t\tException (6, oldpc);\n"); + printf ("\t\tException (6);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); addcycles000 (2); printf ("\tif ((uae_s32)dst < 0) {\n"); printf ("\t\tSET_NFLG (1);\n"); - printf ("\t\tException (6, oldpc);\n"); + printf ("\t\tException (6);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); fill_prefetch_next (); need_endlabel = 1; break; case i_CHK2: - printf ("\tuaecptr oldpc = m68k_getpc ();\n"); genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0); fill_prefetch_0 (); @@ -2644,7 +2665,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); - printf ("\tif ((extra & 0x800) && GET_CFLG ()) { Exception (6, oldpc); goto %s; }\n}\n", endlabelstr); + printf ("\tif ((extra & 0x800) && GET_CFLG ()) { Exception (6); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; @@ -3182,18 +3203,17 @@ static void gen_opcode (unsigned long int opcode) if (curi->smode != am_unknown && curi->smode != am_illg) genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0, 0); fill_prefetch_0 (); - printf ("\tif (cctrue (%d)) { Exception (7, m68k_getpc ()); goto %s; }\n", curi->cc, endlabelstr); + printf ("\tif (cctrue (%d)) { Exception (7); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: - printf ("\tuaecptr oldpc = m68k_getpc ();\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); } sync_m68k_pc (); - printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n"); + printf ("\tm68k_divl(opcode, dst, extra);\n"); break; case i_MULL: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0); @@ -3341,7 +3361,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (!is_cycle_ce ()) {\n"); genastore ("src", curi->smode, "srcreg", curi->size, "src"); printf ("\t} else {\n"); - printf ("\t\tdo_cycles_ce000 (4);\n"); + printf ("\t\t%s (4);\n", do_cycles); printf ("\t}\n"); } break; @@ -3620,7 +3640,7 @@ static char *outopcode (int opcode) return out; } -static void generate_one_opcode (int rp) +static void generate_one_opcode (int rp, char *extra) { int idx; uae_u16 smsk, dmsk; @@ -3642,21 +3662,21 @@ static void generate_one_opcode (int rp) if (opcode_next_clev[rp] != cpu_level) { char *name = ua (lookuptab[idx].name); if (generate_stbl) - fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d), %d }, /* %s */\n", + fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), %d }, /* %s */\n", (using_ce || using_ce020) ? "(cpuop_func*)" : "", opcode, opcode_last_postfix[rp], - opcode, name); + extra, opcode, name); xfree (name); return; } - fprintf (headerfile, "extern %s op_%04lx_%d_nf;\n", - (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix); - fprintf (headerfile, "extern %s op_%04lx_%d_ff;\n", - (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix); + fprintf (headerfile, "extern %s op_%04lx_%d%s_nf;\n", + (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix, extra); + fprintf (headerfile, "extern %s op_%04lx_%d%s_ff;\n", + (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix, extra); printf ("/* %s */\n", outopcode (opcode)); if (i68000) printf("#ifndef CPUEMU_68000_ONLY\n"); - printf ("%s REGPARAM2 CPUFUNC(op_%04lx_%d)(uae_u32 opcode)\n{\n", (using_ce || using_ce020) ? "void" : "unsigned long", opcode, postfix); + printf ("%s REGPARAM2 CPUFUNC(op_%04lx_%d%s)(uae_u32 opcode)\n{\n", (using_ce || using_ce020) ? "void" : "unsigned long", opcode, postfix, extra); switch (table68k[opcode].stype) { case 0: smsk = 7; break; @@ -3748,16 +3768,16 @@ static void generate_one_opcode (int rp) char *name = ua (lookuptab[idx].name); if (i68000) fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n"); - fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d), %d }, /* %s */\n", + fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), %d }, /* %s */\n", (using_ce || using_ce020) ? "(cpuop_func*)" : "", - opcode, postfix, opcode, name); + opcode, postfix, extra, opcode, name); if (i68000) fprintf (stblfile, "#endif\n"); xfree (name); } } -static void generate_func (void) +static void generate_func (char *extra) { int j, rp; @@ -3783,7 +3803,7 @@ static void generate_func (void) int k = (j * nr_cpuop_funcs) / 8; printf ("#ifdef PART_%d\n",j); for (; rp < k; rp++) - generate_one_opcode (rp); + generate_one_opcode (rp, extra); printf ("#endif\n\n"); } @@ -3791,10 +3811,89 @@ static void generate_func (void) fprintf (stblfile, "{ 0, 0 }};\n"); } -int main (int argc, char **argv) +static void generate_cpu (int id, int mode) { - int i, rp, postfix2; char fname[100]; + char *extra, *extraup; + static int postfix2 = -1; + int rp; + + using_tracer = mode; + extra = ""; + extraup = ""; + if (using_tracer) { + extra = "_t"; + extraup = "_T"; + } + + postfix = id; + if (id == 0 || id == 11 || id == 12 || id == 20 || id == 21 || id == 31) { + if (generate_stbl) + fprintf (stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup); + postfix2 = postfix; + sprintf (fname, "cpuemu_%d%s.cpp", postfix, extra); + freopen (fname, "wb", stdout); + generate_includes (stdout); + } + + using_mmu = 0; + using_prefetch = 0; + using_ce = 0; + using_ce020 = 0; + using_mmu = 0; + + if (id == 11 || id == 12) { // 11 = 68000 prefetch, 12 = 68000 cycle-exact + cpu_level = 0; + using_prefetch = 1; + using_exception_3 = 1; + if (id == 12) + using_ce = 1; + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = 0; + } else if (id == 20) { // 68020 cycle-exact + cpu_level = 2; + using_ce020 = 1; + read_counts (); + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = cpu_level; + } else if (id == 21 || id == 22 || id == 23) { // 68030+ "cycle-exact" + cpu_level = 3 + (23 - id); + using_ce020 = 2; + if (id == 21) { + read_counts (); + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = cpu_level; + } + } else if (id >= 31 && id < 40) { // 31 = 68040 MMU + cpu_level = 4; + using_mmu = 1; + if (id == 31) + read_counts (); + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = cpu_level; + } else { + cpu_level = 5 - id; // "generic" + } + using_indirect = using_ce && !using_ce020; + + if (generate_stbl) { + if ((id > 0 && id < 10) || (id >= 20)) + fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n"); + fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d%s)[] = {\n", postfix, extra); + } + generate_func (extra); + if (generate_stbl) { + if ((id > 0 && id < 10) || (id >= 20)) + fprintf (stblfile, "#endif /* CPUEMU_68000_ONLY */\n"); + if (postfix2 >= 0) + fprintf (stblfile, "#endif /* CPUEMU_%d%s */\n", postfix2, extraup); + } + postfix2 = -1; +} + +int main (int argc, char **argv) +{ + int i; read_table68k (); do_merges (); @@ -3819,70 +3918,11 @@ int main (int argc, char **argv) using_exception_3 = 1; using_ce = 0; - postfix2 = -1; for (i = 0; i < 32; i++) { - postfix = i; if ((i >= 6 && i < 11) || (i > 12 && i < 20) || (i > 23 && i < 31)) continue; generate_stbl = 1; - if (i == 0 || i == 11 || i == 12 || i == 20 || i == 21 || i == 31) { - if (generate_stbl) - fprintf (stblfile, "#ifdef CPUEMU_%d\n", postfix); - postfix2 = postfix; - sprintf (fname, "cpuemu_%d.cpp", postfix); - freopen (fname, "wb", stdout); - generate_includes (stdout); - } - using_mmu = 0; - using_prefetch = 0; - using_ce = 0; - using_ce020 = 0; - using_mmu = 0; - cpu_level = 5 - i; - if (i == 11 || i == 12) { - cpu_level = 0; - using_prefetch = 1; - using_exception_3 = 1; - if (i == 12) - using_ce = 1; - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = 0; - } else if (i == 20) { - cpu_level = 2; - using_ce020 = 1; - read_counts (); - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = cpu_level; - } else if (i == 21 || i == 22 || i == 23) { - cpu_level = 3 + (23 - i); - using_ce020 = 2; - if (i == 21) { - read_counts (); - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = cpu_level; - } - } else if (i >= 31 && i < 40) { - cpu_level = 4; - using_mmu = 1; - if (i == 31) - read_counts (); - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = cpu_level; - } - - if (generate_stbl) { - if ((i > 0 && i < 10) || (i >= 20)) - fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n"); - fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); - } - generate_func (); - if (generate_stbl) { - if ((i > 0 && i < 10) || (i >= 20)) - fprintf (stblfile, "#endif /* CPUEMU_68000_ONLY */\n"); - if (postfix2 >= 0) - fprintf (stblfile, "#endif /* CPUEMU_%d */\n", postfix2); - } - postfix2 = -1; + generate_cpu (i, 0); } free (table68k); diff --git a/include/blkdev.h b/include/blkdev.h index edbf4d11..b267a233 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -122,6 +122,7 @@ typedef int (*rawread_func)(int, uae_u8*, int, int, int, uae_u32); typedef int (*write_func)(int, uae_u8*, int, int); typedef int (*isatapi_func)(int); typedef int (*ismedia_func)(int, int); +typedef int (*scsiemu_func)(int, uae_u8*); struct device_functions { const TCHAR *name; @@ -147,6 +148,8 @@ struct device_functions { isatapi_func isatapi; ismedia_func ismedia; + scsiemu_func scsiemu; + }; extern struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; diff --git a/include/cia.h b/include/cia.h index b76d5888..63398bba 100644 --- a/include/cia.h +++ b/include/cia.h @@ -7,8 +7,10 @@ */ extern void CIA_reset (void); -extern void CIA_vsync_handler (int); -extern void CIA_hsync_handler (int); +extern void CIA_vsync_prehandler (void); +extern void CIA_hsync_prehandler (void); +extern void CIA_vsync_posthandler (bool); +extern void CIA_hsync_posthandler (bool); extern void CIA_handler (void); extern void diskindex_handler (void); @@ -24,6 +26,4 @@ extern int parallel_direct_read_data (uae_u8*); extern int parallel_direct_write_status (uae_u8, uae_u8); extern int parallel_direct_read_status (uae_u8*); -extern void CIA_inprec_prepare(void); - -extern void rtc_hardreset(void); +extern void rtc_hardreset (void); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index db273c79..b35d2df1 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -14,6 +14,17 @@ STATIC_INLINE uae_u32 get_long_prefetch (int o) #ifdef CPUEMU_20 + +STATIC_INLINE void do_cycles_ce020 (int clocks) +{ + do_cycles_ce (clocks * cpucycleunit); +} +STATIC_INLINE void do_cycles_ce020_mem (int clocks) +{ + regs.ce020memcycles -= clocks * cpucycleunit; + do_cycles_ce (clocks * cpucycleunit); +} + STATIC_INLINE void checkcycles_ce020 (void) { if (regs.ce020memcycles > 0) @@ -259,6 +270,8 @@ STATIC_INLINE void m68k_do_rts_ce020 (void) m68k_setpc (get_long_ce020 (m68k_areg (regs, 7))); m68k_areg (regs, 7) += 4; } + + #endif #ifdef CPUEMU_21 @@ -327,10 +340,16 @@ STATIC_INLINE void m68k_do_rts_ce030 (void) m68k_setpc (get_long_ce030 (m68k_areg (regs, 7))); m68k_areg (regs, 7) += 4; } + #endif #ifdef CPUEMU_12 +STATIC_INLINE void do_cycles_ce000 (int clocks) +{ + x_do_cycles (clocks * cpucycleunit); +} + STATIC_INLINE void ipl_fetch (void) { regs.ipl = regs.ipl_pin; @@ -344,8 +363,9 @@ STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr) return wait_cpu_cycle_read (addr, 1); case CE_MEMBANK_FAST: case CE_MEMBANK_FAST16BIT: - do_cycles_ce000 (4); - break; + uae_u32 v = get_word (addr); + x_do_cycles_post (4 * cpucycleunit, v); + return v; } return get_word (addr); } @@ -357,8 +377,9 @@ STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr) return wait_cpu_cycle_read (addr, 1); case CE_MEMBANK_FAST: case CE_MEMBANK_FAST16BIT: - do_cycles_ce000 (4); - break; + uae_u32 v = get_wordi (addr); + x_do_cycles_post (4 * cpucycleunit, v); + return v; } return get_wordi (addr); } @@ -371,9 +392,9 @@ STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr) return wait_cpu_cycle_read (addr, 0); case CE_MEMBANK_FAST: case CE_MEMBANK_FAST16BIT: - do_cycles_ce000 (4); - break; - + uae_u32 v = get_byte (addr); + x_do_cycles_post (4 * cpucycleunit, v); + return v; } return get_byte (addr); } @@ -386,8 +407,9 @@ STATIC_INLINE void mem_access_delay_byte_write (uaecptr addr, uae_u32 v) return; case CE_MEMBANK_FAST: case CE_MEMBANK_FAST16BIT: - do_cycles_ce000 (4); - break; + put_byte (addr, v); + x_do_cycles_post (4 * cpucycleunit, v); + return; } put_byte (addr, v); } @@ -398,50 +420,50 @@ STATIC_INLINE void mem_access_delay_word_write (uaecptr addr, uae_u32 v) case CE_MEMBANK_CHIP: wait_cpu_cycle_write (addr, 1, v); return; - break; case CE_MEMBANK_FAST: case CE_MEMBANK_FAST16BIT: - do_cycles_ce000 (4); - break; + put_word (addr, v); + x_do_cycles_post (4 * cpucycleunit, v); + return; } put_word (addr, v); } -STATIC_INLINE uae_u32 get_long_ce (uaecptr addr) +STATIC_INLINE uae_u32 get_long_ce000 (uaecptr addr) { uae_u32 v = mem_access_delay_word_read (addr) << 16; v |= mem_access_delay_word_read (addr + 2); return v; } -STATIC_INLINE uae_u32 get_word_ce (uaecptr addr) +STATIC_INLINE uae_u32 get_word_ce000 (uaecptr addr) { return mem_access_delay_word_read (addr); } -STATIC_INLINE uae_u32 get_wordi_ce (uaecptr addr) +STATIC_INLINE uae_u32 get_wordi_ce000 (int offset) { - return mem_access_delay_wordi_read (addr); + return mem_access_delay_wordi_read (m68k_getpc () + offset); } -STATIC_INLINE uae_u32 get_byte_ce (uaecptr addr) +STATIC_INLINE uae_u32 get_byte_ce000 (uaecptr addr) { return mem_access_delay_byte_read (addr); } -STATIC_INLINE uae_u32 get_word_ce_prefetch (int o) +STATIC_INLINE uae_u32 get_word_ce000_prefetch (int o) { uae_u32 v = regs.irc; - regs.irc = get_wordi_ce (m68k_getpc () + o); + regs.irc = x_get_iword (o); return v; } -STATIC_INLINE void put_long_ce (uaecptr addr, uae_u32 v) +STATIC_INLINE void put_long_ce000 (uaecptr addr, uae_u32 v) { mem_access_delay_word_write (addr, v >> 16); mem_access_delay_word_write (addr + 2, v); } -STATIC_INLINE void put_word_ce (uaecptr addr, uae_u32 v) +STATIC_INLINE void put_word_ce000 (uaecptr addr, uae_u32 v) { mem_access_delay_word_write (addr, v); } -STATIC_INLINE void put_byte_ce (uaecptr addr, uae_u32 v) +STATIC_INLINE void put_byte_ce000 (uaecptr addr, uae_u32 v) { mem_access_delay_byte_write (addr, v); } @@ -449,11 +471,11 @@ STATIC_INLINE void put_byte_ce (uaecptr addr, uae_u32 v) STATIC_INLINE void m68k_do_rts_ce (void) { uaecptr pc; - pc = get_word_ce (m68k_areg (regs, 7)) << 16; - pc |= get_word_ce (m68k_areg (regs, 7) + 2); + pc = x_get_word (m68k_areg (regs, 7)) << 16; + pc |= x_get_word (m68k_areg (regs, 7) + 2); m68k_areg (regs, 7) += 4; if (pc & 1) - exception3 (0x4e75, m68k_getpc (), pc); + exception3 (0x4e75, pc); else m68k_setpc (pc); } @@ -461,16 +483,26 @@ STATIC_INLINE void m68k_do_rts_ce (void) STATIC_INLINE void m68k_do_bsr_ce (uaecptr oldpc, uae_s32 offset) { m68k_areg (regs, 7) -= 4; - put_word_ce (m68k_areg (regs, 7), oldpc >> 16); - put_word_ce (m68k_areg (regs, 7) + 2, oldpc); + x_put_word (m68k_areg (regs, 7), oldpc >> 16); + x_put_word (m68k_areg (regs, 7) + 2, oldpc); m68k_incpc (offset); } STATIC_INLINE void m68k_do_jsr_ce (uaecptr oldpc, uaecptr dest) { m68k_areg (regs, 7) -= 4; - put_word_ce (m68k_areg (regs, 7), oldpc >> 16); - put_word_ce (m68k_areg (regs, 7) + 2, oldpc); + x_put_word (m68k_areg (regs, 7), oldpc >> 16); + x_put_word (m68k_areg (regs, 7) + 2, oldpc); m68k_setpc (dest); } -#endif \ No newline at end of file + +#endif + +STATIC_INLINE uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp) +{ + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + return base + (uae_s8)dp + regd; +} diff --git a/include/custom.h b/include/custom.h index 61d77941..655c3539 100644 --- a/include/custom.h +++ b/include/custom.h @@ -1,15 +1,15 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * custom chip support - * - * (c) 1995 Bernd Schmidt - */ +/* +* UAE - The Un*x Amiga Emulator +* +* custom chip support +* +* (c) 1995 Bernd Schmidt +*/ #include "machdep/rpt.h" /* These are the masks that are ORed together in the chipset_mask option. - * If CSMASK_AGA is set, the ECS bits are guaranteed to be set as well. */ +* If CSMASK_AGA is set, the ECS bits are guaranteed to be set as well. */ #define CSMASK_ECS_AGNUS 1 #define CSMASK_ECS_DENISE 2 #define CSMASK_AGA 4 @@ -18,7 +18,8 @@ uae_u32 get_copper_address (int copno); extern int custom_init (void); -extern void customreset (int hardreset); +extern void custom_prepare (void); +extern void custom_reset (int hardreset); extern int intlev (void); extern void dumpcustom (void); @@ -28,7 +29,7 @@ extern void do_copper (void); extern void notice_new_xcolors (void); extern void notice_screen_contents_lost (void); extern void init_row_map (void); -extern void init_hz (void); +extern void init_hz_full (void); extern void init_custom (void); extern bool picasso_requested_on; @@ -36,14 +37,13 @@ extern bool picasso_on; extern void set_picasso_hack_rate (int hz); /* Set to 1 to leave out the current frame in average frame time calculation. - * Useful if the debugger was active. */ +* Useful if the debugger was active. */ extern int bogusframe; -extern unsigned long int hsync_counter; +extern unsigned long int hsync_counter, vsync_counter; extern uae_u16 dmacon; extern uae_u16 intena, intreq, intreqr; -extern int current_hpos (void); extern int vpos; extern int find_copper_record (uaecptr, int *, int *); @@ -52,7 +52,7 @@ extern int n_frames; STATIC_INLINE int dmaen (unsigned int dmamask) { - return (dmamask & dmacon) && (dmacon & 0x200); + return (dmamask & dmacon) && (dmacon & 0x200); } #define SPCFLAG_STOP 2 @@ -130,11 +130,11 @@ extern frame_time_t syncbase; #define CYCLE_REFRESH 0x01 #define CYCLE_STROBE 0x02 -#define CYCLE_MISC 0x04 +#define CYCLE_MISC 0x04 #define CYCLE_SPRITE 0x08 #define CYCLE_COPPER 0x10 #define CYCLE_BLITTER 0x20 -#define CYCLE_CPU 0x40 +#define CYCLE_CPU 0x40 #define CYCLE_CPUNASTY 0x80 extern unsigned long frametime, timeframes; @@ -142,8 +142,8 @@ extern int plfstrt, plfstop, plffirstline, plflastline; extern uae_u16 htotal, vtotal, beamcon0; /* 100 words give you 1600 horizontal pixels. Should be more than enough for - * superhires. Don't forget to update the definition in genp2c.c as well. - * needs to be larger for superhires support */ +* superhires. Don't forget to update the definition in genp2c.c as well. +* needs to be larger for superhires support */ #ifdef CUSTOM_SIMPLE #define MAX_WORDS_PER_LINE 50 #else @@ -178,26 +178,26 @@ extern int xbluecolor_s, xbluecolor_b, xbluecolor_m; /* get resolution from bplcon0 */ STATIC_INLINE int GET_RES_DENISE (uae_u16 con0) { - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - con0 &= ~0x40; - return ((con0) & 0x8000) ? RES_HIRES : ((con0) & 0x40) ? RES_SUPERHIRES : RES_LORES; + if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) + con0 &= ~0x40; // SUPERHIRES + return ((con0) & 0x8000) ? RES_HIRES : ((con0) & 0x40) ? RES_SUPERHIRES : RES_LORES; } STATIC_INLINE int GET_RES_AGNUS (uae_u16 con0) { - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - con0 &= ~0x40; - return ((con0) & 0x8000) ? RES_HIRES : ((con0) & 0x40) ? RES_SUPERHIRES : RES_LORES; + if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + con0 &= ~0x40; // SUPERHIRES + return ((con0) & 0x8000) ? RES_HIRES : ((con0) & 0x40) ? RES_SUPERHIRES : RES_LORES; } /* get sprite width from FMODE */ #define GET_SPRITEWIDTH(FMODE) ((((FMODE) >> 2) & 3) == 3 ? 64 : (((FMODE) >> 2) & 3) == 0 ? 16 : 32) /* Compute the number of bitplanes from a value written to BPLCON0 */ STATIC_INLINE int GET_PLANES(uae_u16 bplcon0) { - if ((bplcon0 & 0x0010) && (bplcon0 & 0x7000)) - return 0; - if (bplcon0 & 0x0010) - return 8; - return (bplcon0 >> 12) & 7; + if ((bplcon0 & 0x0010) && (bplcon0 & 0x7000)) + return 0; // >8 planes = 0 planes + if (bplcon0 & 0x0010) + return 8; // AGA 8-planes bit + return (bplcon0 >> 12) & 7; // normal planes bits } extern void fpscounter_reset (void); @@ -205,10 +205,11 @@ extern unsigned long idletime; extern int lightpen_x, lightpen_y, lightpen_cx, lightpen_cy; struct customhack { - uae_u16 v; - int vpos, hpos; + uae_u16 v; + int vpos, hpos; }; void customhack_put (struct customhack *ch, uae_u16 v, int hpos); uae_u16 customhack_get (struct customhack *ch, int hpos); extern void alloc_cycle_ext (int, int); extern bool ispal (void); +extern int current_maxvpos (void); \ No newline at end of file diff --git a/include/disk.h b/include/disk.h index 4e30a5a6..45514d4d 100644 --- a/include/disk.h +++ b/include/disk.h @@ -14,12 +14,13 @@ typedef enum { DRV_NONE = -1, DRV_35_DD = 0, DRV_35_HD, DRV_525_SD, DRV_35_DD_ES extern void DISK_init (void); extern void DISK_free (void); extern void DISK_select (uae_u8 data); +extern void DISK_select_set (uae_u8 data); extern uae_u8 DISK_status (void); extern void disk_eject (int num); extern int disk_empty (int num); extern void disk_insert (int num, const TCHAR *name); -extern void disk_insert_force (int num, const TCHAR *name); -extern void DISK_check_change (void); +extern void disk_insert_force (int num, const TCHAR *name, bool writeprotected); +extern void DISK_vsync (void); extern int DISK_validate_filename (const TCHAR *fname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf); extern void DISK_handler (uae_u32); extern void DISK_update (int hpos); diff --git a/include/drawing.h b/include/drawing.h index 50b34979..df402501 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -277,6 +277,7 @@ extern void notice_interlace_seen (void); extern void frame_drawn (void); extern void redraw_frame (void); extern int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy); +extern void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq); /* Finally, stuff that shouldn't really be shared. */ diff --git a/include/events.h b/include/events.h index 944980df..40b4c1ba 100644 --- a/include/events.h +++ b/include/events.h @@ -20,13 +20,12 @@ extern volatile frame_time_t vsynctime, vsyncmintime; extern void reset_frame_rate_hack (void); extern int rpt_available; extern frame_time_t syncbase; +extern unsigned long int vsync_cycles; +extern unsigned long start_cycles; extern void compute_vsynctime (void); extern void init_eventtab (void); -extern void do_cycles_ce (long cycles); -extern void do_cycles_ce020 (int clocks); -extern void do_cycles_ce020_mem (int clocks); -extern void do_cycles_ce000 (int clocks); +extern void do_cycles_ce (unsigned long cycles); extern int is_cycle_ce (void); extern unsigned long currcycle, nextevent, is_lastline; diff --git a/include/events_jit.h b/include/events_jit.h index 5b54cc10..d32a6bb6 100644 --- a/include/events_jit.h +++ b/include/events_jit.h @@ -51,6 +51,7 @@ STATIC_INLINE unsigned long int get_cycles (void) STATIC_INLINE void set_cycles (unsigned long int x) { currcycle = x; + eventtab[ev_hsync].oldcycles = x; #ifdef EVT_DEBUG if (currcycle & (CYCLE_UNIT - 1)) write_log (L"%x\n", currcycle); @@ -96,18 +97,3 @@ STATIC_INLINE void do_cycles_slow (unsigned long cycles_to_add) #define do_cycles do_cycles_slow #define countdown pissoff - -/* This is a special-case function. Normally, all events should lie in the -future; they should only ever be active at the current cycle during -do_cycles. However, a snapshot is saved during do_cycles, and so when -restoring it, we may have other events pending. */ - -STATIC_INLINE void handle_active_events (void) -{ - int i; - for (i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == currcycle) { - (*eventtab[i].handler)(); - } - } -} diff --git a/include/fsdb.h b/include/fsdb.h index 08abbf3f..5157ada3 100644 --- a/include/fsdb.h +++ b/include/fsdb.h @@ -16,28 +16,32 @@ #endif /* AmigaOS errors */ -#define ERROR_BAD_NUMBER 6 -#define ERROR_NO_FREE_STORE 103 -#define ERROR_OBJECT_IN_USE 202 -#define ERROR_OBJECT_EXISTS 203 -#define ERROR_DIR_NOT_FOUND 204 +#define ERROR_BAD_NUMBER 6 +#define ERROR_NO_FREE_STORE 103 +#define ERROR_OBJECT_IN_USE 202 +#define ERROR_OBJECT_EXISTS 203 +#define ERROR_DIR_NOT_FOUND 204 #define ERROR_OBJECT_NOT_AROUND 205 #define ERROR_ACTION_NOT_KNOWN 209 -#define ERROR_INVALID_LOCK 211 +#define ERROR_INVALID_LOCK 211 #define ERROR_OBJECT_WRONG_TYPE 212 #define ERROR_DISK_WRITE_PROTECTED 214 #define ERROR_DIRECTORY_NOT_EMPTY 216 #define ERROR_DEVICE_NOT_MOUNTED 218 -#define ERROR_SEEK_ERROR 219 +#define ERROR_SEEK_ERROR 219 #define ERROR_COMMENT_TOO_BIG 220 -#define ERROR_DISK_IS_FULL 221 +#define ERROR_DISK_IS_FULL 221 #define ERROR_DELETE_PROTECTED 222 #define ERROR_WRITE_PROTECTED 223 #define ERROR_READ_PROTECTED 224 #define ERROR_NOT_A_DOS_DISK 225 -#define ERROR_NO_DISK 226 +#define ERROR_NO_DISK 226 #define ERROR_NO_MORE_ENTRIES 232 #define ERROR_NOT_IMPLEMENTED 236 +#define ERROR_RECORD_NOT_LOCKED 240 +#define ERROR_LOCK_COLLISION 241 +#define ERROR_LOCK_TIMEOUT 242 +#define ERROR_UNLOCK_ERROR 243 #define A_FIBF_HIDDEN (1<<7) #define A_FIBF_SCRIPT (1<<6) diff --git a/include/gfxfilter.h b/include/gfxfilter.h index 98a68d14..92129c18 100644 --- a/include/gfxfilter.h +++ b/include/gfxfilter.h @@ -8,6 +8,7 @@ typedef unsigned long u32; extern void S2X_refresh (void); extern void S2X_render (void); extern void S2X_init (int dw, int dh, int aw, int ah, int ad, int dd); +extern void S2X_reset (void); extern void S2X_free (void); extern int S2X_getmult (void); diff --git a/include/inputdevice.h b/include/inputdevice.h index 0351b405..478417e0 100644 --- a/include/inputdevice.h +++ b/include/inputdevice.h @@ -126,8 +126,6 @@ INPUTEVENT_END extern void handle_cd32_joystick_cia (uae_u8, uae_u8); extern uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra); extern uae_u8 handle_joystick_buttons (uae_u8, uae_u8); -extern int getbuttonstate (int joy, int button); -extern int getjoystate (int joy); #define MAGICMOUSE_BOTH 0 #define MAGICMOUSE_NATIVE_ONLY 1 @@ -154,7 +152,6 @@ extern void inputdevice_devicechange (struct uae_prefs *prefs); extern int inputdevice_translatekeycode (int keyboard, int scancode, int state); extern void inputdevice_setkeytranslation (struct uae_input_device_kbr_default *trans, int **kbmaps); -extern int handle_input_event (int nr, int state, int max, int autofire); extern void inputdevice_do_keyboard (int code, int state); extern int inputdevice_iskeymapped (int keyboard, int scancode); extern int inputdevice_synccapslock (int, int*); @@ -175,6 +172,8 @@ extern uae_u16 POT1DAT (void); extern void JOYTEST (uae_u16 v); extern uae_u16 JOY0DAT (void); extern uae_u16 JOY1DAT (void); +extern void JOYSET (int num, uae_u16 v); +extern uae_u16 JOYGET (int num); extern void inputdevice_vsync (void); extern void inputdevice_hsync (void); @@ -211,10 +210,11 @@ extern void inputdevice_tablet_strobe (void); #define JSEM_MODE_DEFAULT 0 #define JSEM_MODE_MOUSE 1 #define JSEM_MODE_JOYSTICK 2 -#define JSEM_MODE_JOYSTICK_ANALOG 3 -#define JSEM_MODE_MOUSE_CDTV 4 -#define JSEM_MODE_JOYSTICK_CD32 5 -#define JSEM_MODE_LIGHTPEN 6 +#define JSEM_MODE_GAMEPAD 3 +#define JSEM_MODE_JOYSTICK_ANALOG 4 +#define JSEM_MODE_MOUSE_CDTV 5 +#define JSEM_MODE_JOYSTICK_CD32 6 +#define JSEM_MODE_LIGHTPEN 7 #define JSEM_KBDLAYOUT 0 #define JSEM_JOYS 100 @@ -237,33 +237,6 @@ extern int jsem_iskbdjoy (int port, const struct uae_prefs *p); extern int inputdevice_uaelib (TCHAR *, TCHAR *); -#define INPREC_JOYPORT 1 -#define INPREC_JOYBUTTON 2 -#define INPREC_KEY 3 -#define INPREC_DISKINSERT 4 -#define INPREC_DISKREMOVE 5 -#define INPREC_VSYNC 6 -#define INPREC_CIAVSYNC 7 -#define INPREC_STATEFILE 0x7f -#define INPREC_END 0xff -#define INPREC_QUIT 0xfe - -extern int input_recording; -extern void inprec_close (void); -extern int inprec_open (const TCHAR*, int); -extern void inprec_rend (void); -extern void inprec_rstart (uae_u8); -extern void inprec_ru8 (uae_u8); -extern void inprec_ru16 (uae_u16); -extern void inprec_ru32 (uae_u32); -extern void inprec_rstr (const TCHAR*); -extern int inprec_pstart (uae_u8); -extern void inprec_pend (void); -extern uae_u8 inprec_pu8 (void); -extern uae_u16 inprec_pu16 (void); -extern uae_u32 inprec_pu32 (void); -extern int inprec_pstr (TCHAR*); - extern int inputdevice_testread (int*, int*, int*); extern int inputdevice_istest (void); extern void inputdevice_settest (int); diff --git a/include/inputrecord.h b/include/inputrecord.h new file mode 100644 index 00000000..0a307616 --- /dev/null +++ b/include/inputrecord.h @@ -0,0 +1,56 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * Input recording and playback + * + * Copyright 2010 Toni Wilen + */ + +extern int inputrecord_debug; + +//#define INPREC_JOYPORT 1 +//#define INPREC_JOYBUTTON 2 +//#define INPREC_KEY 3 +#define INPREC_DISKINSERT 4 +#define INPREC_DISKREMOVE 5 +//#define INPREC_VSYNC 6 +//#define INPREC_CIAVSYNC 7 +#define INPREC_EVENT 8 +#define INPREC_CIADEBUG 0x61 +#define INPREC_DEBUG 0x62 +#define INPREC_DEBUG2 0x63 +#define INPREC_STOP 0x7d +#define INPREC_END 0x7e +#define INPREC_QUIT 0x7f + +#define INPREC_RECORD_START 1 +#define INPREC_RECORD_NORMAL 2 +#define INPREC_RECORD_RERECORD 3 +#define INPREC_RECORD_PLAYING 4 +#define INPREC_PLAY_NORMAL 1 +#define INPREC_PLAY_RERECORD 2 + +extern int input_record, input_play; +extern void inprec_close (bool); +extern void inprec_save (const TCHAR*, const TCHAR*); +extern int inprec_open (const TCHAR*, const TCHAR*); +extern bool inprec_prepare_record (const TCHAR*); +extern void inprec_playtorecord (void); +extern void inprec_startup (void); + +extern bool inprec_playevent (int *nr, int *state, int *max, int *autofire); +extern void inprec_playdiskchange (void); +extern void inprec_recordevent (int nr, int state, int max, int autofire); +extern void inprec_recorddiskchange (int nr, const TCHAR *fname, bool writeprotected); + +extern void inprec_recorddebug (uae_u32); +extern void inprec_playdebug (uae_u32); +extern void inprec_recorddebug_cpu (int); +extern void inprec_playdebug_cpu (int); +extern void inprec_recorddebug_cia (uae_u32, uae_u32, uae_u32); +extern void inprec_playdebug_cia (uae_u32, uae_u32, uae_u32); + +extern int inprec_getposition (void); +extern void inprec_setposition (int offset, int replaycounter); +extern bool inprec_realtime (void); +extern void inprec_getstatus (TCHAR*); \ No newline at end of file diff --git a/include/keyboard.h b/include/keyboard.h index 7ce9f6d9..e1bcbded 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -138,7 +138,8 @@ enum aks { AKS_ENTERGUI = 0x200, AKS_SCREENSHOT_FILE, AKS_SCREENSHOT_CLIPBOARD, AKS_TOGGLEDEFAULTSCREEN, AKS_TOGGLEWINDOWEDFULLSCREEN, AKS_TOGGLEFULLWINDOWFULLSCREEN, AKS_TOGGLEWINDOWFULLWINDOW, AKS_ENTERDEBUGGER, AKS_IRQ7, - AKS_PAUSE, AKS_WARP, AKS_INHIBITSCREEN, AKS_STATEREWIND, + AKS_PAUSE, AKS_WARP, AKS_INHIBITSCREEN, + AKS_STATEREWIND, AKS_STATECURRENT, AKS_STATECAPTURE, AKS_VOLDOWN, AKS_VOLUP, AKS_VOLMUTE, AKS_MVOLDOWN, AKS_MVOLUP, AKS_MVOLMUTE, AKS_QUIT, AKS_HARDRESET, AKS_SOFTRESET, diff --git a/include/newcpu.h b/include/newcpu.h index df31789a..1336063c 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -84,7 +84,7 @@ typedef double fptype; #endif #endif -#define CPU_PIPELINE_MAX 2 +#define CPU_PIPELINE_MAX 3 #define CPU000_MEM_CYCLE 4 #define CPU000_CLOCK_MULT 2 #define CPU020_MEM_CYCLE 3 @@ -123,6 +123,7 @@ struct regstruct uae_u32 pc; uae_u8 *pc_p; uae_u8 *pc_oldp; + uae_u32 instruction_pc; uae_u16 irc, ir; uae_u32 spcflags; @@ -135,6 +136,7 @@ struct regstruct flagtype m; flagtype x; flagtype stopped; + int exception; int intmask; int ipl, ipl_pin; @@ -157,7 +159,6 @@ struct regstruct uae_u16 wb3_status; int mmu_enabled; int mmu_pagesize_8k; - uae_u32 fault_pc; #endif uae_u32 pcr; @@ -166,13 +167,35 @@ struct regstruct uae_u8 panic; uae_u32 panic_pc, panic_addr; - uae_u32 prefetch020data[CPU_PIPELINE_MAX]; - uae_u32 prefetch020addr[CPU_PIPELINE_MAX]; + uae_u16 prefetch020[CPU_PIPELINE_MAX]; + uae_u32 prefetch020addr; + uae_u32 cacheholdingdata020; + uae_u32 cacheholdingaddr020; int ce020memcycles; }; extern struct regstruct regs; +#define MAX_CPUTRACESIZE 128 +struct cputracememory +{ + uae_u32 addr; + uae_u32 data; + int mode; +}; + +struct cputracestruct +{ + uae_u32 regs[16]; + uae_u32 usp, isp, pc; + uae_u16 ir, irc, sr, opcode; + int intmask, stopped, state; + int memoryoffset; + int cyclecounter, cyclecounter_pre, cyclecounter_post; + int readcounter, writecounter; + struct cputracememory ctm[MAX_CPUTRACESIZE]; +}; + STATIC_INLINE uae_u32 munge24 (uae_u32 x) { return x & regs.address_space_mask; @@ -198,7 +221,7 @@ STATIC_INLINE void unset_special (uae_u32 x) STATIC_INLINE void m68k_setpc (uaecptr newpc) { regs.pc_p = regs.pc_oldp = get_real_address (newpc); - regs.fault_pc = regs.pc = newpc; + regs.instruction_pc = regs.pc = newpc; } STATIC_INLINE uaecptr m68k_getpc (void) @@ -219,12 +242,12 @@ STATIC_INLINE void m68k_incpc (int o) STATIC_INLINE void m68k_setpc_mmu (uaecptr newpc) { - regs.fault_pc = regs.pc = newpc; + regs.instruction_pc = regs.pc = newpc; regs.pc_p = regs.pc_oldp = 0; } STATIC_INLINE void m68k_setpci (uaecptr newpc) { - regs.fault_pc = regs.pc = newpc; + regs.instruction_pc = regs.pc = newpc; } STATIC_INLINE uaecptr m68k_getpci (void) { @@ -241,11 +264,6 @@ STATIC_INLINE void m68k_do_rts (void) m68k_setpc (newpc); m68k_areg (regs, 7) += 4; } -STATIC_INLINE void m68k_do_rtsi (void) -{ - m68k_setpci (get_long (m68k_areg (regs, 7))); - m68k_areg (regs, 7) += 4; -} STATIC_INLINE void m68k_do_bsr (uaecptr oldpc, uae_s32 offset) { @@ -253,12 +271,6 @@ STATIC_INLINE void m68k_do_bsr (uaecptr oldpc, uae_s32 offset) put_long (m68k_areg (regs, 7), oldpc); m68k_incpc (offset); } -STATIC_INLINE void m68k_do_bsri (uaecptr oldpc, uae_s32 offset) -{ - m68k_areg (regs, 7) -= 4; - put_long (m68k_areg (regs, 7), oldpc); - m68k_incpci (offset); -} STATIC_INLINE uae_u32 get_ibyte (int o) { @@ -309,6 +321,8 @@ STATIC_INLINE uae_u32 next_ilongi (void) return r; } +extern uae_u32 (*x_prefetch)(int); +extern uae_u32 (*x_prefetch_long)(int); extern uae_u32 (*x_get_byte)(uaecptr addr); extern uae_u32 (*x_get_word)(uaecptr addr); extern uae_u32 (*x_get_long)(uaecptr addr); @@ -317,6 +331,12 @@ extern void (*x_put_word)(uaecptr addr, uae_u32 v); extern void (*x_put_long)(uaecptr addr, uae_u32 v); extern uae_u32 (*x_next_iword)(void); extern uae_u32 (*x_next_ilong)(void); +extern uae_u32 (*x_get_ilong)(int); +extern uae_u32 (*x_get_iword)(int); +extern uae_u32 (*x_get_ibyte)(int); +extern void (*x_do_cycles)(unsigned long); +extern void (*x_do_cycles_pre)(unsigned long); +extern void (*x_do_cycles_post)(unsigned long, uae_u32); extern uae_u32 REGPARAM3 x_get_disp_ea_020 (uae_u32 base, uae_u32 dp) REGPARAM; extern uae_u32 REGPARAM3 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM; @@ -326,7 +346,6 @@ extern void m68k_setstopped (void); extern void m68k_resumestopped (void); extern uae_u32 REGPARAM3 get_disp_ea_020 (uae_u32 base, uae_u32 dp) REGPARAM; -extern uae_u32 REGPARAM3 get_disp_ea_000 (uae_u32 base, uae_u32 dp) REGPARAM; extern uae_u32 REGPARAM3 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM; extern void REGPARAM3 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM; @@ -337,7 +356,7 @@ extern int get_cpu_model (void); extern void REGPARAM3 MakeSR (void) REGPARAM; extern void REGPARAM3 MakeFromSR (void) REGPARAM; -extern void REGPARAM3 Exception (int, uaecptr) REGPARAM; +extern void REGPARAM3 Exception (int) REGPARAM; extern void NMI (void); extern void NMI_delayed (void); extern void prepare_interrupt (uae_u32); @@ -345,7 +364,7 @@ extern void doint (void); extern void dump_counts (void); extern int m68k_move2c (int, uae_u32 *); extern int m68k_movec2 (int, uae_u32 *); -extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); +extern void m68k_divl (uae_u32, uae_u32, uae_u16); extern void m68k_mull (uae_u32, uae_u32, uae_u16); extern void init_m68k (void); extern void init_m68k_full (void); @@ -373,12 +392,12 @@ extern void fpu_reset (void); extern void fpux_save (int*); extern void fpux_restore (int*); -extern void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault); -extern void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault); -extern void exception2 (uaecptr addr, uaecptr fault); +extern void exception3 (uae_u32 opcode, uaecptr addr); +extern void exception3i (uae_u32 opcode, uaecptr addr); +extern void exception2 (uaecptr addr); extern void cpureset (void); -extern void fill_prefetch_slow (void); +extern void fill_prefetch (void); #define CPU_OP_NAME(a) op ## a @@ -424,3 +443,7 @@ struct cpum2c { TCHAR *regname; }; extern struct cpum2c m2cregs[]; + +extern bool is_cpu_tracer (void); +extern bool set_cpu_tracer (bool force); +extern bool can_cpu_tracer (void); \ No newline at end of file diff --git a/include/options.h b/include/options.h index d2a4e1c9..3b53deae 100644 --- a/include/options.h +++ b/include/options.h @@ -9,7 +9,7 @@ #define UAEMAJOR 2 #define UAEMINOR 3 -#define UAESUBREV 0 +#define UAESUBREV 1 typedef enum { KBD_LANG_US, KBD_LANG_DK, KBD_LANG_DE, KBD_LANG_SE, KBD_LANG_FR, KBD_LANG_IT, KBD_LANG_ES } KbdLang; @@ -45,6 +45,7 @@ struct uae_input_device { }; #define MAX_JPORTS 4 +#define NORMAL_JPORTS 2 #define MAX_JPORTNAME 128 struct jport { int id; @@ -119,11 +120,12 @@ enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_A500, CP_A500P, CP_A600, CP_A1000, #define GFX_FULLWINDOW 2 #define AUTOSCALE_NONE 0 -#define AUTOSCALE_STATIC_NOMINAL 1 -#define AUTOSCALE_STATIC_MAX 2 -#define AUTOSCALE_NORMAL 3 -#define AUTOSCALE_RESIZE 4 -#define AUTOSCALE_CENTER 5 +#define AUTOSCALE_STATIC_AUTO 1 +#define AUTOSCALE_STATIC_NOMINAL 2 +#define AUTOSCALE_STATIC_MAX 3 +#define AUTOSCALE_NORMAL 4 +#define AUTOSCALE_RESIZE 5 +#define AUTOSCALE_CENTER 6 struct uae_prefs { @@ -194,8 +196,8 @@ struct uae_prefs { struct wh gfx_size_win; struct wh gfx_size_fs; struct wh gfx_size; - struct wh gfx_size_win_xtra[4]; - struct wh gfx_size_fs_xtra[4]; + struct wh gfx_size_win_xtra[6]; + struct wh gfx_size_fs_xtra[6]; bool gfx_autoresolution; bool gfx_scandoubler; int gfx_refreshrate; @@ -309,7 +311,7 @@ struct uae_prefs { TCHAR quitstatefile[MAX_DPATH]; TCHAR statefile[MAX_DPATH]; TCHAR inprecfile[MAX_DPATH]; - int inprecmode; + bool inprec_autoplay; TCHAR path_floppy[256]; TCHAR path_hardfile[256]; @@ -399,7 +401,6 @@ struct uae_prefs { TCHAR win32_parjoyport0[MAX_DPATH]; TCHAR win32_parjoyport1[MAX_DPATH]; - bool statecapture; int statecapturerate, statecapturebuffersize; /* input */ diff --git a/include/savestate.h b/include/savestate.h index d60b67f3..5ac119c3 100644 --- a/include/savestate.h +++ b/include/savestate.h @@ -10,6 +10,16 @@ /* functions to save byte,word or long word * independent of CPU's endianess */ +extern void save_store_pos_func (uae_u8 **); +extern void save_store_size_func (uae_u8 **); +extern void restore_store_pos_func (uae_u8 **); +extern void restore_store_size_func (uae_u8 **); + +#define save_store_pos() save_store_pos_func (&dst) +#define save_store_size() save_store_size_func (&dst) +#define restore_store_pos() restore_store_pos_func (&src) +#define restore_store_size() restore_store_size_func (&src) + extern void save_u64_func (uae_u8 **, uae_u64); extern void save_u32_func (uae_u8 **, uae_u32); extern void save_u16_func (uae_u8 **, uae_u16); @@ -43,6 +53,8 @@ extern void restore_cpu_finish (void); extern uae_u8 *save_cpu (int *, uae_u8 *); extern uae_u8 *restore_cpu_extra (uae_u8 *); extern uae_u8 *save_cpu_extra (int *, uae_u8 *); +extern uae_u8 *save_cpu_trace (int *, uae_u8 *); +extern uae_u8 *restore_cpu_trace (uae_u8 *); extern uae_u8 *restore_mmu (uae_u8 *); extern uae_u8 *save_mmu (int *, uae_u8 *); @@ -51,9 +63,11 @@ extern uae_u8 *restore_fpu (uae_u8 *); extern uae_u8 *save_fpu (int *, uae_u8 *); extern uae_u8 *restore_disk (int, uae_u8 *); -extern uae_u8 *save_disk (int, int *, uae_u8 *); +extern uae_u8 *save_disk (int, int *, uae_u8 *, bool); extern uae_u8 *restore_floppy (uae_u8 *src); extern uae_u8 *save_floppy (int *len, uae_u8 *); +extern uae_u8 *save_disk2 (int num, int *len, uae_u8 *dstptr); +extern uae_u8 *restore_disk2 (int num,uae_u8 *src); extern void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklen, uae_u16 *pdsksync, uae_u16 *pdskbytr); extern void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskbytr); extern void restore_disk_finish (void); @@ -69,15 +83,22 @@ extern uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *); extern uae_u8 *restore_custom_agacolors (uae_u8 *src); extern uae_u8 *save_custom_agacolors (int *len, uae_u8 *); +extern uae_u8 *restore_custom_event_delay (uae_u8 *src); +extern uae_u8 *save_custom_event_delay (int *len, uae_u8 *dstptr); + extern uae_u8 *restore_blitter (uae_u8 *src); extern uae_u8 *save_blitter (int *len, uae_u8 *); +extern uae_u8 *restore_blitter_new (uae_u8 *src); +extern uae_u8 *save_blitter_new (int *len, uae_u8 *); extern void restore_blitter_finish (void); extern uae_u8 *restore_audio (int, uae_u8 *); extern uae_u8 *save_audio (int, int *, uae_u8 *); +extern void restore_audio_finish (void); extern uae_u8 *restore_cia (int, uae_u8 *); extern uae_u8 *save_cia (int, int *, uae_u8 *); +extern void restore_cia_finish (void); extern uae_u8 *restore_expansion (uae_u8 *); extern uae_u8 *save_expansion (int *, uae_u8 *); @@ -87,18 +108,18 @@ extern uae_u8 *save_p96 (int *, uae_u8 *); extern void restore_p96_finish (void); extern uae_u8 *restore_keyboard (uae_u8 *); -extern uae_u8 *save_keyboard (int *); +extern uae_u8 *save_keyboard (int *,uae_u8*); extern uae_u8 *restore_akiko (uae_u8 *src); -extern uae_u8 *save_akiko (int *len); +extern uae_u8 *save_akiko (int *len, uae_u8*); extern void restore_akiko_finish (void); extern uae_u8 *restore_cdtv (uae_u8 *src); -extern uae_u8 *save_cdtv (int *len); +extern uae_u8 *save_cdtv (int *len, uae_u8*); extern void restore_cdtv_finish (void); extern uae_u8 *restore_dmac (uae_u8 *src); -extern uae_u8 *save_dmac (int *len); +extern uae_u8 *save_dmac (int *len, uae_u8*); extern uae_u8 *restore_filesys (uae_u8 *src); extern uae_u8 *save_filesys (int num, int *len); @@ -107,9 +128,9 @@ extern uae_u8 *save_filesys_common (int *len); extern int save_filesys_cando(void); extern uae_u8 *restore_gayle(uae_u8 *src); -extern uae_u8 *save_gayle (int *len); +extern uae_u8 *save_gayle (int *len, uae_u8*); extern uae_u8 *restore_ide (uae_u8 *src); -extern uae_u8 *save_ide (int num, int *len); +extern uae_u8 *save_ide (int num, int *len, uae_u8*); extern uae_u8 *save_cd (int num, int *len); extern uae_u8 *restore_cd (int, uae_u8 *src); @@ -122,6 +143,20 @@ extern uae_u8 *restore_log (uae_u8 *src); extern uae_u8 *restore_input (uae_u8 *src); extern uae_u8 *save_input (int *len, uae_u8 *dstptr); +extern uae_u8 *restore_inputstate (uae_u8 *src); +extern uae_u8 *save_inputstate (int *len, uae_u8 *dstptr); +extern void clear_inputstate (void); + +extern uae_u8 *save_a2065 (int *len, uae_u8 *dstptr); +extern uae_u8 *restore_a2065 (uae_u8 *src); +extern void restore_a2065_finish (void); + +extern uae_u8 *restore_debug_memwatch (uae_u8 *src); +extern uae_u8 *save_debug_memwatch (int *len, uae_u8 *dstptr); + +extern uae_u8 *save_cycles (int *len, uae_u8 *dstptr); +extern uae_u8 *restore_cycles (uae_u8 *src); + extern void restore_cram (int, size_t); extern void restore_bram (int, size_t); extern void restore_fram (int, size_t); @@ -150,14 +185,18 @@ extern uae_u8 *save_action_replay (int *, uae_u8 *); extern uae_u8 *restore_hrtmon (uae_u8 *); extern uae_u8 *save_hrtmon (int *, uae_u8 *); -extern void savestate_initsave (const TCHAR *filename, int docompress, int nodialogs); +extern void savestate_initsave (const TCHAR *filename, int docompress, int nodialogs, bool save); extern int save_state (const TCHAR *filename, const TCHAR *description); extern void restore_state (const TCHAR *filename); extern void savestate_restore_finish (void); +extern void savestate_memorysave (void); + extern void custom_save_state (void); extern void custom_prepare_savestate (void); +extern bool savestate_check (void); + #define STATE_SAVE 1 #define STATE_RESTORE 2 #define STATE_DOSAVE 4 @@ -169,6 +208,11 @@ extern int savestate_state; extern TCHAR savestate_fname[MAX_DPATH]; extern struct zfile *savestate_file; +STATIC_INLINE bool isrestore (void) +{ + return savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND; +} + extern void savestate_quick (int slot, int save); extern void savestate_capture (int); @@ -177,4 +221,4 @@ extern void savestate_init (void); extern void savestate_rewind (void); extern int savestate_dorewind (int); extern void savestate_listrewind (void); - +extern void statefile_save_recording (const TCHAR*); diff --git a/include/statusline.h b/include/statusline.h index 11562149..727ea63d 100644 --- a/include/statusline.h +++ b/include/statusline.h @@ -24,4 +24,3 @@ static int td_pos = (TD_RIGHT|TD_BOTTOM); #define STATUSLINE_TARGET 0x80 extern void draw_status_line_single (uae_u8 *buf, int bpp, int y, int totalwidth, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *alpha); - diff --git a/include/uae.h b/include/uae.h index 13d4b5bc..92c53039 100644 --- a/include/uae.h +++ b/include/uae.h @@ -29,6 +29,8 @@ extern bool get_plugin_path (TCHAR *out, int size, const TCHAR *path); extern void stripslashes (TCHAR *p); extern void fixtrailing (TCHAR *p); extern void fullpath (TCHAR *path, int size); +extern void getpathpart (TCHAR *outpath, int size, const TCHAR *inpath); +extern void getfilepart (TCHAR *out, int size, const TCHAR *path); extern int quit_program; extern bool console_emulation; @@ -58,5 +60,9 @@ extern void fetch_configurationpath (TCHAR *out, int size); extern void fetch_screenshotpath (TCHAR *out, int size); extern void fetch_ripperpath (TCHAR *out, int size); extern void fetch_statefilepath (TCHAR *out, int size); +extern void fetch_inputfilepath (TCHAR *out, int size); extern void fetch_datapath (TCHAR *out, int size); -extern int uaerand (void); +extern uae_u32 uaerand (void); +extern uae_u32 uaesrand (uae_u32 seed); +extern uae_u32 uaerandgetseed (void); + diff --git a/include/xwin.h b/include/xwin.h index da09c97c..3187984b 100644 --- a/include/xwin.h +++ b/include/xwin.h @@ -93,6 +93,8 @@ struct vidbuf_description int maxblocklines; /* Set to 0 if you want calls to flush_line after each drawn line, or the number of * lines that flush_block wants to/can handle (it isn't really useful to use another * value than maxline here). */ + int gfx_resolution_reserved; // reserved space for currprefs.gfx_resolution + int gfx_vresolution_reserved; // reserved space for currprefs.gfx_resolution }; extern struct vidbuf_description gfxvidinfo; diff --git a/include/zarchive.h b/include/zarchive.h index 45ec42d7..b9b863bb 100644 --- a/include/zarchive.h +++ b/include/zarchive.h @@ -14,6 +14,7 @@ struct zfile { int archiveid; uae_s64 size; // real size uae_s64 datasize; // available size (not yet unpacked completely?) + uae_s64 allocsize; // memory allocated before realloc() needed again uae_s64 seek; // seek position int deleteafterclose; int textmode; diff --git a/include/zfile.h b/include/zfile.h index fb7be8b2..5a9cd702 100644 --- a/include/zfile.h +++ b/include/zfile.h @@ -30,7 +30,8 @@ struct fs_filehandle typedef int (*zfile_callback)(struct zfile*, void*); extern struct zfile *zfile_fopen (const TCHAR *, const TCHAR *, int mask); -extern struct zfile *zfile_fopen2 (const TCHAR *, const TCHAR *, int mask, int index); +extern struct zfile *zfile_fopen (const TCHAR *, const TCHAR *); +extern struct zfile *zfile_fopen (const TCHAR *, const TCHAR *, int mask, int index); extern struct zfile *zfile_fopen_empty (struct zfile*, const TCHAR *name, uae_u64 size); extern struct zfile *zfile_fopen_empty (struct zfile*, const TCHAR *name); extern struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, uae_u8 *data); @@ -68,6 +69,7 @@ extern int zfile_convertimage (const TCHAR *src, const TCHAR *dst); extern struct zfile *zuncompress (struct znode*, struct zfile *z, int dodefault, int mask, int *retcode, int index); extern void zfile_seterror (const TCHAR *format, ...); extern TCHAR *zfile_geterror (void); +extern int zfile_truncate (struct zfile *z, uae_s64 size); #define ZFD_NONE 0 #define ZFD_ARCHIVE 1 //zip/lha.. diff --git a/inputdevice.cpp b/inputdevice.cpp index 7f8b4325..fb7bdf92 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -24,6 +24,7 @@ #include "options.h" #include "keyboard.h" #include "inputdevice.h" +#include "inputrecord.h" #include "keybuf.h" #include "custom.h" #include "xwin.h" @@ -104,7 +105,9 @@ static uae_u8 scancodeused[MAX_INPUT_DEVICES][256]; // fire/left mouse button pullup resistors enabled? static bool mouse_pullup = true; -static bool joystick_pullup = false; + +static int joymodes[MAX_JPORTS]; +static int *joyinputs[MAX_JPORTS]; static int input_acquired; static int testmode, testmode_read, testmode_toggle; @@ -121,255 +124,12 @@ static int testmode_count; static struct teststore testmode_data[TESTMODE_MAX]; static struct teststore testmode_wait[TESTMODE_MAX]; -static uae_u8 *inprec_buffer, *inprec_p; -static struct zfile *inprec_zf; -static int inprec_size; -int input_recording = 0; -static uae_u8 *inprec_plast, *inprec_plastptr; -static int inprec_div; - -static uae_u32 oldbuttons[4]; -static uae_u16 oldjoy[2]; - static int bouncy; static signed long bouncy_cycles; #define BOUNCY_CYCLES 30 -int inprec_open (const TCHAR *fname, int record) -{ - uae_u32 t = (uae_u32)time(0); - int i; - - inprec_close(); - inprec_zf = zfile_fopen (fname, record > 0 ? L"wb" : L"rb", ZFD_NORMAL); - if (inprec_zf == NULL) - return 0; - inprec_size = 10000; - inprec_div = 1; - if (record < 0) { - uae_u32 id; - zfile_fseek (inprec_zf, 0, SEEK_END); - inprec_size = zfile_ftell (inprec_zf); - zfile_fseek (inprec_zf, 0, SEEK_SET); - inprec_buffer = inprec_p = xmalloc (uae_u8, inprec_size); - zfile_fread (inprec_buffer, inprec_size, 1, inprec_zf); - inprec_plastptr = inprec_buffer; - id = inprec_pu32(); - if (id != 'UAE\0') { - inprec_close (); - return 0; - } - inprec_pu32(); - t = inprec_pu32 (); - i = inprec_pu32 (); - while (i-- > 0) - inprec_pu8 (); - inprec_p = inprec_plastptr; - if (inprec_pstart (INPREC_STATEFILE)) { - inprec_pstr (savestate_fname); - savestate_state = STATE_RESTORE; - inprec_pend (); - } - oldbuttons[0] = oldbuttons[1] = oldbuttons[2] = oldbuttons[3] = 0; - oldjoy[0] = oldjoy[1] = 0; - if (record < -1) - inprec_div = maxvpos; - } else if (record > 0) { - inprec_buffer = inprec_p = xmalloc (uae_u8, inprec_size); - inprec_ru32 ('UAE\0'); - inprec_ru8 (1); - inprec_ru8 (UAEMAJOR); - inprec_ru8 (UAEMINOR); - inprec_ru8 (UAESUBREV); - inprec_ru32 (t); - inprec_ru32 (0); // extra header size - if (savestate_state == STATE_DORESTORE) { - inprec_rstart (INPREC_STATEFILE); - inprec_rstr (savestate_fname); - inprec_rend (); - } - } else { - return 0; - } - input_recording = record; - srand (t); - CIA_inprec_prepare (); - write_log (L"inprec initialized '%s', mode=%d\n", fname, input_recording); - return 1; -} - -void inprec_close (void) -{ - if (!inprec_zf) - return; - if (inprec_buffer && input_recording > 0) { - hsync_counter++; - inprec_rstart(INPREC_END); - inprec_rend(); - hsync_counter--; - zfile_fwrite (inprec_buffer, inprec_p - inprec_buffer, 1, inprec_zf); - inprec_p = inprec_buffer; - } - zfile_fclose (inprec_zf); - inprec_zf = NULL; - xfree (inprec_buffer); - inprec_buffer = NULL; - input_recording = 0; - write_log (L"inprec finished\n"); -} - -void inprec_ru8(uae_u8 v) -{ - *inprec_p++= v; -} -void inprec_ru16 (uae_u16 v) -{ - inprec_ru8 ((uae_u8)(v >> 8)); - inprec_ru8 ((uae_u8)v); -} -void inprec_ru32 (uae_u32 v) -{ - inprec_ru16 ((uae_u16)(v >> 16)); - inprec_ru16 ((uae_u16)v); -} -void inprec_rstr (const TCHAR *src) -{ - char *s = ua (src); - char *ss = s; - while(*s) { - inprec_ru8 (*s); - s++; - } - inprec_ru8 (0); - xfree (ss); -} -void inprec_rstart (uae_u8 type) -{ - write_log (L"INPREC: %08X: %d\n", hsync_counter, type); - inprec_ru32 (hsync_counter); - inprec_ru8 (0); - inprec_plast = inprec_p; - inprec_ru8 (0xff); - inprec_ru8 (type); -} -void inprec_rend (void) -{ - *inprec_plast = inprec_p - (inprec_plast + 2); - if (inprec_p >= inprec_buffer + inprec_size - 256) { - zfile_fwrite (inprec_buffer, inprec_p - inprec_buffer, 1, inprec_zf); - inprec_p = inprec_buffer; - } -} - -int inprec_pstart (uae_u8 type) -{ - uae_u8 *p = inprec_p; - uae_u32 hc = hsync_counter; - static uae_u8 *lastp; - uae_u32 hc_orig, hc2_orig; - - if (savestate_state) - return 0; - if (p[5 + 1] == INPREC_END) { - inprec_close (); - return 0; - } else if (p[5 + 1] == INPREC_QUIT) { - inprec_close (); - uae_quit (); - return 0; - } - hc_orig = hc; - hc /= inprec_div; - hc *= inprec_div; - for (;;) { - uae_u32 hc2 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - if (p > lastp) { - write_log (L"INPREC: Next %08x (%08x=%d): %d (%d)\n", hc2, hc, hc2 - hc, p[5 + 1], p[5]); - lastp = p; - } - hc2_orig = hc2; - hc2 /= inprec_div; - hc2 *= inprec_div; - if (hc > hc2) { - write_log (L"INPREC: %08x > %08x: %d (%d) missed!\n", hc, hc2, p[5 + 1], p[5]); - inprec_close (); - return 0; - } - if (hc2 != hc) { - lastp = p; - break; - } - if (p[5 + 1] == type) { - write_log (L"INPREC: %08x: %d (%d) (%+d)\n", hc, type, p[5], hc_orig - hc2_orig); - inprec_plast = p; - inprec_plastptr = p + 5 + 2; - return 1; - } - p += 5 + 2 + p[5]; - } - inprec_plast = NULL; - return 0; -} -void inprec_pend (void) -{ - uae_u8 *p = inprec_p; - uae_u32 hc = hsync_counter; - - if (!inprec_plast) - return; - inprec_plast[5 + 1] = 0; - inprec_plast = NULL; - inprec_plastptr = NULL; - hc /= inprec_div; - hc *= inprec_div; - for (;;) { - uae_u32 hc2 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - hc2 /= inprec_div; - hc2 *= inprec_div; - if (hc2 != hc) - break; - if (p[5 + 1] != 0) - return; - p += 5 + 2 + p[5]; - } - inprec_p = p; - if (p[5 + 1] == INPREC_END) - inprec_close (); -} - -uae_u8 inprec_pu8 (void) -{ - return *inprec_plastptr++; -} -uae_u16 inprec_pu16 (void) -{ - uae_u16 v = inprec_pu8 () << 8; - v |= inprec_pu8 (); - return v; -} -uae_u32 inprec_pu32 (void) -{ - uae_u32 v = inprec_pu16 () << 16; - v |= inprec_pu16 (); - return v; -} -int inprec_pstr (TCHAR *dst) -{ - char tmp[MAX_DPATH]; - char *s; - int len = 0; +static int handle_input_event (int nr, int state, int max, int autofire, bool canstoprecord, bool playbackevent); - s = tmp; - for(;;) { - uae_u8 v = inprec_pu8 (); - *s++ = v; - if (!v) - break; - len++; - } - au_copy (dst, MAX_DPATH, tmp); - return len; -} static int isdevice (struct uae_input_device *id) { @@ -389,7 +149,7 @@ int inputdevice_uaelib (TCHAR *s, TCHAR *parm) for (i = 1; events[i].name; i++) { if (!_tcscmp (s, events[i].confname)) { - handle_input_event (i, _tstol (parm), 1, 0); + handle_input_event (i, _tstol (parm), 1, 0, false, false); return 1; } } @@ -400,43 +160,53 @@ static struct uae_input_device *joysticks; static struct uae_input_device *mice; static struct uae_input_device *keyboards; static struct uae_input_device_kbr_default *keyboard_default; + +#define KBR_DEFAULT_MAP_FIRST 0 +#define KBR_DEFAULT_MAP_LAST 5 +#define KBR_DEFAULT_MAP_CD32_FIRST 6 +#define KBR_DEFAULT_MAP_CD32_LAST 8 + #define KBR_DEFAULT_MAP_NP 0 #define KBR_DEFAULT_MAP_CK 1 #define KBR_DEFAULT_MAP_SE 2 -#define KBR_DEFAULT_MAP_CD32_NP 3 -#define KBR_DEFAULT_MAP_CD32_CK 4 -#define KBR_DEFAULT_MAP_CD32_SE 5 -#define KBR_DEFAULT_MAP_XA1 6 -#define KBR_DEFAULT_MAP_XA2 7 -#define KBR_DEFAULT_MAP_ARCADIA 8 -#define KBR_DEFAULT_MAP_ARCADIA_XA 9 -#define KBR_DEFAULT_MAP_CDTV 10 +#define KBR_DEFAULT_MAP_NP3 3 +#define KBR_DEFAULT_MAP_CK3 4 +#define KBR_DEFAULT_MAP_SE3 5 +#define KBR_DEFAULT_MAP_CD32_NP 6 +#define KBR_DEFAULT_MAP_CD32_CK 7 +#define KBR_DEFAULT_MAP_CD32_SE 8 +#define KBR_DEFAULT_MAP_XA1 9 +#define KBR_DEFAULT_MAP_XA2 10 +#define KBR_DEFAULT_MAP_ARCADIA 11 +#define KBR_DEFAULT_MAP_ARCADIA_XA 12 +#define KBR_DEFAULT_MAP_CDTV 13 static int **keyboard_default_kbmaps; static int mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; static int oldm_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; -static int mouse_x[MAX_INPUT_DEVICES], mouse_y[MAX_INPUT_DEVICE_EVENTS]; -static int mouse_delta[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; -static int mouse_deltanoreset[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS]; -static int joybutton[MAX_INPUT_DEVICES]; -static unsigned int joydir[MAX_INPUT_DEVICE_EVENTS]; -static int joydirpot[MAX_INPUT_DEVICE_EVENTS][2]; -static int mouse_frame_x[2], mouse_frame_y[2]; - -static int mouse_port[2]; -static int cd32_shifter[2]; -static int cd32_pad_enabled[2]; +static int mouse_x[MAX_JPORTS], mouse_y[MAX_JPORTS]; +static int mouse_delta[MAX_JPORTS][MAX_INPUT_DEVICE_EVENTS]; +static int mouse_deltanoreset[MAX_JPORTS][MAX_INPUT_DEVICE_EVENTS]; +static int joybutton[MAX_JPORTS]; +static int joydir[MAX_JPORTS]; +static int joydirpot[MAX_JPORTS][2]; +static int mouse_frame_x[MAX_JPORTS], mouse_frame_y[MAX_JPORTS]; + +static int mouse_port[NORMAL_JPORTS]; +static int cd32_shifter[NORMAL_JPORTS]; +static int cd32_pad_enabled[NORMAL_JPORTS]; static int parport_joystick_enabled; -static int oldmx[4], oldmy[4]; -static int oleft[4], oright[4], otop[4], obot[4]; +static int oldmx[MAX_JPORTS], oldmy[MAX_JPORTS]; +static int oleft[MAX_JPORTS], oright[MAX_JPORTS], otop[MAX_JPORTS], obot[MAX_JPORTS]; +static int horizclear[MAX_JPORTS], vertclear[MAX_JPORTS]; uae_u16 potgo_value; -static int pot_cap[2][2]; -static uae_u8 pot_dat[2][2]; -static int pot_dat_act[2][2]; -static int analog_port[2][2]; -static int digital_port[2][2]; +static int pot_cap[NORMAL_JPORTS][2]; +static uae_u8 pot_dat[NORMAL_JPORTS][2]; +static int pot_dat_act[NORMAL_JPORTS][2]; +static int analog_port[NORMAL_JPORTS][2]; +static int digital_port[NORMAL_JPORTS][2]; #define POTDAT_DELAY_PAL 8 #define POTDAT_DELAY_NTSC 7 @@ -1789,33 +1559,9 @@ STATIC_INLINE int adjust (int val) return val; } -int getbuttonstate (int joy, int button) +static int getbuttonstate (int joy, int button) { - int v; - - v = (joybutton[joy] & (1 << button)) ? 1 : 0; - if (input_recording > 0 && ((joybutton[joy] ^ oldbuttons[joy]) & (1 << button))) { - oldbuttons[joy] &= ~(1 << button); - if (v) - oldbuttons[joy] |= 1 << button; - inprec_rstart (INPREC_JOYBUTTON); - inprec_ru8 (joy); - inprec_ru8 (button); - inprec_ru8 (v); - inprec_rend (); - } else if (input_recording < 0) { - while (inprec_pstart (INPREC_JOYBUTTON)) { - uae_u8 j = inprec_pu8 (); - uae_u8 but = inprec_pu8 (); - uae_u8 vv = inprec_pu8 (); - inprec_pend (); - oldbuttons[j] &= ~(1 << but); - if (vv) - oldbuttons[j] |= 1 << but; - } - v = (oldbuttons[joy] & (1 << button)) ? 1 : 0; - } - return v; + return (joybutton[joy] & (1 << button)) ? 1 : 0; } static int getvelocity (int num, int subnum, int pct) @@ -1934,27 +1680,24 @@ static void readinput (void) uae_u32 totalvpos; int diff; - totalvpos = input_frame * maxvpos + vpos; + totalvpos = input_frame * current_maxvpos () + vpos; diff = totalvpos - input_vpos; if (diff > 0) { if (diff < 10) { mouseupdate (0, 0); } else { - mouseupdate (diff * 1000 / maxvpos, 0); + mouseupdate (diff * 1000 / current_maxvpos (), 0); } } input_vpos = totalvpos; } -int getjoystate (int joy) +static uae_u16 getjoystate (int joy) { int left = 1, right = 1, top = 1, bot = 1; uae_u16 v; - if (inputdevice_logging & 2) - write_log (L"JOY%dDAT %08x\n", joy, M68K_GETPC); - readinput (); if (joydir[joy] & DIR_LEFT) left = 0; if (joydir[joy] & DIR_RIGHT) @@ -1979,25 +1722,15 @@ int getjoystate (int joy) if (notinrom ()) write_log (L"JOY%dDAT %04X %s\n", joy, v, debuginfo (0)); #endif - if (input_recording > 0 && oldjoy[joy] != v) { - oldjoy[joy] = v; - inprec_rstart (INPREC_JOYPORT); - inprec_ru16 (v); - inprec_rend (); - } else if (input_recording < 0) { - v = oldjoy[joy]; - if (inprec_pstart (INPREC_JOYPORT)) { - v = inprec_pu16 (); - inprec_pend (); - } - oldjoy[joy] = v; - } + if (inputdevice_logging & 2) + write_log (L"JOY%dDAT=%04x %08x\n", joy, v, M68K_GETPC); return v; } uae_u16 JOY0DAT (void) { uae_u16 v; + readinput (); v = getjoystate (0); v = dongle_joydat (0, v); return v; @@ -2006,11 +1739,36 @@ uae_u16 JOY0DAT (void) uae_u16 JOY1DAT (void) { uae_u16 v; + readinput (); v = getjoystate (1); v = dongle_joydat (1, v); + + if (inputrecord_debug & 2) { + if (input_record > 0) + inprec_recorddebug_cia (v, -1, m68k_getpc ()); + else if (input_play > 0) + inprec_playdebug_cia (v, -1, m68k_getpc ()); + } + + return v; +} + +uae_u16 JOYGET (int num) +{ + uae_u16 v; + v = getjoystate (num); + v = dongle_joydat (num, v); return v; } +void JOYSET (int num, uae_u16 dat) +{ + mouse_x[num] = dat & 0xff; + mouse_y[num] = (dat >> 8) & 0xff; + mouse_frame_x[num] = mouse_x[num]; + mouse_frame_y[num] = mouse_y[num]; +} + void JOYTEST (uae_u16 v) { mouse_x[0] &= 3; @@ -2079,6 +1837,14 @@ static bool cd32padmode (uae_u16 p5dir, uae_u16 p5dat) return true; } +static bool is_joystick_pullup (int joy) +{ + return joymodes[joy] == JSEM_MODE_GAMEPAD; +} +static bool is_mouse_pullup (int joy) +{ + return mouse_pullup; +} static void charge_cap (int joy, int idx, int charge) { @@ -2124,13 +1890,13 @@ static void cap_check (void) joypot = joydirpot[joy][i]; if (analog_port[joy][i] && pot_cap[joy][i] < joypot) charge = 1; // slow charge via pot variable resistor - if (((joystick_pullup && digital_port[joy][i]) || (mouse_pullup && mouse_port[joy] && digital_port[joy][i]))) + if ((is_joystick_pullup (joy) && digital_port[joy][i]) || (is_mouse_pullup (joy) && mouse_port[joy])) charge = 1; // slow charge via pull-up resistor } if (!(potgo_value & pdir)) { // input? if (pot_dat_act[joy][i]) pot_dat[joy][i]++; - /* first 8 lines after potgo has been started = discharge cap */ + /* first 7 or 8 lines after potgo has been started = discharge cap */ if (pot_dat_act[joy][i] == 1) { if (pot_dat[joy][i] < (currprefs.ntscmode ? POTDAT_DELAY_NTSC : POTDAT_DELAY_PAL)) { charge = -2; /* fast discharge delay */ @@ -2172,13 +1938,13 @@ static void cap_check (void) /* official Commodore mouse has pull-up resistors in button lines * NOTE: 3rd party mice may not have pullups! */ - if (dong < 0 && (mouse_pullup && mouse_port[joy] && digital_port[joy][i]) && charge == 0) + if (dong < 0 && (is_mouse_pullup (joy) && mouse_port[joy] && digital_port[joy][i]) && charge == 0) charge = 2; /* emulate pullup resistor if button mapped because there too many broken * programs that read second button in input-mode (and most 2+ button pads have * pullups) */ - if (dong < 0 && (joystick_pullup && digital_port[joy][i]) && charge == 0) + if (dong < 0 && (is_joystick_pullup (joy) && digital_port[joy][i]) && charge == 0) charge = 2; charge_cap (joy, i, charge); @@ -2216,8 +1982,12 @@ uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra) } } - if (inputdevice_logging & 4) - write_log (L"BFE001: %02X:%02X %x\n", dra, but, M68K_GETPC); + if (inputdevice_logging & 4) { + static uae_u8 old; + if (but != old) + write_log (L"BFE001: %02X:%02X %x\n", dra, but, M68K_GETPC); + old = but; + } return but; } @@ -2322,7 +2092,7 @@ void inputdevice_hsync (void) iq->state = 0; else iq->state = iq->storedstate; - handle_input_event (iq->event, iq->state, iq->max, 0); + handle_input_event (iq->event, iq->state, iq->max, 0, false, true); iq->linecnt = iq->nextlinecnt; } } @@ -2331,12 +2101,27 @@ void inputdevice_hsync (void) if (bouncy && get_cycles () > bouncy_cycles) bouncy = 0; - if ((++cnt & 63) == 63 ) { - inputdevice_read (); - } else if (inputdelay > 0) { - inputdelay--; - if (inputdelay == 0) + if (input_record && input_record != INPREC_RECORD_PLAYING) { + if (vpos == 0) + inputdevice_read (); + inputdelay = 0; + } + if (input_play) { + inprec_playdiskchange (); + int nr, state, max, autofire; + while (inprec_playevent (&nr, &state, &max, &autofire)) + handle_input_event (nr, state, max, autofire, false, true); + if (vpos == 0) + handle_msgpump (); + } + if (!input_record && !input_play) { + if ((++cnt & 63) == 63 ) { inputdevice_read (); + } else if (inputdelay > 0) { + inputdelay--; + if (inputdelay == 0) + inputdevice_read (); + } } } @@ -2443,7 +2228,7 @@ static void queue_input_event (int event, int state, int max, int linecnt, int a iq->linecnt = -1; iq->event = 0; if (iq->state == 0) - handle_input_event (event, 0, 1, 0); + handle_input_event (event, 0, 1, 0, false, false); } else if (i < 0) { for (i = 0; i < INPUT_QUEUE_SIZE; i++) { iq = &input_queue[i]; @@ -2517,15 +2302,47 @@ void inputdevice_do_keyboard (int code, int state) inputdevice_add_inputcode (code, state); } +// these need cpu trace data +static bool needcputrace (int code) +{ + switch (code) + { + case AKS_ENTERGUI: + case AKS_STATECAPTURE: + case AKS_STATESAVEQUICK: + case AKS_STATESAVEQUICK1: + case AKS_STATESAVEQUICK2: + case AKS_STATESAVEQUICK3: + case AKS_STATESAVEQUICK4: + case AKS_STATESAVEQUICK5: + case AKS_STATESAVEQUICK6: + case AKS_STATESAVEQUICK7: + case AKS_STATESAVEQUICK8: + case AKS_STATESAVEQUICK9: + case AKS_STATESAVEDIALOG: + return true; + } + return false; +} + void inputdevice_handle_inputcode (void) { static int swapperslot; int code = inputcode_pending; int state = inputcode_pending_state; + static int tracer_enable; - inputcode_pending = 0; if (code == 0) - return; + goto end; + if (needcputrace (code) && can_cpu_tracer () == true && is_cpu_tracer () == false) { + if (set_cpu_tracer (true)) { + tracer_enable = 1; + return; // wait for next frame + } + } + + inputcode_pending = 0; + if (vpos != 0) write_log (L"inputcode=%d but vpos = %d", code, vpos); @@ -2610,7 +2427,13 @@ void inputdevice_handle_inputcode (void) toggle_inhibit_frame (IHF_SCROLLLOCK); break; case AKS_STATEREWIND: - savestate_dorewind (1); + savestate_dorewind (-2); + break; + case AKS_STATECURRENT: + savestate_dorewind (-1); + break; + case AKS_STATECAPTURE: + savestate_capture (1); break; case AKS_VOLDOWN: sound_volume (-1); @@ -2755,6 +2578,11 @@ void inputdevice_handle_inputcode (void) break; #endif } +end: + if (tracer_enable) { + set_cpu_tracer (false); + tracer_enable = 0; + } } int handle_custom_event (TCHAR *custom) @@ -2785,15 +2613,32 @@ int handle_custom_event (TCHAR *custom) return 0; } -int handle_input_event (int nr, int state, int max, int autofire) +static int handle_input_event (int nr, int state, int max, int autofire, bool canstopplayback, bool playbackevent) { struct inputevent *ie; int joy; + bool isaks = false; if (nr <= 0) return 0; ie = &events[nr]; - if (inputdevice_logging & 1) + if (ie->unit == 0 && ie->data >= 0x200) + isaks = true; + + if (!isaks) { + if (input_record && input_record != INPREC_RECORD_PLAYING) + inprec_recordevent (nr, state, max, autofire); + if (input_play && state && canstopplayback) { + if (inprec_realtime ()) { + if (input_record && input_record != INPREC_RECORD_PLAYING) + inprec_recordevent (nr, state, max, autofire); + } + } + if (!playbackevent && input_play) + return 0; + } + + if ((inputdevice_logging & 1) || input_record || input_play) write_log (L"'%s' STATE=%d MAX=%d AF=%d\n", ie->name, state, max, autofire); if (autofire) { if (state) @@ -2851,9 +2696,11 @@ int handle_input_event (int nr, int state, int max, int autofire) } if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) { - // emulate contact bounce, 1st button only, others have capacitors - bouncy = 1; - bouncy_cycles = get_cycles () + CYCLE_UNIT * BOUNCY_CYCLES; + if (!input_record && !input_play) { + // emulate contact bounce, 1st button only, others have capacitors + bouncy = 1; + bouncy_cycles = get_cycles () + CYCLE_UNIT * BOUNCY_CYCLES; + } } @@ -2984,14 +2831,34 @@ int handle_input_event (int nr, int state, int max, int autofire) int left = oleft[joy], right = oright[joy], top = otop[joy], bot = obot[joy]; if (ie->type & 16) { /* button to axis mapping */ - if (ie->data & DIR_LEFT) + if (ie->data & DIR_LEFT) { left = oleft[joy] = state ? 1 : 0; - if (ie->data & DIR_RIGHT) + if (horizclear[joy] && left) { + horizclear[joy] = 0; + right = oright[joy] = 0; + } + } + if (ie->data & DIR_RIGHT) { right = oright[joy] = state ? 1 : 0; - if (ie->data & DIR_UP) + if (horizclear[joy] && right) { + horizclear[joy] = 0; + left = oleft[joy] = 0; + } + } + if (ie->data & DIR_UP) { top = otop[joy] = state ? 1 : 0; - if (ie->data & DIR_DOWN) + if (vertclear[joy] && top) { + vertclear[joy] = 0; + bot = obot[joy] = 0; + } + } + if (ie->data & DIR_DOWN) { bot = obot[joy] = state ? 1 : 0; + if (vertclear[joy] && bot) { + vertclear[joy] = 0; + top = otop[joy] = 0; + } + } } else { /* "normal" joystick axis */ int deadzone = currprefs.input_joystick_deadzone * max / 100; @@ -3000,14 +2867,34 @@ int handle_input_event (int nr, int state, int max, int autofire) state = 0; neg = state < 0 ? 1 : 0; pos = state > 0 ? 1 : 0; - if (ie->data & DIR_LEFT) + if (ie->data & DIR_LEFT) { left = oleft[joy] = neg; - if (ie->data & DIR_RIGHT) + if (horizclear[joy] && left) { + horizclear[joy] = 0; + right = oright[joy] = 0; + } + } + if (ie->data & DIR_RIGHT) { right = oright[joy] = pos; - if (ie->data & DIR_UP) + if (horizclear[joy] && right) { + horizclear[joy] = 0; + left = oleft[joy] = 0; + } + } + if (ie->data & DIR_UP) { top = otop[joy] = neg; - if (ie->data & DIR_DOWN) + if (vertclear[joy] && top) { + vertclear[joy] = 0; + bot = obot[joy] = 0; + } + } + if (ie->data & DIR_DOWN) { bot = obot[joy] = pos; + if (vertclear[joy] && bot) { + vertclear[joy] = 0; + top = otop[joy] = 0; + } + } } mouse_deltanoreset[joy][0] = 1; mouse_deltanoreset[joy][1] = 1; @@ -3070,9 +2957,13 @@ void inputdevice_vsync (void) input_frame++; mouseupdate (0, 1); - inputdevice_read (); - inputdelay = uaerand () % (maxvpos <= 1 ? 1 : maxvpos - 1); + if (!input_record) { + inputdevice_read (); + if (!input_play) + inputdelay = uaerand () % (maxvpos <= 1 ? 1 : maxvpos - 1); + } + inputdevice_handle_inputcode (); if (mouseedge_alive > 0) mouseedge_alive--; @@ -3104,6 +2995,7 @@ void inputdevice_reset (void) mousehack_reset (); if (inputdevice_is_tablet ()) mousehack_enable (); + bouncy = 0; } static int getoldport (struct uae_input_device *id) @@ -3271,6 +3163,10 @@ static void setbuttonstateall (struct uae_input_device *id, struct uae_input_dev uae_u32 omask = id2->buttonmask & mask; uae_u32 nmask = (state ? 1 : 0) << button; + if (input_play && state) + inprec_realtime (); + if (input_play) + return; if (!id->enabled) { if (state) switchdevice (id, button, 1); @@ -3285,7 +3181,7 @@ static void setbuttonstateall (struct uae_input_device *id, struct uae_input_dev int toggle = (id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]] & ID_FLAG_TOGGLE) ? 1 : 0; if (state < 0) { - handle_input_event (evt, 1, 1, 0); + handle_input_event (evt, 1, 1, 0, true, false); queue_input_event (evt, 0, 1, 1, 0); /* send release event next frame */ if (i == 0) process_custom_event (id, ID_BUTTON_OFFSET + button, state); @@ -3297,12 +3193,12 @@ static void setbuttonstateall (struct uae_input_device *id, struct uae_input_dev continue; id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]] ^= ID_FLAG_TOGGLED; toggled = (id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]] & ID_FLAG_TOGGLED) ? 1 : 0; - handle_input_event (evt, toggled, 1, autofire); + handle_input_event (evt, toggled, 1, autofire, true, false); if (i == 0) process_custom_event (id, ID_BUTTON_OFFSET + button, toggled); } else { if ((omask ^ nmask) & mask) { - handle_input_event (evt, state, 1, autofire); + handle_input_event (evt, state, 1, autofire, true, false); if (i == 0) process_custom_event (id, ID_BUTTON_OFFSET + button, state); } @@ -3382,19 +3278,19 @@ static int isanalog (int ei) static int isdigitalbutton (int ei) { if (ei == INPUTEVENT_JOY1_2ND_BUTTON) { - digital_port[0][0] = 1; + digital_port[0][1] = 1; return 1; } if (ei == INPUTEVENT_JOY1_3RD_BUTTON) { - digital_port[0][1] = 1; + digital_port[0][0] = 1; return 1; } if (ei == INPUTEVENT_JOY2_2ND_BUTTON) { - digital_port[1][0] = 1; + digital_port[1][1] = 1; return 1; } if (ei == INPUTEVENT_JOY2_3RD_BUTTON) { - digital_port[1][1] = 1; + digital_port[1][0] = 1; return 1; } return 0; @@ -3411,7 +3307,7 @@ static void scanevents (struct uae_prefs *p) parport_joystick_enabled = 0; mouse_port[0] = mouse_port[1] = 0; - for (i = 0; i < 2; i++) { + for (i = 0; i < NORMAL_JPORTS; i++) { for (j = 0; j < 2; j++) { digital_port[i][j] = 0; analog_port[i][j] = 0; @@ -3419,7 +3315,7 @@ static void scanevents (struct uae_prefs *p) } } - for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) + for (i = 0; i < MAX_JPORTS; i++) joydir[i] = 0; for (i = 0; i < MAX_INPUT_DEVICES; i++) { @@ -3594,6 +3490,16 @@ static int ip_joy2[] = { INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, -1 }; +static int ip_joypad1[] = { + INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, + INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON, + -1 +}; +static int ip_joypad2[] = { + INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN, + INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON, + -1 +}; static int ip_joycd321[] = { INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN, INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW, @@ -3683,6 +3589,8 @@ static void checkcompakb (int *kb, int *srcmap) } j++; } + if (srcmap[k] < 0) + break; j++; k++; } @@ -3781,9 +3689,6 @@ static void setcompakb (int *kb, int *srcmap, int index, int af) } } -static int joymodes[MAX_JPORTS]; -static int *joyinputs[MAX_JPORTS]; - int inputdevice_get_compatibility_input (struct uae_prefs *prefs, int index, int *typelist, int **inputlist, int **at) { if (index >= MAX_JPORTS || joymodes[index] < 0) @@ -4018,6 +3923,9 @@ static void setjoyinputs (struct uae_prefs *prefs, int port) else joyinputs[port] = port == 1 ? ip_joy2 : ip_joy1; break; + case JSEM_MODE_GAMEPAD: + joyinputs[port] = port ? ip_joypad2 : ip_joypad1; + break; case JSEM_MODE_JOYSTICK_CD32: joyinputs[port] = port ? ip_joycd322 : ip_joycd321; break; @@ -4108,15 +4016,21 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) { case JSEM_MODE_DEFAULT: case JSEM_MODE_JOYSTICK: + case JSEM_MODE_GAMEPAD: case JSEM_MODE_JOYSTICK_CD32: default: { bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd); - joymodes[i] = iscd32 ? JSEM_MODE_JOYSTICK_CD32 : JSEM_MODE_JOYSTICK; - if (!iscd32) - joyinputs[i] = i ? ip_joy2 : ip_joy1; - else + if (iscd32) { + joymodes[i] = JSEM_MODE_JOYSTICK_CD32; joyinputs[i] = i ? ip_joycd322 : ip_joycd321; + } else if (mode == JSEM_MODE_GAMEPAD) { + joymodes[i] = JSEM_MODE_GAMEPAD; + joyinputs[i] = i ? ip_joypad2 : ip_joypad1; + } else { + joymodes[i] = JSEM_MODE_JOYSTICK; + joyinputs[i] = i ? ip_joy2 : ip_joy1; + } break; } case JSEM_MODE_JOYSTICK_ANALOG: @@ -4194,12 +4108,18 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) { case JSEM_MODE_DEFAULT: case JSEM_MODE_JOYSTICK: + case JSEM_MODE_GAMEPAD: case JSEM_MODE_JOYSTICK_CD32: default: { bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd); - input_get_default_joystick (joysticks, joy, i, af, iscd32 ? JSEM_MODE_JOYSTICK_CD32 : 0); - joymodes[i] = iscd32 ? JSEM_MODE_JOYSTICK_CD32 : JSEM_MODE_JOYSTICK; + input_get_default_joystick (joysticks, joy, i, af, mode); + if (iscd32) + joymodes[i] = JSEM_MODE_JOYSTICK_CD32; + else if (mode == JSEM_MODE_GAMEPAD) + joymodes[i] = JSEM_MODE_GAMEPAD; + else + joymodes[i] = JSEM_MODE_JOYSTICK; break; } case JSEM_MODE_JOYSTICK_ANALOG: @@ -4229,16 +4149,20 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) if (gameports) { // replace possible old mappings with default keyboard mapping - for (i = KBR_DEFAULT_MAP_NP; i <= KBR_DEFAULT_MAP_SE; i++) { + for (i = KBR_DEFAULT_MAP_FIRST; i <= KBR_DEFAULT_MAP_LAST; i++) { checkcompakb (keyboard_default_kbmaps[i], ip_joy2); checkcompakb (keyboard_default_kbmaps[i], ip_joy1); + checkcompakb (keyboard_default_kbmaps[i], ip_joypad2); + checkcompakb (keyboard_default_kbmaps[i], ip_joypad1); checkcompakb (keyboard_default_kbmaps[i], ip_parjoy2); checkcompakb (keyboard_default_kbmaps[i], ip_parjoy1); checkcompakb (keyboard_default_kbmaps[i], ip_mouse2); checkcompakb (keyboard_default_kbmaps[i], ip_mouse1); } - checkcompakb (keyboard_default_kbmaps[5], ip_joycd321); - checkcompakb (keyboard_default_kbmaps[5], ip_joycd322); + for (i = KBR_DEFAULT_MAP_CD32_FIRST; i <= KBR_DEFAULT_MAP_CD32_LAST; i++) { + checkcompakb (keyboard_default_kbmaps[i], ip_joycd321); + checkcompakb (keyboard_default_kbmaps[i], ip_joycd322); + } } for (i = 0; i < 2; i++) { @@ -4252,16 +4176,22 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) if (JSEM_ISNUMPAD (i, prefs)) { if (cd32) kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_NP]; + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP3]; else kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP]; } else if (JSEM_ISCURSOR (i, prefs)) { if (cd32) kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_CK]; + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK3]; else kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK]; } else if (JSEM_ISSOMEWHEREELSE (i, prefs)) { if (cd32) kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_SE]; + else if (mode == JSEM_MODE_GAMEPAD) + kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE3]; else kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE]; } else if (JSEM_ISXARCADE1 (i, prefs)) { @@ -4273,11 +4203,15 @@ static void compatibility_copy (struct uae_prefs *prefs, bool gameports) switch (mode) { case JSEM_MODE_JOYSTICK: + case JSEM_MODE_GAMEPAD: case JSEM_MODE_JOYSTICK_CD32: case JSEM_MODE_DEFAULT: if (cd32) { setcompakb (kb, i ? ip_joycd322 : ip_joycd321, i, af); joymodes[i] = JSEM_MODE_JOYSTICK_CD32; + } else if (mode == JSEM_MODE_GAMEPAD) { + setcompakb (kb, i ? ip_joypad2 : ip_joypad1, i, af); + joymodes[i] = JSEM_MODE_GAMEPAD; } else { setcompakb (kb, i ? ip_joy2 : ip_joy1, i, af); joymodes[i] = JSEM_MODE_JOYSTICK; @@ -4508,7 +4442,7 @@ void inputdevice_updateconfig (struct uae_prefs *prefs) otop[i] = 0; obot[i] = 0; } - for (i = 0; i < MAX_INPUT_DEVICES; i++) { + for (i = 0; i < MAX_JPORTS; i++) { mouse_deltanoreset[i][0] = 0; mouse_delta[i][0] = 0; mouse_deltanoreset[i][1] = 0; @@ -4687,6 +4621,7 @@ static int inputdevice_translatekeycode_2 (int keyboard, int scancode, int state if (!keyboards || scancode < 0) return handled; + j = 0; while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) { if (na->extra[j] == scancode) { @@ -4716,9 +4651,9 @@ static int inputdevice_translatekeycode_2 (int keyboard, int scancode, int state continue; na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] ^= ID_FLAG_TOGGLED; toggled = (na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] & ID_FLAG_TOGGLED) ? 1 : 0; - handled |= handle_input_event (evt, toggled, 1, autofire); + handled |= handle_input_event (evt, toggled, 1, autofire, true, false); } else { - handled |= handle_input_event (evt, state, 1, autofire); + handled |= handle_input_event (evt, state, 1, autofire, true, false); } } process_custom_event (na, j, state); @@ -4783,7 +4718,7 @@ void inputdevice_close (void) idev[IDTYPE_JOYSTICK].close (); idev[IDTYPE_MOUSE].close (); idev[IDTYPE_KEYBOARD].close (); - inprec_close (); + inprec_close (true); } static struct uae_input_device *get_uid (const struct inputdevice_functions *id, int devnum) @@ -5505,13 +5440,17 @@ void setjoystickstate (int joy, int axis, int state, int max) v2 = 0; if (v1 == v2) return; + if (input_play && state) + inprec_realtime (); + if (input_play) + return; if (!joysticks[joy].enabled) { if (v1) switchdevice (&joysticks[joy], axis * 2 + (v1 < 0 ? 0 : 1), 0); return; } for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) - handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE); + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE, true, false); id2->states[axis] = state; } int getjoystickstate (int joy) @@ -5535,6 +5474,8 @@ void setmousestate (int mouse, int axis, int data, int isabs) inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_AXIS, axis, 0); return; } + if (input_play) + return; if (!mice[mouse].enabled) { if (isabs && currprefs.input_tablet > 0) { if (axis == 0) @@ -5575,7 +5516,7 @@ void setmousestate (int mouse, int axis, int data, int isabs) v += diff; fract[mouse][axis] -= diff; for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) - handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0); + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0, true, false); } int getmousestate (int joy) @@ -5777,3 +5718,61 @@ int inputdevice_getjoyportdevice (int port, int val) } return idx; } + +// for state recorder use only! + +uae_u8 *save_inputstate (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + for (int i = 0; i < MAX_JPORTS; i++) { + save_u16 (joydir[i]); + save_u16 (joybutton[i]); + save_u16 (otop[i]); + save_u16 (obot[i]); + save_u16 (oleft[i]); + save_u16 (oright[i]); + } + for (int i = 0; i < NORMAL_JPORTS; i++) { + save_u16 (cd32_shifter[i]); + for (int j = 0; j < 2; j++) { + save_u16 (pot_cap[i][j]); + save_u16 (joydirpot[i][j]); + } + } + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_inputstate (uae_u8 *src) +{ + for (int i = 0; i < MAX_JPORTS; i++) { + joydir[i] = restore_u16 (); + joybutton[i] = restore_u16 (); + otop[i] = restore_u16 (); + obot[i] = restore_u16 (); + oleft[i] = restore_u16 (); + oright[i] = restore_u16 (); + } + for (int i = 0; i < NORMAL_JPORTS; i++) { + cd32_shifter[i] = restore_u16 (); + for (int j = 0; j < 2; j++) { + pot_cap[i][j] = restore_u16 (); + joydirpot[i][j] = restore_u16 (); + } + } + return src; +} + +void clear_inputstate (void) +{ + return; + for (int i = 0; i < MAX_JPORTS; i++) { + horizclear[i] = 1; + vertclear[i] = 1; + } +} diff --git a/inputevents.def b/inputevents.def index e7ae6a7f..5337c8db 100644 --- a/inputevents.def +++ b/inputevents.def @@ -314,7 +314,11 @@ DEFEVENT(SPC_PAUSE,L"Pause emulation",AM_K,0,0,AKS_PAUSE) DEFEVENT(SPC_WARP,L"Warp mode",AM_K,0,0,AKS_WARP) DEFEVENT(SPC_INHIBITSCREEN,L"Toggle screen updates",AM_K,0,0,AKS_INHIBITSCREEN) DEFEVENT(SPC_IRQ7,L"Level 7 interrupt",AM_K,0,0,AKS_IRQ7) -DEFEVENT(SPC_STATEREWIND,L"Load previous state capture",AM_K,0,0,AKS_STATEREWIND) + +DEFEVENT(SPC_STATEREWIND,L"Load previous state capture checkpoint",AM_K,0,0,AKS_STATEREWIND) +DEFEVENT(SPC_STATECURRENT,L"Load current state capture checkpoint",AM_K,0,0,AKS_STATECURRENT) +DEFEVENT(SPC_STATECAPTURE,L"Save state capture checkpoint",AM_K,0,0,AKS_STATECAPTURE) + DEFEVENT(SPC_VOLUME_DOWN,L"Decrease volume level",AM_K,0,0,AKS_VOLDOWN) DEFEVENT(SPC_VOLUME_UP,L"Increase volume level",AM_K,0,0,AKS_VOLUP) DEFEVENT(SPC_VOLUME_MUTE,L"Mute/unmute volume",AM_K,0,0,AKS_VOLMUTE) diff --git a/inputrecord.cpp b/inputrecord.cpp new file mode 100644 index 00000000..09aa1625 --- /dev/null +++ b/inputrecord.cpp @@ -0,0 +1,904 @@ +/* +* UAE - The Un*x Amiga Emulator +* +* Input record/playback +* +* Copyright 2010 Toni Wilen +* +*/ + +#define INPUTRECORD_DEBUG 1 + +#define HEADERSIZE 12 + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "options.h" +#include "inputrecord.h" +#include "zfile.h" +#include "custom.h" +#include "savestate.h" +#include "cia.h" +#include "events.h" +#include "uae.h" +#include "disk.h" + +#if INPUTRECORD_DEBUG > 0 +#include "memory.h" +#include "newcpu.h" +#endif + +int inputrecord_debug = 3; + +extern int inputdevice_logging; + +#define INPREC_BUFFER_SIZE 10000 + +static uae_u8 *inprec_buffer, *inprec_p; +static struct zfile *inprec_zf; +static int inprec_size; +int input_record = 0; +int input_play = 0; +static uae_u8 *inprec_plast, *inprec_plastptr; +static int header_end, header_end2; +static int replaypos; +static int lasthsync, endhsync; +static TCHAR inprec_path[MAX_DPATH]; +static uae_u32 seed; +static uae_u32 lastcycle; +static uae_u32 cycleoffset; + +static uae_u32 pcs[16]; +static uae_u32 pcs2[16]; +extern void activate_debugger (void); +static int warned; + +extern void refreshtitle (void); + +static void setlasthsync (void) +{ + if (lasthsync / current_maxvpos () != hsync_counter / current_maxvpos ()) { + lasthsync = hsync_counter; + refreshtitle (); + } +} + +static void flush (void) +{ + if (inprec_p > inprec_buffer) { + zfile_fwrite (inprec_buffer, inprec_p - inprec_buffer, 1, inprec_zf); + inprec_p = inprec_buffer; + } +} + +static void inprec_ru8 (uae_u8 v) +{ + if (!input_record || !inprec_zf) + return; + *inprec_p++= v; +} +static void inprec_ru16 (uae_u16 v) +{ + if (!input_record || !inprec_zf) + return; + inprec_ru8 ((uae_u8)(v >> 8)); + inprec_ru8 ((uae_u8)v); +} +void inprec_ru32 (uae_u32 v) +{ + if (!input_record || !inprec_zf) + return; + inprec_ru16 ((uae_u16)(v >> 16)); + inprec_ru16 ((uae_u16)v); +} +static void inprec_rstr (const TCHAR *src) +{ + if (!input_record || !inprec_zf) + return; + char *s = uutf8 (src); + char *ss = s; + while (*s) { + inprec_ru8 (*s); + s++; + } + inprec_ru8 (0); + xfree (ss); +} + +static bool inprec_rstart (uae_u8 type) +{ + if (!input_record || !inprec_zf || input_record == INPREC_RECORD_PLAYING) + return false; + lastcycle = get_cycles (); + int mvp = current_maxvpos (); + if ((type != INPREC_DEBUG && type != INPREC_DEBUG2 && type != INPREC_CIADEBUG) || (0 && vsync_counter >= 49 && vsync_counter <= 51)) + write_log (L"INPREC: %010d/%03d: %d (%d/%d) %08x\n", hsync_counter, current_hpos (), type, hsync_counter % mvp, mvp, lastcycle); + inprec_plast = inprec_p; + inprec_ru8 (type); + inprec_ru16 (0xffff); + inprec_ru32 (hsync_counter); + inprec_ru8 (current_hpos ()); + inprec_ru32 (lastcycle); + return true; +} + +static void inprec_rend (void) +{ + if (!input_record || !inprec_zf) + return; + int size = inprec_p - inprec_plast; + inprec_plast[1] = size >> 8; + inprec_plast[2] = size >> 0; + flush (); + endhsync = hsync_counter; + setlasthsync (); +} + +static bool inprec_realtime (bool stopstart) +{ + if (input_record == INPREC_RECORD_RERECORD) + gui_message (L"INPREC error"); + write_log (L"INPREC: play -> record\n"); + input_record = INPREC_RECORD_RERECORD; + input_play = 0; + int offset = inprec_p - inprec_buffer; + zfile_fseek (inprec_zf, offset, SEEK_SET); + zfile_truncate (inprec_zf, offset); + xfree (inprec_buffer); + inprec_size = INPREC_BUFFER_SIZE; + inprec_buffer = inprec_p = xmalloc (uae_u8, inprec_size); + clear_inputstate (); + return true; +} + +static int inprec_pstart (uae_u8 type) +{ + uae_u8 *p = inprec_p; + uae_u32 hc = hsync_counter; + uae_u8 hpos = current_hpos (); + uae_u32 cycles = get_cycles (); + static uae_u8 *lastp; + uae_u32 hc_orig, hc2_orig; + int mvp = current_maxvpos (); + + if (!input_play || !inprec_zf) + return 0; + if (savestate_state || hsync_counter > 0xffff0000) + return 0; + if (p == inprec_buffer + inprec_size) { + write_log (L"INPREC: STOP\n"); + if (input_play == INPREC_PLAY_RERECORD) { + input_play = 0; + inprec_realtime (true); + } else { + inprec_close (true); + } + return 0; + } else if (p > inprec_buffer + inprec_size) { + write_log (L"INPREC: buffer error\n"); + gui_message (L"INPREC error"); + } + if (p[0] == INPREC_END) { + inprec_close (true); + return 0; + } else if (p[0] == INPREC_QUIT) { + inprec_close (true); + uae_quit (); + return 0; + } + hc_orig = hc; + for (;;) { + uae_u32 type2 = p[0]; + uae_u32 hc2 = (p[3] << 24) | (p[4] << 16) | (p[5] << 8) | p[6]; + uae_u32 hpos2 = p[7]; + uae_u32 cycles2 = (p[8] << 24) | (p[9] << 16) | (p[10] << 8) | p[11]; + + if (p >= inprec_buffer + inprec_size) + break; +#if 0 + if (p > lastp) { + write_log (L"INPREC: Next %010d/%03d, %010d/%03d (%d/%d): %d (%d)\n", + hc2, hpos2, hc, hpos, hc2 - hc, hpos2 - hpos, p[5 + 1], p[5]); + lastp = p; + } +#endif + hc2_orig = hc2; + if (type2 == type && hc > hc2) { + write_log (L"INPREC: %010d/%03d > %010d/%03d: %d missed!\n", hc, hpos, hc2, hpos2, p[0]); + gui_message (L"INPREC missed error"); + lastcycle = cycles; + inprec_plast = p; + inprec_plastptr = p + 12; + setlasthsync (); + return 1; + } + if (hc2 != hc) { + lastp = p; + break; + } + if (type2 == type) { + if (type != INPREC_DEBUG && type != INPREC_DEBUG2 && type != INPREC_CIADEBUG && cycles != cycles2) + write_log (L"INPREC: %010d/%03d: %d (%d/%d) (%d/%d) %08X/%08X\n", hc, hpos, type, hc % mvp, mvp, hc_orig - hc2_orig, hpos - hpos2, cycles, cycles2); + if (cycles != cycles2 + cycleoffset) { + if (warned > 0) { + warned--; + for (int i = 0; i < 7; i++) + write_log (L"%08x (%08x) ", pcs[i], pcs2[i]); + write_log (L"\n"); + } + cycleoffset = cycles - cycles2; + gui_message (L"INPREC OFFSET=%d\n", cycleoffset / CYCLE_UNIT); + } + lastcycle = cycles; + inprec_plast = p; + inprec_plastptr = p + 12; + setlasthsync (); + return 1; + } + if (type2 == INPREC_END || type2 == INPREC_QUIT) + break; + p += (p[1] << 8) | (p[2] << 0); + } + inprec_plast = NULL; + return 0; +} + +static void inprec_pend (void) +{ + uae_u8 *p = inprec_p; + uae_u32 hc = hsync_counter; + uae_u32 hpos = current_hpos (); + + if (!input_play || !inprec_zf) + return; + if (!inprec_plast) + return; + inprec_plast[0] |= 0x80; + inprec_plast = NULL; + inprec_plastptr = NULL; + for (;;) { + uae_u32 hc2 = (p[3] << 24) | (p[4] << 16) | (p[5] << 8) | p[6]; + uae_u32 hpos2 = p[7]; + if (hc2 != hc) + break; + if ((p[0] & 0x80) == 0) + return; + p += (p[1] << 8) | (p[2] << 0); + inprec_p = p; + } +} + +static uae_u8 inprec_pu8 (void) +{ + return *inprec_plastptr++; +} +static uae_u16 inprec_pu16 (void) +{ + uae_u16 v = inprec_pu8 () << 8; + v |= inprec_pu8 (); + return v; +} +static uae_s16 inprec_ps16 (void) +{ + uae_u16 v = inprec_pu8 () << 8; + v |= inprec_pu8 (); + return (uae_s16)v; +} +static uae_u32 inprec_pu32 (void) +{ + uae_u32 v = inprec_pu16 () << 16; + v |= inprec_pu16 (); + return v; +} +static int inprec_pstr (TCHAR *dst) +{ + char tmp[MAX_DPATH]; + char *s; + int len = 0; + + *dst = 0; + s = tmp; + for(;;) { + char v = inprec_pu8 (); + *s++ = v; + if (!v) + break; + len++; + } + if (tmp[0]) { + TCHAR *d = utf8u (tmp); + _tcscpy (dst, d); + xfree (d); + } + return len; +} + +static void findlast (void) +{ + uae_u32 hsync = 0; + uae_u8 *p = inprec_p; + while (p < inprec_buffer + inprec_size) { + hsync = (p[3] << 24) | (p[4] << 16) | (p[5] << 8) | p[6]; + uae_u16 len = (p[1] << 8) | (p[2] << 0); + p += len; + } + endhsync = hsync; +} + + +int inprec_open (const TCHAR *fname, const TCHAR *statefilename) +{ + int i; + + inprec_close (false); + if (fname == NULL) + inprec_zf = zfile_fopen_empty (NULL, L"inp"); + else + inprec_zf = zfile_fopen (fname, input_record ? L"wb" : L"rb", ZFD_NORMAL); + if (inprec_zf == NULL) + return 0; + inprec_path[0] = 0; + if (fname) + getpathpart (inprec_path, sizeof inprec_path / sizeof (TCHAR), fname); + seed = (uae_u32)time(0); + inprec_size = INPREC_BUFFER_SIZE; + lasthsync = 0; + endhsync = 0; + warned = 10; + cycleoffset = 0; + header_end2 = 0; + if (input_play) { + uae_u32 id; + zfile_fseek (inprec_zf, 0, SEEK_END); + inprec_size = zfile_ftell (inprec_zf); + zfile_fseek (inprec_zf, 0, SEEK_SET); + inprec_buffer = inprec_p = xmalloc (uae_u8, inprec_size); + zfile_fread (inprec_buffer, inprec_size, 1, inprec_zf); + inprec_plastptr = inprec_buffer; + id = inprec_pu32(); + if (id != 'UAE\0') { + inprec_close (true); + return 0; + } + int v = inprec_pu8 (); + if (v != 2) { + inprec_close (true); + return 0; + } + inprec_pu8 (); + inprec_pu8 (); + inprec_pu8 (); + seed = inprec_pu32(); + seed = uaesrand (seed); + vsync_counter = inprec_pu32 (); + hsync_counter = inprec_pu32 (); + i = inprec_pu32 (); + while (i-- > 0) + inprec_pu8 (); + header_end = inprec_plastptr - inprec_buffer; + inprec_pstr (savestate_fname); + if (savestate_fname[0]) { + savestate_state = STATE_RESTORE; + for (;;) { + TCHAR tmp[MAX_DPATH]; + _tcscpy (tmp, fname); + _tcscat (tmp, L".uss"); + if (zfile_exists (tmp)) { + _tcscpy (savestate_fname, tmp); + break; + } + if (zfile_exists (savestate_fname)) + break; + TCHAR *p = _tcsrchr (savestate_fname, '\\'); + if (!p) + p = _tcsrchr (savestate_fname, '/'); + if (!p) + p = savestate_fname; + else + p++; + if (zfile_exists (p)) { + _tcscpy (savestate_fname, p); + break; + } + fetch_statefilepath (tmp, sizeof tmp / sizeof (TCHAR)); + _tcscat (tmp, p); + if (zfile_exists (tmp)) { + _tcscpy (savestate_fname, tmp); + break; + } + fetch_inputfilepath (tmp, sizeof tmp / sizeof (TCHAR)); + _tcscat (tmp, p); + if (zfile_exists (tmp)) { + _tcscpy (savestate_fname, tmp); + break; + } + write_log (L"Failed to open linked statefile '%s'\n", savestate_fname); + savestate_fname[0] = 0; + savestate_state = 0; + break; + } + } + inprec_p = inprec_plastptr; + header_end2 = inprec_plastptr - inprec_buffer; + findlast (); + } else if (input_record) { + seed = uaesrand (seed); + inprec_buffer = inprec_p = xmalloc (uae_u8, inprec_size); + inprec_ru32 ('UAE\0'); + inprec_ru8 (2); + inprec_ru8 (UAEMAJOR); + inprec_ru8 (UAEMINOR); + inprec_ru8 (UAESUBREV); + inprec_ru32 (seed); + inprec_ru32 (vsync_counter); + inprec_ru32 (hsync_counter); + inprec_ru32 (0); // extra header size + flush (); + header_end2 = header_end = zfile_ftell (inprec_zf); + } else { + input_record = input_play = 0; + return 0; + } + if (inputrecord_debug) { + if (disk_debug_logging < 1) + disk_debug_logging = 1 | 2; + inputdevice_logging |= 4 | 2; + } + write_log (L"inprec initialized '%s', play=%d rec=%d\n", fname ? fname : L"", input_play, input_record); + refreshtitle (); + return 1; +} + +void inprec_startup (void) +{ + uaesrand (seed); +} + +bool inprec_prepare_record (const TCHAR *statefilename) +{ + TCHAR state[MAX_DPATH]; + int mode = statefilename ? 2 : 1; + state[0] = 0; + if (statefilename) + _tcscpy (state, statefilename); + if (hsync_counter > 0 && savestate_state == 0) { + TCHAR *s = _tcsrchr (changed_prefs.inprecfile, '\\'); + if (!s) + s = _tcsrchr (changed_prefs.inprecfile, '/'); + if (s) { + fetch_statefilepath (state, sizeof state / sizeof (TCHAR)); + _tcscat (state, s + 1); + } else { + _tcscpy (state, changed_prefs.inprecfile); + } + _tcscat (state, L".uss"); + savestate_initsave (state, 1, 1, true); + save_state (state, L"input recording test"); + mode = 2; + } + input_record = INPREC_RECORD_NORMAL; + inprec_open (changed_prefs.inprecfile, state); + changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0; + return true; +} + + +void inprec_close (bool clear) +{ + if (clear) + input_play = input_record = 0; + if (!inprec_zf) + return; + if (inprec_buffer && input_record) { + if (inprec_rstart (INPREC_END)) + inprec_rend (); + } + zfile_fclose (inprec_zf); + inprec_zf = NULL; + xfree (inprec_buffer); + inprec_buffer = NULL; + input_play = input_record = 0; + write_log (L"inprec finished\n"); + refreshtitle (); +} + +static void setwriteprotect (const TCHAR *fname, bool readonly) +{ + struct _stat64 st; + int mode, oldmode; + if (stat (fname, &st)) + return; + oldmode = mode = st.st_mode; + mode &= ~FILEFLAG_WRITE; + if (!readonly) + mode |= FILEFLAG_WRITE; + if (mode != oldmode) + chmod (fname, mode); +} + +void inprec_playdiskchange (void) +{ + if (!input_play) + return; + while (inprec_pstart (INPREC_DISKREMOVE)) { + int drv = inprec_pu8 (); + inprec_pend (); + write_log (L"INPREC: disk eject drive %d\n", drv); + disk_eject (drv); + } + while (inprec_pstart (INPREC_DISKINSERT)) { + int drv = inprec_pu8 (); + bool wp = inprec_pu8 () != 0; + TCHAR tmp[MAX_DPATH]; + inprec_pstr (tmp); + if (!zfile_exists (tmp)) { + TCHAR tmp2[MAX_DPATH]; + _tcscpy (tmp2, inprec_path); + _tcscat (tmp2, tmp); + _tcscpy (tmp, tmp2); + } + _tcscpy (currprefs.floppyslots[drv].df, tmp); + _tcscpy (changed_prefs.floppyslots[drv].df, tmp); + setwriteprotect (tmp, wp); + disk_insert_force (drv, tmp, wp); + write_log (L"INPREC: disk insert drive %d '%s'\n", drv, tmp); + inprec_pend (); + } +} + +bool inprec_playevent (int *nr, int *state, int *max, int *autofire) +{ + if (inprec_pstart (INPREC_EVENT)) { + *nr = inprec_ps16 (); + *state = inprec_ps16 (); + *max = inprec_ps16 (); + *autofire = inprec_ps16 () & 1; + inprec_pend (); + return true; + } + return false; +} + +void inprec_recorddebug_cia (uae_u32 v1, uae_u32 v2, uae_u32 v3) +{ +#if INPUTRECORD_DEBUG > 0 + if (inprec_rstart (INPREC_CIADEBUG)) { + inprec_ru32 (v1); + inprec_ru32 (v2); + inprec_ru32 (v3); + inprec_rend (); + } +#endif +} +void inprec_playdebug_cia (uae_u32 v1, uae_u32 v2, uae_u32 v3) +{ +#if INPUTRECORD_DEBUG > 0 + int err = 0; + if (inprec_pstart (INPREC_CIADEBUG)) { + uae_u32 vv1 = inprec_pu32 (); + uae_u32 vv2 = inprec_pu32 (); + uae_u32 vv3 = inprec_pu32 (); + if (vv1 != v1 || vv2 != v2 || vv3 != v3) + write_log (L"CIA SYNC ERROR %08x,%08x %08x,%08x %08x,%08x\n", vv1, v1, vv2, v2, vv3, v3); + inprec_pend (); + } +#endif +} + +void inprec_recorddebug_cpu (int mode) +{ +#if INPUTRECORD_DEBUG > 0 + if (inprec_rstart (INPREC_DEBUG2)) { + inprec_ru32 (m68k_getpc ()); + inprec_ru32 (get_cycles () | mode); + inprec_rend (); + } +#endif +} +void inprec_playdebug_cpu (int mode) +{ +#if INPUTRECORD_DEBUG > 0 + int err = 0; + if (inprec_pstart (INPREC_DEBUG2)) { + uae_u32 pc1 = m68k_getpc (); + uae_u32 pc2 = inprec_pu32 (); + uae_u32 v1 = get_cycles () | mode; + uae_u32 v2 = inprec_pu32 (); + if (pc1 != pc2) { + if (warned > 0) { + warned--; + write_log (L"SYNC ERROR2 PC %08x != %08x\n", pc1, pc2); + for (int i = 0; i < 15; i++) + write_log (L"%08x ", pcs[i]); + write_log (L"\n"); + + } + err = 1; + } else { + memmove (pcs + 1, pcs, 15 * 4); + pcs[0] = pc1; + memmove (pcs2 + 1, pcs2, 15 * 4); + pcs2[0] = get_cycles (); + } + if (v1 != v2) { + if (warned > 0) { + warned--; + write_log (L"SYNC ERROR2 %08x != %08x\n", v1, v2); + for (int i = 0; i < 15; i++) + write_log (L"%08x ", pcs[i]); + write_log (L"\n"); + } + err = 1; + } + inprec_pend (); + } else if (input_play > 0) { + if (warned > 0) { + warned--; + write_log (L"SYNC ERROR2 debug event missing!?\n"); + } + } +#endif +} + +void inprec_recorddebug (uae_u32 val) +{ +#if INPUTRECORD_DEBUG > 0 + if (inprec_rstart (INPREC_DEBUG)) { + inprec_ru32 (uaerandgetseed ()); + inprec_ru32 (val); + inprec_rend (); + } +#endif +} +void inprec_playdebug (uae_u32 val) +{ +#if INPUTRECORD_DEBUG > 0 + extern void activate_debugger (void); + static uae_u32 pcs[16]; + int err = 0; + if (inprec_pstart (INPREC_DEBUG)) { + uae_u32 seed1 = uaerandgetseed (); + uae_u32 seed2 = inprec_pu32 (); + if (seed1 != seed2) { + write_log (L"SYNC ERROR seed %08x != %08x\n", seed1, seed2); + err = 1; + } + uae_u32 val2 = inprec_pu32 (); + if (val != val2) { + write_log (L"SYNC ERROR val %08x != %08x\n", val, val2); + err = 1; + } + inprec_pend (); + } else if (input_play > 0) { + gui_message (L"SYNC ERROR debug event missing!?\n"); + } +#endif +} + + +void inprec_recordevent (int nr, int state, int max, int autofire) +{ + if (savestate_state) + return; + if (input_record < INPREC_RECORD_NORMAL) + return; + if (inprec_rstart (INPREC_EVENT)) { + inprec_ru16 (nr); + inprec_ru16 (state); + inprec_ru16 (max); + inprec_ru16 (autofire ? 1 : 0); + inprec_rend (); + if (input_record == INPREC_RECORD_NORMAL) + input_record = INPREC_RECORD_RERECORD; + } +} + +void inprec_recorddiskchange (int nr, const TCHAR *fname, bool writeprotected) +{ + if (savestate_state) + return; + if (input_record < INPREC_RECORD_NORMAL) + return; + if (fname && fname[0]) { + if (inprec_rstart (INPREC_DISKINSERT)) { + inprec_ru8 (nr); + inprec_ru8 (writeprotected ? 1 : 0); + inprec_rstr (fname); + write_log (L"INPREC: disk insert %d '%s'\n", nr, fname); + inprec_rend (); + } + } else { + if (inprec_rstart (INPREC_DISKREMOVE)) { + inprec_ru8 (nr); + write_log (L"INPREC: disk eject %d\n", nr); + inprec_rend (); + } + } +} + +int inprec_getposition (void) +{ + int pos = -1; + if (input_play == INPREC_PLAY_RERECORD) { + pos = inprec_p - inprec_buffer; + } else if (input_record) { + pos = zfile_ftell (inprec_zf); + } + write_log (L"INPREC: getpos=%d cycles=%08X\n", pos, lastcycle); + if (pos < 0) { + write_log (L"INPREC: getpos failure\n"); + gui_message (L"INPREC error"); + } + return pos; +} + +// normal play to re-record +void inprec_playtorecord (void) +{ + write_log (L"INPREC: PLAY to RE-RECORD\n"); + replaypos = 0; + findlast (); + input_play = INPREC_PLAY_RERECORD; + input_record = INPREC_RECORD_PLAYING; + zfile_fclose (inprec_zf); + inprec_zf = zfile_fopen_empty (NULL, L"inp"); + zfile_fwrite (inprec_buffer, header_end2, 1, inprec_zf); + uae_u8 *p = inprec_buffer + header_end2; + uae_u8 *end = inprec_buffer + inprec_size; + while (p < end) { + int len = (p[1] << 8) | (p[2] << 0); + p[0] &= ~0x80; + p += len; + } + zfile_fwrite (inprec_buffer + header_end2, inprec_size - header_end2, 1, inprec_zf); +} + +void inprec_setposition (int offset, int replaycounter) +{ + if (!inprec_buffer) + return; + replaypos = replaycounter; + write_log (L"INPREC: setpos=%d\n", offset); + if (offset < header_end || offset > zfile_size (inprec_zf)) { + write_log (L"INPREC: buffer corruption. offset=%d, size=%d\n", offset, zfile_size (inprec_zf)); + gui_message (L"INPREC error"); + } + zfile_fseek (inprec_zf, 0, SEEK_SET); + xfree (inprec_buffer); + inprec_size = zfile_size (inprec_zf); + inprec_buffer = xmalloc (uae_u8, inprec_size); + zfile_fread (inprec_buffer, inprec_size, 1, inprec_zf); + inprec_p = inprec_plastptr = inprec_buffer + offset; + findlast (); + input_play = INPREC_PLAY_RERECORD; + input_record = INPREC_RECORD_PLAYING; + if (currprefs.inprec_autoplay == false) + inprec_realtime (false); +} + +static int savedisk (const TCHAR *path, const TCHAR *file, uae_u8 *data, uae_u8 *outdata) +{ + int len = 0; + TCHAR *fname = utf8u ((const char*)data + 2); + if (fname[0]) { + TCHAR tmp[MAX_DPATH]; + TCHAR filename[MAX_DPATH]; + filename[0] = 0; + struct zfile *zf = zfile_fopen (fname, L"rb", ZFD_NORMAL); + if (!zf) { + _tcscpy (tmp, path); + _tcscat (tmp, fname); + zf = zfile_fopen (tmp, L"rb", ZFD_NORMAL); + if (!zf) + write_log (L"failed to open '%s'\n", tmp); + } + if (zf) { + _tcscpy (tmp, path); + _tcscpy (filename, file); + _tcscat (filename, L"."); + getfilepart (filename + _tcslen (filename), MAX_DPATH, zfile_getname (zf)); + _tcscat (tmp, filename); + struct zfile *zfd = zfile_fopen (tmp, L"wb"); + if (zfd) { + int size = zfile_size (zf); + uae_u8 *data = zfile_getdata (zf, 0, size); + zfile_fwrite (data, size, 1, zfd); + zfile_fclose (zfd); + xfree (data); + } + zfile_fclose (zf); + setwriteprotect (fname, data[1] != 0); + } + if (filename[0]) { + outdata[0] = data[0]; + char *fn = uutf8 (filename); + strcpy ((char*)outdata + 2, fn); + xfree (fn); + len = 2 + strlen ((char*)outdata + 2) + 1; + } + } + xfree (fname); + return len; +} + +void inprec_save (const TCHAR *filename, const TCHAR *statefilename) +{ + TCHAR path[MAX_DPATH], file[MAX_DPATH]; + if (!inprec_buffer) + return; + getpathpart (path, sizeof path / sizeof (TCHAR), filename); + getfilepart (file, sizeof file / sizeof (TCHAR), filename); + struct zfile *zf = zfile_fopen (filename, L"wb", 0); + if (zf) { + TCHAR fn[MAX_DPATH]; + uae_u8 *data; + data = zfile_getdata (inprec_zf, 0, header_end); + zfile_fwrite (data, header_end, 1, zf); + xfree (data); + getfilepart (fn, MAX_DPATH, statefilename); + char *s = uutf8 (fn); + zfile_fwrite (s, strlen (s) + 1, 1, zf); + int len = zfile_size (inprec_zf) - header_end2; + data = zfile_getdata (inprec_zf, header_end2, len); + uae_u8 *p = data; + uae_u8 *end = data + len; + while (p < end) { + uae_u8 tmp[MAX_DPATH]; + int plen = (p[1] << 8) | (p[2] << 0); + int wlen = plen - HEADERSIZE; + memcpy (tmp, p + HEADERSIZE, wlen); + if (p[0] == INPREC_DISKINSERT) { + wlen = savedisk (path, file, p + HEADERSIZE, tmp); + } + if (wlen) { + wlen += HEADERSIZE; + p[1] = wlen >> 8; + p[2] = wlen; + zfile_fwrite (p, HEADERSIZE, 1, zf); + zfile_fwrite (tmp, wlen - HEADERSIZE, 1, zf); + } else { + zfile_fwrite (p, plen, 1, zf); + } + p += plen; + } + xfree (data); + zfile_fclose (zf); + write_log (L"inputfile '%s' saved\n", filename); + } else { + write_log (L"failed to open '%s'\n", filename); + } +} + +bool inprec_realtime (void) +{ + if (input_record != INPREC_RECORD_PLAYING || input_play != INPREC_PLAY_RERECORD) + return false; + //clear_inputstate (); + return inprec_realtime (false); +} + +void inprec_getstatus (TCHAR *title) +{ + TCHAR *p; + if (!input_record && !input_play) + return; + _tcscat (title, L"["); + if (input_record) { + if (input_record != INPREC_RECORD_PLAYING) + _tcscat (title, L"-REC-"); + else + _tcscat (title, L"REPLAY"); + } else if (input_play) { + _tcscat (title, L"PLAY-"); + } + _tcscat (title, L" "); + p = title + _tcslen (title); + int mvp = current_maxvpos (); + _stprintf (p, L"%03d %02d:%02d:%02d/%02d:%02d:%02d", replaypos, + lasthsync / (vblank_hz * mvp * 60), (lasthsync / (vblank_hz * mvp) % 60), (lasthsync / mvp) % vblank_hz, + endhsync / (vblank_hz * mvp * 60), (endhsync / (vblank_hz * mvp) % 60), (endhsync / mvp) % vblank_hz); + p += _tcslen (p); + _tcscat (p, L"] "); + +} diff --git a/keybuf.cpp b/keybuf.cpp index d3edb3f3..9ce99307 100644 --- a/keybuf.cpp +++ b/keybuf.cpp @@ -48,7 +48,7 @@ int get_next_key (void) int record_key (int kc) { - if (input_recording < 0 || pause_emulation) + if (pause_emulation) return 0; return record_key_direct (kc); } @@ -73,12 +73,6 @@ int record_key_direct (int kc) kc ^= AK_CTRL << 1; } - if (input_recording > 0) { - inprec_rstart(INPREC_KEY); - inprec_ru8(kc); - inprec_rend(); - } - keybuf[kpb_first] = kc; kpb_first = kpb_next; return 1; @@ -89,24 +83,3 @@ void keybuf_init (void) kpb_first = kpb_last = 0; inputdevice_updateconfig (&currprefs); } - -#ifdef SAVESTATE - -uae_u8 *save_keyboard (int *len) -{ - uae_u8 *dst, *t; - dst = t = xmalloc (uae_u8, 8); - save_u32 (getcapslockstate () ? 1 : 0); - save_u32 (0); - *len = 8; - return t; -} - -uae_u8 *restore_keyboard (uae_u8 *src) -{ - setcapslockstate (restore_u32 ()); - restore_u32 (); - return src; -} - -#endif /* SAVESTATE */ diff --git a/main.cpp b/main.cpp index b8d15de3..953c592c 100644 --- a/main.cpp +++ b/main.cpp @@ -74,9 +74,30 @@ TCHAR warning_buffer[256]; TCHAR optionsfile[256]; -int uaerand (void) +static uae_u32 randseed; +static int oldhcounter; + +uae_u32 uaesrand (uae_u32 seed) +{ + oldhcounter = -1; + randseed = seed; + //randseed = 0x12345678; + //write_log (L"seed=%08x\n", randseed); + return randseed; +} +uae_u32 uaerand (void) { - return rand (); + if (oldhcounter != hsync_counter) { + srand (hsync_counter ^ randseed); + oldhcounter = hsync_counter; + } + uae_u32 r = rand (); + //write_log (L"rand=%08x\n", r); + return r; +} +uae_u32 uaerandgetseed (void) +{ + return randseed; } void discard_prefs (struct uae_prefs *p, int type) @@ -401,6 +422,10 @@ static int default_config; void uae_reset (int hardreset) { + if (debug_dma) { + record_dma_reset (); + record_dma_reset (); + } currprefs.quitstatefile[0] = changed_prefs.quitstatefile[0] = 0; if (quit_program == 0) { diff --git a/memory.cpp b/memory.cpp index 4763d6d0..fdf91200 100644 --- a/memory.cpp +++ b/memory.cpp @@ -2326,7 +2326,7 @@ void map_overlay (int chip) map_banks (rb, 0, size, 0x80000); } fill_ce_banks (); - if (savestate_state != STATE_RESTORE && savestate_state != STATE_REWIND && valid_address (regs.pc, 4)) + if (!isrestore () && valid_address (regs.pc, 4)) m68k_setpc (m68k_getpc ()); } diff --git a/newcpu.cpp b/newcpu.cpp index 31be1dcc..08bd4882 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -31,7 +31,7 @@ #include "ar.h" #include "gayle.h" #include "cia.h" -#include "inputdevice.h" +#include "inputrecord.h" #ifdef JIT #include "jit/compemu.h" #include @@ -53,12 +53,12 @@ static uaecptr last_fault_for_exception_3; static int last_writeaccess_for_exception_3; /* instruction (1) or data (0) access */ static int last_instructionaccess_for_exception_3; -unsigned long irqcycles[15]; -int irqdelay[15]; int mmu_enabled, mmu_triggered; int cpu_cycles; static int baseclock; + int cpucycleunit; +int cpu_tracer; const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 }; const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; @@ -136,22 +136,492 @@ void dump_counts (void) } #endif +/* + + ok, all this to "record" current instruction state + for later 100% cycle-exact restoring + + */ + +static uae_u32 (*x2_prefetch)(int); +static uae_u32 (*x2_prefetch_long)(int); +static uae_u32 (*x2_next_iword)(void); +static uae_u32 (*x2_next_ilong)(void); +static uae_u32 (*x2_get_ilong)(int); +static uae_u32 (*x2_get_iword)(int); +static uae_u32 (*x2_get_ibyte)(int); +static uae_u32 (*x2_get_long)(uaecptr); +static uae_u32 (*x2_get_word)(uaecptr); +static uae_u32 (*x2_get_byte)(uaecptr); +static void (*x2_put_long)(uaecptr,uae_u32); +static void (*x2_put_word)(uaecptr,uae_u32); +static void (*x2_put_byte)(uaecptr,uae_u32); +static void (*x2_do_cycles)(unsigned long); +static void (*x2_do_cycles_pre)(unsigned long); +static void (*x2_do_cycles_post)(unsigned long, uae_u32); uae_u32 (*x_prefetch)(int); +uae_u32 (*x_prefetch_long)(int); uae_u32 (*x_next_iword)(void); uae_u32 (*x_next_ilong)(void); +uae_u32 (*x_get_ilong)(int); +uae_u32 (*x_get_iword)(int); +uae_u32 (*x_get_ibyte)(int); uae_u32 (*x_get_long)(uaecptr); uae_u32 (*x_get_word)(uaecptr); uae_u32 (*x_get_byte)(uaecptr); void (*x_put_long)(uaecptr,uae_u32); void (*x_put_word)(uaecptr,uae_u32); void (*x_put_byte)(uaecptr,uae_u32); +void (*x_do_cycles)(unsigned long); +void (*x_do_cycles_pre)(unsigned long); +void (*x_do_cycles_post)(unsigned long, uae_u32); + +static struct cputracestruct cputrace; + +STATIC_INLINE void clear_trace (void) +{ + struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++]; + ctm->mode = 0; + cputrace.cyclecounter = 0; + cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0; +} +static void set_trace (uaecptr addr, int accessmode, int size) +{ + struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++]; + ctm->addr = addr; + ctm->data = 0xdeadf00d; + ctm->mode = accessmode | (size << 4); + cputrace.cyclecounter_pre = -1; + if (accessmode == 1) + cputrace.writecounter++; + else + cputrace.readcounter++; +} +static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size) +{ + int mode = accessmode | (size << 4); + struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1]; + ctm->addr = addr; + ctm->data = val; + if (!ctm->mode) { + ctm->mode = mode; + if (accessmode == 1) + cputrace.writecounter++; + else + cputrace.readcounter++; + } + cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0; +} + + +static void check_trace2 (void) +{ + if (cputrace.readcounter || cputrace.writecounter || + cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post) + write_log (L"CPU tracer invalid state during playback!\n"); +} + +static bool check_trace (void) +{ + if (!cpu_tracer) + return true; + if (cputrace.readcounter || cputrace.writecounter || + cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post) + return false; + x_prefetch = x2_prefetch; + x_prefetch_long = x2_prefetch_long; + x_get_ilong = x2_get_ilong; + x_get_iword = x2_get_iword; + x_get_ibyte = x2_get_ibyte; + x_next_iword = x2_next_iword; + x_next_ilong = x2_next_ilong; + x_put_long = x2_put_long; + x_put_word = x2_put_word; + x_put_byte = x2_put_byte; + x_get_long = x2_get_long; + x_get_word = x2_get_word; + x_get_byte = x2_get_byte; + x_do_cycles = x2_do_cycles; + x_do_cycles_pre = x2_do_cycles_pre; + x_do_cycles_post = x2_do_cycles_post; + write_log (L"CPU tracer playback complete\n"); + cpu_tracer = 0; + return true; +} + +static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data) +{ + int mode = accessmode | (size << 4); + for (int i = 0; i < cputrace.memoryoffset; i++) { + struct cputracememory *ctm = &cputrace.ctm[i]; + if (ctm->addr == addr && ctm->mode == mode) { + ctm->mode = 0; + write_log (L"CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d\n", + i, cputrace.pc, addr, ctm->data, accessmode, size, + cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post, + cputrace.readcounter, cputrace.writecounter); + if (accessmode == 1) + cputrace.writecounter--; + else + cputrace.readcounter--; + if (cputrace.writecounter == 0 && cputrace.readcounter == 0) { + if (cputrace.cyclecounter_post) { + int c = cputrace.cyclecounter_post; + cputrace.cyclecounter_post = 0; + x_do_cycles (c); + } else if (cputrace.cyclecounter_pre) { + cputrace.cyclecounter_pre = 0; + check_trace (); + return true; // argh, need to rerun the memory access.. + } + } + check_trace (); + *data = ctm->data; + return false; + } + } + if (cputrace.cyclecounter_post) { + int c = cputrace.cyclecounter_post; + cputrace.cyclecounter_post = 0; + check_trace (); + check_trace2 (); + x_do_cycles (c); + return false; + } + gui_message (L"CPU trace: GET %08x %d %d NOT FOUND!\n", addr, accessmode, size); + check_trace (); + *data = 0; + return false; +} + +static uae_u32 cputracefunc_x_prefetch (int o) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc + o, 2, 2); + uae_u32 v = x2_prefetch (o); + add_trace (pc + o, v, 2, 2); + return v; +} +static uae_u32 cputracefunc2_x_prefetch (int o) +{ + uae_u32 v; + if (get_trace (m68k_getpc () + o, 2, 2, &v)) { + v = x2_prefetch (o); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc_x_prefetch_long (int o) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc + o, 2, 4); + uae_u32 v = x2_prefetch_long (o); + add_trace (pc + o, v, 2, 4); + return v; +} +static uae_u32 cputracefunc2_x_prefetch_long (int o) +{ + uae_u32 v; + if (get_trace (m68k_getpc () + o, 2, 4, &v)) { + v = x2_prefetch_long (o); + check_trace2 (); + } + return v; +} + +static uae_u32 cputracefunc_x_next_iword (void) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc, 2, 2); + uae_u32 v = x2_next_iword (); + add_trace (pc, v, 2, 2); + return v; +} +static uae_u32 cputracefunc_x_next_ilong (void) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc, 2, 4); + uae_u32 v = x2_next_ilong (); + add_trace (pc, v, 2, 4); + return v; +} +static uae_u32 cputracefunc2_x_next_iword (void) +{ + uae_u32 v; + if (get_trace (m68k_getpc (), 2, 2, &v)) { + v = x2_next_iword (); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc2_x_next_ilong (void) +{ + uae_u32 v; + if (get_trace (m68k_getpc (), 2, 4, &v)) { + v = x2_next_ilong (); + check_trace2 (); + } + return v; +} + +static uae_u32 cputracefunc_x_get_ilong (int o) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc + o, 2, 4); + uae_u32 v = x2_get_ilong (o); + add_trace (pc + o, v, 2, 4); + return v; +} +static uae_u32 cputracefunc_x_get_iword (int o) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc + o, 2, 2); + uae_u32 v = x2_get_iword (o); + add_trace (pc + o, v, 2, 2); + return v; +} +static uae_u32 cputracefunc_x_get_ibyte (int o) +{ + uae_u32 pc = m68k_getpc (); + set_trace (pc + o, 2, 1); + uae_u32 v = x2_get_ibyte (o); + add_trace (pc + o, v, 2, 1); + return v; +} +static uae_u32 cputracefunc2_x_get_ilong (int o) +{ + uae_u32 v; + if (get_trace (m68k_getpc () + o, 2, 4, &v)) { + v = x2_get_ilong (o); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc2_x_get_iword (int o) +{ + uae_u32 v; + if (get_trace (m68k_getpc () + o, 2, 2, &v)) { + v = x2_get_iword (o); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc2_x_get_ibyte (int o) +{ + uae_u32 v; + if (get_trace (m68k_getpc () + o, 2, 1, &v)) { + v = x2_get_ibyte (o); + check_trace2 (); + } + return v; +} + +static uae_u32 cputracefunc_x_get_long (uaecptr o) +{ + set_trace (o, 0, 4); + uae_u32 v = x2_get_long (o); + add_trace (o, v, 0, 4); + return v; +} +static uae_u32 cputracefunc_x_get_word (uaecptr o) +{ + set_trace (o, 0, 2); + uae_u32 v = x2_get_word (o); + add_trace (o, v, 0, 2); + return v; +} +static uae_u32 cputracefunc_x_get_byte (uaecptr o) +{ + set_trace (o, 0, 1); + uae_u32 v = x2_get_byte (o); + add_trace (o, v, 0, 1); + return v; +} +static uae_u32 cputracefunc2_x_get_long (uaecptr o) +{ + uae_u32 v; + if (get_trace (o, 0, 4, &v)) { + v = x2_get_long (o); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc2_x_get_word (uaecptr o) +{ + uae_u32 v; + if (get_trace (o, 0, 2, &v)) { + v = x2_get_word (o); + check_trace2 (); + } + return v; +} +static uae_u32 cputracefunc2_x_get_byte (uaecptr o) +{ + uae_u32 v; + if (get_trace (o, 0, 1, &v)) { + v = x2_get_byte (o); + check_trace2 (); + } + return v; +} -// shared memory access functions +static void cputracefunc_x_put_long (uaecptr o, uae_u32 val) +{ + clear_trace (); + add_trace (o, val, 1, 4); + x2_put_long (o, val); +} +static void cputracefunc_x_put_word (uaecptr o, uae_u32 val) +{ + clear_trace (); + add_trace (o, val, 1, 2); + x2_put_word (o, val); +} +static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val) +{ + clear_trace (); + add_trace (o, val, 1, 1); + x2_put_byte (o, val); +} +static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val) +{ + uae_u32 v; + if (get_trace (o, 1, 4, &v)) { + x2_put_long (o, val); + check_trace2 (); + } + if (v != val) + write_log (L"cputracefunc2_x_put_long %d <> %d\n", v, val); +} +static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val) +{ + uae_u32 v; + if (get_trace (o, 1, 2, &v)) { + x2_put_word (o, val); + check_trace2 (); + } + if (v != val) + write_log (L"cputracefunc2_x_put_word %d <> %d\n", v, val); +} +static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val) +{ + uae_u32 v; + if (get_trace (o, 1, 1, &v)) { + x2_put_byte (o, val); + check_trace2 (); + } + if (v != val) + write_log (L"cputracefunc2_x_put_byte %d <> %d\n", v, val); +} + +static void cputracefunc_x_do_cycles (unsigned long cycles) +{ + while (cycles >= CYCLE_UNIT) { + cputrace.cyclecounter += CYCLE_UNIT; + cycles -= CYCLE_UNIT; + x2_do_cycles (CYCLE_UNIT); + } + if (cycles > 0) { + cputrace.cyclecounter += cycles; + x2_do_cycles (cycles); + } +} +static void cputracefunc_x_do_cycles_pre (unsigned long cycles) +{ + cputrace.cyclecounter_post = 0; + cputrace.cyclecounter_pre = 0; + while (cycles >= CYCLE_UNIT) { + cycles -= CYCLE_UNIT; + cputrace.cyclecounter_pre += CYCLE_UNIT; + x2_do_cycles (CYCLE_UNIT); + } + if (cycles > 0) { + x2_do_cycles (cycles); + cputrace.cyclecounter_pre += cycles; + } + cputrace.cyclecounter_pre = 0; +} +static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v) +{ + struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1]; + ctm->data = v; + cputrace.cyclecounter_post = 0; + cputrace.cyclecounter_pre = 0; + while (cycles >= CYCLE_UNIT) { + cycles -= CYCLE_UNIT; + cputrace.cyclecounter_post += CYCLE_UNIT; + x2_do_cycles (CYCLE_UNIT); + } + if (cycles > 0) { + x2_do_cycles (cycles); + cputrace.cyclecounter_post += cycles; + } + cputrace.cyclecounter_post = 0; +} + +static void cputracefunc2_x_do_cycles (unsigned long cycles) +{ + if (cputrace.cyclecounter > cycles) { + cputrace.cyclecounter -= cycles; + return; + } + cycles -= cputrace.cyclecounter; + cputrace.cyclecounter = 0; + check_trace (); + x_do_cycles = x2_do_cycles; + if (cycles > 0) + x_do_cycles (cycles); +} +static void cputracefunc2_x_do_cycles_pre (unsigned long cycles) +{ + if (cputrace.cyclecounter_pre == -1) { + cputrace.cyclecounter_pre = 0; + check_trace (); + check_trace2 (); + return; + } + if (cputrace.cyclecounter_pre > cycles) { + cputrace.cyclecounter_pre -= cycles; + return; + } + cycles -= cputrace.cyclecounter_pre; + cputrace.cyclecounter_pre = 0; + check_trace (); + if (cycles > 0) + x_do_cycles (cycles); +} +static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v) +{ + if (cputrace.cyclecounter_post > cycles) { + cputrace.cyclecounter_post -= cycles; + return; + } + cycles -= cputrace.cyclecounter_post; + cputrace.cyclecounter_post = 0; + check_trace (); + if (cycles > 0) + x_do_cycles (cycles); +} + +static void do_cycles_post (unsigned long cycles, uae_u32 v) +{ + do_cycles (cycles); +} +static void do_cycles_ce_post (unsigned long cycles, uae_u32 v) +{ + do_cycles_ce (cycles); +} + +// indirect memory access functions static void set_x_funcs (void) { if (currprefs.mmu_model) { x_prefetch = get_iword_mmu; + x_prefetch_long = get_ilong_mmu; + x_get_ilong = get_ilong_mmu; + x_get_iword = get_iword_mmu; + x_get_ibyte = get_ibyte_mmu; x_next_iword = next_iword_mmu; x_next_ilong = next_ilong_mmu; x_put_long = put_long_mmu; @@ -160,8 +630,68 @@ static void set_x_funcs (void) x_get_long = get_long_mmu; x_get_word = get_word_mmu; x_get_byte = get_byte_mmu; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; + } else if (currprefs.cpu_model < 68020) { + if (currprefs.cpu_cycle_exact) { + x_prefetch = get_word_ce000_prefetch; + x_prefetch_long = NULL; + x_get_ilong = NULL; + x_get_iword = get_wordi_ce000; + x_get_ibyte = NULL; + x_next_iword = NULL; + x_next_ilong = NULL; + x_put_long = put_long_ce000; + x_put_word = put_word_ce000; + x_put_byte = put_byte_ce000; + x_get_long = get_long_ce000; + x_get_word = get_word_ce000; + x_get_byte = get_byte_ce000; + x_do_cycles = do_cycles_ce; + x_do_cycles_pre = do_cycles_ce; + x_do_cycles_post = do_cycles_ce_post; + } else if (currprefs.cpu_compatible) { + x_prefetch = get_word_prefetch; + x_prefetch_long = get_long_prefetch; + x_get_ilong = NULL; + x_get_iword = get_iword; + x_get_ibyte = get_ibyte; + x_next_iword = NULL; + x_next_ilong = NULL; + 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; + } } else if (!currprefs.cpu_cycle_exact) { - x_prefetch = get_iword; + 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; @@ -170,18 +700,15 @@ static void set_x_funcs (void) x_get_long = get_long; x_get_word = get_word; x_get_byte = get_byte; - } else if (currprefs.cpu_model < 68020) { - x_prefetch = NULL; - x_next_iword = NULL; - x_next_ilong = NULL; - x_put_long = put_long_ce; - x_put_word = put_word_ce; - x_put_byte = put_byte_ce; - x_get_long = get_long_ce; - x_get_word = get_word_ce; - x_get_byte = get_byte_ce; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; } else if (currprefs.cpu_model == 68020) { x_prefetch = get_word_ce020_prefetch; + x_prefetch_long = NULL; + x_get_ilong = get_long_ce020_prefetch; + x_get_iword = get_word_ce020_prefetch; + x_get_ibyte = NULL; x_next_iword = next_iword_020ce; x_next_ilong = next_ilong_020ce; x_put_long = put_long_ce020; @@ -190,8 +717,15 @@ static void set_x_funcs (void) x_get_long = get_long_ce020; x_get_word = get_word_ce020; x_get_byte = get_byte_ce020; + x_do_cycles = do_cycles_ce; + x_do_cycles_pre = do_cycles_ce; + x_do_cycles_post = do_cycles_ce_post; } else { x_prefetch = get_word_ce030_prefetch; + x_prefetch_long = NULL; + x_get_ilong = get_long_ce030_prefetch; + x_get_iword = get_word_ce030_prefetch; + x_get_ibyte = NULL; x_next_iword = next_iword_030ce; x_next_ilong = next_ilong_030ce; x_put_long = put_long_ce030; @@ -200,16 +734,102 @@ static void set_x_funcs (void) x_get_long = get_long_ce030; x_get_word = get_word_ce030; x_get_byte = get_byte_ce030; + x_do_cycles = do_cycles_ce; + x_do_cycles_pre = do_cycles_ce; + x_do_cycles_post = do_cycles_ce_post; + } + x2_prefetch = x_prefetch; + x2_prefetch_long = x_prefetch_long; + x2_get_ilong = x_get_ilong; + x2_get_iword = x_get_iword; + x2_get_ibyte = x_get_ibyte; + x2_next_iword = x_next_iword; + x2_next_ilong = x_next_ilong; + x2_put_long = x_put_long; + x2_put_word = x_put_word; + x2_put_byte = x_put_byte; + x2_get_long = x_get_long; + x2_get_word = x_get_word; + x2_get_byte = x_get_byte; + x2_do_cycles = x_do_cycles; + x2_do_cycles_pre = x_do_cycles_pre; + x2_do_cycles_post = x_do_cycles_post; + + if (cpu_tracer > 0) { + x_prefetch = cputracefunc_x_prefetch; + x_prefetch_long = cputracefunc_x_prefetch_long; + x_get_ilong = cputracefunc_x_get_ilong; + x_get_iword = cputracefunc_x_get_iword; + x_get_ibyte = cputracefunc_x_get_ibyte; + x_next_iword = cputracefunc_x_next_iword; + x_next_ilong = cputracefunc_x_next_ilong; + x_put_long = cputracefunc_x_put_long; + x_put_word = cputracefunc_x_put_word; + x_put_byte = cputracefunc_x_put_byte; + x_get_long = cputracefunc_x_get_long; + x_get_word = cputracefunc_x_get_word; + x_get_byte = cputracefunc_x_get_byte; + x_do_cycles = cputracefunc_x_do_cycles; + x_do_cycles_pre = cputracefunc_x_do_cycles_pre; + x_do_cycles_post = cputracefunc_x_do_cycles_post; + } else if (cpu_tracer < 0) { + if (!check_trace ()) { + x_prefetch = cputracefunc2_x_prefetch; + x_prefetch_long = cputracefunc2_x_prefetch_long; + x_get_ilong = cputracefunc2_x_get_ilong; + x_get_iword = cputracefunc2_x_get_iword; + x_get_ibyte = cputracefunc2_x_get_ibyte; + x_next_iword = cputracefunc2_x_next_iword; + x_next_ilong = cputracefunc2_x_next_ilong; + x_put_long = cputracefunc2_x_put_long; + x_put_word = cputracefunc2_x_put_word; + x_put_byte = cputracefunc2_x_put_byte; + x_get_long = cputracefunc2_x_get_long; + x_get_word = cputracefunc2_x_get_word; + x_get_byte = cputracefunc2_x_get_byte; + x_do_cycles = cputracefunc2_x_do_cycles; + x_do_cycles_pre = cputracefunc2_x_do_cycles_pre; + x_do_cycles_post = cputracefunc2_x_do_cycles_post; + } } +} +bool can_cpu_tracer (void) +{ + return (currprefs.cpu_model == 68000) && currprefs.cpu_cycle_exact; +} + +bool is_cpu_tracer (void) +{ + return cpu_tracer > 0; +} +bool set_cpu_tracer (bool state) +{ + if (cpu_tracer < 0) + return false; + int old = cpu_tracer; + if (input_record) + state = true; + cpu_tracer = 0; + if (state && can_cpu_tracer ()) { + cpu_tracer = 1; + set_x_funcs (); + if (old != cpu_tracer) + write_log (L"CPU tracer enabled\n"); + } + if (old > 0 && state == false) { + set_x_funcs (); + write_log (L"CPU tracer disabled\n"); + } + return is_cpu_tracer (); } static void set_cpu_caches (void) { int i; - for (i = 0; i < CPU_PIPELINE_MAX; i++) - regs.prefetch020addr[i] = 0xffffffff; + regs.prefetch020addr = 0xffffffff; + regs.cacheholdingaddr020 = 0xffffffff; #ifdef JIT if (currprefs.cachesize) { @@ -275,8 +895,6 @@ STATIC_INLINE void count_instr (unsigned int opcode) { } -static unsigned long REGPARAM3 op_illg_1 (uae_u32 opcode) REGPARAM; - static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode) { op_illg (opcode); @@ -406,13 +1024,18 @@ static void build_cpufunctbl (void) } } -void fill_prefetch_slow (void) +void fill_prefetch (void) { if (currprefs.mmu_model) return; regs.ir = x_get_word (m68k_getpc ()); regs.irc = x_get_word (m68k_getpc () + 2); } +static void fill_prefetch_quick (void) +{ + regs.ir = get_word (m68k_getpc ()); + regs.irc = get_word (m68k_getpc () + 2); +} unsigned long cycles_mask, cycles_val; @@ -474,7 +1097,7 @@ void check_prefs_changed_cpu (void) prefs_changed_cpu (); if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible) - fill_prefetch_slow (); + fill_prefetch_quick (); build_cpufunctbl (); changed = 1; } @@ -567,8 +1190,6 @@ void init_m68k (void) struct regstruct regs, mmu_backup_regs; struct flag_struct regflags; -static struct regstruct regs_backup[16]; -static int backup_pointer = 0; static long int m68kpc_offset; #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) @@ -940,6 +1561,7 @@ uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, i break; default: /* Panic? */ + write_log (L"get_bitfield() can't happen %d\n", (offset + width + 7) >> 3); res = 0; break; } @@ -970,6 +1592,9 @@ void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 put_long (dst, bdata[0] | (val >> (offset - 32))); put_byte (dst + 4, bdata[1] | (val << (40 - offset))); break; + default: + write_log (L"put_bitfield() can't happen %d\n", (offset + 7) >> 3); + break; } } @@ -1013,6 +1638,7 @@ uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, break; default: /* Panic? */ + write_log (L"x_get_bitfield() can't happen %d\n", (offset + width + 7) >> 3); res = 0; break; } @@ -1040,6 +1666,9 @@ void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s x_put_long (dst, bdata[0] | (val >> (offset - 32))); x_put_byte (dst + 4, bdata[1] | (val << (40 - offset))); break; + default: + write_log (L"x_put_bitfield() can't happen %d\n", (offset + 7) >> 3); + break; } } @@ -1129,36 +1758,11 @@ uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, uae_u32 dp) } else { v = base + (uae_s32)((uae_s8)dp) + regd; } - if (cycles) - do_cycles_ce020 (cycles); + if (cycles && currprefs.cpu_cycle_exact) + x_do_cycles (cycles * cpucycleunit); return v; } - -uae_u32 REGPARAM3 get_disp_ea_000 (uae_u32 base, uae_u32 dp) REGPARAM -{ - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; -#if 1 - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - return base + (uae_s8)dp + regd; -#else - /* Branch-free code... benchmark this again now that - * things are no longer inline. */ - uae_s32 regd16; - uae_u32 mask; - mask = ((dp & 0x800) >> 11) - 1; - regd16 = (uae_s32)(uae_s16)regd; - regd16 &= mask; - mask = ~mask; - base += (uae_s8)dp; - regd &= mask; - regd |= regd16; - return base + regd; -#endif -} - STATIC_INLINE int in_rom (uaecptr pc) { return (munge24 (pc) & 0xFFF80000) == 0xF80000; @@ -1184,7 +1788,7 @@ void REGPARAM2 MakeFromSR (void) int olds = regs.s; if (currprefs.cpu_cycle_exact && currprefs.cpu_model >= 68020) { - do_cycles_ce (6 * CYCLE_UNIT); + x_do_cycles (6 * CYCLE_UNIT); regs.ce020memcycles = 0; } @@ -1374,7 +1978,7 @@ Interrupt cycle diagram: */ -static void Exception_ce000 (int nr, uaecptr oldpc) +static void Exception_ce000 (int nr) { uae_u32 currpc = m68k_getpc (), newpc; int sv = regs.s; @@ -1390,7 +1994,7 @@ static void Exception_ce000 (int nr, uaecptr oldpc) interrupt = nr >= 24 && nr < 24 + 8; if (start) - do_cycles_ce000 (start); + x_do_cycles (start * cpucycleunit); exception_debug (nr); MakeSR (); @@ -1405,40 +2009,40 @@ static void Exception_ce000 (int nr, uaecptr oldpc) mode |= last_writeaccess_for_exception_3 ? 0 : 16; m68k_areg (regs, 7) -= 14; /* fixme: bit3=I/N */ - put_word_ce (m68k_areg (regs, 7) + 12, last_addr_for_exception_3); - put_word_ce (m68k_areg (regs, 7) + 8, regs.sr); - put_word_ce (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16); - put_word_ce (m68k_areg (regs, 7) + 6, last_op_for_exception_3); - put_word_ce (m68k_areg (regs, 7) + 4, last_fault_for_exception_3); - put_word_ce (m68k_areg (regs, 7) + 0, mode); - put_word_ce (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16); - do_cycles_ce000 (2); - write_log (L"Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (4 * nr)); + x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3); + x_put_word (m68k_areg (regs, 7) + 8, regs.sr); + x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16); + x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3); + x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3); + x_put_word (m68k_areg (regs, 7) + 0, mode); + x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16); + x_do_cycles (2 * cpucycleunit); + write_log (L"Exception %d (%x) at %x -> %x!\n", nr, last_addr_for_exception_3, currpc, get_long (4 * nr)); goto kludge_me_do; } m68k_areg (regs, 7) -= 6; - put_word_ce (m68k_areg (regs, 7) + 4, currpc); // write low address + x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address if (interrupt) { // fetch interrupt vector number - nr = get_byte_ce (0x00fffff1 | ((nr - 24) << 1)); - do_cycles_ce000 (4); + nr = x_get_byte (0x00fffff1 | ((nr - 24) << 1)); + x_do_cycles (4 * cpucycleunit); } - put_word_ce (m68k_areg (regs, 7) + 0, regs.sr); // write SR - put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address + x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR + x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address kludge_me_do: - newpc = get_word_ce (4 * nr) << 16; // read high address - newpc |= get_word_ce (4 * nr + 2); // read low address + newpc = x_get_word (4 * nr) << 16; // read high address + newpc |= x_get_word (4 * nr + 2); // read low address if (newpc & 1) { if (nr == 2 || nr == 3) uae_reset (1); /* there is nothing else we can do.. */ else - exception3 (regs.ir, m68k_getpc (), newpc); + exception3 (regs.ir, newpc); return; } m68k_setpc (newpc); - regs.ir = get_word_ce (m68k_getpc ()); // prefetch 1 - do_cycles_ce000 (2); - regs.irc = get_word_ce (m68k_getpc () + 2); // prefetch 2 + regs.ir = x_get_word (m68k_getpc ()); // prefetch 1 + x_do_cycles (2 * cpucycleunit); + regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2 #ifdef JIT set_special (SPCFLAG_END_COMPILE); #endif @@ -1446,9 +2050,9 @@ kludge_me_do: } #endif -static void Exception_mmu (int nr, uaecptr oldpc) +static void Exception_mmu (int nr) { - uae_u32 currpc = m68k_getpc (), newpc; + uae_u32 newpc; int sv = regs.s; int i; @@ -1494,7 +2098,7 @@ static void Exception_mmu (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), 0x7000 + nr * 4); m68k_areg (regs, 7) -= 4; - put_long_mmu (m68k_areg (regs, 7), oldpc); + put_long_mmu (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), regs.sr); goto kludge_me_do; @@ -1521,12 +2125,11 @@ static void Exception_mmu (int nr, uaecptr oldpc) put_word_mmu (m68k_areg (regs, 7), ssw); m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), 0xb000 + nr * 4); - write_log (L"Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (regs.vbr + 4*nr)); } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { m68k_areg (regs, 7) -= 4; - put_long_mmu (m68k_areg (regs, 7), oldpc); + put_long_mmu (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), 0x2000 + nr * 4); @@ -1535,7 +2138,7 @@ static void Exception_mmu (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), nr * 4); m68k_areg (regs, 7) -= 4; - put_long_mmu (m68k_areg (regs, 7), currpc); + put_long_mmu (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), regs.sr); regs.sr |= (1 << 13); @@ -1551,7 +2154,7 @@ static void Exception_mmu (int nr, uaecptr oldpc) } m68k_areg (regs, 7) -= 4; - put_long_mmu (m68k_areg (regs, 7), currpc); + put_long_mmu (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; put_word_mmu (m68k_areg (regs, 7), regs.sr); kludge_me_do: @@ -1560,20 +2163,20 @@ kludge_me_do: if (nr == 2 || nr == 3) uae_reset (1); /* there is nothing else we can do.. */ else - exception3 (regs.ir, m68k_getpc (), newpc); + exception3 (regs.ir, newpc); return; } m68k_setpc (newpc); #ifdef JIT set_special (SPCFLAG_END_COMPILE); #endif - fill_prefetch_slow (); + fill_prefetch (); exception_trace (nr); } -static void Exception_normal (int nr, uaecptr oldpc) +static void Exception_normal (int nr) { - uae_u32 currpc = m68k_getpc (), newpc; + uae_u32 currpc, newpc; int sv = regs.s; if (nr >= 24 && nr < 24 + 8 && currprefs.cpu_model <= 68010) @@ -1593,13 +2196,13 @@ static void Exception_normal (int nr, uaecptr oldpc) mmu_set_super (regs.s != 0); } if (currprefs.cpu_model > 68000) { + currpc = regs.instruction_pc; if (nr == 2 || nr == 3) { int i; if (currprefs.cpu_model >= 68040) { if (nr == 2) { - // bus error if (currprefs.mmu_model) { - + // 68040 mmu bus error for (i = 0 ; i < 7 ; i++) { m68k_areg (regs, 7) -= 4; x_put_long (m68k_areg (regs, 7), 0); @@ -1625,7 +2228,7 @@ static void Exception_normal (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4); m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), oldpc); + x_put_long (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), regs.sr); newpc = x_get_long (regs.vbr + 4 * nr); @@ -1633,7 +2236,7 @@ static void Exception_normal (int nr, uaecptr oldpc) if (nr == 2 || nr == 3) uae_reset (1); /* there is nothing else we can do.. */ else - exception3 (regs.ir, m68k_getpc (), newpc); + exception3 (regs.ir, newpc); return; } m68k_setpc (newpc); @@ -1645,6 +2248,7 @@ static void Exception_normal (int nr, uaecptr oldpc) } else { + // 68040 bus error (not really, some garbage?) for (i = 0 ; i < 18 ; i++) { m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0); @@ -1664,7 +2268,7 @@ static void Exception_normal (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4); m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), oldpc); + x_put_long (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), regs.sr); goto kludge_me_do; @@ -1678,7 +2282,7 @@ static void Exception_normal (int nr, uaecptr oldpc) x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4); } } else { - // address error + // 68020 address error uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40; ssw |= 0x20; @@ -1699,10 +2303,10 @@ static void Exception_normal (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0xb000 + nr * 4); } - write_log (L"Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr)); + write_log (L"Exception %d (%x) at %x -> %x!\n", nr, regs.instruction_pc, currpc, x_get_long (regs.vbr + 4*nr)); } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), oldpc); + x_put_long (m68k_areg (regs, 7), regs.instruction_pc); m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4); } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */ @@ -1721,18 +2325,22 @@ static void Exception_normal (int nr, uaecptr oldpc) m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), nr * 4); } - } else if (nr == 2 || nr == 3) { - uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); - mode |= last_writeaccess_for_exception_3 ? 0 : 16; - m68k_areg (regs, 7) -= 14; - /* fixme: bit3=I/N */ - x_put_word (m68k_areg (regs, 7) + 0, mode); - x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3); - x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3); - x_put_word (m68k_areg (regs, 7) + 8, regs.sr); - x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3); - write_log (L"Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr)); - goto kludge_me_do; + } else { + currpc = m68k_getpc (); + if (nr == 2 || nr == 3) { + // 68000 address error + uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); + mode |= last_writeaccess_for_exception_3 ? 0 : 16; + m68k_areg (regs, 7) -= 14; + /* fixme: bit3=I/N */ + x_put_word (m68k_areg (regs, 7) + 0, mode); + x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3); + x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3); + x_put_word (m68k_areg (regs, 7) + 8, regs.sr); + x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3); + write_log (L"Exception %d (%x) at %x -> %x!\n", nr, last_fault_for_exception_3, currpc, x_get_long (regs.vbr + 4*nr)); + goto kludge_me_do; + } } m68k_areg (regs, 7) -= 4; x_put_long (m68k_areg (regs, 7), currpc); @@ -1744,28 +2352,35 @@ kludge_me_do: if (nr == 2 || nr == 3) uae_reset (1); /* there is nothing else we can do.. */ else - exception3 (regs.ir, m68k_getpc (), newpc); + exception3 (regs.ir, newpc); return; } m68k_setpc (newpc); #ifdef JIT set_special (SPCFLAG_END_COMPILE); #endif - fill_prefetch_slow (); + fill_prefetch (); exception_trace (nr); } -void REGPARAM2 Exception (int nr, uaecptr oldpc) +void REGPARAM2 Exception (int nr) { + regs.exception = nr; + if (cpu_tracer) { + cputrace.state = nr; + } + + if (currprefs.cachesize) + regs.instruction_pc = m68k_getpc (); #ifdef CPUEMU_12 if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) - Exception_ce000 (nr, oldpc); + Exception_ce000 (nr); else #endif if (currprefs.mmu_model) - Exception_mmu (nr, oldpc); + Exception_mmu (nr); else - Exception_normal (nr, oldpc); + Exception_normal (nr); if (debug_illegal && !in_rom (M68K_GETPC)) { int v = nr; @@ -1774,6 +2389,10 @@ void REGPARAM2 Exception (int nr, uaecptr oldpc) activate_debugger (); } } + regs.exception = 0; + if (cpu_tracer) { + cputrace.state = 0; + } } STATIC_INLINE void do_interrupt (int nr) @@ -1781,11 +2400,18 @@ STATIC_INLINE void do_interrupt (int nr) if (debug_dma) record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos); + if (inputrecord_debug & 2) { + if (input_record > 0) + inprec_recorddebug_cpu (2); + else if (input_play > 0) + inprec_playdebug_cpu (2); + } + regs.stopped = 0; unset_special (SPCFLAG_STOP); assert (nr < 8 && nr >= 0); - Exception (nr + 24, 0); + Exception (nr + 24); regs.intmask = nr; doint (); @@ -1987,11 +2613,11 @@ STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae return 0; } -void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) +void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra) { #if defined (uae_s64) if (src == 0) { - Exception (5, oldpc); + Exception (5); return; } if (extra & 0x800) { @@ -2046,7 +2672,7 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) } #else if (src == 0) { - Exception (5, oldpc); + Exception (5); return; } if (extra & 0x800) { @@ -2220,7 +2846,7 @@ void m68k_reset (int hardreset) regs.spcflags = 0; regs.ipl = regs.ipl_pin = 0; #ifdef SAVESTATE - if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) { + if (isrestore ()) { m68k_setpc (regs.pc); SET_XFLG ((regs.sr >> 4) & 1); SET_NFLG ((regs.sr >> 3) & 1); @@ -2295,7 +2921,7 @@ void m68k_reset (int hardreset) if (kickstart_rom) regs.pcr |= 2; /* disable FPU */ } - fill_prefetch_slow (); + fill_prefetch_quick (); } unsigned long REGPARAM2 op_illg (uae_u32 opcode) @@ -2308,7 +2934,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) if (cloanto_rom && (opcode & 0xF100) == 0x7100) { m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF); m68k_incpc (2); - fill_prefetch_slow (); + fill_prefetch (); return 4; } @@ -2324,7 +2950,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) uae_u16 arg = get_iword (2); m68k_incpc (4); ersatz_perform (arg); - fill_prefetch_slow (); + fill_prefetch (); return 4; } else if (inrt) { /* User-mode STOP replacement */ @@ -2337,7 +2963,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) /* Calltrap. */ m68k_incpc (2); m68k_handle_trap (opcode & 0xFFF); - fill_prefetch_slow (); + fill_prefetch (); return 4; } #endif @@ -2347,7 +2973,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) write_log (L"B-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p); warned++; } - Exception (0xB, 0); + Exception (0xB); //activate_debugger (); return 4; } @@ -2356,7 +2982,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) write_log (L"A-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p); warned++; } - Exception (0xA, 0); + Exception (0xA); //activate_debugger(); return 4; } @@ -2366,7 +2992,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 opcode) //activate_debugger(); } - Exception (4, 0); + Exception (4); return 4; } @@ -2563,7 +3189,7 @@ static void do_trace (void) /* probably never used so why bother */ /* We can afford this to be inefficient... */ m68k_setpc (m68k_getpc ()); - fill_prefetch_slow (); + fill_prefetch (); opcode = x_get_word (regs.pc); if (opcode == 0x4e73 /* RTE */ || opcode == 0x4e74 /* RTD */ @@ -2592,25 +3218,16 @@ static void do_trace (void) // handle interrupt delay (few cycles) -STATIC_INLINE int time_for_interrupt (void) +STATIC_INLINE bool time_for_interrupt (void) { - if (regs.ipl > regs.intmask || regs.ipl == 7) { -#if 0 - if (regs.ipl == 3 && current_hpos () < 11) { - write_log (L"%d\n", current_hpos ()); - activate_debugger (); - } -#endif - return 1; - } - return 0; + return regs.ipl > regs.intmask || regs.ipl == 7; } void doint (void) { if (currprefs.cpu_cycle_exact) { regs.ipl_pin = intlev (); - set_special (SPCFLAG_INT); + unset_special (SPCFLAG_INT); return; } if (currprefs.cpu_compatible) @@ -2623,6 +3240,7 @@ void doint (void) STATIC_INLINE int do_specialties (int cycles) { + regs.instruction_pc = m68k_getpc (); #ifdef ACTION_REPLAY #ifdef ACTION_REPLAY_HRTMON if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) { @@ -2673,21 +3291,21 @@ STATIC_INLINE int do_specialties (int cycles) cycles = 0; } else c = 4; - do_cycles (c * CYCLE_UNIT); + x_do_cycles (c * CYCLE_UNIT); if (regs.spcflags & SPCFLAG_COPPER) do_copper (); } if (regs.spcflags & SPCFLAG_DOTRACE) - Exception (9, last_trace_ad); + Exception (9); if (regs.spcflags & SPCFLAG_TRAP) { unset_special (SPCFLAG_TRAP); - Exception (3, 0); + Exception (3); } while (regs.spcflags & SPCFLAG_STOP) { - do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT); + x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT); if (regs.spcflags & SPCFLAG_COPPER) do_copper (); @@ -2900,21 +3518,72 @@ static void m68k_run_1_ce (void) { struct regstruct *r = ®s; - ipl_fetch (); + if (cpu_tracer < 0) { + memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32)); + r->ir = cputrace.ir; + r->irc = cputrace.irc; + r->sr = cputrace.sr; + r->usp = cputrace.usp; + r->isp = cputrace.isp; + r->intmask = cputrace.intmask; + r->stopped = cputrace.stopped; + m68k_setpc (cputrace.pc); + if (cputrace.state > 1) + Exception (cputrace.state); + else if (cputrace.state == 1) + (*cpufunctbl[cputrace.opcode])(cputrace.opcode); + if (regs.stopped) + set_special (SPCFLAG_STOP); + set_cpu_tracer (false); + goto cont; + } + + set_cpu_tracer (false); + for (;;) { uae_u32 opcode = r->ir; #if DEBUG_CD32CDTVIO out_cd32io (m68k_getpc ()); #endif + if (cpu_tracer) { + memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32)); + cputrace.opcode = opcode; + cputrace.ir = r->ir; + cputrace.irc = r->irc; + cputrace.sr = r->sr; + cputrace.usp = r->usp; + cputrace.isp = r->isp; + cputrace.intmask = r->intmask; + cputrace.stopped = r->stopped; + cputrace.state = 1; + cputrace.pc = m68k_getpc (); + cputrace.memoryoffset = 0; + cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0; + cputrace.readcounter = cputrace.writecounter = 0; + } + + if (inputrecord_debug & 4) { + if (input_record > 0) + inprec_recorddebug_cpu (1); + else if (input_play > 0) + inprec_playdebug_cpu (1); + } + (*cpufunctbl[opcode])(opcode); - if (r->spcflags) { + if (cpu_tracer) { + cputrace.state = 0; + } +cont: + if (r->spcflags || time_for_interrupt ()) { if (do_specialties (0)) return; } + if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68000) return; } } + #endif #ifdef JIT /* Completely different run_2 replacement */ @@ -2933,7 +3602,6 @@ void exec_nostats (void) for (;;) { uae_u16 opcode = get_iword (0); - cpu_cycles = (*cpufunctbl[opcode])(opcode); cpu_cycles &= cycles_mask; @@ -3014,7 +3682,7 @@ static void m68k_run_2 (void) #else -static void opcodedebug (uae_u32 pc, uae_u16 opcode) +static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full) { struct mnemolookup *lookup; struct instr *dp; @@ -3034,10 +3702,12 @@ static void opcodedebug (uae_u32 pc, uae_u16 opcode) } if (!fault) { TCHAR buf[100]; - write_log (L"mmufixup=%d %04x %04x\n", mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw); + if (full) + write_log (L"mmufixup=%d %04x %04x\n", mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw); m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0); write_log (L"%s\n", buf); - m68k_dumpstate (stdout, NULL); + if (full) + m68k_dumpstate (stdout, NULL); } } @@ -3049,7 +3719,7 @@ static void m68k_run_mmu040 (void) retry: TRY (prb) { for (;;) { - pc = regs.fault_pc = m68k_getpc (); + pc = regs.instruction_pc = regs.instruction_pc = m68k_getpc (); #if 0 static int done; if (pc == 0x16AF94) { @@ -3075,7 +3745,8 @@ retry: } } #endif - opcode = x_prefetch (0); + + opcode = get_iword_mmu (0); count_instr (opcode); do_cycles (cpu_cycles); cpu_cycles = (*cpufunctbl[opcode])(opcode); @@ -3089,12 +3760,13 @@ retry: } CATCH (prb) { if (currprefs.mmu_model == 68060) { - regs.fault_pc = pc; + regs.instruction_pc = pc; if (mmufixup[1].reg >= 0) { m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value; mmufixup[1].reg = -1; } } else { +#if 0 if (regs.wb3_status & 0x80) { // movem to memory? if ((opcode & 0xff80) == 0x4880) { @@ -3102,9 +3774,10 @@ retry: //write_log (L"MMU_SSW_CM\n"); } } +#endif } - //opcodedebug (regs.fault_pc, opcode); + //opcodedebug (pc, opcode, false); if (mmufixup[0].reg >= 0) { m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; @@ -3112,7 +3785,7 @@ retry: } //activate_debugger (); TRY (prb2) { - Exception (prb, regs.fault_pc); + Exception (prb); } CATCH (prb2) { write_log (L"MMU: double bus error, rebooting..\n"); regs.tcr = 0; @@ -3129,21 +3802,71 @@ retry: /* "cycle exact" 68020/030 */ #define MAX68020CYCLES 4 + static void m68k_run_2ce (void) { struct regstruct *r = ®s; int tmpcycles = MAX68020CYCLES; + if (cpu_tracer < 0) { + memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32)); + r->ir = cputrace.ir; + r->irc = cputrace.irc; + r->sr = cputrace.sr; + r->usp = cputrace.usp; + r->isp = cputrace.isp; + r->intmask = cputrace.intmask; + r->stopped = cputrace.stopped; + m68k_setpc (cputrace.pc); + if (cputrace.state > 1) + Exception (cputrace.state); + else if (cputrace.state == 1) + (*cpufunctbl[cputrace.opcode])(cputrace.opcode); + if (regs.stopped) + set_special (SPCFLAG_STOP); + set_cpu_tracer (false); + goto cont; + } + + set_cpu_tracer (false); ipl_fetch (); + for (;;) { + r->instruction_pc = m68k_getpc (); uae_u32 opcode = x_prefetch (0); + + if (cpu_tracer) { + memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32)); + cputrace.opcode = opcode; + cputrace.ir = r->ir; + cputrace.irc = r->irc; + cputrace.sr = r->sr; + cputrace.usp = r->usp; + cputrace.isp = r->isp; + cputrace.intmask = r->intmask; + cputrace.stopped = r->stopped; + cputrace.state = 1; + cputrace.pc = m68k_getpc (); + cputrace.memoryoffset = 0; + cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0; + cputrace.readcounter = cputrace.writecounter = 0; + } + + if (inputrecord_debug & 4) { + if (input_record > 0) + inprec_recorddebug_cpu (1); + else if (input_play > 0) + inprec_playdebug_cpu (1); + } + (*cpufunctbl[opcode])(opcode); if (r->ce020memcycles > 0) { tmpcycles = CYCLE_UNIT * MAX68020CYCLES; do_cycles_ce (r->ce020memcycles); r->ce020memcycles = 0; } - if (r->spcflags) { +cont: + if (r->spcflags || time_for_interrupt ()) { if (do_specialties (0)) return; } @@ -3163,7 +3886,7 @@ static void m68k_run_2p (void) struct regstruct *r = ®s; prefetch_pc = m68k_getpc (); - prefetch = get_longi (prefetch_pc); + prefetch = x_get_long (prefetch_pc); for (;;) { uae_u32 opcode; uae_u32 pc = m68k_getpc (); @@ -3172,19 +3895,23 @@ static void m68k_run_2p (void) out_cd32io (m68k_getpc ()); #endif - do_cycles (cpu_cycles); + x_do_cycles (cpu_cycles); - if (pc == prefetch_pc) + if (pc == prefetch_pc) { opcode = prefetch >> 16; - else if (pc == prefetch_pc + 2) + regs.instruction_pc = pc; + } else if (pc == prefetch_pc + 2) { + regs.instruction_pc = pc + 2; opcode = prefetch & 0xffff; - else - opcode = get_wordi (pc); + } else { + regs.instruction_pc = pc; + opcode = x_get_word (pc); + } count_instr (opcode); prefetch_pc = m68k_getpc () + 2; - prefetch = get_longi (prefetch_pc); + prefetch = x_get_long (prefetch_pc); cpu_cycles = (*cpufunctbl[opcode])(opcode); cpu_cycles &= cycles_mask; cpu_cycles |= cycles_val; @@ -3251,12 +3978,13 @@ static void exception2_handle (uaecptr addr, uaecptr fault) last_fault_for_exception_3 = fault; last_writeaccess_for_exception_3 = 0; last_instructionaccess_for_exception_3 = 0; - Exception (2, m68k_getpc ()); + Exception (2); } void m68k_go (int may_quit) { int hardboot = 1; + int startup = 1; if (in_m68k_go || !may_quit) { write_log (L"Bug! m68k_go is not reentrant.\n"); @@ -3265,31 +3993,45 @@ void m68k_go (int may_quit) reset_frame_rate_hack (); update_68k_cycles (); + start_cycles = 0; + + set_cpu_tracer (false); in_m68k_go++; for (;;) { void (*run_func)(void); + + cputrace.state = -1; + + if (currprefs.inprecfile[0] && input_play) { + inprec_open (currprefs.inprecfile, NULL); + changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0; + quit_program = 2; + } + if (input_play || input_record) + inprec_startup (); + if (quit_program > 0) { int hardreset = (quit_program == 3 ? 1 : 0) | hardboot; if (quit_program == 1) break; + int restored = 0; + hsync_counter = 0; + vsync_counter = 0; quit_program = 0; hardboot = 0; - if (currprefs.inprecfile[0] && currprefs.inprecmode < 0) { - inprec_open (currprefs.inprecfile, currprefs.inprecmode); - changed_prefs.inprecmode = currprefs.inprecmode = 0; - changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0; - } - #ifdef SAVESTATE + if (savestate_state == STATE_DORESTORE) + savestate_state = STATE_RESTORE; if (savestate_state == STATE_RESTORE) restore_state (savestate_fname); else if (savestate_state == STATE_REWIND) savestate_rewind (); #endif - customreset (hardreset); + set_cycles (start_cycles); + custom_reset (hardreset); m68k_reset (hardreset); if (hardreset) { memory_hardreset (); @@ -3297,28 +4039,41 @@ void m68k_go (int may_quit) } #ifdef SAVESTATE /* We may have been restoring state, but we're done now. */ - if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) { - map_overlay (1); - fill_prefetch_slow (); /* compatibility with old state saves */ + if (isrestore ()) { + if (debug_dma) { + record_dma_reset (); + record_dma_reset (); + } + savestate_restore_finish (); memory_map_dump (); + startup = 1; + restored = 1; } - savestate_restore_finish (); #endif - if (currprefs.inprecfile[0] && currprefs.inprecmode > 0) { - inprec_open (currprefs.inprecfile, currprefs.inprecmode); - changed_prefs.inprecmode = currprefs.inprecmode = 0; - changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0; - } - - fill_prefetch_slow (); if (currprefs.produce_sound == 0) eventtab[ev_audio].active = 0; - handle_active_events (); - if (regs.spcflags) - do_specialties (0); m68k_setpc (regs.pc); + check_prefs_changed_audio (); + + if (!restored || hsync_counter == 0) + savestate_check (); + if (input_record == INPREC_RECORD_START) + input_record = INPREC_RECORD_NORMAL; + } else { + if (input_record == INPREC_RECORD_START) { + input_record = INPREC_RECORD_NORMAL; + savestate_init (); + hsync_counter = 0; + vsync_counter = 0; + savestate_check (); + } } + if (changed_prefs.inprecfile[0] && input_record) + inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL); + + set_cpu_tracer (false); + #ifdef DEBUGGER if (debugging) debug (); @@ -3347,8 +4102,11 @@ void m68k_go (int may_quit) regs.spcflags |= of & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); } #endif - set_x_funcs (); - if (mmu_enabled && !currprefs.cachesize) { + set_x_funcs (); + if (startup) + custom_prepare (); + startup = 0; + if (mmu_enabled && !currprefs.cachesize) { run_func = m68k_run_mmu; } else { run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000 ? m68k_run_1_ce : @@ -3901,6 +4659,37 @@ uae_u8 *restore_cpu (uae_u8 *src) if (khz > 0 && khz < 800000) currprefs.m68k_speed = changed_prefs.m68k_speed = 0; } + set_cpu_caches (); + if (flags & 0x40000000) { + if (model == 68020) { + for (int i = 0; i < CACHELINES020; i++) { + caches020[i].data = restore_u32 (); + caches020[i].tag = restore_u32 (); + caches020[i].valid = restore_u8 () != 0; + } + 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 (); + } else if (model == 68030) { + for (int i = 0; i < CACHELINES030; i++) { + for (int j = 0; j < 4; j++) { + icaches030[i].data[j] = restore_u32 (); + icaches030[i].valid[j] = restore_u8 () != 0; + } + icaches030[i].tag = restore_u32 (); + } + for (int i = 0; i < CACHELINES030; i++) { + for (int j = 0; j < 4; j++) { + dcaches030[i].data[j] = restore_u32 (); + dcaches030[i].valid[j] = restore_u8 () != 0; + } + dcaches030[i].tag = restore_u32 (); + } + } + } + write_log (L"CPU: %d%s%03d, PC=%08X\n", model / 1000, flags & 1 ? L"EC" : L"", model % 1000, regs.pc); @@ -3911,13 +4700,95 @@ void restore_cpu_finish (void) { init_m68k (); m68k_setpc (regs.pc); - set_cpu_caches (); doint (); + fill_prefetch_quick (); + set_cycles (start_cycles); + events_schedule (); if (regs.stopped) set_special (SPCFLAG_STOP); //activate_debugger (); } +uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr) +{ + uae_u8 *dstbak, *dst; + + if (cputrace.state <= 0) + return NULL; + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = xmalloc (uae_u8, 1000); + + save_u32 (2); + save_u16 (cputrace.opcode); + for (int i = 0; i < 16; i++) + save_u32 (cputrace.regs[i]); + save_u32 (cputrace.pc); + save_u16 (cputrace.irc); + save_u16 (cputrace.ir); + save_u32 (cputrace.usp); + save_u32 (cputrace.isp); + save_u16 (cputrace.sr); + save_u16 (cputrace.intmask); + save_u16 (cputrace.stopped); + save_u16 (cputrace.state); + save_u32 (cputrace.cyclecounter); + save_u32 (cputrace.cyclecounter_pre); + save_u32 (cputrace.cyclecounter_post); + save_u32 (cputrace.readcounter); + save_u32 (cputrace.writecounter); + save_u32 (cputrace.memoryoffset); + write_log (L"CPUT SAVE: PC=%08x %08x %08x %08x %d %d %d\n", + cputrace.pc, cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post, + cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset); + for (int i = 0; i < cputrace.memoryoffset; i++) { + save_u32 (cputrace.ctm[i].addr); + save_u32 (cputrace.ctm[i].data); + save_u32 (cputrace.ctm[i].mode); + write_log (L"CPUT%d: %08x %08x %08x\n", i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode); + } + *len = dst - dstbak; + return dstbak; +} + +uae_u8 *restore_cpu_trace (uae_u8 *src) +{ + cpu_tracer = 0; + cputrace.state = 0; + uae_u32 v = restore_u32 (); + if (v != 0 && v != 2) + return src; + cputrace.opcode = restore_u16 (); + for (int i = 0; i < 16; i++) + cputrace.regs[i] = restore_u32 (); + cputrace.pc = restore_u32 (); + cputrace.irc = restore_u16 (); + cputrace.ir = restore_u16 (); + cputrace.usp = restore_u32 (); + cputrace.isp = restore_u32 (); + cputrace.sr = restore_u16 (); + cputrace.intmask = restore_u16 (); + cputrace.stopped = restore_u16 (); + cputrace.state = restore_u16 (); + cputrace.cyclecounter = restore_u32 (); + cputrace.cyclecounter_pre = restore_u32 (); + cputrace.cyclecounter_post = restore_u32 (); + cputrace.readcounter = restore_u32 (); + cputrace.writecounter = restore_u32 (); + cputrace.memoryoffset = restore_u32 (); + for (int i = 0; i < cputrace.memoryoffset; i++) { + cputrace.ctm[i].addr = restore_u32 (); + cputrace.ctm[i].data = restore_u32 (); + cputrace.ctm[i].mode = restore_u32 (); + } + if (v && cputrace.state) + cpu_tracer = -1; + + return src; +} + uae_u8 *restore_cpu_extra (uae_u8 *src) { restore_u32 (); @@ -3975,7 +4846,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) dstbak = dst = xmalloc (uae_u8, 1000); model = currprefs.cpu_model; save_u32 (model); /* MODEL */ - save_u32 (0x80000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */ + save_u32 (0x80000000 | 0x40000000 | (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 */ @@ -4025,6 +4896,33 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) } save_u32 (khz); // clock rate in KHz: -1 = fastest possible save_u32 (0); // spare + if (model == 68020) { + for (int i = 0; i < CACHELINES020; i++) { + save_u32 (caches020[i].data); + save_u32 (caches020[i].tag); + save_u8 (caches020[i].valid ? 1 : 0); + } + save_u32 (regs.prefetch020addr); + save_u32 (regs.cacheholdingaddr020); + save_u32 (regs.cacheholdingdata020); + for (int i = 0; i < CPU_PIPELINE_MAX; i++) + save_u16 (regs.prefetch020[i]); + } else if (model == 68030) { + for (int i = 0; i < CACHELINES030; i++) { + for (int j = 0; j < 4; j++) { + save_u32 (icaches030[i].data[j]); + save_u8 (icaches030[i].valid[j] ? 1 : 0); + } + save_u32 (icaches030[i].tag); + } + for (int i = 0; i < CACHELINES030; i++) { + for (int j = 0; j < 4; j++) { + save_u32 (dcaches030[i].data[j]); + save_u8 (dcaches030[i].valid[j] ? 1 : 0); + } + save_u32 (dcaches030[i].tag); + } + } *len = dst - dstbak; return dstbak; } @@ -4042,7 +4940,7 @@ uae_u8 *save_mmu (int *len, uae_u8 *dstptr) else dstbak = dst = xmalloc (uae_u8, 1000); save_u32 (model); /* MODEL */ - save_u32 (0); /* FLAGS */ + save_u32 (0); /* FLAGS */ *len = dst - dstbak; return dstbak; } @@ -4059,29 +4957,32 @@ uae_u8 *restore_mmu (uae_u8 *src) #endif /* SAVESTATE */ -static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess) +static void exception3f (uae_u32 opcode, uaecptr addr, int writeaccess, int instructionaccess) { if (currprefs.cpu_model >= 68040) addr &= ~1; - last_addr_for_exception_3 = addr; - last_fault_for_exception_3 = fault; + if (currprefs.cpu_model <= 68010) + last_addr_for_exception_3 = m68k_getpc (); + else + last_addr_for_exception_3 = regs.instruction_pc; + last_fault_for_exception_3 = addr; last_op_for_exception_3 = opcode; last_writeaccess_for_exception_3 = writeaccess; last_instructionaccess_for_exception_3 = instructionaccess; - Exception (3, fault); + Exception (3); } -void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault) +void exception3 (uae_u32 opcode, uaecptr addr) { - exception3f (opcode, addr, fault, 0, 0); + exception3f (opcode, addr, 0, 0); } -void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault) +void exception3i (uae_u32 opcode, uaecptr addr) { - exception3f (opcode, addr, fault, 0, 1); + exception3f (opcode, addr, 0, 1); } -void exception2 (uaecptr addr, uaecptr fault) +void exception2 (uaecptr addr) { write_log (L"delayed exception2!\n"); regs.panic_pc = m68k_getpc (); @@ -4092,7 +4993,7 @@ void exception2 (uaecptr addr, uaecptr fault) #ifdef JIT set_special (SPCFLAG_END_COMPILE); #endif - fill_prefetch_slow (); + fill_prefetch (); } void cpureset (void) @@ -4102,7 +5003,7 @@ void cpureset (void) uae_u16 ins; if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) { - customreset (0); + custom_reset (0); return; } pc = m68k_getpc (); @@ -4110,11 +5011,11 @@ void cpureset (void) addrbank *b = &get_mem_bank (pc); if (b->check (pc, 2 + 2)) { /* We have memory, hope for the best.. */ - customreset (0); + custom_reset (0); return; } write_log (L"M68K RESET PC=%x, rebooting..\n", pc); - customreset (0); + custom_reset (0); m68k_setpc (ksboot); return; } @@ -4124,14 +5025,14 @@ void cpureset (void) int reg = ins & 7; uae_u32 addr = m68k_areg (regs, reg); write_log (L"reset/jmp (ax) combination emulated -> %x\n", addr); - customreset (0); + custom_reset (0); if (addr < 0x80000) addr += 0xf80000; m68k_setpc (addr - 2); return; } write_log (L"M68K RESET PC=%x, rebooting..\n", pc); - customreset (0); + custom_reset (0); m68k_setpc (ksboot); } @@ -4154,9 +5055,9 @@ void m68k_resumestopped (void) regs.stopped = 0; if (currprefs.cpu_cycle_exact) { if (currprefs.cpu_model == 68000) - do_cycles_ce000 (6); + x_do_cycles (6 * cpucycleunit); } - fill_prefetch_slow (); + fill_prefetch (); unset_special (SPCFLAG_STOP); } @@ -4311,8 +5212,8 @@ STATIC_INLINE void fill_cache040 (uae_u32 addr) for (i = 0; i < CACHELINES040; i++) { if (c->valid[i] && c->tag[i] == tag) { // cache hit - regs.prefetch020addr[0] = addr; - regs.prefetch020data[0] = c->data[i][lws]; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = c->data[i][lws]; return; } } @@ -4327,12 +5228,12 @@ STATIC_INLINE void fill_cache040 (uae_u32 addr) c->data[i][0] = data; } } - regs.prefetch020addr[0] = addr; - regs.prefetch020data[0] = data; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = data; } // this one is really simple and easy -STATIC_INLINE void fill_icache020 (uae_u32 addr, int idx) +static void fill_icache020 (uae_u32 addr) { int index; uae_u32 tag; @@ -4345,8 +5246,8 @@ STATIC_INLINE void fill_icache020 (uae_u32 addr, int idx) c = &caches020[index]; if (c->valid && c->tag == tag) { // cache hit - regs.prefetch020addr[idx] = addr; - regs.prefetch020data[idx] = c->data; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = c->data; return; } // cache miss @@ -4356,38 +5257,35 @@ STATIC_INLINE void fill_icache020 (uae_u32 addr, int idx) c->valid = !!(regs.cacr & 1); c->data = data; } - regs.prefetch020addr[idx] = addr; - regs.prefetch020data[idx] = data; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = data; } uae_u32 get_word_ce020_prefetch (int o) { uae_u32 pc = m68k_getpc () + o; - for (;;) { - for (int i = 0; i < 2; i++) { - if (pc == regs.prefetch020addr[0]) { - uae_u32 v = regs.prefetch020data[0] >> 16; - fill_icache020 (regs.prefetch020addr[0] + 4, 1); - return v; - } - if (pc == regs.prefetch020addr[0] + 2) { - uae_u32 v = regs.prefetch020data[0] & 0xffff; - if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) { - regs.prefetch020addr[0] = regs.prefetch020addr[1]; - regs.prefetch020data[0] = regs.prefetch020data[1]; - fill_icache020 (regs.prefetch020addr[0] + 4, 1); - } else { - fill_icache020 (pc + 4, 0); - fill_icache020 (regs.prefetch020addr[0] + 4, 1); - } - return v; - } - regs.prefetch020addr[0] = regs.prefetch020addr[1]; - regs.prefetch020data[0] = regs.prefetch020data[1]; - } - fill_icache020 (pc + 0, 0); - fill_icache020 (pc + 4, 1); + if (pc == regs.prefetch020addr) { + uae_u32 v = regs.prefetch020[0]; + 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; + return v; + } 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); } } @@ -4417,7 +5315,7 @@ STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag c->data[lws] = val; } -STATIC_INLINE void fill_icache030 (uae_u32 addr, int idx) +STATIC_INLINE void fill_icache030 (uae_u32 addr) { int lws; uae_u32 tag; @@ -4425,11 +5323,13 @@ STATIC_INLINE void fill_icache030 (uae_u32 addr, int idx) 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 - regs.prefetch020addr[idx] = addr; - regs.prefetch020data[idx] = c->data[lws]; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = c->data[lws]; return; } // cache miss @@ -4446,8 +5346,8 @@ STATIC_INLINE void fill_icache030 (uae_u32 addr, int idx) } #endif } - regs.prefetch020addr[idx] = addr; - regs.prefetch020data[idx] = data; + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = data; } STATIC_INLINE bool cancache030 (uaecptr addr) @@ -4599,34 +5499,30 @@ uae_u32 get_word_ce030_prefetch (int o) { uae_u32 pc = m68k_getpc () + o; - for (;;) { - for (int i = 0; i < 2; i++) { - if (pc == regs.prefetch020addr[0]) { - uae_u32 v = regs.prefetch020data[0] >> 16; - fill_icache030 (regs.prefetch020addr[0] + 4, 1); - return v; - } - if (pc == regs.prefetch020addr[0] + 2) { - uae_u32 v = regs.prefetch020data[0] & 0xffff; - if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) { - regs.prefetch020addr[0] = regs.prefetch020addr[1]; - regs.prefetch020data[0] = regs.prefetch020data[1]; - fill_icache030 (regs.prefetch020addr[0] + 4, 1); - } else { - fill_icache030 (pc + 4, 0); - fill_icache030 (regs.prefetch020addr[0] + 4, 1); - } - return v; - } - regs.prefetch020addr[0] = regs.prefetch020addr[1]; - regs.prefetch020data[0] = regs.prefetch020data[1]; - } - fill_icache030 (pc + 0, 0); - fill_icache030 (pc + 4, 1); + if (pc == regs.prefetch020addr) { + uae_u32 v = regs.prefetch020[0]; + 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); + 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); } } - void flush_dcache (uaecptr addr, int size) { if (!currprefs.cpu_cycle_exact) @@ -4641,21 +5537,6 @@ void flush_dcache (uaecptr addr, int size) } } -void do_cycles_ce020 (int clocks) -{ - do_cycles_ce (clocks * cpucycleunit); -} -void do_cycles_ce020_mem (int clocks) -{ - regs.ce020memcycles -= clocks * cpucycleunit; - do_cycles_ce (clocks * cpucycleunit); -} - -void do_cycles_ce000 (int clocks) -{ - do_cycles_ce (clocks * cpucycleunit); -} - void m68k_do_rte_mmu (uaecptr a7) { uae_u16 ssr = get_word_mmu (a7 + 8 + 4); diff --git a/od-win32/blkdev_win32_aspi.cpp b/od-win32/blkdev_win32_aspi.cpp index 15a675b5..f508ca79 100644 --- a/od-win32/blkdev_win32_aspi.cpp +++ b/od-win32/blkdev_win32_aspi.cpp @@ -1020,5 +1020,5 @@ struct device_functions devicefunc_win32_aspi = { L"ASPI", open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, execscsicmd_out, execscsicmd_in, execscsicmd_direct, - 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0, 0 }; diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index 0523f681..7126a836 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -1052,6 +1052,27 @@ static int ismedia (struct dev_info_ioctl *ciw, int unitnum) return fetch_geometry (ciw, unitnum, &ciw->di); } +static int eject (int unitnum, bool eject) +{ + DWORD len; + struct dev_info_ioctl *ciw = unitisopen (unitnum); + + if (!ciw) + return 0; + if (!unitisopen (unitnum)) + return 0; + cdda_stop (ciw); + if (!open_createfile (ciw, 0)) + return 0; + int ret = 0; + seterrormode (ciw); + if (!DeviceIoControl (ciw->h, eject ? IOCTL_STORAGE_EJECT_MEDIA : IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &len, NULL)) { + ret = 1; + } + reseterrormode (ciw); + return ret; +} + /* read toc */ static int ioctl_command_toc (int unitnum, struct cd_toc_head *tocout) { @@ -1374,13 +1395,27 @@ void win32_ioctl_media_change (TCHAR driveletter, int insert) } } +static int ioctl_scsiemu (int unitnum, uae_u8 *cmd) +{ + uae_u8 c = cmd[0]; + if (c == 0x1b) { + int mode = cmd[4] & 3; + if (mode == 2) + eject (unitnum, true); + else if (mode == 3) + eject (unitnum, false); + return 1; + } + return -1; +} + struct device_functions devicefunc_win32_ioctl = { L"IOCTL", open_bus, close_bus, open_device, close_device, info_device, 0, 0, 0, ioctl_command_pause, ioctl_command_stop, ioctl_command_play, ioctl_command_volume, ioctl_command_qcode, ioctl_command_toc, ioctl_command_read, ioctl_command_rawread, ioctl_command_write, - 0, ioctl_ismedia + 0, ioctl_ismedia, ioctl_scsiemu }; #endif diff --git a/od-win32/blkdev_win32_spti.cpp b/od-win32/blkdev_win32_spti.cpp index ec1e35c7..8991b7bf 100644 --- a/od-win32/blkdev_win32_spti.cpp +++ b/od-win32/blkdev_win32_spti.cpp @@ -870,5 +870,5 @@ struct device_functions devicefunc_win32_spti = { L"SPTI", open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device, execscsicmd_out, execscsicmd_in, execscsicmd_direct, - 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0, 0 }; diff --git a/od-win32/caps/CapsAPI.h b/od-win32/caps/CapsAPI.h index 4b44db24..f4a5e9fa 100644 --- a/od-win32/caps/CapsAPI.h +++ b/od-win32/caps/CapsAPI.h @@ -13,11 +13,13 @@ // 5: generate unformatted data // 6: generate unformatted data, that changes each revolution // 7: directly use source memory buffer supplied with LockImageMemory -// 8: flakey data is created on one revolution, updated with each lock +// 8: flakey/weak data is created on one revolution, updated with each lock // 9: ...Info.type holds the expected structure type // 10: alternate density map as fractions // 11: overlap position is in bits // 12: tracklen is in bits, and the track buffer is bit sized +// 13: track overlap or weak data is never updated, just initialized +// 14: set weak bit generator seed value #define DI_LOCK_INDEX DF_0 #define DI_LOCK_ALIGN DF_1 #define DI_LOCK_DENVAR DF_2 @@ -31,6 +33,8 @@ #define DI_LOCK_DENALT DF_10 #define DI_LOCK_OVLBIT DF_11 #define DI_LOCK_TRKBIT DF_12 +#define DI_LOCK_NOUPDATE DF_13 +#define DI_LOCK_SETWSEED DF_14 #define CAPS_MAXPLATFORM 4 #define CAPS_MTRS 5 @@ -112,6 +116,24 @@ struct CapsTrackInfoT1 { typedef struct CapsTrackInfoT1 *PCAPSTRACKINFOT1; +// disk track information block +struct CapsTrackInfoT2 { + UDWORD type; // track type + UDWORD cylinder; // cylinder# + UDWORD head; // head# + UDWORD sectorcnt; // available sectors + PUBYTE trackbuf; // track buffer memory + UDWORD tracklen; // track buffer memory length + UDWORD timelen; // timing buffer length + PUDWORD timebuf; // timing buffer + SDWORD overlap; // overlap position + UDWORD startbit; // start position of the decoding + UDWORD wseed; // weak bit generator data + UDWORD weakcnt; // number of weak data areas +}; + +typedef struct CapsTrackInfoT2 *PCAPSTRACKINFOT2; + #pragma pack(pop) // image type @@ -122,10 +144,16 @@ enum { // platform IDs, not about configuration, but intended use enum { - ciipNA=0, // invalid platform (dummy entry) - ciipAmiga, // Amiga - ciipAtariST, // Atari ST - ciipPC // PC + ciipNA=0, // invalid platform (dummy entry) + ciipAmiga, + ciipAtariST, + ciipPC, + ciipAmstradCPC, + ciipSpectrum, + ciipSamCoupe, + ciipArchimedes, + ciipC64, + ciipAtari8 }; // track type diff --git a/od-win32/caps/caps_win32.cpp b/od-win32/caps/caps_win32.cpp index b8a458e0..0fe7059c 100644 --- a/od-win32/caps/caps_win32.cpp +++ b/od-win32/caps/caps_win32.cpp @@ -10,6 +10,7 @@ #include "zfile.h" #include "gui.h" #include "win32.h" +#include "uae.h" #include "ComType.h" #include "CapsAPI.h" @@ -18,8 +19,7 @@ static SDWORD caps_cont[4]= {-1, -1, -1, -1}; static int caps_locked[4]; static int caps_flags = DI_LOCK_DENVAR|DI_LOCK_DENNOISE|DI_LOCK_NOISE|DI_LOCK_UPDATEFD|DI_LOCK_TYPE|DI_LOCK_OVLBIT; static struct CapsVersionInfo cvi; -static bool oldlib; -#define LIB_TYPE 1 +static bool oldlib, canseed; typedef SDWORD (__cdecl* CAPSINIT)(void); static CAPSINIT pCAPSInit; @@ -85,12 +85,13 @@ int caps_init (void) pCAPSUnlockAllTracks = (CAPSUNLOCKALLTRACKS)GetProcAddress (h, "CAPSUnlockAllTracks"); pCAPSGetVersionInfo = (CAPSGETVERSIONINFO)GetProcAddress (h, "CAPSGetVersionInfo"); init = 1; - cvi.type = LIB_TYPE; + cvi.type = 1; pCAPSGetVersionInfo (&cvi, 0); write_log (L"CAPS: library version %d.%d (flags=%08X)\n", cvi.release, cvi.revision, cvi.flag); oldlib = (cvi.flag & (DI_LOCK_TRKBIT | DI_LOCK_OVLBIT)) != (DI_LOCK_TRKBIT | DI_LOCK_OVLBIT); if (!oldlib) caps_flags |= DI_LOCK_TRKBIT | DI_LOCK_OVLBIT; + canseed = (cvi.flag & DI_LOCK_SETWSEED) != 0; for (i = 0; i < 4; i++) caps_cont[i] = pCAPSAddImage (); return 1; @@ -142,7 +143,7 @@ int caps_loadimage (struct zfile *zf, int drv, int *num_tracks) if (cvi.release < 4) { // pre-4.x bug workaround struct CapsTrackInfoT1 cit; - cit.type = LIB_TYPE; + cit.type = 1; if (pCAPSLockTrack ((PCAPSTRACKINFO)&cit, caps_cont[drv], 0, 0, caps_flags) == imgeIncompatible) { if (!notified) notify_user (NUMSG_OLDCAPS); @@ -195,13 +196,29 @@ static void mfmcopy (uae_u16 *mfm, uae_u8 *data, int len) } } +static int load (struct CapsTrackInfoT2 *ci, int drv, int track) +{ + int flags; + + ci->type = 1; + flags = caps_flags; + + if (canseed) { + flags |= DI_LOCK_SETWSEED; + ci->type = 2; + ci->wseed = uaerand (); + } + if (pCAPSLockTrack ((PCAPSTRACKINFO)ci, caps_cont[drv], track / 2, track & 1, flags) != imgeOk) + return 0; + return 1; +} + int caps_loadrevolution (uae_u16 *mfmbuf, int drv, int track, int *tracklength) { int len; - struct CapsTrackInfoT1 ci; + struct CapsTrackInfoT2 ci; - ci.type = LIB_TYPE; - if (pCAPSLockTrack ((PCAPSTRACKINFO)&ci, caps_cont[drv], track / 2, track & 1, caps_flags) != imgeOk) + if (!load (&ci, drv, track)) return 0; if (oldlib) len = ci.tracklen * 8; @@ -215,12 +232,11 @@ int caps_loadrevolution (uae_u16 *mfmbuf, int drv, int track, int *tracklength) int caps_loadtrack (uae_u16 *mfmbuf, uae_u16 *tracktiming, int drv, int track, int *tracklength, int *multirev, int *gapoffset) { int len; - struct CapsTrackInfoT1 ci; + struct CapsTrackInfoT2 ci; - ci.type = LIB_TYPE; if (tracktiming) *tracktiming = 0; - if (pCAPSLockTrack ((PCAPSTRACKINFO)&ci, caps_cont[drv], track / 2, track & 1, caps_flags) != imgeOk) + if (!load (&ci, drv, track)) return 0; *multirev = (ci.type & CTIT_FLAG_FLAKEY) ? 1 : 0; if (oldlib) { diff --git a/od-win32/debug_win32.cpp b/od-win32/debug_win32.cpp index 9c6db138..9c6988a0 100644 --- a/od-win32/debug_win32.cpp +++ b/od-win32/debug_win32.cpp @@ -436,7 +436,7 @@ static void ShowMisc(void) free(p2); } for (i = 0; i < 4; i++) { - p = p2 = save_disk (i, &len, NULL); + p = p2 = save_disk (i, &len, NULL, false); ULBS(L""); ULBS(L"Drive DF%d: (%s)", i, (p[4] & 2) ? "disabled" : "enabled"); ULBS(L"ID %08X Motor %s Cylinder %2d MFMPOS %d", diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index cc070da8..e2978514 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -137,6 +137,39 @@ int dinput_winmousemode (void) return 0; } +#if 0 +static LRESULT CALLBACK LowLevelKeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) +{ + write_log (L"*"); + if (nCode >= 0) { + KBDLLHOOKSTRUCT *k = (KBDLLHOOKSTRUCT*)lParam; + int vk = k->vkCode; + int sc = k->scanCode; + write_log (L"%02x %02x\n", vk, sc); + } + return CallNextHookEx (NULL, nCode, wParam, lParam); +} + +static HHOOK kbhook; +static void lock_kb (void) +{ + if (kbhook) + return; + kbhook = SetWindowsHookEx (WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0); + if (!kbhook) + write_log (L"SetWindowsHookEx %d\n", GetLastError ()); + else + write_log (L"***************************\n"); +} +static void unlock_kb (void) +{ + if (!kbhook) + return; + write_log (L"!!!!!!!!!!!!!!!!!!!!!!!!\n"); + UnhookWindowsHookEx (kbhook); + kbhook = NULL; +} +#endif static BYTE ledkeystate[256]; @@ -2247,6 +2280,7 @@ static int acquire_kb (int num, int flags) set_leds (oldusedleds); } + //lock_kb (); setcoop (&di_keyboard[num], DISCL_NOWINKEY | DISCL_FOREGROUND | DISCL_EXCLUSIVE, L"keyboard"); kb_do_refresh = ~0; di_keyboard[num].acquired = -1; @@ -2292,6 +2326,7 @@ static void unacquire_kb (int num) } #endif } + //unlock_kb (); } static int refresh_kb (LPDIRECTINPUTDEVICE8 lpdi, int num) diff --git a/od-win32/keyboard_win32.cpp b/od-win32/keyboard_win32.cpp index 24672cf3..8f325089 100644 --- a/od-win32/keyboard_win32.cpp +++ b/od-win32/keyboard_win32.cpp @@ -180,6 +180,10 @@ static struct uae_input_device_kbr_default keytrans[] = { static int kb_np[] = { DIK_NUMPAD4, -1, DIK_NUMPAD6, -1, DIK_NUMPAD8, -1, DIK_NUMPAD2, -1, DIK_NUMPAD0, DIK_NUMPAD5, -1, DIK_DECIMAL, DIK_NUMPADENTER, -1, -1 }; static int kb_ck[] = { DIK_LEFT, -1, DIK_RIGHT, -1, DIK_UP, -1, DIK_DOWN, -1, DIK_RCONTROL, DIK_RMENU, -1, DIK_RSHIFT, -1, -1 }; static int kb_se[] = { DIK_A, -1, DIK_D, -1, DIK_W, -1, DIK_S, -1, DIK_LMENU, -1, DIK_LSHIFT, -1, -1 }; +static int kb_np3[] = { DIK_NUMPAD4, -1, DIK_NUMPAD6, -1, DIK_NUMPAD8, -1, DIK_NUMPAD2, -1, DIK_NUMPAD0, DIK_NUMPAD5, -1, DIK_DECIMAL, -1, DIK_NUMPADENTER, -1, -1 }; +static int kb_ck3[] = { DIK_LEFT, -1, DIK_RIGHT, -1, DIK_UP, -1, DIK_DOWN, -1, DIK_RCONTROL, -1, DIK_RSHIFT, -1, DIK_RMENU, -1, -1 }; +static int kb_se3[] = { DIK_A, -1, DIK_D, -1, DIK_W, -1, DIK_S, -1, DIK_LMENU, -1, DIK_LSHIFT, -1, DIK_LCONTROL, -1, -1 }; + static int kb_cd32_np[] = { DIK_NUMPAD4, -1, DIK_NUMPAD6, -1, DIK_NUMPAD8, -1, DIK_NUMPAD2, -1, DIK_NUMPAD0, DIK_NUMPAD5, DIK_NUMPAD1, -1, DIK_DECIMAL, DIK_NUMPAD3, -1, DIK_NUMPAD7, -1, DIK_NUMPAD9, -1, DIK_DIVIDE, -1, DIK_SUBTRACT, -1, DIK_MULTIPLY, -1, -1 }; static int kb_cd32_ck[] = { DIK_LEFT, -1, DIK_RIGHT, -1, DIK_UP, -1, DIK_DOWN, -1, DIK_RCONTROL, -1, DIK_RMENU, -1, DIK_NUMPAD7, -1, DIK_NUMPAD9, -1, DIK_DIVIDE, -1, DIK_SUBTRACT, -1, DIK_MULTIPLY, -1, -1 }; @@ -192,7 +196,11 @@ static int kb_xa2[] = { DIK_D, -1, DIK_G, -1, DIK_R, -1, DIK_F, -1, DIK_A, -1, D static int kb_arcadia[] = { DIK_F2, -1, DIK_1, -1, DIK_2, -1, DIK_5, -1, DIK_6, -1, -1 }; static int kb_arcadiaxa[] = { DIK_1, -1, DIK_2, -1, DIK_3, -1, DIK_4, -1, DIK_6, -1, DIK_LBRACKET, DIK_LSHIFT, -1, DIK_RBRACKET, -1, DIK_C, -1, DIK_5, -1, DIK_Z, -1, DIK_X, -1, -1 }; -static int *kbmaps[] = { kb_np, kb_ck, kb_se, kb_cd32_np, kb_cd32_ck, kb_cd32_se, kb_xa1, kb_xa2, kb_arcadia, kb_arcadiaxa, kb_cdtv }; +static int *kbmaps[] = { + kb_np, kb_ck, kb_se, kb_np3, kb_ck3, kb_se3, + kb_cd32_np, kb_cd32_ck, kb_cd32_se, + kb_xa1, kb_xa2, kb_arcadia, kb_arcadiaxa, kb_cdtv +}; extern int ispressed (int key); diff --git a/od-win32/registry.cpp b/od-win32/registry.cpp index 3ddb979a..8ebc3d79 100644 --- a/od-win32/registry.cpp +++ b/od-win32/registry.cpp @@ -382,14 +382,16 @@ int reginitializeinit (const TCHAR *ppath) if (!ppath) { int ok = 0; TCHAR *posn; - _tcscpy (path, _wpgmptr); + path[0] = 0; + GetFullPathName (_wpgmptr, sizeof path / sizeof (TCHAR), path, NULL); if (_tcslen (path) > 4 && !_tcsicmp (path + _tcslen (path) - 4, L".exe")) { _tcscpy (path + _tcslen (path) - 3, L"ini"); if (GetFileAttributes (path) != INVALID_FILE_ATTRIBUTES) ok = 1; } if (!ok) { - _tcscpy (path, _wpgmptr); + path[0] = 0; + GetFullPathName (_wpgmptr, sizeof path / sizeof (TCHAR), path, NULL); if((posn = _tcsrchr (path, '\\'))) posn[1] = 0; _tcscat (path, L"winuae.ini"); diff --git a/od-win32/resources/resource b/od-win32/resources/resource index 400772a8..322bdbe0 100644 --- a/od-win32/resources/resource +++ b/od-win32/resources/resource @@ -341,6 +341,8 @@ #define IDS_AUTOSCALE_CENTER 365 #define IDS_AUTOSCALE_MAX 366 #define IDS_AUTOSCALE_TV 367 +#define IDS_JOYMODE_GAMEPAD 368 +#define IDS_AUTOSCALE_DEFAULT 369 #define IDS_QS_MODELS 1000 #define IDS_QS_MODEL_A500 1001 #define IDS_QS_MODEL_A500P 1002 @@ -427,6 +429,8 @@ #define IDC_LORES 1176 #define IDC_LORES_SMOOTHED 1179 #define IDC_FLICKERFIXER 1180 +#define IDC_LORES_SMOOTHED2 1181 +#define IDC_AUTORESOLUTION 1181 #define IDC_FRAMERATE 1185 #define IDC_RATETEXT 1186 #define IDC_XSIZE 1187 @@ -657,8 +661,9 @@ #define IDC_HIGHPRIORITY 1530 #define IDC_MINIMIZED_NOSOUND 1530 #define IDC_MINIMIZED_PAUSE 1531 -#define IDC_STATE_CAPTURE 1532 +#define IDC_STATEREC_RECORD 1532 #define IDC_KBLED_USB 1533 +#define IDC_STATEREC_CAPTURE2 1533 #define IDC_SER_SHARED 1553 #define IDC_SER_CTSRTS 1554 #define IDC_SER_DIRECT 1555 @@ -753,16 +758,16 @@ #define IDC_SAMPLERIPPER_ACTIVATED 1616 #define IDC_AVIOUTPUT_BORDER_TRIM 1617 #define IDC_FILTERVZ 1617 -#define IDC_INPREC_RECORD 1617 #define IDC_AVIOUTPUT_AUDIO_STATIC 1618 #define IDC_FILTERHO 1618 #define IDC_AVIOUTPUT_VIDEO_STATIC 1619 #define IDC_FILTERVO 1619 #define IDC_AVIOUTPUT_8BIT 1620 -#define IDC_INPREC_PLAY 1620 #define IDC_FILTERASPECT 1620 +#define IDC_STATEREC_PLAY 1620 #define IDC_AVIOUTPUT_24BIT 1621 #define IDC_FILTERASPECT2 1621 +#define IDC_STATEREC_SAVE 1621 #define IDC_AVIOUTPUT_WIDTH 1622 #define IDC_AVIOUTPUT_HEIGHT 1623 #define IDC_AVIOUTPUT_FRAME 1624 @@ -807,9 +812,7 @@ #define IDC_ACTIVE_PRI 1644 #define IDC_MINIMIZED_PRIORITY 1645 #define IDC_AVIOUTPUT_FRAMELIMITER 1645 -#define IDC_STATE_RATE 1646 -#define IDC_INPREC_PLAYMODE 1646 -#define IDC_STATE_BUFFERSIZE 1647 +#define IDC_STATEREC_RATE 1646 #define IDC_SOUNDDRIVESELECT 1647 #define IDC_PANELTREE 1647 #define IDC_AVIOUTPUT_NOSOUNDOUTPUT 1647 @@ -828,7 +831,10 @@ #define IDC_AVIOUTPUT_ORIGINALSIZE2 1650 #define IDC_SCREENSHOT_ORIGINALSIZE 1650 #define IDC_SOUNDCARDLIST 1651 +#define IDC_STATE_BUFFERSIZE2 1651 +#define IDC_STATEREC_BUFFERSIZE 1651 #define IDC_SOUNDFREQ 1652 +#define IDC_STATEREC_AUTOPLAY 1652 #define IDC_SOUNDFREQTXT 1653 #define IDC_PANEL_FRAME 1653 #define IDC_SOUNDFILTERTXT 1654 @@ -1101,7 +1107,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 356 +#define _APS_NEXT_RESOURCE_VALUE 370 #define _APS_NEXT_COMMAND_VALUE 40050 #define _APS_NEXT_CONTROL_VALUE 1808 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index fd9443eb..a239e15a 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -121,7 +121,7 @@ BEGIN EDITTEXT IDC_XSIZE,59,48,48,12,ES_NUMBER EDITTEXT IDC_YSIZE,114,48,47,12,ES_NUMBER GROUPBOX "Settings",IDC_SETTINGSTEXT,12,73,199,137 - CONTROL "Blacker than black",IDC_BLACKER_THAN_BLACK,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,19,125,92,10 + CONTROL "Blacker than black",IDC_BLACKER_THAN_BLACK,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,17,125,92,10 LTEXT "Refresh:",IDC_REFRESHTEXT,18,173,28,8 CONTROL "Slider1",IDC_FRAMERATE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,47,168,75,20 EDITTEXT IDC_RATETEXT,124,172,77,12,ES_CENTER | ES_READONLY @@ -138,7 +138,7 @@ BEGIN CONTROL "",IDC_FRAMERATE2,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,47,188,127,20 EDITTEXT IDC_RATE2TEXT,175,192,26,12,ES_CENTER | ES_READONLY COMBOBOX IDC_RESOLUTIONDEPTH,134,27,46,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP - CONTROL "Filtered low resolution",IDC_LORES_SMOOTHED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,125,89,10 + CONTROL "Filtered low resolution",IDC_LORES_SMOOTHED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,125,89,10 COMBOBOX IDC_SCREENMODE_NATIVE,100,85,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_SCREENMODE_RTG,100,103,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP RTEXT "Native mode:",IDC_STATIC,19,85,59,15,SS_CENTERIMAGE @@ -146,10 +146,11 @@ BEGIN PUSHBUTTON "Reset to defaults",IDC_DA_RESET,212,218,73,14 RTEXT "Resolution:",IDC_STATIC,27,152,59,15,SS_CENTERIMAGE COMBOBOX IDC_LORES,100,152,102,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP - CONTROL "Remove interlace artifacts",IDC_FLICKERFIXER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,139,99,10 + CONTROL "Remove interlace artifacts",IDC_FLICKERFIXER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,139,99,10 RTEXT "Windowed:",IDC_STATIC,17,46,40,15,SS_CENTERIMAGE RTEXT "Fullscreen:",IDC_STATIC,17,19,40,15,SS_CENTERIMAGE COMBOBOX IDC_DISPLAY_BUFFERCNT,187,47,87,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP + CONTROL "Resolution autoswitch",IDC_AUTORESOLUTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,139,89,10 END IDD_MEMORY DIALOGEX 0, 0, 300, 182 @@ -480,32 +481,27 @@ IDD_MISC1 DIALOGEX 0, 0, 300, 237 STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - GROUPBOX "Miscellaneous Options",IDC_STATIC,8,2,290,136 + GROUPBOX "Miscellaneous Options",IDC_STATIC,4,2,293,165 CONTROL "Untrap = middle button",IDC_JULIAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,19,110,10 CONTROL "Show GUI on startup",IDC_SHOWGUI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,43,109,10 - CONTROL "Native OSD",IDC_SHOWLEDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,95,76,10 + CONTROL "Native on-screen display",IDC_SHOWLEDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,139,109,10 CONTROL "Don't show taskbar button",IDC_NOTASKBARBUTTON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,67,109,10 CONTROL "Use CTRL-F11 to quit",IDC_CTRLF11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,55,110,10 - GROUPBOX "Keyboard LEDs",IDC_STATIC,7,140,85,94 - COMBOBOX IDC_KBLED1,22,154,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_KBLED2,22,173,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_KBLED3,22,193,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Logging",IDC_STATIC,97,140,202,25 - CONTROL "Create log file",IDC_CREATELOGFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,151,72,10 - CONTROL "Illegal memory accesses",IDC_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,189,151,95,10 - GROUPBOX "State Files",IDC_STATIC,98,167,201,68 - PUSHBUTTON "Load state...",IDC_DOLOADSTATE,105,180,49,14 - PUSHBUTTON "Save state...",IDC_DOSAVESTATE,105,208,49,14 - CONTROL "Enable state recording",IDC_STATE_CAPTURE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,200,182,88,10 - RTEXT "Recording rate (seconds):",IDC_STATIC,157,199,86,10,SS_CENTERIMAGE | WS_TABSTOP - COMBOBOX IDC_STATE_RATE,248,197,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - RTEXT "Recording buffer (MB):",IDC_STATIC,160,219,83,10,SS_CENTERIMAGE | WS_TABSTOP - COMBOBOX IDC_STATE_BUFFERSIZE,248,217,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Keyboard LEDs",IDC_STATIC,3,207,294,29 + COMBOBOX IDC_KBLED1,10,218,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_KBLED2,78,218,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_KBLED3,145,218,56,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Logging",IDC_STATIC,4,167,151,38 + CONTROL "Create log file",IDC_CREATELOGFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,176,72,10 + CONTROL "Illegal memory accesses",IDC_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,41,188,95,10 + GROUPBOX "State Files",IDC_STATIC,162,167,135,38 + PUSHBUTTON "Load state...",IDC_DOLOADSTATE,175,182,49,14 + PUSHBUTTON "Save state...",IDC_DOSAVESTATE,235,182,49,14 CONTROL "Always on top",IDC_ALWAYSONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,79,110,10 - CONTROL "USB mode",IDC_KBLED_USB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,216,64,10 + CONTROL "USB mode",IDC_KBLED_USB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,217,219,64,10 COMBOBOX IDC_SCSIMODE,213,26,80,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_LANGUAGE,153,117,122,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Language",IDC_STATIC,138,107,154,27 + COMBOBOX IDC_LANGUAGE,153,144,122,65,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Language",IDC_STATIC,138,134,154,27 CONTROL "Disable screensaver",IDC_POWERSAVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,91,109,10 COMBOBOX IDC_DD_SURFACETYPE,213,78,79,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP RTEXT "DirectDraw display buffer:",IDC_STATIC,112,79,97,10,SS_CENTERIMAGE @@ -513,7 +509,7 @@ BEGIN CONTROL "Synchronize clock",IDC_CLOCKSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,103,111,10 CONTROL "Faster RTG [] Enables less accurate custom chipset emulation mode when Picasso96 is enabled.",IDC_FASTERRTG, "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,19,115,111,10 - CONTROL "RTG OSD",IDC_SHOWLEDSRTG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,227,95,63,10 + CONTROL "RTG on-screen display",IDC_SHOWLEDSRTG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,151,109,10 RTEXT "Graphics API:",IDC_STATIC,130,62,79,10,SS_CENTERIMAGE COMBOBOX IDC_DXMODE,213,60,79,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP CONTROL "Minimize when focus is lost",IDC_FOCUSMINIMIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,31,110,10 @@ -686,11 +682,11 @@ BEGIN CONTROL "A1000 Agnus (8361/8367)",IDC_CS_DIPAGNUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,159,107,10 END -IDD_AVIOUTPUT DIALOGEX 0, 0, 288, 217 +IDD_AVIOUTPUT DIALOGEX 0, 0, 288, 236 STYLE DS_LOCALEDIT | DS_SETFONT | DS_CONTROL | WS_CHILD FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - GROUPBOX "Output Properties",IDC_STATIC,5,0,274,126 + GROUPBOX "Output Properties",IDC_STATIC,5,0,274,115 EDITTEXT IDC_AVIOUTPUT_FILETEXT,15,15,226,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_CLIENTEDGE PUSHBUTTON "...",IDC_AVIOUTPUT_FILE,249,15,19,12 CONTROL "Audio",IDC_AVIOUTPUT_AUDIO,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | BS_FLAT | WS_TABSTOP,15,33,39,14 @@ -698,23 +694,28 @@ BEGIN CONTROL "Video",IDC_AVIOUTPUT_VIDEO,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | BS_FLAT | WS_TABSTOP,15,50,39,14 CONTROL "",IDC_AVIOUTPUT_VIDEO_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | SS_SUNKEN | WS_GROUP,59,51,209,13 CONTROL "Disable frame rate limit",IDC_AVIOUTPUT_FRAMELIMITER, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,71,122,10 - CONTROL "AVI output enabled",IDC_AVIOUTPUT_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,15,103,108,14 - PUSHBUTTON "Save screenshot",IDC_SCREENSHOT,16,141,77,14 - GROUPBOX "Ripper",IDC_STATIC,5,127,274,49 - PUSHBUTTON "Pro Wizard 1.62",IDC_PROWIZARD,192,141,77,14,WS_DISABLED - CONTROL "Sample ripper",IDC_SAMPLERIPPER_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,192,159,77,14 - GROUPBOX "Input Recorder",IDC_STATIC,5,178,274,33 - CONTROL "Record",IDC_INPREC_RECORD,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,192,190,77,14 - CONTROL "Playback",IDC_INPREC_PLAY,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,16,190,77,14 - CONTROL "Alt. playback mode",IDC_INPREC_PLAYMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,192,78,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,69,122,10 + CONTROL "AVI output enabled",IDC_AVIOUTPUT_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,15,94,108,14 + PUSHBUTTON "Save screenshot",IDC_SCREENSHOT,16,129,77,14 + GROUPBOX "Ripper",IDC_STATIC,5,115,274,49 + PUSHBUTTON "Pro Wizard 1.62",IDC_PROWIZARD,192,129,77,14,WS_DISABLED + CONTROL "Sample ripper",IDC_SAMPLERIPPER_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,192,146,77,14 + GROUPBOX "Re-recorder",IDC_STATIC,5,165,274,70 + CONTROL "Play recording",IDC_STATEREC_PLAY,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,15,177,77,14 CONTROL "Disable sound output",IDC_AVIOUTPUT_NOSOUNDOUTPUT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,88,123,10 - CONTROL "Disable sound sync",IDC_AVIOUTPUT_NOSOUNDSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,88,120,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,81,123,10 + CONTROL "Disable sound sync",IDC_AVIOUTPUT_NOSOUNDSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,81,120,10 CONTROL "Capture before filtering",IDC_AVIOUTPUT_ORIGINALSIZE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,71,120,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,69,120,10 CONTROL "Take screenshot before filtering",IDC_SCREENSHOT_ORIGINALSIZE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,160,162,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,148,162,10 + RTEXT "Recording rate (seconds):",IDC_STATIC,12,218,86,10,SS_CENTERIMAGE | WS_TABSTOP + COMBOBOX IDC_STATEREC_RATE,103,216,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + RTEXT "Recording buffers:",IDC_STATIC,148,218,75,10,SS_CENTERIMAGE | WS_TABSTOP + COMBOBOX IDC_STATEREC_BUFFERSIZE,229,216,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "Re-recording enabled",IDC_STATEREC_RECORD,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,160,177,108,14 + PUSHBUTTON "Save recording",IDC_STATEREC_SAVE,160,195,108,14 + CONTROL "Automatic replay",IDC_STATEREC_AUTOPLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,200,129,10 END IDD_INPUT DIALOGEX 0, 0, 300, 242 @@ -1058,8 +1059,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,0,0 - PRODUCTVERSION 2,3,0,0 + FILEVERSION 2,3,1,0 + PRODUCTVERSION 2,3,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -1075,12 +1076,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "WinUAE" - VALUE "FileVersion", "2.3.0.0" + VALUE "FileVersion", "2.3.1.0" VALUE "InternalName", "WinUAE" VALUE "LegalCopyright", "© 1996-2010 under the GNU Public License (GPL)" VALUE "OriginalFilename", "WinUAE.exe" VALUE "ProductName", "WinUAE" - VALUE "ProductVersion", "2.3.0.0" + VALUE "ProductVersion", "2.3.1.0" END END BLOCK "VarFileInfo" @@ -1260,6 +1261,10 @@ BEGIN BEGIN END + IDD_AVIOUTPUT, DIALOG + BEGIN + END + IDD_INPUT, DIALOG BEGIN END @@ -1644,7 +1649,7 @@ BEGIN IDS_TABLET_BOTH_CURSORS "Show both cursors" IDS_TABLET_NATIVE_CURSOR "Show native cursor only" IDS_TABLET_HOST_CURSOR "Show host cursor only" - IDS_AUTOSCALE_DISABLED "No Autoscaling" + IDS_AUTOSCALE_DISABLED "No scaling" IDS_AUTOSCALE_SCALING "Automatic scaling" IDS_AUTOSCALE_RESIZE "Automatic resize" IDS_PRINTER_ASCII "ASCII-Only" @@ -1671,6 +1676,12 @@ BEGIN IDS_AUTOSCALE_TV "Fullscreen (TV)" END +STRINGTABLE +BEGIN + IDS_JOYMODE_GAMEPAD "Gamepad" + IDS_AUTOSCALE_DEFAULT "Default" +END + #endif // English resources ///////////////////////////////////////////////////////////////////////////// diff --git a/od-win32/rp.cpp b/od-win32/rp.cpp index 41b07b35..844f39fa 100644 --- a/od-win32/rp.cpp +++ b/od-win32/rp.cpp @@ -477,7 +477,7 @@ static void set_screenmode (struct RPScreenMode *sm, struct uae_prefs *p) p->gfx_size_fs.height = disp->rect.bottom - disp->rect.top; } - p->gfx_filter = rp_filter_default; + //p->gfx_filter = rp_filter_default; p->gfx_filter_horiz_zoom_mult = 1000; p->gfx_filter_vert_zoom_mult = 1000; //p->gfx_filter_autoscale = 0; @@ -665,12 +665,12 @@ static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM TCHAR *s = (TCHAR*)pData; DWORD ret = FALSE; if (s == NULL) { - savestate_initsave (NULL, 0, TRUE); + savestate_initsave (NULL, 0, TRUE, true); return 1; } if (vpos == 0) { - savestate_initsave (L"", 1, TRUE); - save_state (s, L"AF2008"); + savestate_initsave (L"", 1, TRUE, true); + save_state (s, L"AmigaForever"); ret = 1; } else { //savestate_initsave (s, 1, TRUE); @@ -825,6 +825,7 @@ void rp_fixup_options (struct uae_prefs *p) rp_filter_default = rp_filter = currprefs.gfx_filter; if (rp_filter == 0) rp_filter = UAE_FILTER_NULL; + //p->gfx_api = 0; fixup_size (p); get_screenmode (&sm, p); diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index ff568d3c..1c94b71e 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -519,3 +519,4 @@ #define HAVE_WINDOWS_H 1 #define FSDB_DIR_SEPARATOR '\\' +#define FSDB_DIR_SEPARATOR_S L"\\" diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index f9093e68..2d32073d 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -85,6 +85,7 @@ #include "direct3d.h" #include "clipboard_win32.h" #include "blkdev.h" +#include "inputrecord.h" #ifdef RETROPLATFORM #include "rp.h" #include "cloanto/RetroPlatformIPC.h" @@ -92,6 +93,7 @@ extern int harddrive_dangerous, do_rdbdump, aspi_allow_all, no_rawinput; extern int force_directsound; +extern int log_a2065, a2065_promiscuous; int log_scsi, log_net, uaelib_debug; int pissoff_value = 25000; unsigned int fpucontrol; @@ -269,7 +271,7 @@ frame_time_t read_processor_time (void) cnt++; if (cnt > 1000000) { - write_log(L"**************\n"); + write_log (L"**************\n"); cnt = 0; } #endif @@ -463,6 +465,7 @@ static void setmaintitle (HWND hwnd) return; #endif txt[0] = 0; + inprec_getstatus (txt); if (config_filename[0]) { _tcscat (txt, L"["); _tcscat (txt, config_filename); @@ -488,6 +491,11 @@ static void setmaintitle (HWND hwnd) SetWindowText (hwnd, txt); } +void refreshtitle (void) +{ + if (isfullscreen () == 0) + setmaintitle (hMainWnd); +} #ifndef AVIOUTPUT static int avioutput_video = 0; @@ -562,8 +570,10 @@ void setmouseactive (int active) if (mouseactive > 0) focus = 1; + if (focus) { int donotfocus = 0; + HWND f = GetFocus (); HWND fw = GetForegroundWindow (); HWND w1 = hAmigaWnd; HWND w2 = hMainWnd; @@ -572,16 +582,11 @@ void setmouseactive (int active) if (rp_isactive ()) w3 = rp_getparent (); #endif - if (isfullscreen () > 0 || (!(fw == w1 || fw == w2))) { - if (SetForegroundWindow (w2) == FALSE) { - if (SetForegroundWindow (w1) == FALSE) { - if (w3 == NULL || SetForegroundWindow (w3) == FALSE) { - donotfocus = 1; - write_log (L"wanted focus but SetForegroundWindow() failed\n"); - } - } - } - } + if (f != w1 && f != w2) + donotfocus = 1; + if (w3 != NULL && f == w3) + donotfocus = 0; + #ifdef RETROPLATFORM if (rp_isactive () && isfullscreen () == 0) donotfocus = 0; @@ -589,10 +594,11 @@ void setmouseactive (int active) if (isfullscreen () > 0) donotfocus = 0; if (donotfocus) { - focus = 0; + //focus = 0; mouseactive = 0; } } + if (mouseactive) { if (focus) { if (!showcursor) { @@ -743,6 +749,7 @@ void minimizewindow (void) void disablecapture (void) { setmouseactive (0); + focus = 0; } void gui_gameport_button_change (int port, int button, int onoff) @@ -1752,6 +1759,7 @@ int handle_msgpump (void) TranslateMessage (&msg); DispatchMessage (&msg); } + while (checkIPC (globalipc, &currprefs)); return got; } @@ -1792,11 +1800,13 @@ void handle_events (void) if (quit_program) break; } +#if 0 while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } while (checkIPC (globalipc, &currprefs)); +#endif if (was_paused) { resumepaused (was_paused); sound_closed = 0; @@ -2293,6 +2303,23 @@ void fullpath (TCHAR *path, int size) GetFullPathName (tmp, size, path, NULL); } } +void getpathpart (TCHAR *outpath, int size, const TCHAR *inpath) +{ + _tcscpy (outpath, inpath); + TCHAR *p = _tcsrchr (outpath, '\\'); + if (p) + p[0] = 0; + fixtrailing (outpath); +} +void getfilepart (TCHAR *out, int size, const TCHAR *path) +{ + out[0] = 0; + const TCHAR *p = _tcsrchr (path, '\\'); + if (p) + _tcscpy (out, p + 1); + else + _tcscpy (out, path); +} typedef DWORD (STDAPICALLTYPE *PFN_GetKey)(LPVOID lpvBuffer, DWORD dwSize); uae_u8 *target_load_keyfile (struct uae_prefs *p, const TCHAR *path, int *sizep, TCHAR *name) @@ -3063,6 +3090,10 @@ void fetch_statefilepath (TCHAR *out, int size) { fetch_path (L"StatefilePath", out, size); } +void fetch_inputfilepath (TCHAR *out, int size) +{ + fetch_path (L"InputPath", out, size); +} void fetch_datapath (TCHAR *out, int size) { fetch_path (NULL, out, size); @@ -4134,7 +4165,7 @@ static void getstartpaths (void) if (!_tcscmp (prevpath, L"AMIGAFOREVERDATA")) path_type = PATH_TYPE_AMIGAFOREVERDATA; - _tcscpy (start_path_exe, _wpgmptr); + GetFullPathName (_wpgmptr, sizeof start_path_exe / sizeof (TCHAR), start_path_exe, NULL); if((posn = _tcsrchr (start_path_exe, '\\'))) posn[1] = 0; @@ -4156,8 +4187,9 @@ static void getstartpaths (void) ispath = true; if (!ispath) { if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, tmp))) { + GetFullPathName (tmp, sizeof tmp / sizeof (TCHAR), tmp2, NULL); // installed in Program Files? - if (_tcsnicmp (tmp, start_path_exe, _tcslen (tmp)) == 0) { + if (_tcsnicmp (tmp, tmp2, _tcslen (tmp)) == 0) { if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, tmp))) { fixtrailing (tmp); _tcscpy (tmp2, tmp); @@ -4353,7 +4385,9 @@ static TCHAR *getdefaultini (void) { FILE *f; TCHAR path[MAX_DPATH], orgpath[MAX_DPATH]; - _tcscpy (path, _wpgmptr); + path[0] = 0; + if (!GetFullPathName (_wpgmptr, sizeof path / sizeof (TCHAR), path, NULL)) + _tcscpy (path, _wpgmptr); TCHAR *posn; if((posn = _tcsrchr (path, '\\'))) posn[1] = 0; @@ -4453,6 +4487,18 @@ static int parseargs (const TCHAR *argx, const TCHAR *np, const TCHAR *np2) log_net = 1; return 1; } + if (!_tcscmp (arg, L"a2065log")) { + log_a2065 = 1; + return 1; + } + if (!_tcscmp (arg, L"a2065log2")) { + log_a2065 = 2; + return 1; + } + if (!_tcscmp (arg, L"a2065_promiscuous")) { + a2065_promiscuous = 1; + return 1; + } if (!_tcscmp (arg, L"seriallog")) { log_uaeserial = 1; return 1; @@ -4591,6 +4637,10 @@ static int parseargs (const TCHAR *argx, const TCHAR *np, const TCHAR *np2) pissoff_value = getval (np); return 2; } + if (!_tcscmp (arg, L"inputrecorddebug")) { + inputrecord_debug = getval (np); + return 2; + } #ifdef RETROPLATFORM if (!_tcscmp (arg, L"rphost")) { rp_param = my_strdup (np); @@ -4793,12 +4843,11 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR for (i = 0; argv2[i]; i++) write_log (L"%d: '%s'\n", i + 1, argv2[i]); } - if (WIN32_RegisterClasses () && WIN32_InitLibraries () && DirectDraw_Start (NULL)) { + if (WIN32_RegisterClasses () && WIN32_InitLibraries ()) { DEVMODE devmode; DWORD i; WIN32_HandleRegistryStuff (); - DirectDraw_Release (); write_log (L"Enumerating display devices.. \n"); enumeratedisplays (multi_display); write_log (L"Sorting devices and modes..\n"); @@ -5028,7 +5077,8 @@ LONG WINAPI WIN32_ExceptionFilter (struct _EXCEPTION_POINTERS *pExceptionPointer if (ppc != regs.pc_p) { prevpc = (uae_u8*)ppc; } - exception2 (opc, (uaecptr)p); + m68k_setpc ((uaecptr)p); + exception2 (opc); lRet = EXCEPTION_CONTINUE_EXECUTION; } } diff --git a/od-win32/win32.h b/od-win32/win32.h index 2e3e1090..606ae212 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -15,11 +15,11 @@ #define GETBDM(x) (((x) - ((x / 10000) * 10000)) / 100) #define GETBDD(x) ((x) % 100) -#define WINUAEPUBLICBETA 0 +#define WINUAEPUBLICBETA 1 #define LANG_DLL 1 -#define WINUAEBETA L"" -#define WINUAEDATE MAKEBD(2010, 9, 24) +#define WINUAEBETA L"1" +#define WINUAEDATE MAKEBD(2010, 10, 23) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32_scaler.cpp b/od-win32/win32_scaler.cpp index 852a6035..9fa8aada 100644 --- a/od-win32/win32_scaler.cpp +++ b/od-win32/win32_scaler.cpp @@ -43,6 +43,7 @@ struct uae_filter uaefilters[] = static int filteroffsetx, filteroffsety, filterxmult = 1000, filterymult = 1000; static int dst_width, dst_height, amiga_width, amiga_height, amiga_depth, dst_depth, scale; +static int dst_width2, dst_height2, amiga_width2, amiga_height2, amiga_depth2, dst_depth2; static int temp_width, temp_height; uae_u8 *bufmem_ptr; static LPDIRECTDRAWSURFACE7 tempsurf; @@ -51,6 +52,7 @@ static int cleartemp; static uae_u32 rc[256], gc[256], bc[256]; static int deskw, deskh; static int d3d; +static bool inited; void getfilteroffset (int *dx, int *dy, int *mx, int *my) { @@ -188,8 +190,10 @@ void getfilterrect2 (RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height SetRect (zr, 0, 0, 0, 0); dr->left = (temp_width - aws) /2; dr->top = (temp_height - ahs) / 2; - dr->left -= (dst_width - aws) / 2; - dr->top -= (dst_height - ahs) / 2; + if (currprefs.gfx_xcenter_pos < 0) + dr->left -= (dst_width - aws) / 2; + if (currprefs.gfx_ycenter_pos < 0) + dr->top -= (dst_height - ahs) / 2; dr->right = dr->left + dst_width; dr->bottom = dr->top + dst_height; @@ -210,20 +214,39 @@ void getfilterrect2 (RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height dstratio = srcratio; } - if (currprefs.gfx_filter_autoscale) { + int scalemode = currprefs.gfx_filter_autoscale; + + if (scalemode == AUTOSCALE_STATIC_AUTO) { + if (currprefs.gfx_afullscreen) { + scalemode = AUTOSCALE_STATIC_NOMINAL; + } else { + int w1 = (800 / 2) << currprefs.gfx_resolution; + int w2 = (640 / 2) << currprefs.gfx_resolution; + int h1 = (600 / 2) << currprefs.gfx_vresolution; + int h2 = (480 / 2) << currprefs.gfx_vresolution; + int w = currprefs.gfx_size_win.width; + int h = currprefs.gfx_size_win.height; + if (w <= w1 && h <= h1 && w >= w2 && h >= h2) + scalemode = AUTOSCALE_NONE; + else + scalemode = AUTOSCALE_STATIC_NOMINAL; + } + } + + if (scalemode) { int cw, ch, cx, cy, cv; static int oxmult, oymult; filterxmult = 1000 / scale; filterymult = 1000 / scale; - if (currprefs.gfx_filter_autoscale == AUTOSCALE_STATIC_MAX || currprefs.gfx_filter_autoscale == AUTOSCALE_STATIC_NOMINAL) { + if (scalemode == AUTOSCALE_STATIC_MAX || scalemode == AUTOSCALE_STATIC_NOMINAL) { cw = (752 / 2) << currprefs.gfx_resolution; ch = (572 / 2) << currprefs.gfx_vresolution; cx = 0; cy = 0; cv = 1; - if (currprefs.gfx_filter_autoscale == AUTOSCALE_STATIC_NOMINAL) { + if (scalemode == AUTOSCALE_STATIC_NOMINAL) { cw -= 80; ch -= 50; cx = 56; @@ -236,7 +259,7 @@ void getfilterrect2 (RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height if (cv) { int diff; - if (currprefs.gfx_filter_autoscale == AUTOSCALE_CENTER) { + if (scalemode == AUTOSCALE_CENTER) { int ww = cw * scale; int hh = ch * scale; @@ -248,7 +271,8 @@ void getfilterrect2 (RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height OffsetRect (zr, cx * scale - (dst_width - ww) / 2, cy * scale - (dst_height - hh) / 2); goto cont; - } else if (currprefs.gfx_filter_autoscale == AUTOSCALE_RESIZE && isfullscreen () == 0 && !currprefs.gfx_filteroverlay[0]) { + } else if (scalemode == AUTOSCALE_RESIZE && isfullscreen () == 0 && !currprefs.gfx_filteroverlay[0]) { + static int lastresize = 0; static int lastdelay = 1; static int ocw, och, ocx, ocy, lcw, lch, lcx, lcy; @@ -520,6 +544,13 @@ void S2X_configure (int rb, int gb, int bb, int rs, int gs, int bs) bufmem_ptr = 0; } +void S2X_reset (void) +{ + if (!inited) + return; + S2X_init (dst_width2, dst_height2, amiga_width2, amiga_height2, dst_depth2, amiga_depth2); +} + void S2X_free (void) { changed_prefs.leds_on_screen = currprefs.leds_on_screen = currprefs.leds_on_screen & ~STATUSLINE_TARGET; @@ -535,6 +566,7 @@ void S2X_free (void) filterxmult = 1000; filterymult = 1000; scale = 1; + inited = false; } void S2X_init (int dw, int dh, int aw, int ah, int ad, int dd) @@ -542,6 +574,14 @@ void S2X_init (int dw, int dh, int aw, int ah, int ad, int dd) int flags = 0; int res_shift; + dst_width2 = dw; + dst_height2 = dh; + dst_depth2 = dd; + amiga_width2 = aw; + amiga_height2 = ah; + amiga_depth2 = ad; + + S2X_free (); d3d = currprefs.gfx_api; changed_prefs.leds_on_screen = currprefs.leds_on_screen = currprefs.leds_on_screen | STATUSLINE_TARGET; @@ -614,7 +654,7 @@ void S2X_init (int dw, int dh, int aw, int ah, int ad, int dd) } if (!tempsurf && !d3d) write_log (L"DDRAW: failed to create temp surface (%dx%d)\n", temp_width, temp_height); - + inited = true; } void S2X_render (void) diff --git a/od-win32/win32_uaenet.cpp b/od-win32/win32_uaenet.cpp index b599aa5b..4eb70591 100644 --- a/od-win32/win32_uaenet.cpp +++ b/od-win32/win32_uaenet.cpp @@ -405,7 +405,7 @@ struct netdriverdata *uaenet_enumerate (struct netdriverdata **out, const TCHAR tc->mac[0], tc->mac[1], tc->mac[2], tc->mac[3], tc->mac[4], tc->mac[5], cnt++); tc->active = 1; - tc->mtu = 1500; + tc->mtu = 1522; tc->name = au (d->name); tc->desc = au (d->description); } else { diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 750af36c..48fe2d79 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -631,73 +631,77 @@ void sortdisplays (void) md1->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES); md1->DisplayModes[0].depth = -1; md1->disabled = 1; - if (DirectDraw_Start (md1->primary ? NULL : &md1->guid)) { - if (SUCCEEDED (DirectDraw_GetDisplayMode ())) { - int w = DirectDraw_CurrentWidth (); - int h = DirectDraw_CurrentHeight (); - int b = DirectDraw_GetCurrentDepth (); - int maxw = 0, maxh = 0; - - DirectDraw_EnumDisplayModes (DDEDM_REFRESHRATES, modesCallback, md1); - idx2 = 0; - while (md1->DisplayModes[idx2].depth >= 0) { - struct PicassoResolution *pr = &md1->DisplayModes[idx2]; - if (pr->res.width > maxw) - maxw = pr->res.width; - if (pr->res.height > maxh) - maxh = pr->res.height; - idx2++; - } - write_log (L"Desktop: W=%d H=%d B=%d. MaxW=%d MaxH=%d CXVS=%d CYVS=%d\n", w, h, b, maxw, maxh, - GetSystemMetrics (SM_CXVIRTUALSCREEN), GetSystemMetrics (SM_CYVIRTUALSCREEN)); - idx = 0; - for (;;) { - int found; - DEVMODE dm; - dm.dmSize = sizeof dm; - dm.dmDriverExtra = 0; - if (!EnumDisplaySettingsEx (md1->primary ? NULL : md1->name3, idx, &dm, EDS_RAWMODE)) - break; - idx2 = 0; - found = 0; - while (md1->DisplayModes[idx2].depth >= 0 && !found) { - struct PicassoResolution *pr = &md1->DisplayModes[idx2]; - if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) { - for (i = 0; pr->refresh[i]; i++) { - if (pr->refresh[i] == dm.dmDisplayFrequency) { - found = 1; - break; - } - } + int w = GetSystemMetrics (SM_CXSCREEN); + int h = GetSystemMetrics (SM_CYSCREEN); + HDC hdc = GetDC (NULL); + int b = 0; + + if (hdc) { + b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); + ReleaseDC (NULL, hdc); + } + + int maxw = 0, maxh = 0; + if (DirectDraw_Start (NULL)) { + DirectDraw_EnumDisplayModes (DDEDM_REFRESHRATES, modesCallback, md1); + idx2 = 0; + while (md1->DisplayModes[idx2].depth >= 0) { + struct PicassoResolution *pr = &md1->DisplayModes[idx2]; + if (pr->res.width > maxw) + maxw = pr->res.width; + if (pr->res.height > maxh) + maxh = pr->res.height; + idx2++; + } + DirectDraw_Release (); + } + write_log (L"Desktop: W=%d H=%d B=%d. MaxW=%d MaxH=%d CXVS=%d CYVS=%d\n", w, h, b, maxw, maxh, + GetSystemMetrics (SM_CXVIRTUALSCREEN), GetSystemMetrics (SM_CYVIRTUALSCREEN)); + idx = 0; + for (;;) { + int found; + DEVMODE dm; + dm.dmSize = sizeof dm; + dm.dmDriverExtra = 0; + if (!EnumDisplaySettingsEx (md1->primary ? NULL : md1->name3, idx, &dm, EDS_RAWMODE)) + break; + idx2 = 0; + found = 0; + while (md1->DisplayModes[idx2].depth >= 0 && !found) { + struct PicassoResolution *pr = &md1->DisplayModes[idx2]; + if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) { + for (i = 0; pr->refresh[i]; i++) { + if (pr->refresh[i] == dm.dmDisplayFrequency) { + found = 1; + break; } - idx2++; } - if (!found && dm.dmBitsPerPel > 8) { - int freq = 0; + } + idx2++; + } + if (!found && dm.dmBitsPerPel > 8) { + int freq = 0; #if 0 - write_log (L"EnumDisplaySettings(%dx%dx%d %dHz %08x)\n", - dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency, dm.dmFields); + write_log (L"EnumDisplaySettings(%dx%dx%d %dHz %08x)\n", + dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency, dm.dmFields); #endif - if (dm.dmFields & DM_DISPLAYFREQUENCY) { - freq = dm.dmDisplayFrequency; - if (freq < 10) - freq = 0; - } - if (freq < 75 && dm.dmPelsWidth <= maxw && dm.dmPelsHeight <= maxh) { - if ((dm.dmFields & DM_PELSWIDTH) && (dm.dmFields & DM_PELSHEIGHT) && (dm.dmFields & DM_BITSPERPEL)) - addmode (md1, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, freq, 1); - } - } - idx++; + if (dm.dmFields & DM_DISPLAYFREQUENCY) { + freq = dm.dmDisplayFrequency; + if (freq < 10) + freq = 0; + } + if (freq < 75 && dm.dmPelsWidth <= maxw && dm.dmPelsHeight <= maxh) { + if ((dm.dmFields & DM_PELSWIDTH) && (dm.dmFields & DM_PELSHEIGHT) && (dm.dmFields & DM_BITSPERPEL)) + addmode (md1, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, freq, 1); } - //dhack(); - sortmodes (md1); - modesList (md1); - DirectDraw_Release (); - if (md1->DisplayModes[0].depth >= 0) - md1->disabled = 0; } + idx++; } + //dhack(); + sortmodes (md1); + modesList (md1); + if (md1->DisplayModes[0].depth >= 0) + md1->disabled = 0; i = 0; while (md1->DisplayModes[i].depth > 0) i++; @@ -1289,8 +1293,8 @@ int check_prefs_changed_gfx (void) c |= currprefs.gfx_filter_gamma != changed_prefs.gfx_filter_gamma ? (1|8) : 0; //c |= currprefs.gfx_filter_ != changed_prefs.gfx_filter_ ? (1|8) : 0; - c |= currprefs.gfx_resolution != changed_prefs.gfx_resolution ? (2 | 8) : 0; - c |= currprefs.gfx_vresolution != changed_prefs.gfx_vresolution ? (2 | 8) : 0; + c |= currprefs.gfx_resolution != changed_prefs.gfx_resolution ? (128) : 0; + c |= currprefs.gfx_vresolution != changed_prefs.gfx_vresolution ? (128) : 0; c |= currprefs.gfx_scanlines != changed_prefs.gfx_scanlines ? (2 | 8) : 0; c |= currprefs.gfx_lores_mode != changed_prefs.gfx_lores_mode ? (2 | 8) : 0; @@ -1379,6 +1383,14 @@ int check_prefs_changed_gfx (void) DirectDraw_Fill (NULL, 0); DirectDraw_BlitToPrimary (NULL); } + if (c & 128) { + if (currprefs.gfx_autoresolution) { + c |= 2 | 8; + } else { + drawing_init (); + S2X_reset (); + } + } if ((c & 16) || ((c & 8) && keepfsmode)) { if (reopen (c & 2)) c |= 2; @@ -1398,7 +1410,7 @@ int check_prefs_changed_gfx (void) if (currprefs.chipset_refreshrate != changed_prefs.chipset_refreshrate) { currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate; - init_hz (); + init_hz_full (); return 1; } @@ -2466,10 +2478,19 @@ static BOOL doInit (void) } else { #endif currentmode->native_depth = currentmode->current_depth; + gfxvidinfo.gfx_resolution_reserved = currprefs.gfx_resolution; + gfxvidinfo.gfx_vresolution_reserved = currprefs.gfx_vresolution; #if defined (GFXFILTER) if (currentmode->flags & (DM_D3D | DM_SWSCALE)) { - currentmode->amiga_width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution; - currentmode->amiga_height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution; + if (!currprefs.gfx_autoresolution) { + currentmode->amiga_width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution; + currentmode->amiga_height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution; + } else { + gfxvidinfo.gfx_resolution_reserved = currprefs.gfx_resolution == RES_SUPERHIRES ? RES_SUPERHIRES : RES_HIRES; + gfxvidinfo.gfx_vresolution_reserved = VRES_DOUBLE; + currentmode->amiga_width = AMIGA_WIDTH_MAX << gfxvidinfo.gfx_resolution_reserved; + currentmode->amiga_height = AMIGA_HEIGHT_MAX << gfxvidinfo.gfx_vresolution_reserved; + } if (currprefs.gfx_resolution == RES_SUPERHIRES) currentmode->amiga_height *= 2; if (currentmode->amiga_height > 960) diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 7563051e..97a76565 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -48,6 +48,7 @@ #include "filesys.h" #include "autoconf.h" #include "inputdevice.h" +#include "inputrecord.h" #include "xwin.h" #include "keyboard.h" #include "zfile.h" @@ -1280,7 +1281,7 @@ static int addrom (UAEREG *fkey, struct romdata *rd, const TCHAR *name) return 1; } -static int isromext (const TCHAR *path) +static int isromext (const TCHAR *path, bool deepscan) { const TCHAR *ext; int i; @@ -1297,6 +1298,8 @@ static int isromext (const TCHAR *path) return 1; if (_tcslen (ext) >= 2 && toupper(ext[0]) == 'U' && isdigit (ext[1])) return 1; + if (!deepscan) + return 0; for (i = 0; uae_archive_extensions[i]; i++) { if (!_tcsicmp (ext, uae_archive_extensions[i])) return 1; @@ -1379,7 +1382,7 @@ static int scan_rom_2 (struct zfile *f, void *vrsd) struct romdata *rd; scan_rom_hook (NULL, 0); - if (!isromext (path)) + if (!isromext (path, true)) return 0; rd = scan_single_rom_2 (f); if (rd) { @@ -1396,13 +1399,13 @@ static int scan_rom_2 (struct zfile *f, void *vrsd) return 0; } -static int scan_rom (const TCHAR *path, UAEREG *fkey) +static int scan_rom (const TCHAR *path, UAEREG *fkey, bool deepscan) { struct romscandata rsd = { fkey, 0 }; struct romdata *rd; int cnt = 0; - if (!isromext (path)) { + if (!isromext (path, deepscan)) { //write_log("ROMSCAN: skipping file '%s', unknown extension\n", path); return 0; } @@ -1499,7 +1502,7 @@ static void show_rom_list (void) free (p); } -static int scan_roms_2 (UAEREG *fkey, const TCHAR *path) +static int scan_roms_2 (UAEREG *fkey, const TCHAR *path, bool deepscan) { TCHAR buf[MAX_DPATH]; WIN32_FIND_DATA find_data; @@ -1521,7 +1524,7 @@ static int scan_roms_2 (UAEREG *fkey, const TCHAR *path) _tcscpy (tmppath, path); _tcscat (tmppath, find_data.cFileName); if (!(find_data.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |FILE_ATTRIBUTE_SYSTEM)) && find_data.nFileSizeLow < 10000000) { - if (scan_rom (tmppath, fkey)) + if (scan_rom (tmppath, fkey, deepscan)) ret = 1; } if (!scan_rom_hook (NULL, 0) || FindNextFile (handle, &find_data) == 0) { @@ -1538,6 +1541,7 @@ static int scan_roms_3 (UAEREG *fkey, TCHAR **paths, const TCHAR *path) { int i, ret; TCHAR pathp[MAX_DPATH]; + bool deepscan = true; ret = 0; scan_rom_hook (NULL, 0); @@ -1546,12 +1550,12 @@ static int scan_roms_3 (UAEREG *fkey, TCHAR **paths, const TCHAR *path) if (!pathp[0]) return ret; if (_tcsicmp (pathp, start_path_exe) == 0) - return ret; + deepscan = false; // do not scan root dir archives for (i = 0; i < MAX_ROM_PATHS; i++) { if (paths[i] && !_tcsicmp (paths[i], pathp)) return ret; } - ret = scan_roms_2 (fkey, pathp); + ret = scan_roms_2 (fkey, pathp, deepscan); for (i = 0; i < MAX_ROM_PATHS; i++) { if (!paths[i]) { paths[i] = my_strdup(pathp); @@ -2121,14 +2125,14 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs WIN32GUI_LoadUIString (IDS_ADF, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), DISK_FORMAT_STRING, sizeof (DISK_FORMAT_STRING) + sizeof (TCHAR)); - defext = L"ADF"; + defext = L"adf"; break; case 1: WIN32GUI_LoadUIString (IDS_CHOOSEBLANK, szTitle, MAX_DPATH); WIN32GUI_LoadUIString (IDS_ADF, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), L"(*.adf)\0*.adf\0", 15 * sizeof (TCHAR)); - defext = L"ADF"; + defext = L"adf"; break; case 2: case 3: @@ -2136,7 +2140,7 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs WIN32GUI_LoadUIString (IDS_HDF, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), HDF_FORMAT_STRING, sizeof (HDF_FORMAT_STRING) + sizeof (TCHAR)); - defext = L"HDF"; + defext = L"hdf"; break; case 4: case 5: @@ -2144,21 +2148,21 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs WIN32GUI_LoadUIString (IDS_UAE, szFormat, MAX_DPATH ); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), L"(*.uae)\0*.uae\0", 15 * sizeof (TCHAR)); - defext = L"UAE"; + defext = L"uae"; break; case 6: WIN32GUI_LoadUIString (IDS_SELECTROM, szTitle, MAX_DPATH); WIN32GUI_LoadUIString (IDS_ROM, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), ROM_FORMAT_STRING, sizeof (ROM_FORMAT_STRING) + sizeof (TCHAR)); - defext = L"ROM"; + defext = L"rom"; break; case 7: WIN32GUI_LoadUIString (IDS_SELECTKEY, szTitle, MAX_DPATH); WIN32GUI_LoadUIString (IDS_KEY, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), L"(*.key)\0*.key\0", 15 * sizeof (TCHAR)); - defext = L"KEY"; + defext = L"key"; break; case 15: case 16: @@ -2166,7 +2170,7 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs WIN32GUI_LoadUIString (IDS_INP, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), INP_FORMAT_STRING, sizeof (INP_FORMAT_STRING) + sizeof (TCHAR)); - defext = L"IMP"; + defext = L"inp"; break; case 9: case 10: @@ -2203,14 +2207,14 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs *p = 0; all = 0; } - defext = L"USS"; + defext = L"uss"; break; case 11: WIN32GUI_LoadUIString (IDS_SELECTFLASH, szTitle, MAX_DPATH); WIN32GUI_LoadUIString (IDS_FLASH, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), L"(*.nvr)\0*.nvr\0", 15 * sizeof (TCHAR)); - defext = L"NVR"; + defext = L"nvr"; break; case 8: default: @@ -2235,7 +2239,7 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs WIN32GUI_LoadUIString (IDS_CD, szFormat, MAX_DPATH); _stprintf (szFilter, L"%s ", szFormat); memcpy (szFilter + _tcslen (szFilter), CD_FORMAT_STRING, sizeof (CD_FORMAT_STRING) + sizeof (TCHAR)); - defext = L"CUE"; + defext = L"cue"; break; } if (all) { @@ -2338,8 +2342,10 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs selectdisk (prefs, hDlg, 3, IDC_DF3TEXT, full_path); break; case IDC_DOSAVESTATE: + savestate_initsave (full_path, openFileName.nFilterIndex, FALSE, true); + break; case IDC_DOLOADSTATE: - savestate_initsave (full_path, openFileName.nFilterIndex, FALSE); + savestate_initsave (full_path, openFileName.nFilterIndex, FALSE, false); break; case IDC_CREATE: { @@ -2386,13 +2392,11 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs _tcscpy (workprefs.cartfile, full_path); fullpath (workprefs.cartfile, MAX_DPATH); break; - case IDC_INPREC_PLAY: + case IDC_STATEREC_PLAY: + case IDC_STATEREC_RECORD: + case IDC_STATEREC_SAVE: _tcscpy (workprefs.inprecfile, full_path); - workprefs.inprecmode = ischecked (hDlg, IDC_INPREC_PLAYMODE) ? -1 : -2; - break; - case IDC_INPREC_RECORD: _tcscpy (workprefs.inprecfile, full_path); - workprefs.inprecmode = 1; break; } if (!nosavepath || 1) { @@ -5702,6 +5706,8 @@ static void values_to_displaydlg (HWND hDlg) CheckDlgButton (hDlg, IDC_XCENTER, workprefs.gfx_xcenter); CheckDlgButton (hDlg, IDC_YCENTER, workprefs.gfx_ycenter); + CheckDlgButton (hDlg, IDC_AUTORESOLUTION, workprefs.gfx_autoresolution); + SendDlgItemMessage(hDlg, IDC_DISPLAY_BUFFERCNT, CB_RESETCONTENT, 0, 0); WIN32GUI_LoadUIString(IDS_BUFFER_SINGLE, buffer, sizeof buffer / sizeof (TCHAR)); SendDlgItemMessage(hDlg, IDC_DISPLAY_BUFFERCNT, CB_ADDSTRING, 0, (LPARAM)buffer); @@ -5800,6 +5806,7 @@ static void values_from_displaydlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l workprefs.chipset_refreshrate = 0; workprefs.gfx_xcenter = ischecked (hDlg, IDC_XCENTER) ? 2 : 0; /* Smart centering */ workprefs.gfx_ycenter = ischecked (hDlg, IDC_YCENTER) ? 2 : 0; /* Smart centering */ + workprefs.gfx_autoresolution = ischecked (hDlg, IDC_AUTORESOLUTION); if (msg == WM_COMMAND && HIWORD (wParam) == CBN_SELCHANGE) { @@ -7169,16 +7176,11 @@ static void enable_for_miscdlg (HWND hDlg) ew (hDlg, IDC_DOSAVESTATE, TRUE); ew (hDlg, IDC_SCSIMODE, FALSE); ew (hDlg, IDC_CLOCKSYNC, FALSE); - ew (hDlg, IDC_STATE_CAPTURE, FALSE); - ew (hDlg, IDC_STATE_RATE, FALSE); - ew (hDlg, IDC_STATE_BUFFERSIZE, FALSE); } else { #if !defined (SCSIEMU) EnableWindow (GetDlgItem(hDlg, IDC_SCSIMODE), TRUE); #endif ew (hDlg, IDC_DOSAVESTATE, FALSE); - ew (hDlg, IDC_STATE_RATE, workprefs.statecapture ? TRUE : FALSE); - ew (hDlg, IDC_STATE_BUFFERSIZE, workprefs.statecapture ? TRUE : FALSE); } ew (hDlg, IDC_ASSOCIATELIST, !rp_isactive ()); ew (hDlg, IDC_ASSOCIATE_ON, !rp_isactive ()); @@ -7305,8 +7307,6 @@ static void misc_setlang (int v) static void values_to_miscdlg (HWND hDlg) { - TCHAR txt[100]; - if (currentpage == MISC1_ID) { CheckDlgButton (hDlg, IDC_FOCUSMINIMIZE, workprefs.win32_minimize_inactive); @@ -7321,7 +7321,6 @@ static void values_to_miscdlg (HWND hDlg) CheckDlgButton (hDlg, IDC_ALWAYSONTOP, workprefs.win32_alwaysontop); CheckDlgButton (hDlg, IDC_CLOCKSYNC, workprefs.tod_hack); CheckDlgButton (hDlg, IDC_POWERSAVE, workprefs.win32_powersavedisabled); - CheckDlgButton (hDlg, IDC_STATE_CAPTURE, workprefs.statecapture); CheckDlgButton (hDlg, IDC_FASTERRTG, workprefs.picasso96_nocustom); misc_kbled (hDlg, IDC_KBLED1, workprefs.keyboard_leds[0]); @@ -7329,24 +7328,6 @@ static void values_to_miscdlg (HWND hDlg) misc_kbled (hDlg, IDC_KBLED3, workprefs.keyboard_leds[2]); CheckDlgButton (hDlg, IDC_KBLED_USB, workprefs.win32_kbledmode); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_ADDSTRING, 0, (LPARAM)L"1"); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_ADDSTRING, 0, (LPARAM)L"5"); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_ADDSTRING, 0, (LPARAM)L"10"); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_ADDSTRING, 0, (LPARAM)L"20"); - SendDlgItemMessage (hDlg, IDC_STATE_RATE, CB_ADDSTRING, 0, (LPARAM)L"30"); - _stprintf (txt, L"%d", workprefs.statecapturerate / 50); - SendDlgItemMessage( hDlg, IDC_STATE_RATE, WM_SETTEXT, 0, (LPARAM)txt); - - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"5"); - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"10"); - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"20"); - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"50"); - SendDlgItemMessage (hDlg, IDC_STATE_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"100"); - _stprintf (txt, L"%d", workprefs.statecapturebuffersize / (1024 * 1024)); - SendDlgItemMessage( hDlg, IDC_STATE_BUFFERSIZE, WM_SETTEXT, 0, (LPARAM)txt); - misc_scsi (hDlg); misc_lang (hDlg); @@ -7355,6 +7336,13 @@ static void values_to_miscdlg (HWND hDlg) SendDlgItemMessage (hDlg, IDC_DXMODE, CB_ADDSTRING, 0, (LPARAM)L"Direct3D"); SendDlgItemMessage (hDlg, IDC_DXMODE, CB_SETCURSEL, workprefs.gfx_api, 0); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"NonLocalVRAM"); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"DefaultRAM *"); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"LocalVRAM"); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"SystemRAM"); + SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_SETCURSEL, ddforceram, 0); + SendDlgItemMessage (hDlg, IDC_WINDOWEDMODE, CB_RESETCONTENT, 0, 0); SendDlgItemMessage (hDlg, IDC_WINDOWEDMODE, CB_ADDSTRING, 0, (LPARAM)L"Borderless"); SendDlgItemMessage (hDlg, IDC_WINDOWEDMODE, CB_ADDSTRING, 0, (LPARAM)L"Minimal"); @@ -7364,13 +7352,6 @@ static void values_to_miscdlg (HWND hDlg) workprefs.win32_borderless ? 0 : (workprefs.win32_statusbar + 1), 0); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"NonLocalVRAM"); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"DefaultRAM *"); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"LocalVRAM"); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_ADDSTRING, 0, (LPARAM)L"SystemRAM"); - SendDlgItemMessage (hDlg, IDC_DD_SURFACETYPE, CB_SETCURSEL, ddforceram, 0); - } else if (currentpage == MISC2_ID) { CheckDlgButton (hDlg, IDC_INACTIVE_PAUSE, workprefs.win32_inactive_pause); @@ -7386,7 +7367,6 @@ static void values_to_miscdlg (HWND hDlg) static INT_PTR MiscDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { - TCHAR txt[100]; int v, i; static int recursive; @@ -7455,13 +7435,6 @@ static INT_PTR MiscDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) case IDC_KBLED3: misc_getkbled (hDlg, IDC_KBLED3, 2); break; - case IDC_STATE_RATE: - getcbn (hDlg, IDC_STATE_RATE, txt, sizeof (txt) / sizeof (TCHAR)); - workprefs.statecapturerate = _tstol (txt) * 50; - break; - case IDC_STATE_BUFFERSIZE: - getcbn (hDlg, IDC_STATE_BUFFERSIZE, txt, sizeof (txt) / sizeof (TCHAR)); - break; case IDC_LANGUAGE: if (HIWORD (wParam) == CBN_SELENDOK) { v = SendDlgItemMessage (hDlg, IDC_LANGUAGE, CB_GETCURSEL, 0, 0L); @@ -7529,10 +7502,6 @@ static INT_PTR MiscDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) if (DiskSelection(hDlg, wParam, 10, &workprefs, 0)) savestate_state = STATE_DORESTORE; break; - case IDC_STATE_CAPTURE: - workprefs.statecapture = ischecked (hDlg, IDC_STATE_CAPTURE); - enable_for_miscdlg (hDlg); - break; case IDC_ILLEGAL: workprefs.illegal_mem = ischecked (hDlg, IDC_ILLEGAL); break; @@ -10961,6 +10930,8 @@ static INT_PTR CALLBACK GamePortsDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); WIN32GUI_LoadUIString (IDS_JOYMODE_JOYSTICK, tmp, MAX_DPATH); SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); + WIN32GUI_LoadUIString (IDS_JOYMODE_GAMEPAD, tmp, MAX_DPATH); + SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); WIN32GUI_LoadUIString (IDS_JOYMODE_JOYSTICKANALOG, tmp, MAX_DPATH); SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp); WIN32GUI_LoadUIString (IDS_JOYMODE_MOUSE_CDTV, tmp, MAX_DPATH); @@ -12228,6 +12199,8 @@ static void values_to_hw3ddlg (HWND hDlg) SendDlgItemMessage (hDlg, IDC_FILTERAUTOSCALE, CB_RESETCONTENT, 0, 0L); WIN32GUI_LoadUIString (IDS_AUTOSCALE_DISABLED, txt, sizeof (txt) / sizeof (TCHAR)); SendDlgItemMessage (hDlg, IDC_FILTERAUTOSCALE, CB_ADDSTRING, 0, (LPARAM)txt); + WIN32GUI_LoadUIString (IDS_AUTOSCALE_DEFAULT, txt, sizeof (txt) / sizeof (TCHAR)); + SendDlgItemMessage (hDlg, IDC_FILTERAUTOSCALE, CB_ADDSTRING, 0, (LPARAM)txt); WIN32GUI_LoadUIString (IDS_AUTOSCALE_TV, txt, sizeof (txt) / sizeof (TCHAR)); SendDlgItemMessage (hDlg, IDC_FILTERAUTOSCALE, CB_ADDSTRING, 0, (LPARAM)txt); WIN32GUI_LoadUIString (IDS_AUTOSCALE_MAX, txt, sizeof (txt) / sizeof (TCHAR)); @@ -12834,6 +12807,9 @@ static void values_to_avioutputdlg (HWND hDlg) CheckDlgButton (hDlg, IDC_AVIOUTPUT_ACTIVATED, avioutput_requested ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton (hDlg, IDC_SCREENSHOT_ORIGINALSIZE, screenshot_originalsize ? TRUE : FALSE); CheckDlgButton (hDlg, IDC_SAMPLERIPPER_ACTIVATED, sampleripper_enabled ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hDlg, IDC_STATEREC_RECORD, input_record ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hDlg, IDC_STATEREC_PLAY, input_play ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hDlg, IDC_STATEREC_AUTOPLAY, workprefs.inprec_autoplay ? BST_CHECKED : BST_UNCHECKED); } static void values_from_avioutputdlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -12864,6 +12840,9 @@ static void enable_for_avioutputdlg (HWND hDlg) ew (hDlg, IDC_AVIOUTPUT_AUDIO_STATIC, TRUE); } + ew (hDlg, IDC_STATEREC_RATE, !input_record && full_property_sheet ? TRUE : FALSE); + ew (hDlg, IDC_STATEREC_BUFFERSIZE, !input_record && full_property_sheet ? TRUE : FALSE); + if (avioutput_audio == AVIAUDIO_WAV) { _tcscpy (tmp, L"Wave (internal)"); } else { @@ -12893,11 +12872,11 @@ static void enable_for_avioutputdlg (HWND hDlg) ew (hDlg, IDC_AVIOUTPUT_ACTIVATED, (!avioutput_audio && !avioutput_video) ? FALSE : TRUE); - ew (hDlg, IDC_INPREC_RECORD, input_recording >= 0); - CheckDlgButton (hDlg, IDC_INPREC_RECORD, input_recording > 0 ? BST_CHECKED : BST_UNCHECKED); - ew (hDlg, IDC_INPREC_PLAY, input_recording <= 0); - CheckDlgButton (hDlg, IDC_INPREC_PLAY, input_recording < 0 ? BST_CHECKED : BST_UNCHECKED); - ew (hDlg, IDC_INPREC_PLAYMODE, input_recording == 0); + CheckDlgButton (hDlg, IDC_STATEREC_RECORD, input_record ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hDlg, IDC_STATEREC_PLAY, input_play ? BST_CHECKED : BST_UNCHECKED); + ew (hDlg, IDC_STATEREC_RECORD, !(input_play == INPREC_PLAY_NORMAL && full_property_sheet)); + ew (hDlg, IDC_STATEREC_SAVE, input_record == INPREC_RECORD_RERECORD || input_record == INPREC_RECORD_PLAYING); + ew (hDlg, IDC_STATEREC_PLAY, input_record != INPREC_RECORD_RERECORD); } static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -12917,6 +12896,30 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP fetch_path (L"VideoPath", avioutput_filename, sizeof (avioutput_filename) / sizeof (TCHAR)); _tcscat (avioutput_filename, L"output.avi"); } + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"-"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"1"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"2"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"5"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"10"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"20"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"30"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_ADDSTRING, 0, (LPARAM)L"60"); + SendDlgItemMessage (hDlg, IDC_STATEREC_RATE, CB_SETCURSEL, 0, 0); + if (workprefs.statecapturerate > 0) { + _stprintf (tmp, L"%d", workprefs.statecapturerate / 50); + SendDlgItemMessage( hDlg, IDC_STATEREC_RATE, WM_SETTEXT, 0, (LPARAM)tmp); + } + + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"50"); + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"100"); + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"500"); + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"1000"); + SendDlgItemMessage (hDlg, IDC_STATEREC_BUFFERSIZE, CB_ADDSTRING, 0, (LPARAM)L"10000"); + _stprintf (tmp, L"%d", workprefs.statecapturebuffersize); + SendDlgItemMessage( hDlg, IDC_STATEREC_BUFFERSIZE, WM_SETTEXT, 0, (LPARAM)tmp); + case WM_USER: recursive++; @@ -12939,12 +12942,9 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP if(recursive > 0) break; - recursive++; - switch(wParam) { - case IDC_AVIOUTPUT_FRAMELIMITER: avioutput_framelimiter = ischecked (hDlg, IDC_AVIOUTPUT_FRAMELIMITER) ? 0 : 1; AVIOutput_SetSettings (); @@ -12965,22 +12965,47 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP screenshot_originalsize = ischecked (hDlg, IDC_SCREENSHOT_ORIGINALSIZE) ? 1 : 0; regsetint (NULL, L"Screenshot_Original", screenshot_originalsize); break; - - case IDC_INPREC_PLAYMODE: + case IDC_STATEREC_SAVE: + if (input_record > INPREC_RECORD_NORMAL) { + if (DiskSelection (hDlg, wParam, 16, &workprefs, NULL)) { + TCHAR tmp[MAX_DPATH]; + _tcscpy (tmp, workprefs.inprecfile); + _tcscat (tmp, L".uss"); + inprec_save (workprefs.inprecfile, tmp); + statefile_save_recording (tmp); + workprefs.inprecfile[0] = 0; + } + } break; - case IDC_INPREC_RECORD: - if (input_recording) - inprec_close (); - else - DiskSelection (hDlg, wParam, 16, &workprefs, NULL); + case IDC_STATEREC_RECORD: + { + if (input_play) { + inprec_playtorecord (); + } else if (input_record) { + inprec_close (true); + } else { + input_record = INPREC_RECORD_START; + set_special (SPCFLAG_MODE_CHANGE); + } break; - case IDC_INPREC_PLAY: - if (input_recording) - inprec_close (); - else - DiskSelection (hDlg, wParam, 15, &workprefs, NULL); + } + case IDC_STATEREC_AUTOPLAY: + workprefs.inprec_autoplay = ischecked (hDlg, IDC_STATEREC_AUTOPLAY) ? 1 : 0; + break; + case IDC_STATEREC_PLAY: + if (input_record) + inprec_close (true); + if (input_play) { + inprec_close (true); + } else { + inprec_close (true); + if (DiskSelection (hDlg, wParam, 15, &workprefs, NULL)) { + input_play = INPREC_PLAY_NORMAL; + _tcscpy (currprefs.inprecfile, workprefs.inprecfile); + set_special (SPCFLAG_MODE_CHANGE); + } + } break; - #ifdef PROWIZARD case IDC_PROWIZARD: moduleripper (); @@ -12993,15 +13018,12 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP case IDC_AVIOUTPUT_ACTIVATED: avioutput_requested = !avioutput_requested; - SendMessage (hDlg, WM_HSCROLL, (WPARAM) NULL, (LPARAM) NULL); if (!avioutput_requested) AVIOutput_End (); break; - case IDC_SCREENSHOT: screenshot(1, 0); break; - case IDC_AVIOUTPUT_AUDIO: { if (avioutput_enabled) @@ -13014,7 +13036,6 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP } break; } - case IDC_AVIOUTPUT_VIDEO: { if (avioutput_enabled) @@ -13030,7 +13051,6 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP enable_for_avioutputdlg (hDlg); break; } - case IDC_AVIOUTPUT_FILE: { OPENFILENAME ofn; @@ -13063,7 +13083,23 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP } break; } - + } + if (HIWORD (wParam) == CBN_SELENDOK || HIWORD (wParam) == CBN_KILLFOCUS || HIWORD (wParam) == CBN_EDITCHANGE) { + switch (LOWORD (wParam)) + { + case IDC_STATEREC_RATE: + getcbn (hDlg, IDC_STATEREC_RATE, tmp, sizeof tmp / sizeof (TCHAR)); + workprefs.statecapturerate = _tstol (tmp) * 50; + if (workprefs.statecapturerate <= 0) + workprefs.statecapturerate = -1; + break; + case IDC_STATEREC_BUFFERSIZE: + getcbn (hDlg, IDC_STATEREC_BUFFERSIZE, tmp, sizeof tmp / sizeof (TCHAR)); + workprefs.statecapturebuffersize = _tstol (tmp); + if (workprefs.statecapturebuffersize <= 0) + workprefs.statecapturebuffersize = 100; + break; + } } values_from_avioutputdlg (hDlg, msg, wParam, lParam); diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj b/od-win32/winuae_msvc10/winuae_msvc.vcxproj index e4646355..1d2aa945 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj @@ -551,6 +551,8 @@ + + diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters index 52500e76..e413e83b 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters @@ -487,6 +487,12 @@ win32 + + common + + + common + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 26e5aff3..77c0c21b 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,85 @@ +Beta 1 + +!!!!!! NOTE: Re-recorder discussion will be opened later in another thread. All posts related to new input recorder +in this thread will disappear. !!!!! + +- directory filesystem ACTION_LOCK_RECORD and ACTION_FREE_RECORD dos packets implemented (very rarely used) +- CDTV CDA playback didn't work if play ending track was set to last track (Prehistorik CDTV) +- reset CD support internal flags when reseting or loading new configuration +- save chipset extra setting to statefile, previously state restore always restored full + advanced chipset configuration and reset chipset extra setting +- 3-stage 68020 cycle-exact prefetch pipeline (not much difference compared to old one) +- do not emulate very small audio periods exactly in non-cycle exact modes, this combined with + very short samples used huge amounts of CPU power (used by some stupid audio routines) (2.3.0) +- when restoring state, sound was initialized after first frame, could have caused glitches + or missing sound if audio registers were modified during first frame +- mouse counters (JOYxDAT) were not restored from statefile, fixes random statefile restore mouse jump +- VPOSW ECS/AGA-only LOL-bit (long line) is hardwired to zero (can't be modified) in standard PAL mode +- SCSI emulation START/STOP UNIT translated to physical drive load/eject command +- combined volume and period modulation was broken in 2.3 audio update (probably never used in real world..) +- added "gamepad" device type to gameports panel, has two differences compared to "joystick", 3 buttons + mapped and pullup resistors emulated (most Amiga compatible gamepads have pullups). It is not possible + to have pullups automatically in joystick mode because it can break some badly programmed single-button + games, some detect always pressed button in this situation.. (fixes Aladdin and other games that + only have working 2nd button if buttons have pullup resistors) +- allow scanning of plain roms (no archives) in winuae root directory +- A2065 statefile support (autoconfig location saved), max allowed transmit size was too small, big packets + were silently dropped, random lost transmit interrupts, broadcast packets being ignored if NIC chip + hardware multicast filter was disabled +- change emulated board filesystem and Z3 board IDs because of ID conflicts with QuickNet Z2 board (2011/2) +- set default filter to 1x (was FS) and enable new "default" scaling method that only scales if window + size is set to "large enough" or so small that image wouldn't fit, always scales in fullscreen modes. +- "autoresolution" checkbox added to Display panel, automatically selects lowest used resolution setting + (lores screen = lores/nondoubled, lores and hires at the same time = hires/nondoubled etc..) Positioning + may not work correctly yet, glitches possible.. Enable some autoscaling settings if you don't want changing + display size.. +- do not attempt to steal focus in magic mouse mode if WinUAE is not active, it only messes up focus state +- A500 power led fade tricks should really work now +- less accurate CIA register access timing in JIT modes (not really much point in accuracy..) +- "re-recorder" implemented (completely rewritten combined input/state recorder). More information + coming later. + +- many statefile related changes for input/state recorder compatibility, may break something else.. + - WARNING: statefiles created with betas may not be compatible with future versions! + - save current track's data and density in statefile if disk drive motor was active (regenerated + raw track data/density after state restore may not be identical if using ipf or fdi images) + - state save/restore while disk DMA is active is now fully supported + - save strings in utf8 (should have been done long time ago during unicode updates..) + - useless DMAC chunk was saved in non-CDTV configurations (2.3.0) + - CD state chunks were saved even if selected configuration didn't have any CD drives (2.3.0) + - 68020 cache and prefetch pipeline saved and restored + - debugger memory watchpoints saved and restored + - save active (very rare) interrupt delays (interrupts that have been triggered but have not yet + been noticed by Paula) + - mid-instruction CPU state save support, restored state CPU state is now exactly same + as when state was saved (68000 CE only, 68020 CE later), previously current instruction + was simply restarted (this was really complex and non-trivial task, it is only easy if you + accept much higher CPU usage. Which isn't good idea...) + - full blitter statefile support in cycle exact mode, state capture/input recorder only currently. + This saves blitter emulation variables, not real hardware state (internal statemachine state, latches, + counters etc..) because internal structure is unknown. State capture only because it requires 100% + identical state after restore (normal blitter state forces current blit to finish). This is not + enabled in normal state saving because it is very difficult to keep state saving compatibility + between versions when state is hardcoded to current emulation implementation. + +- input recorder and state recorder completely rewritten and merged, it is now "re-recorder" + - desynch issues fixed + - input recording file is linked to statefile, statefile is automatically loaded with input file + - statefile/inputfile pair plus including all used disk images will be saved to disk when + "save recording" button is clicked (does not stop recording, can be saved multiple times) + - buffer size configuration replaced with number of states buffered (circular buffer) + - rewind operation change, less than 0.5s from latest state: remove newest state and jump to + previous state, more than 0.5s from last state: jump to newest save + - "rewind" = "Load previous state capture checkpoint" input event or "Load current state capture + cheakpoint" = "rewind" to newest capture checkpoint, never earlier + - rewind restore graphics glitches fixed + - cdtv/cd32 support (state recorder only, cd timing is not compatible with input recorder) + - automatic in-memory input recording, rewind automatically starts input recorder playback (if enabled), + any user input event (or end of input data) restarts recording. + - save checkpoints manually by using "Save state capture checkpoint" input event + + Final 2.3.0 Beta 20 (RC3): diff --git a/od-win32/writelog.cpp b/od-win32/writelog.cpp index e65ac284..dd20d17d 100644 --- a/od-win32/writelog.cpp +++ b/od-win32/writelog.cpp @@ -367,8 +367,8 @@ static TCHAR *writets (void) p += _tcslen (p); _stprintf (p, L"%03d", tb.millitm); p += _tcslen (p); - if (timeframes || (vpos > 0 && current_hpos () > 0)) - _stprintf (p, L" [%d %03dx%03d]", timeframes, current_hpos (), vpos); + if (vsync_counter != 0xffffffff) + _stprintf (p, L" [%d %03dx%03d]", vsync_counter, current_hpos (), vpos); _tcscat (p, L": "); return out; } diff --git a/savestate.cpp b/savestate.cpp index c25c82f9..6d24567a 100644 --- a/savestate.cpp +++ b/savestate.cpp @@ -61,27 +61,37 @@ #include "gui.h" #include "audio.h" #include "filesys.h" +#include "inputrecord.h" +#include "disk.h" int savestate_state = 0; +bool savestate_first_capture; + +static bool new_blitter = false; -#define MAX_STATERECORDS 1024 /* must be power of 2 */ -struct staterecord { - uae_u8 *start; - uae_u8 *end; - uae_u8 *next; - uae_u8 *cpu; -}; static int replaycounter; -static int replaylastreloaded = -1; -static int frameextra; struct zfile *savestate_file; -static uae_u8 *replaybuffer, *replaybufferend; static int savestate_docompress, savestate_specialdump, savestate_nodialogs; -static int replaybuffersize; TCHAR savestate_fname[MAX_DPATH]; -static struct staterecord staterecords[MAX_STATERECORDS]; + +#define STATEFILE_ALLOC_SIZE 600000 +static int statefile_alloc; +static int staterecords_max = 1000; +static int staterecords_first = 0; +static struct zfile *staterecord_statefile; +struct staterecord +{ + int len; + int inuse; + uae_u8 *cpu; + uae_u8 *data; + uae_u8 *end; + int inprecoffset; +}; + +static struct staterecord **staterecords; static void state_incompatible_warn (void) { @@ -122,6 +132,29 @@ static void state_incompatible_warn (void) /* functions for reading/writing bytes, shorts and longs in big-endian * format independent of host machine's endianess */ +static uae_u8 *storepos; +void save_store_pos_func (uae_u8 **dstp) +{ + storepos = *dstp; + *dstp += 4; +} +void save_store_size_func (uae_u8 **dstp) +{ + uae_u8 *p = storepos; + save_u32_func (&p, *dstp - storepos); +} +void restore_store_pos_func (uae_u8 **srcp) +{ + storepos = *srcp; + *srcp += 4; +} +void restore_store_size_func (uae_u8 **srcp) +{ + uae_u8 *p = storepos; + uae_u32 len = restore_u32_func (&p); + *srcp = storepos + len; +} + void save_u32_func (uae_u8 **dstp, uae_u32 v) { uae_u8 *dst = *dstp; @@ -153,7 +186,7 @@ void save_string_func (uae_u8 **dstp, const TCHAR *from) { uae_u8 *dst = *dstp; char *s, *s2; - s2 = s = ua (from); + s2 = s = uutf8 (from); while (s && *s) *dst++ = *s++; *dst++ = 0; @@ -209,7 +242,7 @@ TCHAR *restore_string_func (uae_u8 **dstp) *top++ = v; } while (v); *dstp = dst; - s = au (to); + s = utf8u (to); xfree (to); return s; } @@ -420,6 +453,7 @@ void restore_state (const TCHAR *filename) zfile_fseek (f, 0, SEEK_END); filesize = zfile_ftell (f); zfile_fseek (f, 0, SEEK_SET); + savestate_state = STATE_RESTORE; savestate_init (); chunk = restore_chunk (f, name, &len, &totallen, &filepos); @@ -427,6 +461,7 @@ void restore_state (const TCHAR *filename) write_log (L"%s is not an AmigaStateFile\n", filename); goto error; } + write_log (L"STATERESTORE:\n"); config_changed = 1; savestate_file = f; restore_header (chunk); @@ -439,7 +474,6 @@ void restore_state (const TCHAR *filename) changed_prefs.mbresmem_low_size = 0; changed_prefs.mbresmem_high_size = 0; z3num = 0; - savestate_state = STATE_RESTORE; for (;;) { name[0] = 0; chunk = end = restore_chunk (f, name, &len, &totallen, &filepos); @@ -482,10 +516,14 @@ void restore_state (const TCHAR *filename) restore_pram (totallen, filepos); continue; #endif + } else if (!_tcscmp (name, L"CYCS")) { + end = restore_cycles (chunk); } else if (!_tcscmp (name, L"CPU ")) { end = restore_cpu (chunk); } else if (!_tcscmp (name, L"CPUX")) end = restore_cpu_extra (chunk); + else if (!_tcscmp (name, L"CPUT")) + end = restore_cpu_trace (chunk); #ifdef FPUEMU else if (!_tcscmp (name, L"FPU ")) end = restore_fpu (chunk); @@ -522,6 +560,8 @@ void restore_state (const TCHAR *filename) end = restore_input (chunk); else if (!_tcscmp (name, L"CHPX")) end = restore_custom_extra (chunk); + else if (!_tcscmp (name, L"CHPD")) + end = restore_custom_event_delay (chunk); else if (!_tcscmp (name, L"AUD0")) end = restore_audio (0, chunk); else if (!_tcscmp (name, L"AUD1")) @@ -532,6 +572,8 @@ void restore_state (const TCHAR *filename) end = restore_audio (3, chunk); else if (!_tcscmp (name, L"BLIT")) end = restore_blitter (chunk); + else if (!_tcscmp (name, L"BLTX")) + end = restore_blitter_new (chunk); else if (!_tcscmp (name, L"DISK")) end = restore_floppy (chunk); else if (!_tcscmp (name, L"DSK0")) @@ -542,6 +584,14 @@ void restore_state (const TCHAR *filename) end = restore_disk (2, chunk); else if (!_tcscmp (name, L"DSK3")) end = restore_disk (3, chunk); + else if (!_tcscmp (name, L"DSD0")) + end = restore_disk2 (0, chunk); + else if (!_tcscmp (name, L"DSD1")) + end = restore_disk2 (1, chunk); + else if (!_tcscmp (name, L"DSD2")) + end = restore_disk2 (2, chunk); + else if (!_tcscmp (name, L"DSD3")) + end = restore_disk2 (3, chunk); else if (!_tcscmp (name, L"KEYB")) end = restore_keyboard (chunk); #ifdef AUTOCONFIG @@ -582,6 +632,12 @@ void restore_state (const TCHAR *filename) end = restore_ide (chunk); else if (!_tcsncmp (name, L"CDU", 3)) end = restore_cd (name[3] - '0', chunk); + else if (!_tcsncmp (name, L"2065", 4)) + end = restore_a2065 (chunk); + + else if (!_tcsncmp (name, L"DMWP", 4)) + end = restore_debug_memwatch (chunk); + else if (!_tcscmp (name, L"CONF")) end = restore_configuration (chunk); else if (!_tcscmp (name, L"LOG ")) @@ -598,11 +654,6 @@ void restore_state (const TCHAR *filename) name, totallen, end - chunk); xfree (chunk); } - restore_disk_finish (); - restore_blitter_finish (); - restore_akiko_finish (); - restore_cdtv_finish (); - restore_p96_finish (); target_addtorecent (filename, 0); return; @@ -617,17 +668,26 @@ error: void savestate_restore_finish (void) { - if (savestate_state != STATE_RESTORE && savestate_state != STATE_REWIND) + if (!isrestore ()) return; zfile_fclose (savestate_file); savestate_file = 0; - savestate_state = 0; restore_cpu_finish (); - init_hz (); + restore_audio_finish (); + restore_disk_finish (); + restore_blitter_finish (); + restore_akiko_finish (); + restore_cdtv_finish (); + restore_p96_finish (); + restore_a2065_finish (); + restore_cia_finish (); + savestate_state = 0; + init_hz_full (); + audio_activate (); } /* 1=compressed,2=not compressed,3=ram dump,4=audio dump */ -void savestate_initsave (const TCHAR *filename, int mode, int nodialogs) +void savestate_initsave (const TCHAR *filename, int mode, int nodialogs, bool save) { if (filename == NULL) { savestate_fname[0] = 0; @@ -640,6 +700,11 @@ void savestate_initsave (const TCHAR *filename, int mode, int nodialogs) savestate_docompress = (mode == 1) ? 1 : 0; savestate_specialdump = (mode == 3) ? 1 : (mode == 4) ? 2 : 0; savestate_nodialogs = nodialogs; + new_blitter = false; + if (save) { + savestate_free (); + inprec_close (true); + } } static void save_rams (struct zfile *f, int comp) @@ -675,52 +740,16 @@ static void save_rams (struct zfile *f, int comp) /* Save all subsystems */ -int save_state (const TCHAR *filename, const TCHAR *description) +static int save_state_internal (struct zfile *f, const TCHAR *description, int comp, bool savepath) { uae_u8 endhunk[] = { 'E', 'N', 'D', ' ', 0, 0, 0, 8 }; uae_u8 header[1000]; TCHAR tmp[100]; uae_u8 *dst; - struct zfile *f; - int len,i; TCHAR name[5]; - int comp = savestate_docompress; - - if (!savestate_specialdump && !savestate_nodialogs) { - state_incompatible_warn (); - if (!save_filesys_cando ()) { - gui_message (L"Filesystem active. Try again later"); - return -1; - } - } - savestate_nodialogs = 0; - custom_prepare_savestate (); - f = zfile_fopen (filename, L"w+b", 0); - if (!f) - return 0; - if (savestate_specialdump) { - size_t pos; - if (savestate_specialdump == 2) - write_wavheader (f, 0, 22050); - pos = zfile_ftell (f); - save_rams (f, -1); - if (savestate_specialdump == 2) { - int len, len2, i; - uae_u8 *tmp; - len = zfile_ftell (f) - pos; - tmp = xmalloc (uae_u8, len); - zfile_fseek(f, pos, SEEK_SET); - len2 = zfile_fread (tmp, 1, len, f); - for (i = 0; i < len2; i++) - tmp[i] += 0x80; - write_wavheader (f, len, 22050); - zfile_fwrite (tmp, len2, 1, f); - xfree (tmp); - } - zfile_fclose (f); - return 1; - } + int i, len; + write_log (L"STATESAVE (%s):\n", f ? zfile_getname (f) : L""); dst = header; save_u32 (0); save_string (L"UAE"); @@ -729,6 +758,10 @@ int save_state (const TCHAR *filename, const TCHAR *description) save_string (description); save_chunk (f, header, dst-header, L"ASF ", 0); + dst = save_cycles (&len, 0); + save_chunk (f, dst, len, L"CYCS", 0); + xfree (dst); + dst = save_cpu (&len, 0); save_chunk (f, dst, len, L"CPU ", 0); xfree (dst); @@ -737,6 +770,10 @@ int save_state (const TCHAR *filename, const TCHAR *description) save_chunk (f, dst, len, L"CPUX", 0); xfree (dst); + dst = save_cpu_trace (&len, 0); + save_chunk (f, dst, len, L"CPUT", 0); + xfree (dst); + #ifdef FPUEMU dst = save_fpu (&len,0 ); save_chunk (f, dst, len, L"FPU ", 0); @@ -751,21 +788,28 @@ int save_state (const TCHAR *filename, const TCHAR *description) _tcscpy(name, L"DSKx"); for (i = 0; i < 4; i++) { - dst = save_disk (i, &len, 0); + dst = save_disk (i, &len, 0, savepath); if (dst) { name[3] = i + '0'; save_chunk (f, dst, len, name, 0); xfree (dst); } } + _tcscpy(name, L"DSDx"); + for (i = 0; i < 4; i++) { + dst = save_disk2 (i, &len, 0); + if (dst) { + name[3] = i + '0'; + save_chunk (f, dst, len, name, comp); + xfree (dst); + } + } + + dst = save_floppy (&len, 0); save_chunk (f, dst, len, L"DISK", 0); xfree (dst); - dst = save_blitter (&len, 0); - save_chunk (f, dst, len, L"BLIT", 0); - xfree (dst); - dst = save_custom (&len, 0, 0); save_chunk (f, dst, len, L"CHIP", 0); xfree (dst); @@ -774,6 +818,19 @@ int save_state (const TCHAR *filename, const TCHAR *description) save_chunk (f, dst, len, L"CHPX", 0); xfree (dst); + dst = save_custom_event_delay (&len, 0); + save_chunk (f, dst, len, L"CHPD", 0); + xfree (dst); + + dst = save_blitter_new (&len, 0); + save_chunk (f, dst, len, L"BLTX", 0); + xfree (dst); + if (new_blitter == false) { + dst = save_blitter (&len, 0); + save_chunk (f, dst, len, L"BLIT", 0); + xfree (dst); + } + dst = save_input (&len, 0); save_chunk (f, dst, len, L"CINP", 0); xfree (dst); @@ -806,7 +863,7 @@ int save_state (const TCHAR *filename, const TCHAR *description) save_chunk (f, dst, len, L"CIAB", 0); xfree (dst); - dst = save_keyboard (&len); + dst = save_keyboard (&len, NULL); save_chunk (f, dst, len, L"KEYB", 0); xfree (dst); @@ -814,6 +871,8 @@ int save_state (const TCHAR *filename, const TCHAR *description) dst = save_expansion (&len, 0); save_chunk (f, dst, len, L"EXPA", 0); #endif + dst = save_a2065 (&len, NULL); + save_chunk (f, dst, len, L"2065", 0); #ifdef PICASSO96 dst = save_p96 (&len, 0); save_chunk (f, dst, len, L"P96 ", 0); @@ -829,23 +888,23 @@ int save_state (const TCHAR *filename, const TCHAR *description) } while ((dst = save_rom (0, &len, 0))); #ifdef CD32 - dst = save_akiko (&len); + dst = save_akiko (&len, NULL); save_chunk (f, dst, len, L"CD32", 0); xfree (dst); #endif #ifdef CDTV - dst = save_cdtv (&len); + dst = save_cdtv (&len, NULL); save_chunk (f, dst, len, L"CDTV", 0); xfree (dst); - dst = save_dmac (&len); + dst = save_dmac (&len, NULL); save_chunk (f, dst, len, L"DMAC", 0); xfree (dst); #endif #ifdef ACTION_REPLAY - dst = save_action_replay (&len, 0); + dst = save_action_replay (&len, NULL); save_chunk (f, dst, len, L"ACTR", comp); - dst = save_hrtmon (&len, 0); + dst = save_hrtmon (&len, NULL); save_chunk (f, dst, len, L"HRTM", comp); #endif #ifdef FILESYS @@ -861,13 +920,13 @@ int save_state (const TCHAR *filename, const TCHAR *description) } } #endif - dst = save_gayle (&len); + dst = save_gayle (&len, NULL); if (dst) { save_chunk (f, dst, len, L"GAYL", 0); xfree(dst); } for (i = 0; i < 4; i++) { - dst = save_ide (i, &len); + dst = save_ide (i, &len, NULL); if (dst) { save_chunk (f, dst, len, L"IDE ", 0); xfree (dst); @@ -882,6 +941,12 @@ int save_state (const TCHAR *filename, const TCHAR *description) } } + dst = save_debug_memwatch (&len, NULL); + if (dst) { + save_chunk (f, dst, len, L"DMWP", 0); + xfree(dst); + } + /* add fake END tag, makes it easy to strip CONF and LOG hunks */ /* move this if you want to use CONF or LOG hunks when restoring state */ zfile_fwrite (endhunk, 1, 8, f); @@ -899,10 +964,55 @@ int save_state (const TCHAR *filename, const TCHAR *description) zfile_fwrite (endhunk, 1, 8, f); - write_log (L"Save of '%s' complete\n", filename); + return 1; +} + +int save_state (const TCHAR *filename, const TCHAR *description) +{ + struct zfile *f; + int comp = savestate_docompress; + + if (!savestate_specialdump && !savestate_nodialogs) { + state_incompatible_warn (); + if (!save_filesys_cando ()) { + gui_message (L"Filesystem active. Try again later."); + return -1; + } + } + new_blitter = false; + savestate_nodialogs = 0; + custom_prepare_savestate (); + f = zfile_fopen (filename, L"w+b", 0); + if (!f) + return 0; + if (savestate_specialdump) { + size_t pos; + if (savestate_specialdump == 2) + write_wavheader (f, 0, 22050); + pos = zfile_ftell (f); + save_rams (f, -1); + if (savestate_specialdump == 2) { + int len, len2, i; + uae_u8 *tmp; + len = zfile_ftell (f) - pos; + tmp = xmalloc (uae_u8, len); + zfile_fseek(f, pos, SEEK_SET); + len2 = zfile_fread (tmp, 1, len, f); + for (i = 0; i < len2; i++) + tmp[i] += 0x80; + write_wavheader (f, len, 22050); + zfile_fwrite (tmp, len2, 1, f); + xfree (tmp); + } + zfile_fclose (f); + return 1; + } + int v = save_state_internal (f, description, comp, true); + if (v) + write_log (L"Save of '%s' complete\n", filename); zfile_fclose (f); savestate_state = 0; - return 1; + return v; } void savestate_quick (int slot, int save) @@ -937,29 +1047,54 @@ void savestate_quick (int slot, int save) } } -static struct staterecord *canrewind (int pos) +bool savestate_check (void) { - int i; - struct staterecord *st; + if (vpos == 0 && !savestate_state) { + if (hsync_counter == 0 && input_play == INPREC_PLAY_NORMAL) + savestate_memorysave (); + savestate_capture (0); + } + if (savestate_state == STATE_DORESTORE) { + savestate_state = STATE_RESTORE; + return true; + } else if (savestate_state == STATE_DOREWIND) { + savestate_state = STATE_REWIND; + return true; + } + return false; +} + +static int rewindmode; - if (!replaybuffer) + +static struct staterecord *canrewind (int pos) +{ + if (pos < 0) + pos += staterecords_max; + if (!staterecords) return 0; - i = replaycounter; - st = &staterecords[i]; - if (st->start) - return st; - return 0; + if (staterecords[pos] == NULL) + return NULL; + if (staterecords[pos]->inuse == 0) + return NULL; + if ((pos + 1) % staterecords_max == staterecords_first) + return NULL; + return staterecords[pos]; } int savestate_dorewind (int pos) { + rewindmode = pos; + if (pos < 0) + pos = replaycounter - 1; if (canrewind (pos)) { savestate_state = STATE_DOREWIND; + write_log (L"dorewind %d (%010d/%03d) -> %d\n", replaycounter - 1, hsync_counter, vsync_counter, pos); return 1; } return 0; } - +#if 0 void savestate_listrewind (void) { int i = replaycounter; @@ -982,33 +1117,55 @@ void savestate_listrewind (void) i += MAX_STATERECORDS; } } +#endif void savestate_rewind (void) { int len, i, dummy; uae_u8 *p, *p2; struct staterecord *st; + int pos; + bool rewind = false; - st = canrewind (1); - if (!st) - return; - frameextra = timeframes % currprefs.statecapturerate; - p = st->start; + if (hsync_counter % currprefs.statecapturerate <= 25 && rewindmode <= -2) { + pos = replaycounter - 2; + rewind = true; + } else { + pos = replaycounter - 1; + } + st = canrewind (pos); + if (!st) { + rewind = false; + pos = replaycounter - 1; + st = canrewind (pos); + if (!st) + return; + } + p = st->data; p2 = st->end; - write_log (L"rewinding from %d\n", replaycounter); + write_log (L"rewinding %d -> %d\n", replaycounter - 1, pos); + hsync_counter = restore_u32_func (&p); + vsync_counter = restore_u32_func (&p); p = restore_cpu (p); + p = restore_cycles (p); p = restore_cpu_extra (p); + if (restore_u32_func (&p)) + p = restore_cpu_trace (p); #ifdef FPUEMU if (restore_u32_func (&p)) p = restore_fpu (p); #endif for (i = 0; i < 4; i++) { p = restore_disk (i, p); + if (restore_u32_func (&p)) + p = restore_disk2 (i, p); } p = restore_floppy (p); p = restore_custom (p); p = restore_custom_extra (p); - p = restore_blitter (p); + if (restore_u32_func (&p)) + p = restore_custom_event_delay (p); + p = restore_blitter_new (p); p = restore_custom_agacolors (p); for (i = 0; i < 8; i++) { p = restore_custom_sprite (i, p); @@ -1018,8 +1175,14 @@ void savestate_rewind (void) } p = restore_cia (0, p); p = restore_cia (1, p); + p = restore_keyboard (p); + p = restore_inputstate (p); #ifdef AUTOCONFIG p = restore_expansion (p); +#endif +#ifdef PICASSO96 + if (restore_u32_func (&p)) + p = restore_p96 (p); #endif len = restore_u32_func (&p); memcpy (chipmemory, p, currprefs.chipmem_size > len ? len : currprefs.chipmem_size); @@ -1038,70 +1201,144 @@ void savestate_rewind (void) #ifdef ACTION_REPLAY if (restore_u32_func (&p)) p = restore_action_replay (p); + if (restore_u32_func (&p)) + p = restore_hrtmon (p); +#endif +#ifdef CD32 + if (restore_u32_func (&p)) + p = restore_akiko (p); +#endif +#ifdef CDTV + if (restore_u32_func (&p)) + p = restore_cdtv (p); + if (restore_u32_func (&p)) + p = restore_dmac (p); #endif + if (restore_u32_func (&p)) + p = restore_gayle (p); + for (i = 0; i < 4; i++) { + if (restore_u32_func (&p)) + p = restore_ide (p); + } p += 4; if (p != p2) { gui_message (L"reload failure, address mismatch %p != %p", p, p2); uae_reset (0); return; } - st->start = st->next = 0; - replaycounter--; - if (replaycounter < 0) - replaycounter += MAX_STATERECORDS; + inprec_setposition (st->inprecoffset, pos); + write_log (L"state %d restored. (%010d/%03d)\n", pos, hsync_counter, vsync_counter); + if (rewind) { + replaycounter--; + if (replaycounter < 0) + replaycounter += staterecords_max; + st = canrewind (replaycounter); + st->inuse = 0; + } + } #define BS 10000 -static int bufcheck (uae_u8 **pp, int len) +STATIC_INLINE int bufcheck (struct staterecord *sr, uae_u8 *p, int len) { - uae_u8 *p = *pp; - if (p + len + BS >= replaybuffer + replaybuffersize) { - //write_log (L"capture buffer wrap-around\n"); + if (p - sr->data + BS + len >= sr->len) return 1; - } return 0; } +void savestate_memorysave (void) +{ + new_blitter = true; + // create real statefile in memory too for later saving + zfile_fclose (staterecord_statefile); + staterecord_statefile = zfile_fopen_empty (NULL, L"statefile.inp.uss"); + if (staterecord_statefile) + save_state_internal (staterecord_statefile, L"rerecording", 1, false); +} + void savestate_capture (int force) { uae_u8 *p, *p2, *p3, *dst; int i, len, tlen, retrycnt; - struct staterecord *st, *stn; + struct staterecord *st; + bool firstcapture = false; #ifdef FILESYS if (nr_units ()) return; #endif - if (!replaybuffer) + if (!staterecords) return; - if (!force && (!currprefs.statecapture || !currprefs.statecapturerate || ((timeframes + frameextra) % currprefs.statecapturerate))) + if (!input_record) return; + if (currprefs.statecapturerate && hsync_counter == 0 && input_record == INPREC_RECORD_START && savestate_first_capture) { + // first capture + force = true; + firstcapture = true; + savestate_first_capture = false; + } + if (!force) { + if (currprefs.statecapturerate <= 0) + return; + if (hsync_counter % currprefs.statecapturerate) + return; + } retrycnt = 0; retry2: - st = &staterecords[replaycounter]; - if (st->next == 0) { - replaycounter = 0; - st = &staterecords[replaycounter]; - st->next = replaybuffer; + st = staterecords[replaycounter]; + if (st == NULL) { + st = (struct staterecord*)xmalloc (uae_u8, statefile_alloc); + st->len = statefile_alloc; + } else if (retrycnt > 0) { + st->len += STATEFILE_ALLOC_SIZE; + st = (struct staterecord*)xrealloc (uae_u8, st, st->len); } - stn = &staterecords[(replaycounter + 1) & (MAX_STATERECORDS - 1)]; - p = p2 = st->next; + if (st->len > statefile_alloc) + statefile_alloc = st->len; + st->inuse = 0; + st->data = (uae_u8*)(st + 1); + staterecords[replaycounter] = st; + retrycnt++; + p = p2 = st->data; tlen = 0; - if (bufcheck (&p, 0)) + save_u32_func (&p, hsync_counter); + save_u32_func (&p, vsync_counter); + tlen += 8; + + if (bufcheck (st, p, 0)) goto retry; - stn->cpu = p; + st->cpu = p; save_cpu (&len, p); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) + goto retry; + save_cycles (&len, p); + tlen += len; + p += len; + + if (bufcheck (st, p, 0)) goto retry; save_cpu_extra (&len, p); tlen += len; p += len; + + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_cpu_trace (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } + #ifdef FPUEMU - if (bufcheck (&p, 0)) + if (bufcheck (st, p, 0)) goto retry; p3 = p; save_u32_func (&p, 0); @@ -1113,77 +1350,128 @@ retry2: } #endif for (i = 0; i < 4; i++) { - if (bufcheck (&p, 0)) + if (bufcheck (st, p, 0)) goto retry; - save_disk (i, &len, p); + save_disk (i, &len, p, true); tlen += len; p += len; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_disk2 (i, &len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } } - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) goto retry; save_floppy (&len, p); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) goto retry; save_custom (&len, p, 0); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) goto retry; save_custom_extra (&len, p); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_custom_event_delay (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } + + if (bufcheck (st, p, 0)) goto retry; - save_blitter (&len, p); + save_blitter_new (&len, p); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, 0)) goto retry; save_custom_agacolors (&len, p); tlen += len; p += len; for (i = 0; i < 8; i++) { - if (bufcheck (&p, 0)) + if (bufcheck (st, p, 0)) goto retry; save_custom_sprite (i, &len, p); tlen += len; p += len; } + for (i = 0; i < 4; i++) { - if (bufcheck (&p, 0)) + if (bufcheck (st, p, 0)) goto retry; save_audio (i, &len, p); tlen += len; p += len; } - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, len)) goto retry; save_cia (0, &len, p); tlen += len; p += len; - if (bufcheck (&p, 0)) + + if (bufcheck (st, p, len)) goto retry; save_cia (1, &len, p); tlen += len; p += len; + + if (bufcheck (st, p, len)) + goto retry; + save_keyboard (&len, p); + tlen += len; + p += len; + + if (bufcheck (st, p, len)) + goto retry; + save_inputstate (&len, p); + tlen += len; + p += len; #ifdef AUTOCONFIG - if (bufcheck (&p, 0)) + if (bufcheck (st, p, len)) goto retry; save_expansion (&len, p); tlen += len; p += len; +#endif +#ifdef PICASSO96 + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_p96 (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } #endif dst = save_cram (&len); - if (bufcheck (&p, len)) + if (bufcheck (st, p, len)) goto retry; save_u32_func (&p, len); memcpy (p, dst, len); tlen += len + 4; p += len; dst = save_bram (&len); - if (bufcheck (&p, len)) + if (bufcheck (st, p, len)) goto retry; save_u32_func (&p, len); memcpy (p, dst, len); @@ -1191,14 +1479,14 @@ retry2: p += len; #ifdef AUTOCONFIG dst = save_fram (&len); - if (bufcheck (&p, len)) + if (bufcheck (st, p, len)) goto retry; save_u32_func (&p, len); memcpy (p, dst, len); tlen += len + 4; p += len; dst = save_zram (&len, 0); - if (bufcheck (&p, len)) + if (bufcheck (st, p, len)) goto retry; save_u32_func (&p, len); memcpy (p, dst, len); @@ -1206,7 +1494,7 @@ retry2: p += len; #endif #ifdef ACTION_REPLAY - if (bufcheck (&p, 0)) + if (bufcheck (st, p, 0)) goto retry; p3 = p; save_u32_func (&p, 0); @@ -1216,58 +1504,151 @@ retry2: tlen += len; p += len; } + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_hrtmon (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } #endif +#ifdef CD32 + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_akiko (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } +#endif +#ifdef CDTV + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_cdtv (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_dmac (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } +#endif + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_gayle (&len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } + for (i = 0; i < 4; i++) { + if (bufcheck (st, p, 0)) + goto retry; + p3 = p; + save_u32_func (&p, 0); + tlen += 4; + if (save_ide (i, &len, p)) { + save_u32_func (&p3, 1); + tlen += len; + p += len; + } + } save_u32_func (&p, tlen); - stn->next = p; - stn->start = p2; - stn->end = p; - replaylastreloaded = -1; + st->end = p; + st->inuse = 1; + st->inprecoffset = inprec_getposition (); + replaycounter++; - replaycounter &= (MAX_STATERECORDS - 1); - i = (replaycounter + 1) & (MAX_STATERECORDS - 1); - staterecords[i].next = staterecords[i].start = 0; - i = replaycounter - 1; - while (i != replaycounter) { - if (i < 0) - i += MAX_STATERECORDS; - st = &staterecords[i]; - if (p2 <= st->start && p >= st->end) { - st->start = st->next = 0; - break; + if (replaycounter >= staterecords_max) + replaycounter -= staterecords_max; + if (replaycounter == staterecords_first) { + staterecords_first++; + if (staterecords_first >= staterecords_max) + staterecords_first -= staterecords_max; + } + + write_log (L"state capture %d (%010d/%03d,%d/%d) (%d bytes, alloc %d)\n", + replaycounter, hsync_counter, vsync_counter, + hsync_counter % current_maxvpos (), current_maxvpos (), + st->end - st->data, statefile_alloc); + + if (firstcapture) { + savestate_memorysave (); + input_record++; + for (i = 0; i < 4; i++) { + bool wp = true; + DISK_validate_filename (currprefs.floppyslots[i].df, false, &wp, NULL, NULL); + inprec_recorddiskchange (i, currprefs.floppyslots[i].df, wp); } - i--; + input_record--; } - //write_log (L"state capture %d (%d bytes)\n", replaycounter, p - p2); + + return; retry: - staterecords[replaycounter].next = replaybuffer; - retrycnt++; - if (retrycnt > 1) { - write_log (L"can't save, too small capture buffer\n"); - return; - } - goto retry2; + if (retrycnt < 10) + goto retry2; + write_log (L"can't save, too small capture buffer or out of memory\n"); + return; } void savestate_free (void) { - xfree (replaybuffer); - replaybuffer = 0; + xfree (staterecords); + staterecords = NULL; } void savestate_init (void) { savestate_free (); - memset (staterecords, 0, sizeof (staterecords)); replaycounter = 0; - replaylastreloaded = -1; - frameextra = 0; - if (currprefs.statecapture && currprefs.statecapturebuffersize && currprefs.statecapturerate) { - replaybuffersize = currprefs.statecapturebuffersize; - replaybuffer = xmalloc (uae_u8, replaybuffersize); + staterecords_max = currprefs.statecapturebuffersize; + if (input_record && savestate_state != STATE_DORESTORE) { + zfile_fclose (staterecord_statefile); + staterecord_statefile = NULL; + inprec_close (false); + staterecords = xcalloc (struct staterecord*, staterecords_max); + statefile_alloc = STATEFILE_ALLOC_SIZE; + inprec_open (NULL, NULL); + savestate_first_capture = true; } } + +void statefile_save_recording (const TCHAR *filename) +{ + if (!staterecord_statefile) + return; + struct zfile *zf = zfile_fopen (filename, L"wb", 0); + if (zf) { + int len = zfile_size (staterecord_statefile); + uae_u8 *data = zfile_getdata (staterecord_statefile, 0, len); + zfile_fwrite (data, len, 1, zf); + xfree (data); + zfile_fclose (zf); + write_log (L"input statefile '%s' saved\n", filename); + } +} + + /* My (Toni Wilen ) diff --git a/statusline.cpp b/statusline.cpp new file mode 100644 index 00000000..27d85220 --- /dev/null +++ b/statusline.cpp @@ -0,0 +1,213 @@ +#include "sysconfig.h" +#include "sysdeps.h" + +#include +#include + +#include "options.h" +#include "uae.h" +#include "xwin.h" +#include "gui.h" +#include "custom.h" +#include "drawing.h" +#include "statusline.h" + +/* +* Some code to put status information on the screen. +*/ + +static const char *numbers = { /* ugly 0123456789CHD%+- */ + "+++++++--++++-+++++++++++++++++-++++++++++++++++++++++++++++++++++++++++++++-++++++-++++----++---+--------------" + "+xxxxx+--+xx+-+xxxxx++xxxxx++x+-+x++xxxxx++xxxxx++xxxxx++xxxxx++xxxxx++xxxx+-+x++x+-+xxx++-+xx+-+x---+----------" + "+x+++x+--++x+-+++++x++++++x++x+++x++x++++++x++++++++++x++x+++x++x+++x++x++++-+x++x+-+x++x+--+x++x+--+x+----+++--" + "+x+-+x+---+x+-+xxxxx++xxxxx++xxxxx++xxxxx++xxxxx+--++x+-+xxxxx++xxxxx++x+----+xxxx+-+x++x+----+x+--+xxx+--+xxx+-" + "+x+++x+---+x+-+x++++++++++x++++++x++++++x++x+++x+--+x+--+x+++x++++++x++x++++-+x++x+-+x++x+---+x+x+--+x+----+++--" + "+xxxxx+---+x+-+xxxxx++xxxxx+----+x++xxxxx++xxxxx+--+x+--+xxxxx++xxxxx++xxxx+-+x++x+-+xxx+---+x++xx--------------" + "+++++++---+++-++++++++++++++----+++++++++++++++++--+++--++++++++++++++++++++-++++++-++++------------------------" +}; + +STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a) +{ + uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff]; + if (a) + v |= a[255 - ((c >> 24) & 0xff)]; + return v; +} + +static void write_tdnumber (uae_u8 *buf, int bpp, int x, int y, int num, uae_u32 c1, uae_u32 c2) +{ + int j; + const char *numptr; + + numptr = numbers + num * TD_NUM_WIDTH + NUMBERS_NUM * TD_NUM_WIDTH * y; + for (j = 0; j < TD_NUM_WIDTH; j++) { + if (*numptr == 'x') + putpixel (buf, bpp, x + j, c1, 1); + else if (*numptr == '+') + putpixel (buf, bpp, x + j, c2, 0); + numptr++; + } +} + +void draw_status_line_single (uae_u8 *buf, int bpp, int y, int totalwidth, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *alpha) +{ + int x_start, j, led, border; + uae_u32 c1, c2, cb; + + c1 = ledcolor (0x00ffffff, rc, gc, bc, alpha); + c2 = ledcolor (0x00000000, rc, gc, bc, alpha); + cb = ledcolor (TD_BORDER, rc, gc, bc, alpha); + + if (td_pos & TD_RIGHT) + x_start = totalwidth - TD_PADX - VISIBLE_LEDS * TD_WIDTH; + else + x_start = TD_PADX; + + for (led = 0; led < LED_MAX; led++) { + int side, pos, num1 = -1, num2 = -1, num3 = -1, num4 = -1; + int x, c, on = 0, am = 2; + xcolnr on_rgb, on_rgb2, off_rgb, pen_rgb; + int half = 0; + + pen_rgb = c1; + if (led >= LED_DF0 && led <= LED_DF3) { + int pled = led - LED_DF0; + int track = gui_data.drive_track[pled]; + pos = 6 + pled; + on_rgb = 0x00cc00; + on_rgb2 = 0x006600; + off_rgb = 0x003300; + if (!gui_data.drive_disabled[pled]) { + num1 = -1; + num2 = track / 10; + num3 = track % 10; + on = gui_data.drive_motor[pled]; + if (gui_data.drive_writing[pled]) { + on_rgb = 0xcc0000; + on_rgb2 = 0x880000; + } + half = gui_data.drive_side ? 1 : -1; + if (gui_data.df[pled][0] == 0) + pen_rgb = ledcolor (0x00aaaaaa, rc, gc, bc, alpha); + } + side = gui_data.drive_side; + } else if (led == LED_POWER) { + pos = 3; + on_rgb = ((gui_data.powerled_brightness * 10 / 16) + 0x33) << 16; + on = 1; + off_rgb = 0x330000; + } else if (led == LED_CD) { + pos = 5; + on = gui_data.cd & (LED_CD_AUDIO | LED_CD_ACTIVE); + on_rgb = (on & LED_CD_AUDIO) ? 0x00cc00 : 0x0000cc; + if ((gui_data.cd & LED_CD_ACTIVE2) && !(gui_data.cd & LED_CD_AUDIO)) { + on_rgb &= 0xfefefe; + on_rgb >>= 1; + } + off_rgb = 0x000033; + num1 = -1; + num2 = 10; + num3 = 12; + } else if (led == LED_HD) { + pos = 4; + on = gui_data.hd; + on_rgb = on == 2 ? 0xcc0000 : 0x0000cc; + off_rgb = 0x000033; + num1 = -1; + num2 = 11; + num3 = 12; + } else if (led == LED_FPS) { + int fps = (gui_data.fps + 5) / 10; + pos = 2; + on_rgb = 0x000000; + off_rgb = 0x000000; + if (fps > 999) + fps = 999; + num1 = fps / 100; + num2 = (fps - num1 * 100) / 10; + num3 = fps % 10; + am = 3; + if (num1 == 0) + am = 2; + } else if (led == LED_CPU) { + int idle = (gui_data.idle + 5) / 10; + pos = 1; + on = framecnt && !picasso_on; + on_rgb = 0xcc0000; + off_rgb = 0x000000; + num1 = idle / 100; + num2 = (idle - num1 * 100) / 10; + num3 = idle % 10; + num4 = num1 == 0 ? 13 : -1; + am = 3; + } else if (led == LED_SND) { + int snd = abs(gui_data.sndbuf + 5) / 10; + if (snd > 99) + snd = 99; + pos = 0; + on = gui_data.sndbuf_status; + if (on < 3) { + num1 = gui_data.sndbuf < 0 ? 15 : 14; + num2 = snd / 10; + num3 = snd % 10; + } + on_rgb = 0x000000; + if (on < 0) + on_rgb = 0xcccc00; // underflow + else if (on == 2) + on_rgb = 0xcc0000; // really big overflow + else if (on == 1) + on_rgb = 0x0000cc; // "normal" overflow + off_rgb = 0x000000; + am = 3; + } else if (led == LED_MD && gui_data.drive_disabled[3]) { + // DF3 reused as internal non-volatile ram led (cd32/cdtv) + pos = 6 + 3; + on = gui_data.md; + on_rgb = on == 2 ? 0xcc0000 : 0x00cc00; + off_rgb = 0x003300; + num1 = -1; + num2 = -1; + num3 = -1; + } else + return; + on_rgb |= 0x33000000; + off_rgb |= 0x33000000; + if (half > 0) { + c = ledcolor (on ? (y >= TD_TOTAL_HEIGHT / 2 ? on_rgb2 : on_rgb) : off_rgb, rc, gc, bc, alpha); + } else if (half < 0) { + c = ledcolor (on ? (y < TD_TOTAL_HEIGHT / 2 ? on_rgb2 : on_rgb) : off_rgb, rc, gc, bc, alpha); + } else { + c = ledcolor (on ? on_rgb : off_rgb, rc, gc, bc, alpha); + } + border = 0; + if (y == 0 || y == TD_TOTAL_HEIGHT - 1) { + c = ledcolor (TD_BORDER, rc, gc, bc, alpha); + border = 1; + } + + x = x_start + pos * TD_WIDTH; + if (!border) + putpixel (buf, bpp, x - 1, cb, 0); + for (j = 0; j < TD_LED_WIDTH; j++) + putpixel (buf, bpp, x + j, c, 0); + if (!border) + putpixel (buf, bpp, x + j, cb, 0); + + if (y >= TD_PADY && y - TD_PADY < TD_NUM_HEIGHT) { + if (num3 >= 0) { + x += (TD_LED_WIDTH - am * TD_NUM_WIDTH) / 2; + if (num1 > 0) { + write_tdnumber (buf, bpp, x, y - TD_PADY, num1, pen_rgb, c2); + x += TD_NUM_WIDTH; + } + write_tdnumber (buf, bpp, x, y - TD_PADY, num2, pen_rgb, c2); + x += TD_NUM_WIDTH; + write_tdnumber (buf, bpp, x, y - TD_PADY, num3, pen_rgb, c2); + x += TD_NUM_WIDTH; + if (num4 > 0) + write_tdnumber (buf, bpp, x, y - TD_PADY, num4, pen_rgb, c2); + } + } + } +} diff --git a/traps.cpp b/traps.cpp index bdc4ec3a..742315b9 100644 --- a/traps.cpp +++ b/traps.cpp @@ -166,7 +166,7 @@ void REGPARAM2 m68k_handle_trap (unsigned int trap_num) if (implicit_rts) { m68k_do_rts (); - fill_prefetch_slow (); + fill_prefetch (); } } } else @@ -318,7 +318,7 @@ static uae_u32 trap_Call68k (TrapContext *context, uaecptr func_addr) /* Set PC to address of 68k call trap, so that it will be * executed when emulator context resumes. */ m68k_setpc (m68k_call_trapaddr); - fill_prefetch_slow (); + fill_prefetch (); /* Switch to emulator context. */ uae_sem_post (&context->switch_to_emu_sem); @@ -359,7 +359,7 @@ static uae_u32 REGPARAM3 m68k_call_handler (TrapContext *dummy_ctx) /* Set PC to address of 68k function to call. */ m68k_setpc (context->call68k_func_addr); - fill_prefetch_slow (); + fill_prefetch (); /* End critical section: allow other traps run. */ uae_sem_post (&trap_mutex); diff --git a/uaeunp.cpp b/uaeunp.cpp index 10e6697d..24285bf4 100644 --- a/uaeunp.cpp +++ b/uaeunp.cpp @@ -36,7 +36,7 @@ void gui_message (const TCHAR *format, ...) { } -int uaerand (void) +uae_u32 uaerand (void) { return rand (); } @@ -377,7 +377,7 @@ static int unpack (const TCHAR *src, const TCHAR *filename, const TCHAR *dst, in TCHAR fn[MAX_DPATH]; ret = 0; - zv = zfile_fopen_archive_root (src, ZFD_ALL | ZFD_NORECURSE); + zv = zfile_fopen_archive_root (src, ZFD_ALL); if (zv == NULL) { geterror(); _tprintf (L"Couldn't open archive '%s'\n", src); @@ -457,7 +457,10 @@ static int unpack (const TCHAR *src, const TCHAR *filename, const TCHAR *dst, in } geterror (); if (!found && !level) { - _tprintf (L"'%s' not found\n", fn); + if (dst[0]) + _tprintf (L"'%s' not found\n", dst); + else + _tprintf (L"nothing extracted\n"); } return ret; } @@ -472,7 +475,7 @@ static int unpack2 (const TCHAR *src, const TCHAR *match, int level) TCHAR fn[MAX_DPATH]; ret = 0; - zv = zfile_fopen_archive_root (src, ZFD_ALL | ZFD_NORECURSE); + zv = zfile_fopen_archive_root (src, ZFD_ALL); if (zv == NULL) { geterror(); _tprintf (L"Couldn't open archive '%s'\n", src); @@ -698,7 +701,7 @@ int __cdecl wmain (int argc, wchar_t *argv[], wchar_t *envp[]) ok = 1; } if (!ok) { - _tprintf (L"UAE unpacker uaeunp 0.8c by Toni Wilen (c)2010\n"); + _tprintf (L"UAE unpacker uaeunp 0.8d by Toni Wilen (c)2010\n"); _tprintf (L"\n"); _tprintf (L"List: \"uaeunp (-l) \"\n"); _tprintf (L"List all recursively: \"uaeunp -l **\"\n"); diff --git a/zfile.cpp b/zfile.cpp index 6a294b2a..4bfad15b 100644 --- a/zfile.cpp +++ b/zfile.cpp @@ -1827,7 +1827,6 @@ static struct zfile *zfile_fopenx2 (const TCHAR *name, const TCHAR *mode, int ma { struct zfile *f; TCHAR tmp[MAX_DPATH]; - TCHAR dirsep[2] = { FSDB_DIR_SEPARATOR, '\0' }; #ifdef _WIN32 if (isinternetfile (name)) @@ -1880,7 +1879,11 @@ struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask) { return zfile_fopenx (name, mode, mask, 0); } -struct zfile *zfile_fopen2 (const TCHAR *name, const TCHAR *mode, int mask, int index) +struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode) +{ + return zfile_fopenx (name, mode, 0, 0); +} +struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask, int index) { return zfile_fopenx (name, mode, mask, index); } @@ -1956,15 +1959,17 @@ struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name, uae_u64 } l->size = size; l->datasize = size; + l->allocsize = size; } else { - l->data = xcalloc (uae_u8, 1); + l->data = xcalloc (uae_u8, 1000); l->size = 0; + l->allocsize = 1000; } return l; } struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name) { - return zfile_fopen_empty (prev, name, 10000); + return zfile_fopen_empty (prev, name, 0); } struct zfile *zfile_fopen_parent (struct zfile *z, const TCHAR *name, uae_u64 offset, uae_u64 size) @@ -2006,6 +2011,24 @@ struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, uae_u8 *data) return l; } +int zfile_truncate (struct zfile *z, uae_s64 size) +{ + if (z->data) { + if (z->size > size) { + z->size = size; + if (z->datasize > z->size) + z->datasize = z->size; + if (z->seek > z->size) + z->seek = z->size; + return 1; + } + return 0; + } else { + /* !!! */ + return 0; + } +} + uae_s64 zfile_size (struct zfile *z) { return z->size; @@ -2108,12 +2131,25 @@ size_t zfile_fwrite (void *b, size_t l1, size_t l2, struct zfile *z) return 0; if (z->data) { int off = z->seek + l1 * l2; - if (off > z->size) { - z->data = xrealloc (uae_u8, z->data, off); + if (z->allocsize == 0) { + write_log (L"zfile_fwrite(data,%s) but allocsize=0!\n", z->name); + return 0; + } + if (off > z->allocsize) { + if (z->allocsize < off) + z->allocsize = off; + z->allocsize += z->size / 2; + if (z->allocsize < 10000) + z->allocsize = 10000; + z->data = xrealloc (uae_u8, z->data, z->allocsize); z->datasize = z->size = off; } memcpy (z->data + z->seek, b, l1 * l2); z->seek += l1 * l2; + if (z->seek > z->size) + z->size = z->seek; + if (z->size > z->datasize) + z->datasize = z->size; return l2; } return fwrite (b, l1, l2, z->f); @@ -2219,7 +2255,7 @@ int zfile_ferror (struct zfile *z) uae_u8 *zfile_getdata (struct zfile *z, uae_s64 offset, int len) { - uae_s64 pos; + uae_s64 pos = zfile_ftell (z); uae_u8 *b; if (len < 0) { zfile_fseek (z, 0, SEEK_END); @@ -2227,7 +2263,6 @@ uae_u8 *zfile_getdata (struct zfile *z, uae_s64 offset, int len) zfile_fseek (z, 0, SEEK_SET); } b = xmalloc (uae_u8, len); - pos = zfile_ftell (z); zfile_fseek (z, offset, SEEK_SET); zfile_fread (b, len, 1, z); zfile_fseek (z, pos, SEEK_SET); @@ -2336,7 +2371,6 @@ static struct zvolume *zvolume_list; static void recurparent (TCHAR *newpath, struct znode *zn, int recurse) { - TCHAR tmp[2] = { FSDB_DIR_SEPARATOR, 0 }; if (zn->parent && (&zn->volume->root != zn->parent || zn->volume->parentz == NULL)) { if (&zn->volume->root == zn->parent && zn->volume->parentz == NULL && !_tcscmp (zn->name, zn->parent->name)) goto end; @@ -2348,7 +2382,7 @@ static void recurparent (TCHAR *newpath, struct znode *zn, int recurse) } end: if (newpath[0]) - _tcscat (newpath, tmp); + _tcscat (newpath, FSDB_DIR_SEPARATOR_S); _tcscat (newpath, zn->name); } @@ -2358,7 +2392,6 @@ static struct znode *znode_alloc (struct znode *parent, const TCHAR *name) TCHAR tmpname[MAX_DPATH]; struct znode *zn = xcalloc (struct znode, 1); struct znode *zn2; - TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 }; _tcscpy (tmpname, name); zn2 = parent->child; @@ -2385,7 +2418,7 @@ static struct znode *znode_alloc (struct znode *parent, const TCHAR *name) fullpath[0] = 0; recurparent (fullpath, parent, FALSE); - _tcscat (fullpath, sep); + _tcscat (fullpath, FSDB_DIR_SEPARATOR_S); _tcscat (fullpath, tmpname); #ifdef ZFILE_DEBUG write_log (L"znode_alloc vol='%s' parent='%s' name='%s'\n", parent->volume->root.name, parent->name, name); @@ -2601,7 +2634,7 @@ static struct zvolume *zfile_fopen_archive_data (struct znode *parent, struct zf static struct znode *get_znode (struct zvolume *zv, const TCHAR *ppath, int); -static void zfile_fopen_archive_recurse2 (struct zvolume *zv, struct znode *zn) +static void zfile_fopen_archive_recurse2 (struct zvolume *zv, struct znode *zn, int flags) { struct zvolume *zvnew; struct znode *zndir; @@ -2628,7 +2661,7 @@ static void zfile_fopen_archive_recurse2 (struct zvolume *zv, struct znode *zn) } } -static int zfile_fopen_archive_recurse (struct zvolume *zv) +static int zfile_fopen_archive_recurse (struct zvolume *zv, int flags) { struct znode *zn; int i, added; @@ -2642,7 +2675,7 @@ static int zfile_fopen_archive_recurse (struct zvolume *zv) if (ext && !zn->vchild && zn->type == ZNODE_FILE) { for (i = 0; !done && archive_extensions[i]; i++) { if (!strcasecmp (ext + 1, archive_extensions[i])) { - zfile_fopen_archive_recurse2 (zv, zn); + zfile_fopen_archive_recurse2 (zv, zn, flags); done = 1; } } @@ -2650,7 +2683,7 @@ static int zfile_fopen_archive_recurse (struct zvolume *zv) if (!done) { z = archive_getzfile (zn, zv->method, 0); if (z && iszip (z)) - zfile_fopen_archive_recurse2 (zv, zn); + zfile_fopen_archive_recurse2 (zv, zn, flags); } zn = zn->next; } @@ -2673,7 +2706,7 @@ static struct zvolume *prepare_recursive_volume (struct zvolume *zv, const TCHAR if (!zvnew && !(flags & ZFD_NORECURSE)) { #if 1 zvnew = archive_directory_plain (zf); - zfile_fopen_archive_recurse (zvnew); + zfile_fopen_archive_recurse (zvnew, flags); done = 1; #else int rc; @@ -2705,7 +2738,7 @@ static struct zvolume *prepare_recursive_volume (struct zvolume *zv, const TCHAR #endif } else { zvnew->parent = zv->parent; - zfile_fopen_archive_recurse (zvnew); + zfile_fopen_archive_recurse (zvnew, flags); done = 1; } if (!done) @@ -2787,11 +2820,10 @@ struct znode *znode_adddir (struct znode *parent, const TCHAR *name, struct zarc { struct znode *zn; TCHAR path[MAX_DPATH]; - TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 }; path[0] = 0; recurparent (path, parent, FALSE); - _tcscat (path, sep); + _tcscat (path, FSDB_DIR_SEPARATOR_S); _tcscat (path, name); zn = get_znode (parent->volume, path, FALSE); if (zn) @@ -2932,7 +2964,7 @@ struct zvolume *zfile_fopen_archive (const TCHAR *filename, int flags) #if RECURSIVE_ARCHIVES if (zv && !(flags & ZFD_NORECURSE)) - zfile_fopen_archive_recurse (zv); + zfile_fopen_archive_recurse (zv, flags); #endif if (zv) diff --git a/zfile_archive.cpp b/zfile_archive.cpp index 082d8906..848b3538 100644 --- a/zfile_archive.cpp +++ b/zfile_archive.cpp @@ -1064,7 +1064,7 @@ static struct zfile *archive_access_plain (struct znode *zn) if (zn->offset) { struct zfile *zf; z = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size); - zf = zfile_fopen2 (zfile_getname (zn->volume->archive), L"rb", zn->volume->archive->zfdmask & ~ZFD_ADF, zn->offset - 1); + zf = zfile_fopen (zfile_getname (zn->volume->archive), L"rb", zn->volume->archive->zfdmask & ~ZFD_ADF, zn->offset - 1); if (zf) { zfile_fread (z->data, zn->size, 1, zf); zfile_fclose (zf); -- 2.47.3