@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.
Files changed (343) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/NOTICE.md +105 -3
  3. package/README.md +301 -15
  4. package/dist/audio-files.js +82 -0
  5. package/dist/audio.js +23 -138
  6. package/dist/block-merge.js +43 -0
  7. package/dist/color-reduce.js +44 -0
  8. package/dist/colors.js +87 -0
  9. package/dist/delta.js +75 -0
  10. package/dist/disk-diff.js +220 -0
  11. package/dist/drawing.js +83 -869
  12. package/dist/embroidery/compile.js +85 -0
  13. package/dist/embroidery/dst.js +79 -0
  14. package/dist/embroidery/exp.js +26 -0
  15. package/dist/embroidery/fill.js +49 -0
  16. package/dist/embroidery/geom.js +82 -0
  17. package/dist/embroidery/pes.js +79 -0
  18. package/dist/embroidery/satin.js +29 -0
  19. package/dist/embroidery/simulate.js +30 -0
  20. package/dist/embroidery/strokeFont.js +253 -0
  21. package/dist/embroidery/svg.js +24 -0
  22. package/dist/embroidery/types.js +13 -0
  23. package/dist/embroidery/units.js +26 -0
  24. package/dist/embroidery/validate.js +15 -0
  25. package/dist/formats/blocks.js +1 -103
  26. package/dist/formats/character.js +1 -83
  27. package/dist/formats/cmf.js +1 -37
  28. package/dist/formats/fli.js +1 -296
  29. package/dist/formats/fliLimits.js +1 -54
  30. package/dist/formats/game.js +1 -193
  31. package/dist/formats/gif.js +1 -125
  32. package/dist/formats/graphicScripts.js +1 -44
  33. package/dist/formats/map.js +1 -38
  34. package/dist/formats/monster.js +1 -69
  35. package/dist/formats/palette.js +1 -58
  36. package/dist/formats/recording.js +1 -17
  37. package/dist/formats/sound.js +1 -44
  38. package/dist/formats/voc.js +1 -303
  39. package/dist/gif-shrink.js +56 -0
  40. package/dist/image/png.js +42 -0
  41. package/dist/images.js +81 -43
  42. package/dist/kit/actors.js +19 -0
  43. package/dist/kit/align.js +204 -0
  44. package/dist/kit/blit.js +45 -0
  45. package/dist/kit/blockRoles.js +97 -0
  46. package/dist/kit/clips.js +40 -0
  47. package/dist/kit/coverPaint.js +18 -0
  48. package/dist/kit/disk.js +76 -0
  49. package/dist/kit/fadeOut.js +13 -0
  50. package/dist/kit/fliClips.js +133 -0
  51. package/dist/kit/fliShrink.js +277 -0
  52. package/dist/kit/gameSim.js +235 -0
  53. package/dist/kit/hopBot.js +142 -0
  54. package/dist/kit/levelGen.js +1423 -0
  55. package/dist/kit/levelGrid.js +33 -0
  56. package/dist/kit/levelPicture.js +27 -0
  57. package/dist/kit/menuVersion.js +19 -0
  58. package/dist/kit/microText.js +35 -0
  59. package/dist/kit/mumble.js +74 -0
  60. package/dist/kit/music.js +8 -0
  61. package/dist/kit/palRamps.js +32 -0
  62. package/dist/kit/palette.js +49 -0
  63. package/dist/kit/pcText.js +72 -0
  64. package/dist/kit/photo.js +150 -0
  65. package/dist/kit/pixels.js +79 -0
  66. package/dist/kit/png.js +40 -0
  67. package/dist/kit/quantize.js +72 -0
  68. package/dist/kit/raytrace.js +379 -0
  69. package/dist/kit/recordedDemo.js +10 -0
  70. package/dist/kit/reel.js +77 -0
  71. package/dist/kit/road3d.js +67 -0
  72. package/dist/kit/routeChecks.js +8 -0
  73. package/dist/kit/saveSlots.js +11 -0
  74. package/dist/kit/sceneInit.js +13 -0
  75. package/dist/kit/sceneSim.js +112 -0
  76. package/dist/kit/screenText.js +15 -0
  77. package/dist/kit/sdftext.js +237 -0
  78. package/dist/kit/shading.js +69 -0
  79. package/dist/kit/song.js +251 -0
  80. package/dist/kit/songFx.js +179 -0
  81. package/dist/kit/sound.js +52 -0
  82. package/dist/kit/synthParts.js +20 -0
  83. package/dist/kit/tar.js +53 -0
  84. package/dist/kit/textBounds.js +84 -0
  85. package/dist/kit/textfit.js +246 -0
  86. package/dist/kit/transforms.js +57 -0
  87. package/dist/kit/tune.js +21 -0
  88. package/dist/look-alike.js +50 -0
  89. package/dist/menu-version.js +4 -0
  90. package/dist/mesh/colorBodies.js +137 -0
  91. package/dist/mesh/decimate.js +207 -0
  92. package/dist/mesh/meshCheck.js +51 -0
  93. package/dist/mesh/overhang.js +41 -0
  94. package/dist/mesh/sampledField.js +12 -0
  95. package/dist/mesh/stl.js +36 -0
  96. package/dist/mesh/surfaceNets.js +79 -0
  97. package/dist/mesh/tetraMesh.js +62 -0
  98. package/dist/mesh/threeMf.js +58 -0
  99. package/dist/mesh/zipFile.js +52 -0
  100. package/dist/microFont.js +101 -0
  101. package/dist/music/compose.js +72 -0
  102. package/dist/pack/meshPack.js +198 -0
  103. package/dist/pack/threeMfPack.js +92 -0
  104. package/dist/palette-reserve.js +116 -0
  105. package/dist/palettes.js +138 -0
  106. package/dist/release-notes.js +40 -0
  107. package/dist/simulation.js +16 -2774
  108. package/dist/text.js +74 -0
  109. package/dist/types/audio.d.ts +4 -0
  110. package/dist/types/audioFiles.d.ts +22 -0
  111. package/dist/types/audioWav.d.ts +4 -0
  112. package/dist/types/blockMerge.d.ts +24 -0
  113. package/dist/types/colorReduce.d.ts +23 -0
  114. package/dist/types/{web/packages/tools/src/colors.d.ts → colors.d.ts} +6 -0
  115. package/dist/types/delta.d.ts +32 -0
  116. package/dist/types/diskDiff.d.ts +47 -0
  117. package/dist/types/drawing.d.ts +15 -0
  118. package/dist/types/embroidery/compile.d.ts +3 -0
  119. package/dist/types/embroidery/dst.d.ts +13 -0
  120. package/dist/types/embroidery/exp.d.ts +8 -0
  121. package/dist/types/embroidery/fill.d.ts +6 -0
  122. package/dist/types/embroidery/geom.d.ts +19 -0
  123. package/dist/types/embroidery/pes.d.ts +10 -0
  124. package/dist/types/embroidery/satin.d.ts +11 -0
  125. package/dist/types/embroidery/simulate.d.ts +19 -0
  126. package/dist/types/embroidery/strokeFont.d.ts +20 -0
  127. package/dist/types/embroidery/svg.d.ts +3 -0
  128. package/dist/types/embroidery/types.d.ts +70 -0
  129. package/dist/types/embroidery/units.d.ts +10 -0
  130. package/dist/types/embroidery/validate.d.ts +22 -0
  131. package/dist/types/formats/blocks.d.ts +1 -0
  132. package/dist/types/formats/character.d.ts +1 -0
  133. package/dist/types/formats/cmf.d.ts +1 -0
  134. package/dist/types/formats/fli.d.ts +1 -0
  135. package/dist/types/formats/fliLimits.d.ts +1 -0
  136. package/dist/types/formats/game.d.ts +1 -0
  137. package/dist/types/formats/gif.d.ts +1 -0
  138. package/dist/types/formats/graphicScripts.d.ts +1 -0
  139. package/dist/types/formats/map.d.ts +1 -0
  140. package/dist/types/formats/monster.d.ts +1 -0
  141. package/dist/types/formats/palette.d.ts +1 -0
  142. package/dist/types/formats/recording.d.ts +1 -0
  143. package/dist/types/formats/sound.d.ts +1 -0
  144. package/dist/types/formats/voc.d.ts +1 -0
  145. package/dist/types/gifShrink.d.ts +8 -0
  146. package/dist/types/image/animatedGif.d.ts +9 -0
  147. package/dist/types/image/surface.d.ts +26 -0
  148. package/dist/types/images.d.ts +13 -0
  149. package/dist/types/kit/actors.d.ts +7 -0
  150. package/dist/types/kit/align.d.ts +93 -0
  151. package/dist/types/kit/audioEvents.d.ts +26 -0
  152. package/dist/types/kit/blit.d.ts +20 -0
  153. package/dist/types/kit/blockRoles.d.ts +243 -0
  154. package/dist/types/{games/kit → kit}/clips.d.ts +1 -1
  155. package/dist/types/kit/coverPaint.d.ts +7 -0
  156. package/dist/types/kit/disk.d.ts +15 -0
  157. package/dist/types/kit/fadeOut.d.ts +12 -0
  158. package/dist/types/kit/fliClips.d.ts +32 -0
  159. package/dist/types/kit/fliShrink.d.ts +149 -0
  160. package/dist/types/{games/kit → kit}/gameSim.d.ts +9 -5
  161. package/dist/types/kit/hopBot.d.ts +72 -0
  162. package/dist/types/kit/laserClearance.d.ts +16 -0
  163. package/dist/types/kit/laserJoints.d.ts +39 -0
  164. package/dist/types/kit/laserLayout.d.ts +54 -0
  165. package/dist/types/kit/laserPixels.d.ts +52 -0
  166. package/dist/types/kit/laserPreview.d.ts +9 -0
  167. package/dist/types/kit/laserSvg.d.ts +35 -0
  168. package/dist/types/kit/levelGen/castle.d.ts +17 -0
  169. package/dist/types/kit/levelGen/dungeon.d.ts +11 -0
  170. package/dist/types/kit/levelGen/forest.d.ts +17 -0
  171. package/dist/types/kit/levelGen/furnish.d.ts +31 -0
  172. package/dist/types/kit/levelGen/grid.d.ts +46 -0
  173. package/dist/types/kit/levelGen/index.d.ts +138 -0
  174. package/dist/types/kit/levelGen/interior.d.ts +18 -0
  175. package/dist/types/kit/levelGen/jumpModel.d.ts +78 -0
  176. package/dist/types/kit/levelGen/needs.d.ts +44 -0
  177. package/dist/types/kit/levelGen/overworld.d.ts +21 -0
  178. package/dist/types/kit/levelGen/platform.d.ts +59 -0
  179. package/dist/types/kit/levelGen/platformCap.d.ts +13 -0
  180. package/dist/types/kit/levelGen/platformReach.d.ts +37 -0
  181. package/dist/types/kit/levelGen/props.d.ts +37 -0
  182. package/dist/types/kit/levelGen/town.d.ts +24 -0
  183. package/dist/types/kit/levelGrid.d.ts +16 -0
  184. package/dist/types/kit/levelPicture.d.ts +9 -0
  185. package/dist/types/kit/menuVersion.d.ts +7 -0
  186. package/dist/types/kit/microText.d.ts +18 -0
  187. package/dist/types/kit/mumble.d.ts +41 -0
  188. package/dist/types/kit/music.d.ts +1 -0
  189. package/dist/types/kit/palMerge.d.ts +10 -0
  190. package/dist/types/kit/palRamps.d.ts +28 -0
  191. package/dist/types/kit/pcText.d.ts +19 -0
  192. package/dist/types/kit/photo.d.ts +69 -0
  193. package/dist/types/kit/png.d.ts +7 -0
  194. package/dist/types/kit/quantize.d.ts +20 -0
  195. package/dist/types/kit/raytrace.d.ts +169 -0
  196. package/dist/types/kit/recordedDemo.d.ts +1 -0
  197. package/dist/types/kit/road3d.d.ts +71 -0
  198. package/dist/types/kit/routeChecks.d.ts +6 -0
  199. package/dist/types/kit/saveSlots.d.ts +17 -0
  200. package/dist/types/kit/sceneInit.d.ts +11 -0
  201. package/dist/types/{games/kit → kit}/sceneSim.d.ts +5 -5
  202. package/dist/types/kit/screenText.d.ts +3 -0
  203. package/dist/types/kit/sdftext.d.ts +34 -0
  204. package/dist/types/kit/shading.d.ts +23 -0
  205. package/dist/types/kit/shareBlocks.d.ts +20 -0
  206. package/dist/types/kit/song.d.ts +89 -0
  207. package/dist/types/kit/songFx.d.ts +99 -0
  208. package/dist/types/kit/synthParts.d.ts +7 -0
  209. package/dist/types/kit/tar.d.ts +13 -0
  210. package/dist/types/kit/textfit.d.ts +74 -0
  211. package/dist/types/kit/transforms.d.ts +8 -0
  212. package/dist/types/lookAlike.d.ts +31 -0
  213. package/dist/types/menuVersionEntry.d.ts +1 -0
  214. package/dist/types/mesh/colorBodies.d.ts +18 -0
  215. package/dist/types/mesh/decimate.d.ts +10 -0
  216. package/dist/types/mesh/fieldTrinket.d.ts +40 -0
  217. package/dist/types/mesh/figureShapes.d.ts +24 -0
  218. package/dist/types/mesh/mesh.d.ts +9 -0
  219. package/dist/types/mesh/meshCheck.d.ts +22 -0
  220. package/dist/types/mesh/overhang.d.ts +24 -0
  221. package/dist/types/mesh/pixelFigure.d.ts +41 -0
  222. package/dist/types/mesh/sampledField.d.ts +3 -0
  223. package/dist/types/mesh/sdfShapes.d.ts +20 -0
  224. package/dist/types/mesh/stl.d.ts +9 -0
  225. package/dist/types/mesh/strokeText.d.ts +8 -0
  226. package/dist/types/mesh/surfaceNets.d.ts +14 -0
  227. package/dist/types/mesh/tetraMesh.d.ts +4 -0
  228. package/dist/types/mesh/threeMf.d.ts +12 -0
  229. package/dist/types/mesh/trinketKinds.d.ts +72 -0
  230. package/dist/types/mesh/trinketTool.d.ts +26 -0
  231. package/dist/types/mesh/voxel.d.ts +10 -0
  232. package/dist/types/mesh/zipFile.d.ts +13 -0
  233. package/dist/types/microFont.d.ts +6 -0
  234. package/dist/types/pack/meshPack.d.ts +26 -0
  235. package/dist/types/pack/threeMfPack.d.ts +11 -0
  236. package/dist/types/palettePresetData.d.ts +4 -0
  237. package/dist/types/palettePresets.d.ts +12 -0
  238. package/dist/types/paletteReserve.d.ts +52 -0
  239. package/dist/types/palettes.d.ts +4 -0
  240. package/dist/types/releaseNotes.d.ts +3 -0
  241. package/dist/types/simulation.d.ts +6 -0
  242. package/dist/types/{web/packages/tools/src/text.d.ts → text.d.ts} +6 -6
  243. package/package.json +145 -15
  244. package/dist/binary-D7wuaC5g.js +0 -120
  245. package/dist/pixels-DzfIIUOl.js +0 -76
  246. package/dist/types/games/kit/blit.d.ts +0 -10
  247. package/dist/types/games/kit/music.d.ts +0 -1
  248. package/dist/types/games/kit/pcText.d.ts +0 -8
  249. package/dist/types/games/kit/shading.d.ts +0 -11
  250. package/dist/types/web/packages/tools/src/audio.d.ts +0 -3
  251. package/dist/types/web/packages/tools/src/drawing.d.ts +0 -10
  252. package/dist/types/web/packages/tools/src/images.d.ts +0 -2
  253. package/dist/types/web/packages/tools/src/microFont.d.ts +0 -1
  254. package/dist/types/web/packages/tools/src/simulation.d.ts +0 -3
  255. package/dist/types/web/scripts/cdGames.d.ts +0 -103
  256. package/dist/types/web/scripts/gameShots.d.ts +0 -12
  257. package/dist/types/web/scripts/ogImage.d.ts +0 -21
  258. package/dist/types/web/src/audio/cmfLoad.d.ts +0 -7
  259. package/dist/types/web/src/audio/cmfPlayer.d.ts +0 -69
  260. package/dist/types/web/src/audio/context.d.ts +0 -12
  261. package/dist/types/web/src/audio/engine.d.ts +0 -39
  262. package/dist/types/web/src/audio/music.worklet.d.ts +0 -14
  263. package/dist/types/web/src/audio/opl.d.ts +0 -37
  264. package/dist/types/web/src/audio/output.d.ts +0 -13
  265. package/dist/types/web/src/desk/boxes/boxFacts.d.ts +0 -85
  266. package/dist/types/web/src/dosPlayer/fileExtensions.d.ts +0 -44
  267. package/dist/types/web/src/dosPlayer/patchRules.d.ts +0 -24
  268. package/dist/types/web/src/dosPlayer/patchTable.d.ts +0 -80
  269. package/dist/types/web/src/edition.d.ts +0 -6
  270. package/dist/types/web/src/eggs/eggState.d.ts +0 -26
  271. package/dist/types/web/src/eggs/eggs.d.ts +0 -31
  272. package/dist/types/web/src/engine/character.d.ts +0 -30
  273. package/dist/types/web/src/engine/funcKeys.d.ts +0 -33
  274. package/dist/types/web/src/engine/game.d.ts +0 -52
  275. package/dist/types/web/src/engine/keys.d.ts +0 -17
  276. package/dist/types/web/src/engine/machine.d.ts +0 -99
  277. package/dist/types/web/src/engine/menus.d.ts +0 -46
  278. package/dist/types/web/src/engine/monsters.d.ts +0 -19
  279. package/dist/types/web/src/engine/playGain.d.ts +0 -11
  280. package/dist/types/web/src/engine/playerLook.d.ts +0 -26
  281. package/dist/types/web/src/engine/recorder.d.ts +0 -60
  282. package/dist/types/web/src/engine/render.d.ts +0 -8
  283. package/dist/types/web/src/engine/scene.d.ts +0 -156
  284. package/dist/types/web/src/engine/scroll.d.ts +0 -16
  285. package/dist/types/web/src/engine/showGraphic.d.ts +0 -39
  286. package/dist/types/web/src/engine/slowPc.d.ts +0 -62
  287. package/dist/types/web/src/engine/touch.d.ts +0 -33
  288. package/dist/types/web/src/engine/world.d.ts +0 -215
  289. package/dist/types/web/src/export/gameAbout.d.ts +0 -15
  290. package/dist/types/web/src/formats/binary.d.ts +0 -44
  291. package/dist/types/web/src/formats/blocks.d.ts +0 -52
  292. package/dist/types/web/src/formats/character.d.ts +0 -65
  293. package/dist/types/web/src/formats/cmf.d.ts +0 -33
  294. package/dist/types/web/src/formats/fli.d.ts +0 -45
  295. package/dist/types/web/src/formats/fliLimits.d.ts +0 -13
  296. package/dist/types/web/src/formats/game.d.ts +0 -72
  297. package/dist/types/web/src/formats/gif.d.ts +0 -15
  298. package/dist/types/web/src/formats/graphicScripts.d.ts +0 -18
  299. package/dist/types/web/src/formats/highscore.d.ts +0 -10
  300. package/dist/types/web/src/formats/map.d.ts +0 -24
  301. package/dist/types/web/src/formats/monster.d.ts +0 -48
  302. package/dist/types/web/src/formats/palette.d.ts +0 -15
  303. package/dist/types/web/src/formats/recording.d.ts +0 -7
  304. package/dist/types/web/src/formats/sound.d.ts +0 -13
  305. package/dist/types/web/src/formats/voc.d.ts +0 -13
  306. package/dist/types/web/src/gfx/cp437Glyphs.d.ts +0 -2
  307. package/dist/types/web/src/gfx/font8x8.d.ts +0 -2
  308. package/dist/types/web/src/gfx/levelPicture.d.ts +0 -81
  309. package/dist/types/web/src/gfx/screen.d.ts +0 -46
  310. package/dist/types/web/src/gfx/titlePicture.d.ts +0 -21
  311. package/dist/types/web/src/input/chords.d.ts +0 -22
  312. package/dist/types/web/src/input/deskMouse.d.ts +0 -14
  313. package/dist/types/web/src/input/keyboard.d.ts +0 -39
  314. package/dist/types/web/src/input/scancodes.d.ts +0 -3
  315. package/dist/types/web/src/manual/printables/types.d.ts +0 -277
  316. package/dist/types/web/src/project/bizarre.d.ts +0 -28
  317. package/dist/types/web/src/project/companion.d.ts +0 -35
  318. package/dist/types/web/src/project/diskFacts.d.ts +0 -30
  319. package/dist/types/web/src/project/files.d.ts +0 -124
  320. package/dist/types/web/src/project/gameFiles.d.ts +0 -49
  321. package/dist/types/web/src/project/gamePack.d.ts +0 -17
  322. package/dist/types/web/src/project/health.d.ts +0 -30
  323. package/dist/types/web/src/project/secretGames.d.ts +0 -19
  324. package/dist/types/web/src/project/storage.d.ts +0 -46
  325. package/dist/types/web/src/project/streamGame.d.ts +0 -38
  326. package/dist/types/web/src/project/zip.d.ts +0 -33
  327. package/dist/types/web/src/retro/dos/disks.d.ts +0 -33
  328. package/dist/types/web/src/retro/text/cp437.d.ts +0 -4
  329. package/dist/types/web/src/seededRandom.d.ts +0 -6
  330. package/dist/types/web/src/tinHearts/deskHearts.d.ts +0 -33
  331. package/dist/types/web/src/tinHearts/manifest.d.ts +0 -30
  332. package/dist/types/web/src/tinHearts/tinHearts.d.ts +0 -84
  333. package/dist/types/web/src/walkthrough/format.d.ts +0 -92
  334. package/dist/types/web/src/walkthrough/madeUpScores.d.ts +0 -6
  335. package/dist/types/web/src/walkthrough/runtime.d.ts +0 -134
  336. /package/dist/types/{web/src/assistant → image}/png.d.ts +0 -0
  337. /package/dist/types/{games/kit → kit}/palette.d.ts +0 -0
  338. /package/dist/types/{games/kit → kit}/pixels.d.ts +0 -0
  339. /package/dist/types/{games/kit → kit}/reel.d.ts +0 -0
  340. /package/dist/types/{games/kit → kit}/sound.d.ts +0 -0
  341. /package/dist/types/{games/kit → kit}/textBounds.d.ts +0 -0
  342. /package/dist/types/{games/kit → kit}/tune.d.ts +0 -0
  343. /package/dist/types/{web/src/audio → music}/compose.d.ts +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ Changes to `@lewismoten/gamemaker-sandbox-tools`, released as `tools-v*` tags. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [3.4.0] - 2026-11-07
