]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Debugger updates.
authorToni Wilen <twilen@winuae.net>
Sun, 27 Jan 2019 15:17:12 +0000 (17:17 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 27 Jan 2019 15:17:12 +0000 (17:17 +0200)
debug.cpp
debugmem.cpp
include/debug.h
memory.cpp

index 6c2bf313f0537448fac3da8f03c826e809d8ac94..822f718e00fb117b1612cb4b28107e571873c3e5 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -207,7 +207,7 @@ static const TCHAR help[] = {
        _T("  W <addr> 'string'     Write into Amiga memory.\n")
        _T("  Wf <addr> <endaddr> <bytes or string like above>, fill memory.\n")
        _T("  Wc <addr> <endaddr> <destaddr>, copy memory.\n")
-       _T("  w <num> <address> <length> <R/W/I> <F/C> [<value>[.x]] (read/write/opcode) (freeze/mustchange).\n")
+       _T("  w <num> <address> <length> <R/W/I> <F/C/L/N> [<value>[.x]] (read/write/opcode) (freeze/mustchange/logonly/nobreak).\n")
        _T("                        Add/remove memory watchpoints.\n")
        _T("  wd [<0-1>]            Enable illegal access logger. 1 = enable break.\n")
        _T("  L <file> <addr> [<n>] Load a block of Amiga memory.\n")
@@ -2834,6 +2834,8 @@ uae_u8 *save_debug_memwatch (int *len, uae_u8 *dstptr)
                save_u32 (m->pc);
                save_u32 (m->access_mask);
                save_u32 (m->reg);
+               save_u8(m->nobreak);
+               save_u8(m->reportonly);
                save_store_size ();
        }
        *len = dst - dstbak;
@@ -2863,6 +2865,8 @@ uae_u8 *restore_debug_memwatch (uae_u8 *src)
                m->pc = restore_u32 ();
                m->access_mask = restore_u32();
                m->reg = restore_u32();
+               m->nobreak = restore_u8();
+               m->reportonly = restore_u8();
                restore_store_size ();
        }
        return src;
@@ -2894,6 +2898,21 @@ static void mungwall_memwatch(uaecptr addr, int rwi, int size, uae_u32 valp)
        }
 }
 
+static void memwatch_hit_msg(int mw)
+{
+       console_out_f(_T("Memwatch %d: break at %08X.%c %c%c%c %08X PC=%08X "), mw, mwhit.addr,
+               mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'),
+               (mwhit.rwi & 1) ? 'R' : ' ', (mwhit.rwi & 2) ? 'W' : ' ', (mwhit.rwi & 4) ? 'I' : ' ',
+               mwhit.val, mwhit.pc);
+       for (int i = 0; memwatch_access_masks[i].mask; i++) {
+               if (mwhit.access_mask == memwatch_access_masks[i].mask)
+                       console_out_f(_T("%s (%03x)\n"), memwatch_access_masks[i].name, mwhit.reg);
+       }
+       if (mwhit.access_mask & (MW_MASK_BLITTER_A | MW_MASK_BLITTER_B | MW_MASK_BLITTER_C | MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F)) {
+               blitter_debugdump();
+       }
+}
+
 static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u32 accessmask, uae_u32 reg)
 {
        uae_u32 val = *valp;
@@ -2951,7 +2970,7 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3
                        isoldval = 1;
                }
 
-               if (m->pc != 0xffffff) {
+               if (m->pc != 0xffffffff) {
                        if (m->pc != regs.instruction_pc)
                                continue;
                }
@@ -3040,10 +3059,15 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3
                if (mwhit.rwi & 2)
                        mwhit.val = val;
                memwatch_triggered = i + 1;
-               debugging = 1;
-               debug_pc = M68K_GETPC;
-               debug_cycles();
-               set_special (SPCFLAG_BRK);
+               if (m->reportonly) {
+                       memwatch_hit_msg(memwatch_triggered - 1);
+               }
+               if (!m->nobreak && !m->reportonly) {
+                       debugging = 1;
+                       debug_pc = M68K_GETPC;
+                       debug_cycles();
+                       set_special(SPCFLAG_BRK);
+               }
                return 1;
        }
        return 1;
