@lewismoten/gamemaker-sandbox-engine 0.0.0-stage → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +24 -0
- package/NOTICE.md +58 -0
- package/README.md +149 -2
- package/dist/assets/music.worklet-aD2x7RRM.js +466 -0
- package/dist/audio/cmfLoad.js +10 -0
- package/dist/audio/cmfPlayer.js +201 -0
- package/dist/audio/context.js +75 -0
- package/dist/audio/engine.js +173 -0
- package/dist/audio/mix.js +40 -0
- package/dist/audio/opl.js +245 -0
- package/dist/audio/output.js +40 -0
- package/dist/core/gameFiles.js +89 -0
- package/dist/engine/character.js +187 -0
- package/dist/engine/funcKeys.js +164 -0
- package/dist/engine/game.js +133 -0
- package/dist/engine/keys.js +68 -0
- package/dist/engine/machine.js +192 -0
- package/dist/engine/menus.js +135 -0
- package/dist/engine/monsters.js +259 -0
- package/dist/engine/playGain.js +10 -0
- package/dist/engine/playerLook.js +48 -0
- package/dist/engine/recorder.js +127 -0
- package/dist/engine/render.js +45 -0
- package/dist/engine/scene.js +324 -0
- package/dist/engine/scroll.js +79 -0
- package/dist/engine/showGraphic.js +107 -0
- package/dist/engine/slowPc.js +98 -0
- package/dist/engine/slowPcMusic.js +46 -0
- package/dist/engine/touch.js +61 -0
- package/dist/engine/world.js +205 -0
- package/dist/formats/binary.js +120 -0
- package/dist/formats/blocks.js +103 -0
- package/dist/formats/character.js +83 -0
- package/dist/formats/cmf.js +37 -0
- package/dist/formats/cmfEdit.js +154 -0
- package/dist/formats/cmfPreview.js +89 -0
- package/dist/formats/cmfSong.js +190 -0
- package/dist/formats/fli.js +340 -0
- package/dist/formats/fliFrames.js +34 -0
- package/dist/formats/fliLimits.js +54 -0
- package/dist/formats/game.js +198 -0
- package/dist/formats/gif.js +125 -0
- package/dist/formats/gifProgressive.js +99 -0
- package/dist/formats/graphicScripts.js +44 -0
- package/dist/formats/highscore.js +30 -0
- package/dist/formats/jpeg.js +359 -0
- package/dist/formats/map.js +38 -0
- package/dist/formats/monster.js +69 -0
- package/dist/formats/palette.js +58 -0
- package/dist/formats/recording.js +17 -0
- package/dist/formats/sound.js +44 -0
- package/dist/formats/voc.js +303 -0
- package/dist/gfx/colorVision.js +45 -0
- package/dist/gfx/cp437Glyphs.js +337 -0
- package/dist/gfx/font8x8.js +10 -0
- package/dist/gfx/screen.js +151 -0
- package/dist/index.js +15 -0
- package/dist/input/chords.js +46 -0
- package/dist/input/deskMouse.js +24 -0
- package/dist/input/keyboard.js +82 -0
- package/dist/input/scancodes.js +143 -0
- package/dist/player/fileExtensions.js +118 -0
- package/dist/player/patchRules.js +129 -0
- package/dist/player/patchTable.js +1753 -0
- package/dist/text/cp437.js +44 -0
- package/dist/types/audio/cmfLoad.d.ts +7 -0
- package/dist/types/audio/cmfPlayer.d.ts +69 -0
- package/dist/types/audio/context.d.ts +12 -0
- package/dist/types/audio/engine.d.ts +60 -0
- package/dist/types/audio/mix.d.ts +14 -0
- package/dist/types/audio/music.worklet.d.ts +22 -0
- package/dist/types/audio/opl.d.ts +37 -0
- package/dist/types/audio/output.d.ts +13 -0
- package/dist/types/core/gameFiles.d.ts +49 -0
- package/dist/types/engine/character.d.ts +30 -0
- package/dist/types/engine/funcKeys.d.ts +35 -0
- package/dist/types/engine/game.d.ts +57 -0
- package/dist/types/engine/keys.d.ts +17 -0
- package/dist/types/engine/machine.d.ts +103 -0
- package/dist/types/engine/menus.d.ts +46 -0
- package/dist/types/engine/monsters.d.ts +19 -0
- package/dist/types/engine/playGain.d.ts +11 -0
- package/dist/types/engine/playerLook.d.ts +44 -0
- package/dist/types/engine/recorder.d.ts +67 -0
- package/dist/types/engine/render.d.ts +8 -0
- package/dist/types/engine/scene.d.ts +188 -0
- package/dist/types/engine/scroll.d.ts +24 -0
- package/dist/types/engine/showGraphic.d.ts +39 -0
- package/dist/types/engine/slowPc.d.ts +124 -0
- package/dist/types/engine/slowPcMusic.d.ts +18 -0
- package/dist/types/engine/touch.d.ts +33 -0
- package/dist/types/engine/world.d.ts +237 -0
- package/dist/types/formats/binary.d.ts +44 -0
- package/dist/types/formats/blocks.d.ts +52 -0
- package/dist/types/formats/character.d.ts +65 -0
- package/dist/types/formats/cmf.d.ts +33 -0
- package/dist/types/formats/cmfEdit.d.ts +53 -0
- package/dist/types/formats/cmfPreview.d.ts +19 -0
- package/dist/types/formats/cmfSong.d.ts +74 -0
- package/dist/types/formats/fli.d.ts +56 -0
- package/dist/types/formats/fliFrames.d.ts +18 -0
- package/dist/types/formats/fliLimits.d.ts +13 -0
- package/dist/types/formats/game.d.ts +79 -0
- package/dist/types/formats/gif.d.ts +15 -0
- package/dist/types/formats/gifProgressive.d.ts +46 -0
- package/dist/types/formats/graphicScripts.d.ts +18 -0
- package/dist/types/formats/highscore.d.ts +10 -0
- package/dist/types/formats/jpeg.d.ts +20 -0
- package/dist/types/formats/map.d.ts +24 -0
- package/dist/types/formats/monster.d.ts +48 -0
- package/dist/types/formats/palette.d.ts +15 -0
- package/dist/types/formats/recording.d.ts +7 -0
- package/dist/types/formats/sound.d.ts +13 -0
- package/dist/types/formats/voc.d.ts +13 -0
- package/dist/types/gfx/colorVision.d.ts +26 -0
- package/dist/types/gfx/cp437Glyphs.d.ts +2 -0
- package/dist/types/gfx/font8x8.d.ts +2 -0
- package/dist/types/gfx/screen.d.ts +50 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/input/chords.d.ts +22 -0
- package/dist/types/input/deskMouse.d.ts +14 -0
- package/dist/types/input/keyboard.d.ts +39 -0
- package/dist/types/input/scancodes.d.ts +3 -0
- package/dist/types/player/fileExtensions.d.ts +44 -0
- package/dist/types/player/patchRules.d.ts +24 -0
- package/dist/types/player/patchTable.d.ts +83 -0
- package/dist/types/text/cp437.d.ts +6 -0
- package/package.json +339 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Changes to `@lewismoten/gamemaker-sandbox-engine`, released as `engine-v*` tags. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [3.3.0] - 2026-11-07
|
|
9
|
+
|
|
10
|
+
Slow-PC presets that play a game at the pace of a 486, 386, 286 or IBM PS/1, experimental gameplay patches, live
|
|
11
|
+
control of the sound mix and sound card, and a hook for life losses. Fixes cover scroll speed, JPEG and FLI decoding,
|
|
12
|
+
short CMF files, and a recorded Enter on key screens.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Slow-PC presets (`SPEED_PRESETS`: 486, 386, 286 and the IBM PS/1) with voice-read stalls, disk-read costs and music holds. They are estimates, and the default speed charges nothing.
|
|
17
|
+
- Experimental gameplay patches (`player/patchTable` group `play`, `World.tune`). With no patches, play is unchanged.
|
|
18
|
+
- Player life-loss events, so a caller can watch for them without counting recorded playback.
|
|
19
|
+
- Color-vision simulation (`gfx/colorVision`) and sparse FLI palette changes.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- The sound mix (music, voice, effects: on and volume) is followed live, and sound-card output changes without restarting audio or play.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Scroll speed wraps like DOS's 16-bit integers. Damaged FLI and CMF files give a clear error, and progressive JPEGs decode only complete data.
|
|
28
|
+
|
|
29
|
+
Full list: [changes/release/engine/3.3.0.md](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/engine-v3.3.0/changes/release/engine/3.3.0.md)
|
|
30
|
+
|
|
31
|
+
## [3.1.0] - 2026-10-29
|
|
32
|
+
|
|
33
|
+
The first release of the browser engine as an npm package: the TypeScript port of PLAYGAME with readers and writers
|
|
34
|
+
for every Game-Maker file format, OPL2 and CMF audio, screen, input and fonts.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- The engine, scoped as `@lewismoten/gamemaker-sandbox-engine` and published to GitHub Packages from version tags.
|
|
39
|
+
|
|
40
|
+
[Unreleased]: https://github.com/lewismoten/GameMaker-SandboxEdition/compare/engine-v3.3.0...HEAD
|
|
41
|
+
[3.3.0]: https://github.com/lewismoten/GameMaker-SandboxEdition/compare/engine-v3.1.0...engine-v3.3.0
|
|
42
|
+
[3.1.0]: https://github.com/lewismoten/GameMaker-SandboxEdition/releases/tag/engine-v3.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014 gandrewstone
|
|
4
|
+
Copyright (c) 2026 Lewis Moten (modifications: the web port, the 1994 desk, the
|
|
5
|
+
Sandbox Software and Bard of Bizarre games, and the Mac, Windows and Linux players;
|
|
6
|
+
see NOTICE.md)
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
package/NOTICE.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Notices for @lewismoten/gamemaker-sandbox-engine
|
|
2
|
+
|
|
3
|
+
This package contains the browser game engine and audio worklet from
|
|
4
|
+
[Game-Maker: Sandbox Edition](https://github.com/lewismoten/GameMaker-SandboxEdition).
|
|
5
|
+
It is licensed under the MIT License; see [LICENSE](LICENSE). It contains no games,
|
|
6
|
+
site editor, DOS executables, or native player shells.
|
|
7
|
+
|
|
8
|
+
## Source and contributors
|
|
9
|
+
|
|
10
|
+
- **RSD Game-Maker** was created by G. Andrew (Andy) Stone, G. Oliver Stone,
|
|
11
|
+
Oliver Stone Jr., and Joan Stone for Recreational Software Designs. Andy Stone
|
|
12
|
+
released its source under the MIT License in 2014. The browser engine follows
|
|
13
|
+
that source and its game file formats, including the behavior of its CMF music
|
|
14
|
+
player. The original project is at
|
|
15
|
+
[gandrewstone/GameMaker](https://github.com/gandrewstone/GameMaker).
|
|
16
|
+
- **Game-Maker: Sandbox Edition** is Lewis Moten's fork. Its TypeScript web port
|
|
17
|
+
was written with Claude Opus 5.5 (Anthropic), directed and reviewed by Lewis.
|
|
18
|
+
This npm package was extracted and documented with OpenAI Codex (GPT-6) in
|
|
19
|
+
Visual Studio Code, directed by Lewis.
|
|
20
|
+
|
|
21
|
+
## Data, formats, and hardware
|
|
22
|
+
|
|
23
|
+
- **8×8 text font:** `font8x8_basic`, `font8x8_ext_latin`, `font8x8_misc`, and
|
|
24
|
+
`font8x8_greek` by Daniel Hepper are public domain. They supply the ASCII and
|
|
25
|
+
selected code page 437 glyphs in `src/gfx/font8x8.ts` and `src/gfx/cp437Glyphs.ts`.
|
|
26
|
+
The upstream headers also credit Marcel Sondaar and International Business Machines
|
|
27
|
+
(public domain VGA fonts) as their basis. [Source](https://github.com/dhepper/font8x8).
|
|
28
|
+
The remaining CP437 symbols and box-drawing glyphs were drawn for this project with
|
|
29
|
+
Anthropic Claude Opus 5.5 under Lewis Moten's direction and are distributed under the
|
|
30
|
+
project's MIT License; they were not copied from IBM's ROM.
|
|
31
|
+
- **GIF:** Graphics Interchange Format is a format and trademark of CompuServe
|
|
32
|
+
Incorporated. The engine implements GIF decoding from the format description.
|
|
33
|
+
- **FLI:** Autodesk Animator's animation format, implemented from its public
|
|
34
|
+
documentation. Autodesk Animator is a product of Autodesk, Inc.
|
|
35
|
+
- **Sound Blaster formats:** CMF, VOC, and SBI are Creative Technology Ltd.
|
|
36
|
+
formats. The CMF player follows RSD Game-Maker's `SBMUSIC.C` and the behavior
|
|
37
|
+
of Creative's SBFMDRV driver. The VOC decoder's Creative ADPCM tables refer
|
|
38
|
+
to the Sound Blaster DSP behavior documented in
|
|
39
|
+
[DOSBox's `sblaster.cpp`](https://github.com/joncampbell123/dosbox-x/blob/master/src/hardware/sblaster.cpp)
|
|
40
|
+
(GPL-2.0-or-later).
|
|
41
|
+
- **OPL2 / YM3812:** Yamaha Corporation's FM synthesis chip. The engine's
|
|
42
|
+
emulation was written for this project from the chip's published register
|
|
43
|
+
documentation.
|
|
44
|
+
|
|
45
|
+
The package does not bundle DOSBox, Creative software, or Autodesk software.
|
|
46
|
+
|
|
47
|
+
## Incremental JPEG decoding
|
|
48
|
+
|
|
49
|
+
The JPEG decoder follows ITU-T Recommendation T.81 (1992), by CCITT/ITU and the
|
|
50
|
+
Joint Photographic Experts Group: [specification](https://www.w3.org/Graphics/JPEG/itu-t81.pdf).
|
|
51
|
+
This is a format reference; the recommendation's text and diagrams are not bundled.
|
|
52
|
+
The existing AC-refinement procedure identifies libjpeg's `decode_mcu_AC_refine` as its
|
|
53
|
+
algorithm reference (Independent JPEG Group, Thomas G. Lane and contributors;
|
|
54
|
+
[IJG License](https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/README.ijg)).
|
|
55
|
+
This software is based in part on the work of the Independent JPEG Group.
|
|
56
|
+
No libjpeg C source or binaries are bundled. Incremental block visibility and atomic
|
|
57
|
+
MCU updates were corrected with OpenAI Codex (GPT-6), directed by Lewis Moten, under
|
|
58
|
+
this project's MIT License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,150 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Game-Maker: Sandbox Edition browser engine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@lewismoten/gamemaker-sandbox-engine` runs RSD Game-Maker games from their original DOS files in a browser. It is the same TypeScript engine used by the Game-Maker: Sandbox Edition web player. The package includes its audio worklet and TypeScript declarations; it does not include games or the site's editor and catalog.
|
|
4
|
+
|
|
5
|
+
Install from your configured npm registry:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @lewismoten/gamemaker-sandbox-engine
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If your registry requires authentication or a scope mapping, configure npm using that registry's instructions.
|
|
12
|
+
|
|
13
|
+
Pass the files from one game's DOS directory to `GameFiles`. Names are case insensitive and use DOS 8.3 names. `GameFiles.mainGame()` finds a `.GAM` file. Keep the original file names and bytes; the game refers to its other files by name.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { GameFiles, Machine, runGame } from '@lewismoten/gamemaker-sandbox-engine';
|
|
17
|
+
|
|
18
|
+
const input = document.querySelector<HTMLInputElement>('#files')!;
|
|
19
|
+
const canvas = document.querySelector<HTMLCanvasElement>('#screen')!;
|
|
20
|
+
const play = document.querySelector<HTMLButtonElement>('#play')!;
|
|
21
|
+
let files: GameFiles | undefined;
|
|
22
|
+
|
|
23
|
+
input.addEventListener('change', async () => {
|
|
24
|
+
const entries = await Promise.all(
|
|
25
|
+
Array.from(input.files ?? [], async (file): Promise<[string, Uint8Array]> => [
|
|
26
|
+
file.name,
|
|
27
|
+
new Uint8Array(await file.arrayBuffer()),
|
|
28
|
+
]),
|
|
29
|
+
);
|
|
30
|
+
files = new GameFiles(entries);
|
|
31
|
+
play.disabled = !files.mainGame();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
play.addEventListener('click', async () => {
|
|
35
|
+
if (!files) return;
|
|
36
|
+
const gam = files.mainGame();
|
|
37
|
+
if (!gam) throw new Error('Choose a game directory containing a .GAM file');
|
|
38
|
+
|
|
39
|
+
const machine = new Machine(canvas, files);
|
|
40
|
+
try {
|
|
41
|
+
await machine.audio.resume(); // the click is a user gesture
|
|
42
|
+
await runGame(machine, gam);
|
|
43
|
+
} finally {
|
|
44
|
+
machine.destroy();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<input id="files" type="file" webkitdirectory multiple aria-label="Game directory" />
|
|
51
|
+
<button id="play" disabled>Play</button>
|
|
52
|
+
<canvas id="screen" tabindex="0" aria-label="Game screen"></canvas>
|
|
53
|
+
<style>
|
|
54
|
+
#screen { width: min(100%, 960px); aspect-ratio: 8 / 5; image-rendering: pixelated; }
|
|
55
|
+
</style>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`Machine` owns the screen, keyboard and audio. Call `machine.destroy()` when play finishes or the containing page closes. `runGame` accepts `RunOptions` for callbacks, joystick input, playback and the optional DOS player appearance. The game may write saves or high scores into `GameFiles`; use `files.onChange` to persist those bytes. The package targets modern browsers and ES modules.
|
|
59
|
+
|
|
60
|
+
`machine.screen.dosCropped` is observer metadata for PLAYGAME’s CropScreen state: true during level rendering and its fades, false for function-key screens and after a level. `sceneNumber` identifies the last rendered level. These fields do not change rendering or game timing.
|
|
61
|
+
|
|
62
|
+
## Read a game file in Node.js
|
|
63
|
+
|
|
64
|
+
The format modules need no browser. This reads a `.GAM` file from the original CD (run it from the repository root) and lists its scene titles:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { readFileSync } from 'node:fs';
|
|
68
|
+
import { parseGame } from '@lewismoten/gamemaker-sandbox-engine/formats/game';
|
|
69
|
+
import { fromCp437 } from '@lewismoten/gamemaker-sandbox-engine/text/cp437';
|
|
70
|
+
|
|
71
|
+
const game = parseGame(readFileSync('cd/gameware/peach/peach.gam'));
|
|
72
|
+
console.log(`${game.scenes.length} scenes: ${game.scenes.slice(2, 4).map((s) => fromCp437(s.desc)).join(' and ')}`);
|
|
73
|
+
// prints: 20 scenes: Grasslands 1 and Grasslands 2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
A test (`web/test/readmeExamples.test.ts`) runs this block in Node against the built package and compares what it prints with the `// prints:` line.
|
|
77
|
+
|
|
78
|
+
Parsed descriptions are DOS byte strings, not Unicode. For a game name outside DOS use
|
|
79
|
+
`gameTitle(game)` from `formats/game`: it decodes CP437 and trims decorative menu frames.
|
|
80
|
+
For other DOS labels use `fromCp437`; for DOS text-file bytes use `cp437Text` from `text/cp437`,
|
|
81
|
+
which retains ASCII controls so the caller can handle line endings and DOS EOF. Neither API
|
|
82
|
+
is for already decoded Unicode, JSON, HTML or UTF-8 text. Keep the parsed fields and original
|
|
83
|
+
bytes for DOS rendering and round trips; convert only at the presentation boundary.
|
|
84
|
+
|
|
85
|
+
## Native player screens
|
|
86
|
+
|
|
87
|
+
The package includes the complete DOS player front end. The example above shows
|
|
88
|
+
its title images or animation and menu before play. The menu offers instructions,
|
|
89
|
+
storyline, credits, top scores and quitting; during play the native function keys
|
|
90
|
+
open help, inventory, load and save screens. Include the files named by the game's
|
|
91
|
+
`.GAM` file, along with any saved games or high scores you want to keep.
|
|
92
|
+
|
|
93
|
+
`runGame` uses these screens by default. For a direct play test, pass
|
|
94
|
+
`{ skipTitle: true }` to start a new game at its initial scene link; its normal
|
|
95
|
+
ending screens and menu still follow when play ends. `RunOptions.player` accepts
|
|
96
|
+
DOS player customizations for words, colors, frames, positions, timing and function
|
|
97
|
+
keys. `gmHelp` optionally supplies Game-Maker's own help text before the game's
|
|
98
|
+
instructions. See the exported `RunOptions` type for these settings and callbacks.
|
|
99
|
+
|
|
100
|
+
Observe actual life loss with `onLifeLost`, including the last life, or the final
|
|
101
|
+
result and score with `onPlayEnd`. Recorded demo playback does not emit either
|
|
102
|
+
callback. Persist `GameFiles.onChange` to retain save files and high scores between
|
|
103
|
+
visits.
|
|
104
|
+
|
|
105
|
+
The source is MIT licensed; see `LICENSE` and `NOTICE.md` for credits.
|
|
106
|
+
|
|
107
|
+
Hosts can call `machine.audio.setSoundCard(enabled)` to change the optional sound-card
|
|
108
|
+
output during play. Removing it pauses FM and cuts digital effects without stopping the
|
|
109
|
+
PC speaker. Restoring it resumes the loaded song, or starts the latest song requested
|
|
110
|
+
while absent. `soundCardEnabled` reports the current card state; returning the card
|
|
111
|
+
preserves a disabled music preference. An explicit song stop remains stopped. Normal DOS-compatible startup
|
|
112
|
+
behavior is unchanged unless the host opts into live card control.
|
|
113
|
+
Set the audio card state before `runGame` and call the same method for later switches;
|
|
114
|
+
effects then use the PC speaker while the card is absent. `RunOptions.noSoundCard` retains
|
|
115
|
+
the original startup-only detection, including its fixed speaker-only choice for that run.
|
|
116
|
+
|
|
117
|
+
## Incremental picture decoding
|
|
118
|
+
|
|
119
|
+
`formats/jpeg` exports `decodePartialJpeg(bytes)` for baseline and progressive Huffman JPEGs.
|
|
120
|
+
Pass only the bytes received so far. `shown` marks pixels with completed luminance/DC blocks;
|
|
121
|
+
`pixels` holds grayscale or RGB data. A partial first progressive scan reveals only its
|
|
122
|
+
completed blocks; later scans retain the previous coefficients until each MCU is complete.
|
|
123
|
+
Restart markers preserve already decoded MCUs. `scans` counts fully delimited scans and
|
|
124
|
+
`complete` reports an end-of-image marker. The decoder does not invent data for unread blocks.
|
|
125
|
+
|
|
126
|
+
`RunOptions.onLifeLost` observes each player death, including the final life.
|
|
127
|
+
`onPlayEnd(score, how, gained)` reports `won`, `lost`, or `quit` once a play ends.
|
|
128
|
+
Neither callback runs during demo or walkthrough playback. These callbacks do not
|
|
129
|
+
change DOS gameplay or the game files.
|
|
130
|
+
|
|
131
|
+
`Machine.onItem` is an observer hook: `showGraphic` calls it as each picture, cartoon, text page or slide list begins (the walkthrough player's item marks). It never changes timing or behavior.
|
|
132
|
+
|
|
133
|
+
## Subpath exports
|
|
134
|
+
|
|
135
|
+
Everything is also importable from its own subpath, for example `import { parseBlocks } from '@lewismoten/gamemaker-sandbox-engine/formats/blocks'`, so a Node script or a bundler can take one module without the player:
|
|
136
|
+
|
|
137
|
+
- `formats/*`: readers and writers for the DOS files: `blocks`, `character`, `cmf`, `cmfEdit`, `cmfPreview`, `cmfSong`, `fli`, `fliFrames`, `fliLimits`, `game`, `gif`, `gifProgressive`, `graphicScripts`, `highscore`, `jpeg`, `map`, `monster`, `palette`, `recording`, `sound`, `voc`, and `binary` (byte helpers).
|
|
138
|
+
- `engine/*`: the PLAYGAME port: `machine`, `game`, `world`, `scene`, `scroll`, `render`, `showGraphic`, `menus`, `monsters`, `character`, `keys`, `funcKeys`, `touch`, `recorder`, `playGain`, `playerLook`, `slowPc`.
|
|
139
|
+
- `audio/*`: OPL2 and CMF playback: `opl`, `cmfPlayer`, `cmfLoad`, `engine`, `mix`, `output`, `context`.
|
|
140
|
+
- `gfx/*`: `screen`, `font8x8`, `cp437Glyphs`, `colorVision` (color-vision simulation matrices); `text/cp437`.
|
|
141
|
+
- `input/*`: `keyboard`, `scancodes`, `chords`, `deskMouse`.
|
|
142
|
+
- `core/gameFiles` (`GameFiles`) and `player/*` (`fileExtensions`, `patchRules`, `patchTable`).
|
|
143
|
+
|
|
144
|
+
## Supported environments
|
|
145
|
+
|
|
146
|
+
Playback needs a browser with canvas, Web Audio and keyboard events (the `Machine` class owns them). The file-format, decoding and simulation modules have no DOM dependency and also run in Node.js 22.12 or later, which is the version the package declares in `engines`. It ships as ES modules with TypeScript declarations.
|
|
147
|
+
|
|
148
|
+
## Developing
|
|
149
|
+
|
|
150
|
+
This package's source lives in [the project's repository](https://github.com/lewismoten/GameMaker-SandboxEdition), in `web/packages/engine`. The folder holds all its source in `src/`, plus its build configuration, license and notices. It can be copied outside the repository: run `npm install` and `npm run verify` there to build and test a packed consumer. Inside the repository, run `npm ci` at the root, then `npm run build -w @lewismoten/gamemaker-sandbox-engine`. Run `npm pack` in the package folder to inspect a local distribution. Tarballs are build artifacts and should not be committed. The [monorepo guide](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/master/docs/monorepo.md) covers the workspace layout, and the [package release guide](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/master/docs/package-releases.md) covers publishing.
|