ui: refresh windows when errors/EmuHalt; arm32 changes

This commit is contained in:
Steven Hugg 2021-06-12 11:29:49 -05:00
parent d79f3c3da9
commit 240578d942
6 changed files with 297 additions and 256 deletions

View File

@ -201,11 +201,13 @@ TODO:
- show current tool for file
- download non-text incbin source file
- show hidden header files that only exist in Emscripten FS
can't modify/delete an include file if project doesn't compile
Probing
- probe log doesn't start @ reset
- scroll to current probe log location
Debug, play then halt cpu doesn't highlight final line
- illegal instruction should show debug info + jump to line
- halt cpu should show video too
vcs: input not preserved when replaying frames?

File diff suppressed because it is too large Load Diff

View File

@ -1126,7 +1126,6 @@ function showExceptionAsError(err, msg:string) {
werr = Object.create(err.$loc);
werr.msg = msg;
console.log(werr);
projectWindows.refresh(false);
}
showErrorAlert([werr], true);
}
@ -1149,6 +1148,7 @@ function setCompileOutput(data: WorkerResult) {
if (data && data.errors && data.errors.length > 0) {
toolbar.addClass("has-errors");
projectWindows.setErrors(data.errors);
refreshWindowList(); // to make sure windows are created for showErrorAlert()
showErrorAlert(data.errors, false);
} else {
toolbar.removeClass("has-errors"); // may be added in next callback
@ -1657,14 +1657,15 @@ function addFileToProject(type, ext, linefn) {
function _addIncludeFile() {
var fn = getCurrentMainFilename();
var tool = platform.getToolForFilename(fn);
// TODO: more tools?
if (fn.endsWith(".c") || tool == 'sdcc' || tool == 'cc65' || tool == 'cmoc' || tool == 'smlrc')
addFileToProject("Header", ".h", (s) => { return '#include "'+s+'"' });
else if (tool == 'dasm' || tool == 'zmac')
addFileToProject("Include File", ".inc", (s) => { return '\tinclude "'+s+'"' });
else if (tool == 'ca65' || tool == 'sdasz80')
addFileToProject("Include File", ".inc", (s) => { return '\t.include "'+s+'"' });
addFileToProject("Include", ".inc", (s) => { return '\tinclude "'+s+'"' });
else if (tool == 'ca65' || tool == 'sdasz80' || tool == 'vasm' || tool == 'armips')
addFileToProject("Include", ".inc", (s) => { return '\t.include "'+s+'"' });
else if (tool == 'verilator')
addFileToProject("Verilog File", ".v", (s) => { return '`include "'+s+'"' });
addFileToProject("Verilog", ".v", (s) => { return '`include "'+s+'"' });
else
alertError("Can't add include file to this project type (" + tool + ")");
}
@ -2340,6 +2341,8 @@ export function getSaveState() {
export function emulationHalted(err: EmuHalt) {
var msg = (err && err.message) || msg;
showExceptionAsError(err, msg);
projectWindows.refresh(true);
if (platform.saveState) showDebugInfo(platform.saveState());
}
// get remote file from local fs

View File

@ -6,23 +6,23 @@ import { TssChannelAdapter, MasterAudio, AY38910_Audio } from "../common/audio";
import { Debuggable, EmuState } from "../common/baseplatform";
import { hex, lpad, printFlags } from "../common/util";
const SPACEINV_KEYCODE_MAP = makeKeycodeMap([
[Keys.A, 1, 0x10], // P1
[Keys.LEFT, 1, 0x20],
[Keys.RIGHT, 1, 0x40],
[Keys.P2_A, 2, 0x10], // P2
[Keys.P2_LEFT, 2, 0x20],
[Keys.P2_RIGHT, 2, 0x40],
[Keys.SELECT, 1, 0x1],
[Keys.START, 1, 0x4],
[Keys.P2_START, 1, 0x2],
var GBA_KEYCODE_MAP = makeKeycodeMap([
[Keys.A, 0, 0x1],
[Keys.B, 0, 0x2],
[Keys.SELECT,0, 0x4],
[Keys.START ,0, 0x8],
[Keys.RIGHT, 0, 0x10],
[Keys.LEFT, 0, 0x20],
[Keys.UP, 0, 0x40],
[Keys.DOWN, 0, 0x80],
]);
const ROM_START = 0x0;
const ROM2_START= 0xff800000;
const ROM_SIZE = 0x80000;
const RAM_START = 0x20000000;
const RAM_START = 0x2000000;
const RAM_SIZE = 0x80000;
const IO_START = 0x4000000;
const IO_SIZE = 0x100;
const CPU_FREQ = 4000000; // 4 MHz
@ -47,14 +47,13 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
constructor() {
super();
this.connectCPUMemoryBus(this);
this.handler = newKeyboardHandler(this.inputs, SPACEINV_KEYCODE_MAP);
this.handler = newKeyboardHandler(this.inputs, GBA_KEYCODE_MAP);
}
connectVideo(pixels:Uint32Array) : void {
super.connectVideo(pixels);
this.pixels32 = pixels;
this.pixels8 = new Uint8Array(pixels.buffer);
//this.pixels.fill(0xff000000);
}
// TODO: 32-bit bus?
@ -66,8 +65,8 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
[RAM_START, RAM_START+RAM_SIZE-1, RAM_SIZE-1, (a) => {
return this.ram[a];
}],
[ROM2_START, ROM2_START+ROM_SIZE-1, ROM_SIZE-1, (a) => {
return this.rom ? this.rom[a] : 0;
[IO_START, IO_START+IO_SIZE-1, IO_SIZE-1, (a, v) => {
return this.readIO(a);
}],
]);
@ -75,8 +74,28 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
[RAM_START, RAM_START+RAM_SIZE-1, RAM_SIZE-1, (a, v) => {
this.ram[a] = v;
}],
[IO_START, IO_START+IO_SIZE-1, IO_SIZE-1, (a, v) => {
this.writeIO(a, v);
}],
]);
readIO(a : number) : number {
switch (a) {
case 0x0:
return this.inputs[0];
default:
return 0;
}
}
writeIO(a : number, v : number) : void {
switch (a) {
case 0x0:
//this.brightness = v & 0xff;
break;
}
}
startScanline() {
}
@ -96,29 +115,32 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
}
getDebugCategories() {
return ['CPU'];
return ['CPU', 'Stack'];
}
getDebugInfo?(category: string, state: EmuState) : string {
var s = '';
var c = state.c as ARMCoreState;
const EXEC_MODE = {2:'Thumb',4:'ARM'};
const REGNAMES = {15:'PC',14:'LR',13:'SP',12:'IP',11:'FP',9:'SB'};
for (var i=0; i<16; i++) {
s += lpad(REGNAMES[i]||'',3) + lpad('r'+i, 5) + ' ' + hex(c.gprs[i],8) + '\n';
switch (category) {
case 'CPU':
var s = '';
var c = state.c as ARMCoreState;
const EXEC_MODE = {2:'Thumb',4:'ARM'};
const REGNAMES = {15:'PC',14:'LR',13:'SP',12:'IP',11:'FP',9:'SB'};
for (var i=0; i<16; i++) {
s += lpad(REGNAMES[i]||'',3) + lpad('r'+i, 5) + ' ' + hex(c.gprs[i],8) + '\n';
}
s += 'Flags ';
s += c.cpsrN ? " N" : " -";
s += c.cpsrV ? " V" : " -";
s += c.cpsrF ? " F" : " -";
s += c.cpsrZ ? " Z" : " -";
s += c.cpsrC ? " C" : " -";
s += c.cpsrI ? " I" : " -";
s += '\n';
s += 'MODE ' + EXEC_MODE[c.instructionWidth] + ' ' + MODE_NAMES[c.mode] + '\n';
s += 'SPSR ' + hex(c.spsr,8) + '\n';
s += 'cycl ' + c.cycles + '\n';
return s;
}
s += 'Flags ';
s += c.cpsrN ? " N" : " -";
s += c.cpsrV ? " V" : " -";
s += c.cpsrF ? " F" : " -";
s += c.cpsrZ ? " Z" : " -";
s += c.cpsrC ? " C" : " -";
s += c.cpsrI ? " I" : " -";
s += '\n';
s += 'MODE ' + EXEC_MODE[c.instructionWidth] + ' ' + MODE_NAMES[c.mode] + '\n';
s += 'SPSR ' + hex(c.spsr,8) + '\n';
s += 'cycl ' + c.cycles + '\n';
return s;
}
}

View File

@ -251,9 +251,8 @@ class ARM32Platform extends BaseARMMachinePlatform<ARM32Machine> implements Plat
newMachine() { return new ARM32Machine(); }
readAddress(a) { return this.machine.read(a); }
getMemoryMap = function() { return { main:[
{name:'ROM',start:0x00000000,size:0x80000,type:'rom'},
{name:'RAM',start:0x20000000,size:0x80000,type:'ram'},
{name:'Video RAM',start:0x40000000,size:0x20000,type:'ram'},
{name:'ROM',start:0x0000000,size:0x80000,type:'rom'},
{name:'RAM',start:0x2000000,size:0x80000,type:'ram'},
] } };
disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
var is_thumb = this.machine.cpu.isThumb();

View File

@ -455,15 +455,17 @@ function gatherFiles(step:BuildStep, options?:BuildOptions) {
step.files = [path];
}
if (step.path && !step.prefix) {
step.prefix = step.path;
var pos = step.prefix.lastIndexOf('.');
if (pos > 0)
step.prefix = step.prefix.substring(0, pos);
step.prefix = getPrefix(step.path);
}
step.maxts = maxts;
return maxts;
}
function getPrefix(s : string) : string {
var pos = s.lastIndexOf('.');
return (pos > 0) ? s.substring(0, pos) : s;
}
function populateFiles(step:BuildStep, fs, options?:BuildOptions) {
gatherFiles(step, options);
if (!step.files) throw Error("call gatherFiles() first");
@ -2903,6 +2905,10 @@ function assembleARMIPS(step:BuildStep) {
});
var FS = armips['FS'];
var code = getWorkFileAsString(step.path);
code = `.arm.little :: .create "${objpath}",0 :: ${code}
.close`;
putWorkFile(step.path, code);
populateFiles(step, FS);
execMain(step, armips, args);
if (errors.length)
@ -2916,26 +2922,30 @@ function assembleARMIPS(step:BuildStep) {
var symbolmap = {};
var segments = [];
var listings : CodeListingMap = {};
var lstout = FS.readFile(lstpath, {encoding:'utf8'}) as string;
var lines = lstout.split(re_crlf);
var lstlines : SourceLine[] = [];
//00000034 .word 0x11223344 ; /vidfill.armips line 25
var re_asmline = /^([0-9A-F]+) (.+?); [/](.+?) line (\d+)/;
var lastofs = -1;
for (var line of lines) {
var m;
if (m = re_asmline.exec(line)) {
var path = m[3];
var path2 = getPrefix(path) + '.lst'; // TODO: don't rename listing
var lst = listings[path2];
if (lst == null) { lst = listings[path2] = {lines:[]}; }
var ofs = parseInt(m[1], 16);
var insn = objout.slice(ofs, ofs+4); // TODO: doesn't do thumb or !=4 bytes
lstlines.push({
path: m[3],
if (lastofs == ofs) lst.lines.pop(); else lastofs = ofs;
lst.lines.push({
path: path,
line: parseInt(m[4]),
offset: ofs,
insns: hex(insn[0]) + hex(insn[1]) + hex(insn[2]) + hex(insn[3])
insns: hex(insn[3]) + hex(insn[2]) + hex(insn[1]) + hex(insn[0])
});
}
}
listings[lstpath] = {lines:lstlines, text:lstout};
//listings[lstpath] = {lines:lstlines, text:lstout};
var symout = FS.readFile(sympath, {encoding:'utf8'}) as string;
//0000000C loop2
@ -2988,7 +2998,6 @@ function assembleVASMARM(step:BuildStep) {
path:matches[4],
msg:matches[5],
});
console.log(matches);
} else {
matches = re_err2.exec(s);
if (matches) {