]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Debugger updates.
authorToni Wilen <twilen@winuae.net>
Sat, 12 Jan 2019 14:42:51 +0000 (16:42 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 12 Jan 2019 14:42:51 +0000 (16:42 +0200)
cfgfile.cpp
debug.cpp
debugmem.cpp
filesys.cpp
include/debug.h
include/debugmem.h
include/options.h
newcpu.cpp

index 7adf91336d0f50c46ecf990b0331b41ce358f7d0..10fce2c77e1abc0cdfb1157dfb917df3a05a3b53 100644 (file)
@@ -1829,6 +1829,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
                }
        }
 
+       if (p->trainerfile[0])
+               cfgfile_write_str(f, _T("trainerfile"), p->trainerfile);
+
        if (p->statefile[0])
                cfgfile_write_str (f, _T("statefile"), p->statefile);
        if (p->quitstatefile[0])
@@ -3752,6 +3755,9 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
                return 1;
        }
 
+       if (cfgfile_path(option, value, _T("trainerfile"), p->trainerfile, sizeof p->trainerfile / sizeof(TCHAR)))
+               return 1;
+
        if (cfgfile_path (option, value, _T("statefile_quit"), p->quitstatefile, sizeof p->quitstatefile / sizeof (TCHAR)))
                return 1;
 
index 52852333967088e8ba259a9170be784c1723c8a6..6c2bf313f0537448fac3da8f03c826e809d8ac94 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -47,6 +47,8 @@
 #include "drawing.h"
 #include "devices.h"
 #include "blitter.h"
+#include "ini.h"
+#include "readcpu.h"
 
 #define TRACE_SKIP_INS 1
 #define TRACE_MATCH_PC 2
@@ -896,7 +898,8 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
        double out;
 
        form[0] = 0;