@@ -3498,6 +3522,10 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num)
                                buf = buf_out(buf, &bufsize, _T(" C"));
                        if (mwn->pc != 0xffffffff)
                                buf = buf_out(buf, &bufsize, _T(" PC=%08x"), mwn->pc);
+                       if (mwn->reportonly)
+                               buf = buf_out(buf, &bufsize, _T(" L"));
+                       if (mwn->nobreak)
+                               buf = buf_out(buf, &bufsize, _T(" N"));
                        for (int j = 0; memwatch_access_masks[j].mask; j++) {
                                uae_u32 mask = memwatch_access_masks[j].mask;
                                if ((mwn->access_mask & mask) == mask && (usedmask & mask) == 0) {
@@ -3641,6 +3669,10 @@ static void memwatch (TCHAR **c)
                                                next_char(c);
                                                mwn->pc = readhex(c, NULL);
                                        }
+                                       if (ncc == 'L')
+                                               mwn->reportonly = true;
+                                       if (ncc == 'N')
+                                               mwn->nobreak = true;
                                        if (!more_params(c))
                                                break;
                                }
@@ -5903,11 +5935,9 @@ static void debug_1 (void)
 
 static void addhistory (void)
 {
-       uae_u32 pc = m68k_getpc ();
-       //    if (!notinrom())
-       //      return;
+       uae_u32 pc = currprefs.cpu_model >= 68020 && currprefs.cpu_compatible ? regs.instruction_pc : m68k_getpc();
        history[lasthist].regs = regs;
-       history[lasthist].regs.pc = m68k_getpc ();
+       history[lasthist].regs.pc = pc;
        history[lasthist].vpos = vpos;
        history[lasthist].hpos = current_hpos();
        history[lasthist].fp = timeframes;
@@ -5924,7 +5954,6 @@ static void debug_continue(void)
        set_special (SPCFLAG_BRK);
 }
 
-
 void debug (void)
 {
        int i;
@@ -6088,18 +6117,8 @@ void debug (void)
                        debug_cycles();
                }
        } else {
-               console_out_f (_T("Memwatch %d: break at %08X.%c %c%c%c %08X PC=%08X "), memwatch_triggered - 1, mwhit.addr,
-                       mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'),
-                       (mwhit.rwi & 1) ? 'R' : ' ', (mwhit.rwi & 2) ? 'W' : ' ', (mwhit.rwi & 4) ? 'I' : ' ',
-                       mwhit.val, mwhit.pc);
-               for (i = 0; memwatch_access_masks[i].mask; i++) {
-                       if (mwhit.access_mask == memwatch_access_masks[i].mask)
-                               console_out_f (_T("%s (%03x)\n"), memwatch_access_masks[i].name, mwhit.reg);
-               }
+               memwatch_hit_msg(memwatch_triggered - 1);
                memwatch_triggered = 0;
-               if (mwhit.access_mask & (MW_MASK_BLITTER_A | MW_MASK_BLITTER_B | MW_MASK_BLITTER_C | MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F)) {
-                       blitter_debugdump();
-               }
        }
 
        wasactive = ismouseactive ();
@@ -6768,7 +6787,7 @@ static void debug_trainer_enable(struct trainerpatch *tp, bool enable)
                                mwn->access_mask = MW_MASK_CPU_D_R | MW_MASK_CPU_D_W;
                                mwn->reg = 0xffffffff;
                                mwn->pc = tp->patchtype == TRAINER_NOP ? tp->addr : 0xffffffff;
-                               mwn->frozen = tp->patchtype == TRAINER_FREEZE;
+                               mwn->frozen = tp->patchtype == TRAINER_FREEZE || tp->patchtype == TRAINER_NOP;
                                mwn->modval_written = 0;
                                mwn->val_enabled = 0;
                                mwn->val_mask = 0xffffffff;
