diff --git a/web/app.js b/web/app.js
index f4d9c66..003f594 100644
--- a/web/app.js
+++ b/web/app.js
@@ -76,7 +76,7 @@ function drawFrame(module, canvas) {
canvas.height = height;
}
- const source = new Uint8Array(module.wasmMemory.buffer);
+ const source = module.HEAPU8;
const image = new ImageData(width, height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
@@ -153,6 +153,24 @@ function enableControls(module) {
}
}
+let logEl = null;
+const logBuffer = [];
+const LOG_MAX_LINES = 1000;
+
+function logLine(message) {
+ logBuffer.push(message);
+ if (logBuffer.length > LOG_MAX_LINES) {
+ logBuffer.splice(0, logBuffer.length - LOG_MAX_LINES);
+ }
+ if (logEl) {
+ const atBottom = logEl.scrollTop + logEl.clientHeight >= logEl.scrollHeight - 4;
+ logEl.textContent = logBuffer.join('\n');
+ if (atBottom) {
+ logEl.scrollTop = logEl.scrollHeight;
+ }
+ }
+}
+
async function boot(file, variant, setStatus) {
if (!crossOriginIsolated) {
throw new Error('This emulator requires COOP/COEP headers. Start it with `make web`.');
@@ -175,14 +193,15 @@ async function boot(file, variant, setStatus) {
'-machine', `xteink,variant=${variant}`,
'-L', '/bios',
'-display', 'none',
- '-serial', 'null',
+ '-serial', 'stdio',
'-nic', 'none',
+ '-d', 'guest_errors,unimp',
'-drive', 'file=/flash.bin,if=mtd,format=raw',
],
locateFile: path => new URL(path, artifactRoot).href,
mainScriptUrlOrBlob: qemuUrl.href,
- print: message => console.log(message),
- printErr: message => console.error(message),
+ print: message => { console.log(message); logLine(message); },
+ printErr: message => { console.error(message); logLine(message); },
};
options.preRun = [() => {
options.FS.mkdir('/bios');
@@ -201,6 +220,11 @@ function initialize() {
const bootButton = document.querySelector('#boot');
const status = document.querySelector('#status');
const canvas = document.querySelector('#screen');
+ logEl = document.querySelector('#log');
+ document.querySelector('#log-clear').addEventListener('click', () => {
+ logBuffer.length = 0;
+ logEl.textContent = '';
+ });
const setStatus = (message, error = false) => {
status.textContent = message;
diff --git a/web/index.html b/web/index.html
index 5d504a6..50cd15b 100644
--- a/web/index.html
+++ b/web/index.html
@@ -48,6 +48,14 @@
+
+
diff --git a/web/styles.css b/web/styles.css
index 28dd336..24dd0be 100644
--- a/web/styles.css
+++ b/web/styles.css
@@ -69,3 +69,8 @@ canvas { display: block; width: 100%; height: auto; background: #fff; image-rend
.device { grid-template-columns: 1fr; }
.controls { max-width: 24rem; width: 100%; margin: 0 auto; }
}
+
+.log-panel { margin-top: 2rem; }
+.log-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: .5rem; font-size: .85rem; color: #b9b3a4; }
+.log-header button { min-height: auto; padding: .25rem .75rem; font-size: .8rem; }
+.log { margin: 0; max-height: 20rem; overflow: auto; padding: .75rem 1rem; border-radius: .6rem; background: #1c1d1a; color: #d6d0c2; font: .78rem/1.4 ui-monospace, monospace; white-space: pre-wrap; word-break: break-word; }