-       *size = 0;
+       if (size)
+               *size = 0;
        p = form;
        for (;;) {
                uae_u32 v;
@@ -908,7 +911,8 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
                p += _tcslen (p);
                if (peekchar (cp) == '.') {
                        readchar (cp);
-                       *size = readsize (v, cp);
+                       if (size)
+                               *size = readsize (v, cp);
                }
                if (!isoperator (cp))
                        break;
@@ -917,7 +921,7 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
                *p = 0;
        }
        if (!gotop) {
-               if (*size == 0) {
+               if (size && *size == 0) {
                        uae_s32 v = (uae_s32)(*val);
                        if (v > 65535 || v < -32767) {
                                *size = 4;
@@ -931,7 +935,7 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
        }
        if (calc (form, &out)) {
                *val = (uae_u32)out;
-               if (*size == 0) {
+               if (size && *size == 0) {
                        uae_s32 v = (uae_s32)(*val);
                        if (v > 255 || v < -127) {
                                *size = 2;
@@ -2947,6 +2951,11 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3
                        isoldval = 1;
                }
 
+               if (m->pc != 0xffffff) {
+                       if (m->pc != regs.instruction_pc)
+                               continue;
+               }
+
                if (!m->frozen && m->val_enabled) {
                        int trigger = 0;
                        uae_u32 mask = m->size == 4 ? 0xffffffff : (1 << (m->size * 8)) - 1;
@@ -3022,7 +3031,6 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3
                }
                //      if (!notinrom ())
                //          return 1;
-               mwhit.pc = M68K_GETPC;
                mwhit.addr = addr;
                mwhit.rwi = rwi;
                mwhit.size = size;
@@ -3033,7 +3041,7 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3
                        mwhit.val = val;
                memwatch_triggered = i + 1;
                debugging = 1;
-               debug_pc = mwhit.pc;
+               debug_pc = M68K_GETPC;
                debug_cycles();
                set_special (SPCFLAG_BRK);
                return 1;
@@ -3382,6 +3390,10 @@ static void initialize_memwatch (int mode)
        debug_mem_banks = xcalloc (addrbank*, membank_total);
        debug_mem_area = xcalloc (addrbank, membank_total);
        membank_stores = xcalloc (struct membank_store, MEMWATCH_STORE_SLOTS);
+       for (int i = 0; i < MEMWATCH_TOTAL; i++) {
+               struct memwatch_node *m = &mwnodes[i];
+               m->pc = 0xffffffff;
+       }
 #if 0
        int i, j, as;
        addrbank *a1, *a2, *oa;
@@ -3483,7 +3495,9 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num)
                        if (mwn->modval_written)
                                buf = buf_out (buf, &bufsize, _T(" =M"));
                        if (mwn->mustchange)
-                               buf = buf_out (buf, &bufsize, _T(" C"));
+                               buf = buf_out(buf, &bufsize, _T(" C"));
+                       if (mwn->pc != 0xffffffff)
+                               buf = buf_out(buf, &bufsize, _T(" PC=%08x"), mwn->pc);
                        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) {
@@ -3609,7 +3623,7 @@ static void memwatch (TCHAR **c)
                        ignore_ws (c);
                        if (more_params(c)) {
                                for (;;) {
-                                       TCHAR ncc = peek_next_char(c);
+                                       TCHAR ncc = _totupper(peek_next_char(c));
                                        TCHAR nc = _totupper (next_char (c));
                                        if (mwn->rwi == 7)
                                                mwn->rwi = 0;
@@ -3623,6 +3637,10 @@ static void memwatch (TCHAR **c)
                                                mwn->rwi |= 1;
                                        if (ncc == ' ')
                                                break;
+                                       if (nc == 'P' && ncc == 'C') {
+                                               next_char(c);
+                                               mwn->pc = readhex(c, NULL);
+                                       }
                                        if (!more_params(c))
                                                break;
                                }
@@ -6539,3 +6557,465 @@ void debug_parser (const TCHAR *cmd, TCHAR *out, uae_u32 outsize)
        setconsolemode (NULL, 0);
        xfree (input);
 }
+
+/*
+
+trainer file is .ini file with following one or more [patch] sections.
+Each [patch] section describes single trainer option.
+
+After [patch] section must come at least one patch descriptor.
+
+[patch]
+name=name
+enable=true/false
+
+; patch descriptor
+data=200e46802d400026200cxx02 ; this is comment
+offset=2
+access=write
+setvalue=<value>
+type=nop/freeze/set/setonce
+
+; patch descriptor
+data=11223344556677889900
+offset=10
+replacedata=4e71
+replaceoffset=4
+
+; next patch section
+[patch]
+
+
+name: name of the option (appears in GUI in the future)
+enable: true = automatically enabled at startup. (false=manually activated using key shortcut etc.., will be implemented later)
+
+data: match data, when emulated CPU executes first opcode of this data and following words also match: match is detected. x = anything.
+offset: word offset from beginning of "data" that points to memory read/write instruction that you want to "patch". Default=0.
+access: read=read access, write=write access. Default: write if instruction does both memory read and write, read if read-only.
+
+setvalue: value to write if type is set or setonce.
+type=nop: found instruction's write does nothing. This instruction only. Other instruction(s) modifying same memory location are not skipped.
+type=freeze: found instruction's memory read always returns value in memory. Write does nothing.
+type=set: found instruction's memory read always returns "setvalue" contents. Write works normally.
+type=setonce: "setvalue" contents are written to memory when patch is detected.
+
+replacedata: data to be copied over data + replaceoffset. x masking is also supported. Memory is modified.
+replaceoffset: word offset from data.
+
+---
+
+Internally it uses debugger memory watch points to modify/freeze memory contents. No memory or code is modified.
+Only type=setonce and replacedata modifies memory.
+
+When CPU emulator current to be executed instruction's matches contents of data[offset], other words of data are also checked.
+If all words match: instruction's effective address(es) are calculated and matching (read/write) EA is stored. Matching part
+of patch is now done.
+
+Reason for this complexity is to enable single patch to work even if game is relocatable or it uses different memory
+locations depending on hardware config.
+
+If type=nop/freeze/set: debugger memwatch point is set that handles faking of read/write access.
+If type=setonce: "setvalue" contents gets written to detected effective address.
+If replacedata is set: copy code.
+
+Detection phase may cause increased CPU load, this may get optimized more but it shouldn't be (too) noticeable in basic
+A500 or A1200 modes.
+
+*/
+
+#define TRAINER_NOP 0
+#define TRAINER_FREEZE 1
+#define TRAINER_SET 2
+#define TRAINER_SETONCE 3
+
+struct trainerpatch
+{
+       TCHAR *name;
+       uae_u16 *data;
+       uae_u16 *maskdata;
+       uae_u16 *replacedata;
+       uae_u16 *replacemaskdata;
+       uae_u16 *replacedata_original;
+       uae_u16 first;
+       int length;
+       int offset;
+       int access;
+       int replacelength;
+       int replaceoffset;
+       uaecptr addr;
+       uaecptr varaddr;
+       int varsize;
+       uae_u32 oldval;
+       int patchtype;
+       int setvalue;
+       int memwatchindex;
+       bool enabledatstart;
+       bool enabled;
+};
+
+static struct trainerpatch **tpptr;
+static int tpptrcnt;
+bool debug_opcode_watch;
+
+uaecptr ShowEA(void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode);
+
+static int debug_trainer_get_ea(struct trainerpatch *tp, uaecptr pc, uae_u16 opcode, uaecptr *addr)
+{
+       struct instr *dp = table68k + opcode;
+       uae_u32 sea = 0, dea = 0;
+       uaecptr spc = 0, dpc = 0;
+       uaecptr pc2 = pc + 2;
+       if (dp->suse) {
+               spc = pc2;
+               pc2 = ShowEA(NULL, pc2, opcode, dp->sreg, dp->smode, dp->size, NULL, &sea, 1);
+               if (sea == spc)
+                       spc = 0xffffffff;
+       }
+       if (dp->duse) {
+               dpc = pc2;
+               pc2 = ShowEA(NULL, pc2, opcode, dp->dreg, dp->dmode, dp->size, NULL, &dea, 1);
+               if (dea == dpc)
+                       dpc = 0xffffffff;
+       }
+       if (dea && dpc != 0xffffffff && tp->access == 1) {
+               *addr = dea;
+               return 1 << dp->size;
+       }
+       if (sea && spc != 0xffffffff && tp->access == 0) {
+               *addr = sea;
+               return 1 << dp->size;
+       }
+       if (dea && tp->access > 1) {
+               *addr = dea;
+               return 1 << dp->size;
+       }
+       if (sea && tp->access > 1) {
+               *addr = sea;
+               return 1 << dp->size;
+       }
+       return 0;
+}
+
+static void debug_trainer_enable(struct trainerpatch *tp, bool enable)
+{
+       if (tp->enabled == enable)
+               return;
+
+       if (tp->replacedata) {
+               if (enable) {
+                       bool first = false;
+                       if (!tp->replacedata_original) {
+                               tp->replacedata_original = xcalloc(uae_u16, tp->replacelength);
+                               first = true;
+                       }
+                       for (int j = 0; j < tp->replacelength; j++) {
+                               uae_u16 v = tp->replacedata[j];
+                               uae_u16 m = tp->replacemaskdata[j];
+                               uaecptr addr = (tp->addr - tp->offset * 2) + j * 2 + tp->replaceoffset * 2;
+                               if (m == 0xffff) {
+                                       x_put_word(addr, v);
+                               } else {
+                                       uae_u16 vo = x_get_word(addr);
+                                       x_put_word(addr, (vo & ~m) | (v & m));
+                                       if (first)
+                                               tp->replacedata_original[j] = vo;
+                               }
+                       }
+               } else if (tp->replacedata_original) {
+                       for (int j = 0; j < tp->replacelength; j++) {
+                               uae_u16 m = tp->replacemaskdata[j];
+                               uaecptr addr = (tp->addr - tp->offset * 2) + j * 2 + tp->replaceoffset * 2;
+                               if (m != 0xffff) {
+                                       x_put_word(addr, tp->replacedata_original[j]);
+                               }
+                       }
+               }
+       }
+
+       if (tp->patchtype == TRAINER_SETONCE && tp->varaddr != 0xffffffff) {
+               uae_u32 v = enable ? tp->setvalue : tp->oldval;
+               switch (tp->varsize)
+               {
+               case 1:
+                       x_put_byte(tp->varaddr, tp->setvalue);
+                       break;
+               case 2:
+                       x_put_word(tp->varaddr, tp->setvalue);
+                       break;
+               case 4:
+                       x_put_long(tp->varaddr, tp->setvalue);
+                       break;
+               }
+       }
+
+       if ((tp->patchtype == TRAINER_NOP || tp->patchtype == TRAINER_FREEZE || tp->patchtype == TRAINER_SET) && tp->varaddr != 0xffffffff) {
+               struct memwatch_node *mwn;
+               if (!memwatch_enabled)
+                       initialize_memwatch(0);
+               if (enable) {
+                       int i;
+                       for (i = MEMWATCH_TOTAL - 1; i >= 0; i--) {
+                               mwn = &mwnodes[i];
+                               if (!mwn->size)
+                                       break;
+                       }
+                       if (i < 0) {
+                               write_log(_T("Trainer out of free memwatchpoints ('%s' %08x\n).\n"), tp->name, tp->addr);
+                       } else {
+                               mwn->addr = tp->varaddr;
+                               mwn->size = tp->varsize;
+                               mwn->rwi = 1 | 2;
+                               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->modval_written = 0;
+                               mwn->val_enabled = 0;
+                               mwn->val_mask = 0xffffffff;
+                               mwn->val = 0;
+                               if (tp->patchtype == TRAINER_SET) {
+                                       mwn->val_enabled = 1;
+                                       mwn->val = tp->setvalue;
+                               }
+                               memwatch_setup();
+                               TCHAR buf[256];
+                               memwatch_dump2(buf, sizeof(buf) / sizeof(TCHAR), i);
+                               write_log(_T("%s"), buf);
+                       }
+               } else {
+                       mwn = &mwnodes[tp->memwatchindex];
+                       mwn->size = 0;
+                       memwatch_setup();
+               }
+       }
+
+       write_log(_T("Trainer '%s' %s (addr=%08x)\n"), tp->name, enable ? _T("enabled") : _T("disabled"), tp->addr);
+       tp->enabled = enable;
+}
+
+void debug_trainer_match(void)
+{
+       uaecptr pc = m68k_getpc();
+       uae_u16 opcode = x_get_word(pc);
+       for (int i = 0; i < tpptrcnt; i++) {
+               struct trainerpatch *tp = tpptr[i];
+               if (tp->first != opcode)
+                       continue;
+               if (tp->addr)
+                       continue;
+               int j;
+               for (j = 0; j < tp->length; j++) {
+                       uae_u16 d = x_get_word(pc + (j - tp->offset) * 2);
+                       if ((d & tp->maskdata[j]) != tp->data[j])
+                               break;
+               }
+               if (j < tp->length)
+                       continue;
+               tp->first = 0xffff;
+               tp->addr = pc;
+               tp->varsize = -1;
+               tp->varaddr = 0xffffffff;
+               tp->oldval = 0xffffffff;
+               if (tp->access >= 0) {
+                       tp->varsize = debug_trainer_get_ea(tp, pc, opcode, &tp->varaddr);
+                       switch (tp->varsize)
+                       {
+                       case 1:
+                               tp->oldval = x_get_byte(tp->varaddr);
+                               break;
+                       case 2:
+                               tp->oldval = x_get_word(tp->varaddr);
+                               break;
+                       case 4:
+                               tp->oldval = x_get_long(tp->varaddr);
+                               break;
+                       }
+               }
+               write_log(_T("Patch %d match at %08x. Addr %08x, size %d, val %08x\n"), i, pc, tp->varaddr, tp->varsize, tp->oldval);
+
+               if (tp->enabledatstart)
+                       debug_trainer_enable(tp, true);
+
+               // all detected?
+               for (j = 0; j < tpptrcnt; j++) {
+                       struct trainerpatch *tp = tpptr[j];
+                       if (!tp->addr)
+                               break;
+               }
+               if (j == tpptrcnt)
+                       debug_opcode_watch = false;
+       }
+}
+
+static int parsetrainerdata(const TCHAR *data, uae_u16 *outdata, uae_u16 *outmask)
+{
+       int len = _tcslen(data);
+       uae_u16 v = 0, vm = 0;
+       int j = 0;
+       for (int i = 0; i < len; ) {
+               TCHAR c1 = _totupper(data[i + 0]);
+               TCHAR c2 = _totupper(data[i + 1]);
+               if (c1 > 0 && c1 <= ' ') {
+                       i++;
+                       continue;
+               }
+               if (i + 1 >= len)
+                       return 0;
+
+               vm <<= 8;
+               vm |= 0xff;
+               if (c1 == 'X' || c1 == '?')
+                       vm &= 0x0f;
+               if (c2 == 'X' || c2 == '?')
+                       vm &= 0xf0;
+
+               if (c1 >= 'A')
+                       c1 -= 'A' - 10;
+               else if (c1 >= '0')
+                       c1 -= '0';
+               if (c2 >= 'A')
+                       c2 -= 'A' - 10;
+               else if (c2 >= '0')
+                       c2 -= '0';
+
+               v <<= 8;
+               if (c1 >= 0 && c1 < 16)
+                       v |= c1 << 4;
+               if (c2 >= 0 && c2 < 16)
+                       v |= c2;
+
+               if (i & 2) {
+                       outdata[j] = v;
+                       outmask[j] = vm;
+                       j++;
+               }
+
+               i += 2;
+       }
+       return j;
+}
+
+void debug_init_trainer(const TCHAR *file)
+{
+       TCHAR *data;
+       TCHAR section[256];
+       int cnt = 1;
+
+       struct ini_data *ini = ini_load(file, false);
+       if (!ini)
+               return;
+
+       write_log(_T("Loaded '%s'\n"), file);
+
+       _tcscpy(section, _T("patch"));
+
+       for (;;) {
+               struct ini_context ictx;
+               ini_initcontext(ini, &ictx);
+
+               for (;;) {
+                       TCHAR *name = NULL;
+
+                       ini_getstring_multi(ini, section, _T("name"), &name, &ictx);
+
+                       if (!ini_getstring_multi(ini, section, _T("data"), &data, &ictx))
+                               break;
+                       ini_setcurrentasstart(ini, &ictx);
+                       ini_setlast(ini, section, _T("data"), &ictx);
+
+                       TCHAR *p = _tcschr(data, ';');
+                       if (p)
+                               *p = 0;
+                       my_trim(data);
+
+                       struct trainerpatch *tp = xcalloc(struct trainerpatch, 1);
+
+                       int datalen = (_tcslen(data) + 3) / 4;
+                       tp->data = xcalloc(uae_u16, datalen);
+                       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)
+                               tp->offset = 0;
+
+                       if (ini_getstring_multi(ini, section, _T("replacedata"), &data, &ictx)) {
+                               int replacedatalen = (_tcslen(data) + 3) / 4;
+                               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;
+                       }
+
+                       tp->access = 2;
+                       if (ini_getstring_multi(ini, section, _T("access"), &tp->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;
+                       }
+
+                       if (ini_getstring_multi(ini, section, _T("type"), &data, &ictx)) {
+                               if (!_tcsicmp(data, _T("freeze")))
+                                       tp->patchtype = TRAINER_FREEZE;
+                               else if (!_tcsicmp(data, _T("nop")))
+                                       tp->patchtype = TRAINER_NOP;
+                               else if (!_tcsicmp(data, _T("set")))
+                                       tp->patchtype = TRAINER_SET;
+                               else if (!_tcsicmp(data, _T("setonce")))
+                                       tp->patchtype = TRAINER_SETONCE;
+                               xfree(data);
+                       }
+
+                       if (ini_getstring_multi(ini, section, _T("setvalue"), &data, &ictx)) {
+                               TCHAR *endptr;
+                               if (data[0] == '$') {
+                                       tp->setvalue = _tcstol(data + 1, &endptr, 16);
+                               } else if (_tcslen(data) > 2 && data[0] == '0' && _totupper(data[1]) == 'x') {
+                                       tp->setvalue = _tcstol(data + 2, &endptr, 16);
+                               } else {
+                                       tp->setvalue = _tcstol(data, &endptr, 10);
+                               }
+                               xfree(data);
+                       }
+
+                       tp->first = tp->data[tp->offset];
+                       tp->name = name;
+
+                       if (tpptrcnt)
+                               tpptr = xrealloc(struct trainerpatch*, tpptr, tpptrcnt + 1);
+                       else
+                               tpptr = xcalloc(struct trainerpatch*, tpptrcnt + 1);
+                       tpptr[tpptrcnt++] = tp;
+
+                       write_log(_T("%d: '%s' parsed and enabled\n"), cnt, tp->name ? tp->name : _T("<no name>"));
+                       cnt++;
+
+                       ini_setlastasstart(ini, &ictx);
+               }
+err:
+               xfree(data);
+
+               if (!ini_nextsection(ini, section))
+                       break;
+
+       }
+
+end:
+       if (tpptrcnt > 0)
+               debug_opcode_watch = true;
+
+       ini_free(ini);
+}
index 9b6cf2bbe771c2c253c02dafce4af474f9f815a6..e37b8d027bca2cf4925c8252985613d30c739e0c 100644 (file)
@@ -17,6 +17,7 @@
 #include "zfile.h"
 #include "uae.h"
 #include "fsdb.h"
+#include "rommgr.h"
 
 #define N_GSYM 0x20
 #define N_FUN 0x24
@@ -106,7 +107,7 @@ struct stabtype
 
 struct debugcodefile
 {
-       const TCHAR *name;
+       const TCHAR *name, *path;
        int length;
        uae_u8 *data;
        int lines;
@@ -142,7 +143,7 @@ struct debugsymbol
        void *data;
 };
 static struct debugsymbol **symbols;
-static int symbolcnt;
+static int symbolcnt, symbolindex;
 
 struct libname
 {
@@ -229,9 +230,23 @@ struct debugsegtracker
        uaecptr resident;
 };
 static struct debugsegtracker **dsegt;
-static int segtrackermax;
+static int segtrackermax, segtrackerindex;
 static uae_u32 inhibit_break, last_break;
 
+static uae_u8 *lebx(uae_u8 *p, uae_u32 *v)
+{
+       uae_u32 val = 0;
+       for (;;) {
+               uae_u8 b = *p++;
+               val |= b & 0x7f;
+               if (!(b & 0x80))
+                       break;
+               val <<= 7;
+       }
+       *v = val;
+       return p;
+}
+
 bool debugmem_break(int type)
 {
        if (inhibit_break & (1 << type))
@@ -1032,13 +1047,13 @@ static uae_u32 gl(uae_u8 *p)
        return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
 }
 
-static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name)
+static bool loadcodefiledata(struct debugcodefile *cf)
 {
        TCHAR fpath[MAX_DPATH];
        fpath[0] = 0;
-       if (path)
-               _tcscat(fpath, path);
-       _tcscat(fpath, name);
+       if (cf->path)
+               _tcscat(fpath, cf->path);
+       _tcscat(fpath, cf->name);
        struct zfile *zf = zfile_fopen(fpath, _T("rb"));
        if (!zf) {
                console_out_f(_T("Couldn't open source file '%s'\n"), fpath);
@@ -1055,12 +1070,6 @@ static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name)
        memcpy(data, data2, length);
        xfree(data2);
        zfile_fclose(zf);
-       struct debugcodefile *cf = codefiles[codefilecnt];
-       if (!cf) {
-               cf = codefiles[codefilecnt] = xcalloc(struct debugcodefile, 1);
-       }
-       codefilecnt++;
-       cf->name = my_strdup(name);
        cf->data = data;
        cf->length = length;
        cf->lines = 1;
@@ -1089,7 +1098,40 @@ static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name)
                                s[len - 1] = 0;
                }
        }
-       console_out_f(_T("Loaded source file '%s', %d bytes, %d lines\n"), fpath, cf->length, cf->lines);
+}
+
+static struct debugcodefile *preallocatecodefile(const TCHAR *path, const TCHAR *name)
+{
+       struct debugcodefile *cf = codefiles[codefilecnt];
+       if (!cf) {
+               cf = codefiles[codefilecnt] = xcalloc(struct debugcodefile, 1);
+       }
+       codefilecnt++;
+       cf->name = my_strdup(name);
+       cf->path = my_strdup(path);
+       return cf;
+}
+
+static void freecodefile(struct debugcodefile *cf)
+{
+       for (int i = 0; i < codefilecnt; i++) {
+               struct debugcodefile *c = codefiles[i];
+               if (c == cf) {
+                       xfree(codefiles[i]);
+                       codefiles[i] = NULL;
+               }
+       }
+}
+
+static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name)
+{
+       struct debugcodefile *cf = preallocatecodefile(path, name);
+       if (!loadcodefiledata(cf)) {
+               freecodefile(cf);
+               cf = NULL;
+       } else {
+               console_out_f(_T("Loaded source file '%s' '%s', %d bytes, %d lines\n"), cf->path, cf->name, cf->length, cf->lines);
+       }
        return cf;
 }
 
