From 9650bad8f80df3a145413a67d4d4c54d09c31e62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Thu, 23 Jun 2022 15:16:35 +0100
Subject: [PATCH] feat: retina canvas support Also added error icon

---
 examples/web/index.css     |   2 ++
 examples/web/index.ts      |  58 ++++++++++++++++++++++++++++++++-----
 examples/web/res/storm.png | Bin 0 -> 1889 bytes
 3 files changed, 53 insertions(+), 7 deletions(-)
 create mode 100644 examples/web/res/storm.png

diff --git a/examples/web/index.css b/examples/web/index.css
index 5a483d5..3145e88 100644
--- a/examples/web/index.css
+++ b/examples/web/index.css
@@ -88,6 +88,8 @@ p {
     border: 2px solid #50cb93;
     margin-top: 76px;
     max-width: 100%;
+    width: 640px;
+    height: 320px;
     padding: 8px 8px 8px 8px;
 }
 
diff --git a/examples/web/index.ts b/examples/web/index.ts
index 4911362..2be3cc5 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -3,7 +3,6 @@ import info from "./package.json";
 
 const PIXEL_SET_COLOR = 0x50cb93ff;
 const PIXEL_UNSET_COLOR = 0x1b1a17ff;
-const PIXEL_ERROR_COLOR = 0xe63946ff;
 
 const LOGIC_HZ = 600;
 const VISUAL_HZ = 60;
