From 8f8779fee144dfdf10b57530166376ce38aad20d Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 26 Oct 2025 17:02:43 +0200 Subject: [PATCH 01/10] DOS font --- Dockerfile | 1 + README.md | 1 + scripts/dos-httpd | 26 ++++++++++++++++++++++++-- scripts/start-services.sh | 3 +++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0da7b46..75f6262 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,7 @@ COPY scripts/dos-shell /usr/local/bin/dos-shell COPY scripts/dos-httpd /usr/local/bin/dos-httpd COPY scripts/prepare-svardos.sh /usr/local/bin/prepare-svardos COPY scripts/start-services.sh /usr/local/bin/start-dos-services +COPY WebPlus_IBM_VGA_8x16.woff /usr/local/share/dos-httpd/WebPlus_IBM_VGA_8x16.woff RUN chmod +x /usr/local/bin/dos-shell /usr/local/bin/dos-httpd /usr/local/bin/start-dos-services /usr/local/bin/prepare-svardos && echo "/usr/local/bin/dos-shell" >> /etc/shells # Create sshd runtime directory diff --git a/README.md b/README.md index 0d90568..197d3b6 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ You can override which binary is used for the Linux side by setting `DOS_LINUX_S | `DOS_SSH_PORT` | `2222` | Host port forwarded to container port 22. | | `DOS_TELNET_PORT` | `2323` | Host port forwarded to container port 23. | | `DOS_HTTP_PORT` | `8080` | Host port forwarded to the web console. | +| `DOS_HTTP_FONT_PATH` | `/usr/local/share/dos-httpd/WebPlus_IBM_VGA_8x16.woff` | Override the font served to the web console. | | `ENABLE_TELNET` | `1` | Toggle BusyBox telnetd. | | `ENABLE_HTTP_CONSOLE` | `1` | Launch the built-in web terminal. | | `TELNET_PORT` | `23` | Port inside the container where telnetd listens. | diff --git a/scripts/dos-httpd b/scripts/dos-httpd index b4c3c8c..424c8ed 100644 --- a/scripts/dos-httpd +++ b/scripts/dos-httpd @@ -36,12 +36,17 @@ HTML_PAGE = """
SvarBox DOS Console
-
+
+
+
From 507becd4909e555e46978f7247eff0be3451f292 Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 26 Oct 2025 20:50:39 +0200 Subject: [PATCH 06/10] crt stretch --- scripts/dos-httpd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/dos-httpd b/scripts/dos-httpd index e192c27..34479e1 100644 --- a/scripts/dos-httpd +++ b/scripts/dos-httpd @@ -70,6 +70,8 @@ HTML_PAGE = """ border: 1px solid #2b2b2b; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45); padding: 12px; + transform-origin: top center; + transform: scaleY(1.2); box-sizing: content-box; } #terminal .xterm { @@ -163,7 +165,6 @@ HTML_PAGE = """ await waitForDosvgaFont(); const term = new Terminal({ - rendererType: "canvas", cursorBlink: true, convertEol: true, fontFamily: "DOSVGA, Fira Code, Cascadia Mono, Hack, monospace", From dee37378584f51fc7fd3e0d655378bc56425d552 Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 26 Oct 2025 21:03:48 +0200 Subject: [PATCH 07/10] color fix --- scripts/dos-httpd | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/scripts/dos-httpd b/scripts/dos-httpd index 34479e1..4ea79f1 100644 --- a/scripts/dos-httpd +++ b/scripts/dos-httpd @@ -66,12 +66,12 @@ HTML_PAGE = """ } #terminal { display: inline-flex; - background: #000; + background: rgb(12 12 12); border: 1px solid #2b2b2b; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45); padding: 12px; - transform-origin: top center; - transform: scaleY(1.2); + transform-origin: center center; + position: relative; box-sizing: content-box; } #terminal .xterm { @@ -90,6 +90,9 @@ HTML_PAGE = """ height: 400px !important; padding: 0 !important; } + .xterm-dom-renderer-owner-1 .xterm-bg-0 { + background-color: rgb(14 14 14) !important; + } @@ -107,6 +110,7 @@ HTML_PAGE = """ const CHAR_HEIGHT = 16; const VIEWPORT_WIDTH = 640; const VIEWPORT_HEIGHT = 400; + const BASE_VERTICAL_STRETCH = 1.2; const TARGET_ROW_HEIGHT = VIEWPORT_HEIGHT / ROWS; const terminalHost = document.getElementById("terminal"); @@ -162,6 +166,22 @@ HTML_PAGE = """ } } + function updateScale() { + const maxWidth = window.innerWidth * 0.85; + const maxHeight = window.innerHeight * 0.85; + + // reset transform to measure base stretched size + terminalHost.style.transform = `scaleY(${BASE_VERTICAL_STRETCH})`; + terminalHost.style.transformOrigin = "center center"; + + const rect = terminalHost.getBoundingClientRect(); + const scaleForWidth = maxWidth / rect.width; + const scaleForHeight = maxHeight / rect.height; + const uniformScale = Math.min(scaleForWidth, scaleForHeight); + + terminalHost.style.transform = `scale(${uniformScale}) scaleY(${BASE_VERTICAL_STRETCH})`; + } + await waitForDosvgaFont(); const term = new Terminal({ @@ -181,6 +201,7 @@ HTML_PAGE = """ term.open(terminalHost); term.resize(COLS, ROWS); applyViewportClamp(); + updateScale(); const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws"; const socket = new WebSocket(`${wsProtocol}://${window.location.host}/ws`); @@ -199,6 +220,7 @@ HTML_PAGE = """ socket.send(JSON.stringify({ type: "resize", cols: term.cols, rows: term.rows })); term.focus(); applyViewportClamp(); + updateScale(); }); socket.addEventListener("message", (event) => { @@ -230,13 +252,18 @@ HTML_PAGE = """ term.onResize(({ cols, rows }) => { socket.send(JSON.stringify({ type: "resize", cols, rows })); applyViewportClamp(); + updateScale(); }); term.onRender(() => { applyViewportClamp(); + updateScale(); }); - window.addEventListener("resize", () => applyViewportClamp(), { passive: true }); + window.addEventListener("resize", () => { + applyViewportClamp(); + updateScale(); + }, { passive: true }); })(); From 091f4d53e9ebdacf023bdc75c1fb0433c1c62dfe Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 26 Oct 2025 21:51:57 +0200 Subject: [PATCH 08/10] CRT --- scripts/dos-httpd | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/scripts/dos-httpd b/scripts/dos-httpd index 4ea79f1..d3f70cd 100644 --- a/scripts/dos-httpd +++ b/scripts/dos-httpd @@ -73,6 +73,55 @@ HTML_PAGE = """ transform-origin: center center; position: relative; box-sizing: content-box; + overflow: hidden; + } + .crt-display { + filter: saturate(1.1) contrast(1.12) brightness(0.85); + --crt-line-step: 1; + } + .crt-display::before { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + background-image: + repeating-linear-gradient( + to bottom, + rgba(255, 255, 255, 0.1) 0px, + rgba(255, 255, 255, 0.1) calc(var(--crt-line-step) * 1px), + rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 1px), + rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 2px) + ), + repeating-linear-gradient( + to right, + rgba(255, 255, 255, 0.04) 0px, + rgba(255, 255, 255, 0.04) calc(var(--crt-line-step) * 1px), + rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 1px), + rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 2px) + ); + mix-blend-mode: screen; + opacity: 0.4; + animation: crt-scan 6s linear infinite; + } + .crt-display::after { + content: ""; + position: absolute; + inset: -8%; + pointer-events: none; + background: radial-gradient(circle at center, rgba(255, 255, 255, 0.08) 0%, rgba(0, 0, 0, 0.45) 70%, rgba(0, 0, 0, 0.75) 100%); + mix-blend-mode: multiply; + animation: crt-flicker 3s infinite; + } + @keyframes crt-scan { + 0% { transform: translateY(-2%); } + 100% { transform: translateY(2%); } + } + @keyframes crt-flicker { + 0%, 100% { opacity: 0.35; } + 45% { opacity: 0.45; } + 50% { opacity: 0.3; } + 55% { opacity: 0.4; } + 90% { opacity: 0.33; } } #terminal .xterm { width: 100% !important; @@ -151,6 +200,7 @@ HTML_PAGE = """ if (screen) { screen.style.width = `${VIEWPORT_WIDTH}px`; screen.style.height = `${VIEWPORT_HEIGHT}px`; + screen.classList.add("crt-display"); } const rows = terminalHost.querySelector(".xterm-rows"); @@ -179,6 +229,7 @@ HTML_PAGE = """ const scaleForHeight = maxHeight / rect.height; const uniformScale = Math.min(scaleForWidth, scaleForHeight); + terminalHost.style.setProperty('--crt-line-step', (1 / uniformScale).toString()); terminalHost.style.transform = `scale(${uniformScale}) scaleY(${BASE_VERTICAL_STRETCH})`; } From 11cceb4c30d4e16c490ca84dae7527aba29e5522 Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 26 Oct 2025 22:21:50 +0200 Subject: [PATCH 09/10] web feature --- README.md | 2 +- scripts/dos-httpd | 62 +++++++++++++++++++++++++++------------ scripts/start-services.sh | 11 +++++-- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 197d3b6..220bace 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ You can override which binary is used for the Linux side by setting `DOS_LINUX_S | `DOS_SSH_PORT` | `2222` | Host port forwarded to container port 22. | | `DOS_TELNET_PORT` | `2323` | Host port forwarded to container port 23. | | `DOS_HTTP_PORT` | `8080` | Host port forwarded to the web console. | -| `DOS_HTTP_FONT_PATH` | `/usr/local/share/dos-httpd/WebPlus_IBM_VGA_8x16.woff` | Override the font served to the web console. | +| `DOS_HTTP_CRT` | `1` | Toggle the CRT styling applied to the web console (`0` to disable). | | `ENABLE_TELNET` | `1` | Toggle BusyBox telnetd. | | `ENABLE_HTTP_CONSOLE` | `1` | Launch the built-in web terminal. | | `TELNET_PORT` | `23` | Port inside the container where telnetd listens. | diff --git a/scripts/dos-httpd b/scripts/dos-httpd index d3f70cd..fc884d1 100644 --- a/scripts/dos-httpd +++ b/scripts/dos-httpd @@ -28,6 +28,18 @@ from aiohttp import web, WSMsgType LOG = logging.getLogger("dos_httpd") + +def _env_bool(name: str, default: bool) -> bool: + value = os.environ.get(name) + if value is None: + return default + value = value.strip().lower() + if value in {"1", "true", "yes", "on"}: + return True + if value in {"0", "false", "no", "off"}: + return False + return default + HTML_PAGE = """ @@ -76,7 +88,7 @@ HTML_PAGE = """ overflow: hidden; } .crt-display { - filter: saturate(1.1) contrast(1.12) brightness(0.85); + filter: saturate(1.05) contrast(1.08) brightness(0.95); --crt-line-step: 1; } .crt-display::before { @@ -87,15 +99,15 @@ HTML_PAGE = """ background-image: repeating-linear-gradient( to bottom, - rgba(255, 255, 255, 0.1) 0px, - rgba(255, 255, 255, 0.1) calc(var(--crt-line-step) * 1px), + rgba(255, 255, 255, 0.06) 0px, + rgba(255, 255, 255, 0.06) calc(var(--crt-line-step) * 1px), rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 1px), rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 2px) ), repeating-linear-gradient( to right, - rgba(255, 255, 255, 0.04) 0px, - rgba(255, 255, 255, 0.04) calc(var(--crt-line-step) * 1px), + rgba(255, 255, 255, 0.025) 0px, + rgba(255, 255, 255, 0.025) calc(var(--crt-line-step) * 1px), rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 1px), rgba(0, 0, 0, 0) calc(var(--crt-line-step) * 2px) ); @@ -152,6 +164,7 @@ HTML_PAGE = """