@@ -1109,7 +1151,7 @@ static struct debugsymbol *issymbol(const TCHAR *name)
 {
        for (int i = 0; i < symbolcnt; i++) {
                struct debugsymbol *ds = symbols[i];
-               if (!_tcsicmp(ds->name, name)) {
+               if (ds->allocid && !_tcsicmp(ds->name, name)) {
                        return ds;
                }
        }
@@ -1346,6 +1388,172 @@ static void parse_stabs(void)
        xfree(pathprefix);
 }
 
+static uae_u32 getrombase(int size)
+{
+       if (size > 524288 * 3)
+               return 0;
+       if (size > 524288 * 2) {
+               return 0xa00000;
+       } else if (size > 524288 * 1) {
+               return 0xa80000;
+       } else {
+               return 0xf80000;
+       }
+}
+
+static void addsimplesymbol(const TCHAR *name, uae_u32 v, int type, int flags, int segmentid, int segmentnum)
+{
+       if (!symbols)
+               return;
+
+       for (int i = 0; i < symbolcnt; i++) {
+               struct debugsymbol *ds = symbols[i];
+               if (ds->segment == segmentid && !_tcscmp(name, ds->name))
+                       return;
+       }
+       //write_log(_T("ELF Section %d, symbol %s=%08x\n"), segmentnum, name, v);
+       int rnd = 0;
+       for (;;) {
+               if (symbolindex >= MAX_DEBUGSYMS) {
+                       symbolindex = 0;
+                       rnd++;
+                       if (rnd > 1)
+                               return;
+               } else {
+                       symbolindex++;
+               }
+               struct debugsymbol *ds = symbols[symbolindex];
+               if (ds->allocid == 0) {
+                       ds->allocid = -1;
+                       ds->name = my_strdup(name);
+                       ds->value = v;
+                       ds->type = type;
+                       ds->flags = flags;
+                       ds->segment = segmentid;
+                       if (symbolindex >= symbolcnt)
+                               symbolcnt = symbolindex + 1;
+                       return;
+               }
+       }
+}
+
+static uae_u8 *loadhunkfile(uae_u8 *file, int filelen, uae_u32 seglist, int segmentid, int *outsizep, bool rommode)
+{
+       uae_u8 *p = file;
+       uae_u8 *out = NULL;
+
+       if (gl(p) != 0x3f3) {
+               return NULL;
+       }
+       p += 4;
+       if (gl(p) != 0) {
+               return 0;
+       }
+       p += 4;
+       int hunktotal = gl(p);
+       int first = gl(p + 4);
+       int last = gl(p + 8);
+       if (hunktotal > 1000 || (last - first + 1) > 1000) {
+               return 0;
+       }
+       if (first > last) {
+               return 0;
+       }
+       p += 12;
+       uae_u32 *hunklens = xcalloc(uae_u32, last + 1);
+       uae_u32 *hunkoffsets = xcalloc(uae_u32, last + 1);
+       int totalsize = 0;
+       for (int i = first; i <= last; i++) {
+               uae_u32 len = gl(p);
+               p += 4;
+               if ((len & 0xc0000000) == 0xc0000000) {
+                       p += 4;
+               }
+               len &= ~(0x80000000 | 0x40000000);
+               hunklens[i] = len * 4;
+               hunkoffsets[i] = totalsize;
+               totalsize += hunklens[i];
+       }
+       uae_u32 relocate_base = getrombase(totalsize);
+       int outsize = 0;
+       int hunkindex = -1;
+       for (;;) {
+               uae_u32 hunktype = gl(p) & ~0xc0000000;
+               if (hunktype == 0x3e9 || hunktype == 0x3ea || hunktype == 0x3eb) {
+                       uae_u32 hunklen = gl(p + 4) * 4;
+                       p += 8;
+                       hunkindex++;
+                       if (!out)
+                               out = xcalloc(uae_u8, outsize + hunklens[hunkindex]);
+                       else
+                               out = xrealloc(uae_u8, out, outsize + hunklens[hunkindex]);
+                       memset(out + outsize, 0, hunklens[hunkindex]);
+                       if (hunktype != 0x3eb) {
+                               memcpy(out + outsize, p, hunklen);
+                               p += hunklen;
+                       }
+                       outsize += hunklens[hunkindex];
+
+                       if (gl(p) == 0x3ec) { // reloc
+
+                               p += 4;
+                               for (;;) {
+                                       int reloccnt = gl(p);
+                                       p += 4;
+                                       if (!reloccnt)
+                                               break;
+                                       int relochunk = gl(p);
+                                       p += 4;
+                                       if (relochunk > last) {
+                                               return 0;
+                                       }
+                                       uaecptr hunkptr = hunkoffsets[relochunk] + relocate_base;
+                                       uae_u8 *currenthunk = out + hunkoffsets[relochunk];
+                                       for (int j = 0; j < reloccnt; j++) {
+                                               uae_u32 reloc = gl(p);
+                                               p += 4;
+                                               if (reloc >= outsize - 3) {
+                                                       return 0;
+                                               }
+                                               put_long_host(currenthunk + reloc, get_long_host(currenthunk + reloc) + hunkptr);
+                                       }
+                               }
+                       }
+                       continue;
+               }
+
+               if (hunktype == 0x3f0) { // symbol
+                       int symcnt = 0;
+                       p += 4;
+                       for (;;) {
+                               int size = gl(p);
+                               p += 4;
+                               if (!size)
+                                       break;
+                               if (hunkindex >= 0) {
+                                       p += 4 * size;
+                                       addsimplesymbol(au((char*)p), gl(p) + hunkoffsets[hunkindex] + 8 + relocate_base, 0, SYMBOL_GLOBAL, hunkindex, -1);
+                                       p += 4;
+                               } else {
+                                       p += 4 * size + 4;
+                               }
+                       }
+               } else if (hunktype == 0x3f2) {
+
+                       p += 4;
+
+               } else {
+
+                       break;
+
+               }
+       }
+       xfree(hunkoffsets);
+       xfree(hunklens);
+       *outsizep = outsize;
+       return out;
+}
+
 uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack)
 {
        uae_u8 *p = get_real_address(exeaddress);
@@ -1354,7 +1562,7 @@ uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *s
        uae_u32 lens[1000], memtypes[1000];
        uae_u32 parentid = 0;
 
-       debugmem_init();
+       debugmem_init(true);
        if (!debugmem_initialized)
                return 0;
 
@@ -1987,40 +2195,584 @@ bool debugger_load_libraries(void)
        return true;
 }
 