9
+
10
+ Most of the game-building kit moves into the package: a seeded level generator for dungeons, forests, towns, castles
11
+ and side views, block roles, nonsense-talk voices, and tools for FLI shrinking, palettes, disk diffs, embroidery, and
12
+ 3D-printable and laser models.
13
+
14
+ ### Added
15
+
16
+ - `kit/levelGen`, a seeded level generator with no DOM: dungeons, forests, homes, shops, castles, towns, overworlds and platform side views, with each key reachable before its lock.
17
+ - Shared game-building APIs move into the package: DOS disk writing, native character and text-screen builders, route checks, the engine-backed simulator and more.
18
+ - `kit/blockRoles`, `kit/mumble` (nonsense talk as a .VOC), `kit/levelGrid` and `image/animatedGif`.
19
+ - Mesh, embroidery and laser-kit tools: surface nets and STL files, a stitch generator with DST, EXP and PES files, finger-joint panels and a wooden-nickel builder.
20
+ - `diskDiff` and `kit/fliShrink`.
21
+
22
+ ### Changed
23
+
24
+ - Game builds replace `disk/` files in place, and `kit/tar` is browser-safe.
25
+
26
+ ### Fixed
27
+
28
+ - `kit/gameSim`: a scene with a blank character or character-blocks slot keeps the last scene's, as PLAYGAME's loadscene does.
29
+
30
+ Full list: [changes/release/tools/3.4.0.md](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/tools-v3.4.0/changes/release/tools/3.4.0.md)
31
+
32
+ ## [3.1.0] - 2026-10-29
33
+
34
+ The first release of the development tools as an npm package: drawing, palettes, fonts, music and PNG builders.
35
+
36
+ ### Added
37
+
38
+ - The tools package, scoped as `@lewismoten/gamemaker-sandbox-tools` and published to GitHub Packages from version tags.
39
+ - CP437 and micro text drawn as indexed game pixels, with documented font, text-effect and lighting APIs.
40
+ - Reusable color ramps and time-of-day VGA lighting.
41
+
42
+ [Unreleased]: https://github.com/lewismoten/GameMaker-SandboxEdition/compare/tools-v3.4.0...HEAD
43
+ [3.4.0]: https://github.com/lewismoten/GameMaker-SandboxEdition/compare/tools-v3.1.0...tools-v3.4.0
44
+ [3.1.0]: https://github.com/lewismoten/GameMaker-SandboxEdition/releases/tag/tools-v3.1.0
package/NOTICE.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Notices
2
2
 
