From a7659d7fb8321cce108df97f8ecdfd3ac877cbcb Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Sun, 11 Oct 2026 19:35:44 -0700 Subject: [PATCH] Size Flash streams to the exact SWF stage Scaling the display up relied on full screen scaling the movie, but games that set StageScaleMode.NO_SCALE stay at their native size in full screen, leaving a small game against black. At the exact stage size, full screen fits every scale mode and the browser scales the stream. --- streaming/README.md | 2 +- streaming/session-manager/src/games.ts | 11 ++--------- streaming/session-manager/test/games.test.ts | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/streaming/README.md b/streaming/README.md index 3f9d64d..095e57e 100644 --- a/streaming/README.md +++ b/streaming/README.md @@ -53,7 +53,7 @@ in secure contexts. A game is streamable when its platform is in `STREAM_PLATFORMS` (default `Java,Shockwave,Flash`) and the streamer can resolve its launcher. The display is sized from the content it launches: a Director movie's or projector's stage, -a SWF's stage scaled up to fit 1280x960, a page's applet or largest embed, with +a SWF's stage, a page's applet or largest embed, with fallbacks of 800x600, or 1024x768 for pages. Saves are `{relative path: base64 contents}` for the files under the diff --git a/streaming/session-manager/src/games.ts b/streaming/session-manager/src/games.ts index 90e1954..9ffef99 100644 --- a/streaming/session-manager/src/games.ts +++ b/streaming/session-manager/src/games.ts @@ -11,9 +11,6 @@ const JAVA_APPS = new Set(['fpsoftware\\startjava.bat', 'fpsoftware\\startjavain const DEFAULT_SIZE: Size = { width: 800, height: 600 }; const BROWSER_SIZE: Size = { width: 1024, height: 768 }; -/** Flash is vector art, so it renders sharper at a larger display than its stage. */ -const FLASH_MAX: Size = { width: 1280, height: 960 }; - /** A page's default body margin around embedded content. */ const PAGE_MARGIN = 8; @@ -79,7 +76,8 @@ export class GameCatalog { return even((content && directorStageSize(content)) ?? DEFAULT_SIZE); } if (extension === '.swf') { - return even(scaleToFit((content && swfStageSize(content)) ?? DEFAULT_SIZE, FLASH_MAX)); + // The exact stage: in full screen, games that set noScale keep their native size + return even((content && swfStageSize(content)) ?? DEFAULT_SIZE); } const embed = content && embedSize(content.toString('latin1')); return even(embed ? { width: embed.width + 2 * PAGE_MARGIN, height: embed.height + 2 * PAGE_MARGIN } : BROWSER_SIZE); @@ -158,11 +156,6 @@ function even({ width, height }: Size): Size { return { width: width + (width % 2), height: height + (height % 2) }; } -function scaleToFit(size: Size, max: Size): Size { - const scale = Math.min(max.width / size.width, max.height / size.height); - return scale > 1 ? { width: Math.round(size.width * scale), height: Math.round(size.height * scale) } : size; -} - /** Reads the stage size from a SWF header: a rect of twips after the 8-byte header. */ export function swfStageSize(swf: Buffer): Size | null { const signature = swf.toString('latin1', 0, 3); diff --git a/streaming/session-manager/test/games.test.ts b/streaming/session-manager/test/games.test.ts index 7a59a4f..5df2584 100644 --- a/streaming/session-manager/test/games.test.ts +++ b/streaming/session-manager/test/games.test.ts @@ -181,7 +181,7 @@ test('GameCatalog streams allowed platforms whose launcher resolves, sized from oldcpu: { width: 500, height: 426 }, secure: { width: 640, height: 480 }, navigator: { width: 528, height: 400 }, - flash: { width: 1280, height: 960 }, + flash: { width: 500, height: 376 }, unity: null, 'no-program': null, exe: { width: 800, height: 600 },