+struct elfheader
+{
+       uae_u8 ident[16];
+       uae_u16 type;
+       uae_u16 machine;
+       uae_u32 version;
+       uae_u32 entry;
+       uae_u32 phoff;
+       uae_u32 shoff;
+       uae_u32 flags;
+       uae_u16 ehsize;
+       uae_u16 phentsize;
+       uae_u16 phnum;
+       uae_u16 shentsize;
+       uae_u16 shnum;
+       uae_u16 shstrndx;
+};
+struct sheader
+{
+       uae_u32 name;
+       uae_u32 type;
+       uae_u32 flags;
+       uae_u32 addr;
+       uae_u32 offset;
+       uae_u32 size;
+       uae_u32 link;
+       uae_u32 info;
+       uae_u32 addralign;
+       uae_u32 entsize;
+};
+struct symbol
+{
+       uae_u32 name;
+       uae_u32 value;
+       uae_u32 size;
+       uae_u8 info;
+       uae_u8 other;
+       uae_u16 shindex;
+};
+struct rel
+{
+       uae_u32 offset;
+       uae_u32 info;
+       uae_u32 addend;
+};
+struct debuglineheader
+{
+       uae_u16 length[2];
+       uae_u16 version;
+       uae_u16 header_length[2];
+       uae_u8 min_instruction_length;
+       uae_u8 default_is_stmt;
+       uae_s8 line_base;
+       uae_u8 line_range;
+       uae_u8 opcode_base;
+       uae_u8 std_opcode_lengths[12];
+};
+
+#define SHT_PROGBITS       1
+#define SHT_SYMTAB         2
+#define SHT_STRTAB         3
+#define SHT_RELA           4
+#define SHT_NOBITS         8
+#define SHT_REL            9
+#define SHT_SYMTAB_SHNDX   18
+
+#define SHN_UNDEF       0
+#define SHN_LORESERVE   0xff00
+#define SHN_ABS         0xfff1
+#define SHN_COMMON      0xfff2
+#define SHN_XINDEX      0xffff
+
+#define R_68K_NONE      0
+#define R_68K_32        1
+#define R_68K_16        2
+#define R_68K_8         3
+#define R_68K_PC32      4
+#define R_68K_PC16      5
+#define R_68K_PC8       6
+
+#define SHF_ALLOC       (1 << 1)
+
+static void wswp(uae_u16 *v)
+{
+       *v = (*v >> 8) | (*v << 8);
+}
+static void lswp(uae_u32 *v)
+{
+       *v = (*v >> 24) | ((*v >> 8) & 0x0000ff00) | ((*v << 8) & 0x00ff0000) | (*v << 24);
+}
+static void lwswp(uae_u16 *vp)
+{
+       uae_u32 v = (vp[1] << 16) | vp[0];
+       v = (v >> 24) | ((v >> 8) & 0x0000ff00) | ((v << 8) & 0x00ff0000) | (v << 24);
+       vp[1] = v >> 16;
+       vp[0] = v;
+}
+
+static void swap_lineheader(struct debuglineheader *d, struct debuglineheader *s)
+{
+       memcpy(d, s, sizeof(struct debuglineheader));
+       lwswp(d->length);
+       lwswp(d->header_length);
+}
+
+static void swap_header(struct sheader *d, struct sheader *s)
+{
+       memcpy(d, s, sizeof(struct sheader));
+       lswp(&d->name);
+       lswp(&d->type);
+       lswp(&d->flags);
+       lswp(&d->addr);
+       lswp(&d->offset);
+       lswp(&d->size);
+       lswp(&d->link);
+       lswp(&d->info);
+       lswp(&d->addralign);
+       lswp(&d->entsize);
+}
+static void swap_symbol(struct symbol *d, struct symbol *s)
+{
+       memcpy(d, s, sizeof(struct symbol));
+       lswp(&d->name);
+       wswp(&d->shindex);
+       lswp(&d->value);
+       lswp(&d->size);
+}
+static void swap_rel(struct rel *d, struct rel *s)
+{
+       memcpy(d, s, sizeof(struct rel));
+       lswp(&d->addend);
+       lswp(&d->info);
+       lswp(&d->offset);
+}
+
+static int loadelf(uae_u8 *file, int filelen, uae_u8 **outp, int outsize, uae_u32 addr, struct sheader *sh)
+{
+       int size = sh->size;
+       uae_u8 *out = *outp;
+       if (!out)
+               out = xcalloc(uae_u8, outsize + size);
+       else
+               out = xrealloc(uae_u8, out, outsize + size);
+       memcpy(out + outsize, file + sh->offset, size);
+       outsize += size;
+       *outp = out;
+       return outsize;
+}
+
+static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segmentid, int *outsizep, bool rommode)
+{
+       uae_u8 *outp = NULL;
+       uae_u8 *outptr = NULL;
+       int outsize;
+       bool relocate = rommode;
+       uae_u32 relocate_base = 0;
+
+       struct elfheader *eh = (struct elfheader*)file;
+       uae_u8 *p = file + sizeof(struct elfheader);
+
+       wswp(&eh->type);
+       wswp(&eh->machine);
+       wswp(&eh->ehsize);
+       wswp(&eh->phentsize);
+       wswp(&eh->phnum);
+       wswp(&eh->shentsize);
+       wswp(&eh->shnum);
+       wswp(&eh->shstrndx);
+       lswp(&eh->version);
+       lswp(&eh->flags);
+       lswp(&eh->entry);
+       lswp(&eh->phoff);
+       lswp(&eh->shoff);
+
+       uae_u32 shnum = eh->shnum;
+       if (shnum == 0) {
+               if (eh->shoff == 0)
+                       return NULL;
+               struct sheader *sh = (struct sheader*)p;
+               shnum = sh->size;
+               if (shnum == 0)
+                       return NULL;
+               p += sizeof(struct sheader);
+       }
+
+       uae_u8 *strtab = NULL, *strtabsym = NULL;
+       struct sheader *symtab_shndx = NULL, *linesheader = NULL;
+       struct debuglineheader lineheader;
+       struct symbol *symtab = NULL;
+       uae_u8 *debuginfo = NULL;
+       int debuginfo_size;
+       int symtab_num = 0;
+       for (int i = 0; i < shnum; i++) {
+               struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff);
+               struct sheader sh;
+               swap_header(&sh, shp);
+               if (sh.type == SHT_STRTAB) {
+                       if (!strtab && i != eh->shstrndx) {
+                               strtab = file + sh.offset;
+                       }
+                       if (!strtabsym && i == eh->shstrndx) {
+                               strtabsym = file + sh.offset;
+                       }
+               } else if (sh.type == SHT_SYMTAB_SHNDX) {
+                       if (!symtab_shndx)
+                               symtab_shndx = (struct sheader*)(file + sh.offset);
+               } else if (sh.type == SHT_SYMTAB) {
+                       if (!symtab) {
+                               symtab = (struct symbol*)(file + sh.offset);
+                               symtab_num = sh.size / sh.entsize;
+                       }
+               }
+       }
+       for (int i = 0; i < shnum; i++) {
+               struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff);
+               struct sheader sh;
+               swap_header(&sh, shp);
+               uae_char *name = (uae_char*)(strtabsym + sh.name);
+               if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_line")) {
+                       swap_lineheader(&lineheader, (struct debuglineheader*)(file + sh.offset));
+                       linesheader = shp;
+               } else if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_info")) {
+                       debuginfo = file + sh.offset;
+                       debuginfo_size = sh.size;
+               }
+       }
+
+       struct sheader *shp_first = (struct sheader*)(file + eh->shoff);
+       int section = -1;
+       uae_u32 seg = seglist * 4;
+       uae_u32 nextseg = 0;
+
+       uae_u32 *sectionoffsets = xcalloc(uae_u32, shnum);
+       uae_u32 *sectionbases = xcalloc(uae_u32, shnum);
+       outsize = 0;
+       for (int i = 0; i < shnum; i++) {
+               struct sheader *shp = (struct sheader*)&shp_first[i];
+               struct sheader sh;
+               swap_header(&sh, shp);
+               sectionoffsets[i] = 0xffffffff;
+               sectionbases[i] = 0xffffffff;
+               uae_char *namep = (uae_char*)(strtab + 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);
+               if (sh.type == SHT_PROGBITS) {
+                       if ((sh.flags & SHF_ALLOC) && sh.size) {
+                               write_log(_T(" - load data. Offset %08x\n"), outsize);
+                               sectionoffsets[i] = outsize;
+                               if (relocate)
+                                       sectionbases[i] = outsize;
+                               outsize += sh.size;
+                       }
+               } else if (sh.type == SHT_NOBITS) {
+                       if (sh.size) {
+                               sectionbases[i] = sh.addr;
+                       }
+               }
+       }
+
+       if (rommode) {
+               relocate_base = getrombase(outsize);
+               if (!relocate_base)
+                       goto end;
+               for (int i = 0; i < shnum; i++) {
+                       if (sectionoffsets[i] != 0xffffffff)
+                               sectionbases[i] += relocate_base;
+               }
+       }
+
+       for (int i = 0; i < symtab_num; i++) {
+               struct symbol sym;
+               swap_symbol(&sym, &symtab[i]);
+               if (!sym.name)
+                       continue;
+               int sflags, stype;
+               uae_u8 type = sym.info & 15;
+               uae_u8 bind = sym.info >> 4;
+               if (type == 1) {
+                       stype = 0;
+               } else if (type == 2) {
+                       stype = SYMBOLTYPE_FUNC;
+               } else {
+                       continue;
+               }
+               if (bind == 0) {
+                       sflags = SYMBOL_LOCAL;
+               } else if (bind == 1) {
+                       sflags = SYMBOL_GLOBAL;
+               } else {
+                       continue;
+               }
+               if (sym.shindex == SHN_ABS) {
+                       uae_char *namep = (uae_char*)(strtabsym + sym.name);
+                       TCHAR *name = au(namep);
+                       addsimplesymbol(name, sym.value, stype, sflags, segmentid, sym.shindex);
+                       xfree(name);
+               } else if (sym.shindex < shnum && sectionoffsets[i] != 0xffffffff) {
+                       uae_char *namep = (uae_char*)(strtabsym + sym.name);
+                       TCHAR *name = au(namep);
+                       uae_u32 v = sym.value + sectionbases[sym.shindex];
+                       addsimplesymbol(name, v, stype, sflags, segmentid, sym.shindex);
+                       xfree(name);
+               }
+       }
+
+       outsize = 0;
+       outptr = NULL;
+       for (int i = 0; i < shnum; i++) {
+               struct sheader *shp = (struct sheader*)&shp_first[i];
+               struct sheader sh;
+               swap_header(&sh, shp);
+
+               if (nextseg) {
+                       seg = nextseg;
+                       nextseg = 0;
+               }
+
+               sectionoffsets[i] = outsize;
+
+               if (sh.type == SHT_NOBITS) {
+                       outptr = NULL;
+                       if ((sh.flags & SHF_ALLOC) && sh.size) {
+                               section++;
+                               if (seg)
+                                       nextseg = get_long(seg) * 4;
+                       }
+                       continue;
+               }
+
+               if (sh.type == SHT_PROGBITS) {
+                       outptr = NULL;
+                       if ((sh.flags & SHF_ALLOC) && sh.size) {
+                               section++;
+                               if (seg)
+                                       nextseg = get_long(seg) * 4;
+                               if (relocate) {
+                                       int newoutsize = loadelf(file, filelen, &outp, outsize, relocate_base, &sh);
+                                       outptr = outp + outsize;
+                                       outsize = newoutsize;
+                                       *outsizep = outsize;
+                               }
+                       }
+                       continue;
+               }
+
+
+
+               if (sh.type != SHT_RELA)
+                       continue;
+
+               struct sheader *shsymtabp = &shp_first[sh.link];
+               struct sheader shsymtab;
+               swap_header(&shsymtab, shsymtabp);
+
+               struct sheader *torelocp = &shp_first[sh.info];
+               struct sheader toreloc;
+               swap_header(&toreloc, torelocp);
+
+               struct symbol *symtabp = (struct symbol *)(file + shsymtab.offset);
+               struct symbol symtab;
+               swap_symbol(&symtab, symtabp);
+
+               int numrel = sh.size / sh.entsize;
+
+               for (int j = 0; j < numrel; j++) {
+
+                       struct rel *relp = (struct rel*)(file + sh.offset + j * sizeof(rel));
+                       struct rel rel;
+                       swap_rel(&rel, relp);
+
+                       struct symbol *symp = &symtabp[rel.info >> 8];
+                       struct symbol sym;
+                       swap_symbol(&sym, symp);
+
+                       uae_u32 shindex;
+                       uae_u32 addr;
+                       uae_u32 s;
+                       uae_u32 relocaddr;
+
+                       relocaddr = rel.offset;
 
-void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock)
+                       if (sym.shindex != SHN_XINDEX) {
+                               shindex = sym.shindex;
+                       } else {
+                               if (symtab_shndx == NULL)
+                                       return NULL;
+                               shindex = ((uae_u32*)(file + symtab_shndx->offset))[rel.info >> 8];
+                       }
+                       uae_char *namep = (uae_char*)(file + gl((uae_u8*)(&shp_first[shsymtab.link].offset)) + sym.name);
+                       bool doreloc = false;
+                       TCHAR *name = au(namep);
+                       switch (shindex)
+                       {
+                               case SHN_COMMON:
+                               {
+                                       write_log(_T("ELF Common symbol '%s'"), name);
+                                       break;
+                               }
+                               case SHN_ABS:
+                               {
+                                       s = sym.value;
+                                       doreloc = true;
+                                       break;
+                               }
+                               case SHN_UNDEF:
+                               {
+                                       if ((rel.info & 0xff) != 0) {
+                                               write_log(_T("ELF Undefined symbol '%s'\n"), name);
+                                       }
+                               }
+                               default:
+                               {
+                                       if (sectionbases[shindex] == 0xffffffff) {
+                                               s = 0;
+                                       } else {
+                                               s = sectionbases[shindex] + sym.value;
+                                               doreloc = true;
+                                       }
+                                       break;
+                               }
+                       }
+                       if (doreloc) {
+                               bool has = false;
+                               switch (rel.info & 0xff)
+                               {
+                               case R_68K_32:
+                                       addr = s + rel.addend;
+                                       if (outptr) {
+                                               outptr[relocaddr + 0] = (uae_u8)(addr >> 24);
+                                               outptr[relocaddr + 1] = (uae_u8)(addr >> 16);
+                                               outptr[relocaddr + 2] = (uae_u8)(addr >> 8);
+                                               outptr[relocaddr + 3] = (uae_u8)(addr >> 0);
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_16:
+                                       addr = s + rel.addend;
+                                       if (outptr) {
+                                               outptr[relocaddr + 0] = (uae_u8)(addr >> 8);
+                                               outptr[relocaddr + 1] = (uae_u8)(addr >> 0);
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_8:
+                                       addr = s + rel.addend;
+                                       if (outptr) {
+                                               outptr[relocaddr] = (uae_u8)addr;
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_PC32:
+                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       if (outptr) {
+                                               outptr[relocaddr + 0] = (uae_u8)(addr >> 24);
+                                               outptr[relocaddr + 1] = (uae_u8)(addr >> 16);
+                                               outptr[relocaddr + 2] = (uae_u8)(addr >> 8);
+                                               outptr[relocaddr + 3] = (uae_u8)(addr >> 0);
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_PC16:
+                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       if (outptr) {
+                                               outptr[relocaddr + 0] = (uae_u8)(addr >> 8);
+                                               outptr[relocaddr + 1] = (uae_u8)(addr >> 0);
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_PC8:
+                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       if (outptr) {
+                                               outptr[relocaddr] = (uae_u8)addr;
+                                       }
+                                       has = true;
+                                       break;
+                               case R_68K_NONE:
+                               default:
+                                       break;
+                               }
+                               if (has) {
+                                       if (seg)
+                                               addr += seg + 4;
+                                       addsimplesymbol(name, addr, 0, SYMBOL_GLOBAL, segmentid, i);
+                               }
+                       }
+                       xfree(name);
+               }
+               outptr = NULL;
+       }
+#if 0
+       if (debuginfo) {
+               uae_u8 *p = debuginfo;
+               while (debuginfo_size > 0) {
+                       uae_u8 *start = p;
+                       uae_u32 length = gl(p);
+                       p += 4;
+                       uae_u8 *end = p + length;
+                       p += 2;
+                       uae_u32 abbrev_offset = gl(p);
+                       p += 4;
+                       uae_u8 ptr_size = *p++;
+                       while (p < end) {
+                               uae_u8 abbrevnum = *p++;
+                               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;
+                                               break;
+                                       }
+                                       case 2:
+                                       {
+                                               p += 4 + 1 + 1 + 4;
+                                               break;
+                                       }
+                                       case 3:
+                                       {
+                                               p += 1 + 1 + 4;
+                                               break;
+                                       }
+                               }
+                       }
+                       debuginfo_size -= length;
+               }
+       }
+#endif
+
+end:
+       xfree(sectionoffsets);
+       xfree(sectionbases);
+       return outp;
+}
+
+void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock, bool residentonly)
 {
        uae_u8 *file = NULL;
-       int filelen;
-       bool hasfile = false;
+       uae_u8 *symfile = NULL;
+       int filelen, symfilelen;
+       bool elffile = false, elfsymfile = false;
        int fileoffset = 0;
        int segmentid;
 
        if (!debugmem_initialized)
-               debugmem_init();
+               debugmem_init(true);
        if (!seg || !debugmem_initialized)
                return;
        seg *= 4;
        uaecptr seg2 = seg;
        uaecptr resident = 0;
-       while (seg) {
-               uaecptr next = get_long(seg) * 4;
-               uaecptr len = get_long(seg - 4) * 4;
-               for (int i = 0; i < len - 26; i += 2) {
-                       uae_u16 w = get_word(seg + 4 + i);
-                       if (w == 0x4afc) {
-                               uae_u32 l = get_long(seg + 4 + i + 2);
-                               if (l == seg + 4 + i) {
-                                       resident = seg + 4 + i;
-                                       seg = 0;
-                                       break;
+       if (residentonly) {
+               while (seg) {
+                       uaecptr next = get_long(seg) * 4;
+                       uaecptr len = get_long(seg - 4) * 4;
+                       for (int i = 0; i < len - 26; i += 2) {
+                               uae_u16 w = get_word(seg + 4 + i);
+                               if (w == 0x4afc) {
+                                       uae_u32 l = get_long(seg + 4 + i + 2);
+                                       if (l == seg + 4 + i) {
+                                               resident = seg + 4 + i;
+                                               seg = 0;
+                                               break;
+                                       }
                                }
                        }
+                       seg = next;
                }
-               seg = next;
+               if (!resident)
+                       return;
        }
-       if (!resident)
-               return;
        console_out_f(_T("Adding segment %08x, Resident %08x.\n"), seg2, resident);
        struct debugsegtracker *sg = NULL;
        for (segmentid = 0; segmentid < MAX_DEBUGSEGS; segmentid++) {
@@ -2040,28 +2792,59 @@ void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock)
                nativepath[0] = 0;
                strcpyah_safe(aname, name, sizeof aname);
                sg->name = au(aname);
-               if (lock && !get_native_path(ctx, lock, nativepath)) {
-                       struct zfile *zf = zfile_fopen(nativepath, _T("rb"));
-                       if (zf) {
-                               file = zfile_getdata(zf, 0, -1, &filelen);
-                               zfile_fclose(zf);
-
+               if (!lock) {
+                       _tcscpy(nativepath, currprefs.mountconfig[0].ci.rootdir);
+                       _tcscat(nativepath, sg->name);
+               } else {
+                       get_native_path(ctx, lock, nativepath);
+               }
+               struct zfile *zf = zfile_fopen(nativepath, _T("rb"));
+               if (zf) {
+                       file = zfile_getdata(zf, 0, -1, &filelen);
+                       zfile_fclose(zf);
+               }
+               _tcscat(nativepath, _T(".dbg"));
+               zf = zfile_fopen(nativepath, _T("rb"));
+               if (zf) {
+                       symfile = zfile_getdata(zf, 0, -1, &symfilelen);
+                       zfile_fclose(zf);
+               }
+               if (file) {
+                       uae_u32 v = gl(file);
+                       if (v == 0x7f454c46) {
+                               // elf
+                               elffile = true;
+                       } else if (v == 0x000003f3) {
+                               // hunk
+                               if (gl(file + 4) == 0x0) {
+                                       int hunks = gl(file + 8);
+                                       fileoffset = 5 * 4 + hunks * 4;
+                               }
+                       } else {
+                               xfree(file);
+                               file = NULL;
                        }
-                       while (file) {
-                               if (gl(file) != 0x03f3)
-                                       break;
-                               if (gl(file + 4) != 0x0)
-                                       break;
-                               int hunks = gl(file + 8);
-                               hasfile = true;
-                               fileoffset = 5 * 4 + hunks * 4;
-                               break;
+               }
+               if (symfile) {
+                       uae_u32 v = gl(symfile);
+                       if (v == 0x7f454c46) {
+                               elfsymfile = true;
+                       } else {
+                               xfree(symfile);
+                               symfile = NULL;
                        }
                }
                console_out_f(_T("Name '%s', native path '%s'\n"), sg->name, nativepath[0] ? nativepath : _T("<n/a>"));
        } else {
                sg->name = my_strdup(_T("<unknown>"));
        }
+
+       if (elfsymfile) {
+               loadelffile(symfile, symfilelen, seg, segmentid, NULL, false);
+       } else if (elffile) {
+               loadelffile(file, filelen, seg, segmentid, NULL, false);
+       }
+
        int parentid = 0;
        int cnt = 1;
        seg = seg2;
@@ -2074,7 +2857,7 @@ void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock)
                        parentid = dm->id;
                        dm->parentid = dm->id;
                }
-               if (hasfile) {
+               if (file && !elffile) {
                        dm->idtype = gl(&file[fileoffset]);
                        fileoffset += 4;
                        int hunklen = gl(&file[fileoffset]);
@@ -2154,7 +2937,9 @@ void debugmem_remsegs(uaecptr seg)
                }
                seg = next;
        }
-       console_out_f(_T("Freeing segment %08x...\n"), seg);
+
+       console_out_f(_T("Freeing segment %08x...\n"), seg2);
+
        struct debugmemallocs *nextavail = NULL;
        for (int i = 0; i < MAX_DEBUGMEMALLOCS; i++) {
                struct debugmemallocs *alloc = allocs[i];
@@ -2164,6 +2949,7 @@ void debugmem_remsegs(uaecptr seg)
                        nextavail = alloc;
                }
        }
+
        struct debugsegtracker *sg = NULL;
        for (int i = 0; i < MAX_DEBUGSEGS; i++) {
                if (dsegt[i]->allocid == parentid) {
@@ -2173,6 +2959,14 @@ void debugmem_remsegs(uaecptr seg)
                        break;
                }
        }
+
+       for (int i = 0; i < symbolcnt; i++) {
+               struct debugsymbol *ds = symbols[i];
+               if (ds->segment == parentid) {
+                       ds->allocid = 0;
+               }
+       }
+
        if (!sg) {
                return;
        }
@@ -2195,53 +2989,174 @@ static void allocate_stackframebuffers(void)
        stackframecntsuper = 0;
 }
 
-void debugmem_init(void)
+#if 0
+void debugmem_add_seglist(TrapContext *ctx, uaecptr segList, uaecptr aname)
 {
-       debug_waiting = false;
-       if (!debugmem_bank.baseaddr) {
-               int size = 0x10000000;
-               for (uae_u32 mem = 0x70000000; mem < 0xf0000000; mem += size) {
-                       if (get_mem_bank_real(mem) == &dummy_bank && get_mem_bank_real(mem + size - 65536) == &dummy_bank) {
-                               debugmem_bank.reserved_size = size;
-                               debugmem_bank.mask = debugmem_bank.reserved_size - 1;
-                               debugmem_bank.start = mem;
-                               if (!mapped_malloc(&debugmem_bank)) {
-                                       console_out_f(_T("Failed to automatically allocate debugmem (mapped_malloc)!\n"));
-                                       return;
+       int rnd = 0;
+       if (!debugmem_initialized) {
+               debugmem_init(false);
+       }
+       for (;;) {
+               if (segtrackerindex >= MAX_DEBUGSEGS) {
+                       segtrackerindex = 0;
+                       rnd++;
+                       if (rnd > 1)
+                               return;
+               } else {
+                       segtrackerindex++;
+               }
+               struct debugsegtracker *st = dsegt[segtrackermax];
+               if (!st->allocid) {
+                       uae_char name[256];
+                       strcpyah_safe(name, aname, sizeof name);
+                       st->name = au(name);
+                       st->resident = mod;
+                       st->allocid = segtrackerindex;
+                       if (segtrackerindex > segtrackermax)
+                               segtrackermax = segtrackerindex;
+                       return;
+               }
+       }
+}
+void debugmem_rem_seglist(TrapContext *ctx, uaecptr segList)
+{
+       for (int i = 0; i < segtrackermax; i++) {
+               struct debugsegtracker *st = dsegt[i];
+               if (st->resident == mod) {
+                       for (int j = 0; j < MAX_DEBUGMEMALLOCS; j++) {
+                               struct debugmemallocs *dm = allocs[j];
+                               if (dm->parentid == st->allocid) {
+                                       dm->id = 0;
+                                       if (segtrackerindex >= j)
+                                               segtrackerindex = j - 1;
                                }
-                               map_banks(&debugmem_bank, debugmem_bank.start >> 16, debugmem_bank.allocated_size >> 16, 0);
-                               console_out_f(_T("Automatically allocated debugmem location: %08x - %08x %08x\n"),
-                                       debugmem_bank.start, debugmem_bank.start + debugmem_bank.allocated_size - 1, debugmem_bank.allocated_size);
-                               break;
                        }
                }
-               if (!debugmem_bank.baseaddr) {
-                       console_out_f(_T("Failed to automatically allocate debugmem (no space)!\n"));
+       }
+}
+
+void debugmem_add_segment(uaecptr mod, uae_u32 num, uae_u32 type, uaecptr start, uae_u32 size)
+{
+       struct debugsegtracker *st = NULL;
+       for (int i = 0; i < segtrackermax; i++) {
+               if (dsegt[i]->resident == mod) {
+                       st = dsegt[i];
+                       break;
+               }
+       }
+       if (!st)
+               return;
+       struct debugmemallocs *dm = getallocblock();
+       if (!dm)
+               return;
+       dm->parentid = st->allocid;
+       dm->internalid = num;
+       dm->type = type;
+       dm->start = start;
+       dm->size = size;
+}
+void debugmem_rem_segment(uaecptr mod, uaecptr start)
+{
+       struct debugsegtracker *st = NULL;
+       for (int i = 0; i < segtrackermax; i++) {
+               if (dsegt[i]->resident == mod) {
+                       st = dsegt[i];
+                       break;
+               }
+       }
+       if (!st)
+               return;
+       for (int j = 0; j < MAX_DEBUGMEMALLOCS; j++) {
+               struct debugmemallocs *dm = allocs[j];
+               if (start >= dm->start && start < dm->start + dm->size) {
+                       dm->id = 0;
+                       for (int j = 0; j < MAX_DEBUGSYMS; j++) {
+                               struct debugsymbol *ds = symbols[j];
+                               if (ds->allocid && dm->start <= ds->value && dm->start + dm->size >= ds->value) {
+                                       ds->allocid = 0;
+                               }
+                       }
+                       symbolindex = 0;
+               }
+       }
+}
+void debugmem_add_symbol(uae_u32 value, uaecptr aname)
+{
+       int rnd = 0;
+       for (;;) {
+               if (symbolindex >= MAX_DEBUGSYMS) {
+                       symbolindex = 0;
+                       rnd++;
+                       if (rnd > 1)
+                               return;
+               } else {
+                       symbolindex++;
+               }
+               struct debugsymbol *ds = symbols[symbolindex];
+               if (ds->allocid == 0) {
+                       uae_char name[256];
+                       strcpyah_safe(name, aname, sizeof name);
+                       ds->allocid = symbolindex;
+                       ds->value = value;
+                       ds->name = au(name);
+                       ds->type = SYMBOL_GLOBAL;
+                       if (symbolindex > symbolcnt)
+                               symbolcnt = symbolindex;
                        return;
                }
        }
-       memset(debugmem_bank.baseaddr, 0xa5, debugmem_bank.allocated_size);
-       if (!debugmem_func_lgeti) {
-
-               debugmem_func_lgeti = debugmem_bank.lgeti;
-               debugmem_func_wgeti = debugmem_bank.wgeti;
-               debugmem_func_lget = debugmem_bank.lget;
-               debugmem_func_wget = debugmem_bank.wget;
-               debugmem_func_bget = debugmem_bank.bget;
-               debugmem_func_lput = debugmem_bank.lput;
-               debugmem_func_wput = debugmem_bank.wput;
-               debugmem_func_bput = debugmem_bank.bput;
-               debugmem_func_xlate = debugmem_bank.xlateaddr;
-
-               debugmem_bank.lgeti = debugmem_lgeti;
-               debugmem_bank.wgeti = debugmem_wgeti;
-               debugmem_bank.lget = debugmem_lget;
-               debugmem_bank.wget = debugmem_wget;
-               debugmem_bank.bget = debugmem_bget;
-               debugmem_bank.lput = debugmem_lput;
-               debugmem_bank.wput = debugmem_wput;
-               debugmem_bank.bput = debugmem_bput;
-               debugmem_bank.xlateaddr = debugmem_xlate;
+}
+#endif
+
+void debugmem_init(bool initmem)
+{
+       debug_waiting = false;
+       if (initmem) {
+               if (!debugmem_bank.baseaddr) {
+                       int size = 0x10000000;
+                       for (uae_u32 mem = 0x70000000; mem < 0xf0000000; mem += size) {
+                               if (get_mem_bank_real(mem) == &dummy_bank && get_mem_bank_real(mem + size - 65536) == &dummy_bank) {
+                                       debugmem_bank.reserved_size = size;
+                                       debugmem_bank.mask = debugmem_bank.reserved_size - 1;
+                                       debugmem_bank.start = mem;
+                                       if (!mapped_malloc(&debugmem_bank)) {
+                                               console_out_f(_T("Failed to automatically allocate debugmem (mapped_malloc)!\n"));
+                                               return;
+                                       }
+                                       map_banks(&debugmem_bank, debugmem_bank.start >> 16, debugmem_bank.allocated_size >> 16, 0);
+                                       console_out_f(_T("Automatically allocated debugmem location: %08x - %08x %08x\n"),
+                                               debugmem_bank.start, debugmem_bank.start + debugmem_bank.allocated_size - 1, debugmem_bank.allocated_size);
+                                       break;
+                               }
+                       }
+                       if (!debugmem_bank.baseaddr) {
+                               console_out_f(_T("Failed to automatically allocate debugmem (no space)!\n"));
+                               return;
+                       }
+               }
+               memset(debugmem_bank.baseaddr, 0xa5, debugmem_bank.allocated_size);
+               if (!debugmem_func_lgeti) {
+
+                       debugmem_func_lgeti = debugmem_bank.lgeti;
+                       debugmem_func_wgeti = debugmem_bank.wgeti;
+                       debugmem_func_lget = debugmem_bank.lget;
+                       debugmem_func_wget = debugmem_bank.wget;
+                       debugmem_func_bget = debugmem_bank.bget;
+                       debugmem_func_lput = debugmem_bank.lput;
+                       debugmem_func_wput = debugmem_bank.wput;
+                       debugmem_func_bput = debugmem_bank.bput;
+                       debugmem_func_xlate = debugmem_bank.xlateaddr;
+
+                       debugmem_bank.lgeti = debugmem_lgeti;
+                       debugmem_bank.wgeti = debugmem_wgeti;
+                       debugmem_bank.lget = debugmem_lget;
+                       debugmem_bank.wget = debugmem_wget;
+                       debugmem_bank.bget = debugmem_bget;
+                       debugmem_bank.lput = debugmem_lput;
+                       debugmem_bank.wput = debugmem_wput;
+                       debugmem_bank.bput = debugmem_bput;
+                       debugmem_bank.xlateaddr = debugmem_xlate;
+               }
        }
        alloccnt = 0;
        if (!allocs) {
@@ -2320,8 +3235,10 @@ void debugmem_init(void)
        linemapsize = 0;
        codefilecnt = 0;
        symbolcnt = 0;
+       symbolindex = 0;
        executable_last_segment = 0;
        segtrackermax = 0;
+       segtrackerindex = 0;
        debugmem_initialized = true;
        debugmem_chiplimit = 0x400;
        debugstack_word_state = 0;
@@ -2416,14 +3333,14 @@ bool debugmem_get_symbol_value(const TCHAR *name, uae_u32 *valp)
        }
        for (int i = 0; i < symbolcnt; i++) {
                struct debugsymbol *ds = symbols[i];
-               if (!_tcscmp(ds->name, name)) {
+               if (ds->allocid && !_tcscmp(ds->name, name)) {
                        *valp = ds->value;
                        return true;
                }
        }
        for (int i = 0; i < symbolcnt; i++) {
                struct debugsymbol *ds = symbols[i];
-               if (!_tcsicmp(ds->name, name)) {
+               if (ds->allocid && !_tcsicmp(ds->name, name)) {
                        *valp = ds->value;
                        return true;
                }
@@ -2438,7 +3355,7 @@ int debugmem_get_symbol(uaecptr addr, TCHAR *out, int maxsize)
        int found = 0;
        for (int i = 0; i < symbolcnt; i++) {
                struct debugsymbol *ds = symbols[i];
-               if (ds->value == addr) {
+               if (ds->allocid && ds->value == addr) {
                        if (out) {
                                TCHAR txt[256];
                                _tcscpy(txt, ds->name);
@@ -2531,7 +3448,10 @@ int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize)
                                break;
                        }
                        struct debugcodefile *cf = lm->file;
-                       if (cf->lineptr[line] && cf->lineptr[line][0]) {
+                       if (!cf->data) {
+                               loadcodefiledata(cf);
+                       }
+                       if (cf->data && cf->lineptr[line] && cf->lineptr[line][0]) {
                                if (last_codefile != cf) {
                                        TCHAR txt[256];
                                        last_codefile = cf;
@@ -2769,3 +3689,52 @@ bool debugmem_illg(uae_u16 opcode)
        debugmem_break(12);
        return true;
 }
+
+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
+};
+
+struct zfile *read_executable_rom(struct zfile *z, int size, int maxblocks)
+{
+       int len, outlen;
+       uae_u8 *out;
+       uae_u8 *file = zfile_getdata(z, 0, -1, &len);
+       if (!file)
+               return NULL;
+       if (!debugmem_initialized)
+               debugmem_init(false);
+       if (!debugmem_initialized)
+               return NULL;
+       uae_u8 header[8] = { 0 };
+       zfile_fseek(z, 0, SEEK_SET);
+       zfile_fread(header, 1, sizeof(header), z);
+       zfile_fseek(z, 0, SEEK_SET);
+       if (header[0] == 0x7f)
+               out = loadelffile(file, len, 0, -1, &outlen, true);
+       else
+               out = loadhunkfile(file, len, 0, -1, &outlen, true);
+       if (out) {
+               if (outlen > size * maxblocks) {
+                       write_log(_T("read_executable_rom '%s' size %d larger than max %d\n"), zfile_getname(z), outlen, size);
+                       xfree(out);
+                       return NULL;
+               }
+               int romsize = ((outlen + size - 1) / size) * size;
+               uae_u8 *temp = xcalloc(uae_u8, romsize);
+               memcpy(temp, out, outlen);
+               if (outlen < romsize && romsize == 524288) {
+                       if (outlen < size - 16) {
+                               memcpy(temp + size - 20, romend, sizeof(romend));
+                       }
+                       kickstart_fix_checksum(temp, size);
+               }
+               struct zfile *zo = zfile_fopen_empty(NULL, zfile_getname(z), romsize);
+               zfile_fwrite(temp, 1, romsize, zo);
+               zfile_fseek(zo, 0, SEEK_SET);
+               write_log(_T("read_executable_rom loaded '%s' size %d -> %d\n"), zfile_getname(z), outlen, romsize);
+               return zo;
+       }
+       xfree(file);
+       return NULL;
+}
index 28ddc167b87ff63ba26ac7177f7d889e674cd501..447e1ead8ede30021f596bfeaa2826e52ccbae60 100644 (file)
@@ -8965,10 +8965,11 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *ctx)
                debugmem_break(8);
                return 1;
        } else if (mode == 202) {
-               // a0 = segment, a1 = name, d2 = lock
-               debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2));
+               // a0 = seglist, a1 = name, d2 = lock
+               debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2), true);
                return 1;
        } else if (mode == 203) {
+               // a0 = seglist
                debugmem_remsegs(trap_get_areg(ctx, 0));
                return 1;
        } else if (mode == 204 || mode == 206) {
@@ -8994,6 +8995,14 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *ctx)
        } else if (mode == 210) {
                // debug trapcode
                debugmem_trap(trap_get_areg(ctx, 0));
+       } else if (mode == 212) {
+               // a0 = seglist, a1 = name, d2 = lock
+               debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2), false);
+               return 1;
+       } else if (mode == 213) {
+               // a0 = seglist
+               debugmem_remsegs(trap_get_areg(ctx, 0));
+               return 1;
        } else if (mode == 299) {
                return debugmem_exit();
 
index 725579bebc20066feec5a0f738507cc6675447b8..57ace369d6a7c0de25b7a4f0fefcc043f9ae0604 100644 (file)
@@ -60,6 +60,10 @@ extern int debug_write_memory_8 (uaecptr addr, uae_u8 v);
 extern bool debug_enforcer(void);
 extern int debug_safe_addr(uaecptr addr, int size);
 
+extern void debug_init_trainer(const TCHAR*);
+extern void debug_trainer_match(void);
+extern bool debug_opcode_watch;
+
 #define BREAKPOINT_TOTAL 20
 #define BREAKPOINT_REG_Dx 0
 #define BREAKPOINT_REG_Ax 8
index 25a633050f8716391dabd30ba2c9de4535d7acb1..4fc3be47aba50762a4a2a1be829cab863cb38c21 100644 (file)
@@ -1,10 +1,10 @@
 
 uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack);
-void debugmem_init(void);
+void debugmem_init(bool);
 uaecptr debugmem_allocmem(int mode, uae_u32 size, uae_u32 flags, uae_u32 caller);
 uae_u32 debugmem_freemem(int mode, uaecptr addr, uae_u32 size, uae_u32 caller);
 void debugmem_trap(uaecptr addr);
-void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock);
+void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock, bool residentonly);
 void debugmem_remsegs(uaecptr seg);
 uae_u32 debugmem_exit(void);
 bool debugmem_break(int);
index e5023aef830a9743e4347ba8b176123a4944531a..f55618d37aa013af79ec6c0a3d1b8324898a4830 100644 (file)
@@ -685,6 +685,7 @@ struct uae_prefs {
        TCHAR quitstatefile[MAX_DPATH];
        TCHAR statefile[MAX_DPATH];
        TCHAR inprecfile[MAX_DPATH];
+       TCHAR trainerfile[MAX_DPATH];
        bool inprec_autoplay;
        bool refresh_indicator;
 
index d2f5ca7ce2c20128df89c8f7bd386cbac314b6bc..57ce33e2cf19601a24622f5f937b71e4ccd5ef4f 100644 (file)
@@ -2378,7 +2378,7 @@ static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHA
        return addr;
 }
 
-static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
+uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
 {
        uaecptr addr = pc;
        uae_s16 disp16;
@@ -3953,6 +3953,7 @@ static void m68k_reset2(bool hardreset)
        }
 //     regs.ce020memcycles = 0;
        regs.ce020startcycle = regs.ce020endcycle = 0;
+
        fill_prefetch ();
 }
 
@@ -4020,6 +4021,7 @@ static void cpu_do_fallback(void)
                fallback_cpu_model = 0;
        }
        init_m68k();
+       build_cpufunctbl();
        m68k_reset2(false);
        if (!fallbackmode) {
                // restore original 68020+
@@ -5088,6 +5090,9 @@ static void m68k_run_1 (void)
                                        //write_log (_T("%08X-%04X "), pc, r->opcode);
                                }
 #endif
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
                                do_cycles (cpu_cycles);
                                r->instruction_pc = m68k_getpc ();
                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
@@ -5193,6 +5198,10 @@ static void m68k_run_1_ce (void)
                                                inprec_playdebug_cpu (1);
                                }
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
                                r->instruction_pc = m68k_getpc ();
                                (*cpufunctbl[r->opcode])(r->opcode);
                                wait_memory_cycles();
@@ -6039,6 +6048,10 @@ static void m68k_run_3ce (void)
                                if (regs.cacr & 0x8000)
                                        fill_icache040(r->instruction_pc + 16);
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
                                (*cpufunctbl[r->opcode])(r->opcode);
 
                                if (r->spcflags) {
@@ -6080,6 +6093,10 @@ static void m68k_run_3p(void)
                                if (regs.cacr & 0x8000)
                                        fill_icache040(r->instruction_pc + 16);
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
                                (*cpufunctbl[r->opcode])(r->opcode);
 
                                cpu_cycles = 1 * CYCLE_UNIT;
@@ -6215,6 +6232,10 @@ static void m68k_run_2ce (void)
                                                inprec_playdebug_cpu (1);
                                }
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
                                (*cpufunctbl[r->opcode])(r->opcode);
                
                                wait_memory_cycles();
@@ -6337,6 +6358,10 @@ static void m68k_run_2p (void)
                                                inprec_playdebug_cpu (1);
                                }
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
+
                                if (cpu_cycles > 0)
                                        x_do_cycles(cpu_cycles);
 
@@ -6436,6 +6461,9 @@ static void m68k_run_2 (void)
                                r->opcode = x_get_iword(0);
                                count_instr (r->opcode);
 
+                               if (debug_opcode_watch) {
+                                       debug_trainer_match();
+                               }
                                do_cycles (cpu_cycles);
 
                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
@@ -6616,6 +6644,9 @@ void m68k_go (int may_quit)
                if (changed_prefs.inprecfile[0] && input_record)
                        inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
 
+               if (changed_prefs.trainerfile[0])
+                       debug_init_trainer(changed_prefs.trainerfile);
+
                set_cpu_tracer (false);
 
 #ifdef DEBUGGER
@@ -7704,17 +7735,17 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                } else if (lookup->mnemo == i_MVMEL) {
                        uae_u16 mask = extra;
                        pc += 2;
-                       pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                       pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                        movemout (instrname, mask, dp->dmode, 0, true);
                } else if (lookup->mnemo == i_MVMLE) {
                        uae_u16 mask = extra;
                        pc += 2;
                        if (movemout(instrname, mask, dp->dmode, 0, false))
                                _tcscat(instrname, _T(","));
-                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
                        TCHAR *p;
-                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                        extra = get_word_debug(pc);
                        pc += 2;
                        p = instrname + _tcslen(instrname);
@@ -7726,13 +7757,13 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        TCHAR *p;
                        pc += 2;
                        if (!(extra & 0x0800)) {
-                               pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                                p = instrname + _tcslen(instrname);
                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                        } else {
                                p = instrname + _tcslen(instrname);
                                _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
-                               pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                        }
                } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
                                   lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