3
- This development toolkit is extracted from Game-Maker: Sandbox Edition by Lewis Moten, released under the MIT License. It includes the fork's native format codecs, drawing and audio builders, and headless reference simulation.
3
+ This development toolkit is extracted from Game-Maker: Sandbox Edition by Lewis Moten, released under the MIT License. It owns the drawing and audio builders and headless reference simulation; shared native format codecs, runtime types and CP437 font data come through its declared engine dependency, and archive support through its declared archives dependency.
4
4
 
5
5
  The reference engine is a TypeScript port of RSD Game-Maker 3.0 by Recreational Software Designs: G. Andrew Stone, G. Oliver Stone, Oliver Stone Jr. and Joan Stone. Andy Stone released the original source under the MIT License in 2014. The original copyright notice is retained in LICENSE. Peter Savage wrote the original Sound Blaster voice-file and joystick routines.
6
6
 
7
7
  ## Fonts
8
8
 
9
- - **8×8 ASCII and selected CP437 glyphs:** Daniel Hepper's [font8x8](https://github.com/dhepper/font8x8), specifically `font8x8_basic`, `font8x8_ext_latin`, `font8x8_greek`, and `font8x8_misc`. Each upstream header declares **Public Domain** and credits **Marcel Sondaar** and **International Business Machines (public domain VGA fonts)** as its basis. See the [upstream source header](https://github.com/dhepper/font8x8/blob/master/font8x8_basic.h). This data is used in `web/src/gfx/font8x8.ts` and the marked entries of `web/src/gfx/cp437Glyphs.ts`, exposed here through `FONT8X8` and `FONT_CP437`.
10
- - **Additional CP437 glyphs:** the other symbols and box-drawing glyphs in `web/src/gfx/cp437Glyphs.ts` were drawn for Game-Maker: Sandbox Edition using **Anthropic Claude Opus 5.5**, under **Lewis Moten's** direction, and are distributed under the project's **MIT License**. These additions were not copied from IBM's ROM; the full 256-glyph table combines them with the public-domain data above.
9
+ - **8×8 ASCII and selected CP437 glyphs:** Daniel Hepper's [font8x8](https://github.com/dhepper/font8x8), specifically `font8x8_basic`, `font8x8_ext_latin`, `font8x8_greek`, and `font8x8_misc`. Each upstream header declares **Public Domain** and credits **Marcel Sondaar** and **International Business Machines (public domain VGA fonts)** as its basis. See the [upstream source header](https://github.com/dhepper/font8x8/blob/master/font8x8_basic.h). This data is used in `web/packages/engine/src/gfx/font8x8.ts` and the marked entries of `web/packages/engine/src/gfx/cp437Glyphs.ts`, exposed here through `FONT8X8` and `FONT_CP437`.
10
+ - **Additional CP437 glyphs:** the other symbols and box-drawing glyphs in `web/packages/engine/src/gfx/cp437Glyphs.ts` were drawn for Game-Maker: Sandbox Edition using **Anthropic Claude Opus 5.5**, under **Lewis Moten's** direction, and are distributed under the project's **MIT License**. These additions were not copied from IBM's ROM; the full 256-glyph table combines them with the public-domain data above.
11
11
  - **3×5 micro font (`MICRO_GLYPHS`):** the project's small sign font, introduced in `games/teddy/draw.ts` by **Lewis Moten using Anthropic Claude Opus 5.5**, then maintained in `games/teddy/src/art/draw.ts`. Its provenance is recorded in [commit 7241036f49cab9dea52f58541e30ce6c9ce86052](https://github.com/lewismoten/GameMaker-SandboxEdition/commit/7241036f49cab9dea52f58541e30ce6c9ce86052). It is distributed under the project's **MIT License**, not the public-domain dedication of Hepper's font. **OpenAI Codex (GPT-6/6.1)** extracted the table into this toolkit's `src/microFont.ts` and added the reusable rendering APIs under Lewis's direction.