@@ -6777,6 +6796,7 @@ static void debug_trainer_enable(struct trainerpatch *tp, bool enable)
                                        mwn->val_enabled = 1;
                                        mwn->val = tp->setvalue;
                                }
+                               mwn->nobreak = true;
                                memwatch_setup();
                                TCHAR buf[256];
                                memwatch_dump2(buf, sizeof(buf) / sizeof(TCHAR), i);
@@ -6897,7 +6917,6 @@ static int parsetrainerdata(const TCHAR *data, uae_u16 *outdata, uae_u16 *outmas
 
 void debug_init_trainer(const TCHAR *file)
 {
-       TCHAR *data;
        TCHAR section[256];
        int cnt = 1;
 
@@ -6915,6 +6934,7 @@ void debug_init_trainer(const TCHAR *file)
 
                for (;;) {
                        TCHAR *name = NULL;
+                       TCHAR *data;
 
                        ini_getstring_multi(ini, section, _T("name"), &name, &ictx);
 
@@ -6935,7 +6955,6 @@ void debug_init_trainer(const TCHAR *file)
                        tp->maskdata = xcalloc(uae_u16, datalen);
                        tp->length = parsetrainerdata(data, tp->data, tp->maskdata);
                        xfree(data);
-                       data = NULL;
 
                        ini_getval_multi(ini, section, _T("offset"), &tp->offset, &ictx);
                        if (tp->offset < 0 || tp->offset >= tp->length)
@@ -6946,25 +6965,20 @@ void debug_init_trainer(const TCHAR *file)
                                tp->replacedata = xcalloc(uae_u16, replacedatalen);
                                tp->replacemaskdata = xcalloc(uae_u16, replacedatalen);
                                tp->replacelength = parsetrainerdata(data, tp->replacedata, tp->replacemaskdata);
-                               xfree(data);
-                               data = NULL;
                                ini_getval_multi(ini, section, _T("replaceoffset"), &tp->offset, &ictx);
                                if (tp->replaceoffset < 0 || tp->replaceoffset >= tp->length)
                                        tp->replaceoffset = 0;
                                tp->access = -1;
+                               xfree(data);
                        }
 
                        tp->access = 2;
-                       if (ini_getstring_multi(ini, section, _T("access"), &tp->data, &ictx)) {
+                       if (ini_getstring_multi(ini, section, _T("access"), &data, &ictx)) {
                                if (!_tcsicmp(data, _T("read")))
                                        tp->access = 0;
                                else if (!_tcsicmp(data, _T("write")))
                                        tp->access = 1;
-                       }
-
-                       if (ini_getstring_multi(ini, section, _T("enable"), &data, &ictx)) {
-                               if (!_tcsicmp(data, _T("true")))
-                                       tp->enabledatstart = true;
+                               xfree(data);
                        }
 
                        if (ini_getstring_multi(ini, section, _T("type"), &data, &ictx)) {
@@ -6991,6 +7005,12 @@ void debug_init_trainer(const TCHAR *file)
                                xfree(data);
                        }
 
+                       if (ini_getstring(ini, section, _T("enable"), &data)) {
+                               if (!_tcsicmp(data, _T("true")))
+                                       tp->enabledatstart = true;
+                               xfree(data);
+                       }
+
                        tp->first = tp->data[tp->offset];
                        tp->name = name;
 
@@ -7005,8 +7025,6 @@ void debug_init_trainer(const TCHAR *file)
 
                        ini_setlastasstart(ini, &ictx);
                }
-err:
-               xfree(data);
 
                if (!ini_nextsection(ini, section))
                        break;
index e37b8d027bca2cf4925c8252985613d30c739e0c..ba7802ad7672e1e0cafbde7ad996d7a434f20f80 100644 (file)
@@ -70,7 +70,7 @@ bool debugmem_trace;
 #define MAX_DEBUGSEGS 1000
 #define MAX_DEBUGSYMS 10000
 #define MAX_STACKVARS 10000
-#define MAX_DEBUGCODEFILES 1000
+#define MAX_DEBUGCODEFILES 10000
 #define MAX_STACKFRAMES 100
 
 
@@ -114,6 +114,8 @@ struct debugcodefile
        uae_u8 **lineptr;
        struct stabtype *stabtypes;
        int stabtypecount;
+       uae_u32 start_pc;
+       uae_u32 end_pc;
 };
 static struct debugcodefile **codefiles;
 static int codefilecnt;
@@ -1046,6 +1048,10 @@ static uae_u32 gl(uae_u8 *p)
 {
        return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
 }
+static uae_u16 gw(uae_u8 *p)
+{
+       return (p[0] << 8) | (p[1]);
+}
 
 static bool loadcodefiledata(struct debugcodefile *cf)
 {
@@ -1098,6 +1104,7 @@ static bool loadcodefiledata(struct debugcodefile *cf)
                                s[len - 1] = 0;
                }
        }
