UNPKG

@marioslab/ulang-vm

Version:

Virtual machine & assembler for recreational programming like it's 1992.

404 lines 34.2 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import * as ulang from "./wrapper"; export { compile, printMemory } from "./wrapper"; export var VirtualMachineState; (function (VirtualMachineState) { VirtualMachineState[VirtualMachineState["Stopped"] = 0] = "Stopped"; VirtualMachineState[VirtualMachineState["Running"] = 1] = "Running"; VirtualMachineState[VirtualMachineState["Paused"] = 2] = "Paused"; })(VirtualMachineState || (VirtualMachineState = {})); export var LogLevel; (function (LogLevel) { LogLevel[LogLevel["None"] = 0] = "None"; LogLevel[LogLevel["Info"] = 1] = "Info"; })(LogLevel || (LogLevel = {})); export class VirtualMachine { constructor(canvasElement) { this.state = VirtualMachineState.Stopped; this.compilerResult = null; this.vmStart = 0; this.executedInstructions = 0; this.vsyncHit = false; this.debugSyscallHit = false; this.breakpoints = []; this.bpPtr = 0; this.numBps = 0; this.syscallHandlerPtr = 0; this.lastStepHitBreakpoint = false; this.stateChangeListener = null; this.logLevel = LogLevel.Info; this.mouseX = 0; this.mouseY = 0; this.mouseButtonDown = false; this.keys = new Map(); this.listeners = []; if (typeof (canvasElement) === "string") this.canvas = document.getElementById(canvasElement); else this.canvas = canvasElement; this.rgbaFramePtr = ulang.alloc(320 * 240 * 4); this.addEventListener("mousemove", (e) => { var rect = this.canvas.getBoundingClientRect(); this.mouseX = ((e.clientX - rect.left) / this.canvas.clientWidth * 320) | 0; this.mouseY = ((e.clientY - rect.top) / this.canvas.clientHeight * 240) | 0; }); this.addEventListener("mousedown", (e) => { var rect = this.canvas.getBoundingClientRect(); this.mouseX = ((e.clientX - rect.left) / this.canvas.clientWidth * 320) | 0; this.mouseY = ((e.clientY - rect.top) / this.canvas.clientHeight * 240) | 0; this.mouseButtonDown = true; }); this.addEventListener("mouseup", (e) => { var rect = this.canvas.getBoundingClientRect(); this.mouseX = ((e.clientX - rect.left) / this.canvas.clientWidth * 320) | 0; this.mouseY = ((e.clientY - rect.top) / this.canvas.clientHeight * 240) | 0; this.mouseButtonDown = false; }); this.addEventListener("mouseleave", (e) => { var rect = this.canvas.getBoundingClientRect(); this.mouseX = ((e.clientX - rect.left) / this.canvas.clientWidth * 320) | 0; this.mouseY = ((e.clientY - rect.top) / this.canvas.clientHeight * 240) | 0; this.mouseButtonDown = false; }); let syscallHandler = (syscall, vmPtr) => { let vm = ulang.ptrToUlangVm(vmPtr); switch (syscall) { case 0: this.pause(); this.debugSyscallHit = true; return 0; case 1: let buffer = vm.popUint(); ulang.argbToRgba(vm.memoryPtr() + buffer, this.rgbaFramePtr, 320 * 240); let frame = new Uint8ClampedArray(ulang.HEAPU8().buffer, this.rgbaFramePtr, 320 * 240 * 4); let imageData = new ImageData(frame, 320, 240); this.canvas.getContext("2d").putImageData(imageData, 0, 0); this.vsyncHit = true; return 0; case 2: { let str = ""; while (true) { let argType = vm.popUint(); if (argType == 6) break; switch (argType) { case 0: str += vm.popInt(); break; case 1: str += "0x" + vm.popInt().toString(16); break; case 2: str += vm.popFloat(); break; case 3: let strAddr = vm.popUint(); str += ulang.UTF8ArrayToString(ulang.HEAPU8(), vm.memoryPtr() + strAddr); break; case 4: str += " "; break; case 5: str += "\n"; break; default: break; } } console.log(str); return -1; } case 3: { vm.pushInt(this.mouseX); vm.pushInt(this.mouseY); vm.pushInt(this.mouseButtonDown ? -1 : 0); return -1; } case 4: { } case 5: { vm.pushFloat(performance.now() / 1000); return -1; } } }; this.syscallHandlerPtr = ulang.addFunction(syscallHandler, "iii"); } addEventListener(type, listener) { this.canvas.addEventListener(type, listener); this.listeners.push({ type: type, listener: listener }); } dipose() { this.stop(); for (let i = 0; i < this.listeners.length; i++) { let listener = this.listeners[i]; this.canvas.removeEventListener(listener.type, listener.listener); } ulang.free(this.rgbaFramePtr); } setLogLevel(logLevel) { this.logLevel = logLevel; } setStateChangeListener(listener) { this.stateChangeListener = listener; } setBreakpoints(breakpoints) { this.breakpoints = breakpoints; if (this.bpPtr != 0) { ulang.free(this.bpPtr); this.bpPtr = 0; this.numBps = 0; } if (this.state != VirtualMachineState.Stopped) this.calculateBreakpoints(); } calculateBreakpoints() { if (this.bpPtr != 0) return this.bpPtr; // Needs to come before the next line, as WASM memory can grow and pointers may get relocated let addressToLine = this.vm.program().addressToLine(); let p = this.bpPtr = ulang.alloc(4 * this.breakpoints.length); for (let i = 0; i < this.breakpoints.length; i++) { let bpLine = this.breakpoints[i]; for (let j = 0; j < addressToLine.length; j++) { if (addressToLine[j] == bpLine) { ulang.setUint32(p, j * 4); p += 4; this.numBps++; break; } } } return this.bpPtr; } run(source) { if (this.compilerResult) { this.compilerResult.free(); this.compilerResult = null; } if (this.vm) { this.vm.free(); this.vm = null; } this.compilerResult = ulang.compile(source); if (this.compilerResult.error.isSet()) { alert("Can't run program with errors."); this.compilerResult.error.print(); this.compilerResult.free(); if (this.stateChangeListener) this.stateChangeListener(this, this.state); return; } this.vm = ulang.newVm(this.compilerResult.program); for (let i = 0; i <= 255; i++) { this.vm.setSyscall(i, this.syscallHandlerPtr); } this.vmStart = performance.now(); this.executedInstructions = 0; this.lastStepHitBreakpoint = false; this.state = VirtualMachineState.Running; if (this.stateChangeListener) this.stateChangeListener(this, this.state); requestAnimationFrame(() => this.frame()); } stop() { if (this.state != VirtualMachineState.Running && this.state != VirtualMachineState.Paused) return; this.state = VirtualMachineState.Stopped; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmTime(); this.printVmState(); } pause() { if (this.state != VirtualMachineState.Running) return; this.state = VirtualMachineState.Paused; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmState(); } continue() { if (this.state != VirtualMachineState.Paused) return; this.state = VirtualMachineState.Running; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmState(); requestAnimationFrame(() => this.frame()); } step() { if (this.state != VirtualMachineState.Paused) return; if (!this.vm.step()) { if (this.vsyncHit || this.debugSyscallHit) { this.vsyncHit = false; this.debugSyscallHit = false; } else { this.state = VirtualMachineState.Stopped; if (this.stateChangeListener) this.stateChangeListener(this, this.state); return; } } if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmState(); } getCurrentLine() { if (this.state != VirtualMachineState.Paused) return -1; let pc = this.vm.registers()[14].ui() >> 2; let addressToLine = this.vm.program().addressToLine(); if (pc >= addressToLine.length) return -1; return addressToLine[pc]; } getState() { return this.state; } getRegisters() { return this.vm.registers(); } getProgram() { return this.vm.program(); } getInt(addr) { return ulang.getInt32(this.vm.memoryPtr() + addr); } getFloat(addr) { return ulang.getFloat32(this.vm.memoryPtr() + addr); } printVmTime() { if (this.logLevel == LogLevel.None) return; let vmTime = (performance.now() - this.vmStart) / 1000; console.log("VM took " + vmTime + " secs"); console.log("Executed " + this.executedInstructions + " instructions, " + ((this.executedInstructions / vmTime) | 0) + " ins/s"); } printVmState() { if (this.logLevel == LogLevel.None) return; this.vm.print(); } getCanvas() { return this.canvas; } frame() { if (this.state == VirtualMachineState.Running) { let frameStart = performance.now(); const instsPerStep = 20000; // if we had a breakpoint in the last frame, we need // to step over the current instruction, so we don't // get stuck there. if (this.lastStepHitBreakpoint) { this.lastStepHitBreakpoint = false; if (!this.vm.step()) { if (this.vsyncHit || this.debugSyscallHit) { this.vsyncHit = false; this.debugSyscallHit = false; requestAnimationFrame(() => this.frame()); return; } this.state = VirtualMachineState.Stopped; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmTime(); this.printVmState(); return; } } while (true) { this.executedInstructions += instsPerStep; let result = 0; if (this.breakpoints.length > 0) this.calculateBreakpoints(); if (this.numBps > 0) { result = this.vm.stepNBP(instsPerStep, this.bpPtr, this.numBps); // hit a breakpoint, pause execution if (result >= 1) { this.lastStepHitBreakpoint = true; this.state = VirtualMachineState.Paused; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmState(); return; } } else { result = this.vm.stepN(instsPerStep); } if (!result) { if (this.vsyncHit || this.debugSyscallHit) { this.vsyncHit = false; this.debugSyscallHit = false; requestAnimationFrame(() => this.frame()); return; } this.state = VirtualMachineState.Stopped; if (this.stateChangeListener) this.stateChangeListener(this, this.state); this.printVmTime(); this.printVmState(); return; } let frameTime = performance.now() - frameStart; if (frameTime > 16) { requestAnimationFrame(() => this.frame()); return; } } } } } let loaded = false; export function loadUlang() { return __awaiter(this, void 0, void 0, function* () { if (!loaded) { loaded = true; yield ulang.loadUlang(); } }); } export function createPlayerFromGist(canvas, gistId) { return __awaiter(this, void 0, void 0, function* () { yield loadUlang(); let response = yield fetch(`https:/api.github.com/gists/${gistId}`); if (response.status >= 400) throw new Error(`Couldn't fetch gist ${gistId}`); let gist = yield response.json(); if (!gist.files || !gist.files["source.ul"] || !gist.files["source.ul"].content) { throw new Error("Gist ${gistId} is not a ulang program."); } return new UlangPlayer(canvas, gist.files["source.ul"].content); }); } export class UlangPlayer { constructor(canvas, source) { this.vm = new VirtualMachine(canvas); this.source = source; } play() { this.vm.run(this.source); } getVirtualMachine() { return this.vm; } getSource() { return this.source; } dispose() { if (this.vm) this.vm.dipose(); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxLQUFLLEtBQUssTUFBTSxXQUFXLENBQUM7QUFFbkMsT0FBTyxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFakQsTUFBTSxDQUFOLElBQVksbUJBRVg7QUFGRCxXQUFZLG1CQUFtQjtJQUM5QixtRUFBTyxDQUFBO0lBQUUsbUVBQU8sQ0FBQTtJQUFFLGlFQUFNLENBQUE7QUFDekIsQ0FBQyxFQUZXLG1CQUFtQixLQUFuQixtQkFBbUIsUUFFOUI7QUFFRCxNQUFNLENBQU4sSUFBWSxRQUdYO0FBSEQsV0FBWSxRQUFRO0lBQ25CLHVDQUFJLENBQUE7SUFDSix1Q0FBSSxDQUFBO0FBQ0wsQ0FBQyxFQUhXLFFBQVEsS0FBUixRQUFRLFFBR25CO0FBT0QsTUFBTSxPQUFPLGNBQWM7SUF1QjFCLFlBQWEsYUFBeUM7UUFwQjlDLFVBQUssR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLENBQUM7UUFDcEMsbUJBQWMsR0FBaUMsSUFBSSxDQUFBO1FBQ25ELFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWix5QkFBb0IsR0FBRyxDQUFDLENBQUM7UUFDekIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQixvQkFBZSxHQUFHLEtBQUssQ0FBQztRQUN4QixnQkFBVyxHQUFhLEVBQUUsQ0FBQztRQUMzQixVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsV0FBTSxHQUFHLENBQUMsQ0FBQztRQUNYLHNCQUFpQixHQUFHLENBQUMsQ0FBQztRQUN0QiwwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDOUIsd0JBQW1CLEdBQTZELElBQUksQ0FBQztRQUNyRixhQUFRLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztRQUN6QixXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsV0FBTSxHQUFHLENBQUMsQ0FBQztR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