diff --git a/src/disp/disp_sc8850.mjs b/src/disp/disp_sc8850.mjs index 5c2b37e..252e07a 100644 --- a/src/disp/disp_sc8850.mjs +++ b/src/disp/disp_sc8850.mjs @@ -60,6 +60,7 @@ let Sc8850Display = class extends RootDisplay { #nmdb = new Uint8Array(totalPixelCount); #dmdb = new Uint8Array(totalPixelCount); #omdb = new Uint8Array(totalPixelCount); + #bmdb = new Uint8Array(totalPixelCount); #linger = new Uint8Array(allocated.ch); #lingerExtra = new Uint8Array(allocated.ch); #ch = 0; @@ -71,6 +72,7 @@ let Sc8850Display = class extends RootDisplay { #unresolvedEx = false; #awaitEx = 0; #promptEx = 0; + #dumpExpire = 0; #booted = 0; #bootFrame = 0; font55 = new MxFont40("./data/bitmaps/sc/libre55.tsv"); @@ -105,6 +107,18 @@ let Sc8850Display = class extends RootDisplay { upThis.#scheduledEx = true; getDebugState() && console.debug(`Scheduled a SysEx prompt.`); }); + upThis.device.addEventListener("reset", (ev) => { + upThis.#bmdb.fill(0); + }); + upThis.device.addEventListener("screen", (ev) => { + let data = ev.data; + if (data.type == "sc8850") { + for (let i = 0; i < data.data.length; i ++) { + upThis.#bmdb[data.offset + i] = data.data[i] ? 255 : 0; + }; + }; + upThis.#dumpExpire = Date.now() + 5000; + }); upThis.bootBm.load(`RsrcName\tBitmap\nboot_mr\t009e003efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffe3ffffffffffffffffffe0007fffffffffffffff8ffffffffffffffffffe0000fffffe3ffffffffffffffffffffffffffff01e01fffff8ffffffffffffffffffffffffffff03ff07f83f007c0787e187f01ffffffffffffff83ffe0f003803800e1f8e3e003fffffffffffffe1fff83838787c18187c70f0607fffffffffffff07ffe0c3f3e3e1f861e3c787e1fffffffffffffc3fff863fff0f1fe1871e1c7f87ffffffffffffe0fffc10fffc787f8e18f8e1fe3fffffffffffff83fff0c7fff1e3fe3847e38ff8fffffffffffffe0fff831fff878ff0e03f0e3fc3fffffffffffffc1ff81c7f3e3e3f8781fc78fe1ffffffffffffff00f01f06070f8301e0fe1e0c07fffffffffffffe0000fe003c7e000f83f8f8003ffffffffffffffc000ffc07e1fe063e1fc3f818fffffffffffffffe01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\nbs_0\t000700073880000000000\nbs_1\t000700073888081020000\nbs_2\t0007000738080810288e0\nbs_3\t00070007388a0c18288e0\nbs_4\t00070007000a0c18288e0\nbs_5\t0007000700020408088e0\nbs_6\t000700070002040808000\nbs_7\t000700070000000000000`); (async () => { await Promise.all([upThis.font55.loaded.wait(), upThis.font56.loaded.wait(), upThis.font7a.loaded.wait()]); @@ -131,7 +145,9 @@ let Sc8850Display = class extends RootDisplay { let timeNow = Date.now(); let fullRefresh = false; let scConf = upThis.device.modelEx.sc; - upThis.#nmdb.fill(0); + if (timeNow >= upThis.#dumpExpire) { + upThis.#nmdb.fill(0); + }; // Prepare the canvas if (timeNow - upThis.#lastBg >= 3600000) { ctx.fillStyle = backlight.orange; @@ -152,7 +168,9 @@ let Sc8850Display = class extends RootDisplay { fullRefresh = true; }; // Booted? - if (upThis.#booted > 0 && upThis.#bootFrame > 99) { + if (timeNow < upThis.#dumpExpire) { + upThis.#nmdb.set(upThis.#bmdb); + } else if (upThis.#booted > 0 && upThis.#bootFrame > 99) { // Test SysEx status if (upThis.#scheduledEx) { upThis.#scheduledEx = false; diff --git a/src/state/index.mjs b/src/state/index.mjs index f4b4124..803be28 100644 --- a/src/state/index.mjs +++ b/src/state/index.mjs @@ -3973,6 +3973,38 @@ let OctaviaDevice = class extends CustomEventSource { }; }; }; + }).add([69, 18, 32], (msg, track, id) => { + // SC-8850 screen dump (partial) + let bundleId = msg[0], boundOff = msg[1], workArr = msg.subarray(2); + if (bundleId >> 4) { + console.warn(`SC-8850 partial screen dump out of bounds: invalid bundle.\n`, msg); + return; + }; + let desiredByteTail = boundOff + workArr.length, + desiredLengthHead = boundOff * 6 - ((boundOff * 2428 >> 16) << 1), + desiredLengthTail = desiredByteTail * 6 - ((desiredByteTail * 2428 >> 16) << 1); // That's an integer division of 27, then a multiple of 2. + if (desiredLengthHead >= 640) { + console.warn(`SC-8850 partial screen dump out of bounds: invalid buffer range.\n`, msg); + return; + }; + if (desiredLengthTail > 640) { + console.info(`SC-8850 partial screen dump out of bounds: invalid buffer end, automatically restricted.\n`, msg); + desiredLengthTail = 640; + }; + let screenBuffer = new Uint8Array(desiredLengthTail - desiredLengthHead); + workArr.forEach((e, i) => { + let ri = i + boundOff; + let isLineEnd = ((ri * 2428 & 65535) * 27 >> 16) == 26; + let pi = ri * 6 - ((ri * 2428 >> 16) << 1); + let bi = isLineEnd ? 2 : 0; + while (bi < 6) { + screenBuffer[pi + (5 - bi)] = (e >> bi) & 1; + bi ++; + }; + }); + let byteOffset = bundleId * 108 + boundOff, + offset = byteOffset * 6 - ((byteOffset * 2428 >> 16) << 1); // Used for emitting events than for internal processing. + upThis.dispatchEvent("screen", {type: "sc8850", offset, data: screenBuffer}); }); // GS Part setup // I wanted this to also be written in a circular structure