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.
This commit is contained in:
2026-10-13 11:10:34 -07:00
parent b996609832
commit a7659d7fb8
3 changed files with 4 additions and 11 deletions
+1 -1
View File
@@ -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
+2 -9
View File
@@ -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);
+1 -1
View File
@@ -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 },