+       return true;
 }
 
 static struct debugcodefile *preallocatecodefile(const TCHAR *path, const TCHAR *name)
@@ -1108,7 +1115,8 @@ static struct debugcodefile *preallocatecodefile(const TCHAR *path, const TCHAR
        }
        codefilecnt++;
        cf->name = my_strdup(name);
-       cf->path = my_strdup(path);
+       if (path)
+               cf->path = my_strdup(path);
        return cf;
 }
 
@@ -2385,7 +2393,11 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
        struct debuglineheader lineheader;
        struct symbol *symtab = NULL;
        uae_u8 *debuginfo = NULL;
+       uae_u8 *debugstr = NULL;
+       uae_u8 *debugabbrev = NULL;
        int debuginfo_size;
+       int debugstr_size;
+       int debugabbrev_size;
        int symtab_num = 0;
        for (int i = 0; i < shnum; i++) {
                struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff);
@@ -2419,6 +2431,12 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                } else if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_info")) {
                        debuginfo = file + sh.offset;
                        debuginfo_size = sh.size;
+               } else if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_str")) {
+                       debugstr = file + sh.offset;
+                       debugstr_size = sh.size;
+               } else if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_abbrev")) {
+                       debugabbrev = file + sh.offset;
+                       debugabbrev_size = sh.size;
                }
        }
 
@@ -2436,7 +2454,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                swap_header(&sh, shp);
                sectionoffsets[i] = 0xffffffff;
                sectionbases[i] = 0xffffffff;
-               uae_char *namep = (uae_char*)(strtab + sh.name);
+               uae_char *namep = (uae_char*)(strtabsym + sh.name);
                TCHAR *n = au(namep);
                write_log(_T("ELF section %d: type=%08x flags=%08x size=%08x ('%s')\n"), i, sh.type, sh.flags, sh.size, n);
                xfree(n);
@@ -2492,7 +2510,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                        TCHAR *name = au(namep);
                        addsimplesymbol(name, sym.value, stype, sflags, segmentid, sym.shindex);
                        xfree(name);
-               } else if (sym.shindex < shnum && sectionoffsets[i] != 0xffffffff) {
+               } else if (sym.shindex < shnum && sectionoffsets[sym.shindex] != 0xffffffff) {
                        uae_char *namep = (uae_char*)(strtabsym + sym.name);
                        TCHAR *name = au(namep);
                        uae_u32 v = sym.value + sectionbases[sym.shindex];
@@ -2685,6 +2703,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                }
                outptr = NULL;
        }
