@lewismoten/gamemaker-sandbox-tools 3.1.0 → 3.4.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 +44 -0
- package/NOTICE.md +105 -3
- package/README.md +301 -15
- package/dist/audio-files.js +82 -0
- package/dist/audio.js +23 -138
- package/dist/block-merge.js +43 -0
- package/dist/color-reduce.js +44 -0
- package/dist/colors.js +87 -0
- package/dist/delta.js +75 -0
- package/dist/disk-diff.js +220 -0
- package/dist/drawing.js +83 -869
- package/dist/embroidery/compile.js +85 -0
- package/dist/embroidery/dst.js +79 -0
- package/dist/embroidery/exp.js +26 -0
- package/dist/embroidery/fill.js +49 -0
- package/dist/embroidery/geom.js +82 -0
- package/dist/embroidery/pes.js +79 -0
- package/dist/embroidery/satin.js +29 -0
- package/dist/embroidery/simulate.js +30 -0
- package/dist/embroidery/strokeFont.js +253 -0
- package/dist/embroidery/svg.js +24 -0
- package/dist/embroidery/types.js +13 -0
- package/dist/embroidery/units.js +26 -0
- package/dist/embroidery/validate.js +15 -0
- package/dist/formats/blocks.js +1 -103
- package/dist/formats/character.js +1 -83
- package/dist/formats/cmf.js +1 -37
- package/dist/formats/fli.js +1 -296
- package/dist/formats/fliLimits.js +1 -54
- package/dist/formats/game.js +1 -193
- package/dist/formats/gif.js +1 -125
- package/dist/formats/graphicScripts.js +1 -44
- package/dist/formats/map.js +1 -38
- package/dist/formats/monster.js +1 -69
- package/dist/formats/palette.js +1 -58
- package/dist/formats/recording.js +1 -17
- package/dist/formats/sound.js +1 -44
- package/dist/formats/voc.js +1 -303
- package/dist/gif-shrink.js +56 -0
- package/dist/image/png.js +42 -0
- package/dist/images.js +81 -43
- package/dist/kit/actors.js +19 -0
- package/dist/kit/align.js +204 -0
- package/dist/kit/blit.js +45 -0
- package/dist/kit/blockRoles.js +97 -0
- package/dist/kit/clips.js +40 -0
- package/dist/kit/coverPaint.js +18 -0
- package/dist/kit/disk.js +76 -0
- package/dist/kit/fadeOut.js +13 -0
- package/dist/kit/fliClips.js +133 -0
- package/dist/kit/fliShrink.js +277 -0
- package/dist/kit/gameSim.js +235 -0
- package/dist/kit/hopBot.js +142 -0
- package/dist/kit/levelGen.js +1423 -0
- package/dist/kit/levelGrid.js +33 -0
- package/dist/kit/levelPicture.js +27 -0
- package/dist/kit/menuVersion.js +19 -0
- package/dist/kit/microText.js +35 -0
- package/dist/kit/mumble.js +74 -0
- package/dist/kit/music.js +8 -0
- package/dist/kit/palRamps.js +32 -0
- package/dist/kit/palette.js +49 -0
- package/dist/kit/pcText.js +72 -0
- package/dist/kit/photo.js +150 -0
- package/dist/kit/pixels.js +79 -0
- package/dist/kit/png.js +40 -0
- package/dist/kit/quantize.js +72 -0
- package/dist/kit/raytrace.js +379 -0
- package/dist/kit/recordedDemo.js +10 -0
- package/dist/kit/reel.js +77 -0
- package/dist/kit/road3d.js +67 -0
- package/dist/kit/routeChecks.js +8 -0
- package/dist/kit/saveSlots.js +11 -0
- package/dist/kit/sceneInit.js +13 -0
- package/dist/kit/sceneSim.js +112 -0
- package/dist/kit/screenText.js +15 -0
- package/dist/kit/sdftext.js +237 -0
- package/dist/kit/shading.js +69 -0
- package/dist/kit/song.js +251 -0
- package/dist/kit/songFx.js +179 -0
- package/dist/kit/sound.js +52 -0
- package/dist/kit/synthParts.js +20 -0
- package/dist/kit/tar.js +53 -0
- package/dist/kit/textBounds.js +84 -0
- package/dist/kit/textfit.js +246 -0
- package/dist/kit/transforms.js +57 -0
- package/dist/kit/tune.js +21 -0
- package/dist/look-alike.js +50 -0
- package/dist/menu-version.js +4 -0
- package/dist/mesh/colorBodies.js +137 -0
- package/dist/mesh/decimate.js +207 -0
- package/dist/mesh/meshCheck.js +51 -0
- package/dist/mesh/overhang.js +41 -0
- package/dist/mesh/sampledField.js +12 -0
- package/dist/mesh/stl.js +36 -0
- package/dist/mesh/surfaceNets.js +79 -0
- package/dist/mesh/tetraMesh.js +62 -0
- package/dist/mesh/threeMf.js +58 -0
- package/dist/mesh/zipFile.js +52 -0
- package/dist/microFont.js +101 -0
- package/dist/music/compose.js +72 -0
- package/dist/pack/meshPack.js +198 -0
- package/dist/pack/threeMfPack.js +92 -0
- package/dist/palette-reserve.js +116 -0
- package/dist/palettes.js +138 -0
- package/dist/release-notes.js +40 -0
- package/dist/simulation.js +16 -2774
- package/dist/text.js +74 -0
- package/dist/types/audio.d.ts +4 -0
- package/dist/types/audioFiles.d.ts +22 -0
- package/dist/types/audioWav.d.ts +4 -0
- package/dist/types/blockMerge.d.ts +24 -0
- package/dist/types/colorReduce.d.ts +23 -0
- package/dist/types/{web/packages/tools/src/colors.d.ts → colors.d.ts} +6 -0
- package/dist/types/delta.d.ts +32 -0
- package/dist/types/diskDiff.d.ts +47 -0
- package/dist/types/drawing.d.ts +15 -0
- package/dist/types/embroidery/compile.d.ts +3 -0
- package/dist/types/embroidery/dst.d.ts +13 -0
- package/dist/types/embroidery/exp.d.ts +8 -0
- package/dist/types/embroidery/fill.d.ts +6 -0
- package/dist/types/embroidery/geom.d.ts +19 -0
- package/dist/types/embroidery/pes.d.ts +10 -0
- package/dist/types/embroidery/satin.d.ts +11 -0
- package/dist/types/embroidery/simulate.d.ts +19 -0
- package/dist/types/embroidery/strokeFont.d.ts +20 -0
- package/dist/types/embroidery/svg.d.ts +3 -0
- package/dist/types/embroidery/types.d.ts +70 -0
- package/dist/types/embroidery/units.d.ts +10 -0
- package/dist/types/embroidery/validate.d.ts +22 -0
- package/dist/types/formats/blocks.d.ts +1 -0
- package/dist/types/formats/character.d.ts +1 -0
- package/dist/types/formats/cmf.d.ts +1 -0
- package/dist/types/formats/fli.d.ts +1 -0
- package/dist/types/formats/fliLimits.d.ts +1 -0
- package/dist/types/formats/game.d.ts +1 -0
- package/dist/types/formats/gif.d.ts +1 -0
- package/dist/types/formats/graphicScripts.d.ts +1 -0
- package/dist/types/formats/map.d.ts +1 -0
- package/dist/types/formats/monster.d.ts +1 -0
- package/dist/types/formats/palette.d.ts +1 -0
- package/dist/types/formats/recording.d.ts +1 -0
- package/dist/types/formats/sound.d.ts +1 -0
- package/dist/types/formats/voc.d.ts +1 -0
- package/dist/types/gifShrink.d.ts +8 -0
- package/dist/types/image/animatedGif.d.ts +9 -0
- package/dist/types/image/surface.d.ts +26 -0
- package/dist/types/images.d.ts +13 -0
- package/dist/types/kit/actors.d.ts +7 -0
- package/dist/types/kit/align.d.ts +93 -0
- package/dist/types/kit/audioEvents.d.ts +26 -0
- package/dist/types/kit/blit.d.ts +20 -0
- package/dist/types/kit/blockRoles.d.ts +243 -0
- package/dist/types/{games/kit → kit}/clips.d.ts +1 -1
- package/dist/types/kit/coverPaint.d.ts +7 -0
- package/dist/types/kit/disk.d.ts +15 -0
- package/dist/types/kit/fadeOut.d.ts +12 -0
- package/dist/types/kit/fliClips.d.ts +32 -0
- package/dist/types/kit/fliShrink.d.ts +149 -0
- package/dist/types/{games/kit → kit}/gameSim.d.ts +9 -5
- package/dist/types/kit/hopBot.d.ts +72 -0
- package/dist/types/kit/laserClearance.d.ts +16 -0
- package/dist/types/kit/laserJoints.d.ts +39 -0
- package/dist/types/kit/laserLayout.d.ts +54 -0
- package/dist/types/kit/laserPixels.d.ts +52 -0
- package/dist/types/kit/laserPreview.d.ts +9 -0
- package/dist/types/kit/laserSvg.d.ts +35 -0
- package/dist/types/kit/levelGen/castle.d.ts +17 -0
- package/dist/types/kit/levelGen/dungeon.d.ts +11 -0
- package/dist/types/kit/levelGen/forest.d.ts +17 -0
- package/dist/types/kit/levelGen/furnish.d.ts +31 -0
- package/dist/types/kit/levelGen/grid.d.ts +46 -0
- package/dist/types/kit/levelGen/index.d.ts +138 -0
- package/dist/types/kit/levelGen/interior.d.ts +18 -0
- package/dist/types/kit/levelGen/jumpModel.d.ts +78 -0
- package/dist/types/kit/levelGen/needs.d.ts +44 -0
- package/dist/types/kit/levelGen/overworld.d.ts +21 -0
- package/dist/types/kit/levelGen/platform.d.ts +59 -0
- package/dist/types/kit/levelGen/platformCap.d.ts +13 -0
- package/dist/types/kit/levelGen/platformReach.d.ts +37 -0
- package/dist/types/kit/levelGen/props.d.ts +37 -0
- package/dist/types/kit/levelGen/town.d.ts +24 -0
- package/dist/types/kit/levelGrid.d.ts +16 -0
- package/dist/types/kit/levelPicture.d.ts +9 -0
- package/dist/types/kit/menuVersion.d.ts +7 -0
- package/dist/types/kit/microText.d.ts +18 -0
- package/dist/types/kit/mumble.d.ts +41 -0
- package/dist/types/kit/music.d.ts +1 -0
- package/dist/types/kit/palMerge.d.ts +10 -0
- package/dist/types/kit/palRamps.d.ts +28 -0
- package/dist/types/kit/pcText.d.ts +19 -0
- package/dist/types/kit/photo.d.ts +69 -0
- package/dist/types/kit/png.d.ts +7 -0
- package/dist/types/kit/quantize.d.ts +20 -0
- package/dist/types/kit/raytrace.d.ts +169 -0
- package/dist/types/kit/recordedDemo.d.ts +1 -0
- package/dist/types/kit/road3d.d.ts +71 -0
- package/dist/types/kit/routeChecks.d.ts +6 -0
- package/dist/types/kit/saveSlots.d.ts +17 -0
- package/dist/types/kit/sceneInit.d.ts +11 -0
- package/dist/types/{games/kit → kit}/sceneSim.d.ts +5 -5
- package/dist/types/kit/screenText.d.ts +3 -0
- package/dist/types/kit/sdftext.d.ts +34 -0
- package/dist/types/kit/shading.d.ts +23 -0
- package/dist/types/kit/shareBlocks.d.ts +20 -0
- package/dist/types/kit/song.d.ts +89 -0
- package/dist/types/kit/songFx.d.ts +99 -0
- package/dist/types/kit/synthParts.d.ts +7 -0
- package/dist/types/kit/tar.d.ts +13 -0
- package/dist/types/kit/textfit.d.ts +74 -0
- package/dist/types/kit/transforms.d.ts +8 -0
- package/dist/types/lookAlike.d.ts +31 -0
- package/dist/types/menuVersionEntry.d.ts +1 -0
- package/dist/types/mesh/colorBodies.d.ts +18 -0
- package/dist/types/mesh/decimate.d.ts +10 -0
- package/dist/types/mesh/fieldTrinket.d.ts +40 -0
- package/dist/types/mesh/figureShapes.d.ts +24 -0
- package/dist/types/mesh/mesh.d.ts +9 -0
- package/dist/types/mesh/meshCheck.d.ts +22 -0
- package/dist/types/mesh/overhang.d.ts +24 -0
- package/dist/types/mesh/pixelFigure.d.ts +41 -0
- package/dist/types/mesh/sampledField.d.ts +3 -0
- package/dist/types/mesh/sdfShapes.d.ts +20 -0
- package/dist/types/mesh/stl.d.ts +9 -0
- package/dist/types/mesh/strokeText.d.ts +8 -0
- package/dist/types/mesh/surfaceNets.d.ts +14 -0
- package/dist/types/mesh/tetraMesh.d.ts +4 -0
- package/dist/types/mesh/threeMf.d.ts +12 -0
- package/dist/types/mesh/trinketKinds.d.ts +72 -0
- package/dist/types/mesh/trinketTool.d.ts +26 -0
- package/dist/types/mesh/voxel.d.ts +10 -0
- package/dist/types/mesh/zipFile.d.ts +13 -0
- package/dist/types/microFont.d.ts +6 -0
- package/dist/types/pack/meshPack.d.ts +26 -0
- package/dist/types/pack/threeMfPack.d.ts +11 -0
- package/dist/types/palettePresetData.d.ts +4 -0
- package/dist/types/palettePresets.d.ts +12 -0
- package/dist/types/paletteReserve.d.ts +52 -0
- package/dist/types/palettes.d.ts +4 -0
- package/dist/types/releaseNotes.d.ts +3 -0
- package/dist/types/simulation.d.ts +6 -0
- package/dist/types/{web/packages/tools/src/text.d.ts → text.d.ts} +6 -6
- package/package.json +145 -15
- package/dist/binary-D7wuaC5g.js +0 -120
- package/dist/pixels-DzfIIUOl.js +0 -76
- package/dist/types/games/kit/blit.d.ts +0 -10
- package/dist/types/games/kit/music.d.ts +0 -1
- package/dist/types/games/kit/pcText.d.ts +0 -8
- package/dist/types/games/kit/shading.d.ts +0 -11
- package/dist/types/web/packages/tools/src/audio.d.ts +0 -3
- package/dist/types/web/packages/tools/src/drawing.d.ts +0 -10
- package/dist/types/web/packages/tools/src/images.d.ts +0 -2
- package/dist/types/web/packages/tools/src/microFont.d.ts +0 -1
- package/dist/types/web/packages/tools/src/simulation.d.ts +0 -3
- package/dist/types/web/scripts/cdGames.d.ts +0 -103
- package/dist/types/web/scripts/gameShots.d.ts +0 -12
- package/dist/types/web/scripts/ogImage.d.ts +0 -21
- package/dist/types/web/src/audio/cmfLoad.d.ts +0 -7
- package/dist/types/web/src/audio/cmfPlayer.d.ts +0 -69
- package/dist/types/web/src/audio/context.d.ts +0 -12
- package/dist/types/web/src/audio/engine.d.ts +0 -39
- package/dist/types/web/src/audio/music.worklet.d.ts +0 -14
- package/dist/types/web/src/audio/opl.d.ts +0 -37
- package/dist/types/web/src/audio/output.d.ts +0 -13
- package/dist/types/web/src/desk/boxes/boxFacts.d.ts +0 -85
- package/dist/types/web/src/dosPlayer/fileExtensions.d.ts +0 -44
- package/dist/types/web/src/dosPlayer/patchRules.d.ts +0 -24
- package/dist/types/web/src/dosPlayer/patchTable.d.ts +0 -80
- package/dist/types/web/src/edition.d.ts +0 -6
- package/dist/types/web/src/eggs/eggState.d.ts +0 -26
- package/dist/types/web/src/eggs/eggs.d.ts +0 -31
- package/dist/types/web/src/engine/character.d.ts +0 -30
- package/dist/types/web/src/engine/funcKeys.d.ts +0 -33
- package/dist/types/web/src/engine/game.d.ts +0 -52
- package/dist/types/web/src/engine/keys.d.ts +0 -17
- package/dist/types/web/src/engine/machine.d.ts +0 -99
- package/dist/types/web/src/engine/menus.d.ts +0 -46
- package/dist/types/web/src/engine/monsters.d.ts +0 -19
- package/dist/types/web/src/engine/playGain.d.ts +0 -11
- package/dist/types/web/src/engine/playerLook.d.ts +0 -26
- package/dist/types/web/src/engine/recorder.d.ts +0 -60
- package/dist/types/web/src/engine/render.d.ts +0 -8
- package/dist/types/web/src/engine/scene.d.ts +0 -156
- package/dist/types/web/src/engine/scroll.d.ts +0 -16
- package/dist/types/web/src/engine/showGraphic.d.ts +0 -39
- package/dist/types/web/src/engine/slowPc.d.ts +0 -62
- package/dist/types/web/src/engine/touch.d.ts +0 -33
- package/dist/types/web/src/engine/world.d.ts +0 -215
- package/dist/types/web/src/export/gameAbout.d.ts +0 -15
- package/dist/types/web/src/formats/binary.d.ts +0 -44
- package/dist/types/web/src/formats/blocks.d.ts +0 -52
- package/dist/types/web/src/formats/character.d.ts +0 -65
- package/dist/types/web/src/formats/cmf.d.ts +0 -33
- package/dist/types/web/src/formats/fli.d.ts +0 -45
- package/dist/types/web/src/formats/fliLimits.d.ts +0 -13
- package/dist/types/web/src/formats/game.d.ts +0 -72
- package/dist/types/web/src/formats/gif.d.ts +0 -15
- package/dist/types/web/src/formats/graphicScripts.d.ts +0 -18
- package/dist/types/web/src/formats/highscore.d.ts +0 -10
- package/dist/types/web/src/formats/map.d.ts +0 -24
- package/dist/types/web/src/formats/monster.d.ts +0 -48
- package/dist/types/web/src/formats/palette.d.ts +0 -15
- package/dist/types/web/src/formats/recording.d.ts +0 -7
- package/dist/types/web/src/formats/sound.d.ts +0 -13
- package/dist/types/web/src/formats/voc.d.ts +0 -13
- package/dist/types/web/src/gfx/cp437Glyphs.d.ts +0 -2
- package/dist/types/web/src/gfx/font8x8.d.ts +0 -2
- package/dist/types/web/src/gfx/levelPicture.d.ts +0 -81
- package/dist/types/web/src/gfx/screen.d.ts +0 -46
- package/dist/types/web/src/gfx/titlePicture.d.ts +0 -21
- package/dist/types/web/src/input/chords.d.ts +0 -22
- package/dist/types/web/src/input/deskMouse.d.ts +0 -14
- package/dist/types/web/src/input/keyboard.d.ts +0 -39
- package/dist/types/web/src/input/scancodes.d.ts +0 -3
- package/dist/types/web/src/manual/printables/types.d.ts +0 -277
- package/dist/types/web/src/project/bizarre.d.ts +0 -28
- package/dist/types/web/src/project/companion.d.ts +0 -35
- package/dist/types/web/src/project/diskFacts.d.ts +0 -30
- package/dist/types/web/src/project/files.d.ts +0 -124
- package/dist/types/web/src/project/gameFiles.d.ts +0 -49
- package/dist/types/web/src/project/gamePack.d.ts +0 -17
- package/dist/types/web/src/project/health.d.ts +0 -30
- package/dist/types/web/src/project/secretGames.d.ts +0 -19
- package/dist/types/web/src/project/storage.d.ts +0 -46
- package/dist/types/web/src/project/streamGame.d.ts +0 -38
- package/dist/types/web/src/project/zip.d.ts +0 -33
- package/dist/types/web/src/retro/dos/disks.d.ts +0 -33
- package/dist/types/web/src/retro/text/cp437.d.ts +0 -4
- package/dist/types/web/src/seededRandom.d.ts +0 -6
- package/dist/types/web/src/tinHearts/deskHearts.d.ts +0 -33
- package/dist/types/web/src/tinHearts/manifest.d.ts +0 -30
- package/dist/types/web/src/tinHearts/tinHearts.d.ts +0 -84
- package/dist/types/web/src/walkthrough/format.d.ts +0 -92
- package/dist/types/web/src/walkthrough/madeUpScores.d.ts +0 -6
- package/dist/types/web/src/walkthrough/runtime.d.ts +0 -134
- /package/dist/types/{web/src/assistant → image}/png.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/palette.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/pixels.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/reel.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/sound.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/textBounds.d.ts +0 -0
- /package/dist/types/{games/kit → kit}/tune.d.ts +0 -0
- /package/dist/types/{web/src/audio → music}/compose.d.ts +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { midi as x } from "../music/compose.js";
|
|
2
|
+
const M = { kick: 11, snare: 12, tom: 13, cymbal: 14, hat: 15 }, A = { w: 4, h: 2, q: 1, e: 0.5, s: 0.25, t: 1 / 3, x: 1 / 6 };
|
|
3
|
+
function E(l) {
|
|
4
|
+
const t = [];
|
|
5
|
+
for (const r of l.split(",").map((n) => n.trim()).filter(Boolean)) {
|
|
6
|
+
const n = /^(~+)?(\S+)\s+([whqestx])(\.?)(\\+)?([!-]*)$/.exec(r);
|
|
7
|
+
if (!n) throw new Error(`Bad note "${r}"`);
|
|
8
|
+
const o = A[n[3]] * (n[4] ? 1.5 : 1), s = [...n[6]].reduce((i, h) => i + (h === "!" ? 14 : -18), 0);
|
|
9
|
+
if (n[2] === "_") {
|
|
10
|
+
const i = t[t.length - 1];
|
|
11
|
+
if (!i) throw new Error("A hold with nothing to hold");
|
|
12
|
+
t.push({ n: i.n, beats: o, scoop: 0, fall: n[5] ? n[5].length * 2 : 0, accent: 0, tie: !0 });
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
t.push({ n: x(n[2]), beats: o, scoop: n[1] ? n[1].length * 2 : 0, fall: n[5] ? n[5].length * 2 : 0, accent: s, tie: !1 });
|
|
16
|
+
}
|
|
17
|
+
return t;
|
|
18
|
+
}
|
|
19
|
+
function U(l, t) {
|
|
20
|
+
const r = Uint8Array.from(l);
|
|
21
|
+
return t.mod !== void 0 && (r[2] = r[2] & 192 | Math.max(0, Math.min(63, Math.round(t.mod)))), t.car !== void 0 && (r[3] = r[3] & 192 | Math.max(0, Math.min(63, Math.round(t.car)))), r;
|
|
22
|
+
}
|
|
23
|
+
function B(l) {
|
|
24
|
+
const t = Uint8Array.from(l);
|
|
25
|
+
return t[0] ^= 64, t[1] ^= 64, t;
|
|
26
|
+
}
|
|
27
|
+
function q(l, t, r) {
|
|
28
|
+
const n = Uint8Array.from(l);
|
|
29
|
+
return n[8] = t & 3, n[9] = r & 3, n;
|
|
30
|
+
}
|
|
31
|
+
function F(l, t, r, n) {
|
|
32
|
+
const o = (s, i, h) => s === void 0 || i === void 0 ? void 0 : s + (i - s) * h;
|
|
33
|
+
return Array.from({ length: t }, (s, i) => {
|
|
34
|
+
const h = t === 1 ? 1 : i / (t - 1);
|
|
35
|
+
return U(l, { mod: o(r.mod, n.mod, h), car: o(r.car, n.car, h) });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const v = (l, t, r) => Math.max(1, Math.min(127, Math.round(l + (t - l) * Math.max(0, Math.min(1, r)))));
|
|
39
|
+
class R {
|
|
40
|
+
constructor(t) {
|
|
41
|
+
this.w = t;
|
|
42
|
+
}
|
|
43
|
+
w;
|
|
44
|
+
/** The patch each channel has now (after its program changes). */
|
|
45
|
+
now = /* @__PURE__ */ new Map();
|
|
46
|
+
/** Where each section starts (beat), for the preview tools. */
|
|
47
|
+
sections = [];
|
|
48
|
+
tick(t) {
|
|
49
|
+
return Math.round(t * this.w.tpb);
|
|
50
|
+
}
|
|
51
|
+
/** The channel's opening patch (instrument n for channel n, loaded before the first note). */
|
|
52
|
+
open(t, r) {
|
|
53
|
+
return this.w.instruments[t] = r, this.now.set(t, r), this;
|
|
54
|
+
}
|
|
55
|
+
/** The instrument number of a patch: a channel's own opening patch, or one of the extra ones from 16 up (128 at most). */
|
|
56
|
+
patch(t) {
|
|
57
|
+
const r = this.w.instruments;
|
|
58
|
+
for (let o = 0; o < r.length; o++) if (r[o] && (r[o] === t || k(r[o], t))) return o;
|
|
59
|
+
const n = Math.max(16, r.length);
|
|
60
|
+
if (n >= 128) throw new Error("A CMF holds 128 instruments");
|
|
61
|
+
return r[n] = t, n;
|
|
62
|
+
}
|
|
63
|
+
/** A program change at beat `at` (nothing if the channel already has the patch). */
|
|
64
|
+
program(t, r, n) {
|
|
65
|
+
const o = this.now.get(t);
|
|
66
|
+
return o && (o === n || k(o, n)) ? this : (this.w.events.push({ tick: this.tick(r), data: [192 | t, this.patch(n)] }), this.now.set(t, n), this);
|
|
67
|
+
}
|
|
68
|
+
/** A section's start: a CMF marker (controller 0x66, value = its number) that PLAYGAME skips. */
|
|
69
|
+
marker(t, r) {
|
|
70
|
+
return this.sections.push({ at: t, name: r }), this.w.events.push({ tick: this.tick(t), data: [176, 102, Math.min(127, this.sections.length)] }), this;
|
|
71
|
+
}
|
|
72
|
+
/** One note, `len` beats from `at` (legato: the part of it held before letting go). */
|
|
73
|
+
note(t, r, n, o, s, i = 0.92) {
|
|
74
|
+
return this.w.note(t, r, n, o, Math.max(1, Math.min(127, Math.round(s))), i), this;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A phrase from beat `at` on one channel (see tones()): scoops slide up into their note in
|
|
78
|
+
* two-tick steps, falls slide away at the end, ties hold on. Returns its length in beats.
|
|
79
|
+
*/
|
|
80
|
+
phrase(t, r, n, o, s = 0, i = 0.92) {
|
|
81
|
+
const h = E(n);
|
|
82
|
+
let e = r;
|
|
83
|
+
for (let c = 0; c < h.length; c++) {
|
|
84
|
+
const a = h[c];
|
|
85
|
+
if (a.n === null || a.tie) {
|
|
86
|
+
e += a.beats;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
let p = a.beats, u = a.fall;
|
|
90
|
+
for (let d = c + 1; d < h.length && h[d].tie; d++)
|
|
91
|
+
p += h[d].beats, u = h[d].fall || u;
|
|
92
|
+
const f = a.n + s, w = o + a.accent;
|
|
93
|
+
let m = e;
|
|
94
|
+
a.scoop && (m = this.slide(t, e, f - a.scoop, f - 1, 2, w - 10));
|
|
95
|
+
const b = u ? u * 2 / this.w.tpb : 0, g = Math.max(1 / this.w.tpb, e + p * i - m - b);
|
|
96
|
+
u ? this.note(t, m, g + 1 / this.w.tpb, f, w, 1) : this.note(t, m, e + p - m, f, w, i), u && this.slide(t, m + g + 1 / this.w.tpb, f - 1, f - u, 2, w - 20), e += a.beats;
|
|
97
|
+
}
|
|
98
|
+
return e - r;
|
|
99
|
+
}
|
|
100
|
+
/** Semitone steps from `from` to `to`, `ticks` timer ticks each, on one channel; returns the beat it ends on. */
|
|
101
|
+
slide(t, r, n, o, s, i) {
|
|
102
|
+
const h = o >= n ? 1 : -1, e = s / this.w.tpb;
|
|
103
|
+
let c = r;
|
|
104
|
+
for (let a = n; h > 0 ? a <= o : a >= o; a += h)
|
|
105
|
+
this.note(t, c, e, a, i, 1), c += e;
|
|
106
|
+
return c;
|
|
107
|
+
}
|
|
108
|
+
/** The same notes on two channels at once, the second with the twin patch (a two-voice choir). */
|
|
109
|
+
choir(t, r, n, o, s, i = 0) {
|
|
110
|
+
return this.phrase(t, n, o, s, i), this.phrase(r, n, o, s - 8, i);
|
|
111
|
+
}
|
|
112
|
+
/** Program changes on `chs` stepping through `patches` evenly over `beats` from `at` (a swell or a filter sweep). */
|
|
113
|
+
swell(t, r, n, o) {
|
|
114
|
+
return o.forEach((s, i) => {
|
|
115
|
+
const h = r + (o.length === 1 ? 0 : n * i / (o.length - 1));
|
|
116
|
+
for (const e of t) this.program(e, h, s);
|
|
117
|
+
}), this;
|
|
118
|
+
}
|
|
119
|
+
/** A chord on one channel: its notes in turn, one every `every` beats, for `beats` ('up', 'down', 'updown'). */
|
|
120
|
+
arp(t, r, n, o, s, i, h = "up") {
|
|
121
|
+
const e = h === "up" ? o : h === "down" ? [...o].reverse() : [...o, ...o.slice(1, -1).reverse()], c = Math.round(n / s);
|
|
122
|
+
for (let a = 0; a < c; a++) this.note(t, r + a * s, s, e[a % e.length], i, 0.95);
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
/** A chord spread round several channels, a note every `every` beats; each rings on until its channel's next note (a harp). */
|
|
126
|
+
harp(t, r, n, o, s, i) {
|
|
127
|
+
const h = Math.round(n / s);
|
|
128
|
+
for (let e = 0; e < h; e++) {
|
|
129
|
+
const c = Math.min(h, e + t.length) * s, a = typeof i == "number" ? i : i(e);
|
|
130
|
+
this.note(t[e % t.length], r + e * s, c - e * s, o[e % o.length], a, 0.97);
|
|
131
|
+
}
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
/** The phrase again on `ch`, `delay` beats later, `times` times, each softer (an echo). */
|
|
135
|
+
echo(t, r, n, o, s, i = 1, h = 0.6, e = 0) {
|
|
136
|
+
for (let c = 1; c <= i; c++) this.phrase(t, r + s * c, n, o * h ** c, e, 0.7);
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
/** One note retriggered on its own channel `times` times, `gap` beats apart, each softer. */
|
|
140
|
+
stutter(t, r, n, o, s, i, h = 0.72) {
|
|
141
|
+
for (let e = 0; e < o; e++) this.note(t, r + e * s, s, n, i * h ** e, 0.8);
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
/** The bass drum as a pitched voice (its patch from boomPatch). */
|
|
145
|
+
boom(t, r, n, o) {
|
|
146
|
+
return this.note(M.kick, t, r, n, o, 0.9);
|
|
147
|
+
}
|
|
148
|
+
/** A drum hit every `every` beats for `beats`, velocity ramping (a roll); tuned drums (tom, kick) walk through `notes`. */
|
|
149
|
+
drumRoll(t, r, n, o, s, i, h = [t === M.tom ? 48 : t === M.cymbal ? 72 : 55]) {
|
|
150
|
+
const e = Math.round(n / o);
|
|
151
|
+
for (let c = 0; c < e; c++)
|
|
152
|
+
this.note(t, r + c * o, Math.min(o, 0.5), h[c % h.length], v(s, i, e === 1 ? 1 : c / (e - 1)), 0.6);
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
/** Puts every drum channel back on its opening patch and the song's length in bars, then writes the CMF. */
|
|
156
|
+
cmf(t) {
|
|
157
|
+
this.w.bar = t;
|
|
158
|
+
for (const r of [11, 12, 13, 14, 15]) {
|
|
159
|
+
const n = this.w.instruments[r];
|
|
160
|
+
n && this.program(r, t * 4, n);
|
|
161
|
+
}
|
|
162
|
+
return this.w.cmf();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const k = (l, t) => l.length === t.length && l.every((r, n) => r === t[n]);
|
|
166
|
+
function _(l = {}) {
|
|
167
|
+
const t = l.growl ?? 32;
|
|
168
|
+
return Uint8Array.from([33, 33, t, 0, 244, 240 | (l.decay ?? 3), 15, 16 | (l.release ?? 6), 0, 0, 4, 0, 0, 0, 0, 0]);
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
M as DRUM,
|
|
172
|
+
R as Fx,
|
|
173
|
+
_ as boomPatch,
|
|
174
|
+
B as detuned,
|
|
175
|
+
U as leveled,
|
|
176
|
+
F as sweep,
|
|
177
|
+
E as tones,
|
|
178
|
+
q as waved
|
|
179
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { encodeVoc as M } from "@lewismoten/gamemaker-sandbox-engine/formats/voc";
|
|
2
|
+
import { NUMFREQ as u } from "@lewismoten/gamemaker-sandbox-engine/formats/sound";
|
|
3
|
+
import { rng as h } from "./pixels.js";
|
|
4
|
+
function a(t) {
|
|
5
|
+
return Uint16Array.from({ length: u }, (n, e) => Math.max(0, Math.min(8192, Math.round(t(e, e / (u - 1))))));
|
|
6
|
+
}
|
|
7
|
+
const k = {
|
|
8
|
+
rise: (t = 200, n = 2e3) => a((e, r) => t * (n / t) ** r),
|
|
9
|
+
fall: (t = 2e3, n = 150) => a((e, r) => t * (n / t) ** r),
|
|
10
|
+
coin: () => a((t) => t < 4 ? 988 : t < 18 ? 1319 : 0),
|
|
11
|
+
hurt: () => a((t) => (t % 2 ? 140 : 95) * (1 - t / 60)),
|
|
12
|
+
zap: () => a((t) => 3e3 - t * 75 + t % 3 * 300),
|
|
13
|
+
chirp: () => a((t) => t < 12 ? 1200 + t * 120 : 0),
|
|
14
|
+
arpeggio: (t = [523, 659, 784, 1047]) => a((n) => n < t.length * 6 ? t[Math.floor(n / 6)] : 0),
|
|
15
|
+
noise: (t = 1, n = 100, e = 2e3) => {
|
|
16
|
+
const r = h(t);
|
|
17
|
+
return a((o) => o < 30 ? n + r() * (e - n) : 0);
|
|
18
|
+
},
|
|
19
|
+
warble: (t = 600, n = 300, e = 1.3) => a((r) => t + Math.sin(r * e) * n)
|
|
20
|
+
}, f = {
|
|
21
|
+
sine: (t) => {
|
|
22
|
+
let n = 0, e = 0;
|
|
23
|
+
return (r) => {
|
|
24
|
+
const o = typeof t == "number" ? t : t(r);
|
|
25
|
+
return n += 2 * Math.PI * o * (r - e), e = r, Math.sin(n);
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
square: (t) => {
|
|
29
|
+
const n = f.sine(t);
|
|
30
|
+
return (e) => n(e) >= 0 ? 1 : -1;
|
|
31
|
+
},
|
|
32
|
+
noise: (t = 7) => {
|
|
33
|
+
const n = h(t);
|
|
34
|
+
return () => n() * 2 - 1;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function v(t, n, e = {}) {
|
|
38
|
+
const r = e.rate ?? 11025, o = Math.round(t * r), i = new Float32Array(o), l = e.attack ?? 5e-3;
|
|
39
|
+
for (let c = 0; c < o; c++) {
|
|
40
|
+
const s = c / r, m = e.envelope ? e.envelope(s / t) : Math.min(1, s / l) * (1 - s / t) ** 1.5;
|
|
41
|
+
i[c] = Math.max(-1, Math.min(1, n(s) * m * (e.gain ?? 0.9)));
|
|
42
|
+
}
|
|
43
|
+
return M(i, r);
|
|
44
|
+
}
|
|
45
|
+
const y = (...t) => (n) => t.reduce((e, [r, o]) => e + r(n) * o, 0);
|
|
46
|
+
export {
|
|
47
|
+
k as SPEAKER,
|
|
48
|
+
y as mix,
|
|
49
|
+
f as osc,
|
|
50
|
+
v as sample,
|
|
51
|
+
a as speaker
|
|
52
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { rng as s } from "./pixels.js";
|
|
2
|
+
function i(e, t) {
|
|
3
|
+
const n = s(e);
|
|
4
|
+
let r = 0;
|
|
5
|
+
return (a) => {
|
|
6
|
+
const o = typeof t == "number" ? t : t(a);
|
|
7
|
+
return r += o * (n() * 2 - 1 - r), r * (1.4 / Math.sqrt(Math.max(0.05, o)));
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const c = (e, t, n) => (r) => r >= t && r < n ? e(r) : 0, h = (e, t) => (n) => Math.min(1, n / e) * Math.max(0, 1 - n) ** t;
|
|
11
|
+
function l(e, t) {
|
|
12
|
+
let n = 0;
|
|
13
|
+
return (r) => n += (e(r) - n) * t;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
h as env,
|
|
17
|
+
c as gate,
|
|
18
|
+
i as lowNoise,
|
|
19
|
+
l as lowpass
|
|
20
|
+
};
|
package/dist/kit/tar.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const h = new TextEncoder();
|
|
2
|
+
function s(e, r, t, n) {
|
|
3
|
+
const c = typeof n == "string" ? h.encode(n) : n;
|
|
4
|
+
if (c.length > t) throw new Error(`Tar field too long: ${typeof n == "string" ? n : c.length}`);
|
|
5
|
+
e.set(c, r);
|
|
6
|
+
}
|
|
7
|
+
const i = (e, r) => e.toString(8).padStart(r - 1, "0");
|
|
8
|
+
function y(e) {
|
|
9
|
+
if (h.encode(e).length <= 100) return [e, ""];
|
|
10
|
+
for (let r = e.lastIndexOf("/", e.length - 2); r > 0; r = e.lastIndexOf("/", r - 1)) {
|
|
11
|
+
const [t, n] = [e.slice(0, r), e.slice(r + 1)];
|
|
12
|
+
if (h.encode(n).length <= 100 && h.encode(t).length <= 155) return [n, t];
|
|
13
|
+
}
|
|
14
|
+
throw new Error(`Path too long for a tar archive: ${e}`);
|
|
15
|
+
}
|
|
16
|
+
function x(e, r) {
|
|
17
|
+
const t = new Uint8Array(512), n = e.path.endsWith("/"), [c, o] = y(e.path);
|
|
18
|
+
s(t, 0, 100, c), s(t, 100, 8, i(e.mode ?? (n ? 493 : 420), 8)), s(t, 108, 8, i(0, 8)), s(t, 116, 8, i(0, 8)), s(t, 124, 12, i(n ? 0 : e.data?.length ?? 0, 12)), s(t, 136, 12, i(r, 12)), t.fill(32, 148, 156), t[156] = n ? 53 : 48, s(t, 257, 6, "ustar\0"), s(t, 263, 2, "00"), s(t, 265, 32, "gamemaker"), s(t, 297, 32, "gamemaker"), s(t, 345, 155, o);
|
|
19
|
+
const a = t.reduce((f, d) => f + d, 0);
|
|
20
|
+
return s(t, 148, 8, `${i(a, 7)}\0`), t;
|
|
21
|
+
}
|
|
22
|
+
function T(e, r = /* @__PURE__ */ new Date()) {
|
|
23
|
+
const t = Math.floor(r.getTime() / 1e3), n = [];
|
|
24
|
+
for (const a of e)
|
|
25
|
+
n.push(x(a, t)), a.data && !a.path.endsWith("/") && (n.push(a.data), a.data.length % 512 && n.push(new Uint8Array(512 - a.data.length % 512)));
|
|
26
|
+
n.push(new Uint8Array(1024));
|
|
27
|
+
const c = new Uint8Array(n.reduce((a, f) => a + f.length, 0));
|
|
28
|
+
let o = 0;
|
|
29
|
+
for (const a of n)
|
|
30
|
+
c.set(a, o), o += a.length;
|
|
31
|
+
return c;
|
|
32
|
+
}
|
|
33
|
+
async function g(e, r) {
|
|
34
|
+
return new Uint8Array(await new Response(new Blob([e]).stream().pipeThrough(r)).arrayBuffer());
|
|
35
|
+
}
|
|
36
|
+
async function k(e, r) {
|
|
37
|
+
return g(T(e, r), new CompressionStream("gzip"));
|
|
38
|
+
}
|
|
39
|
+
async function A(e) {
|
|
40
|
+
const r = e[0] === 31 && e[1] === 139 ? await g(e, new DecompressionStream("gzip")) : e, t = new TextDecoder(), n = (o, a) => t.decode(r.subarray(o, o + a)).replace(/\0.*$/s, ""), c = [];
|
|
41
|
+
for (let o = 0; o + 512 <= r.length && !r.subarray(o, o + 512).every((u) => u === 0); ) {
|
|
42
|
+
const a = parseInt(n(o + 148, 8).trim(), 8), f = r.subarray(o, o + 512).reduce((u, w, p) => u + (p >= 148 && p < 156 ? 32 : w), 0);
|
|
43
|
+
if (a !== f) throw new Error("Bad tar header checksum.");
|
|
44
|
+
const d = n(o + 345, 155), m = (d ? `${d}/` : "") + n(o, 100), l = parseInt(n(o + 124, 12), 8);
|
|
45
|
+
c.push({ path: m, mode: parseInt(n(o + 100, 8), 8), data: r.slice(o + 512, o + 512 + l) }), o += 512 + Math.ceil(l / 512) * 512;
|
|
46
|
+
}
|
|
47
|
+
return c;
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
T as createTar,
|
|
51
|
+
k as createTarGz,
|
|
52
|
+
A as readTar
|
|
53
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const f = () => process.getBuiltinModule("node:fs"), x = (s) => /[\x20-\x7e\u25cf\u2022]/.test(s), u = typeof process < "u" ? process.env.TEXT_BOUNDS : void 0, p = [], o = /* @__PURE__ */ new Map(), d = (s, n, e, t) => `${s}x${n} ${e} ${t}`, m = /\/art\/(font|draw|canvas)\.ts|screens\/(draw|screen)\.ts/;
|
|
2
|
+
function w() {
|
|
3
|
+
const s = (new Error().stack ?? "").split(`
|
|
4
|
+
`).slice(1).map((t) => /\(?((?:\/|file:)[^():]+):(\d+):\d+\)?\s*$/.exec(t)).filter((t) => !!t).map((t) => ({ path: t[1].replace(/^file:\/\//, "").replace(/^.*\/games\//, ""), line: t[2] })).filter((t) => !/node_modules|kit\/textBounds\.ts/.test(t.path)).map((t) => ({ ...t, helper: m.test(t.path), name: `${t.path}:${t.line}` })), n = s.findIndex((t) => !t.helper);
|
|
5
|
+
return {
|
|
6
|
+
at: s.filter((t) => !t.helper).slice(0, 2).map((t) => t.name).join(" < "),
|
|
7
|
+
via: s.slice(0, n + 1).map((t) => t.name).join(" > ")
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
u && process.on("exit", () => {
|
|
11
|
+
const s = {
|
|
12
|
+
overflows: p,
|
|
13
|
+
shown: Object.fromEntries([...o].map(([n, e]) => [n, [...e].map((t) => t.split(",").map(Number))]))
|
|
14
|
+
};
|
|
15
|
+
f().writeFileSync(u, JSON.stringify(s));
|
|
16
|
+
});
|
|
17
|
+
class k {
|
|
18
|
+
constructor(n, e, t, i, r) {
|
|
19
|
+
this.w = n, this.h = e, this.s = t, this.area = i, this.has = r;
|
|
20
|
+
}
|
|
21
|
+
w;
|
|
22
|
+
h;
|
|
23
|
+
s;
|
|
24
|
+
area;
|
|
25
|
+
has;
|
|
26
|
+
x0 = 1 / 0;
|
|
27
|
+
y0 = 1 / 0;
|
|
28
|
+
x1 = -1 / 0;
|
|
29
|
+
y1 = -1 / 0;
|
|
30
|
+
/** A lit rectangle of the string (a font pixel, scaled). */
|
|
31
|
+
add(n, e, t = 1, i = 1) {
|
|
32
|
+
n < this.x0 && (this.x0 = n), e < this.y0 && (this.y0 = e), n + t > this.x1 && (this.x1 = n + t), e + i > this.y1 && (this.y1 = e + i);
|
|
33
|
+
}
|
|
34
|
+
end() {
|
|
35
|
+
if (this.x1 < this.x0) return;
|
|
36
|
+
const [n, e, t, i] = this.area, r = this.x0 < n - 0.5 || this.y0 < e - 0.5 || this.x1 > t + 0.5 || this.y1 > i + 0.5, { at: a, via: c } = w(), l = [...new Set(this.s)].filter((h) => !this.has(h)).join("");
|
|
37
|
+
if (l)
|
|
38
|
+
p.push({
|
|
39
|
+
s: this.s,
|
|
40
|
+
w: this.w,
|
|
41
|
+
h: this.h,
|
|
42
|
+
ink: [this.x0, this.y0, this.x1, this.y1].map((h) => Math.round(h)),
|
|
43
|
+
area: this.area,
|
|
44
|
+
at: a,
|
|
45
|
+
via: c,
|
|
46
|
+
missing: l
|
|
47
|
+
});
|
|
48
|
+
else if (r)
|
|
49
|
+
p.push({ s: this.s, w: this.w, h: this.h, ink: [this.x0, this.y0, this.x1, this.y1].map((h) => Math.round(h)), area: this.area, at: a, via: c });
|
|
50
|
+
else {
|
|
51
|
+
const h = d(this.w, this.h, c, this.s);
|
|
52
|
+
o.has(h) || o.set(h, /* @__PURE__ */ new Set()), o.get(h).add(`${Math.round(this.x0)},${Math.round(this.y0)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function $(s, n, e, t = x) {
|
|
57
|
+
if (!(!u || !n.trim()))
|
|
58
|
+
return new k(s.w, s.h, n, e ?? [0, 0, s.w, s.h], t);
|
|
59
|
+
}
|
|
60
|
+
function y(s) {
|
|
61
|
+
const n = (i) => (s.shown[d(i.w, i.h, i.via, i.s)] ?? []).some(([r, a]) => Math.abs(r - i.ink[0]) > 2 || Math.abs(a - i.ink[1]) > 2), e = /* @__PURE__ */ new Map(), t = [];
|
|
62
|
+
for (const i of s.overflows) {
|
|
63
|
+
const r = d(i.w, i.h, i.via, i.s);
|
|
64
|
+
if (!i.missing && n(i)) {
|
|
65
|
+
t.push(i);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const a = e.get(r);
|
|
69
|
+
a ? a.ink = [Math.min(a.ink[0], i.ink[0]), Math.min(a.ink[1], i.ink[1]), Math.max(a.ink[2], i.ink[2]), Math.max(a.ink[3], i.ink[3])] : e.set(r, { ...i, ink: [...i.ink] });
|
|
70
|
+
}
|
|
71
|
+
return { cut: [...e.values()], moving: t };
|
|
72
|
+
}
|
|
73
|
+
function g(s) {
|
|
74
|
+
return s.missing ? `"${s.s}" has ${[...s.missing].map((n) => `U+${n.charCodeAt(0).toString(16).toUpperCase()}`).join(" ")}, a box in the PC font (${s.w}x${s.h}) at ${s.at}` : `"${s.s}" ink ${s.ink.join(",")} outside ${s.area.join(",")} (${s.w}x${s.h}) at ${s.at}`;
|
|
75
|
+
}
|
|
76
|
+
function M(s) {
|
|
77
|
+
if (!f().existsSync(s)) throw new Error(`${s}: the build wrote no text-bounds report`);
|
|
78
|
+
return y(JSON.parse(f().readFileSync(s, "utf8")));
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
g as describe,
|
|
82
|
+
M as readBounds,
|
|
83
|
+
$ as textInk
|
|
84
|
+
};
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { readdirSync as O, readFileSync as j } from "node:fs";
|
|
2
|
+
import { join as G } from "node:path";
|
|
3
|
+
import { isGif as W, decodeGif as z } from "@lewismoten/gamemaker-sandbox-engine/formats/gif";
|
|
4
|
+
import { isFli as D, parseFli as H, newFliCanvas as _, applyFliFrame as B } from "@lewismoten/gamemaker-sandbox-engine/formats/fli";
|
|
5
|
+
import { parseBackdrop as Y, textLines as N, parseSlideList as Q } from "@lewismoten/gamemaker-sandbox-engine/formats/graphicScripts";
|
|
6
|
+
import { parseGame as R } from "@lewismoten/gamemaker-sandbox-engine/formats/game";
|
|
7
|
+
import { parsePalette as X, matchColor as Z } from "@lewismoten/gamemaker-sandbox-engine/formats/palette";
|
|
8
|
+
import { FONT8X8 as q } from "@lewismoten/gamemaker-sandbox-engine/gfx/font8x8";
|
|
9
|
+
const y = 320, w = 200, k = [63, 10, 10], C = [10, 10, 63], J = [63, 63, 0], v = 768, I = [50, 10, 50];
|
|
10
|
+
function ft(t) {
|
|
11
|
+
const e = /* @__PURE__ */ new Map();
|
|
12
|
+
for (const o of O(t)) e.set(o.toLowerCase(), new Uint8Array(j(G(t, o))));
|
|
13
|
+
return e;
|
|
14
|
+
}
|
|
15
|
+
const K = (t) => (/\.[^.]*$/.exec(t)?.[0] ?? "").toLowerCase(), b = (t, e) => Z(t, e[0], e[1], e[2]);
|
|
16
|
+
class $ {
|
|
17
|
+
pixels = new Uint8Array(y * w);
|
|
18
|
+
palette = new Uint8Array(v);
|
|
19
|
+
/** The `cols` a slide list hands from entry to entry (the last picture's palette). */
|
|
20
|
+
cols = new Uint8Array(v);
|
|
21
|
+
clone() {
|
|
22
|
+
const e = new $();
|
|
23
|
+
return e.pixels.set(this.pixels), e.palette.set(this.palette), e.cols.set(this.cols), e;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function A(t, e, o, n, c = 0, i = 0) {
|
|
27
|
+
for (let l = 0; l < n; l++) {
|
|
28
|
+
const m = l + i;
|
|
29
|
+
if (!(m < 0 || m >= w))
|
|
30
|
+
for (let r = 0; r < o; r++) {
|
|
31
|
+
const f = r + c;
|
|
32
|
+
f >= 0 && f < y && (t.pixels[m * y + f] = e[l * o + r]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function F(t, e, o, n, c, i, l, m = I) {
|
|
37
|
+
const r = t.get(e.toLowerCase());
|
|
38
|
+
if (!r) return;
|
|
39
|
+
const f = K(e);
|
|
40
|
+
if (f === ".gif" || f === ".bkd") {
|
|
41
|
+
let s = e, a = 0, p = 0;
|
|
42
|
+
if (f === ".bkd") {
|
|
43
|
+
const u = Y(r);
|
|
44
|
+
[s, a, p] = [u.gif, u.x, u.y];
|
|
45
|
+
}
|
|
46
|
+
const x = t.get(s.toLowerCase());
|
|
47
|
+
if (!x || !W(x)) return;
|
|
48
|
+
const h = z(x);
|
|
49
|
+
A(o, h.pixels, h.width, h.height, a, p), o.cols.set(h.palette), o.palette.set(h.palette);
|
|
50
|
+
} else if (f === ".fli") {
|
|
51
|
+
if (!D(r)) return;
|
|
52
|
+
const s = H(r), a = _(s);
|
|
53
|
+
a.palette.set(o.palette), a.pixels.set(o.pixels.subarray(0, a.pixels.length));
|
|
54
|
+
for (let p = 0; p < s.frameCount; p++) B(s, p, a);
|
|
55
|
+
A(o, a.pixels, s.width, s.height), o.palette.set(a.palette), o.cols.set(a.palette);
|
|
56
|
+
} else if (f === ".txt") {
|
|
57
|
+
const s = b(l ?? n, m), a = b(n, k), p = N(r);
|
|
58
|
+
for (let x = 0; x * 16 < p.length; x++) {
|
|
59
|
+
const h = p.slice(x * 16, x * 16 + 16).map((u, d) => ({ x: 40, y: (5 + d) * 8, col: s, text: u }));
|
|
60
|
+
p.length > (x + 1) * 16 && h.push({ x: 224, y: 168, col: a, text: "MORE...", want: k }), c.push({ name: `${i}${e}${p.length > 16 ? ` p${x + 1}` : ""}`, kind: "page", pixels: o.pixels.slice(), palette: o.palette.slice(), texts: h });
|
|
61
|
+
}
|
|
62
|
+
} else if (f === ".lst")
|
|
63
|
+
for (const s of Q(r)) F(t, s.name, o, n, c, `${i}${e} > `, o.cols, m);
|
|
64
|
+
}
|
|
65
|
+
function M(t, e, o) {
|
|
66
|
+
const n = t.scenes[e]?.files[o];
|
|
67
|
+
return n ? n.toLowerCase() : void 0;
|
|
68
|
+
}
|
|
69
|
+
function S(t, e) {
|
|
70
|
+
const o = new $();
|
|
71
|
+
return F(t, e, o, o.palette, [], ""), o;
|
|
72
|
+
}
|
|
73
|
+
function pt(t, e = I) {
|
|
74
|
+
const o = [...t.keys()].find((f) => f.endsWith(".gam"));
|
|
75
|
+
if (!o) throw new Error("no .gam on the disk");
|
|
76
|
+
const n = R(t.get(o)), c = [], i = M(n, 0, 2), l = i ? S(t, i) : new $(), m = /* @__PURE__ */ new Set();
|
|
77
|
+
if (n.scenes.forEach((f, s) => {
|
|
78
|
+
const a = s === 0 ? [0, 4, 6, 7] : s === 1 ? [0, 2] : [9, 10];
|
|
79
|
+
let p = l.palette;
|
|
80
|
+
if (s > 1) {
|
|
81
|
+
const x = M(n, s, 0), h = x && t.get(x);
|
|
82
|
+
h && (p = X(h));
|
|
83
|
+
}
|
|
84
|
+
for (const x of a) {
|
|
85
|
+
const h = M(n, s, x);
|
|
86
|
+
if (!h || m.has(h)) continue;
|
|
87
|
+
m.add(h);
|
|
88
|
+
const u = s === 0 && x !== 0 ? l.clone() : new $();
|
|
89
|
+
F(t, h, u, p, c, "", void 0, e);
|
|
90
|
+
}
|
|
91
|
+
}), i) {
|
|
92
|
+
const f = b(l.palette, C), s = [{ x: 96, y: 104, col: f, text: n.scenes[0].desc }];
|
|
93
|
+
["Play", "Read Instructions", "Read Storyline", "See Credits", "See Highest Scores", "Quit"].forEach((a, p) => {
|
|
94
|
+
s.push({ x: 80, y: (15 + p) * 8, col: f, text: a }), s.push({ x: 70, y: 113 + (p + 1) * 8, col: f, text: "", box: { w: 6, h: 5 } });
|
|
95
|
+
}), c.push({ name: `menu ${i}`, kind: "menu", pixels: l.pixels, palette: l.palette, texts: s });
|
|
96
|
+
}
|
|
97
|
+
const r = M(n, 0, 8);
|
|
98
|
+
if (r) {
|
|
99
|
+
const f = S(t, r), s = b(f.palette, k), a = b(f.palette, C), p = [{ x: 104, y: 0, col: s, text: "Top Ten Scores" }];
|
|
100
|
+
let x = 22, h = 27;
|
|
101
|
+
for (let u = 0; u < 10; u++)
|
|
102
|
+
p.push({ x: 20, y: h, col: a, text: `${String(1234567890 - u)} ${"M".repeat(22)}` }), h += x, u % 2 === 0 && x--, x--;
|
|
103
|
+
p.push({ x: 20, y: h, col: a, text: `${"1234".padStart(10)} Your Latest Score` }), p.push({ x: 116, y: 192, col: s, text: "Hit any key" }), c.push({ name: `scores ${r}`, kind: "scores", pixels: f.pixels, palette: f.palette, texts: p });
|
|
104
|
+
}
|
|
105
|
+
for (const [f, s] of [
|
|
106
|
+
[9, "load"],
|
|
107
|
+
[10, "save"]
|
|
108
|
+
]) {
|
|
109
|
+
const a = M(n, 0, f);
|
|
110
|
+
if (!a) continue;
|
|
111
|
+
const p = S(t, a), x = b(p.palette, J), h = b(p.palette, k), u = b(p.palette, C), d = [];
|
|
112
|
+
for (let g = 0; g < 10; g++)
|
|
113
|
+
d.push({ x: 80, y: 40 + g * 14, col: x, text: "M".repeat(20) }), d.push({ x: 60, y: 27 + (g + 1) * 14, col: h, text: "", box: { w: 6, h: 5 } });
|
|
114
|
+
s === "load" ? d.push({ x: 40, y: 185, col: u, text: "This game has not been saved!" }) : d.push({ x: 112, y: 185, col: u, text: "Game Saved!" }), c.push({ name: `${s} ${a}`, kind: s, pixels: p.pixels, palette: p.palette, texts: d });
|
|
115
|
+
}
|
|
116
|
+
return c;
|
|
117
|
+
}
|
|
118
|
+
function T(t) {
|
|
119
|
+
const e = [];
|
|
120
|
+
if (t.box) {
|
|
121
|
+
for (let o = 0; o < t.box.h; o++) for (let n = 0; n < t.box.w; n++) e.push([t.x + n, t.y + o]);
|
|
122
|
+
return e;
|
|
123
|
+
}
|
|
124
|
+
for (let o = 0; o < t.text.length; o++) {
|
|
125
|
+
const n = (t.text.charCodeAt(o) & 255) * 8;
|
|
126
|
+
for (let c = 0; c < 8; c++) {
|
|
127
|
+
const i = q[n + c];
|
|
128
|
+
for (let l = 0; l < 8; l++) i & 1 << l && e.push([t.x + o * 8 + l, t.y + c]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return e;
|
|
132
|
+
}
|
|
133
|
+
const E = (t, e) => [0, 1, 2].map((o) => t[e * 3 + o] << 2 | t[e * 3 + o] >> 4), L = (t) => {
|
|
134
|
+
const e = t / 255;
|
|
135
|
+
return e <= 0.03928 ? e / 12.92 : ((e + 0.055) / 1.055) ** 2.4;
|
|
136
|
+
}, P = (t) => 0.2126 * L(t[0]) + 0.7152 * L(t[1]) + 0.0722 * L(t[2]), V = (t, e) => {
|
|
137
|
+
const [o, n] = [P(t), P(e)].sort((c, i) => i - c);
|
|
138
|
+
return (o + 0.05) / (n + 0.05);
|
|
139
|
+
};
|
|
140
|
+
function U(t, e) {
|
|
141
|
+
const o = T(t);
|
|
142
|
+
if (!o.length) return;
|
|
143
|
+
let [n, c, i, l] = [1 / 0, 1 / 0, -1 / 0, -1 / 0];
|
|
144
|
+
for (const [m, r] of o) [n, c, i, l] = [Math.min(n, m), Math.min(c, r), Math.max(i, m), Math.max(l, r)];
|
|
145
|
+
return { x0: n - e, y0: c - e, x1: i + e, y1: l + e };
|
|
146
|
+
}
|
|
147
|
+
function tt(t, e) {
|
|
148
|
+
const o = [[], [], []];
|
|
149
|
+
for (const n of t.texts) {
|
|
150
|
+
const c = U(n, e);
|
|
151
|
+
if (c)
|
|
152
|
+
for (let i = Math.max(0, c.y0); i <= Math.min(w - 1, c.y1); i++)
|
|
153
|
+
for (let l = Math.max(0, c.x0); l <= Math.min(y - 1, c.x1); l++) {
|
|
154
|
+
const m = E(t.palette, t.pixels[i * y + l]);
|
|
155
|
+
for (let r = 0; r < 3; r++) o[r].push(m[r]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return o.map((n) => (n.sort((c, i) => c - i), n[n.length >> 1] ?? 0));
|
|
159
|
+
}
|
|
160
|
+
function xt(t, e = {}, o) {
|
|
161
|
+
const n = e.margin ?? 2, c = e.artDistance ?? 72, i = e.allowArt ?? 0, l = e.minContrast ?? 3, m = [];
|
|
162
|
+
for (const r of t.texts) {
|
|
163
|
+
const f = U(r, n);
|
|
164
|
+
if (!f) continue;
|
|
165
|
+
const s = [];
|
|
166
|
+
(f.x0 + n < 0 || f.y0 + n < 0 || f.x1 - n >= y || f.y1 - n >= w) && s.push("off the screen");
|
|
167
|
+
const a = { ...t, texts: [r] }, p = tt(a, n);
|
|
168
|
+
let x = 0;
|
|
169
|
+
for (let u = Math.max(0, f.y0); u <= Math.min(w - 1, f.y1); u++)
|
|
170
|
+
for (let d = Math.max(0, f.x0); d <= Math.min(y - 1, f.x1); d++) {
|
|
171
|
+
const g = E(t.palette, t.pixels[u * y + d]);
|
|
172
|
+
Math.hypot(g[0] - p[0], g[1] - p[1], g[2] - p[2]) > c && (x++, o && (o[u * y + d] = 1));
|
|
173
|
+
}
|
|
174
|
+
x > i && s.push(`${x} art pixels within ${n}px`);
|
|
175
|
+
const h = V(E(t.palette, r.col), p);
|
|
176
|
+
if (h < l && s.push(`contrast ${h.toFixed(2)}`), r.want) {
|
|
177
|
+
const u = [0, 1, 2].map((d) => t.palette[r.col * 3 + d]);
|
|
178
|
+
Math.hypot(u[0] - r.want[0], u[1] - r.want[1], u[2] - r.want[2]) > 30 && s.push(`ink shows as rgb(${u.join(",")}), not rgb(${r.want.join(",")})`);
|
|
179
|
+
}
|
|
180
|
+
s.length && m.push({ screen: t.name, text: r.box ? "[marker]" : r.text, x: r.x, y: r.y, artPixels: x, contrast: h, problems: s });
|
|
181
|
+
}
|
|
182
|
+
return m;
|
|
183
|
+
}
|
|
184
|
+
function ht(t, e) {
|
|
185
|
+
const o = new Uint8Array(y * w * 3), n = t.pixels.slice();
|
|
186
|
+
for (const c of t.texts) for (const [i, l] of T(c)) i >= 0 && l >= 0 && i < y && l < w && (n[l * y + i] = c.col);
|
|
187
|
+
for (let c = 0; c < y * w; c++) {
|
|
188
|
+
let i = E(t.palette, n[c]);
|
|
189
|
+
e?.[c] && n[c] === t.pixels[c] && (i = [255, 0, 255]), o.set(i, c * 3);
|
|
190
|
+
}
|
|
191
|
+
return o;
|
|
192
|
+
}
|
|
193
|
+
function ut(t) {
|
|
194
|
+
const e = [...t.keys()].find((i) => i.endsWith(".gam"));
|
|
195
|
+
if (!e) throw new Error("no .gam on the disk");
|
|
196
|
+
const o = R(t.get(e)), n = [], c = /* @__PURE__ */ new Set();
|
|
197
|
+
return o.scenes.forEach((i, l) => {
|
|
198
|
+
if (!(l < 2))
|
|
199
|
+
for (const m of [9, 10]) {
|
|
200
|
+
const r = M(o, l, m);
|
|
201
|
+
if (!r || c.has(r) || !t.has(r)) continue;
|
|
202
|
+
c.add(r);
|
|
203
|
+
const f = S(t, r);
|
|
204
|
+
n.push({ name: `scene ${l} ${r}`, pixels: f.pixels, palette: f.palette });
|
|
205
|
+
}
|
|
206
|
+
}), n;
|
|
207
|
+
}
|
|
208
|
+
function mt(t) {
|
|
209
|
+
const e = (s, a) => t.pixels[a * y + s], o = e(24, 16);
|
|
210
|
+
let [n, c, i, l] = [24, 24, 16, 16];
|
|
211
|
+
for (; n > 0 && e(n - 1, 16) === o; ) n--;
|
|
212
|
+
for (; c < y - 1 && e(c + 1, 16) === o; ) c++;
|
|
213
|
+
for (let s = n + 2; s <= c - 2; s++) {
|
|
214
|
+
if (e(s, 16) !== o) continue;
|
|
215
|
+
let [a, p] = [16, 16];
|
|
216
|
+
for (; a > 0 && e(s, a - 1) === o; ) a--;
|
|
217
|
+
for (; p < w - 1 && e(s, p + 1) === o; ) p++;
|
|
218
|
+
i = Math.min(i, a), l = Math.max(l, p);
|
|
219
|
+
}
|
|
220
|
+
if (c - n < 100 || l - i < 30 || l - i > 90) return [];
|
|
221
|
+
const m = /* @__PURE__ */ new Set();
|
|
222
|
+
for (let s = Math.max(0, n - 6); s <= Math.min(y - 1, c + 6); s++) for (let a = Math.max(0, i - 6); a < i; a++) m.add(e(s, a));
|
|
223
|
+
for (let s = i; s <= Math.min(l, i + 6); s++) for (const a of [n - 1, n - 2, n - 3, c + 1, c + 2, c + 3]) m.add(e(a, s));
|
|
224
|
+
const r = /* @__PURE__ */ new Set();
|
|
225
|
+
for (let s = i; s <= l; s++) for (let a = n; a <= c; a++) e(a, s) !== o && !m.has(e(a, s)) && r.add(e(a, s));
|
|
226
|
+
const f = [];
|
|
227
|
+
for (const [s, a, p] of [
|
|
228
|
+
["left", n - 14, n - 1],
|
|
229
|
+
["right", c + 1, c + 14]
|
|
230
|
+
]) {
|
|
231
|
+
let x = 0;
|
|
232
|
+
for (let h = i; h <= l; h++) for (let u = Math.max(0, a); u <= Math.min(y - 1, p); u++) r.has(e(u, h)) && x++;
|
|
233
|
+
x && f.push(`text runs past the ${s} edge of its box (${x} pixels outside it)`);
|
|
234
|
+
}
|
|
235
|
+
return f;
|
|
236
|
+
}
|
|
237
|
+
export {
|
|
238
|
+
w as H,
|
|
239
|
+
y as W,
|
|
240
|
+
mt as cardOverflow,
|
|
241
|
+
xt as checkTextScreen,
|
|
242
|
+
ut as levelCards,
|
|
243
|
+
ft as readDisk,
|
|
244
|
+
ht as renderRgb,
|
|
245
|
+
pt as textScreens
|
|
246
|
+
};
|