@@ -7747,7 +7778,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                                reg = (extra >> 12) & 7;
                        if (lookup->mnemo == i_BFINS)
                                _stprintf(p, _T("D%d,"), reg);
-                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                        _tcscat(instrname, _T(" {"));
                        p = instrname + _tcslen(instrname);
                        if (extra & 0x0800)
@@ -7839,9 +7870,9 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                                        else
                                                movemout(instrname, regmask, dp->dmode, fpmode, false);
                                        _tcscat(instrname, _T(","));
-                                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                                } else {
-                                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                                        p = instrname + _tcslen(instrname);
                                        if (mode & 1)
                                                _stprintf(p, _T(",D%d"), dreg);
@@ -7861,7 +7892,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                                        _tcscat(instrname, _T(" "));
                                        p = instrname + _tcslen(instrname);
                                        _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
-                                       pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
                                        p = instrname + _tcslen(instrname);
                                        if (size == 7) {
                                                _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
@@ -7875,7 +7906,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                                                _tcscat(instrname, _T("."));
                                                _tcscat(instrname, fpsizes[size]);
                                                _tcscat(instrname, _T(" "));
-                                               pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
+                                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
                                        } else { // source is FPx
                                                p = instrname + _tcslen(instrname);
                                                _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
@@ -7893,7 +7924,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        _tcscpy(instrname, _T("A-LINE"));
                } else {
                        if (dp->suse) {
-                               pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+                               pc = ShowEA (NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
 
                                // JSR x(a6) / JMP x(a6)
                                if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) {
@@ -7912,7 +7943,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        if (dp->suse && dp->duse)
                                _tcscat (instrname, _T(","));
                        if (dp->duse) {
-                               pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
+                               pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
                        }
                }