picopilot 0.0.0 → 0.1.1
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/LICENSE +661 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/audio.d.ts +17 -0
- package/dist/commands/audio.d.ts.map +1 -0
- package/dist/commands/audio.js +315 -0
- package/dist/commands/audio.js.map +1 -0
- package/dist/commands/export.d.ts +36 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +257 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/gfx.d.ts +28 -0
- package/dist/commands/gfx.d.ts.map +1 -0
- package/dist/commands/gfx.js +521 -0
- package/dist/commands/gfx.js.map +1 -0
- package/dist/commands/init.d.ts +34 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +151 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +20 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +90 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/minify.d.ts +20 -0
- package/dist/commands/minify.d.ts.map +1 -0
- package/dist/commands/minify.js +129 -0
- package/dist/commands/minify.js.map +1 -0
- package/dist/commands/music.d.ts +13 -0
- package/dist/commands/music.d.ts.map +1 -0
- package/dist/commands/music.js +241 -0
- package/dist/commands/music.js.map +1 -0
- package/dist/commands/playtest.d.ts +29 -0
- package/dist/commands/playtest.d.ts.map +1 -0
- package/dist/commands/playtest.js +631 -0
- package/dist/commands/playtest.js.map +1 -0
- package/dist/commands/run.d.ts +30 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +224 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/serve.d.ts +50 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +213 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/sfx.d.ts +13 -0
- package/dist/commands/sfx.d.ts.map +1 -0
- package/dist/commands/sfx.js +254 -0
- package/dist/commands/sfx.js.map +1 -0
- package/dist/commands/tokens.d.ts +36 -0
- package/dist/commands/tokens.d.ts.map +1 -0
- package/dist/commands/tokens.js +129 -0
- package/dist/commands/tokens.js.map +1 -0
- package/dist/commands/verify.d.ts +57 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +213 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/version.d.ts +12 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +24 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/engine/audio/index.d.ts +14 -0
- package/dist/engine/audio/index.d.ts.map +1 -0
- package/dist/engine/audio/index.js +14 -0
- package/dist/engine/audio/index.js.map +1 -0
- package/dist/engine/audio/music.d.ts +116 -0
- package/dist/engine/audio/music.d.ts.map +1 -0
- package/dist/engine/audio/music.js +138 -0
- package/dist/engine/audio/music.js.map +1 -0
- package/dist/engine/audio/section.d.ts +34 -0
- package/dist/engine/audio/section.d.ts.map +1 -0
- package/dist/engine/audio/section.js +67 -0
- package/dist/engine/audio/section.js.map +1 -0
- package/dist/engine/audio/sfx.d.ts +141 -0
- package/dist/engine/audio/sfx.d.ts.map +1 -0
- package/dist/engine/audio/sfx.js +506 -0
- package/dist/engine/audio/sfx.js.map +1 -0
- package/dist/engine/cart/cart.d.ts +75 -0
- package/dist/engine/cart/cart.d.ts.map +1 -0
- package/dist/engine/cart/cart.js +153 -0
- package/dist/engine/cart/cart.js.map +1 -0
- package/dist/engine/cart/errors.d.ts +29 -0
- package/dist/engine/cart/errors.d.ts.map +1 -0
- package/dist/engine/cart/errors.js +26 -0
- package/dist/engine/cart/errors.js.map +1 -0
- package/dist/engine/cart/gfx.d.ts +79 -0
- package/dist/engine/cart/gfx.d.ts.map +1 -0
- package/dist/engine/cart/gfx.js +171 -0
- package/dist/engine/cart/gfx.js.map +1 -0
- package/dist/engine/cart/index.d.ts +15 -0
- package/dist/engine/cart/index.d.ts.map +1 -0
- package/dist/engine/cart/index.js +15 -0
- package/dist/engine/cart/index.js.map +1 -0
- package/dist/engine/cart/map.d.ts +46 -0
- package/dist/engine/cart/map.d.ts.map +1 -0
- package/dist/engine/cart/map.js +118 -0
- package/dist/engine/cart/map.js.map +1 -0
- package/dist/engine/config/config.d.ts +74 -0
- package/dist/engine/config/config.d.ts.map +1 -0
- package/dist/engine/config/config.js +103 -0
- package/dist/engine/config/config.js.map +1 -0
- package/dist/engine/config/index.d.ts +7 -0
- package/dist/engine/config/index.d.ts.map +1 -0
- package/dist/engine/config/index.js +7 -0
- package/dist/engine/config/index.js.map +1 -0
- package/dist/engine/gfx/grid.d.ts +51 -0
- package/dist/engine/gfx/grid.d.ts.map +1 -0
- package/dist/engine/gfx/grid.js +116 -0
- package/dist/engine/gfx/grid.js.map +1 -0
- package/dist/engine/gfx/index.d.ts +17 -0
- package/dist/engine/gfx/index.d.ts.map +1 -0
- package/dist/engine/gfx/index.js +17 -0
- package/dist/engine/gfx/index.js.map +1 -0
- package/dist/engine/gfx/label.d.ts +34 -0
- package/dist/engine/gfx/label.d.ts.map +1 -0
- package/dist/engine/gfx/label.js +190 -0
- package/dist/engine/gfx/label.js.map +1 -0
- package/dist/engine/gfx/overlap.d.ts +42 -0
- package/dist/engine/gfx/overlap.d.ts.map +1 -0
- package/dist/engine/gfx/overlap.js +57 -0
- package/dist/engine/gfx/overlap.js.map +1 -0
- package/dist/engine/gfx/palette.d.ts +29 -0
- package/dist/engine/gfx/palette.d.ts.map +1 -0
- package/dist/engine/gfx/palette.js +46 -0
- package/dist/engine/gfx/palette.js.map +1 -0
- package/dist/engine/gfx/png.d.ts +31 -0
- package/dist/engine/gfx/png.d.ts.map +1 -0
- package/dist/engine/gfx/png.js +165 -0
- package/dist/engine/gfx/png.js.map +1 -0
- package/dist/engine/gfx/render.d.ts +42 -0
- package/dist/engine/gfx/render.d.ts.map +1 -0
- package/dist/engine/gfx/render.js +72 -0
- package/dist/engine/gfx/render.js.map +1 -0
- package/dist/engine/index.d.ts +22 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +22 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/pico8/adapter.d.ts +267 -0
- package/dist/engine/pico8/adapter.d.ts.map +1 -0
- package/dist/engine/pico8/adapter.js +37 -0
- package/dist/engine/pico8/adapter.js.map +1 -0
- package/dist/engine/pico8/drive.d.ts +308 -0
- package/dist/engine/pico8/drive.d.ts.map +1 -0
- package/dist/engine/pico8/drive.js +581 -0
- package/dist/engine/pico8/drive.js.map +1 -0
- package/dist/engine/pico8/harness.d.ts +146 -0
- package/dist/engine/pico8/harness.d.ts.map +1 -0
- package/dist/engine/pico8/harness.js +251 -0
- package/dist/engine/pico8/harness.js.map +1 -0
- package/dist/engine/pico8/index.d.ts +21 -0
- package/dist/engine/pico8/index.d.ts.map +1 -0
- package/dist/engine/pico8/index.js +21 -0
- package/dist/engine/pico8/index.js.map +1 -0
- package/dist/engine/pico8/sentinel.d.ts +63 -0
- package/dist/engine/pico8/sentinel.d.ts.map +1 -0
- package/dist/engine/pico8/sentinel.js +86 -0
- package/dist/engine/pico8/sentinel.js.map +1 -0
- package/dist/engine/pico8/session-daemon-entry.d.ts +10 -0
- package/dist/engine/pico8/session-daemon-entry.d.ts.map +1 -0
- package/dist/engine/pico8/session-daemon-entry.js +11 -0
- package/dist/engine/pico8/session-daemon-entry.js.map +1 -0
- package/dist/engine/pico8/session-daemon-main.d.ts +44 -0
- package/dist/engine/pico8/session-daemon-main.d.ts.map +1 -0
- package/dist/engine/pico8/session-daemon-main.js +71 -0
- package/dist/engine/pico8/session-daemon-main.js.map +1 -0
- package/dist/engine/pico8/session-daemon.d.ts +68 -0
- package/dist/engine/pico8/session-daemon.d.ts.map +1 -0
- package/dist/engine/pico8/session-daemon.js +264 -0
- package/dist/engine/pico8/session-daemon.js.map +1 -0
- package/dist/engine/pico8/session.d.ts +140 -0
- package/dist/engine/pico8/session.d.ts.map +1 -0
- package/dist/engine/pico8/session.js +250 -0
- package/dist/engine/pico8/session.js.map +1 -0
- package/dist/engine/pico8/shell.d.ts +103 -0
- package/dist/engine/pico8/shell.d.ts.map +1 -0
- package/dist/engine/pico8/shell.js +324 -0
- package/dist/engine/pico8/shell.js.map +1 -0
- package/dist/engine/pico8/supervisor.d.ts +137 -0
- package/dist/engine/pico8/supervisor.d.ts.map +1 -0
- package/dist/engine/pico8/supervisor.js +140 -0
- package/dist/engine/pico8/supervisor.js.map +1 -0
- package/dist/engine/scaffold/index.d.ts +8 -0
- package/dist/engine/scaffold/index.d.ts.map +1 -0
- package/dist/engine/scaffold/index.js +8 -0
- package/dist/engine/scaffold/index.js.map +1 -0
- package/dist/engine/scaffold/scaffold.d.ts +49 -0
- package/dist/engine/scaffold/scaffold.d.ts.map +1 -0
- package/dist/engine/scaffold/scaffold.js +259 -0
- package/dist/engine/scaffold/scaffold.js.map +1 -0
- package/dist/engine/shrinko/adapter.d.ts +167 -0
- package/dist/engine/shrinko/adapter.d.ts.map +1 -0
- package/dist/engine/shrinko/adapter.js +107 -0
- package/dist/engine/shrinko/adapter.js.map +1 -0
- package/dist/engine/shrinko/index.d.ts +13 -0
- package/dist/engine/shrinko/index.d.ts.map +1 -0
- package/dist/engine/shrinko/index.js +13 -0
- package/dist/engine/shrinko/index.js.map +1 -0
- package/dist/engine/shrinko/shell.d.ts +69 -0
- package/dist/engine/shrinko/shell.d.ts.map +1 -0
- package/dist/engine/shrinko/shell.js +156 -0
- package/dist/engine/shrinko/shell.js.map +1 -0
- package/dist/engine/skills/index.d.ts +8 -0
- package/dist/engine/skills/index.d.ts.map +1 -0
- package/dist/engine/skills/index.js +8 -0
- package/dist/engine/skills/index.js.map +1 -0
- package/dist/engine/skills/skills.d.ts +104 -0
- package/dist/engine/skills/skills.d.ts.map +1 -0
- package/dist/engine/skills/skills.js +149 -0
- package/dist/engine/skills/skills.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +19 -0
- package/dist/version.js.map +1 -0
- package/package.json +48 -2
- package/src/bin.ts +4 -0
- package/src/cli.ts +61 -0
- package/src/commands/audio.test.ts +280 -0
- package/src/commands/audio.ts +410 -0
- package/src/commands/export.test.ts +310 -0
- package/src/commands/export.ts +316 -0
- package/src/commands/gfx-io.test.ts +178 -0
- package/src/commands/gfx.test.ts +470 -0
- package/src/commands/gfx.ts +645 -0
- package/src/commands/init.test.ts +482 -0
- package/src/commands/init.ts +193 -0
- package/src/commands/lint.test.ts +137 -0
- package/src/commands/lint.ts +117 -0
- package/src/commands/minify.test.ts +166 -0
- package/src/commands/minify.ts +156 -0
- package/src/commands/music.test.ts +272 -0
- package/src/commands/music.ts +288 -0
- package/src/commands/playtest.test.ts +317 -0
- package/src/commands/playtest.ts +773 -0
- package/src/commands/run.test.ts +264 -0
- package/src/commands/run.ts +285 -0
- package/src/commands/serve.test.ts +227 -0
- package/src/commands/serve.ts +272 -0
- package/src/commands/sfx.test.ts +349 -0
- package/src/commands/sfx.ts +300 -0
- package/src/commands/tokens.test.ts +212 -0
- package/src/commands/tokens.ts +168 -0
- package/src/commands/verify.test.ts +238 -0
- package/src/commands/verify.ts +256 -0
- package/src/commands/version.test.ts +70 -0
- package/src/commands/version.ts +24 -0
- package/src/engine/audio/index.ts +47 -0
- package/src/engine/audio/music.test.ts +188 -0
- package/src/engine/audio/music.ts +218 -0
- package/src/engine/audio/section.test.ts +124 -0
- package/src/engine/audio/section.ts +79 -0
- package/src/engine/audio/sfx.test.ts +410 -0
- package/src/engine/audio/sfx.ts +694 -0
- package/src/engine/cart/cart.test.ts +304 -0
- package/src/engine/cart/cart.ts +211 -0
- package/src/engine/cart/errors.ts +39 -0
- package/src/engine/cart/fixtures/crlf.p8 +6 -0
- package/src/engine/cart/fixtures/full.p8 +174 -0
- package/src/engine/cart/fixtures/header-only.p8 +2 -0
- package/src/engine/cart/fixtures/malformed-no-header.p8 +2 -0
- package/src/engine/cart/fixtures/minimal.p8 +10 -0
- package/src/engine/cart/fixtures/no-trailing-newline.p8 +6 -0
- package/src/engine/cart/gfx.ts +195 -0
- package/src/engine/cart/index.ts +27 -0
- package/src/engine/cart/map.ts +134 -0
- package/src/engine/config/config.ts +115 -0
- package/src/engine/config/index.ts +12 -0
- package/src/engine/gfx/grid.test.ts +128 -0
- package/src/engine/gfx/grid.ts +136 -0
- package/src/engine/gfx/index.ts +34 -0
- package/src/engine/gfx/label.test.ts +105 -0
- package/src/engine/gfx/label.ts +229 -0
- package/src/engine/gfx/overlap.test.ts +71 -0
- package/src/engine/gfx/overlap.ts +66 -0
- package/src/engine/gfx/palette.test.ts +35 -0
- package/src/engine/gfx/palette.ts +54 -0
- package/src/engine/gfx/png.test.ts +111 -0
- package/src/engine/gfx/png.ts +196 -0
- package/src/engine/gfx/render.test.ts +180 -0
- package/src/engine/gfx/render.ts +106 -0
- package/src/engine/index.ts +21 -0
- package/src/engine/pico8/adapter.ts +303 -0
- package/src/engine/pico8/drive.test.ts +415 -0
- package/src/engine/pico8/drive.ts +729 -0
- package/src/engine/pico8/harness.test.ts +181 -0
- package/src/engine/pico8/harness.ts +354 -0
- package/src/engine/pico8/index.ts +20 -0
- package/src/engine/pico8/sentinel.test.ts +80 -0
- package/src/engine/pico8/sentinel.ts +93 -0
- package/src/engine/pico8/session-daemon-entry.ts +12 -0
- package/src/engine/pico8/session-daemon-main.ts +98 -0
- package/src/engine/pico8/session-daemon.test.ts +212 -0
- package/src/engine/pico8/session-daemon.ts +306 -0
- package/src/engine/pico8/session.test.ts +239 -0
- package/src/engine/pico8/session.ts +321 -0
- package/src/engine/pico8/shell.test.ts +583 -0
- package/src/engine/pico8/shell.ts +412 -0
- package/src/engine/pico8/supervisor.test.ts +105 -0
- package/src/engine/pico8/supervisor.ts +197 -0
- package/src/engine/scaffold/index.ts +15 -0
- package/src/engine/scaffold/scaffold.ts +278 -0
- package/src/engine/shrinko/adapter.ts +241 -0
- package/src/engine/shrinko/fixtures/count-no-compressed.txt +2 -0
- package/src/engine/shrinko/fixtures/count-over-budget.txt +3 -0
- package/src/engine/shrinko/fixtures/count-under-budget.txt +3 -0
- package/src/engine/shrinko/index.ts +33 -0
- package/src/engine/shrinko/shell.ts +224 -0
- package/src/engine/shrinko/shrinko.test.ts +182 -0
- package/src/engine/skills/index.ts +14 -0
- package/src/engine/skills/skills.test.ts +376 -0
- package/src/engine/skills/skills.ts +205 -0
- package/src/index.ts +13 -0
- package/src/skills/game-design-reference/SKILL.md +70 -0
- package/src/skills/game-jam/SKILL.md +45 -0
- package/src/skills/picopilot-art/SKILL.md +62 -0
- package/src/skills/picopilot-audio/SKILL.md +194 -0
- package/src/skills/picopilot-code/SKILL.md +97 -0
- package/src/skills/picopilot-code/reference/README.md +42 -0
- package/src/skills/picopilot-code/reference/mode7-racing.md +95 -0
- package/src/skills/picopilot-code/reference/platformer.md +119 -0
- package/src/skills/picopilot-code/reference/puzzle-grid.md +106 -0
- package/src/skills/picopilot-code/reference/rpg-menus-dialog.md +122 -0
- package/src/skills/picopilot-code/reference/top-down-adventure.md +117 -0
- package/src/skills/picopilot-code/reference/twin-stick-arcade.md +128 -0
- package/src/skills/picopilot-debug/SKILL.md +195 -0
- package/src/skills/picopilot-overview/SKILL.md +52 -0
- package/src/version.ts +22 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/engine/gfx/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,QAAQ,EAGb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAY,KAAK,QAAQ,EAAC,MAAM,UAAU,CAAC;AAElD;;;;;;;;;;;;;;;GAeG;AAEH,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAUtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CAS1D;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,EAC1C,KAAK,EAAE,MAAM,GACX,QAAQ,CA2BV"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { GFX_HEIGHT, GFX_WIDTH, SPRITE_SIZE, spriteOrigin, } from '../cart/index.js';
|
|
2
|
+
import { paletteColor } from './palette.js';
|
|
3
|
+
import { encodePng } from './png.js';
|
|
4
|
+
/**
|
|
5
|
+
* The `gfx render` JUDGE surface: turn a sprite (or the whole spritesheet) into a
|
|
6
|
+
* nearest-neighbour-upscaled, palette-accurate PNG a multimodal agent can LOOK at.
|
|
7
|
+
*
|
|
8
|
+
* The char grid (`gfx show`/`gfx set`) is the exact EDIT surface, but an LLM reads
|
|
9
|
+
* serialized hex poorly for gestalt/colour (the SVG parallel: models generate
|
|
10
|
+
* structured visual source well but read it back poorly). So this renders the
|
|
11
|
+
* ACTUAL pixels, upscaled enough to be viewable, with each colour index mapped to
|
|
12
|
+
* its exact PICO-8 palette RGB (single source of truth: {@link paletteColor}).
|
|
13
|
+
*
|
|
14
|
+
* Upscale is NEAREST-NEIGHBOUR (each source pixel becomes a `scale`x`scale` block
|
|
15
|
+
* of identical RGB) so the pixel-art stays crisp and the output bytes are
|
|
16
|
+
* deterministic. The scale is chosen so the longer edge lands near ~256px:
|
|
17
|
+
* - a single 8x8 sprite → scale 32 → 256x256 (see {@link SPRITE_RENDER_SCALE}).
|
|
18
|
+
* - the 128x128 sheet → scale 2 → 256x256 (see {@link SHEET_RENDER_SCALE}).
|
|
19
|
+
*/
|
|
20
|
+
/** Nearest-neighbour scale for a single 8x8 sprite: 8 * 32 = 256px. */
|
|
21
|
+
export const SPRITE_RENDER_SCALE = 32;
|
|
22
|
+
/** Nearest-neighbour scale for the 128x128 spritesheet: 128 * 2 = 256px. */
|
|
23
|
+
export const SHEET_RENDER_SCALE = 2;
|
|
24
|
+
/** The target viewable edge length both scales aim for (~256px). */
|
|
25
|
+
export const RENDER_TARGET_PX = 256;
|
|
26
|
+
/**
|
|
27
|
+
* Renders one sprite (0..255) to a PNG buffer: its 8x8 pixels, each mapped to its
|
|
28
|
+
* palette RGB, nearest-neighbour upscaled by {@link SPRITE_RENDER_SCALE}.
|
|
29
|
+
*/
|
|
30
|
+
export function renderSpritePng(sheet, n) {
|
|
31
|
+
const { x0, y0 } = spriteOrigin(n);
|
|
32
|
+
return encodePng(upscale(SPRITE_SIZE, SPRITE_SIZE, (x, y) => sheet.getPixel(x0 + x, y0 + y), SPRITE_RENDER_SCALE));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Renders the whole 128x128 spritesheet to a PNG buffer: every pixel mapped to
|
|
36
|
+
* its palette RGB, nearest-neighbour upscaled by {@link SHEET_RENDER_SCALE}.
|
|
37
|
+
*/
|
|
38
|
+
export function renderSheetPng(sheet) {
|
|
39
|
+
return encodePng(upscale(GFX_WIDTH, GFX_HEIGHT, (x, y) => sheet.getPixel(x, y), SHEET_RENDER_SCALE));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds an upscaled {@link RgbImage} from a source of colour indices. Each
|
|
43
|
+
* source pixel (`getIndex(x, y)`) is mapped to its palette RGB and painted as a
|
|
44
|
+
* `scale`x`scale` block (nearest-neighbour), producing a `(srcW*scale)` x
|
|
45
|
+
* `(srcH*scale)` RGB buffer.
|
|
46
|
+
*/
|
|
47
|
+
export function upscale(srcWidth, srcHeight, getIndex, scale) {
|
|
48
|
+
if (!Number.isInteger(scale) || scale < 1) {
|
|
49
|
+
throw new RangeError(`upscale factor must be a positive integer, got ${scale}`);
|
|
50
|
+
}
|
|
51
|
+
const width = srcWidth * scale;
|
|
52
|
+
const height = srcHeight * scale;
|
|
53
|
+
const rgb = new Uint8Array(width * height * 3);
|
|
54
|
+
for (let sy = 0; sy < srcHeight; sy++) {
|
|
55
|
+
for (let sx = 0; sx < srcWidth; sx++) {
|
|
56
|
+
const { r, g, b } = paletteColor(getIndex(sx, sy));
|
|
57
|
+
// Paint the scale x scale destination block for this source pixel.
|
|
58
|
+
for (let dy = 0; dy < scale; dy++) {
|
|
59
|
+
const y = sy * scale + dy;
|
|
60
|
+
for (let dx = 0; dx < scale; dx++) {
|
|
61
|
+
const x = sx * scale + dx;
|
|
62
|
+
const off = (y * width + x) * 3;
|
|
63
|
+
rgb[off] = r;
|
|
64
|
+
rgb[off + 1] = g;
|
|
65
|
+
rgb[off + 2] = b;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { width, height, rgb };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/engine/gfx/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The picopilot engine layer: pure codecs and external-tool adapters, kept
|
|
3
|
+
* separate from the incur command layer (`src/commands/`) so commands stay thin
|
|
4
|
+
* and the engine stays independently testable.
|
|
5
|
+
*
|
|
6
|
+
* Modules (one per seam; more added by later tasks):
|
|
7
|
+
*
|
|
8
|
+
* - `engine/cart`: the `.p8` cart model: parse sections, addressable
|
|
9
|
+
* gfx/map regions, byte-identical serialize (this seam).
|
|
10
|
+
* - `engine/gfx`: TS codec: `__gfx__` hex to/from char grid, and hex to PNG.
|
|
11
|
+
* - `engine/audio`: TS codec: picopilot-MML to `__sfx__`, patterns to `__music__`.
|
|
12
|
+
* - `engine/shrinko`: adapter shelling out to the external `shrinko8` tool
|
|
13
|
+
* (token count, lint, minify, p8/lua, spritesheet PNG).
|
|
14
|
+
* - `engine/pico8`: headless run + capture + export (needs the PICO-8 binary).
|
|
15
|
+
*
|
|
16
|
+
* Later tasks re-export from here without restructuring.
|
|
17
|
+
*/
|
|
18
|
+
export * from './audio/index.js';
|
|
19
|
+
export * from './cart/index.js';
|
|
20
|
+
export * from './pico8/index.js';
|
|
21
|
+
export * from './shrinko/index.js';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The picopilot engine layer: pure codecs and external-tool adapters, kept
|
|
3
|
+
* separate from the incur command layer (`src/commands/`) so commands stay thin
|
|
4
|
+
* and the engine stays independently testable.
|
|
5
|
+
*
|
|
6
|
+
* Modules (one per seam; more added by later tasks):
|
|
7
|
+
*
|
|
8
|
+
* - `engine/cart`: the `.p8` cart model: parse sections, addressable
|
|
9
|
+
* gfx/map regions, byte-identical serialize (this seam).
|
|
10
|
+
* - `engine/gfx`: TS codec: `__gfx__` hex to/from char grid, and hex to PNG.
|
|
11
|
+
* - `engine/audio`: TS codec: picopilot-MML to `__sfx__`, patterns to `__music__`.
|
|
12
|
+
* - `engine/shrinko`: adapter shelling out to the external `shrinko8` tool
|
|
13
|
+
* (token count, lint, minify, p8/lua, spritesheet PNG).
|
|
14
|
+
* - `engine/pico8`: headless run + capture + export (needs the PICO-8 binary).
|
|
15
|
+
*
|
|
16
|
+
* Later tasks re-export from here without restructuring.
|
|
17
|
+
*/
|
|
18
|
+
export * from './audio/index.js';
|
|
19
|
+
export * from './cart/index.js';
|
|
20
|
+
export * from './pico8/index.js';
|
|
21
|
+
export * from './shrinko/index.js';
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PICO-8 adapter SEAM: the typed interface `picopilot run` talks to, plus
|
|
3
|
+
* the structured result shapes. Mirrors the `engine/shrinko` seam (ADR-0002):
|
|
4
|
+
* the command layer never knows HOW PICO-8 is launched; it talks to
|
|
5
|
+
* {@link Pico8Adapter}, and PICO-8 being ABSENT is a first-class value
|
|
6
|
+
* (`{ok:false, reason:'pico8-not-found', ...}`), never a throw or a hollow
|
|
7
|
+
* success. The v1 implementation shells out to the user's native `pico8 -x`
|
|
8
|
+
* (see `shell.ts` and ADR-0006, native path first); a future web-export /
|
|
9
|
+
* headless-browser implementation can satisfy the SAME interface.
|
|
10
|
+
*
|
|
11
|
+
* PICO-8 is a licensed, paid binary with no pip/npm install path, so absence is
|
|
12
|
+
* a normal, well-signposted boundary (US #14, #19), mirroring shrinko-not-found.
|
|
13
|
+
*/
|
|
14
|
+
/** The remedy string in a pico8-not-found result: how the user makes `run` work. */
|
|
15
|
+
export declare const PICO8_REMEDY: "set PICO8_PATH or install PICO-8";
|
|
16
|
+
/** What `run` needs: the PICO-8 binary (a paid, licensed download; no package manager). */
|
|
17
|
+
export declare const PICO8_NEEDS: readonly ["pico8"];
|
|
18
|
+
/** The default done-sentinel: the cart prints this via `printh` to signal it is finished. */
|
|
19
|
+
export declare const DONE_SENTINEL: "__PICOPILOT_DONE__";
|
|
20
|
+
/**
|
|
21
|
+
* The structured "PICO-8 is not installed" failure (US #19, ADR-0006). Shape
|
|
22
|
+
* mirrors {@link import('../shrinko/adapter.js').ShrinkoNotFound}: `ok:false`, a
|
|
23
|
+
* machine-readable `reason`, the EXACT `remedy`, and the `needs` list. A command
|
|
24
|
+
* maps it onto incur's `error({ code: reason, ... })` with a nonzero exit.
|
|
25
|
+
*/
|
|
26
|
+
export interface Pico8NotFound {
|
|
27
|
+
readonly ok: false;
|
|
28
|
+
readonly reason: 'pico8-not-found';
|
|
29
|
+
readonly remedy: typeof PICO8_REMEDY;
|
|
30
|
+
readonly needs: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
/** Why a run ended: the cart signalled done, the backstop fired, or PICO-8 exited on its own. */
|
|
33
|
+
export type ExitReason = 'sentinel' | 'timeout' | 'exit';
|
|
34
|
+
/**
|
|
35
|
+
* A completed run's collected results. `screenshots` are the PNG paths PICO-8
|
|
36
|
+
* wrote into the run-controlled `-desktop` dir (via the cart's `extcmd("screen")`);
|
|
37
|
+
* `printh` is the captured stdout (the cart's `printh` output plus PICO-8's own
|
|
38
|
+
* lines); `exitReason` says how it ended.
|
|
39
|
+
*/
|
|
40
|
+
export interface RunReport {
|
|
41
|
+
readonly screenshots: readonly string[];
|
|
42
|
+
readonly printh: string;
|
|
43
|
+
readonly exitReason: ExitReason;
|
|
44
|
+
}
|
|
45
|
+
/** A successful adapter call carrying the run report. */
|
|
46
|
+
export interface Pico8Ok {
|
|
47
|
+
readonly ok: true;
|
|
48
|
+
readonly value: RunReport;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The result {@link Pico8Adapter.run} returns: either a {@link RunReport} or the
|
|
52
|
+
* structured {@link Pico8NotFound}. Absence is a value, not a throw, so the
|
|
53
|
+
* two-tier capability contract is total and type-checked at the call site.
|
|
54
|
+
*/
|
|
55
|
+
export type Pico8Result = Pico8Ok | Pico8NotFound;
|
|
56
|
+
/**
|
|
57
|
+
* A completed audio-RECORDING run's results (ADR-0009). `wavPath` is the WAV the
|
|
58
|
+
* cart wrote via `extcmd("audio_end", 1)` into the run-controlled folder (the
|
|
59
|
+
* `audio_end(1)`-to-current-folder quirk, isolated to a temp `wavDir`), or
|
|
60
|
+
* `undefined` if none was produced (e.g. a headless `-x` capture, which yields a
|
|
61
|
+
* silent 0-frame file we treat as "no usable WAV", or a run that never recorded).
|
|
62
|
+
* `printh` + `exitReason` mirror {@link RunReport}, so a recording is a run with a
|
|
63
|
+
* WAV alongside the same run state.
|
|
64
|
+
*/
|
|
65
|
+
export interface RecordReport {
|
|
66
|
+
readonly wavPath: string | undefined;
|
|
67
|
+
readonly printh: string;
|
|
68
|
+
readonly exitReason: ExitReason;
|
|
69
|
+
}
|
|
70
|
+
/** A successful audio-record call carrying the {@link RecordReport}. */
|
|
71
|
+
export interface Pico8RecordOk {
|
|
72
|
+
readonly ok: true;
|
|
73
|
+
readonly value: RecordReport;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A completed DRIVE run's results (ADR-0011, `playtest`). Same shape family as
|
|
77
|
+
* {@link RunReport}: `screenshots` are the PNGs the driven cart wrote at the SHOT
|
|
78
|
+
* points (named `<basename>0.png`, ...), `printh` is the captured stdout (the
|
|
79
|
+
* cart's ACKs + the done-sentinel + any cart printh), `exitReason` says how it
|
|
80
|
+
* ended. A driven run is a run whose input + frame loop the harness owned.
|
|
81
|
+
*/
|
|
82
|
+
export interface DriveReport {
|
|
83
|
+
readonly screenshots: readonly string[];
|
|
84
|
+
readonly printh: string;
|
|
85
|
+
readonly exitReason: ExitReason;
|
|
86
|
+
}
|
|
87
|
+
/** A successful drive call carrying the {@link DriveReport}. */
|
|
88
|
+
export interface Pico8DriveOk {
|
|
89
|
+
readonly ok: true;
|
|
90
|
+
readonly value: DriveReport;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The result {@link Pico8Adapter.drive} returns: a {@link DriveReport} or the
|
|
94
|
+
* structured {@link Pico8NotFound} (PICO-8 absent), mirroring {@link Pico8Result}.
|
|
95
|
+
*/
|
|
96
|
+
export type Pico8DriveResult = Pico8DriveOk | Pico8NotFound;
|
|
97
|
+
/**
|
|
98
|
+
* Options for a single {@link Pico8Adapter.drive} (ADR-0011). The cart is the
|
|
99
|
+
* THROWAWAY driven cart the drive-transform produced; `blocks` are the encoded
|
|
100
|
+
* FIXED-SIZE command blocks piped to its live `-x` stdin (the load-bearing
|
|
101
|
+
* transport: small unpadded writes coalesce/drop, so the whole block stream is
|
|
102
|
+
* written up front for the one-shot). Screenshots land in `shotDir` (`-desktop`).
|
|
103
|
+
*/
|
|
104
|
+
export interface DriveOptions {
|
|
105
|
+
/** Absolute path to the throwaway driven `.p8` cart to run. */
|
|
106
|
+
readonly cartPath: string;
|
|
107
|
+
/** The run-controlled dir PICO-8 writes screenshots into (`-desktop <dir>`). */
|
|
108
|
+
readonly shotDir: string;
|
|
109
|
+
/** The encoded fixed-size command blocks to pipe to the cart's stdin. */
|
|
110
|
+
readonly blocks: Uint8Array;
|
|
111
|
+
/** The stdout line that ends the run when matched (defaults to {@link DONE_SENTINEL}). */
|
|
112
|
+
readonly sentinel?: string;
|
|
113
|
+
/** The hard backstop in ms: kill PICO-8 if it neither signals nor exits by then. */
|
|
114
|
+
readonly backstopMs: number;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The result {@link Pico8Adapter.record} returns: a {@link RecordReport} or the
|
|
118
|
+
* structured {@link Pico8NotFound} (PICO-8 absent), mirroring {@link Pico8Result}.
|
|
119
|
+
*/
|
|
120
|
+
export type Pico8RecordResult = Pico8RecordOk | Pico8NotFound;
|
|
121
|
+
/**
|
|
122
|
+
* Options for a single {@link Pico8Adapter.record} (ADR-0009). The recorded cart
|
|
123
|
+
* is expected to COOPERATE: at start it does `extcmd("set_filename", <base>)` +
|
|
124
|
+
* `extcmd("audio_rec")`, and when finished `extcmd("audio_end", 1)` (save to the
|
|
125
|
+
* current folder) then `printh` the sentinel. For `audio record <cart>` the
|
|
126
|
+
* caller injects that harness around the user's cart; for `audio render` the
|
|
127
|
+
* whole harness cart is built by {@link import('./harness.js')}.
|
|
128
|
+
*/
|
|
129
|
+
export interface RecordOptions {
|
|
130
|
+
/** Absolute path to the `.p8` cart to run and record. */
|
|
131
|
+
readonly cartPath: string;
|
|
132
|
+
/**
|
|
133
|
+
* The run-controlled folder PICO-8 records the WAV into. Because
|
|
134
|
+
* `extcmd("audio_end", 1)` saves to PICO-8's CURRENT folder (NOT `-desktop`),
|
|
135
|
+
* the adapter points PICO-8's `root_path` here so the WAV lands in an isolated
|
|
136
|
+
* temp dir, never `~/Desktop` or the carts root (the shared-write discipline).
|
|
137
|
+
*/
|
|
138
|
+
readonly wavDir: string;
|
|
139
|
+
/**
|
|
140
|
+
* The base filename (no extension) the cart passed to `extcmd("set_filename")`,
|
|
141
|
+
* so the adapter knows which `<base>.wav` to collect. Defaults to
|
|
142
|
+
* {@link RECORD_WAV_BASENAME} when omitted.
|
|
143
|
+
*/
|
|
144
|
+
readonly wavBasename?: string;
|
|
145
|
+
/** The stdout line that ends the run when matched (defaults to {@link DONE_SENTINEL}). */
|
|
146
|
+
readonly sentinel?: string;
|
|
147
|
+
/** The hard backstop in ms: kill PICO-8 if it neither signals nor exits by then. */
|
|
148
|
+
readonly backstopMs: number;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* A completed EXPORT run's results (the PICO-8 HTML export, `pico8 <cart>
|
|
152
|
+
* -export <name>.html -x`). PICO-8 writes a pair into the output dir: the shell
|
|
153
|
+
* page (`<name>.html`, which references its sibling by name) and the
|
|
154
|
+
* Emscripten runtime + baked-in cart payload (`<name>.js`). `htmlPath` is the
|
|
155
|
+
* shell page (undefined for a payload-only export that keeps only the runtime);
|
|
156
|
+
* `jsPath` is the runtime payload; `files` lists every produced file (absolute).
|
|
157
|
+
* `labelWarning` surfaces PICO-8's "please capture a label first" notice: a
|
|
158
|
+
* labelless cart exports with an ugly/blank splash (a soft warning, not a
|
|
159
|
+
* failure).
|
|
160
|
+
*/
|
|
161
|
+
export interface ExportReport {
|
|
162
|
+
readonly htmlPath: string | undefined;
|
|
163
|
+
readonly jsPath: string | undefined;
|
|
164
|
+
readonly files: readonly string[];
|
|
165
|
+
readonly labelWarning: boolean;
|
|
166
|
+
}
|
|
167
|
+
/** A successful export call carrying the {@link ExportReport}. */
|
|
168
|
+
export interface Pico8ExportOk {
|
|
169
|
+
readonly ok: true;
|
|
170
|
+
readonly value: ExportReport;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The result {@link Pico8Adapter.export} returns: an {@link ExportReport} or the
|
|
174
|
+
* structured {@link Pico8NotFound} (PICO-8 absent), mirroring {@link Pico8Result}.
|
|
175
|
+
*/
|
|
176
|
+
export type Pico8ExportResult = Pico8ExportOk | Pico8NotFound;
|
|
177
|
+
/**
|
|
178
|
+
* Options for a single {@link Pico8Adapter.export}. PICO-8 derives the produced
|
|
179
|
+
* file names from `htmlName` (`game.html` -> `game.html` + `game.js`), so the
|
|
180
|
+
* command passes `index.html` to get a directly-serveable `index.html` +
|
|
181
|
+
* `index.js` pair in `outDir`. `payloadOnly` keeps only the `.js` runtime
|
|
182
|
+
* payload (dropping the shell page) for a website that provides its OWN player
|
|
183
|
+
* shell (a Svelte component), never the PICO-8 binary's concern: the split is a
|
|
184
|
+
* post-export file operation the command owns.
|
|
185
|
+
*/
|
|
186
|
+
export interface ExportOptions {
|
|
187
|
+
/** Absolute path to the `.p8` cart to export. */
|
|
188
|
+
readonly cartPath: string;
|
|
189
|
+
/** The run-controlled dir PICO-8 writes the export pair into. */
|
|
190
|
+
readonly outDir: string;
|
|
191
|
+
/**
|
|
192
|
+
* The `.html` name handed to `-export` (e.g. `index.html`); PICO-8 derives the
|
|
193
|
+
* sibling `.js` from it. Defaults to {@link EXPORT_HTML_NAME}.
|
|
194
|
+
*/
|
|
195
|
+
readonly htmlName?: string;
|
|
196
|
+
/** The hard backstop in ms: kill PICO-8 if the export neither completes nor exits. */
|
|
197
|
+
readonly backstopMs: number;
|
|
198
|
+
}
|
|
199
|
+
/** The default `.html` name `export` hands to `-export`: yields a serveable `index.html` + `index.js`. */
|
|
200
|
+
export declare const EXPORT_HTML_NAME: "index.html";
|
|
201
|
+
/** Options for a single {@link Pico8Adapter.run}. */
|
|
202
|
+
export interface RunOptions {
|
|
203
|
+
/** Absolute path to the `.p8` cart to run. */
|
|
204
|
+
readonly cartPath: string;
|
|
205
|
+
/** The run-controlled dir PICO-8 writes screenshots into (`-desktop <dir>`). */
|
|
206
|
+
readonly shotDir: string;
|
|
207
|
+
/** The stdout line that ends the run when matched (defaults to {@link DONE_SENTINEL}). */
|
|
208
|
+
readonly sentinel?: string;
|
|
209
|
+
/** The hard backstop in ms: kill PICO-8 if it neither signals nor exits by then. */
|
|
210
|
+
readonly backstopMs: number;
|
|
211
|
+
/**
|
|
212
|
+
* Optional one-shot scripted input passed as `-p <input>`; the cart reads it
|
|
213
|
+
* via `stat(6)` and replays it (the canned-playtest channel). The cart must
|
|
214
|
+
* cooperate by decoding `stat(6)` (taught in the `picopilot-debug` skill).
|
|
215
|
+
* Absent = no input passed.
|
|
216
|
+
*/
|
|
217
|
+
readonly input?: string;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The PICO-8 capability seam. One method for now: {@link run}. Later PICO-8-gated
|
|
221
|
+
* operations (`audio render`, `export`) extend THIS interface rather than forking.
|
|
222
|
+
*/
|
|
223
|
+
export interface Pico8Adapter {
|
|
224
|
+
/**
|
|
225
|
+
* Launches PICO-8 on `cartPath`, streams stdout, ends the run on the sentinel
|
|
226
|
+
* (with the backstop as the safety net), and collects screenshots + printh +
|
|
227
|
+
* exit reason. Returns {@link Pico8NotFound} when PICO-8 is not installed.
|
|
228
|
+
*/
|
|
229
|
+
run(options: RunOptions): Promise<Pico8Result>;
|
|
230
|
+
/**
|
|
231
|
+
* Launches PICO-8 on `cartPath` in a REAL audio+video session (NOT headless
|
|
232
|
+
* `-x`, which mixes no audio and yields an empty WAV, ADR-0009), streams
|
|
233
|
+
* stdout, ends on the sentinel (backstop as the net), and collects the WAV the
|
|
234
|
+
* cooperating cart wrote via `audio_rec`/`audio_end(1)`. Returns
|
|
235
|
+
* {@link Pico8NotFound} when PICO-8 is not installed. Live capture is a
|
|
236
|
+
* manual/opt-in tier; CI drives a fake runner + the absent boundary.
|
|
237
|
+
*/
|
|
238
|
+
record(options: RecordOptions): Promise<Pico8RecordResult>;
|
|
239
|
+
/**
|
|
240
|
+
* Launches PICO-8 on the THROWAWAY driven cart (`-desktop <shotDir> -x`),
|
|
241
|
+
* pipes the encoded FIXED-SIZE command blocks to its live stdin (the input +
|
|
242
|
+
* frame-loop transport, ADR-0011), ends on the sentinel (backstop as the net),
|
|
243
|
+
* and collects the SHOT screenshots + printh + exit reason. Returns
|
|
244
|
+
* {@link Pico8NotFound} when PICO-8 is absent. Live drive-and-capture is a
|
|
245
|
+
* manual/opt-in tier; CI drives a fake runner + the absent boundary.
|
|
246
|
+
*/
|
|
247
|
+
drive(options: DriveOptions): Promise<Pico8DriveResult>;
|
|
248
|
+
/**
|
|
249
|
+
* Exports `cartPath` as a PICO-8 HTML bundle (`pico8 <cart> -export
|
|
250
|
+
* <outDir>/<htmlName> -x`, the HEADLESS `-x` path, no display needed) and
|
|
251
|
+
* collects the produced `.html` + `.js` pair from `outDir`. Returns
|
|
252
|
+
* {@link Pico8NotFound} when PICO-8 is absent (the CI-testable boundary). Live
|
|
253
|
+
* export is a manual/opt-in tier: it hard-requires the paid binary, and a
|
|
254
|
+
* labelless cart exports with a `labelWarning` set (a soft warning, not a
|
|
255
|
+
* failure). The command owns any post-export payload-only file split.
|
|
256
|
+
*/
|
|
257
|
+
export(options: ExportOptions): Promise<Pico8ExportResult>;
|
|
258
|
+
}
|
|
259
|
+
/** The default WAV basename a recorded cart passes to `extcmd("set_filename")`. */
|
|
260
|
+
export declare const RECORD_WAV_BASENAME: "picopilot-audio";
|
|
261
|
+
/** The 60 audio ticks PICO-8 advances per second: the record-duration unit (finding). */
|
|
262
|
+
export declare const PICO8_TICKS_PER_SECOND = 120;
|
|
263
|
+
/** The video frames PICO-8 runs per second (`_update` at 30fps; `t` counts frames). */
|
|
264
|
+
export declare const PICO8_FRAMES_PER_SECOND = 30;
|
|
265
|
+
/** The frozen {@link Pico8NotFound} value, so every call site returns the same shape. */
|
|
266
|
+
export declare function pico8NotFound(): Pico8NotFound;
|
|
267
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/engine/pico8/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PICO-8 adapter SEAM: the typed interface `picopilot run` talks to, plus
|
|
3
|
+
* the structured result shapes. Mirrors the `engine/shrinko` seam (ADR-0002):
|
|
4
|
+
* the command layer never knows HOW PICO-8 is launched; it talks to
|
|
5
|
+
* {@link Pico8Adapter}, and PICO-8 being ABSENT is a first-class value
|
|
6
|
+
* (`{ok:false, reason:'pico8-not-found', ...}`), never a throw or a hollow
|
|
7
|
+
* success. The v1 implementation shells out to the user's native `pico8 -x`
|
|
8
|
+
* (see `shell.ts` and ADR-0006, native path first); a future web-export /
|
|
9
|
+
* headless-browser implementation can satisfy the SAME interface.
|
|
10
|
+
*
|
|
11
|
+
* PICO-8 is a licensed, paid binary with no pip/npm install path, so absence is
|
|
12
|
+
* a normal, well-signposted boundary (US #14, #19), mirroring shrinko-not-found.
|
|
13
|
+
*/
|
|
14
|
+
/** The remedy string in a pico8-not-found result: how the user makes `run` work. */
|
|
15
|
+
export const PICO8_REMEDY = 'set PICO8_PATH or install PICO-8';
|
|
16
|
+
/** What `run` needs: the PICO-8 binary (a paid, licensed download; no package manager). */
|
|
17
|
+
export const PICO8_NEEDS = ['pico8'];
|
|
18
|
+
/** The default done-sentinel: the cart prints this via `printh` to signal it is finished. */
|
|
19
|
+
export const DONE_SENTINEL = '__PICOPILOT_DONE__';
|
|
20
|
+
/** The default `.html` name `export` hands to `-export`: yields a serveable `index.html` + `index.js`. */
|
|
21
|
+
export const EXPORT_HTML_NAME = 'index.html';
|
|
22
|
+
/** The default WAV basename a recorded cart passes to `extcmd("set_filename")`. */
|
|
23
|
+
export const RECORD_WAV_BASENAME = 'picopilot-audio';
|
|
24
|
+
/** The 60 audio ticks PICO-8 advances per second: the record-duration unit (finding). */
|
|
25
|
+
export const PICO8_TICKS_PER_SECOND = 120;
|
|
26
|
+
/** The video frames PICO-8 runs per second (`_update` at 30fps; `t` counts frames). */
|
|
27
|
+
export const PICO8_FRAMES_PER_SECOND = 30;
|
|
28
|
+
/** The frozen {@link Pico8NotFound} value, so every call site returns the same shape. */
|
|
29
|
+
export function pico8NotFound() {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
reason: 'pico8-not-found',
|
|
33
|
+
remedy: PICO8_REMEDY,
|
|
34
|
+
needs: [...PICO8_NEEDS],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/engine/pico8/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,kCAA2C,CAAC;AAExE,2FAA2F;AAC3F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAO,CAAU,CAAC;AAE9C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,aAAa,GAAG,oBAA6B,CAAC;AAsM3D,0GAA0G;AAC1G,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAqB,CAAC;AAiEtD,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAA0B,CAAC;AAE9D,yFAAyF;AACzF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,yFAAyF;AACzF,MAAM,UAAU,aAAa;IAC5B,OAAO;QACN,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,iBAAiB;QACzB,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC;KACvB,CAAC;AACH,CAAC"}
|