12
12
 
13
13
  ## Other formats and tooling
@@ -17,3 +17,105 @@ The lighting presets were written for this project. GIF, FLI, Creative Voice Fil
17
17
  The underlying web port and game-building tools were written with Anthropic Claude Opus 5.5 under Lewis Moten's direction. OpenAI Codex (GPT-6/6.1) prepared the toolkit packaging, consumer migration, documentation, and verification under his direction.
18
18
 
19
19
  No game-specific artwork, palettes, characters, recordings, or complete games are included. Consumers supply and credit their own content.
20
+
21
+ ## Optional source audio conversion
22
+
23
+ `audio-files` invokes an independently installed [FFmpeg](https://ffmpeg.org/) executable
24
+ by the FFmpeg developers; no FFmpeg code or binary is included in this package. FFmpeg is
25
+ LGPL-2.1-or-later, or GPL-2.0-or-later when its GPL components are enabled; see its
26
+ [licensing information](https://ffmpeg.org/legal.html). FLAC is the lossless audio format
27
+ maintained by Xiph.Org; its [FAQ](https://xiph.org/flac/faq.html) describes sample-exact
28
+ compression. The process wrapper and VOC conversion APIs were implemented with OpenAI
29
+ Codex under Lewis Moten's direction, using this project's existing native VOC encoder.
30
+
31
+ The native mono 8-bit PCM WAV reader uses RIFF/WAVE chunk layout and PCM format fields
32
+ from [Microsoft's WAVEFORMATEX documentation](https://learn.microsoft.com/en-us/windows/win32/api/mmeapi/ns-mmeapi-waveformatex).
33
+ No Microsoft implementation code is included. The reader was implemented with OpenAI
34
+ Codex under Lewis Moten's direction and is distributed under this project's MIT License.
35
+
36
+ ## Additional micro-font glyphs and variants
37
+
38
+ The extended rounded repertoire and square technical-label variant are project-owned
39
+ font data by Lewis Moten using Anthropic Claude Opus 5.5, under this project's MIT License.
40
+ They consolidate the existing tables in the public games' art helpers (including the
41
+ expanded punctuation in `games/brief/src/art/draw.ts` and `games/blaster/src/art/draw.ts`,
42
+ and the cent sign in `games/year2000/src/art/font.ts`). The square face originated in
43
+ [the original Ohm Sweet Ohm drawing helpers](https://github.com/lewismoten/GameMaker-SandboxEdition/commit/1a746bffa).
44
+ OpenAI Codex consolidated the data and APIs under Lewis Moten's direction.
45
+ These fonts are distinct from the separately credited public-domain CP437 glyphs above.
46
+
47
+ ## Shared rendering methods and stroke lettering
48
+
49
+ The rounded stroke lettering in `kit/sdftext` is project font data by Lewis Moten using
50
+ Anthropic Claude Opus 5.5, introduced with the original software-rendered logo helpers
51
+ ([source commit](https://github.com/lewismoten/GameMaker-SandboxEdition/commit/7bb0e7b7c)).
52
+ It is distributed under the project's MIT License, alongside the project-owned rendering,
53
+ quantization, synthesis and object-building code extracted from `games/kit`. OpenAI Codex
54
+ consolidated these modules and their consumers under Lewis Moten's direction.
55
+
56
+ Method references: Paul S. Heckbert, *Color Image Quantization for Frame Buffer Display*
57
+ ([author's publication list](https://www.cs.cmu.edu/~ph/)), for median-cut quantization;
58
+ John C. Hart, *Sphere Tracing: A Geometric Method for the Antialiased Ray Tracing of
59
+ Implicit Surfaces* ([paper](https://graphics.stanford.edu/courses/cs348b-20-spring-content/uploads/hart.pdf)),
60
+ for distance-based sphere tracing. The implementations and project font data here use
61
+ the project's MIT License.
62
+
63
+ ## Original CD Library palette
64
+
65
+ `src/palettes.ts` embeds a byte-for-byte copy of `cd/gameware/library/default.pal`
66
+ from the original RSD Game-Maker CD, by Recreational Software Designs (G. Andrew
67
+ Stone, G. Oliver Stone, Oliver Stone Jr. and Joan Stone). It is distributed under
68
+ the original project's MIT License; this package retains that license in `LICENSE`.
69
+ [Source palette](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/master/cd/gameware/library/default.pal).
70
+ OpenAI Codex packaged this data and the fresh-copy API under Lewis Moten's direction.
71
+
72
+ ## Ready-made palette reference data
73
+
74
+ `src/palettePresetData.ts` contains RGB swatches adapted to six-bit VGA by OpenAI Codex
75
+ under Lewis Moten's direction. Analog console colors are reference approximations, not
76
+ a claim that every television or hardware revision produces identical RGB. No third-party
77
+ font, image, emulator or generator executable is bundled with these swatches.
78
+
79
+ - Atari 2600 NTSC and PAL: Ricardo Cancho Niemietz, 2008, released by the author into the
80
+ public domain (with unrestricted-use fallback). Swatches sampled at the centers of the
81
+ 16×8 color charts; NTSC retains 128 hardware slots, including one duplicated RGB value;
82
+ PAL's repeated gray columns are removed to give 104 slots. Sources and release statements:
83
+ [NTSC](https://commons.wikimedia.org/wiki/File:Atari2600_NTSC_palette.png),
84
+ [PAL](https://commons.wikimedia.org/wiki/File:Atari2600_PAL_palette.png).
85
+ - NES: Persune, Pally, MIT No Attribution (MIT-0), copyright 2024 Persune. The first 64 RGB
86
+ entries (no emphasis) of `docs/NESDev/2C02G_U_wiki.pal` are reduced to 54 distinct swatches.
87
+ [Source at commit 9635e9b71505f969014c7efa15dca3ba35ade871](https://github.com/Gumball2415/pally/blob/9635e9b71505f969014c7efa15dca3ba35ade871/docs/NESDev/2C02G_U_wiki.pal),
88
+ [license](https://github.com/Gumball2415/pally/blob/9635e9b71505f969014c7efa15dca3ba35ade871/LICENSE).
89
+ - Commodore 64 NTSC CXA2025 reference: Groepaz, unrestricted free use, including
90
+ redistribution, commercial use and modification; attribution appreciated. Sixteen
91
+ color-bar centers sampled from the reference, with color 0 normalized to menu black.
92
+ [Author's reference](https://hitmen.c02.at/linked/c64_ntsc_cxa2025.bmp.png),
93
+ [permission and provenance](https://commons.wikimedia.org/wiki/File:C64_ntsc_cxa2025.bmp.png).
94
+
95
+ The RGBI and SMS bit mappings are project-owned MIT implementations of hardware facts,
96
+ referencing IBM's *Technical Reference: Options and Adapters*, volume 2, April 1984
97
+ ([manufacturer's manual](https://bitsavers.org/pdf/ibm/pc/cards/Technical_Reference_Options_and_Adapters_Volume_2_Apr84.pdf)),
98
+ and Maxim / SMS Power contributors' [palette documentation](https://www.smspower.org/Development/Palette).
99
+ Monochrome ramps, the EGA skin/hair additions and LCD-green approximations were designed
100
+ for this project by Lewis Moten using OpenAI Codex, under the project's MIT License.
101
+
102
+ Pally's MIT-0 license:
103
+
104
+ ```text
105
+ MIT No Attribution
106
+
107
+ Copyright 2024 Persune
108
+
109
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
110
+ software and associated documentation files (the "Software"), to deal in the Software
111
+ without restriction, including without limitation the rights to use, copy, modify,
112
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
113
+ permit persons to whom the Software is furnished to do so.
114
+
115
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
116
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
117
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
118
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
119
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
120
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
121
+ ```
package/README.md CHANGED
@@ -1,17 +1,33 @@
1
1
  # @lewismoten/gamemaker-sandbox-tools
2
2
 
3
- Development-only tools for creating and checking native RSD Game-Maker data. Browser playback belongs to `@lewismoten/gamemaker-sandbox-engine`; this package has no game artwork, recordings, characters, or palettes.
3
+ Tools for creating and checking native RSD Game-Maker data. Browser playback belongs to `@lewismoten/gamemaker-sandbox-engine`; this package has no game artwork, recordings, characters, or game-specific palettes.
4
4
 
5
- Requires Node.js 22.12 or newer. Install with `npm install --save-dev @lewismoten/gamemaker-sandbox-tools` once published. Until publication, `npm pack` produces a self-contained installation candidate.
5
+ Requires Node.js 22.12 or newer. Install as a development dependency from your configured npm registry:
6
+
7
+ ```sh
8
+ npm install --save-dev @lewismoten/gamemaker-sandbox-tools
9
+ ```
10
+
11
+ If your registry requires authentication or a scope mapping, configure npm using that registry's instructions.
6
12
 
7
13
  ## APIs
8
14
 
9
15
  - `formats/blocks`, `character`, `game`, `map`, `monster`, `palette`, `gif`, `graphicScripts`, `sound`, `fli`, `fliLimits`, `voc`, `recording`, and `cmf`: native readers, writers, types, and limits. Each is a separate `formats/<name>` subpath.
16
+ - `gif-shrink`: `shrinkGif(bytes)` returns a smaller GIF with a trimmed color table, or `undefined` when it can't shrink without changing what PLAYGAME shows.
10
17
  - `drawing`: indexed pixels, VGA palette builders, font drawing, shading, compositing, and cartoon reels.
11
18
  - `audio`: original FM instrument presets, CMF composition, PC speaker effects, and VOC synthesis.
12
- - `images`: indexed PNG encoding and CRC-32.
19
+ - `images`: indexed PNG encoding, CRC-32, color reduction, indexed drawing and picture transforms.
13
20
  - `simulation`: headless `Sim`, `GameSim`, `readDisk`, `diskSim`, and `newCharInfo` for fixture checks. This includes the reference simulation; it does not replace testing the browser engine package.
14
21
 
22
+ The browser-safe `images` entry also exports `Pixels`, `flipX`, `flipY`, `turn90`,
23
+ `turn180`, and `shiftPixels` for indexed pictures of any size. Quarter turns return a
24
+ picture with exchanged dimensions. `mirrorAll`, `line`, `box`, and `floodFill` support
25
+ painting across tile boundaries. Fill accepts optional mask and writer callbacks for
26
+ missing cells or repeated references to the same tile; traversal uses the original
27
+ pixels so writes to shared cells do not break the fill.
28
+ Shift offsets use whole pixels. Fill ignores seeds outside the image, inside a masked
29
+ cell, or at non-integer coordinates; mismatched buffer dimensions throw a `RangeError`.
30
+
15
31
  ```ts
16
32
  import { emptyBlock, serializeBlocks } from '@lewismoten/gamemaker-sandbox-tools/formats/blocks';
17
33
  import { Pixels } from '@lewismoten/gamemaker-sandbox-tools/drawing';
@@ -21,7 +37,9 @@ blocks[0].pixels.set(new Pixels(20, 20, 1).px);
21
37
  const data = serializeBlocks(blocks);
22
38
  ```
23
39
 
24
- Keep these imports in build scripts and tests. The package explicitly rejects browser imports. Generated game data and your own copied assets belong in the consuming project.
40
+ `medianCutRgba` from `images` chooses up to a requested 1–256 eight-bit RGB colors from portable RGBA image buffers. It needs no canvas or DOM; flatten transparency onto the intended background before calling it. The palette is based on pixel colors and their frequency, not unused color-table entries.
41
+
42
+ Keep drawing and simulation imports in Node build scripts and tests; those entry points reject browser imports. Browser-safe `audio`, `images`, `text`, `colors`, `microFont`, `music/compose`, `image/png`, `kit/tar`, `kit/blockRoles` and `menu-version` (stamps "v1.0" on a game menu picture) entry points also support the web editor. Playback through the engine and archives packages does not load this toolkit. Generated game data and your own copied assets belong in the consuming project.
25
43
 
26
44
  ## Fonts, text images, and lighting
27
45
 
@@ -52,11 +70,283 @@ const lit = lightColor([100, 180, 80], 'night');
52
70
 
53
71
  `outline` and `dropShadow` also decorate `Pixels` sprites within their existing bounds; edges clip. The existing sprite outline uses four neighbors, while text outlines include all eight neighbors.
54
72
 
55
- `colorRamp` returns eight-bit RGB stops without allocating palette entries. `PaletteBuilder.ramp` allocates named ramps in a six-bit VGA palette. `TIME_OF_DAY_LIGHT`, `TIME_OF_DAY_SKY`, and `lightColor` provide morning, noon, afternoon, sunset, night, and stage-light presets. `adjustPalette` returns an adjusted native VGA palette without mutating its input. By default it preserves indexes 0 and 255; pass a custom index list to protect glowing colors or designer inks. Game-specific ramp names and cast colors belong in the consumer.
73
+ `colorRamp` returns eight-bit RGB stops without allocating palette entries. `rgbToHsv` and `hsvToRgb` convert eight-bit RGB and hue in degrees with saturation/value in 0..1, without changing inputs. `PaletteBuilder.ramp` allocates named ramps in a six-bit VGA palette. `TIME_OF_DAY_LIGHT`, `TIME_OF_DAY_SKY`, and `lightColor` provide morning, noon, afternoon, sunset, night, and stage-light presets. `adjustPalette` returns an adjusted native VGA palette without mutating its input. By default it preserves indexes 0 and 255; pass a custom index list to protect glowing colors or designer inks. Game-specific ramp names and cast colors belong in the consumer.
74
+
75
+ ## Source audio files to VOC (Node.js)
76
+
77
+ Mono unsigned 8-bit PCM WAV files at the requested rate decode directly in Node.js, with
78
+ no additional software. For Ogg, FLAC, other WAV variants or resampling, install
79
+ [FFmpeg](https://ffmpeg.org/download.html) separately and make `ffmpeg` available on PATH,
80
+ or pass its executable path as `ffmpegPath`. No decoder binary is bundled, and browser
81
+ playback gains no dependency.
82
+
83
+ ```ts
84
+ import { audioFileToVoc, decodeAudioFile } from '@lewismoten/gamemaker-sandbox-tools/audio-files';
85
+ import { writeFileSync } from 'node:fs';
86
+
87
+ writeFileSync('VOICE.VOC', audioFileToVoc(new URL('./voice.wav', import.meta.url), {
88
+ sampleRate: 11025, maxBytes: 39999,
89
+ }));
90
+ const samples = decodeAudioFile('voice.ogg', { sampleRate: 8000 });
91
+ ```
92
+
93
+ FLAC, Ogg, WAV and other formats supported by your FFmpeg build are accepted. Output is
94
+ mono at the requested sample rate (11025 Hz by default). VOC conversion defaults to a
95
+ 65535-byte DOS limit; oversized clips fail instead of being shortened. `decodeAudioFile`
96
+ returns samples for mixing or other authoring operations, bounded by `maxSamples`
97
+ (default 16 MiB). Both functions accept `timeoutMs` (default 30000).
98
+
99
+ Use PCM WAV sources for inline GitHub audio previews and sample-exact native game builds.
100
+ Lossless FLAC input is also supported at its original sample rate.
101
+ The converter disables dithering and uses the inverse of the native VOC encoder's byte
102
+ mapping. Lossy sources such as Ogg Vorbis are supported for new audio, but cannot recreate
103
+ a previous recording's exact samples. Source `.wav`/`.ogg`/`.flac` files are authoring assets; only
104
+ 8.3-named `.VOC` files belong on the generated DOS disk.
105
+
106
+ ### Extended micro fonts
107
+
108
+ `microFont` exports `MICRO_GLYPHS`, `MICRO_SQUARE_GLYPHS`, and `microGlyphs(characters, square?)`.
109
+ The shared repertoire includes the sign and technical-label additions such as `µ`, `¢`,
110
+ `#`, `%`, `@`, `~`, quotes, underscore, and backslash. Both rounded and square letterforms
111
+ are preserved. `renderText(text, {font: 'micro-square'})` selects the square style;
112
+ `glyphRows(code, 'micro-square')` returns its five rows. `microGlyphs` can select an exact
113
+ legacy repertoire when an existing game's unsupported-character behavior must stay the same.
114
+ See NOTICE.md for the source and license of both project fonts.
115
+
116
+ ### Shared text renderers
117
+
118
+ `drawing` exports `createMicroText` and `createPcText` for adapting existing lettering
119
+ without copying drawing loops. Micro text accepts a glyph repertoire, fallback, spacing,
120
+ and optional consumer-owned multicolor glyphs. PC text accepts custom glyph artwork,
121
+ scaled or absolute shadow offsets, and outline spacing. Both report ink to the existing
122
+ text-bounds audit. The default `text`, `outlined`, and `centered` retain their old behavior.
123
+
124
+ ### Sprite composition
125
+
126
+ `drawing` also exports ASCII sprites, nearest-pixel rotations and reflections, and
127
+ `resampleBlit` for fractional scaling. `outline` can ignore existing outline-colored
128
+ neighbors or use an explicit transparent index; `outlineInPlace` keeps the original
129
+ canvas. `scaleBlitTransparent` selects transparency without changing its mirroring flag.
130
+ `bevel` accepts separate top/left/bottom/right shade offsets, and `pool` paints radial light.
131
+
132
+ `microWidth` measures visible cells with zero width for an empty string; `microAdvance`
133
+ retains the older cell-advance formula when preserving legacy layout. Default micro
134
+ drawing recognizes direct symbols such as `µ` before trying their uppercase forms.
135
+
136
+ ### Palette and texture helpers
137
+
138
+ `drawing` and `kit/coverPaint` expose seeded tileable value noise, RGB mixing, smoothstep,
139
+ and clamping. `kit/palRamps` exports `Pal` and `wrap` for named palette ramps.
140
+
141
+ ### Software rendering
142
+
143
+ `kit/quantize` chooses shared VGA palettes and ordered dithering for RGB frames.
144
+ `kit/sdftext` provides rounded stroke lettering, distance grids and extrusion; `kit/raytrace`
145
+ provides shapes, transforms, cameras and lighting. Consumers supply their own scenes.
146
+ The stroke glyphs, implementation provenance and method references are in NOTICE.md.
147
+
148
+ ### Archives for downloads
149
+
150
+ `kit/blockRoles` is the block-role vocabulary (wall, door, locked door and key with a lock number, furniture with a facing...), `suggestRoles` (guesses from a block's behavior and picture; it never decides) and `cleanRoles`/`packRoles` for editor companion data; it needs no DOM and changes no game bytes.
151
+
152
+ `kit/levelGen` draws a dungeon (binary space partition: rooms joined by corridors) or a forest (cellular automata on a tree mask, clearings, a winding path) into a rectangle of a map from the blocks that hold roles. `checkNeeds(kind, roles)` says which roles a kind needs and which it uses when present; `generate(roles, { kind, seed, rect })` returns block numbers, the plain kind of each cell, the cells a terrain brush should give edges to, and a proposed entry and exit (never applied or linked), or a plain message when a needed role is missing; `offerSeed` gives the four seeds of a set of offers; `verifyReach` checks every open cell can be reached from the entry. Dungeons also get locked doors (a one-wide passage that cuts the entry from the exit, with the matching key placed in the part still reachable with that lock and every later one shut), treasure and a heart in corners and dead ends, and `monsters` (pass monster numbers in `params.monsters`; spread out, five or more steps from the entry); forests get treasure, a heart and monsters. `proveResult` plays the keys out and checks reach, key-before-lock and that everything can be collected. It needs no DOM, runs in a Worker, and the same seed always gives the same blocks. It writes no game data: the map editor places the cells. `town` (a winding main street between two gates, cross streets that end on one side only, a plaza, and houses with a door on the street) and `overworld` (value noise for sea level, mountains and forest, periodic when `GenParams.wrap` is set so the land lines up across the seam; a road cut between three to five sites) also return `links`: doors and sites a person could link to other scenes (`SceneLink`: cell, kind, label). They are proposals only; nothing creates a scene or a link, and `proveResult` checks each can be reached from the entry (`linked`).
153
+
154
+ `generatePlatform({ roles, hero, seed, rect, difficulty, monsters })` draws a **side view** (platform) level and is meant for a game's `build.ts` as well as the editor. `hero` is the parsed character file (`hero.chr`): `heroPhysics(chr)` reads his walk speed, the jump's upward push (the momentum sequence) and whether he climbs, and plays them with the engine's gravity (one pixel a tick back, at most 11 pixels a tick). Nothing about the hero is written in the generator, so a game with a bigger or smaller jump gets bigger or smaller pits. `capability(physics)` measures, with the reach model, the highest step he jumps onto and the widest pit he clears on level ground (and spikes); `difficulty` (percent, 80 by default) is the share of those the layout asks. The layout has ground with pits (spiked at the bottom with a hazard block), steps up and down, towers with a ladder (only with a ladder block and a hero who climbs), spikes to jump over, stepping stones across wide pits, ledges to jump up to (`platform` blocks, solid on top only), coins where the jumps pass, a heart at the highest place he can stand, one tall locked door with its key on an earlier stretch, and monsters on the long stretches. It needs wall and sky blocks; every other role is optional. The entry is on the left and the exit on the right (proposals; nothing is linked). The result's `platform.proof` says whether the reach model (`reachFrom`: walks, jumps with every steering length, falls off edges and ladders tick by tick against the cells) proved the exit reachable, every coin, heart and key touchable, and the locked door a real barrier (the exit unreachable until the key); a layout that cannot be proven is drawn again, easier. The same seed always draws the same layout; `proveResult` and the Generate dialog's chip use the proof. The editor goes one step further (`editors/map/generate/platformBot.ts`): a bot presses the hero's own keys along the model's route on the real engine and the chip says "Bot won". Monsters and fun are not judged.
155
+
156
+ `kit/tar` writes and reads POSIX ustar archives (`createTar`, `createTarGz`, `readTar`). Entries keep
157
+ their Unix mode, so a game folder's programs and scripts unpack executable, and names over 100
158
+ bytes use the header's prefix field. It has no dependencies and runs in Node and browsers
159
+ (`.tar.gz` uses the platform's `CompressionStream`).
160
+
161
+ ### Native object builders
162
+
163
+ `kit/laserJoints` makes flat wooden-box panel outlines for the laser kits: finger (box) joints whose two sides mesh,
164
+ rectilinear outlines from rectangles, and mitered kerf offsets (`jointOutline`, `outlineFromRects`, `offsetPoly`).
165
+ `kit/laserLayout` has `Part` (one flat piece with named elements, kerf applied, spacing-checked with
166
+ `kit/laserClearance`) and `packRows`, which lays parts out on a Glowforge-bed sheet and throws if they do not fit.
167
+ Games' laser kits (`games/sleuth/laser/`) build on them with `kit/laserSvg`, `laserPixels` and `laserPreview`.
168
+
169
+ `embroidery/*` turns a vector design into machine-embroidery files. A `Design` is color blocks of items: `fill` (polygons), `satin` (a center line and a width) and `run`. `compile` sews each item with an underlay (an edge walk inside the shape, loose rows under big shapes, a center walk and zigzag under satin) and then its top stitching, and adds the jumps, trims, small tie stitches, color stops and an end, capping every stitch at 7 mm (`Params`: fill rows 0.4 mm apart with 3.5 mm stitches whose holes are staggered in thirds, satin 0.4 mm apart, 0.3 mm of pull compensation on satin and 0.15 mm on fills, a satin wider than 7 mm sewn as lanes). `fill` makes the tatami rows (a notched shape becomes several chains), `satin` the zigzag columns and their underlay, `strokeFont` a single-line capital alphabet that `arcText` bends around a circle for satin lettering (draw it 5 mm tall or more), and `geom` the outlines (`circle`, `star`, `inset`). `dst` (Tajima: a text header and 3-byte ternary records, a trim written as tiny jumps), `exp` (Melco, Bernina) and `pes` (Brother, Baby Lock: PES v1 written by hand, its PEC section with 7- and 12-bit moves, thread-chart indices and bitmaps) each write and read a `Pattern` (the readers are for checks). `units` turns a pattern into 0.1 mm moves and splits long jumps, `validate` reports stitch count, longest stitch, extents, jumps and color changes against a hoop, `simulate` draws the stitches thread by thread, and `svg` writes the design as a vector drawing in millimeters. None of it has been run on a real machine; sew a test on scrap first. `games/maximus/patch/` is the first design.
170
+
171
+ `kit/actors` builds character sequences and monster paths. `kit/screenText` validates
172
+ 30-column, 16-line DOS text pages and looks up caller-supplied named sprites.
173
+
174
+ `kit/road3d` provides three-lane perspective geometry, timed spawner chains and sprite
175
+ shrinking. `kit/saveSlots` provides PLAYGAME's save-slot rectangles and their backgrounds.
176
+ These helpers take the consuming game's data and palette.
177
+
178
+ ### Image preparation and previews
179
+
180
+ `kit/photo` reads a caller-supplied JPEG (`readScan`) and provides resampling, toning,
181
+ quantization, dithering and indexed photo composition. No photographs are included.
182
+ `kit/png` writes synchronous RGB preview PNGs with a checkerboard for transparent pixels
183
+ and builds block sheets. `kit/levelPicture` renders a level region with its placed monsters, and `kit/levelGrid` is a character grid to paint a level in code.
184
+ These Node build helpers complement the browser-safe `images` API.
185
+
186
+ ### Sound and arrangement helpers
56
187
 
57
- ## Build and inspect
188
+ `audio` / `kit/synthParts` expose low-pass noise, envelopes, gates and filtering.
189
+ `kit/song` builds CMF arrangements from caller-supplied sections; `kit/songFx` adds native
190
+ CMF swells, arpeggios, glides, echoes and rhythm effects. Instrument presets are original
191
+ project data under the MIT License; recordings and complete songs are not included.
58
192
 
59
- From this directory, with the repository's web development dependencies installed:
193
+ ### Mumble-speak (nonsense talk as VOC)
194
+
195
+ `kit/mumble` is a small formant synthesizer that says nonsense, the way a game of 1994 might hum a character's
196
+ talk. A line is a list of syllables `[vowel, fromHz, toHz, seconds, restSeconds?]`. `mumble(line, { rate, gain })`
197
+ returns samples in -1..1, `mumbleVoc(line)` returns an 8-bit mono 11 kHz .VOC, and `syllablesFromText(text, { pitch, speed, seed })`
198
+ turns a line of text into syllables (vowels from its letters, so the same line and seed mumble the same way;
199
+ a question rises, a sentence falls). `MUMBLE_VOICES` has `bright`, `deep` and `small` settings.
200
+
201
+ ```ts
202
+ import { MUMBLE_VOICES, mumbleVoc, syllablesFromText } from '@lewismoten/gamemaker-sandbox-tools/kit/mumble';
203
+
204
+ const voc = mumbleVoc(syllablesFromText('Welcome to the show!', MUMBLE_VOICES.bright)); // write it as HELLO.VOC
205
+ ```
206
+
207
+ ### Native animations and demos
208
+
209
+ `kit/fadeOut` adds palette-only FLI fades. `kit/fliClips` splits long animations at stable
210
+ palette boundaries and builds their slide-list entries; its opt-in `ClipOptions` leave out
211
+ the closing ring frame no player shows (`noLoopFrame`, also an `encodeFli` option) and put
212
+ cuts where a whole frame costs the fewest extra bytes (`cheapCuts`), and run `shrink` steps first.
213
+ `kit/fliShrink` is the size report (`fliReport`: bytes per chunk type per frame, and why) and the shrink
214
+ steps (`sparsePalettesStep` lossless; `holdStillStep`, `snapColorsStep`, `maxColorsStep`,
215
+ `flattenDitherStep`, `dropFramesStep` lossy), each returning the new frames, the bytes saved and how
216
+ visible the change is (`Visibility`: mean, worst, changed share); `decodeFli`/`encodeFrames` convert,
217
+ `shrinkFrames` chains steps. `kit/recordedDemo` turns delta/key
218
+ pairs into a native title demo with configurable Escape press and release delays.
219
+
220
+ ### Shared block sets
221
+
222
+ `kit/shareBlocks` merges several scenes' background blocks into one `.BBL`: only the blocks a
223
+ map uses (and what they change into) are kept, matching blocks and rings become one, a pinned
224
+ number (such as a felt egg's) stays put, and each scene's map is renumbered.
225
+
226
+ ### Look-alike blocks
227
+
228
+ `findLookAlikes` finds background blocks that are drawn the same colors under every palette a set
229
+ is shown with and play the same (it keeps what they turn into in step), and lists blocks that
230
+ share a shape in other colors without joining them: a scene has one palette. `applyFold` removes
231
+ the folded blocks and renumbers maps and links. Import from `@lewismoten/gamemaker-sandbox-tools/look-alike`.
232
+
233
+ ### Versions as deltas
234
+
235
+ `diffVersions`, `applyDelta` and `deltaSize` keep a game's earlier versions like a git repository: a binary file
236
+ is a list of byte-range patches (one recolored block or map cell is a few bytes), a text file (lst, txt, json,
237
+ md...) a line patch, so each version costs only what changed. Lossless for any bytes. Import from
238
+ `@lewismoten/gamemaker-sandbox-tools/delta`.
239
+
240
+ ### Color reduction
241
+
242
+ `reduceBlocks` moves the pixels of blocks that use colors outside their allowed set (a block type's reserved
243
+ range plus the colors nobody reserved) to the nearest allowed color, and scores the change in CIELAB delta E
244
+ (mean over changed pixels, worst pixel; a block is flagged above 6 mean or 20 worst, thresholds a guess). Index
245
+ 0 and 255 never move. Import from `@lewismoten/gamemaker-sandbox-tools/color-reduce`.
246
+
247
+ ### Palette reservations
248
+
249
+ `planRanges` proposes, for a game with no reservations, a range of color numbers for monsters and one for
250
+ characters (sized by the different colors their blocks draw, at most 48 each, starting at 16 because 1-15 look
251
+ like the engine's own interface colors, placed where the fewest other blocks already draw). `syncRange` makes a
252
+ reserved range identical in every palette a role's files are shown with: the role's colors move into the range
253
+ (pixels renumbered, palettes updated), and colors beyond the range's size become the nearest kept one, all scored
254
+ in delta E. Import from `@lewismoten/gamemaker-sandbox-tools/palette-reserve`.
255
+
256
+ ### Joining block sets
257
+
258
+ `mergeBackgroundSets` moves one background set's drawn blocks into another's free slots (reusing an
259
+ identical block already there) and renumbers the moved set's maps; the kept set is not renumbered.
260
+ Pickups, required and starting items and block 0 keep their number or the join is refused.
261
+ Import from `@lewismoten/gamemaker-sandbox-tools/block-merge`.
262
+
263
+ ### Meshes for 3D printing
264
+
265
+ `mesh/surfaceNets` turns a signed distance field (negative inside) into a closed triangle mesh
266
+ (`surfaceNets(field, { min, max, cell })`; it retries with a shifted grid until every edge is in exactly two
267
+ triangles), `mesh/stl` writes and reads binary STL (`writeStl`, `readStl`; a color per triangle goes in the
268
+ attribute bytes the VisCAM way, which slicers ignore) and `mesh/meshCheck` reports whether a mesh is closed,
269
+ how many pieces it has, its size and volume (`inspectMesh`). `mesh/tetraMesh` is the other mesher (four times
270
+ the triangles, but closed for any field, and neighbors meet on the same vertices); `mesh/overhang` measures what
271
+ an FDM printer cannot print (`overhang`) and builds the support pillars as a body of their own (`supportBody`);
272
+ `mesh/colorBodies` picks at most four colors from a colored mesh (`pickPalette`) and splits the solid into one
273
+ closed body per color (`colorBodies`, thinned and grown to the volume you give it); `mesh/decimate` takes the triangles a
274
+ closed mesh does not need out by quadric edge collapse (`decimate(mesh, { maxError })`: stays closed and in one piece, and the
275
+ borders between a triangle color and the next stay put); `mesh/sampledField` samples a field once on a grid and reads it back
276
+ by trilinear interpolation, for the many passes over one figure (`sampledField`); `mesh/threeMf` writes and reads multi-color 3MF files (`write3mf(parts,
277
+ title, codec)`, `read3mf`: parts are a mesh and a color), over the small ZIP writer `mesh/zipFile` (pass Node's
278
+ `deflateRawSync` as `codec.deflate` to compress). `pack/meshPack` packs a binary STL losslessly into a much smaller file
279
+ (`packStl`, `unpackStl`: a table of distinct corners in byte planes, corner numbers as varints, normals worked out again;
280
+ deflate the result) and gives the pieces (`toPlanes`, `packIndices`) for other mesh files; `pack/threeMfPack` does the same
281
+ for a 3MF `write3mf` wrote (`pack3mf`, `unpack3mf`: corners in thousandths, as the file has them; `threeMfEntries` makes
282
+ its inner files again, the same bytes, to zip with any deflate). `mesh/voxel` meshes filled voxels (`voxelMesh`: coplanar faces merged into
283
+ rectangles, no T-junctions, so it stays closed) and `mesh/pixelFigure` turns a pixel sprite into a standee on a base with at
284
+ most four color bodies (`pixelFigure`). They are browser safe, except `mesh/trinketTool`.
285
+
286
+ Trinkets made of distance fields (Depth Perception's, Quest for the Round Tuit's) share one pipeline, all in millimeters
287
+ with the floor at z = 0: `mesh/sdfShapes` has the 2D shapes (circle, rounded rectangle, polygon, ring, capsule and
288
+ `pixelText2`, lettering in the 3x5 micro font), `extrude` and the solid combiners; `mesh/strokeText` (`strokeText2`, `ringText2`) letters raised or sunk text in smooth capsule strokes (capitals, digits, marks; use it instead of the stair-stepped `pixelText2` for anything printed); `mesh/figureShapes` has ellipsoids, round cones, a smooth union and `place3` for 3D figures; `mesh/trinketKinds` builds a `plate` (coin,
289
+ token, key-chain tag or badge: outline, raised rim, raised relief, sunk art, holes, a pin-back `pocket` from `pinBack`), a key-chain `ringTab`, a faceted `gem` (also a crystal shard) and a `die`; `mesh/fieldTrinket`
290
+ (`meshFieldTrinket`) meshes a field with a color per triangle and gives the checks (eroded pieces and specks, overhang),
291
+ up to four color bodies and supports; `mesh/trinketTool` (`runTrinketTool`, Node only) writes the STL, 3MF and manifest.json
292
+ of a game's trinkets, with a source key so an unchanged game is skipped, in worker threads when `--workers N` runs a bundle.
293
+ A game keeps its designs in `games/<id>/src/trinkets/` (`TRINKETS` and `makeTrinket`) and a four-line `tools/trinkets.ts`.
294
+ Surface nets need a cell smaller than half of any gap between pieces (a 0.6 mm kerf wants a 0.26 mm cell).
295
+
296
+ ### Disk comparison
297
+
298
+ `diffDisks(a, b)` takes two `Map<name, bytes>` disks and returns the added, removed and changed files, with a plain-text
299
+ summary per changed file by type (`.gam`, `.pal`, blocks, `.map`, `.chr`, `.mon`, text, GIF, FLI, VOC, else bytes).
300
+ `formatDiff` prints it, sorted and the same every time. Import from
301
+ `@lewismoten/gamemaker-sandbox-tools/disk-diff`; `npm run disk:diff` in `web/` is the command line.
302
+ `releaseNotes(diff)` (`.../release-notes`) turns a diff into short paste-ready text grouped by kind of file, such as
303
+ "Changed 2 maps (A.MAP, B.MAP) and 1 palette (X.PAL). Added 1 sound (SONG3.VOC)."; `disk:diff -- --notes` prints it.
304
+
305
+ ### Headless checking
306
+
307
+ `kit/hopBot` provides configurable hopping, steering and retry support for `GameSim`.
308
+ `kit/align` audits caller-supplied disks, multi-block layouts and pixel seams; finding the
309
+ games to audit and reporting the results belong to the consumer. `simulation` also exposes route scene
310
+ assertions and scene initialization that delegates to the engine. `GameSimState` names
311
+ the snapshot type; compatibility initialization preserves older block-birth bookkeeping.
312
+
313
+ ### DOS disk output
314
+
315
+ `kit/disk` exports `Disk` for collecting 8.3-named files and writing a clean output
316
+ directory, plus the legacy `dosText` byte conversion. Destination and metadata are
317
+ caller-supplied. `kit/menuVersion` can stamp a supplied version on a native menu GIF;
318
+ this package reads no game metadata files and imposes no version policy.
319
+
320
+ `kit/palRamps` also exports `wrapWithBuilder` and `buildRampPalette`: supply ramp
321
+ descriptors, optional named endpoint replacements, and a color transform. The game
322
+ keeps its actual colors and lighting choices. `colors` and `text` are direct browser-safe
323
+ entries for the existing lighting, ramp, glyph-row, and rendered-text APIs.
324
+
325
+ `kit/textfit` audits caller-supplied native files for menu, save-slot, score-table and
326
+ text-page layout and contrast. Choosing which games to check, and printing the results, are left to the consumer.
327
+
328
+ ## Original Library palette
329
+
330
+ `libraryDefaultPalette()` from `@lewismoten/gamemaker-sandbox-tools/palettes` returns
331
+ an independent 768-byte copy of the CD Library's `DEFAULT.PAL`, with black at index
332
+ zero. This is the original RSD palette, rather than the engine's generated fallback.
333
+ It works in browsers and Node without fetching the CD or using repository files.
334
+ See `NOTICE.md` for its source and license.
335
+
336
+ ### Palette templates
337
+
338
+ `PALETTE_PRESETS` from `palettes` lists 20 ready-made templates with names, descriptions,
339
+ occupied entry counts and DOS-safe filename stems. `createPalettePreset(id)` returns a fresh
340
+ 768-byte VGA palette with menu black at index 0, transparency reserved at 255, and unused
341
+ entries black. Templates include monochrome, Atari NTSC/PAL, NES, CGA, EGA, EGA with skin/hair
342
+ ramps, LCD greens, Sega Master System, Commodore 64, web-safe colors and grayscale steps.
343
+ 128-step grayscale necessarily repeats VGA's 64 distinct gray shades. LCD greens include
344
+ four green shades plus menu black. Console RGB references and their licenses are in NOTICE.md;
345
+ all values are adapted to six-bit VGA and do not impose the original consoles' drawing limits.
346
+
347
+ ## Developing
348
+
349
+ This package's source lives in [the project's repository](https://github.com/lewismoten/GameMaker-SandboxEdition), in `web/packages/tools`. The folder holds its builders in `src/`, build configuration, license and notices. Shared codecs and runtime types come through declared engine and archives dependencies, and it never reads source from another repository folder. After `npm install` in a standalone copy, or `npm ci` at the repository root:
60
350
 
61
351
  ```sh
62
352
  npm run build
@@ -64,14 +354,10 @@ npm run verify
64
354
  npm pack
65
355
  ```
66
356
 
67
- The build bundles source from the format, drawing, audio, and simulation modules. It does not use or restart the site's Vite configuration. The tarball contains JavaScript, declarations, this guide, the MIT license, and notices. Validate a packed installation in a separate project before publishing.
68
-
69
- `verify` installs the tarball in a temporary npm consumer and checks codecs, drawing, sound generation, headless simulation, NodeNext declarations, absence of game content, and rejected browser imports. After reviewing the candidate, publish with `npm publish --access public`; publishing is a separate action.
70
-
71
- ## Tagged releases
357
+ The build bundles source from the format, drawing, audio, and simulation modules. It does not use or restart the site's Vite configuration. The tarball contains JavaScript, declarations, this guide, the MIT license, and notices. From the repository root, `npm run verify:packages` copies each package outside the repository, builds it with packed declared dependencies, and tests its npm distribution, which also supports unpublished sibling versions.
72
358
 
73
- The [release workflow](../../../.github/workflows/publish-tools.yml) publishes to the public npm registry when a `tools-v<version>` tag is pushed. The tag must match this package's version and point to a commit on `master`. For this release, use `tools-v3.1.0` after merging the package changes.
359
+ `verify` installs the tarball in a temporary npm consumer and checks codecs, drawing, sound generation, headless simulation, NodeNext declarations, absence of game content, and rejected browser imports. Tarballs are local build artifacts and must not be committed to a consuming project. The [monorepo guide](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/master/docs/monorepo.md) covers the workspace layout, and the [package release guide](https://github.com/lewismoten/GameMaker-SandboxEdition/blob/master/docs/package-releases.md) covers publishing.
74
360
 
75
- Configure the repository's `NPM_TOKEN` Actions secret with an npm publishing token authorized for `@lewismoten/gamemaker-sandbox-tools` (including automated publishing with 2FA). The workflow checks source, builds and verifies the packed package, then publishes with provenance. Ordinary branch pushes do not publish anything. See npm's [publishing documentation](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
361
+ ## License and notices
76
362
 
77
- Tarballs are local build artifacts and must not be committed to a consuming project. Consumers should use `npm install --save-dev @lewismoten/gamemaker-sandbox-tools@^3.1.0` after the tagged release is published.
363
+ The source is MIT licensed. The published package carries `LICENSE` and `NOTICE.md` (credits for third-party code and formats); it includes no game assets.
@@ -0,0 +1,82 @@
1
+ import { execFileSync as l } from "node:child_process";
2
+ import { statSync as u, readFileSync as d } from "node:fs";
3
+ import { fileURLToPath as p } from "node:url";
4
+ import { encodeVoc as g } from "@lewismoten/gamemaker-sandbox-engine/formats/voc";
5
+ function h(t) {
6
+ const n = (a) => String.fromCharCode(...t.subarray(a, a + 4));
7
+ if (t.length < 12 || n(0) !== "RIFF" || n(8) !== "WAVE") return;
8
+ const r = new DataView(t.buffer, t.byteOffset, t.byteLength);
9
+ let o, m;
10
+ for (let a = 12; a + 8 <= t.length; ) {
11
+ const i = n(a), s = r.getUint32(a + 4, !0), e = a + 8;
12
+ if (s > t.length - e) throw new Error("Truncated WAV chunk");
13
+ if (i === "fmt ") {
14
+ if (s < 16) throw new Error("Truncated WAV format");
15
+ if (r.getUint16(e, !0) !== 1 || r.getUint16(e + 2, !0) !== 1 || r.getUint16(e + 14, !0) !== 8) return;
16
+ if (r.getUint16(e + 12, !0) !== 1) throw new Error("Invalid mono 8-bit WAV alignment");
17
+ if (o = r.getUint32(e + 4, !0), !o) throw new Error("Invalid WAV sample rate");
18
+ } else i === "data" && (m = t.subarray(e, e + s));
19
+ a = e + s + (s & 1);
20
+ }
21
+ if (!o || !m) throw new Error("WAV is missing its format or sample data");
22
+ return { sampleRate: o, samples: m };
23
+ }
24
+ function c(t, n) {
25
+ if (!Number.isSafeInteger(t) || t <= 0) throw new RangeError(`${n} must be a positive integer`);
26
+ }
27
+ function w(t, n = {}) {
28
+ const r = n.sampleRate ?? 11025, o = n.maxSamples ?? 16 * 1024 * 1024, m = n.timeoutMs ?? 3e4;
29
+ if (c(r, "sampleRate"), c(o, "maxSamples"), c(m, "timeoutMs"), r < 3906 || r > 1e6) throw new RangeError("sampleRate is outside the VOC time-constant range (3906–1000000 Hz)");
30
+ const a = t instanceof URL ? p(t) : t;
31
+ if (!a) throw new TypeError("An audio file path is required");
32
+ let i;
33
+ if (/\.wav$/i.test(a) && u(a).size <= o + 65536) {
34
+ const e = h(d(a));
35
+ e?.sampleRate === r && (i = e.samples);
36
+ }
37
+ try {
38
+ i ??= l(
39
+ n.ffmpegPath ?? "ffmpeg",
40
+ [
41
+ "-nostdin",
42
+ "-hide_banner",
43
+ "-loglevel",
44
+ "error",
45
+ "-i",
46
+ a,
47
+ "-map",
48
+ "0:a:0",
49
+ "-vn",
50
+ "-ac",
51
+ "1",
52
+ "-ar",
53
+ String(r),
54
+ "-af",
55
+ "aresample=dither_method=none",
56
+ "-c:a",
57
+ "pcm_u8",
58
+ "-f",
59
+ "u8",
60
+ "pipe:1"
61
+ ],
62
+ { timeout: m, maxBuffer: o, stdio: ["ignore", "pipe", "pipe"] }
63
+ );
64
+ } catch (e) {
65
+ const f = e.code;
66
+ throw f === "ENOENT" ? new Error("FFmpeg is required to convert audio files. Install it or set ffmpegPath.", { cause: e }) : f === "ENOBUFS" || f === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ? new RangeError(`Decoded audio exceeds ${o} samples`, { cause: e }) : new Error("FFmpeg could not decode the audio file within the conversion limits.", { cause: e });
67
+ }
68
+ if (i.length > o) throw new RangeError(`Decoded audio exceeds ${o} samples`);
69
+ const s = new Float32Array(i.length);
70
+ for (let e = 0; e < i.length; e++) s[e] = (i[e] - 128) / 127;
71
+ return s;
72
+ }
73
+ function v(t, n = {}) {
74
+ const r = n.maxBytes ?? 65535;
75
+ if (!Number.isSafeInteger(r) || r < 34 || r > 65535) throw new RangeError("maxBytes must be between 34 and 65535");
76
+ const o = w(t, { ...n, maxSamples: r - 33 });
77
+ return g(o, n.sampleRate ?? 11025);
78
+ }
79
+ export {
80
+ v as audioFileToVoc,
81
+ w as decodeAudioFile
82
+ };