@@ -179,7 +178,11 @@ const main = async () => {
             // system and the machine state (to be able to recover)
             // also sets the default color on screen to indicate the issue
             if (isPanic) {
-                clearCanvas();
+                clearCanvas(undefined, {
+                    // @ts-ignore: ts(2580)
+                    image: require("./res/storm.png"),
+                    imageScale: 0.4
+                });
 
                 await wasm();
                 await start({ restore: false });
@@ -649,6 +652,10 @@ const initCanvas = async () => {
     state.canvasScaled = document.getElementById(
         "chip-canvas"
     ) as HTMLCanvasElement;
+    state.canvasScaled.width =
+        state.canvasScaled.width * window.devicePixelRatio;
+    state.canvasScaled.height =
+        state.canvasScaled.height * window.devicePixelRatio;
     state.canvasScaledCtx = state.canvasScaled.getContext("2d");
 
     state.canvasScaledCtx.scale(
@@ -675,12 +682,49 @@ const updateCanvas = (pixels: Uint8Array) => {
     state.canvasScaledCtx.drawImage(state.canvas, 0, 0);
 };
 
-const clearCanvas = (color = PIXEL_UNSET_COLOR) => {
-    for (let i = 0; i < DISPLAY_WIDTH * DISPLAY_HEIGHT; i++) {
-        state.videoBuff.setUint32(i * 4, color);
+const clearCanvas = (
+    color = PIXEL_UNSET_COLOR,
+    { image = null as string, imageScale = 1 } = {}
+) => {
+    state.canvasScaledCtx.fillStyle = `#${color.toString(16).toUpperCase()}`;
+    state.canvasScaledCtx.fillRect(
+        0,
+        0,
+        state.canvasScaled.width,
+        state.canvasScaled.height
+    );
+
+    // in case an image was requested then uses that to load
+    // an image at the center of the screen
+    if (image) {
+        const img = new Image();
+        img.onload = () => {
+            const [imgWidth, imgHeight] = [
+                img.width * imageScale,
+                img.height * imageScale
+            ];
+            const [x0, y0] = [
+                state.canvasScaled.width / 2 - imgWidth / 2,
+                state.canvasScaled.height / 2 - imgHeight / 2
+            ];
+            state.canvasScaledCtx.setTransform(1, 0, 0, 1, 0, 0);
+            try {
+                state.canvasScaledCtx.drawImage(
+                    img,
+                    x0,
+                    y0,
+                    imgWidth,
+                    imgHeight
+                );
+            } finally {
+                state.canvasScaledCtx.scale(
+                    state.canvasScaled.width / state.canvas.width,
+                    state.canvasScaled.height / state.canvas.height
+                );
+            }
+        };
+        img.src = image;
     }
-    state.canvasCtx.putImageData(state.image, 0, 0);
-    state.canvasScaledCtx.drawImage(state.canvas, 0, 0);
 };
 
 const showToast = async (message: string, error = false, timeout = 3500) => {
diff --git a/examples/web/res/storm.png b/examples/web/res/storm.png
new file mode 100644
index 0000000000000000000000000000000000000000..afcff7338dad180df01cfab7bffc39a85ffc50e4
GIT binary patch
literal 1889
zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+Cx8@lv6E*A2M5RPhyD+MT+RZI
z$YP-K>mbbNq%pe!C@5Lt8c`CQpH@<ySd_|8US6)3nU`IhoLG>mmtT}V`<;yx0|TRb
zfKQ0)|NsA8Ts%5ECR9~6<mMJTJG(cPc{Y{0R%R$zS=u@}xHvdCm!~P%+dG+?TiMw<
z+S)o6CCb^@*cT+oSzFmzm|JH=%GldGTUywdn3&tyIojJf#RW>o_(_C#hy}Weg?UM6
zY3leoiDpL0sH<yw+KWW`h?|>R12q~On<*=+I+_bAC@7if@%j4&`TGS+NJwd`@&p8g
z3J3`L`37-w^N0$u0e!^A%EZpb#LvSbBFHKx%q}U)E-5K3Bf%~wD=#n2p`@gus=%eD
zz@??7tFOTebcwk>zlDXhy_uk=ov^2)LV$~CU|?ueWL#{BL0oKdc2+@tUTINbMR|Tu
zRaIk6byIy^TSHZPLw#FAeS1@FZd+?_d$CG;TVH2;S7&=KFnp#rYAo*7UEZ&Iexv!d
z?UuK9TRlH&_x-Zd-y6>VZ@EOtI>!KAX<icK7tFxK!O0~cCaz~-YGvaV5E>qpl2Xv#
z-rKie*|N3k4;?>s{`~o?SFhc;`QYKh=WjoK`uyeRuU~)vzT;9`!@$7m>FMGaQgQ3;
z9p8MPM2X{xZp+X3Yz<l_<+x%M3wLM7`q#=HZ*)}6gqk|aIfdK;H(!{w@8yjR8-Fe@
zt}<F~e0}S@Cp*s<|G!imwpRAW`E_^KG-Ut&#g)x2k<BE)z~sQd!N91%z|z1#6el2{
z*zo22H4Squ(wrHXXWGn*u?S@BE<Ce~IPJ)`e9L86d-Fko@=BL|TP@OzZ8NiVm}l&k
zh>7x8wp!poiA=Gk?aMjg3```t5ZMZluNoL)8W{u}1l`y3rCodb-`M(rsN7l?hOgHW
z)O7yM?_^xR;hiYD9&DDP2GfJ}Gs`Z_(DPh8drkO5uIrCytlgCN!sFK2Gjc2!;yCo?
zX`a0De2Em}5yRQ3cP|9p^1ZFiz=$5o=zI)UEEYJ>oAN8hApTlT@XIH~Yqeq$wfihX
zuU-87@=0>x-mNc6v@@oCt!Te=a&46;(~9GU{8LLyjOW&9y}vH+c%QV01zLV!-pl_I
zg0q<<bQ;ce+#o7Bpg8$}1-rq;H4Vy460=T+YdzRRdXivq;AGt69k-X?Dz7lYD${)Z
z<ErfYlkaCco>yvHI=yVO?Df~852P_e62%!99A%*cx6UV2s@{~Cc>2~Yj%~M2x>zNb
zrixFyoOkV;Lc_Vw2|v9z*(ou8na8I8e3Dzwo6~wa%kP$aQ(&lJCKyLdXvwq3f#I(E
z$+yu5?}{IM{rY6eNA}8}20Ol6R1~b<VBKG~FuIfBSM<sEa~~x9a@;>nM(3YG;hDN$
z;)b)WTXXZ@I^D;TPB1)#o^Supj^#MVm9WHjTXQ8wD#O%`?&4yGzh@6^d#reNW<n5y
zGxr0}MES>x&!;ziM)w<P7Qh}2$<hb5Z*TppWp}i_<k;UY&E`xJXMTAlS|42=@s{m&
zX2&`*QboWCH~pVqlwWWr$Vb;stEm&N5oI9VZ4yoPS;s!#`w(@ri~$HdUHx3vIVCg!
E0K_r{ssI20

literal 0
HcmV?d00001

-- 
GitLab