+
 #if 0
        if (debuginfo) {
                uae_u8 *p = debuginfo;
@@ -2693,25 +2712,97 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                        uae_u32 length = gl(p);
                        p += 4;
                        uae_u8 *end = p + length;
+                       uae_u16 version = gw(p);
                        p += 2;
                        uae_u32 abbrev_offset = gl(p);
+                       uae_u8 *abbrev = debugabbrev + abbrev_offset;
                        p += 4;
                        uae_u8 ptr_size = *p++;
                        while (p < end) {
                                uae_u8 abbrevnum = *p++;
-                               switch (abbrevnum)
+                               uae_u8 *ap = abbrev;
+                               uae_u8 tag = 0;
+                               for (;;) {
+                                       uae_u8 anum = *ap;
+                                       if (anum == abbrevnum)
+                                               break;
+                                       ap++;
+                                       ap++;
+                                       ap++;
+                                       for (;;) {
+                                               uae_u16 v = gw(ap);
+                                               ap += 2;
+                                               if (!v)
+                                                       break;
+                                       }
+                               }
+                               tag = *ap++;
+                               ap++; // haschildren
+                               for (;;) {
+                                       uae_u8 name = *ap++;
+                                       uae_u8 type = *ap++;
+                                       uae_u32 v;
+                                       if (!name && !type)
+                                               break;
+                                       switch (type)
+                                       {
+                                       case 0x8: // string
+                                               for (;;) {
+                                                       if (*ap++ == 0)
+                                                               break;
+                                               }
+                                               break;
+                                       case 0x18: // exprloc
+                                               ap = lebx(ap, &v);
+                                               ap += v;
+                                               break;
+                                       }
+
+                               }
+#if 0
+
+                               switch (abbrevnum)
                                {
                                        case 1:
                                        {
-                                               p += 4; // producer
-                                               p++; //language
-                                               uae_char *namep = (uae_char*)start + gl(p);
-                                               p += 4;
-                                               uae_u32 low_pc = gl(p);
-                                               p += 4;
-                                               uae_u32 high_pc = gl(p);
-                                               p += 4;
-                                               p += 4;
+                                               if (version == 2) {
+                                                       uae_u32 stmt_list = gl(p);
+                                                       p += 4;
+                                                       uae_u32 low_pc = gl(p);
+                                                       p += 4;
+                                                       uae_u32 high_pc = gl(p);
+                                                       p += 4;
+                                                       uae_char *namep = (uae_char*)p;
+                                                       p += strlen((char*)p) + 1;
+                                                       uae_char *comp_dirp = (uae_char*)p;
+                                                       p += strlen((char*)p) + 1;
+                                                       p += strlen((char*)p) + 1; // producer
+                                                       uae_u16 language = gw(p);
+                                                       p += 2;
+                                                       TCHAR *name = au(namep);
+                                                       struct debugcodefile *cf = preallocatecodefile(NULL, name);
+                                                       cf->start_pc = low_pc;
+                                                       cf->end_pc = low_pc + high_pc;
+                                                       xfree(name);
+                                               } else if (version >= 3) {
+                                                       uae_char *producerp = (uae_char*)debugstr + gl(p);
+                                                       p += 4;
+                                                       uae_u8 language = p[0];
+                                                       p += 1;
+                                                       uae_char *namep = (uae_char*)debugstr + gl(p);
+                                                       p += 4;
+                                                       uae_u32 low_pc = gl(p);
+                                                       p += 4;
+                                                       uae_u32 high_pc = gl(p);
+                                                       p += 4;
+                                                       uae_u32 stmt_list = gl(p);
+                                                       p += 4;
+                                                       TCHAR *name = au(namep);
+                                                       struct debugcodefile *cf = preallocatecodefile(NULL, name);
+                                                       cf->start_pc = low_pc;
+                                                       cf->end_pc = low_pc + high_pc;
+                                                       xfree(name);
+                                               }
                                                break;
                                        }
                                        case 2:
@@ -2725,8 +2816,11 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                                break;
                                        }
                                }
+#endif
+                               break;
                        }
                        debuginfo_size -= length;
+                       p = start + length + 4;
                }
        }
 #endif
