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 @@ + +
+
+ QEMU log + +
+

+    
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; }