aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/script/debugger
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/script/debugger
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/script/debugger')
-rw-r--r--Src/Wasabi/api/script/debugger/api_makidebug.cpp20
-rw-r--r--Src/Wasabi/api/script/debugger/api_makidebug.h134
-rw-r--r--Src/Wasabi/api/script/debugger/debugapi.cpp62
-rw-r--r--Src/Wasabi/api/script/debugger/debugapi.h28
-rw-r--r--Src/Wasabi/api/script/debugger/debuggerui.cpp11
-rw-r--r--Src/Wasabi/api/script/debugger/debuggerui.h42
-rw-r--r--Src/Wasabi/api/script/debugger/debugsymbols.cpp75
-rw-r--r--Src/Wasabi/api/script/debugger/debugsymbols.h38
-rw-r--r--Src/Wasabi/api/script/debugger/disasm.cpp193
-rw-r--r--Src/Wasabi/api/script/debugger/disasm.h38
-rw-r--r--Src/Wasabi/api/script/debugger/jitd.cpp176
-rw-r--r--Src/Wasabi/api/script/debugger/jitd.h71
-rw-r--r--Src/Wasabi/api/script/debugger/jitdbreak.cpp27
-rw-r--r--Src/Wasabi/api/script/debugger/jitdbreak.h22
-rw-r--r--Src/Wasabi/api/script/debugger/sdebuggerui.cpp437
-rw-r--r--Src/Wasabi/api/script/debugger/sdebuggerui.h65
-rw-r--r--Src/Wasabi/api/script/debugger/sourcecodeline.cpp69
-rw-r--r--Src/Wasabi/api/script/debugger/sourcecodeline.h100
-rw-r--r--Src/Wasabi/api/script/debugger/vcpudebug.cpp99
-rw-r--r--Src/Wasabi/api/script/debugger/vcpudebug.h39
20 files changed, 1746 insertions, 0 deletions
diff --git a/Src/Wasabi/api/script/debugger/api_makidebug.cpp b/Src/Wasabi/api/script/debugger/api_makidebug.cpp
new file mode 100644
index 00000000..af819fd9
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/api_makidebug.cpp
@@ -0,0 +1,20 @@
+#include <precomp.h>
+#include "api_makidebug.h"
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+#define CBCLASS api_makiDebuggerI
+START_DISPATCH;
+ VCB(API_MAKIDEBUGGER_DEBUGGER_TRACE, debugger_trace);
+ CB(API_MAKIDEBUGGER_DEBUGGER_ISACTIVE, debugger_isActive);
+ CB(API_MAKIDEBUGGER_DEBUGGER_GETVIP, debugger_getVIP);
+ CB(API_MAKIDEBUGGER_DEBUGGER_GETVSD, debugger_getVSD);
+ CB(API_MAKIDEBUGGER_DEBUGGER_GETVCC, debugger_getVCC);
+ CB(API_MAKIDEBUGGER_DEBUGGER_GETVSP, debugger_getVSP);
+ CB(API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT, debugger_filterEvent);
+ VCB(API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE, debugger_eventComplete);
+ CB(API_MAKIDEBUGGER_DEBUGGER_CREATEJITD, debugger_createJITD);
+ CB(API_MAKIDEBUGGER_DEBUGGER_READSTACK, debugger_readStack);
+ CB(API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK, debugger_getCodeBlock);
+END_DISPATCH;
diff --git a/Src/Wasabi/api/script/debugger/api_makidebug.h b/Src/Wasabi/api/script/debugger/api_makidebug.h
new file mode 100644
index 00000000..c55d130e
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/api_makidebug.h
@@ -0,0 +1,134 @@
+#ifndef __API_MAKIDEBUG_H
+#define __API_MAKIDEBUG_H
+
+/*---------------------------------------------------------
+api_makiDebugger
+ void debugger_trace();
+ int debugger_isActive();
+ int debugger_getVIP();
+ int debugger_getVSD();
+ int debugger_getVCC();
+ int debugger_getVSP();
+ int debugger_filterEvent(int vcpuid, int eventid);
+ void debugger_eventComplete();
+ MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1);
+ int debugger_readStack(int n);
+ int debugger_getCodeBlock(int vcpuid);
+---------------------------------------------------------*/
+
+#include <wasabicfg.h>
+
+#ifndef WASABI_COMPILE_SCRIPT
+#error "This module requires the script api"
+#endif
+
+#ifndef WASABI_COMPILE_MAKIDEBUG
+#error "This module requires the script debugger api"
+#endif
+
+#include <bfc/dispatch.h>
+#include <api/script/scriptvar.h>
+
+class MakiJITD;
+
+class NOVTABLE api_makiDebugger : public Dispatchable {
+ public:
+ void debugger_trace();
+ int debugger_isActive();
+ int debugger_getVIP();
+ int debugger_getVSD();
+ int debugger_getVCC();
+ int debugger_getVSP();
+ int debugger_filterEvent(int vcpuid, int eventid);
+ void debugger_eventComplete();
+ MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1);
+ scriptVar debugger_readStack(int n);
+ const char *debugger_getCodeBlock(int vcpuid);
+
+ enum {
+ API_MAKIDEBUGGER_DEBUGGER_TRACE = 0,
+ API_MAKIDEBUGGER_DEBUGGER_ISACTIVE = 10,
+ API_MAKIDEBUGGER_DEBUGGER_GETVIP = 20,
+ API_MAKIDEBUGGER_DEBUGGER_GETVSD = 30,
+ API_MAKIDEBUGGER_DEBUGGER_GETVCC = 40,
+ API_MAKIDEBUGGER_DEBUGGER_GETVSP = 50,
+ API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT = 60,
+ API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE = 70,
+ API_MAKIDEBUGGER_DEBUGGER_CREATEJITD = 80,
+ API_MAKIDEBUGGER_DEBUGGER_READSTACK = 90,
+ API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK = 100,
+ };
+};
+
+inline void api_makiDebugger::debugger_trace() {
+ _voidcall(API_MAKIDEBUGGER_DEBUGGER_TRACE);
+}
+
+inline int api_makiDebugger::debugger_isActive() {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_ISACTIVE, (int)0);
+}
+
+inline int api_makiDebugger::debugger_getVIP() {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_GETVIP, (int)0);
+}
+
+inline int api_makiDebugger::debugger_getVSD() {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_GETVSD, (int)0);
+}
+
+inline int api_makiDebugger::debugger_getVCC() {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_GETVCC, (int)0);
+}
+
+inline int api_makiDebugger::debugger_getVSP() {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_GETVSP, (int)0);
+}
+
+inline int api_makiDebugger::debugger_filterEvent(int vcpuid, int eventid) {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_FILTEREVENT, (int)0, vcpuid, eventid);
+}
+
+inline void api_makiDebugger::debugger_eventComplete() {
+ _voidcall(API_MAKIDEBUGGER_DEBUGGER_EVENTCOMPLETE);
+}
+
+inline MakiJITD *api_makiDebugger::debugger_createJITD(int vcpuid, int bringitup) {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_CREATEJITD, (MakiJITD *)NULL, vcpuid, bringitup);
+}
+
+inline const char *api_makiDebugger::debugger_getCodeBlock(int vcpuid) {
+ return _call(API_MAKIDEBUGGER_DEBUGGER_GETCODEBLOCK, (const char *)NULL, vcpuid);
+}
+
+inline scriptVar api_makiDebugger::debugger_readStack(int n) {
+ scriptVar v={0,0};
+ return _call(API_MAKIDEBUGGER_DEBUGGER_READSTACK, v, n);
+}
+
+class api_makiDebuggerI : public api_makiDebugger {
+ public:
+ virtual void debugger_trace()=0;
+ virtual int debugger_isActive()=0;
+ virtual int debugger_getVIP()=0;
+ virtual int debugger_getVSD()=0;
+ virtual int debugger_getVCC()=0;
+ virtual int debugger_getVSP()=0;
+ virtual int debugger_filterEvent(int vcpuid, int eventid)=0;
+ virtual void debugger_eventComplete()=0;
+ virtual MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1)=0;
+ virtual scriptVar debugger_readStack(int n)=0;
+ virtual const char *debugger_getCodeBlock(int vcpuid)=0;
+
+ protected:
+ RECVS_DISPATCH;
+};
+
+// {858E4B64-AF1E-4b64-8D27-EFFAD9F82BB4}
+static const GUID makiDebugApiServiceGuid =
+{ 0x858e4b64, 0xaf1e, 0x4b64, { 0x8d, 0x27, 0xef, 0xfa, 0xd9, 0xf8, 0x2b, 0xb4 } };
+
+extern api_makiDebugger *debugApi;
+
+#endif
+
+
diff --git a/Src/Wasabi/api/script/debugger/debugapi.cpp b/Src/Wasabi/api/script/debugger/debugapi.cpp
new file mode 100644
index 00000000..31ffc9d9
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debugapi.cpp
@@ -0,0 +1,62 @@
+#include <precomp.h>
+#include <api/script/debugger/debugapi.h>
+#include <api/script/debugger/jitd.h>
+#include <api/script/vcpu.h>
+
+api_makiDebugger *debugApi = NULL;
+
+MakiDebuggerApi::MakiDebuggerApi()
+{
+}
+
+MakiDebuggerApi::~MakiDebuggerApi() {
+
+}
+
+void MakiDebuggerApi::debugger_trace() {
+ debugger.trace();
+}
+
+int MakiDebuggerApi::debugger_isActive() {
+ return debugger.isActive();
+}
+
+int MakiDebuggerApi::debugger_getVIP() {
+ return VCPU::VIP;
+}
+
+int MakiDebuggerApi::debugger_getVSD() {
+ return VCPU::VSD;
+}
+
+int MakiDebuggerApi::debugger_getVCC() {
+ return VCPU::VCC;
+}
+
+int MakiDebuggerApi::debugger_getVSP() {
+ return VCPU::VSP;
+}
+
+int MakiDebuggerApi::debugger_filterEvent(int vcpuid, int eventid) {
+ return debugger.filterEvent(vcpuid, eventid);
+}
+
+void MakiDebuggerApi::debugger_eventComplete() {
+ debugger.eventComplete();
+}
+
+MakiJITD *MakiDebuggerApi::debugger_createJITD(int vcpuid, int bringitup) {
+ MakiJITD *jitd = debugger.createJITD(vcpuid);
+ if (bringitup)
+ jitd->setGlobalBreakpoint(1);
+ return jitd;
+}
+
+scriptVar MakiDebuggerApi::debugger_readStack(int n) {
+ VCPUscriptVar v = VCPU::peekAt(n);
+ return v.v;
+}
+
+const char *MakiDebuggerApi::debugger_getCodeBlock(int vcpuid) {
+ return VCPU::getCodeBlock(vcpuid);
+}
diff --git a/Src/Wasabi/api/script/debugger/debugapi.h b/Src/Wasabi/api/script/debugger/debugapi.h
new file mode 100644
index 00000000..2b44fa4f
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debugapi.h
@@ -0,0 +1,28 @@
+#ifndef __MAKIDEBUGAPI_H
+#define __MAKIDEBUGAPI_H
+
+#include <api/script/debugger/api_makidebug.h>
+#include <api/script/debugger/vcpudebug.h>
+
+class MakiDebuggerApi : public api_makiDebuggerI {
+ public:
+ MakiDebuggerApi();
+ virtual ~MakiDebuggerApi();
+
+ virtual void debugger_trace();
+ virtual int debugger_isActive();
+ virtual int debugger_getVIP();
+ virtual int debugger_getVSD();
+ virtual int debugger_getVCC();
+ virtual int debugger_getVSP();
+ virtual int debugger_filterEvent(int vcpuid, int eventid);
+ virtual void debugger_eventComplete();
+ virtual MakiJITD *debugger_createJITD(int vcpuid, int bringitup=1);
+ virtual scriptVar debugger_readStack(int n);
+ virtual const char *debugger_getCodeBlock(int vcpuid);
+
+ private:
+ VCPUDebugger debugger;
+};
+
+#endif
diff --git a/Src/Wasabi/api/script/debugger/debuggerui.cpp b/Src/Wasabi/api/script/debugger/debuggerui.cpp
new file mode 100644
index 00000000..692fdeee
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debuggerui.cpp
@@ -0,0 +1,11 @@
+#include <precomp.h>
+#include "debuggerui.h"
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+#define CBCLASS DebuggerUII
+START_DISPATCH;
+ CB(DEBUGGERUI_MESSAGELOOP, messageLoop);
+ VCB(DEBUGGERUI_SETJITD, setJITD);
+END_DISPATCH;
diff --git a/Src/Wasabi/api/script/debugger/debuggerui.h b/Src/Wasabi/api/script/debugger/debuggerui.h
new file mode 100644
index 00000000..6138b417
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debuggerui.h
@@ -0,0 +1,42 @@
+#ifndef __DEBUGGERUI_H
+#define __DEBUGGERUI_H
+
+#include <bfc/dispatch.h>
+
+class MakiJITD;
+
+/*-------------------------------------------
+DebuggerUI
+ int messageLoop();
+ void setJITD(MakiJITD *jitd);
+-------------------------------------------*/
+
+class DebuggerUI : public Dispatchable {
+ public:
+ int messageLoop();
+ void setJITD(MakiJITD *jitd);
+
+ enum {
+ DEBUGGERUI_MESSAGELOOP = 0,
+ DEBUGGERUI_SETJITD = 10,
+ };
+};
+
+inline int DebuggerUI::messageLoop() {
+ return _call(DEBUGGERUI_MESSAGELOOP, (int)0);
+}
+
+inline void DebuggerUI::setJITD(MakiJITD *jitd) {
+ _voidcall(DEBUGGERUI_SETJITD, jitd);
+}
+
+class DebuggerUII : public DebuggerUI {
+ public:
+ virtual int messageLoop()=0;
+ virtual void setJITD(MakiJITD *jitd)=0;
+
+ protected:
+ RECVS_DISPATCH;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/debugsymbols.cpp b/Src/Wasabi/api/script/debugger/debugsymbols.cpp
new file mode 100644
index 00000000..e3b85980
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debugsymbols.cpp
@@ -0,0 +1,75 @@
+#include <precomp.h>
+#include "debugsymbols.h"
+#include <api/script/debugger/disasm.h>
+#include <api/script/scriptmgr.h>
+#include <api/script/debugger/sourcecodeline.h>
+#include <api/script/vcpu.h>
+
+DebugSymbols::DebugSymbols(int _vcpuid) : disasm(_vcpuid)
+{
+ gotsymbols = 0;
+ SystemObject *so = SOM::getSystemObjectByScriptId(_vcpuid);
+ if (so != NULL)
+ binaryfilename = so->getFilename();
+
+ VCPUcodeBlock *cb = VCPU::getCodeBlockEntry(_vcpuid);
+ if (cb->debugsize != 0) {
+ gotsymbols = 1;
+ char *p = cb->debugsymbols;
+ int n = *(int *)p; p += 4;
+ while (n--) {
+ int s = *(int *)p; p += 4;
+ wchar_t *m = WMALLOC(s+1);
+ MEMCPY(m, p, s*sizeof(wchar_t));
+ m[s] = 0;
+ StringW *temp = new StringW;
+ temp->own(m);
+ //files.addItem(new String(m));
+ files.addItem(temp);
+ //FREE(m);
+ p+=s;
+ }
+ n = *(int *)p; p += 4;
+ while (n--) {
+ SourceCodeLineI *l = new SourceCodeLineI();
+ l->setPointer(*(int *)p); p += 4;
+ l->setSourceFile(files[*(int *)p]->getValue()); p += 4;
+ l->setSourceFileLine(*(int *)p); p += 4;
+ SourceCodeLineI *last = lines.getLast();
+ if (last != NULL) last->setLength(l->getPointer()-last->getPointer());
+ lines.addItem(l);
+ }
+ SourceCodeLineI *last = lines.getLast();
+ if (last != NULL) last->setLength(cb->size - last->getPointer());
+ }
+}
+
+DebugSymbols::~DebugSymbols()
+{
+ files.deleteAll();
+ lines.deleteAll();
+}
+
+int DebugSymbols::getNumLines() {
+ if (!gotsymbols) return disasm.getNumLines();
+ return lines.getNumItems();
+}
+
+int DebugSymbols::findLine(int pointer) {
+ if (!gotsymbols) return disasm.findLine(pointer);
+ int i;
+ for (i=0;i<lines.getNumItems();i++) {
+ SourceCodeLine *l = lines.enumItem(i);
+ int ip = l->getPointer();
+ int il = l->getLength();
+ if (pointer >= ip && pointer < ip+il) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+SourceCodeLine *DebugSymbols::enumLine(int n) {
+ if (!gotsymbols) return disasm.enumLine(n);
+ return lines.enumItem(n);
+}
diff --git a/Src/Wasabi/api/script/debugger/debugsymbols.h b/Src/Wasabi/api/script/debugger/debugsymbols.h
new file mode 100644
index 00000000..26c23a9c
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/debugsymbols.h
@@ -0,0 +1,38 @@
+#ifndef __DEBUGSYMBOLS_H
+#define __DEBUGSYMBOLS_H
+
+#include <bfc/ptrlist.h>
+#include <bfc/string/StringW.h>
+#include "disasm.h"
+
+class SourceCodeLine;
+class SourceCodeLineI;
+class MakiDisassembler;
+
+class DebugSymbols {
+
+ public:
+
+ DebugSymbols(int vcpuid);
+ virtual ~DebugSymbols();
+
+ virtual int getNumLines();
+ virtual int findLine(int pointer);
+ virtual SourceCodeLine *enumLine(int n);
+
+ private:
+
+ PtrList<SourceCodeLineI> lines;
+ MakiDisassembler disasm;
+ StringW binaryfilename;
+ int gotsymbols;
+ PtrList<StringW> files;
+ //PtrList<MakiVariable> vars;
+};
+
+
+
+
+
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/disasm.cpp b/Src/Wasabi/api/script/debugger/disasm.cpp
new file mode 100644
index 00000000..7b3c17ee
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/disasm.cpp
@@ -0,0 +1,193 @@
+#include <precomp.h>
+#include <api/script/debugger/disasm.h>
+#include <api/script/opcodes.h>
+#include <api/script/vcpu.h>
+#include <api/script/debugger/sourcecodeline.h>
+// ---------------------------------------------------------------------
+
+typedef struct {
+ const wchar_t *opname;
+ unsigned __int8 opval;
+ int type;
+} opentry;
+
+opentry _optable[] = {
+ {L"nop", OPCODE_NOP, OPCODE_TYPE_VOID},
+ {L"push", OPCODE_PUSH, OPCODE_TYPE_VAR},
+ {L"popi", OPCODE_POPI, OPCODE_TYPE_VOID},
+ {L"pop", OPCODE_POP, OPCODE_TYPE_VAR},
+ {L"set ", OPCODE_SET, OPCODE_TYPE_VOID},
+ {L"retf", OPCODE_RETF, OPCODE_TYPE_VOID},
+ {L"call", OPCODE_CALLC, OPCODE_TYPE_PTR},
+ {L"call", OPCODE_CALLM, OPCODE_TYPE_DLF},
+ {L"call", OPCODE_CALLM2, OPCODE_TYPE_NDLF},
+ {L"umv", OPCODE_UMV, OPCODE_TYPE_DISCARD},
+ {L"cmpeq", OPCODE_CMPEQ, OPCODE_TYPE_VOID},
+ {L"cmpne", OPCODE_CMPNE, OPCODE_TYPE_VOID},
+ {L"cmpa", OPCODE_CMPA, OPCODE_TYPE_VOID},
+ {L"cmpae", OPCODE_CMPAE, OPCODE_TYPE_VOID},
+ {L"cmpb", OPCODE_CMPB, OPCODE_TYPE_VOID},
+ {L"cmpbe", OPCODE_CMPBE, OPCODE_TYPE_VOID},
+ {L"jiz", OPCODE_JIZ, OPCODE_TYPE_PTR},
+ {L"jnz", OPCODE_JNZ, OPCODE_TYPE_PTR},
+ {L"jmp", OPCODE_JMP, OPCODE_TYPE_PTR},
+ {L"incs", OPCODE_INCS, OPCODE_TYPE_VOID},
+ {L"decs", OPCODE_DECS, OPCODE_TYPE_VOID},
+ {L"incp", OPCODE_INCP, OPCODE_TYPE_VOID},
+ {L"decp", OPCODE_DECP, OPCODE_TYPE_VOID},
+ {L"add", OPCODE_ADD, OPCODE_TYPE_VOID},
+ {L"sub", OPCODE_SUB, OPCODE_TYPE_VOID},
+ {L"mul", OPCODE_MUL, OPCODE_TYPE_VOID},
+ {L"div", OPCODE_DIV, OPCODE_TYPE_VOID},
+ {L"mod", OPCODE_MOD, OPCODE_TYPE_VOID},
+ {L"neg", OPCODE_NEG, OPCODE_TYPE_VOID},
+ {L"shl", OPCODE_SHL, OPCODE_TYPE_VOID},
+ {L"shr", OPCODE_SHR, OPCODE_TYPE_VOID},
+ {L"bnot", OPCODE_BNOT, OPCODE_TYPE_VOID},
+ {L"bxor", OPCODE_XOR, OPCODE_TYPE_VOID},
+ {L"band", OPCODE_AND, OPCODE_TYPE_VOID},
+ {L"bor", OPCODE_OR, OPCODE_TYPE_VOID},
+ {L"not", OPCODE_NOT, OPCODE_TYPE_VOID},
+ {L"and", OPCODE_LAND, OPCODE_TYPE_VOID},
+ {L"or", OPCODE_LOR, OPCODE_TYPE_VOID},
+ {L"del", OPCODE_DELETE, OPCODE_TYPE_VOID},
+ {L"new", OPCODE_NEW, OPCODE_TYPE_CLASSID},
+ {L"cmpl", OPCODE_CMPLT, OPCODE_TYPE_VOID},
+};
+
+int MakiDisassembler::optable[256];
+int MakiDisassembler::optableready = 0;
+
+
+MakiDisassembler::MakiDisassembler(int _vcpuid) {
+ if (!optableready) {
+ MEMSET(optable, 0, sizeof(optable));
+ for (int i=0;i<sizeof(_optable)/sizeof(opentry);i++) {
+ opentry e = _optable[i];
+ optable[e.opval] = i;
+ }
+ optableready = 1;
+ }
+ vcpuid = _vcpuid;
+ disassemble();
+}
+
+MakiDisassembler::~MakiDisassembler() {
+ lines.deleteAll();
+}
+
+int MakiDisassembler::getVCPUId() {
+ return vcpuid;
+}
+
+int MakiDisassembler::getNumLines() {
+ return lines.getNumItems();
+}
+
+SourceCodeLine *MakiDisassembler::enumLine(int n) {
+ return lines.enumItem(n);
+}
+
+int MakiDisassembler::findLine(int pointer) {
+ int i;
+ for (i=0;i<lines.getNumItems();i++) {
+ SourceCodeLine *l = lines.enumItem(i);
+ int ip = l->getPointer();
+ int il = l->getLength();
+ if (pointer >= ip && pointer < ip+il) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+void MakiDisassembler::disassemble() {
+ int size;
+ const char *codeblock = VCPU::getCodeBlock(vcpuid, &size);
+ if (codeblock != NULL) {
+
+ const char *p = codeblock;
+
+ unsigned char opcode = OPCODE_NOP;
+
+ while (p < codeblock+size) {
+ const char *start_of_instruction = p;
+ opcode = *p;
+ p+=sizeof(opcode);
+
+ StringW inst;
+ int a = optable[opcode];
+ int id;
+ int size = 0;
+ inst = _optable[a].opname;
+ switch (_optable[a].type) {
+ case OPCODE_TYPE_VOID:
+ size = 1;
+ break;
+ case OPCODE_TYPE_VAR:
+ id = *(int *)p; p+=sizeof(int);
+ inst += StringPrintfW(L" var %08X", id);
+ size = 5;
+ break;
+ case OPCODE_TYPE_PTR:
+ id = *(int *)p; p+=sizeof(int);
+ inst += StringPrintfW(L" %08X", id+(p-codeblock));
+ size = 5;
+ break;
+ case OPCODE_TYPE_DLF: {
+ id = *(int *)p; p+=sizeof(int);
+ int np = *(int *)p;
+ if ((np & 0xFFFF0000) == 0xFFFF0000) {
+ p+=sizeof(int);
+ np &= 0xFFFF;
+ } else
+ np = -1;
+ int i = VCPU::dlfBase(vcpuid)+id;
+ if (i != -1) {
+ VCPUdlfEntry *e = VCPU::DLFentryTable.enumItem(i);
+ if (e != NULL) {
+ if (np != -1) inst += StringPrintfW(L"(%d)", np);
+ inst += L" ";
+ inst += e->functionName;
+ }
+ }
+ size = 5 + ((np == -1) ? 0 : 4);
+ break;
+ }
+ case OPCODE_TYPE_NDLF: {
+ id = *(int *)p; p+=sizeof(int);
+ int np = *p; p++;
+ int i = VCPU::dlfBase(vcpuid)+id;
+ if (i != -1) {
+ VCPUdlfEntry *e = VCPU::DLFentryTable.enumItem(i);
+ if (e != NULL) {
+ inst += StringPrintfW(L"(%d) ", np);
+ inst += e->functionName;
+ }
+ }
+ size = 6;
+ break;
+ }
+ case OPCODE_TYPE_CLASSID: {
+ id = *(int *)p; p+=sizeof(int);
+ const wchar_t *cn = WASABI_API_MAKI->vcpu_getClassName(vcpuid, id);
+ inst += L" ";
+ inst += cn;
+ size = 5;
+ break;
+ }
+ case OPCODE_TYPE_DISCARD:
+ id = *(int *)p; p+=sizeof(int);
+ size = 5;
+ break;
+ }
+ SourceCodeLineI *scl = new SourceCodeLineI();
+ scl->setLine(inst),
+ scl->setPointer(start_of_instruction-codeblock);
+ scl->setLength(size);
+ lines.addItem(scl);
+ }
+ }
+}
+
diff --git a/Src/Wasabi/api/script/debugger/disasm.h b/Src/Wasabi/api/script/debugger/disasm.h
new file mode 100644
index 00000000..2d8d3c71
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/disasm.h
@@ -0,0 +1,38 @@
+#ifndef __MakiDisassembler_H
+#define __MakiDisassembler_H
+
+#include <bfc/ptrlist.h>
+
+class SourceCodeLine;
+class SourceCodeLineI;
+
+enum {
+ OPCODE_TYPE_VOID = 0,
+ OPCODE_TYPE_VAR,
+ OPCODE_TYPE_PTR,
+ OPCODE_TYPE_DLF,
+ OPCODE_TYPE_NDLF,
+ OPCODE_TYPE_CLASSID,
+ OPCODE_TYPE_DISCARD,
+};
+
+class MakiDisassembler {
+ public:
+ MakiDisassembler(int vcpuid);
+ virtual ~MakiDisassembler();
+
+ int getVCPUId();
+ int getNumLines();
+ SourceCodeLine *enumLine(int n);
+ int findLine(int pointer);
+
+ private:
+ void disassemble();
+ PtrList<SourceCodeLineI> lines;
+ int vcpuid;
+ static int optable[256];
+ static int optableready;
+};
+
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/jitd.cpp b/Src/Wasabi/api/script/debugger/jitd.cpp
new file mode 100644
index 00000000..62bfa731
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/jitd.cpp
@@ -0,0 +1,176 @@
+#include <precomp.h>
+#include "jitd.h"
+#include "jitdbreak.h"
+#include <api/service/svcs/svc_debuggerui.h>
+#include <api/service/svc_enum.h>
+#include <api/script/debugger/vcpudebug.h>
+#include <api/script/debugger/debuggerui.h>
+#include <api/script/debugger/sdebuggerui.h>
+#include <api/script/debugger/debugsymbols.h>
+
+MakiJITD::MakiJITD(VCPUDebugger *_debugger, int _vcpuid) {
+ vip = vsp = vsd = vcc = -1;
+ globalbreakpoint = 1; // fucko!!
+ onhold = 0;
+ debugger = _debugger;
+ vcpuid = _vcpuid;
+ uisvc = NULL;
+ ui = NULL;
+ simpleui = NULL;
+ codeblock = _debugger->getCodeBlock(vcpuid);
+ sysbp = new JITDBreakpoint(this, 0);
+ breakpoints.addItem(sysbp);
+ sysbp->setEnabled(0);
+ symbols = new DebugSymbols(_vcpuid);
+}
+
+MakiJITD::~MakiJITD() {
+ breakpoints.deleteAll();
+ if (uisvc != NULL) {
+ uisvc->destroyUI(ui);
+ WASABI_API_SVC->service_release(uisvc);
+ }
+ delete simpleui;
+ delete symbols;
+}
+
+int MakiJITD::getVIP() {
+ return vip;
+}
+
+int MakiJITD::getVCC() {
+ return vcc;
+}
+
+int MakiJITD::getVSD() {
+ return vsd;
+}
+
+int MakiJITD::getVSP() {
+ return vsp;
+}
+
+int MakiJITD::isGlobalBreakpointSet() {
+ return globalbreakpoint;
+}
+
+void MakiJITD::setGlobalBreakpoint(int s) {
+ globalbreakpoint = s;
+}
+
+int MakiJITD::getNumBreakpoints() {
+ return breakpoints.getNumItems();
+}
+
+JITDBreakpoint *MakiJITD::enumBreakpoint(int n) {
+ return breakpoints.enumItem(n);
+}
+
+JITDBreakpoint *MakiJITD::findBreakpoint(int pointer) {
+ int i;
+ for (i=0;i<breakpoints.getNumItems();i++) {
+ JITDBreakpoint *bp = breakpoints.enumItem(i);
+ if (bp->isEnabled() && bp->getPointer() == pointer)
+ return bp;
+ }
+ return NULL;
+}
+
+void MakiJITD::addBreakpoint(int pointer) {
+ breakpoints.addItem(new JITDBreakpoint(this, pointer));
+}
+
+void MakiJITD::removeBreakpoint(JITDBreakpoint *breakpoint) {
+ breakpoints.removeItem(breakpoint);
+ delete breakpoint;
+}
+
+void MakiJITD::clearAllBreakpoints() {
+ breakpoints.deleteAll();
+}
+
+int MakiJITD::getVCPUId() {
+ return vcpuid;
+}
+
+void MakiJITD::trace() {
+ vip = debugger->getVIP();
+ vsp = debugger->getVSP();
+ vsd = debugger->getVSD();
+ vcc = debugger->getVCC();
+
+ if (globalbreakpoint || findBreakpoint(vip)) {
+ enterUi();
+ }
+}
+
+int MakiJITD::isActive() {
+ return 1;
+}
+
+void MakiJITD::enterUi() {
+ createUi();
+ sysbp->setEnabled(0);
+ globalbreakpoint = 0;
+ onhold = 1;
+ int next_command = ui->messageLoop();
+ onhold = 0;
+ switch (next_command) {
+ case JITD_RETURN_STEPINTO:
+ globalbreakpoint = 1;
+ break;
+ case JITD_RETURN_STEPOUT:
+ // for now, continue
+ break;
+ case JITD_RETURN_TERMINATE:
+ // for now, continue
+ break;
+ case JITD_RETURN_CONTINUE:
+ // do nothing
+ default:
+ break;
+ }
+}
+
+void MakiJITD::createUi() {
+ if (ui != NULL) return;
+ waServiceFactory *f = WASABI_API_SVC->service_getServiceByGuid(SERVICE_DEBUGGERUI);
+ if (f != NULL) {
+ uisvc = castService<svc_debuggerUI>(f);
+ if (uisvc != NULL) {
+ ui = uisvc->createUI();
+ ui->setJITD(this);
+ }
+ } else {
+ simpleui = new SimpleDebuggerUI();
+ ui = simpleui;
+ ui->setJITD(this);
+ }
+}
+
+int MakiJITD::isOnHold() {
+ return onhold;
+}
+
+const char *MakiJITD::getCodeBlock() {
+ return codeblock;
+}
+
+void MakiJITD::setSysBreakpoint(int pointer) {
+ sysbp->setPointer(pointer);
+ sysbp->setEnabled(1);
+}
+
+int MakiJITD::getNumLines() {
+ return symbols->getNumLines();
+}
+
+SourceCodeLine *MakiJITD::enumLine(int n) {
+ return symbols->enumLine(n);
+}
+
+int MakiJITD::findLine(int pointer) {
+ return symbols->findLine(pointer);
+}
+
+
diff --git a/Src/Wasabi/api/script/debugger/jitd.h b/Src/Wasabi/api/script/debugger/jitd.h
new file mode 100644
index 00000000..6cb41f72
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/jitd.h
@@ -0,0 +1,71 @@
+#ifndef __MAKIJITD_H
+#define __MAKIJITD_H
+
+#include <bfc/ptrlist.h>
+
+class JITDBreakpoint;
+class VCPUDebugger;
+class svc_debuggerUI;
+class SimpleDebuggerUI;
+class DebuggerUI;
+class DebugSymbols;
+class SourceCodeLine;
+
+enum {
+ JITD_RETURN_STEPINTO = 0,
+ JITD_RETURN_STEPOVER = 1,
+ JITD_RETURN_STEPOUT = 2,
+ JITD_RETURN_TERMINATE = 3,
+ JITD_RETURN_CONTINUE = 4,
+};
+
+class MakiJITD { // dispatch me!
+ public:
+ MakiJITD(VCPUDebugger *debugger, int vcpuid);
+ virtual ~MakiJITD();
+
+ int getNumBreakpoints();
+ JITDBreakpoint *enumBreakpoint(int n);
+ JITDBreakpoint *findBreakpoint(int pointer);
+ void addBreakpoint(int pointer);
+ void removeBreakpoint(JITDBreakpoint *breakpoint);
+ void clearAllBreakpoints();
+ int isGlobalBreakpointSet();
+ void setGlobalBreakpoint(int s);
+ void setSysBreakpoint(int pointer); // deactivates automatically next time the debugger is activated
+ int getVCPUId();
+ void trace();
+ int isActive();
+ int isOnHold(); // 1 if running in the jitd's message loop
+
+ int getVIP();
+ int getVSD();
+ int getVCC();
+ int getVSP();
+
+ const char *getCodeBlock();
+
+ virtual int findLine(int pointer);
+ virtual int getNumLines();
+ virtual SourceCodeLine *enumLine(int n);
+
+ private:
+ void createUi();
+ void enterUi();
+
+ int vcpuid;
+ int vip, vsd, vcc, vsp;
+ int globalbreakpoint;
+
+ PtrList<JITDBreakpoint> breakpoints;
+ VCPUDebugger *debugger;
+ svc_debuggerUI *uisvc;
+ DebuggerUI *ui;
+ SimpleDebuggerUI *simpleui;
+ int onhold;
+ const char *codeblock;
+ JITDBreakpoint *sysbp;
+ DebugSymbols *symbols;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/jitdbreak.cpp b/Src/Wasabi/api/script/debugger/jitdbreak.cpp
new file mode 100644
index 00000000..4d12d3fe
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/jitdbreak.cpp
@@ -0,0 +1,27 @@
+#include "precomp.h"
+#include "jitdbreak.h"
+
+JITDBreakpoint::JITDBreakpoint(MakiJITD *_jitd, int _pointer) {
+ jitd = _jitd;
+ pointer = _pointer;
+ enabled = 1;
+}
+
+JITDBreakpoint::~JITDBreakpoint() {
+}
+
+int JITDBreakpoint::getPointer() {
+ return pointer;
+}
+
+void JITDBreakpoint::setEnabled(int e) {
+ enabled = e;
+}
+
+int JITDBreakpoint::isEnabled() {
+ return enabled;
+}
+
+void JITDBreakpoint::setPointer(int _pointer) {
+ pointer = _pointer;
+} \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/jitdbreak.h b/Src/Wasabi/api/script/debugger/jitdbreak.h
new file mode 100644
index 00000000..960e83b6
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/jitdbreak.h
@@ -0,0 +1,22 @@
+#ifndef __JITDBREAKPOINT_H
+#define __JITDBREAKPOINT_H
+
+class MakiJITD;
+
+class JITDBreakpoint {
+ public:
+ JITDBreakpoint(MakiJITD *jitd, int pointer);
+ virtual ~JITDBreakpoint();
+
+ virtual int getPointer();
+ virtual void setPointer(int pointer);
+ virtual void setEnabled(int e);
+ virtual int isEnabled();
+
+ private:
+ MakiJITD *jitd;
+ int pointer;
+ int enabled;
+};
+
+#endif
diff --git a/Src/Wasabi/api/script/debugger/sdebuggerui.cpp b/Src/Wasabi/api/script/debugger/sdebuggerui.cpp
new file mode 100644
index 00000000..c8349b05
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/sdebuggerui.cpp
@@ -0,0 +1,437 @@
+#include <precomp.h>
+#include "sdebuggerui.h"
+#include <api/script/debugger/jitd.h>
+#include <tataki/canvas/canvas.h>
+#include <api/wnd/wndclass/editwnd.h>
+#include <api/script/objcontroller.h>
+#include <bfc/string/stringdict.h>
+#include <bfc/parse/paramparser.h>
+#include <api/wnd/notifmsg.h>
+#include <api/script/objecttable.h>
+#include <api/script/debugger/sourcecodeline.h>
+#include "../nu/AutoWide.h"
+
+#define LEFTCOLUMN 100
+#define RIGHTCOLUMN 200
+#define INPUTHEIGHT 21
+#define NCONSOLELINES 4
+#define LINEHEIGHT 14
+#define REGWIDTH 100
+
+SimpleDebuggerUI::SimpleDebuggerUI()
+{
+ leave = 0;
+ jitd = NULL;
+ edit = NULL;
+ memset(cmdbuf, 0, sizeof(cmdbuf));
+ retcode = JITD_RETURN_CONTINUE;
+}
+
+SimpleDebuggerUI::~SimpleDebuggerUI()
+{}
+
+void SimpleDebuggerUI::setJITD(MakiJITD *_jitd)
+{
+ jitd = _jitd;
+}
+
+int SimpleDebuggerUI::messageLoop()
+{
+ leave = 0;
+ retcode = JITD_RETURN_STEPINTO;
+
+ if (!isInited())
+ {
+ setVirtual(0);
+ setStartHidden(1);
+ setParent(WASABI_API_WND->main_getRootWnd());
+ init(WASABI_API_WND->main_getRootWnd(), 1);
+
+ edit = new EditWnd;
+ edit->setParent(this);
+ edit->setBackgroundColor(RGB(0, 0, 0));
+ edit->setTextColor(RGB(0, 255, 0));
+ edit->setWantFocus(0);
+
+ *cmdbuf = 0;
+ edit->setBuffer(cmdbuf, 256);
+ edit->init(this);
+
+ RECT r;
+ POINT pt = {0, 0};
+ Wasabi::Std::getViewport(&r, &pt);
+ resize(r.right - 656, r.top + 16, 640, 480);
+ bringToFront();
+ }
+
+ for (int s = 0;s < jitd->getVSP();s++)
+ {
+ scriptVar v = WASABI_API_MAKIDEBUG->debugger_readStack(s);
+ StringW str;
+ switch (v.type)
+ {
+ case SCRIPT_VOID:
+ str = L"NULL";
+ break;
+ case SCRIPT_INT:
+ str = StringPrintfW(L"%d", GET_SCRIPT_INT(v));
+ break;
+ case SCRIPT_BOOLEAN:
+ str = StringPrintfW(L"%s", GET_SCRIPT_BOOLEAN(v) ? L"true" : L"false");
+ break;
+ case SCRIPT_FLOAT:
+ str = StringPrintfW(L"%f", GET_SCRIPT_FLOAT(v));
+ break;
+ case SCRIPT_DOUBLE:
+ str = StringPrintfW(L"%f", (float)GET_SCRIPT_DOUBLE(v));
+ break;
+ case SCRIPT_STRING:
+ str = GET_SCRIPT_STRING(v);
+ break;
+ default:
+ {
+ if (v.type == SCRIPT_OBJECT)
+ str = L"Object";
+ else
+ str = ObjectTable::getClassName(v.type);
+#ifdef WASABI_COMPILE_SKIN
+ ScriptObject *o = GET_SCRIPT_OBJECT(v);
+ if (o != NULL)
+ {
+ GuiObject *go = static_cast<GuiObject *>(o->vcpu_getInterface(guiObjectGuid));
+ if (go != NULL)
+ {
+ str += L";";
+ str.cat(go->guiobject_getId());
+ }
+ }
+#endif
+ break;
+ }
+ }
+ strstack.addItem(new StringW(str));
+ }
+
+ setVisible(1);
+
+ //WASABI_API_WND->pushModalWnd(this);
+
+#ifdef WIN32
+ MSG msg;
+ //DWORD leavetime = GetTickCount()+5;
+ while (!leave/* && !(GetTickCount() >leavetime)*/)
+ {
+ if (PeekMessage(&msg, /*(HWND)NULL*/ getOsWindowHandle(), 0, 0, PM_NOREMOVE))
+ {
+ GetMessage(&msg, /*(HWND) NULL*/getOsWindowHandle(), 0, 0) &&
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+#endif
+
+ //WASABI_API_WND->popModalWnd(this);
+
+ setVisible(0);
+ strstack.deleteAll();
+
+ return retcode;
+}
+
+int SimpleDebuggerUI::onPaint(Canvas *c)
+{
+ SimpleDebuggerUI_PARENT::onPaint(c);
+ Wasabi::FontInfo fontInfo;
+ RECT r;
+ getClientRect(&r);
+ c->fillRect(&r, RGB(0, 0, 0));
+ c->drawRect(&r, 1, RGB(0, 255, 0));
+
+ fontInfo.color = RGB(0, 255, 0);
+ fontInfo.pointSize = 14;
+ fontInfo.face = L"Courier New";
+ c->pushPen(PENSTYLE_SOLID, 1, RGB(0, 255, 0));
+ c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8, StringPrintfW(L"VSD:%08X", jitd->getVSD()), &fontInfo);
+ c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1), StringPrintfW(L"VIP:%08X", jitd->getVIP()), &fontInfo);
+ c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*2, StringPrintfW(L"VSP:%08X", jitd->getVSP()), &fontInfo);
+ c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*3, StringPrintfW(L"VCC:%08X", jitd->getVCC()), &fontInfo);
+ c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
+ c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + 2), r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + 2));
+ c->lineDraw(r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right - REGWIDTH, r.bottom);
+ c->lineDraw(r.right - RIGHTCOLUMN, 0, r.right - RIGHTCOLUMN, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
+ disassemble(c);
+ for (int s = 0;s < strstack.getNumItems();s++)
+ {
+ c->textOutEllipsed(r.right - RIGHTCOLUMN + 4, s*LINEHEIGHT + 4, RIGHTCOLUMN - 8, 16, strstack.enumItem(s)->getValue(), &fontInfo);
+ }
+ return 1;
+}
+
+int SimpleDebuggerUI::onLeftButtonDown(int x, int y)
+{
+ SimpleDebuggerUI_PARENT::onLeftButtonDown(x, y);
+ if (edit) edit->onGetFocus();
+// leave = 1;
+ return 1;
+}
+
+void SimpleDebuggerUI::disassemble(Canvas *c)
+{
+ RECT r;
+ getClientRect(&r);
+ int x = 4;
+
+ int y = (r.bottom - r.top - 4) / 2 + 4;
+
+ int ln = jitd->findLine(jitd->getVIP());
+ if (ln != -1)
+ {
+ Wasabi::FontInfo fontInfo;
+ SourceCodeLine *l = jitd->enumLine(ln);
+ int sourcecode = l->getSourceFile() != NULL;
+ int g;
+ int j = 0;
+ for (g = y;g < r.bottom - (INPUTHEIGHT + 4 + (NCONSOLELINES*LINEHEIGHT)) - LINEHEIGHT;g += LINEHEIGHT)
+ {
+ if (!sourcecode || j == 0)
+ l = jitd->enumLine(ln + j);
+ if (!l) break;
+
+ if (j == 0)
+ {
+ RECT br;
+ br.left = 4;
+ br.top = g;
+ br.right = r.right - (RIGHTCOLUMN + 4);
+ br.bottom = br.top + LINEHEIGHT;
+ c->fillRect(&br, RGB(0, 255, 0));
+ fontInfo.color = RGB(0, 0, 0);
+ }
+ if (!sourcecode)
+ {
+ String str;
+ unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
+ for (int k = 0;k < l->getLength();k++)
+ {
+ if (!str.isempty()) str += " ";
+ str += StringPrintf("%02X", *d);
+ d++;
+ }
+ c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
+ c->textOut(x + 70, g, AutoWide(str), &fontInfo);
+ c->textOut(x + 70 + 150, g, l->getLine(), &fontInfo);
+ }
+ else
+ {
+ c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() + j)), &fontInfo);
+ }
+
+ j++;
+ }
+ j = 1;
+ for (g = y - LINEHEIGHT;g > 1;g -= LINEHEIGHT)
+ {
+ if (!sourcecode || j == 0)
+ l = jitd->enumLine(ln - j);
+ if (!l) break;
+ if (!sourcecode)
+ {
+ String str;
+ unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
+ for (int k = 0;k < l->getLength();k++)
+ {
+ if (!str.isempty()) str += " ";
+ str += StringPrintf("%02X", *d);
+ d++;
+ }
+ c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
+ c->textOut(x + 70, g, AutoWide(str), &fontInfo);
+ c->textOut(x + 70 + 150, g, (l->getLine()), &fontInfo);
+ }
+ else
+ {
+ c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() - j)), &fontInfo);
+ }
+ j++;
+ }
+ }
+}
+
+int SimpleDebuggerUI::onResize()
+{
+ SimpleDebuggerUI_PARENT::onResize();
+ if (edit != NULL)
+ {
+ RECT r;
+ getClientRect(&r);
+ edit->resize(1, r.bottom - (INPUTHEIGHT + 1), r.right - r.left - (REGWIDTH + 1), INPUTHEIGHT);
+ }
+ return 1;
+}
+
+int SimpleDebuggerUI::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2)
+{
+ if (child == edit)
+ {
+ if (msg == ChildNotify::EDITWND_ENTER_PRESSED)
+ {
+ onCommand(cmdbuf);
+ }
+ }
+ return SimpleDebuggerUI_PARENT::childNotify(child, msg, p1, p2);
+}
+
+BEGIN_STRINGDICTIONARY(_debuggercommands)
+SDI(L"b", DEBUG_CMD_BREAKPOINT);
+SDI(L"break", DEBUG_CMD_BREAKPOINT);
+SDI(L"x", DEBUG_CMD_CONTINUE);
+SDI(L"continue", DEBUG_CMD_CONTINUE);
+SDI(L"i", DEBUG_CMD_STEPINTO);
+SDI(L"stepinto", DEBUG_CMD_STEPINTO);
+SDI(L"o", DEBUG_CMD_STEPOVER);
+SDI(L"stepover", DEBUG_CMD_STEPOVER);
+SDI(L"p", DEBUG_CMD_STEPOUT);
+SDI(L"stepout", DEBUG_CMD_STEPOUT);
+SDI(L"k", DEBUG_CMD_KILL);
+SDI(L"kill", DEBUG_CMD_KILL);
+SDI(L"?", DEBUG_CMD_HELP);
+SDI(L"help", DEBUG_CMD_HELP);
+END_STRINGDICTIONARY(_debuggercommands, debuggercommands)
+
+
+void SimpleDebuggerUI::onCommand(const wchar_t *cmd)
+{
+ if (*cmd == 0)
+ {
+ stepOver();
+ return;
+ }
+ ParamParser pp(cmd, L" ");
+ int i = debuggercommands.getId(pp.enumItem(0));
+ switch (i)
+ {
+ case DEBUG_CMD_BREAKPOINT:
+ addBreakPoint(pp.enumItem(1));
+ break;
+ case DEBUG_CMD_CONTINUE:
+ continueExecution();
+ break;
+ case DEBUG_CMD_STEPINTO:
+ stepInto();
+ break;
+ case DEBUG_CMD_STEPOVER:
+ stepOver();
+ break;
+ case DEBUG_CMD_KILL:
+ killScript();
+ break;
+ case DEBUG_CMD_HELP:
+ showHelp();
+ break;
+ }
+}
+
+int SimpleDebuggerUI::evaluate(const wchar_t *ascii)
+{
+ if (!_wcsicmp(ascii, L"VSD")) return jitd->getVSD();
+ if (!_wcsicmp(ascii, L"VIP")) return jitd->getVIP();
+ if (!_wcsicmp(ascii, L"VSP")) return jitd->getVSP();
+ if (!_wcsicmp(ascii, L"VCC")) return jitd->getVCC();
+ wchar_t *end;
+ return wcstol(ascii, &end, 16);
+}
+
+void SimpleDebuggerUI::addBreakPoint(const wchar_t *pointer_ascii)
+{
+ /*int i = */evaluate(pointer_ascii);
+}
+
+void SimpleDebuggerUI::continueExecution()
+{
+ retcode = JITD_RETURN_CONTINUE;
+ leave = 1;
+}
+
+void SimpleDebuggerUI::stepInto()
+{
+ retcode = JITD_RETURN_STEPINTO;
+ leave = 1;
+}
+
+void SimpleDebuggerUI::stepOver()
+{
+ int ln = jitd->findLine(jitd->getVIP());
+ ln++;
+ SourceCodeLine *l = jitd->enumLine(ln);
+
+ if (l != NULL) // else ret as last opcode
+ jitd->setSysBreakpoint(l->getPointer());
+
+ retcode = JITD_RETURN_CONTINUE;
+ leave = 1;
+}
+
+void SimpleDebuggerUI::killScript()
+{
+ retcode = JITD_RETURN_TERMINATE;
+ leave = 1;
+}
+
+void SimpleDebuggerUI::showHelp()
+{}
+
+int SimpleDebuggerUI::onGetFocus()
+{
+ SimpleDebuggerUI_PARENT::onGetFocus();
+ if (edit) edit->onGetFocus();
+ return 1;
+}
+
+void SimpleDebuggerUI::onSetVisible(int show)
+{
+ SimpleDebuggerUI_PARENT::onSetVisible(show);
+ if (edit) edit->onGetFocus();
+}
+#undef fgets
+const wchar_t *SimpleDebuggerUI::getLine(const wchar_t *filename, int fileline)
+{
+ if (fileline <= 0)
+ return L"";
+ static StringW str;
+ FILE *f = _wfopen(filename, L"rt");
+ if (!f)
+ {
+ str = L"couldn't load ";
+ str += filename;
+ return str;
+ }
+
+ char t[256] = {0};
+ char u[256] = {0};
+ int n = fileline;
+ while (n--)
+ {
+ *u = 0;
+ char *p;
+ do
+ {
+ p = *u ? t : u;
+ fgets(p, 255, f);
+ t[255] = 0;
+ }
+ while (!feof(f) && p[STRLEN(p)-1] != '\n' && p[STRLEN(p)-1] != '\r');
+ }
+
+ char *p = u;
+ while (p && *p && p < u + 256)
+ {
+ if (*p < 0x21) *p = ' ';
+ p++;
+ }
+
+ str = AutoWide(u, CP_UTF8);
+ fclose(f);
+
+ return str;
+}
+
diff --git a/Src/Wasabi/api/script/debugger/sdebuggerui.h b/Src/Wasabi/api/script/debugger/sdebuggerui.h
new file mode 100644
index 00000000..39f73ee5
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/sdebuggerui.h
@@ -0,0 +1,65 @@
+#ifndef __SIMPLEDEBUGGERUI_H
+#define __SIMPLEDEBUGGERUI_H
+
+#include "debuggerui.h"
+#include <api/wnd/wndclass/clickwnd.h>
+
+class MakiDisassembler;
+class EditWnd;
+class String;
+class SourceCodeLine;
+
+#define SimpleDebuggerUI_PARENT ClickWnd
+
+enum {
+ DEBUG_CMD_BREAKPOINT = 0,
+ DEBUG_CMD_CONTINUE,
+ DEBUG_CMD_STEPINTO,
+ DEBUG_CMD_STEPOVER,
+ DEBUG_CMD_STEPOUT,
+ DEBUG_CMD_KILL,
+ DEBUG_CMD_HELP,
+};
+
+
+class MakiJITD;
+
+class SimpleDebuggerUI : public SimpleDebuggerUI_PARENT, public DebuggerUII {
+ public:
+ SimpleDebuggerUI();
+ virtual ~SimpleDebuggerUI();
+
+ virtual int onPaint(Canvas *c);
+ virtual int onLeftButtonDown(int x, int y);
+ virtual int onResize();
+ virtual int childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2);
+ virtual void onSetVisible(int show);
+
+ virtual int messageLoop();
+ virtual void setJITD(MakiJITD *jitd);
+
+ virtual void disassemble(Canvas *c);
+ virtual void onCommand(const wchar_t *cmd);
+
+ virtual void addBreakPoint(const wchar_t *pointer_ascii);
+ virtual void continueExecution();
+ virtual void stepInto();
+ virtual void stepOver();
+ virtual void killScript();
+ virtual void showHelp();
+ virtual int onGetFocus();
+
+ virtual int evaluate(const wchar_t *ascii);
+ virtual const wchar_t *getLine(const wchar_t *filename, int fileline);
+
+ private:
+
+ int leave;
+ MakiJITD *jitd;
+ EditWnd *edit;
+ wchar_t cmdbuf[256];
+ int retcode;
+ PtrList<StringW> strstack;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/sourcecodeline.cpp b/Src/Wasabi/api/script/debugger/sourcecodeline.cpp
new file mode 100644
index 00000000..b6511c2b
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/sourcecodeline.cpp
@@ -0,0 +1,69 @@
+#include <precomp.h>
+#include "sourcecodeline.h"
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+#define CBCLASS SourceCodeLineI
+START_DISPATCH;
+ CB(SOURCECODELINE_GETLINE, getLine);
+ VCB(SOURCECODELINE_SETLINE, setLine);
+ CB(SOURCECODELINE_GETPOINTER, getPointer);
+ VCB(SOURCECODELINE_SETPOINTER, setPointer);
+ CB(SOURCECODELINE_GETLENGTH, getLength);
+ VCB(SOURCECODELINE_SETLENGTH, setLength);
+ VCB(SOURCECODELINE_SETSOURCEFILE, setSourceFile);
+ CB(SOURCECODELINE_GETSOURCEFILE, getSourceFile);
+ VCB(SOURCECODELINE_SETSOURCEFILELINE, setSourceFileLine);
+ CB(SOURCECODELINE_GETSOURCEFILELINE, getSourceFileLine);
+END_DISPATCH;
+
+SourceCodeLineI::SourceCodeLineI() {
+ pointer = -1;
+ fileline = -1;
+ length = 0;
+}
+
+SourceCodeLineI::~SourceCodeLineI() {
+}
+
+const wchar_t *SourceCodeLineI::getLine()
+{
+ return line;
+}
+
+void SourceCodeLineI::setLine(const wchar_t *_line) {
+ line = _line;
+}
+
+int SourceCodeLineI::getPointer() {
+ return pointer;
+}
+
+void SourceCodeLineI::setPointer(int _pointer) {
+ pointer = _pointer;
+}
+
+int SourceCodeLineI::getLength() {
+ return length;
+}
+
+void SourceCodeLineI::setLength(int _length) {
+ length = _length;
+}
+
+void SourceCodeLineI::setSourceFile(const wchar_t *_file) {
+ file = _file;
+}
+
+const wchar_t *SourceCodeLineI::getSourceFile() {
+ return file;
+}
+
+void SourceCodeLineI::setSourceFileLine(int _linenumber) {
+ fileline = _linenumber;
+}
+
+int SourceCodeLineI::getSourceFileLine() {
+ return fileline;
+} \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/sourcecodeline.h b/Src/Wasabi/api/script/debugger/sourcecodeline.h
new file mode 100644
index 00000000..a3a341ac
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/sourcecodeline.h
@@ -0,0 +1,100 @@
+#ifndef __SOURCECODELINE_H
+#define __SOURCECODELINE_H
+
+#include <bfc/dispatch.h>
+#include <bfc/string/StringW.h>
+
+
+class SourceCodeLine : public Dispatchable {
+ public:
+ const wchar_t *getLine();
+ void setLine(const wchar_t *line);
+ int getPointer();
+ void setPointer(int pointer);
+ int getLength();
+ void setLength(int length);
+ void setSourceFile(const wchar_t *file);
+ const wchar_t *getSourceFile();
+ void setSourceFileLine(int linenumber);
+ int getSourceFileLine();
+
+ enum {
+ SOURCECODELINE_GETLINE = 0,
+ SOURCECODELINE_SETLINE = 10,
+ SOURCECODELINE_GETPOINTER = 20,
+ SOURCECODELINE_SETPOINTER = 30,
+ SOURCECODELINE_GETLENGTH = 40,
+ SOURCECODELINE_SETLENGTH = 50,
+ SOURCECODELINE_SETSOURCEFILE = 60,
+ SOURCECODELINE_GETSOURCEFILE = 70,
+ SOURCECODELINE_SETSOURCEFILELINE = 80,
+ SOURCECODELINE_GETSOURCEFILELINE = 90,
+ };
+};
+
+inline const wchar_t *SourceCodeLine::getLine() {
+ return _call(SOURCECODELINE_GETLINE, (const wchar_t*)NULL);
+}
+
+inline void SourceCodeLine::setLine(const wchar_t *line) {
+ _voidcall(SOURCECODELINE_SETLINE, line);
+}
+
+inline int SourceCodeLine::getPointer() {
+ return _call(SOURCECODELINE_GETPOINTER, (int)0);
+}
+
+inline void SourceCodeLine::setPointer(int pointer) {
+ _voidcall(SOURCECODELINE_SETPOINTER, pointer);
+}
+
+inline int SourceCodeLine::getLength() {
+ return _call(SOURCECODELINE_GETLENGTH, (int)0);
+}
+
+inline void SourceCodeLine::setLength(int length) {
+ _voidcall(SOURCECODELINE_SETLENGTH, length);
+}
+
+inline void SourceCodeLine::setSourceFile(const wchar_t *file) {
+ _voidcall(SOURCECODELINE_SETSOURCEFILE, file);
+}
+
+inline const wchar_t *SourceCodeLine::getSourceFile() {
+ return _call(SOURCECODELINE_GETSOURCEFILE, (const wchar_t *)0);
+}
+
+inline void SourceCodeLine::setSourceFileLine(int linenumber) {
+ _voidcall(SOURCECODELINE_SETSOURCEFILELINE, linenumber);
+}
+
+inline int SourceCodeLine::getSourceFileLine() {
+ return _call(SOURCECODELINE_GETSOURCEFILELINE, (int)0);
+}
+
+class SourceCodeLineI : public SourceCodeLine {
+ public:
+ SourceCodeLineI();
+ virtual ~SourceCodeLineI();
+ virtual const wchar_t *getLine();
+ virtual void setLine(const wchar_t *line);
+ virtual int getPointer();
+ virtual void setPointer(int pointer);
+ virtual int getLength();
+ virtual void setLength(int length);
+ virtual void setSourceFile(const wchar_t *file);
+ virtual const wchar_t *getSourceFile();
+ virtual void setSourceFileLine(int linenumber);
+ virtual int getSourceFileLine();
+
+ protected:
+ RECVS_DISPATCH;
+
+ StringW line;
+ StringW file;
+ int fileline;
+ int pointer;
+ int length;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/script/debugger/vcpudebug.cpp b/Src/Wasabi/api/script/debugger/vcpudebug.cpp
new file mode 100644
index 00000000..94087956
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/vcpudebug.cpp
@@ -0,0 +1,99 @@
+#include <precomp.h>
+#include <wasabicfg.h>
+#include "vcpudebug.h"
+#include <api/script/debugger/jitd.h>
+
+VCPUDebugger::VCPUDebugger() {
+ filter.setFilterObject(&reentryfilter);
+}
+
+VCPUDebugger::~VCPUDebugger() {
+}
+
+// ------------------------------------------------------------------------
+
+// instruction pointer
+int VCPUDebugger::getVIP() {
+ return WASABI_API_MAKIDEBUG->debugger_getVIP();
+}
+
+// script descriptor (vcpuid)
+int VCPUDebugger::getVSD() {
+ return WASABI_API_MAKIDEBUG->debugger_getVSD();
+}
+
+// variables stack pointer
+int VCPUDebugger::getVSP() {
+ return WASABI_API_MAKIDEBUG->debugger_getVSP();
+}
+
+// call stack pointer
+int VCPUDebugger::getVCC() {
+ return WASABI_API_MAKIDEBUG->debugger_getVCC();
+}
+
+// ------------------------------------------------------------------------
+void VCPUDebugger::trace() {
+ int i;
+ for (i=0;i<jitds.getNumItems();i++) {
+ MakiJITD *jitd = jitds.enumItem(i);
+ if (jitd->getVCPUId() == getVSD()) {
+ jitd->trace();
+ }
+ }
+}
+
+MakiJITD *VCPUDebugger::getJITD(int vcpuid) {
+ int i;
+ for (i=0;i<jitds.getNumItems();i++) {
+ MakiJITD *jitd = jitds.enumItem(i);
+ if (jitd->getVCPUId() == vcpuid)
+ return jitd;
+ }
+ return NULL;
+}
+
+// if this returns 1, you should not call eventComplete!
+int VCPUDebugger::filterEvent(int vcpuid, int eventid) {
+ MakiJITD *jitd = getJITD(vcpuid);
+ if (!jitd || !jitd->isOnHold()) {
+ WASABI_API_WND->pushModalWnd();
+ scopestack.push(0);
+ return 0;
+ }
+ filter.enterScope((vcpuid<<16) + eventid); // (vcpuid<<16) + eventid
+ if (filter.mustLeave()) {
+ filter.leaveScope();
+ return 1;
+ }
+ WASABI_API_WND->pushModalWnd();
+ scopestack.push(1);
+ return 0;
+}
+
+void VCPUDebugger::eventComplete() {
+ int n;
+ scopestack.pop(&n);
+ WASABI_API_WND->popModalWnd();
+ if (n) {
+ filter.leaveScope();
+ }
+}
+
+int VCPUDebugger::isActive() {
+ foreach(jitds)
+ if (jitds.getfor()->isActive())
+ return 1;
+ endfor;
+ return 0;
+}
+
+MakiJITD *VCPUDebugger::createJITD(int vcpuid) {
+ MakiJITD *jitd = new MakiJITD(this, vcpuid);
+ jitds.addItem(jitd);
+ return jitd;
+}
+
+const char *VCPUDebugger::getCodeBlock(int vcpuid) {
+ return WASABI_API_MAKIDEBUG->debugger_getCodeBlock(vcpuid);
+}
diff --git a/Src/Wasabi/api/script/debugger/vcpudebug.h b/Src/Wasabi/api/script/debugger/vcpudebug.h
new file mode 100644
index 00000000..6bba084b
--- /dev/null
+++ b/Src/Wasabi/api/script/debugger/vcpudebug.h
@@ -0,0 +1,39 @@
+#ifndef __VCPUDEBUG_H
+#define __VCPUDEBUG_H
+
+#include <bfc/ptrlist.h>
+#include <bfc/stack.h>
+#include <bfc/reentryfilter.h>
+
+class MakiJITD;
+
+class VCPUDebugger {
+ public:
+ VCPUDebugger();
+ virtual ~VCPUDebugger();
+
+ void trace();
+
+ int getVIP(); // instruction pointer
+ int getVSD(); // script descriptor (id)
+ int getVSP(); // variables stack pointer
+ int getVCC(); // call stack pointer
+
+ int filterEvent(int vcpuid, int eventid); // if this returns 1, you should return immediatly and not call eventComplete!
+ void eventComplete();
+
+ int isActive();
+
+ MakiJITD *createJITD(int vcpuid);
+ MakiJITD *getJITD(int vcpuid);
+ const char *getCodeBlock(int vcpuid);
+
+ private:
+
+ PtrList<MakiJITD> jitds;
+ ReentryFilterObject reentryfilter;
+ ReentryFilter filter;
+ Stack<int> scopestack;
+};
+
+#endif