@@ -3413,13 +3507,28 @@ struct debugcodefile *last_codefile;
 
 int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize)
 {
+       if (out)
+               out[0] = 0;
+
+       if (!executable_last_segment && codefilecnt) {
+#if 0
+               for (int i = 0; i < codefilecnt; i++) {
+                       struct debugcodefile *cf = codefiles[i];
+                       if (cf && addr >= cf->start_pc && addr < cf->end_pc) {
+                               _stprintf(out, _T("Source file: %s\n"), cf->name);
+                               return -1;
+                       }
+               }
+#endif
+               return -1;
+       }
+
        if (addr < debugmem_bank.start)
                return -1;
        addr -= debugmem_bank.start;
        if (addr >= debugmem_bank.allocated_size)
                return -1;
-       if (out)
-               out[0] = 0;
+
        for (int i = 1; i <= executable_last_segment; i++) {
                struct debugmemallocs *alloc = allocs[i];
                if (addr >= alloc->start && addr < alloc->start + alloc->size) {
index 57ace369d6a7c0de25b7a4f0fefcc043f9ae0604..93d83e4e87499a18b4871b85379e6eb01059f46c 100644 (file)
@@ -153,6 +153,8 @@ struct memwatch_node {
        int frozen;
        uae_u32 reg;
        uaecptr pc;
+       bool nobreak;
+       bool reportonly;
 };
 extern struct memwatch_node mwnodes[MEMWATCH_TOTAL];
 
index 19913c054e9394659ce7fccfed5452583ca96db6..3494cb7fafd71afdd7db1d018bd924340180e624 100644 (file)
@@ -388,7 +388,6 @@ uae_u32 dummy_get (uaecptr addr, int size, bool inst, uae_u32 defvalue)
                return get_long(addr);
        }
 
-
        if (gary_nonrange(addr) || (size > 1 && gary_nonrange(addr + size - 1))) {
                if (gary_timeout)
                        gary_wait (addr, size, false);
@@ -1504,7 +1503,15 @@ static bool load_extendedkickstart (const TCHAR *romextfile, int type)
                } else if (currprefs.cs_cdtvcd || currprefs.cs_cdtvram) {
                        extendedkickmem_type = EXTENDED_ROM_CDTV;
                } else if (size > 300000) {
-                       extendedkickmem_type = EXTENDED_ROM_CD32;
+                       uae_u8 data[2] = { 0 };
+                       zfile_fseek(f, off, SEEK_SET);
+                       zfile_fread(data, sizeof(data), 1, f);
+                       if (data[0] == 0x11 && data[1] == 0x11) {
+                               if (need_uae_boot_rom(&currprefs) != 0xf00000)
+                                       extendedkickmem_type = EXTENDED_ROM_CDTV;
+                       } else {
+                               extendedkickmem_type = EXTENDED_ROM_CD32;
+                       }
                } else if (need_uae_boot_rom (&currprefs) != 0xf00000) {
                        extendedkickmem_type = EXTENDED_ROM_CDTV;
                }       
@@ -1703,6 +1710,12 @@ static struct zfile *get_kickstart_filehandle(struct uae_prefs *p)
        return f;
 }
 
+extern struct zfile *read_executable_rom(struct zfile*, int size, int blocks);
+static const uae_u8 romend[20] = {
+       0x00, 0x08, 0x00, 0x00,
+       0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f
+};
+
 static int load_kickstart (void)
 {
        TCHAR tmprom[MAX_DPATH];
@@ -1720,59 +1733,92 @@ static int load_kickstart (void)
                int filesize, size, maxsize;
                int kspos = ROM_SIZE_512;
                int extpos = 0;
+               bool singlebigrom = false;
+
+               uae_u8 tmp[8] = { 0 };
+               zfile_fread(tmp, sizeof tmp, 1, f);
 
                maxsize = ROM_SIZE_512;
-               zfile_fseek (f, 0, SEEK_END);
-               filesize = zfile_ftell (f);
-               zfile_fseek (f, 0, SEEK_SET);
-               if (filesize == 1760 * 512) {
-                       filesize = ROM_SIZE_256;
-                       maxsize = ROM_SIZE_256;
-               }
-               if (filesize == ROM_SIZE_512 + 8) {
-                       /* GVP 0xf0 kickstart */
-                       zfile_fseek (f, 8, SEEK_SET);
-               }
-               if (filesize >= ROM_SIZE_512 * 2) {
-                       struct romdata *rd = getromdatabyzfile(f);
-                       zfile_fseek (f, kspos, SEEK_SET);
-               }
-               if (filesize >= ROM_SIZE_512 * 4) {
-                       kspos = ROM_SIZE_512 * 3;
-                       extpos = 0;
-                       zfile_fseek (f, kspos, SEEK_SET);
-               }
-               size = read_kickstart (f, kickmem_bank.baseaddr, maxsize, 1, 0);
-               if (size == 0)
-                       goto err;
-               kickmem_bank.mask = size - 1;
-               kickmem_bank.reserved_size = size;
-               if (filesize >= ROM_SIZE_512 * 2 && !extendedkickmem_type) {
-                       extendedkickmem_bank.reserved_size = ROM_SIZE_512;
-                       if (currprefs.cs_cdtvcd || currprefs.cs_cdtvram) {
-                               extendedkickmem_type = EXTENDED_ROM_CDTV;
-                               extendedkickmem_bank.reserved_size *= 2;
-                               extendedkickmem_bank.label = _T("rom_f0");
-                               extendedkickmem_bank.start = 0xf00000;
-                       } else {
-                               extendedkickmem_type = EXTENDED_ROM_KS;
-                               extendedkickmem_bank.label = _T("rom_e0");
-                               extendedkickmem_bank.start = 0xe00000;
+
+               if ((tmp[0] == 0x00 && tmp[1] == 0x00 && tmp[2] == 0x03 && tmp[3] == 0xf3 &&
+                       tmp[4] == 0x00 && tmp[5] == 0x00 && tmp[6] == 0x00 && tmp[7] == 0x00) ||
+                       (tmp[0] == 0x7f && tmp[1] == 'E' && tmp[2] == 'L' && tmp[3] == 'F')) {
+                       struct zfile *zf = read_executable_rom(f, ROM_SIZE_512, 3);
+                       if (zf) {
+                               int size = zfile_size(zf);
+                               zfile_fclose(f);
+                               f = zf;
+                               if (size > ROM_SIZE_512) {
+                                       maxsize = zfile_size(zf);
+                                       singlebigrom = true;
+                                       extendedkickmem2_bank.reserved_size = size;
+                                       extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
+                                       extendedkickmem2_bank.start = size > 2 * ROM_SIZE_512 ? 0xa00000 : 0xa80000;
+                                       mapped_malloc(&extendedkickmem2_bank);
+                                       read_kickstart(f, extendedkickmem2_bank.baseaddr, size, 0, 1);
+                                       memset(kickmem_bank.baseaddr, 0, ROM_SIZE_512);
+                                       memcpy(kickmem_bank.baseaddr, extendedkickmem2_bank.baseaddr, 0xd0);
+                                       memcpy(kickmem_bank.baseaddr + ROM_SIZE_512 - 20, romend, sizeof(romend));
+                                       kickstart_fix_checksum(kickmem_bank.baseaddr, ROM_SIZE_512);
+                               }
                        }
-                       mapped_malloc (&extendedkickmem_bank);
-                       zfile_fseek (f, extpos, SEEK_SET);
-                       read_kickstart (f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
-                       extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
                }
-               if (filesize > ROM_SIZE_512 * 2) {
-                       extendedkickmem2_bank.reserved_size = ROM_SIZE_512 * 2;
-                       mapped_malloc (&extendedkickmem2_bank);
-                       zfile_fseek (f, extpos + ROM_SIZE_512, SEEK_SET);
-                       read_kickstart (f, extendedkickmem2_bank.baseaddr, ROM_SIZE_512, 0, 1);
-                       zfile_fseek (f, extpos + ROM_SIZE_512 * 2, SEEK_SET);
-                       read_kickstart (f, extendedkickmem2_bank.baseaddr + ROM_SIZE_512, ROM_SIZE_512, 0, 1);
-                       extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
-                       extendedkickmem2_bank.start = 0xa80000;
+
+               if (!singlebigrom) {
+                       zfile_fseek(f, 0, SEEK_END);
+                       filesize = zfile_ftell(f);
+                       zfile_fseek(f, 0, SEEK_SET);
+                       if (!singlebigrom) {
+                               if (filesize == 1760 * 512) {
+                                       filesize = ROM_SIZE_256;
+                                       maxsize = ROM_SIZE_256;
+                               }
+                               if (filesize == ROM_SIZE_512 + 8) {
+                                       /* GVP 0xf0 kickstart */
+                                       zfile_fseek(f, 8, SEEK_SET);
+                               }
+                               if (filesize >= ROM_SIZE_512 * 2) {
+                                       struct romdata *rd = getromdatabyzfile(f);
+                                       zfile_fseek(f, kspos, SEEK_SET);
+                               }
+                               if (filesize >= ROM_SIZE_512 * 4) {
+                                       kspos = ROM_SIZE_512 * 3;
+                                       extpos = 0;
+                                       zfile_fseek(f, kspos, SEEK_SET);
+                               }
+                       }
+                       size = read_kickstart(f, kickmem_bank.baseaddr, maxsize, 1, 0);
+                       if (size == 0)
+                               goto err;
+                       kickmem_bank.mask = size - 1;
+                       kickmem_bank.reserved_size = size;
+                       if (filesize >= ROM_SIZE_512 * 2 && !extendedkickmem_type) {
+                               extendedkickmem_bank.reserved_size = ROM_SIZE_512;
+                               if (currprefs.cs_cdtvcd || currprefs.cs_cdtvram) {
+                                       extendedkickmem_type = EXTENDED_ROM_CDTV;
+                                       extendedkickmem_bank.reserved_size *= 2;
+                                       extendedkickmem_bank.label = _T("rom_f0");
+                                       extendedkickmem_bank.start = 0xf00000;
+                               } else {
+                                       extendedkickmem_type = EXTENDED_ROM_KS;
+                                       extendedkickmem_bank.label = _T("rom_e0");
+                                       extendedkickmem_bank.start = 0xe00000;
+                               }
+                               mapped_malloc(&extendedkickmem_bank);
+                               zfile_fseek(f, extpos, SEEK_SET);
+                               read_kickstart(f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
+                               extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
+                       }
+                       if (filesize > ROM_SIZE_512 * 2) {
+                               extendedkickmem2_bank.reserved_size = ROM_SIZE_512 * 2;
+                               mapped_malloc(&extendedkickmem2_bank);
+                               zfile_fseek(f, extpos + ROM_SIZE_512, SEEK_SET);
+                               read_kickstart(f, extendedkickmem2_bank.baseaddr, ROM_SIZE_512, 0, 1);
+                               zfile_fseek(f, extpos + ROM_SIZE_512 * 2, SEEK_SET);
+                               read_kickstart(f, extendedkickmem2_bank.baseaddr + ROM_SIZE_512, ROM_SIZE_512, 0, 1);
+                               extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
+                               extendedkickmem2_bank.start = 0xa80000;
+                       }
                }
        }
 
@@ -2369,11 +2415,16 @@ static void fill_ce_banks (void)
        }
 }
 
+static int overlay_state;
+
 void map_overlay (int chip)
 {
        int size;
        addrbank *cb;
 
+       if (chip < 0)
+               chip = overlay_state;
+
        if (currprefs.cs_compatible == CP_CASABLANCA) {
                casablanca_map_overlay();
                return;
@@ -2428,6 +2479,7 @@ void map_overlay (int chip)
                        rb = &kickmem_bank;
                map_banks (rb, 0, size, 0x80000);
        }
+       overlay_state = chip;
        fill_ce_banks ();
        cpuboard_overlay_override();
        if (!isrestore () && valid_address (regs.pc, 4))