mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-26 22:31:14 +00:00
started on mame WASM, debugging support, colecovision
This commit is contained in:
parent
495896c43d
commit
ef561b4425
70
mame/debugger.lua
Normal file
70
mame/debugger.lua
Normal file
@ -0,0 +1,70 @@
|
||||
-- JS debug support for MAME using -debugger none
|
||||
|
||||
mamedbg = {}
|
||||
|
||||
local debugging = false
|
||||
local stopped = false
|
||||
|
||||
function mamedbg.init()
|
||||
cpu = manager:machine().devices[":maincpu"]
|
||||
mem = cpu.spaces["program"]
|
||||
debugger = manager:machine():debugger()
|
||||
mamedbg.reset()
|
||||
emu.register_periodic(function ()
|
||||
if debugging then
|
||||
if not stopped then
|
||||
--debugger:command("symlist")
|
||||
--log = debugger.consolelog
|
||||
--for i=1,#log do print(log[i]) end
|
||||
--print(string.format("%4x", cpu.state["PC"].value))
|
||||
--manager:machine():save("state")
|
||||
emu.pause()
|
||||
stopped = true
|
||||
-- callback to JS via console i/o
|
||||
mamedbg.printstate()
|
||||
print(">>>debug_stopped")
|
||||
print("1")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function mamedbg.printstate()
|
||||
for k,v in pairs(cpu.state) do print(">>>cpu_"..k); print(v.value) end
|
||||
end
|
||||
|
||||
function mamedbg.reset()
|
||||
debugging = false
|
||||
stopped = false
|
||||
end
|
||||
|
||||
function mamedbg.start()
|
||||
debugging = true
|
||||
stopped = false
|
||||
end
|
||||
|
||||
function mamedbg.is_stopped()
|
||||
return debugging and stopped
|
||||
end
|
||||
|
||||
function mamedbg.runTo(addr)
|
||||
debugger:command("g " .. string.format("%x", addr))
|
||||
mamedbg.start()
|
||||
end
|
||||
|
||||
function mamedbg.runToVsync(addr)
|
||||
debugger:command("gv")
|
||||
mamedbg.start()
|
||||
end
|
||||
|
||||
function mamedbg.runUntilReturn(addr)
|
||||
debugger:command("out")
|
||||
mamedbg.start()
|
||||
end
|
||||
|
||||
function mamedbg.step()
|
||||
debugger:command("step")
|
||||
mamedbg.start()
|
||||
end
|
||||
|
||||
print("parsed Lua debugger script")
|
4
mame/mamea2600.js
Normal file
4
mame/mamea2600.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mame/mamea2600.wasm
Normal file
BIN
mame/mamea2600.wasm
Normal file
Binary file not shown.
4
mame/mamecoleco.js
Normal file
4
mame/mamecoleco.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mame/mamecoleco.wasm
Normal file
BIN
mame/mamecoleco.wasm
Normal file
Binary file not shown.
4
mame/mamenes.js
Normal file
4
mame/mamenes.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mame/mamenes.wasm
Normal file
BIN
mame/mamenes.wasm
Normal file
Binary file not shown.
148
src/emu.js
148
src/emu.js
@ -903,6 +903,8 @@ var BaseMAMEPlatform = function() {
|
||||
var console_vars = {};
|
||||
var console_varname;
|
||||
var initluavars = false;
|
||||
var luadebugscript;
|
||||
var js_lua_string;
|
||||
|
||||
this.luareset = function() {
|
||||
console_vars = {};
|
||||
@ -911,11 +913,9 @@ var BaseMAMEPlatform = function() {
|
||||
// http://docs.mamedev.org/techspecs/luaengine.html
|
||||
this.luacall = function(s) {
|
||||
console_varname = null;
|
||||
Module.ccall('_Z13js_lua_stringPKc', 'void', ['string'], [s+""]);
|
||||
}
|
||||
|
||||
this.clearDebug = function() {
|
||||
//TODO
|
||||
//Module.ccall('_Z13js_lua_stringPKc', 'void', ['string'], [s+""]);
|
||||
if (!js_lua_string) js_lua_string = Module.cwrap('_Z13js_lua_stringPKc', 'void', ['string']);
|
||||
js_lua_string(s || "");
|
||||
}
|
||||
|
||||
this.pause = function() {
|
||||
@ -926,7 +926,7 @@ var BaseMAMEPlatform = function() {
|
||||
}
|
||||
|
||||
this.resume = function() {
|
||||
if (loaded && !running) {
|
||||
if (loaded && !running) { // TODO
|
||||
this.luacall('emu.unpause()');
|
||||
running = true;
|
||||
}
|
||||
@ -949,6 +949,13 @@ var BaseMAMEPlatform = function() {
|
||||
if (console_varname) console_vars[console_varname] = [];
|
||||
} else if (console_varname) {
|
||||
console_vars[console_varname].push(s);
|
||||
if (console_varname == 'debug_stopped') {
|
||||
var debugSaveState = self.preserveState();
|
||||
self.pause();
|
||||
if (onBreakpointHit) {
|
||||
onBreakpointHit(debugSaveState);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(s);
|
||||
}
|
||||
@ -964,10 +971,14 @@ var BaseMAMEPlatform = function() {
|
||||
$(video.canvas).attr('id','canvas');
|
||||
// load asm.js module
|
||||
console.log("loading", opts.jsfile);
|
||||
var script = document.createElement('script');
|
||||
window.JSMESS = {};
|
||||
window.Module = {
|
||||
arguments: [opts.driver, '-debug', '-verbose', '-window', '-nokeepaspect', '-resolution', canvas.width+'x'+canvas.height, '-cart', romfn],
|
||||
arguments: [opts.driver,
|
||||
'-debug',
|
||||
'-debugger', 'none',
|
||||
'-verbose', '-window', '-nokeepaspect',
|
||||
'-resolution', canvas.width+'x'+canvas.height,
|
||||
'-cart', romfn],
|
||||
screenIsReadOnly: true,
|
||||
print: bufferConsoleOutput,
|
||||
canvas:video.canvas,
|
||||
@ -986,38 +997,72 @@ var BaseMAMEPlatform = function() {
|
||||
FS.writeFile('/roms/' + opts.biosfile, opts.biosdata, {encoding:'binary'});
|
||||
}
|
||||
FS.mkdir('/emulator');
|
||||
FS.writeFile(romfn, romdata, {encoding:'binary'});
|
||||
FS.writeFile('/debug.ini', 'debugger none\n', {encoding:'utf8'});
|
||||
if (romfn) FS.writeFile(romfn, new Uint8Array(romdata), {encoding:'binary'});
|
||||
//FS.writeFile('/debug.ini', 'debugger none\n', {encoding:'utf8'});
|
||||
if (opts.preInit) {
|
||||
opts.preInit(self);
|
||||
}
|
||||
$(video.canvas).click(function(e) {
|
||||
video.canvas.focus();
|
||||
});
|
||||
loaded = true;
|
||||
}
|
||||
},
|
||||
preRun: [
|
||||
function() {
|
||||
$(video.canvas).click(function(e) {
|
||||
video.canvas.focus();
|
||||
});
|
||||
loaded = true;
|
||||
console.log("about to run...");
|
||||
}
|
||||
]
|
||||
};
|
||||
// preload files
|
||||
// TODO: ensure loaded
|
||||
var fetch_cfg, fetch_lua;
|
||||
var fetch_bios = $.Deferred();
|
||||
var fetch_wasm = $.Deferred();
|
||||
// fetch config file
|
||||
if (opts.cfgfile) {
|
||||
$.get('mame/cfg/' + opts.cfgfile, function(data) {
|
||||
fetch_cfg = $.get('mame/cfg/' + opts.cfgfile, function(data) {
|
||||
opts.cfgdata = data;
|
||||
console.log("loaded " + opts.cfgfile);
|
||||
}, 'text');
|
||||
}
|
||||
// fetch BIOS file
|
||||
if (opts.biosfile) {
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.open("GET", 'mame/roms/' + opts.biosfile, true);
|
||||
oReq.responseType = "arraybuffer";
|
||||
oReq.onload = function(oEvent) {
|
||||
console.log("loaded " + opts.biosfile);
|
||||
opts.biosdata = new Uint8Array(oReq.response);
|
||||
var oReq1 = new XMLHttpRequest();
|
||||
oReq1.open("GET", 'mame/roms/' + opts.biosfile, true);
|
||||
oReq1.responseType = "arraybuffer";
|
||||
oReq1.onload = function(oEvent) {
|
||||
opts.biosdata = new Uint8Array(oReq1.response);
|
||||
console.log("loaded " + opts.biosfile + " (" + oEvent.total + " bytes)");
|
||||
fetch_bios.resolve();
|
||||
};
|
||||
oReq.send();
|
||||
oReq1.send();
|
||||
} else {
|
||||
fetch_bios.resolve();
|
||||
}
|
||||
// load debugger Lua script
|
||||
fetch_lua = $.get('mame/debugger.lua', function(data) {
|
||||
luadebugscript = data;
|
||||
console.log("loaded debugger.lua");
|
||||
}, 'text');
|
||||
// load WASM
|
||||
{
|
||||
var oReq2 = new XMLHttpRequest();
|
||||
oReq2.open("GET", 'mame/' + opts.jsfile.replace('.js','.wasm'), true);
|
||||
oReq2.responseType = "arraybuffer";
|
||||
oReq2.onload = function(oEvent) {
|
||||
console.log("loaded WASM file");
|
||||
window.Module.wasmBinary = new Uint8Array(oReq2.response);
|
||||
fetch_wasm.resolve();
|
||||
};
|
||||
oReq2.send();
|
||||
}
|
||||
// start loading script
|
||||
script.src = 'mame/' + opts.jsfile;
|
||||
document.getElementsByTagName('head')[0].appendChild(script);
|
||||
$.when(fetch_lua, fetch_cfg, fetch_bios, fetch_wasm).done(function() {
|
||||
var script = document.createElement('script');
|
||||
script.src = 'mame/' + opts.jsfile;
|
||||
document.getElementsByTagName('head')[0].appendChild(script);
|
||||
console.log("created script element");
|
||||
});
|
||||
}
|
||||
|
||||
this.loadROMFile = function(data) {
|
||||
@ -1041,9 +1086,7 @@ var BaseMAMEPlatform = function() {
|
||||
}
|
||||
}
|
||||
|
||||
this.saveState = function() {
|
||||
this.luareset();
|
||||
this.luacall('cpu = manager:machine().devices[":maincpu"]\nfor k,v in pairs(cpu.state) do print(">>>cpu_"..k); print(v.value) end');
|
||||
this.preserveState = function() {
|
||||
var state = {c:{}};
|
||||
for (var k in console_vars) {
|
||||
if (k.startsWith("cpu_")) {
|
||||
@ -1051,15 +1094,26 @@ var BaseMAMEPlatform = function() {
|
||||
state.c[k.slice(4)] = v;
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// TODO: memory?
|
||||
return state;
|
||||
}
|
||||
|
||||
this.readAddress = function(a) {
|
||||
this.saveState = function() {
|
||||
this.luareset();
|
||||
this.luacall('mamedbg.printstate()');
|
||||
return self.preserveState();
|
||||
}
|
||||
|
||||
this.initlua = function() {
|
||||
if (!initluavars) {
|
||||
self.luacall('cpu = manager:machine().devices[":maincpu"]\nmem = cpu.spaces["program"]\n')
|
||||
self.luacall(luadebugscript);
|
||||
self.luacall('mamedbg.init()')
|
||||
initluavars = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.readAddress = function(a) {
|
||||
self.initlua();
|
||||
self.luacall('print(">>>v"); print(mem:read_u8(' + a + '))');
|
||||
return parseInt(console_vars.v[0]);
|
||||
}
|
||||
@ -1068,17 +1122,39 @@ var BaseMAMEPlatform = function() {
|
||||
|
||||
var onBreakpointHit;
|
||||
|
||||
this.clearDebug = function() {
|
||||
onBreakpointHit = null;
|
||||
}
|
||||
this.getDebugCallback = function() {
|
||||
// TODO
|
||||
return onBreakpointHit;
|
||||
}
|
||||
this.setupDebug = function(callback) {
|
||||
self.initlua();
|
||||
self.luareset();
|
||||
onBreakpointHit = callback;
|
||||
}
|
||||
this.runToPC = function(pc) {
|
||||
self.luacall('mamedbg.runTo(' + pc + ')');
|
||||
self.resume();
|
||||
}
|
||||
this.runToVsync = function() {
|
||||
self.luacall('mamedbg.runToVsync()');
|
||||
self.resume();
|
||||
}
|
||||
this.runUntilReturn = function() {
|
||||
self.luacall('mamedbg.runUntilReturn()');
|
||||
self.resume();
|
||||
}
|
||||
this.step = function() {
|
||||
self.readAddress(0);
|
||||
//self.luacall('cpu.debug()\n')
|
||||
self.luacall('debugger = manager:machine().debugger()')
|
||||
self.luacall('print(debugger)') // TODO
|
||||
self.luacall('mamedbg.step()');
|
||||
self.resume();
|
||||
}
|
||||
// TODO: other than z80
|
||||
this.cpuStateToLongString = function(c) {
|
||||
if (c.HL)
|
||||
return cpuStateToLongString_Z80(c);
|
||||
else
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -956,4 +956,39 @@ var APPLEIIGO_LZG = [
|
||||
76,237,253,165,72,72,165,69,166,70,164,71,52,110,22,52,62,27,59,30,59,14,245,3,251,3,98,250,98,250
|
||||
];
|
||||
|
||||
/// MAME support
|
||||
|
||||
var Apple2MAMEPlatform = function(mainElement) {
|
||||
var self = this;
|
||||
this.__proto__ = new BaseMAMEPlatform();
|
||||
|
||||
this.start = function() {
|
||||
self.startModule(mainElement, {
|
||||
jsfile:'mameapple2e.js',
|
||||
//cfgfile:'nes.cfg',
|
||||
driver:'apple2e',
|
||||
width:256*2,
|
||||
height:240*2,
|
||||
//romfn:'/emulator/cart.nes',
|
||||
//romsize:romSize,
|
||||
//romdata:new lzgmini().decode(lzgRom).slice(0, romSize),
|
||||
preInit:function(_self) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.getOpcodeMetadata = Javatari.getOpcodeMetadata;
|
||||
this.getToolForFilename = getToolForFilename_6502;
|
||||
this.getDefaultExtension = function() { return ".c"; };
|
||||
|
||||
this.getPresets = function() { return APPLE2_PRESETS; }
|
||||
|
||||
this.loadROM = function(title, data) {
|
||||
this.loadROMFile(data);
|
||||
this.loadRegion(":nes_slot:cart:prg_rom", data.slice(0x10, 0x8010));
|
||||
this.loadRegion(":nes_slot:cart:chr_rom", data.slice(0x8010, 0xa010));
|
||||
}
|
||||
}
|
||||
|
||||
PLATFORMS['apple2'] = Apple2Platform;
|
||||
PLATFORMS['apple2-e'] = Apple2MAMEPlatform;
|
||||
|
17
src/ui.js
17
src/ui.js
@ -590,9 +590,8 @@ var lastDebugInfo;
|
||||
var lastDebugState;
|
||||
|
||||
function showMemory(state) {
|
||||
var s = "";
|
||||
if (state && platform.cpuStateToLongString) {
|
||||
s = platform.cpuStateToLongString(state.c);
|
||||
var s = state && platform.cpuStateToLongString && platform.cpuStateToLongString(state.c);
|
||||
if (s) {
|
||||
if (platform.getRasterPosition) {
|
||||
var pos = platform.getRasterPosition();
|
||||
s += "H:" + pos.x + " V:" + pos.y + "\n"; // TODO: padding
|
||||
@ -700,9 +699,13 @@ function runToCursor() {
|
||||
var pc = getCurrentPC();
|
||||
if (pc >= 0) {
|
||||
console.log("Run to", pc.toString(16));
|
||||
platform.runEval(function(c) {
|
||||
return c.PC == pc;
|
||||
});
|
||||
if (platform.runToPC) {
|
||||
platform.runToPC(pc);
|
||||
} else {
|
||||
platform.runEval(function(c) {
|
||||
return c.PC == pc;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1282,7 +1285,7 @@ function setupDebugControls(){
|
||||
$("#dbg_tovsync").click(singleFrameStep).show();
|
||||
else
|
||||
$("#dbg_tovsync").hide();
|
||||
if (platform.runEval && platform_id != 'verilog')
|
||||
if ((platform.runEval || platform.runToPC) && platform_id != 'verilog')
|
||||
$("#dbg_toline").click(runToCursor).show();
|
||||
else
|
||||
$("#dbg_toline").hide();
|
||||
|
@ -60,6 +60,7 @@ var PLATFORM_PARAMS = {
|
||||
'coleco': {
|
||||
rom_start: 0x8000,
|
||||
code_start: 0x8100,
|
||||
code_offset: 0x8147, // TODO: right after cv_start()
|
||||
rom_size: 0x8000,
|
||||
data_start: 0x7000,
|
||||
data_size: 0x400,
|
||||
@ -71,8 +72,8 @@ var PLATFORM_PARAMS = {
|
||||
'main.rel'],
|
||||
},
|
||||
'nes-conio': {
|
||||
define: '__NES__',
|
||||
cfgfile: 'nes.cfg',
|
||||
define: '__NES__',
|
||||
libargs: ['nes.lib'],
|
||||
},
|
||||
'nes-lib': {
|
||||
@ -85,6 +86,11 @@ var PLATFORM_PARAMS = {
|
||||
cfgfile: 'apple2.cfg',
|
||||
libargs: ['apple2.lib'],
|
||||
},
|
||||
'apple2-e': {
|
||||
define: '__APPLE2__',
|
||||
cfgfile: 'apple2.cfg',
|
||||
libargs: ['apple2.lib'],
|
||||
},
|
||||
'verilog': {
|
||||
},
|
||||
};
|
||||
@ -289,8 +295,9 @@ function extractErrors(regex, strings) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
function parseListing(code, lineMatch, iline, ioffset, iinsns, origin) {
|
||||
var lines = [];
|
||||
origin |= 0;
|
||||
for (var line of code.split(/\r?\n/)) {
|
||||
var linem = lineMatch.exec(line);
|
||||
if (linem && linem[1]) {
|
||||
@ -300,7 +307,7 @@ function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
if (insns) {
|
||||
lines.push({
|
||||
line:linenum,
|
||||
offset:offset,
|
||||
offset:offset + origin,
|
||||
insns:insns,
|
||||
});
|
||||
}
|
||||
@ -309,9 +316,10 @@ function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
return lines;
|
||||
}
|
||||
|
||||
function parseSourceLines(code, lineMatch, offsetMatch) {
|
||||
function parseSourceLines(code, lineMatch, offsetMatch, origin) {
|
||||
var lines = [];
|
||||
var lastlinenum = 0;
|
||||
origin |= 0;
|
||||
for (var line of code.split(/\r?\n/)) {
|
||||
var linem = lineMatch.exec(line);
|
||||
if (linem && linem[1]) {
|
||||
@ -322,7 +330,7 @@ function parseSourceLines(code, lineMatch, offsetMatch) {
|
||||
var offset = parseInt(linem[1], 16);
|
||||
lines.push({
|
||||
line:lastlinenum,
|
||||
offset:offset,
|
||||
offset:offset + origin,
|
||||
});
|
||||
lastlinenum = 0;
|
||||
}
|
||||
@ -686,7 +694,7 @@ l_main00101 = 0003, L: test
|
||||
*/
|
||||
var amap = FS.readFile("main.map", {'encoding':'utf8'}); // TODO
|
||||
var aout = FS.readFile("main.bin", {'encoding':'binary'});
|
||||
var asmlines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+/i, 1, 2, 3, 4);
|
||||
var asmlines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+/i, 1, 2, 3, params.rom_start|0);
|
||||
var srclines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+;[(]null[)]:(\d+)/i, 3, 2, 1);
|
||||
return {
|
||||
output:aout,
|
||||
@ -813,9 +821,9 @@ function assemblelinkSDASZ80(code, platform) {
|
||||
var rstout = updateListing ? FS.readFile("main.rst", {encoding:'utf8'}) : lstout;
|
||||
//var dbgout = FS.readFile("main.cdb", {encoding:'utf8'});
|
||||
// 0000 21 02 00 [10] 52 ld hl, #2
|
||||
// TODO: offset by start address?
|
||||
var asmlines = parseListing(lstout, /^\s*([0-9A-F]+)\s+([0-9A-F][0-9A-F r]*[0-9A-F])\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 4, 1, 2, 5, 3);
|
||||
var srclines = parseSourceLines(lstout, /^\s+\d+ ;<stdin>:(\d+):/i, /^\s*([0-9A-F]{4})/i);
|
||||
// TODO: use map to find code_offset
|
||||
var asmlines = parseListing(lstout, /^\s*([0-9A-F]+)\s+([0-9A-F][0-9A-F r]*[0-9A-F])\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 4, 1, 2, params.code_offset); //, 5, 3);
|
||||
var srclines = parseSourceLines(lstout, /^\s+\d+ ;<stdin>:(\d+):/i, /^\s*([0-9A-F]{4})/i, params.code_offset);
|
||||
// parse symbol map
|
||||
var symbolmap = {};
|
||||
for (var s of mapout.split("\n")) {
|
||||
@ -935,7 +943,7 @@ function assembleXASM6809(code, platform) {
|
||||
try {
|
||||
var aout = FS.readFile("main.bin", {encoding:'binary'});
|
||||
// 00001 0000 [ 2] 1048 asld
|
||||
var asmlines = parseListing(alst, /^\s*([0-9A-F]+)\s+([0-9A-F]+)\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 1, 2, 4, 5, 3);
|
||||
var asmlines = parseListing(alst, /^\s*([0-9A-F]+)\s+([0-9A-F]+)\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 1, 2, 4, params.code_offset); //, 5, 3);
|
||||
return {
|
||||
output:aout,
|
||||
errors:msvc_errors,
|
||||
@ -1015,7 +1023,7 @@ function assembleNAKEN(code, platform) {
|
||||
var alst = FS.readFile("out.lst", {encoding:'utf8'});
|
||||
//console.log(alst);
|
||||
// 0x0000: 77 ld (hl),a cycles: 4
|
||||
var asmlines = parseListing(alst, /^0x([0-9a-f]+):\s+([0-9a-f]+)\s+(.+)cycles: (\d+)/i, 0, 1, 2, 3);
|
||||
var asmlines = parseListing(alst, /^0x([0-9a-f]+):\s+([0-9a-f]+)\s+(.+)cycles: (\d+)/i, 0, 1, 2); //, 3);
|
||||
return {
|
||||
output:aout,
|
||||
errors:errors,
|
||||
|
Loading…
Reference in New Issue
Block a user