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.
Files changed (334) hide show
  1. package/LICENSE +661 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +4 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/cli.d.ts +15 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +59 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/audio.d.ts +17 -0
  11. package/dist/commands/audio.d.ts.map +1 -0
  12. package/dist/commands/audio.js +315 -0
  13. package/dist/commands/audio.js.map +1 -0
  14. package/dist/commands/export.d.ts +36 -0
  15. package/dist/commands/export.d.ts.map +1 -0
  16. package/dist/commands/export.js +257 -0
  17. package/dist/commands/export.js.map +1 -0
  18. package/dist/commands/gfx.d.ts +28 -0
  19. package/dist/commands/gfx.d.ts.map +1 -0
  20. package/dist/commands/gfx.js +521 -0
  21. package/dist/commands/gfx.js.map +1 -0
  22. package/dist/commands/init.d.ts +34 -0
  23. package/dist/commands/init.d.ts.map +1 -0
  24. package/dist/commands/init.js +151 -0
  25. package/dist/commands/init.js.map +1 -0
  26. package/dist/commands/lint.d.ts +20 -0
  27. package/dist/commands/lint.d.ts.map +1 -0
  28. package/dist/commands/lint.js +90 -0
  29. package/dist/commands/lint.js.map +1 -0
  30. package/dist/commands/minify.d.ts +20 -0
  31. package/dist/commands/minify.d.ts.map +1 -0
  32. package/dist/commands/minify.js +129 -0
  33. package/dist/commands/minify.js.map +1 -0
  34. package/dist/commands/music.d.ts +13 -0
  35. package/dist/commands/music.d.ts.map +1 -0
  36. package/dist/commands/music.js +241 -0
  37. package/dist/commands/music.js.map +1 -0
  38. package/dist/commands/playtest.d.ts +29 -0
  39. package/dist/commands/playtest.d.ts.map +1 -0
  40. package/dist/commands/playtest.js +631 -0
  41. package/dist/commands/playtest.js.map +1 -0
  42. package/dist/commands/run.d.ts +30 -0
  43. package/dist/commands/run.d.ts.map +1 -0
  44. package/dist/commands/run.js +224 -0
  45. package/dist/commands/run.js.map +1 -0
  46. package/dist/commands/serve.d.ts +50 -0
  47. package/dist/commands/serve.d.ts.map +1 -0
  48. package/dist/commands/serve.js +213 -0
  49. package/dist/commands/serve.js.map +1 -0
  50. package/dist/commands/sfx.d.ts +13 -0
  51. package/dist/commands/sfx.d.ts.map +1 -0
  52. package/dist/commands/sfx.js +254 -0
  53. package/dist/commands/sfx.js.map +1 -0
  54. package/dist/commands/tokens.d.ts +36 -0
  55. package/dist/commands/tokens.d.ts.map +1 -0
  56. package/dist/commands/tokens.js +129 -0
  57. package/dist/commands/tokens.js.map +1 -0
  58. package/dist/commands/verify.d.ts +57 -0
  59. package/dist/commands/verify.d.ts.map +1 -0
  60. package/dist/commands/verify.js +213 -0
  61. package/dist/commands/verify.js.map +1 -0
  62. package/dist/commands/version.d.ts +12 -0
  63. package/dist/commands/version.d.ts.map +1 -0
  64. package/dist/commands/version.js +24 -0
  65. package/dist/commands/version.js.map +1 -0
  66. package/dist/engine/audio/index.d.ts +14 -0
  67. package/dist/engine/audio/index.d.ts.map +1 -0
  68. package/dist/engine/audio/index.js +14 -0
  69. package/dist/engine/audio/index.js.map +1 -0
  70. package/dist/engine/audio/music.d.ts +116 -0
  71. package/dist/engine/audio/music.d.ts.map +1 -0
  72. package/dist/engine/audio/music.js +138 -0
  73. package/dist/engine/audio/music.js.map +1 -0
  74. package/dist/engine/audio/section.d.ts +34 -0
  75. package/dist/engine/audio/section.d.ts.map +1 -0
  76. package/dist/engine/audio/section.js +67 -0
  77. package/dist/engine/audio/section.js.map +1 -0
  78. package/dist/engine/audio/sfx.d.ts +141 -0
  79. package/dist/engine/audio/sfx.d.ts.map +1 -0
  80. package/dist/engine/audio/sfx.js +506 -0
  81. package/dist/engine/audio/sfx.js.map +1 -0
  82. package/dist/engine/cart/cart.d.ts +75 -0
  83. package/dist/engine/cart/cart.d.ts.map +1 -0
  84. package/dist/engine/cart/cart.js +153 -0
  85. package/dist/engine/cart/cart.js.map +1 -0
  86. package/dist/engine/cart/errors.d.ts +29 -0
  87. package/dist/engine/cart/errors.d.ts.map +1 -0
  88. package/dist/engine/cart/errors.js +26 -0
  89. package/dist/engine/cart/errors.js.map +1 -0
  90. package/dist/engine/cart/gfx.d.ts +79 -0
  91. package/dist/engine/cart/gfx.d.ts.map +1 -0
  92. package/dist/engine/cart/gfx.js +171 -0
  93. package/dist/engine/cart/gfx.js.map +1 -0
  94. package/dist/engine/cart/index.d.ts +15 -0
  95. package/dist/engine/cart/index.d.ts.map +1 -0
  96. package/dist/engine/cart/index.js +15 -0
  97. package/dist/engine/cart/index.js.map +1 -0
  98. package/dist/engine/cart/map.d.ts +46 -0
  99. package/dist/engine/cart/map.d.ts.map +1 -0
  100. package/dist/engine/cart/map.js +118 -0
  101. package/dist/engine/cart/map.js.map +1 -0
  102. package/dist/engine/config/config.d.ts +74 -0
  103. package/dist/engine/config/config.d.ts.map +1 -0
  104. package/dist/engine/config/config.js +103 -0
  105. package/dist/engine/config/config.js.map +1 -0
  106. package/dist/engine/config/index.d.ts +7 -0
  107. package/dist/engine/config/index.d.ts.map +1 -0
  108. package/dist/engine/config/index.js +7 -0
  109. package/dist/engine/config/index.js.map +1 -0
  110. package/dist/engine/gfx/grid.d.ts +51 -0
  111. package/dist/engine/gfx/grid.d.ts.map +1 -0
  112. package/dist/engine/gfx/grid.js +116 -0
  113. package/dist/engine/gfx/grid.js.map +1 -0
  114. package/dist/engine/gfx/index.d.ts +17 -0
  115. package/dist/engine/gfx/index.d.ts.map +1 -0
  116. package/dist/engine/gfx/index.js +17 -0
  117. package/dist/engine/gfx/index.js.map +1 -0
  118. package/dist/engine/gfx/label.d.ts +34 -0
  119. package/dist/engine/gfx/label.d.ts.map +1 -0
  120. package/dist/engine/gfx/label.js +190 -0
  121. package/dist/engine/gfx/label.js.map +1 -0
  122. package/dist/engine/gfx/overlap.d.ts +42 -0
  123. package/dist/engine/gfx/overlap.d.ts.map +1 -0
  124. package/dist/engine/gfx/overlap.js +57 -0
  125. package/dist/engine/gfx/overlap.js.map +1 -0
  126. package/dist/engine/gfx/palette.d.ts +29 -0
  127. package/dist/engine/gfx/palette.d.ts.map +1 -0
  128. package/dist/engine/gfx/palette.js +46 -0
  129. package/dist/engine/gfx/palette.js.map +1 -0
  130. package/dist/engine/gfx/png.d.ts +31 -0
  131. package/dist/engine/gfx/png.d.ts.map +1 -0
  132. package/dist/engine/gfx/png.js +165 -0
  133. package/dist/engine/gfx/png.js.map +1 -0
  134. package/dist/engine/gfx/render.d.ts +42 -0
  135. package/dist/engine/gfx/render.d.ts.map +1 -0
  136. package/dist/engine/gfx/render.js +72 -0
  137. package/dist/engine/gfx/render.js.map +1 -0
  138. package/dist/engine/index.d.ts +22 -0
  139. package/dist/engine/index.d.ts.map +1 -0
  140. package/dist/engine/index.js +22 -0
  141. package/dist/engine/index.js.map +1 -0
  142. package/dist/engine/pico8/adapter.d.ts +267 -0
  143. package/dist/engine/pico8/adapter.d.ts.map +1 -0
  144. package/dist/engine/pico8/adapter.js +37 -0
  145. package/dist/engine/pico8/adapter.js.map +1 -0
  146. package/dist/engine/pico8/drive.d.ts +308 -0
  147. package/dist/engine/pico8/drive.d.ts.map +1 -0
  148. package/dist/engine/pico8/drive.js +581 -0
  149. package/dist/engine/pico8/drive.js.map +1 -0
  150. package/dist/engine/pico8/harness.d.ts +146 -0
  151. package/dist/engine/pico8/harness.d.ts.map +1 -0
  152. package/dist/engine/pico8/harness.js +251 -0
  153. package/dist/engine/pico8/harness.js.map +1 -0
  154. package/dist/engine/pico8/index.d.ts +21 -0
  155. package/dist/engine/pico8/index.d.ts.map +1 -0
  156. package/dist/engine/pico8/index.js +21 -0
  157. package/dist/engine/pico8/index.js.map +1 -0
  158. package/dist/engine/pico8/sentinel.d.ts +63 -0
  159. package/dist/engine/pico8/sentinel.d.ts.map +1 -0
  160. package/dist/engine/pico8/sentinel.js +86 -0
  161. package/dist/engine/pico8/sentinel.js.map +1 -0
  162. package/dist/engine/pico8/session-daemon-entry.d.ts +10 -0
  163. package/dist/engine/pico8/session-daemon-entry.d.ts.map +1 -0
  164. package/dist/engine/pico8/session-daemon-entry.js +11 -0
  165. package/dist/engine/pico8/session-daemon-entry.js.map +1 -0
  166. package/dist/engine/pico8/session-daemon-main.d.ts +44 -0
  167. package/dist/engine/pico8/session-daemon-main.d.ts.map +1 -0
  168. package/dist/engine/pico8/session-daemon-main.js +71 -0
  169. package/dist/engine/pico8/session-daemon-main.js.map +1 -0
  170. package/dist/engine/pico8/session-daemon.d.ts +68 -0
  171. package/dist/engine/pico8/session-daemon.d.ts.map +1 -0
  172. package/dist/engine/pico8/session-daemon.js +264 -0
  173. package/dist/engine/pico8/session-daemon.js.map +1 -0
  174. package/dist/engine/pico8/session.d.ts +140 -0
  175. package/dist/engine/pico8/session.d.ts.map +1 -0
  176. package/dist/engine/pico8/session.js +250 -0
  177. package/dist/engine/pico8/session.js.map +1 -0
  178. package/dist/engine/pico8/shell.d.ts +103 -0
  179. package/dist/engine/pico8/shell.d.ts.map +1 -0
  180. package/dist/engine/pico8/shell.js +324 -0
  181. package/dist/engine/pico8/shell.js.map +1 -0
  182. package/dist/engine/pico8/supervisor.d.ts +137 -0
  183. package/dist/engine/pico8/supervisor.d.ts.map +1 -0
  184. package/dist/engine/pico8/supervisor.js +140 -0
  185. package/dist/engine/pico8/supervisor.js.map +1 -0
  186. package/dist/engine/scaffold/index.d.ts +8 -0
  187. package/dist/engine/scaffold/index.d.ts.map +1 -0
  188. package/dist/engine/scaffold/index.js +8 -0
  189. package/dist/engine/scaffold/index.js.map +1 -0
  190. package/dist/engine/scaffold/scaffold.d.ts +49 -0
  191. package/dist/engine/scaffold/scaffold.d.ts.map +1 -0
  192. package/dist/engine/scaffold/scaffold.js +259 -0
  193. package/dist/engine/scaffold/scaffold.js.map +1 -0
  194. package/dist/engine/shrinko/adapter.d.ts +167 -0
  195. package/dist/engine/shrinko/adapter.d.ts.map +1 -0
  196. package/dist/engine/shrinko/adapter.js +107 -0
  197. package/dist/engine/shrinko/adapter.js.map +1 -0
  198. package/dist/engine/shrinko/index.d.ts +13 -0
  199. package/dist/engine/shrinko/index.d.ts.map +1 -0
  200. package/dist/engine/shrinko/index.js +13 -0
  201. package/dist/engine/shrinko/index.js.map +1 -0
  202. package/dist/engine/shrinko/shell.d.ts +69 -0
  203. package/dist/engine/shrinko/shell.d.ts.map +1 -0
  204. package/dist/engine/shrinko/shell.js +156 -0
  205. package/dist/engine/shrinko/shell.js.map +1 -0
  206. package/dist/engine/skills/index.d.ts +8 -0
  207. package/dist/engine/skills/index.d.ts.map +1 -0
  208. package/dist/engine/skills/index.js +8 -0
  209. package/dist/engine/skills/index.js.map +1 -0
  210. package/dist/engine/skills/skills.d.ts +104 -0
  211. package/dist/engine/skills/skills.d.ts.map +1 -0
  212. package/dist/engine/skills/skills.js +149 -0
  213. package/dist/engine/skills/skills.js.map +1 -0
  214. package/dist/index.d.ts +10 -0
  215. package/dist/index.d.ts.map +1 -0
  216. package/dist/index.js +10 -0
  217. package/dist/index.js.map +1 -0
  218. package/dist/version.d.ts +2 -0
  219. package/dist/version.d.ts.map +1 -0
  220. package/dist/version.js +19 -0
  221. package/dist/version.js.map +1 -0
  222. package/package.json +48 -2
  223. package/src/bin.ts +4 -0
  224. package/src/cli.ts +61 -0
  225. package/src/commands/audio.test.ts +280 -0
  226. package/src/commands/audio.ts +410 -0
  227. package/src/commands/export.test.ts +310 -0
  228. package/src/commands/export.ts +316 -0
  229. package/src/commands/gfx-io.test.ts +178 -0
  230. package/src/commands/gfx.test.ts +470 -0
  231. package/src/commands/gfx.ts +645 -0
  232. package/src/commands/init.test.ts +482 -0
  233. package/src/commands/init.ts +193 -0
  234. package/src/commands/lint.test.ts +137 -0
  235. package/src/commands/lint.ts +117 -0
  236. package/src/commands/minify.test.ts +166 -0
  237. package/src/commands/minify.ts +156 -0
  238. package/src/commands/music.test.ts +272 -0
  239. package/src/commands/music.ts +288 -0
  240. package/src/commands/playtest.test.ts +317 -0
  241. package/src/commands/playtest.ts +773 -0
  242. package/src/commands/run.test.ts +264 -0
  243. package/src/commands/run.ts +285 -0
  244. package/src/commands/serve.test.ts +227 -0
  245. package/src/commands/serve.ts +272 -0
  246. package/src/commands/sfx.test.ts +349 -0
  247. package/src/commands/sfx.ts +300 -0
  248. package/src/commands/tokens.test.ts +212 -0
  249. package/src/commands/tokens.ts +168 -0
  250. package/src/commands/verify.test.ts +238 -0
  251. package/src/commands/verify.ts +256 -0
  252. package/src/commands/version.test.ts +70 -0
  253. package/src/commands/version.ts +24 -0
  254. package/src/engine/audio/index.ts +47 -0
  255. package/src/engine/audio/music.test.ts +188 -0
  256. package/src/engine/audio/music.ts +218 -0
  257. package/src/engine/audio/section.test.ts +124 -0
  258. package/src/engine/audio/section.ts +79 -0
  259. package/src/engine/audio/sfx.test.ts +410 -0
  260. package/src/engine/audio/sfx.ts +694 -0
  261. package/src/engine/cart/cart.test.ts +304 -0
  262. package/src/engine/cart/cart.ts +211 -0
  263. package/src/engine/cart/errors.ts +39 -0
  264. package/src/engine/cart/fixtures/crlf.p8 +6 -0
  265. package/src/engine/cart/fixtures/full.p8 +174 -0
  266. package/src/engine/cart/fixtures/header-only.p8 +2 -0
  267. package/src/engine/cart/fixtures/malformed-no-header.p8 +2 -0
  268. package/src/engine/cart/fixtures/minimal.p8 +10 -0
  269. package/src/engine/cart/fixtures/no-trailing-newline.p8 +6 -0
  270. package/src/engine/cart/gfx.ts +195 -0
  271. package/src/engine/cart/index.ts +27 -0
  272. package/src/engine/cart/map.ts +134 -0
  273. package/src/engine/config/config.ts +115 -0
  274. package/src/engine/config/index.ts +12 -0
  275. package/src/engine/gfx/grid.test.ts +128 -0
  276. package/src/engine/gfx/grid.ts +136 -0
  277. package/src/engine/gfx/index.ts +34 -0
  278. package/src/engine/gfx/label.test.ts +105 -0
  279. package/src/engine/gfx/label.ts +229 -0
  280. package/src/engine/gfx/overlap.test.ts +71 -0
  281. package/src/engine/gfx/overlap.ts +66 -0
  282. package/src/engine/gfx/palette.test.ts +35 -0
  283. package/src/engine/gfx/palette.ts +54 -0
  284. package/src/engine/gfx/png.test.ts +111 -0
  285. package/src/engine/gfx/png.ts +196 -0
  286. package/src/engine/gfx/render.test.ts +180 -0
  287. package/src/engine/gfx/render.ts +106 -0
  288. package/src/engine/index.ts +21 -0
  289. package/src/engine/pico8/adapter.ts +303 -0
  290. package/src/engine/pico8/drive.test.ts +415 -0
  291. package/src/engine/pico8/drive.ts +729 -0
  292. package/src/engine/pico8/harness.test.ts +181 -0
  293. package/src/engine/pico8/harness.ts +354 -0
  294. package/src/engine/pico8/index.ts +20 -0
  295. package/src/engine/pico8/sentinel.test.ts +80 -0
  296. package/src/engine/pico8/sentinel.ts +93 -0
  297. package/src/engine/pico8/session-daemon-entry.ts +12 -0
  298. package/src/engine/pico8/session-daemon-main.ts +98 -0
  299. package/src/engine/pico8/session-daemon.test.ts +212 -0
  300. package/src/engine/pico8/session-daemon.ts +306 -0
  301. package/src/engine/pico8/session.test.ts +239 -0
  302. package/src/engine/pico8/session.ts +321 -0
  303. package/src/engine/pico8/shell.test.ts +583 -0
  304. package/src/engine/pico8/shell.ts +412 -0
  305. package/src/engine/pico8/supervisor.test.ts +105 -0
  306. package/src/engine/pico8/supervisor.ts +197 -0
  307. package/src/engine/scaffold/index.ts +15 -0
  308. package/src/engine/scaffold/scaffold.ts +278 -0
  309. package/src/engine/shrinko/adapter.ts +241 -0
  310. package/src/engine/shrinko/fixtures/count-no-compressed.txt +2 -0
  311. package/src/engine/shrinko/fixtures/count-over-budget.txt +3 -0
  312. package/src/engine/shrinko/fixtures/count-under-budget.txt +3 -0
  313. package/src/engine/shrinko/index.ts +33 -0
  314. package/src/engine/shrinko/shell.ts +224 -0
  315. package/src/engine/shrinko/shrinko.test.ts +182 -0
  316. package/src/engine/skills/index.ts +14 -0
  317. package/src/engine/skills/skills.test.ts +376 -0
  318. package/src/engine/skills/skills.ts +205 -0
  319. package/src/index.ts +13 -0
  320. package/src/skills/game-design-reference/SKILL.md +70 -0
  321. package/src/skills/game-jam/SKILL.md +45 -0
  322. package/src/skills/picopilot-art/SKILL.md +62 -0
  323. package/src/skills/picopilot-audio/SKILL.md +194 -0
  324. package/src/skills/picopilot-code/SKILL.md +97 -0
  325. package/src/skills/picopilot-code/reference/README.md +42 -0
  326. package/src/skills/picopilot-code/reference/mode7-racing.md +95 -0
  327. package/src/skills/picopilot-code/reference/platformer.md +119 -0
  328. package/src/skills/picopilot-code/reference/puzzle-grid.md +106 -0
  329. package/src/skills/picopilot-code/reference/rpg-menus-dialog.md +122 -0
  330. package/src/skills/picopilot-code/reference/top-down-adventure.md +117 -0
  331. package/src/skills/picopilot-code/reference/twin-stick-arcade.md +128 -0
  332. package/src/skills/picopilot-debug/SKILL.md +195 -0
  333. package/src/skills/picopilot-overview/SKILL.md +52 -0
  334. 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"}