Spaces:
Sleeping
Sleeping
File size: 8,949 Bytes
a31e333 6cfbb46 a31e333 6cfbb46 a31e333 6cfbb46 a31e333 6cfbb46 a31e333 6cfbb46 a31e333 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>NeuralOS Hypervisor</title>
<style>
/* The ONLY styling in the whole OS: the terminal itself. No UI chrome here. */
html,body{margin:0;padding:0;height:100%;width:100%;background:#000;overflow:hidden}
#fb{display:block;position:fixed;inset:0;width:100vw;height:100vh;
image-rendering:pixelated;image-rendering:crisp-edges;cursor:none;touch-action:none}
</style>
</head>
<body>
<canvas id="fb"></canvas>
<script>
"use strict";
(function(){
var FB = 1024;
var canvas = document.getElementById("fb");
var ctx = canvas.getContext("2d", {alpha:false});
// Framebuffer lives OFF the DOM entirely (OffscreenCanvas, not an element node).
var off, octx;
if (typeof OffscreenCanvas !== "undefined"){
off = new OffscreenCanvas(FB, FB);
octx = off.getContext("2d", {alpha:false});
} else {
off = document.createElement("canvas"); off.width = FB; off.height = FB;
octx = off.getContext("2d", {alpha:false});
}
octx.fillStyle = "#3A6EA5"; octx.fillRect(0,0,FB,FB);
var view = {scale:1, ox:0, oy:0};
function layout(){
var vw = window.innerWidth, vh = window.innerHeight;
var dpr = window.devicePixelRatio || 1;
canvas.width = Math.round(vw*dpr);
canvas.height = Math.round(vh*dpr);
canvas.style.width = vw+"px"; canvas.style.height = vh+"px";
// 100% zoom = one framebuffer pixel per CSS pixel (x dpr for device px).
// Never magnify past 100%; only shrink to fit a viewport smaller than the
// framebuffer. (Previously it always scaled up to fill the window, which
// is why the OS looked "zoomed in" / too big.)
var fit = Math.min(vw/FB, vh/FB);
view.scale = Math.min(fit, 1) * dpr;
view.ox = Math.floor((canvas.width - FB*view.scale)/2);
view.oy = Math.floor((canvas.height - FB*view.scale)/2);
paintAll();
}
// Full repaint of the VISIBLE canvas from the offscreen framebuffer.
function paintAll(){
ctx.imageSmoothingEnabled = false;
ctx.fillStyle = "#000"; ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.drawImage(off, 0,0,FB,FB, view.ox, view.oy, FB*view.scale, FB*view.scale);
}
// Partial repaint: redraw ONLY the changed region. This must not clear the
// whole visible canvas -- doing so blacked out everything outside the patch
// until the next frame happened to touch it ("black tiles until mouseover").
function blit(x,y,w,h){
ctx.imageSmoothingEnabled = false;
var dx = Math.floor(view.ox + x*view.scale);
var dy = Math.floor(view.oy + y*view.scale);
var dx2 = Math.ceil(view.ox + (x+w)*view.scale);
var dy2 = Math.ceil(view.oy + (y+h)*view.scale);
ctx.drawImage(off, x,y,w,h, dx,dy, dx2-dx, dy2-dy);
}
function toFB(clientX, clientY){
return [Math.round((clientX*devicePixelRatio - view.ox)/view.scale),
Math.round((clientY*devicePixelRatio - view.oy)/view.scale)];
}
// ---- binary protocol: [MAGIC][type][u32 hlen][json][payload] ----
var MAGIC = 0x4E;
function decode(buf){
var dv = new DataView(buf);
if (dv.getUint8(0) !== MAGIC) return null;
var type = dv.getUint8(1);
var hlen = dv.getUint32(2);
var header = JSON.parse(new TextDecoder().decode(new Uint8Array(buf,6,hlen)));
var payload = buf.slice(6+hlen);
return {type:type, header:header, payload:payload};
}
var stats = {};
var banner = {text:"connecting...", t:performance.now()};
function applyPatch(p){
var blob = new Blob([p.payload], {type:"image/webp"});
return createImageBitmap(blob).then(function(bmp){
octx.imageSmoothingEnabled = false;
octx.drawImage(bmp, p.header.x, p.header.y);
bmp.close && bmp.close();
blit(p.header.x, p.header.y, p.header.w, p.header.h);
hud();
});
}
function applyFull(p){
var blob = new Blob([p.payload], {type:"image/webp"});
return createImageBitmap(blob).then(function(bmp){
octx.imageSmoothingEnabled = false;
octx.drawImage(bmp, 0, 0);
bmp.close && bmp.close();
paintAll();
hud();
});
}
// HUD is drawn INTO the framebuffer (pixels), not the DOM.
function hud(){
var m = stats;
var line = "v3 ZERO-DOM fb"+FB
+ " | fps~" + (m.fps||0)
+ " | build " + (m.build_ms!=null?m.build_ms:"-") + "ms"
+ " | frame " + (m.frame_ms!=null?m.frame_ms:"-") + "ms"
+ " | tiles " + (m.tiles!=null?m.tiles:"-")
+ " | kb " + (m.bytes!=null?(m.bytes/1024).toFixed(1):"-")
+ " | cache " + (m.cache?(m.cache.hits+"/"+(m.cache.hits+m.cache.misses)):"-")
+ " | wins " + (m.windows!=null?m.windows:"-")
+ " | " + (m.engine?m.engine.engine+"/"+m.engine.device:"-");
octx.fillStyle = "rgba(0,0,0,0.72)";
octx.fillRect(FB-820, FB-2*40-24, 816, 22);
octx.fillStyle = "#0ff";
octx.font = "13px monospace";
octx.fillText(line, FB-812, FB-2*40-8);
if (banner.text){
octx.fillStyle = "rgba(0,0,0,0.75)"; octx.fillRect(8, 8, 640, 24);
octx.fillStyle = "#7fff7f";
octx.fillText(banner.text, 16, 25);
}
var r = 0, w = canvas;
ctx.drawImage(off, FB-820, FB-2*40-24, 816, 22,
view.ox + (FB-820)*view.scale, view.oy + (FB-2*40-24)*view.scale, 816*view.scale, 22*view.scale);
ctx.drawImage(off, 8, 8, 640, 24,
view.ox + 8*view.scale, view.oy + 8*view.scale, 640*view.scale, 24*view.scale);
}
// ---- WebSocket ----
var ws = null, frames = 0, lastT = performance.now();
function connect(){
var proto = location.protocol === "https:" ? "wss" : "ws";
ws = new WebSocket(proto + "://" + location.host + "/kernel");
ws.binaryType = "arraybuffer";
ws.onopen = function(){ banner = {text:"kernel connected", t:performance.now()}; };
ws.onmessage = function(ev){
if (typeof ev.data === "string") return;
var p = decode(ev.data);
if (!p) return;
if (p.type === 2){ banner = {text:p.header.text, t:performance.now()}; return; }
Object.assign(stats, p.header);
if (p.type === 1) applyPatch(p);
else if (p.type === 0) applyFull(p);
frames++;
};
ws.onclose = function(){ banner = {text:"disconnected - retrying", t:performance.now()}; setTimeout(connect, 800); };
ws.onerror = function(){ banner = {text:"socket error", t:performance.now()}; };
}
function send(o){ if (ws && ws.readyState === 1) ws.send(JSON.stringify(o)); }
// ---- input (all handled here; nothing lives in the DOM) ----
var down = null;
canvas.addEventListener("mousedown", function(e){
var p = toFB(e.clientX, e.clientY); down = p;
send({type:"click", x:p[0], y:p[1], button:e.button});
});
canvas.addEventListener("mousemove", function(e){
var p = toFB(e.clientX, e.clientY);
send({type:"move", x:p[0], y:p[1]});
});
canvas.addEventListener("mouseup", function(){
if (down){ send({type:"release"}); down = null; }
});
canvas.addEventListener("dblclick", function(e){
var p = toFB(e.clientX, e.clientY);
send({type:"dblclick", x:p[0], y:p[1]});
});
canvas.addEventListener("contextmenu", function(e){ e.preventDefault(); });
window.addEventListener("keydown", function(e){
if (e.ctrlKey || e.metaKey || e.altKey) return;
if (e.key === "Enter" || e.key === "Backspace" || e.key.length === 1){
send({type:"key", key:e.key});
if (e.key === "Backspace" || e.key.length === 1) e.preventDefault();
}
});
window.addEventListener("resize", layout);
// ---- Text2IMG / Text2OS / LASM API from the console or other agents ----
window.NeuralOS = {
fb: FB,
send: send,
text2os: function(text){ var i=0; for(;i<text.length;i++) send({type:"key", key:text[i]}); send({type:"key", key:"Enter"}); },
wallpaper: function(prompt){ send({type:"wallpaper", prompt:prompt}); },
lasm: function(program){ send({type:"lasm", program:program}); },
stats: function(){ return stats; },
// debug/verification hook: returns the exact framebuffer as a data URL.
// Uses convertToBlob so no DOM node is ever created.
dump: function(){
if (off.convertToBlob){
return off.convertToBlob({type:"image/png"}).then(function(b){
return new Promise(function(res){
var fr = new FileReader();
fr.onload = function(){ res(fr.result); };
fr.readAsDataURL(b);
});
});
}
return Promise.resolve(null);
}
};
setInterval(function(){
var now = performance.now();
stats.fps = Math.round(frames*1000/(now-lastT)); frames = 0; lastT = now;
hud();
}, 1000);
// Size the backing store to the viewport BEFORE anything else. Without this
// the canvas keeps its 300x150 default and the browser stretches it to the
// window -- a massively zoomed-in, blocky desktop.
layout();
connect();
})();
</script>
</body>
</html>
|