More work on debugger

This commit is contained in:
simon987 2020-08-09 21:18:30 -04:00
parent 3ae119072c
commit 60c763167d
11 changed files with 83 additions and 27 deletions

View File

@ -157,6 +157,11 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me
@Override
public void update() {
if (getCpu().isPaused() || getCpu().isExecuting()) {
return;
}
if (currentAction == Action.WALKING) {
if (spendEnergy(100)) {
if (!incrementLocation()) {

View File

@ -276,7 +276,7 @@ public class GameServer implements Runnable {
int allocation = Math.min(user.getControlledUnit().getEnergy() * CPU.INSTRUCTION_COST, maxExecutionInstructions);
cpu.setInstructionAlloction(allocation);
if (!cpu.isPaused()) {
if (!cpu.isPaused() && !cpu.isExecuting()) {
cpu.reset();
executeUserCode(user);
}

View File

@ -23,6 +23,7 @@ public class CPU implements MongoSerializable {
private final Status status;
private boolean trapFlag = false;
private boolean executing = false;
/**
* Memory associated with the CPU, 64kb max
@ -161,6 +162,7 @@ public class CPU implements MongoSerializable {
public int execute() {
executing = true;
int counter = 0;
status.clear();
@ -190,6 +192,7 @@ public class CPU implements MongoSerializable {
writeExecutionStats(counter);
executing = false;
return counter / INSTRUCTION_COST;
}
@ -507,6 +510,10 @@ public class CPU implements MongoSerializable {
return trapFlag;
}
public boolean isExecuting() {
return executing;
}
public void setTrapFlag(boolean trapFlag) {
this.trapFlag = trapFlag;
}

View File

@ -1,6 +1,7 @@
package net.simon987.mar.server.assembly;
import net.simon987.mar.server.io.JSONSerializable;
import net.simon987.mar.server.io.MongoSerializable;
import org.bson.Document;
import org.json.simple.JSONArray;
@ -12,7 +13,7 @@ import java.util.List;
/**
* A set of registers for a CPU
*/
public class RegisterSet implements Target, MongoSerializable, Cloneable {
public class RegisterSet implements Target, MongoSerializable, Cloneable, JSONSerializable {
private int size = 0;
@ -210,4 +211,21 @@ public class RegisterSet implements Target, MongoSerializable, Cloneable {
}
return rs;
}
@Override
public JSONObject jsonSerialise() {
JSONObject json = new JSONObject();
for (int i = 1; i <= size; i++) {
Register reg = getRegister(i);
json.put(reg.getName(), (int)reg.getValue());
}
return json;
}
@Override
public JSONObject debugJsonSerialise() {
return jsonSerialise();
}
}

View File

@ -45,6 +45,10 @@ public class Util {
return String.format("%04X ", a);
}
public static String toHex16(int a) {
return String.format("%04X", a & 0x0000FFFF);
}
public static String toHex(byte[] byteArray) {
StringBuilder result = new StringBuilder();

View File

@ -41,6 +41,7 @@ public class CodeUploadHandler implements MessageHandler {
cpu.setCodeSectionOffset(ar.getCodeSectionOffset());
cpu.reset();
cpu.getRegisterSet().clear();
//Clear keyboard buffer
if (user.getUser().getControlledUnit() != null &&
user.getUser().getControlledUnit().getKeyboardBuffer() != null) {

View File

@ -31,7 +31,7 @@ public class DebugStepHandler implements MessageHandler {
CPU cpu = user.getUser().getControlledUnit().getCpu();
if (!cpu.isPaused()) {
if (!cpu.isPaused() || cpu.isExecuting()) {
return;
}

View File

@ -35,7 +35,7 @@ public class StateRequestHandler implements MessageHandler {
response.put("t", "state");
response.put("memory", cpu.getMemory().toString());
response.put("status", cpu.getStatus().toString());
response.put("registers", cpu.getRegisterSet().toString());
response.put("registers", cpu.getRegisterSet().jsonSerialise());
Map<Integer, Integer> codeLineMap = user.getUser().getCodeLineMap();
Integer line = codeLineMap == null ? null : codeLineMap.get(cpu.getIp());
response.put("line", line == null ? 0 : line);

View File

@ -372,7 +372,7 @@
text-align: right;
}
#disassembly-hl {
.disassembly-hl {
background: #ff000077;
display: inline-block;
width: 100%;

View File

@ -158,40 +158,60 @@ class StateListener implements MessageListener {
stateStatus.removeChild(stateStatus.firstChild);
}
stateMemory.insertAdjacentHTML("beforeend", message.memory.replace(/(0000 )+/g, '<span class="_0">$&</span>'));
// stateMemory.insertAdjacentHTML("beforeend", message.memory);
stateRegisters.insertAdjacentHTML("beforeend", message.registers.replace(/(0000 )+/g, '<span class="_0">$&</span>'));
// stateMemory.insertAdjacentHTML("beforeend", message.memory.replace(/(0000 )+/g, '<span class="_0">$&</span>'));
stateMemory.insertAdjacentHTML("beforeend", message.memory);
let registers = "";
let regKeys = Object.keys(message.registers);
for (let i = 0; i < regKeys.length; i++) {
registers += regKeys[i] + "=" + message.registers[regKeys[i]].toString(16).padStart(4, "0").toUpperCase()
if (i != regKeys.length - 1) {
registers += " ";
}
}
stateRegisters.insertAdjacentHTML("beforeend", registers.replace(/(0000)+/g, '<span class="_0">$&</span>'));
stateStatus.insertAdjacentHTML("beforeend", message.status.replace(/=0/g, '=<span class="_0">0</span>'));
updateDisassemblyPane()
}
}
function hlDisassembly(lines) {
let text = ""
for (let i = 0; i < lines.length; i++) {
text += "<span id='line-" + i + "'>" + lines[i]
.replace(/^\s*([a-zA-Z_]\w*):/gm, '<span class="_l"> $1:</span>')
.replace(/^.*INT 0003$/gm, '<span class="i3">$&</span>')
.replace(/^[0-9A-F]{4}/gm, '<span class="_a">$&</span>')
.replace(/ (MOV|ADD|SUB|AND|OR|TEST|CMP|SHL|SHR|MUL|PUSH|POP|DIV|XOR|DW|NOP|EQU|NEG|HWQ|NOT|ROR|ROL|SAL|SAR|INC|DEC|RCL|XCHG|RCR|PUSHF|POPF|INT|IRET|INTO|SETA|SETNBE|SETAE|SETNB|SETNC|SETBE|SETNA|SETB|SETC|SETNAE|SETE|SETZ|SETNE|SETNZ|SETG|SETNLE|SETGE|SETNL|SETLE|SETNG|SETL|SETNGE|SETO|SETNO|SETS|SETNS)/g, '<span class="_k"> $1</span>')
.replace(/ (CALL|RET|JMP|JNZ|JG|JL|JGE|JLE|HWI|JZ|JS|JNS|JC|JNC|JO|JNO|JA|JNA)/g, '<span class="_o"> $1 </span>')
.replace(/ (BRK)$/gm, '<span class="_b"> $1</span>')
+ "</span>\n";
}
return text;
}
function updateDisassemblyPane() {
const line = mar.pausedLine;
const lines = mar.disassembly.slice();
if (mar.disassembly == undefined || line == -1 || !mar.isPaused) {
return;
}
const stateDisassembly = document.getElementById("state-disassembly");
while (stateDisassembly.firstChild) {
stateDisassembly.removeChild(stateDisassembly.firstChild);
}
if (!mar.disassemblyInitialized) {
mar.disassemblyInitialized = true;
while (stateDisassembly.firstChild) {
stateDisassembly.removeChild(stateDisassembly.firstChild);
}
if (line != -1 && mar.isPaused) {
lines[line] = `<span id="disassembly-hl">${lines[line]}</span>`
}
stateDisassembly.innerHTML = lines.join("\n")
.replace(/^\s*([a-zA-Z_]\w*):/gm, '<span class="_l"> $1:</span>')
.replace(/^.*INT 0003$/gm, '<span class="i3">$&</span>')
.replace(/^[0-9A-F]{4}/gm, '<span class="_a">$&</span>')
.replace(/ (MOV|ADD|SUB|AND|OR|TEST|CMP|SHL|SHR|MUL|PUSH|POP|DIV|XOR|DW|NOP|EQU|NEG|HWQ|NOT|ROR|ROL|SAL|SAR|INC|DEC|RCL|XCHG|RCR|PUSHF|POPF|INT|IRET|INTO|SETA|SETNBE|SETAE|SETNB|SETNC|SETBE|SETNA|SETB|SETC|SETNAE|SETE|SETZ|SETNE|SETNZ|SETG|SETNLE|SETGE|SETNL|SETLE|SETNG|SETL|SETNGE|SETO|SETNO|SETS|SETNS)/g, '<span class="_k"> $1</span>')
.replace(/ (CALL|RET|JMP|JNZ|JG|JL|JGE|JLE|HWI|JZ|JS|JNS|JC|JNC|JO|JNO|JA|JNA) /g, '<span class="_o"> $1 </span>')
.replace(/ (BRK)$/gm, '<span class="_b"> $1</span>')
const hl = document.getElementById("disassembly-hl");
if (hl != null) {
hl.scrollIntoView({block: "center"});
stateDisassembly.innerHTML = hlDisassembly(mar.disassembly)
} else {
[].forEach.call(document.getElementsByClassName("disassembly-hl"), el => el.setAttribute("class", null));
}
const lineElem = document.getElementById("line-" + line);
lineElem.classList.add("disassembly-hl");
lineElem.scrollIntoView({block: "center"});
}
class DisassemblyListener implements MessageListener {

View File

@ -1,6 +1,7 @@
class MarGame {
disassembly : string[];
disassemblyInitialized = false
pausedLine: number = -1;
_isPaused = false