sci2-ts 0.0.0-stage → 0.2.2

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 (357) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +21 -0
  3. package/README.md +113 -2
  4. package/apps/viewer/editor.html +43 -0
  5. package/apps/viewer/explore.html +27 -0
  6. package/apps/viewer/index.html +26 -0
  7. package/apps/viewer/package.json +27 -0
  8. package/apps/viewer/play.html +26 -0
  9. package/apps/viewer/plugin.d.ts +18 -0
  10. package/apps/viewer/plugin.js +75 -0
  11. package/apps/viewer/plugin.ts +84 -0
  12. package/apps/viewer/src/adlib.d.ts +20 -0
  13. package/apps/viewer/src/adlib.js +55 -0
  14. package/apps/viewer/src/adlib.ts +62 -0
  15. package/apps/viewer/src/app.d.ts +5 -0
  16. package/apps/viewer/src/app.js +5 -0
  17. package/apps/viewer/src/app.ts +5 -0
  18. package/apps/viewer/src/asset-index.d.ts +22 -0
  19. package/apps/viewer/src/asset-index.js +74 -0
  20. package/apps/viewer/src/asset-index.ts +90 -0
  21. package/apps/viewer/src/audio.d.ts +28 -0
  22. package/apps/viewer/src/audio.js +102 -0
  23. package/apps/viewer/src/audio.ts +110 -0
  24. package/apps/viewer/src/editor-handles.d.ts +63 -0
  25. package/apps/viewer/src/editor-handles.js +332 -0
  26. package/apps/viewer/src/editor-handles.ts +368 -0
  27. package/apps/viewer/src/editor-languages.d.ts +23 -0
  28. package/apps/viewer/src/editor-languages.js +157 -0
  29. package/apps/viewer/src/editor-languages.ts +135 -0
  30. package/apps/viewer/src/editor.css +213 -0
  31. package/apps/viewer/src/editor.d.ts +1 -0
  32. package/apps/viewer/src/editor.js +393 -0
  33. package/apps/viewer/src/editor.ts +412 -0
  34. package/apps/viewer/src/explore/classes.d.ts +7 -0
  35. package/apps/viewer/src/explore/classes.js +63 -0
  36. package/apps/viewer/src/explore/classes.ts +61 -0
  37. package/apps/viewer/src/explore/context.d.ts +33 -0
  38. package/apps/viewer/src/explore/context.js +96 -0
  39. package/apps/viewer/src/explore/context.ts +124 -0
  40. package/apps/viewer/src/explore/explore.css +93 -0
  41. package/apps/viewer/src/explore/explore.d.ts +1 -0
  42. package/apps/viewer/src/explore/explore.js +102 -0
  43. package/apps/viewer/src/explore/explore.ts +104 -0
  44. package/apps/viewer/src/explore/inspect.d.ts +5 -0
  45. package/apps/viewer/src/explore/inspect.js +208 -0
  46. package/apps/viewer/src/explore/inspect.ts +279 -0
  47. package/apps/viewer/src/explore/live.d.ts +22 -0
  48. package/apps/viewer/src/explore/live.js +318 -0
  49. package/apps/viewer/src/explore/live.ts +365 -0
  50. package/apps/viewer/src/explore/map.d.ts +11 -0
  51. package/apps/viewer/src/explore/map.js +182 -0
  52. package/apps/viewer/src/explore/map.ts +193 -0
  53. package/apps/viewer/src/files.d.ts +21 -0
  54. package/apps/viewer/src/files.js +69 -0
  55. package/apps/viewer/src/files.ts +72 -0
  56. package/apps/viewer/src/game-profile.d.ts +19 -0
  57. package/apps/viewer/src/game-profile.js +4 -0
  58. package/apps/viewer/src/game-profile.ts +26 -0
  59. package/apps/viewer/src/main.d.ts +1 -0
  60. package/apps/viewer/src/main.js +473 -0
  61. package/apps/viewer/src/main.ts +527 -0
  62. package/apps/viewer/src/music.d.ts +14 -0
  63. package/apps/viewer/src/music.js +32 -0
  64. package/apps/viewer/src/music.ts +34 -0
  65. package/apps/viewer/src/opl-worklet.d.ts +1 -0
  66. package/apps/viewer/src/opl-worklet.js +47 -0
  67. package/apps/viewer/src/opl-worklet.ts +55 -0
  68. package/apps/viewer/src/overlay.d.ts +31 -0
  69. package/apps/viewer/src/overlay.js +103 -0
  70. package/apps/viewer/src/overlay.ts +123 -0
  71. package/apps/viewer/src/play.css +14 -0
  72. package/apps/viewer/src/play.d.ts +1 -0
  73. package/apps/viewer/src/play.js +179 -0
  74. package/apps/viewer/src/play.ts +177 -0
  75. package/apps/viewer/src/saves.d.ts +10 -0
  76. package/apps/viewer/src/saves.js +50 -0
  77. package/apps/viewer/src/saves.ts +51 -0
  78. package/apps/viewer/src/session.d.ts +91 -0
  79. package/apps/viewer/src/session.js +301 -0
  80. package/apps/viewer/src/session.ts +321 -0
  81. package/apps/viewer/src/sound-preview.d.ts +7 -0
  82. package/apps/viewer/src/sound-preview.js +214 -0
  83. package/apps/viewer/src/sound-preview.ts +228 -0
  84. package/apps/viewer/src/style.css +64 -0
  85. package/apps/viewer/vite.config.ts +25 -0
  86. package/bin/sci-ts.mjs +9 -0
  87. package/lib/994.sc +49 -0
  88. package/lib/995.sc +53 -0
  89. package/lib/996.sc +299 -0
  90. package/lib/997.sc +198 -0
  91. package/lib/998.sc +338 -0
  92. package/lib/999.sc +189 -0
  93. package/lib/resources.d.ts +2 -0
  94. package/lib/resources.js +84 -0
  95. package/lib/resources.ts +88 -0
  96. package/lib/system.sh +62 -0
  97. package/package.json +75 -4
  98. package/packages/content/room.schema.json +267 -0
  99. package/packages/content/src/index.d.ts +3 -0
  100. package/packages/content/src/index.js +3 -0
  101. package/packages/content/src/index.ts +3 -0
  102. package/packages/content/src/room.d.ts +111 -0
  103. package/packages/content/src/room.js +886 -0
  104. package/packages/content/src/room.ts +1011 -0
  105. package/packages/content/src/target.d.ts +80 -0
  106. package/packages/content/src/target.js +1 -0
  107. package/packages/content/src/target.ts +60 -0
  108. package/packages/content/src/yarn.d.ts +90 -0
  109. package/packages/content/src/yarn.js +214 -0
  110. package/packages/content/src/yarn.ts +261 -0
  111. package/packages/sci/src/analysis/game.d.ts +90 -0
  112. package/packages/sci/src/analysis/game.js +221 -0
  113. package/packages/sci/src/analysis/game.ts +305 -0
  114. package/packages/sci/src/analysis/runtime.d.ts +58 -0
  115. package/packages/sci/src/analysis/runtime.js +133 -0
  116. package/packages/sci/src/analysis/runtime.ts +163 -0
  117. package/packages/sci/src/audio/adlib.d.ts +73 -0
  118. package/packages/sci/src/audio/adlib.js +280 -0
  119. package/packages/sci/src/audio/adlib.ts +329 -0
  120. package/packages/sci/src/audio/index.d.ts +43 -0
  121. package/packages/sci/src/audio/index.js +99 -0
  122. package/packages/sci/src/audio/index.ts +122 -0
  123. package/packages/sci/src/audio/midi.d.ts +92 -0
  124. package/packages/sci/src/audio/midi.js +242 -0
  125. package/packages/sci/src/audio/midi.ts +262 -0
  126. package/packages/sci/src/audio/opl2.d.ts +74 -0
  127. package/packages/sci/src/audio/opl2.js +283 -0
  128. package/packages/sci/src/audio/opl2.ts +283 -0
  129. package/packages/sci/src/audio/sol.d.ts +32 -0
  130. package/packages/sci/src/audio/sol.js +81 -0
  131. package/packages/sci/src/audio/sol.ts +100 -0
  132. package/packages/sci/src/audio/write.d.ts +35 -0
  133. package/packages/sci/src/audio/write.js +91 -0
  134. package/packages/sci/src/audio/write.ts +108 -0
  135. package/packages/sci/src/gfx/cel.d.ts +36 -0
  136. package/packages/sci/src/gfx/cel.js +82 -0
  137. package/packages/sci/src/gfx/cel.ts +110 -0
  138. package/packages/sci/src/gfx/palette.d.ts +24 -0
  139. package/packages/sci/src/gfx/palette.js +49 -0
  140. package/packages/sci/src/gfx/palette.ts +56 -0
  141. package/packages/sci/src/gfx/pic-file.d.ts +46 -0
  142. package/packages/sci/src/gfx/pic-file.js +114 -0
  143. package/packages/sci/src/gfx/pic-file.ts +155 -0
  144. package/packages/sci/src/gfx/pic.d.ts +27 -0
  145. package/packages/sci/src/gfx/pic.js +34 -0
  146. package/packages/sci/src/gfx/pic.ts +53 -0
  147. package/packages/sci/src/gfx/quantize.d.ts +42 -0
  148. package/packages/sci/src/gfx/quantize.js +199 -0
  149. package/packages/sci/src/gfx/quantize.ts +218 -0
  150. package/packages/sci/src/gfx/view-file.d.ts +62 -0
  151. package/packages/sci/src/gfx/view-file.js +182 -0
  152. package/packages/sci/src/gfx/view-file.ts +233 -0
  153. package/packages/sci/src/gfx/view.d.ts +28 -0
  154. package/packages/sci/src/gfx/view.js +45 -0
  155. package/packages/sci/src/gfx/view.ts +62 -0
  156. package/packages/sci/src/index.d.ts +38 -0
  157. package/packages/sci/src/index.js +38 -0
  158. package/packages/sci/src/index.ts +38 -0
  159. package/packages/sci/src/motion/pathfinding.d.ts +40 -0
  160. package/packages/sci/src/motion/pathfinding.js +140 -0
  161. package/packages/sci/src/motion/pathfinding.ts +147 -0
  162. package/packages/sci/src/resource/archive.d.ts +16 -0
  163. package/packages/sci/src/resource/archive.js +51 -0
  164. package/packages/sci/src/resource/archive.ts +56 -0
  165. package/packages/sci/src/resource/lzs.d.ts +12 -0
  166. package/packages/sci/src/resource/lzs.js +64 -0
  167. package/packages/sci/src/resource/lzs.ts +66 -0
  168. package/packages/sci/src/resource/manager.d.ts +45 -0
  169. package/packages/sci/src/resource/manager.js +158 -0
  170. package/packages/sci/src/resource/manager.ts +184 -0
  171. package/packages/sci/src/resource/map.d.ts +18 -0
  172. package/packages/sci/src/resource/map.js +34 -0
  173. package/packages/sci/src/resource/map.ts +44 -0
  174. package/packages/sci/src/resource/types.d.ts +37 -0
  175. package/packages/sci/src/resource/types.js +45 -0
  176. package/packages/sci/src/resource/types.ts +57 -0
  177. package/packages/sci/src/script/assembly.d.ts +67 -0
  178. package/packages/sci/src/script/assembly.js +748 -0
  179. package/packages/sci/src/script/assembly.ts +714 -0
  180. package/packages/sci/src/script/compiler.d.ts +75 -0
  181. package/packages/sci/src/script/compiler.js +993 -0
  182. package/packages/sci/src/script/compiler.ts +1040 -0
  183. package/packages/sci/src/script/disasm.d.ts +81 -0
  184. package/packages/sci/src/script/disasm.js +318 -0
  185. package/packages/sci/src/script/disasm.ts +323 -0
  186. package/packages/sci/src/script/kernel-names.d.ts +6 -0
  187. package/packages/sci/src/script/kernel-names.js +165 -0
  188. package/packages/sci/src/script/kernel-names.ts +165 -0
  189. package/packages/sci/src/script/opcodes.d.ts +22 -0
  190. package/packages/sci/src/script/opcodes.js +45 -0
  191. package/packages/sci/src/script/opcodes.ts +72 -0
  192. package/packages/sci/src/script/script.d.ts +56 -0
  193. package/packages/sci/src/script/script.js +63 -0
  194. package/packages/sci/src/script/script.ts +111 -0
  195. package/packages/sci/src/script/sexpr.d.ts +45 -0
  196. package/packages/sci/src/script/sexpr.js +151 -0
  197. package/packages/sci/src/script/sexpr.ts +139 -0
  198. package/packages/sci/src/script/vocab.d.ts +15 -0
  199. package/packages/sci/src/script/vocab.js +44 -0
  200. package/packages/sci/src/script/vocab.ts +48 -0
  201. package/packages/sci/src/script/world.d.ts +25 -0
  202. package/packages/sci/src/script/world.js +65 -0
  203. package/packages/sci/src/script/world.ts +70 -0
  204. package/packages/sci/src/text/font.d.ts +37 -0
  205. package/packages/sci/src/text/font.js +103 -0
  206. package/packages/sci/src/text/font.ts +125 -0
  207. package/packages/sci/src/text/message.d.ts +69 -0
  208. package/packages/sci/src/text/message.js +171 -0
  209. package/packages/sci/src/text/message.ts +205 -0
  210. package/packages/sci/src/vm/kernels/arrays.d.ts +19 -0
  211. package/packages/sci/src/vm/kernels/arrays.js +182 -0
  212. package/packages/sci/src/vm/kernels/arrays.ts +164 -0
  213. package/packages/sci/src/vm/kernels/audio.d.ts +70 -0
  214. package/packages/sci/src/vm/kernels/audio.js +347 -0
  215. package/packages/sci/src/vm/kernels/audio.ts +349 -0
  216. package/packages/sci/src/vm/kernels/core.d.ts +5 -0
  217. package/packages/sci/src/vm/kernels/core.js +87 -0
  218. package/packages/sci/src/vm/kernels/core.ts +91 -0
  219. package/packages/sci/src/vm/kernels/graphics.d.ts +141 -0
  220. package/packages/sci/src/vm/kernels/graphics.js +467 -0
  221. package/packages/sci/src/vm/kernels/graphics.ts +502 -0
  222. package/packages/sci/src/vm/kernels/index.d.ts +8 -0
  223. package/packages/sci/src/vm/kernels/index.js +29 -0
  224. package/packages/sci/src/vm/kernels/index.ts +32 -0
  225. package/packages/sci/src/vm/kernels/lists.d.ts +6 -0
  226. package/packages/sci/src/vm/kernels/lists.js +127 -0
  227. package/packages/sci/src/vm/kernels/lists.ts +111 -0
  228. package/packages/sci/src/vm/kernels/motion.d.ts +7 -0
  229. package/packages/sci/src/vm/kernels/motion.js +204 -0
  230. package/packages/sci/src/vm/kernels/motion.ts +194 -0
  231. package/packages/sci/src/vm/kernels/palette.d.ts +82 -0
  232. package/packages/sci/src/vm/kernels/palette.js +292 -0
  233. package/packages/sci/src/vm/kernels/palette.ts +303 -0
  234. package/packages/sci/src/vm/kernels/saves.d.ts +45 -0
  235. package/packages/sci/src/vm/kernels/saves.js +123 -0
  236. package/packages/sci/src/vm/kernels/saves.ts +149 -0
  237. package/packages/sci/src/vm/kernels/system.d.ts +62 -0
  238. package/packages/sci/src/vm/kernels/system.js +110 -0
  239. package/packages/sci/src/vm/kernels/system.ts +128 -0
  240. package/packages/sci/src/vm/kernels/text.d.ts +13 -0
  241. package/packages/sci/src/vm/kernels/text.js +338 -0
  242. package/packages/sci/src/vm/kernels/text.ts +328 -0
  243. package/packages/sci/src/vm/memory.d.ts +138 -0
  244. package/packages/sci/src/vm/memory.js +168 -0
  245. package/packages/sci/src/vm/memory.ts +266 -0
  246. package/packages/sci/src/vm/replace.d.ts +11 -0
  247. package/packages/sci/src/vm/replace.js +14 -0
  248. package/packages/sci/src/vm/replace.ts +16 -0
  249. package/packages/sci/src/vm/savegame.d.ts +89 -0
  250. package/packages/sci/src/vm/savegame.js +161 -0
  251. package/packages/sci/src/vm/savegame.ts +188 -0
  252. package/packages/sci/src/vm/value.d.ts +17 -0
  253. package/packages/sci/src/vm/value.js +12 -0
  254. package/packages/sci/src/vm/value.ts +25 -0
  255. package/packages/sci/src/vm/vm.d.ts +155 -0
  256. package/packages/sci/src/vm/vm.js +1053 -0
  257. package/packages/sci/src/vm/vm.ts +914 -0
  258. package/tools/adlib-render.d.ts +1 -0
  259. package/tools/adlib-render.js +49 -0
  260. package/tools/adlib-render.ts +42 -0
  261. package/tools/analyze.d.ts +1 -0
  262. package/tools/analyze.js +25 -0
  263. package/tools/analyze.ts +25 -0
  264. package/tools/art/build.d.ts +34 -0
  265. package/tools/art/build.js +175 -0
  266. package/tools/art/build.ts +153 -0
  267. package/tools/art.d.ts +1 -0
  268. package/tools/art.js +31 -0
  269. package/tools/art.ts +29 -0
  270. package/tools/asm.d.ts +1 -0
  271. package/tools/asm.js +61 -0
  272. package/tools/asm.ts +55 -0
  273. package/tools/cli.d.ts +1 -0
  274. package/tools/cli.js +99 -0
  275. package/tools/cli.ts +100 -0
  276. package/tools/editor-server.d.ts +29 -0
  277. package/tools/editor-server.js +162 -0
  278. package/tools/editor-server.ts +176 -0
  279. package/tools/explore.d.ts +1 -0
  280. package/tools/explore.js +305 -0
  281. package/tools/explore.ts +250 -0
  282. package/tools/game/audio.d.ts +19 -0
  283. package/tools/game/audio.js +143 -0
  284. package/tools/game/audio.ts +130 -0
  285. package/tools/game/build.d.ts +46 -0
  286. package/tools/game/build.js +259 -0
  287. package/tools/game/build.ts +283 -0
  288. package/tools/game/defaults.d.ts +26 -0
  289. package/tools/game/defaults.js +82 -0
  290. package/tools/game/defaults.ts +83 -0
  291. package/tools/game/font.d.ts +3 -0
  292. package/tools/game/font.js +124 -0
  293. package/tools/game/font.ts +126 -0
  294. package/tools/game/kit.d.ts +7 -0
  295. package/tools/game/kit.js +7 -0
  296. package/tools/game/kit.ts +10 -0
  297. package/tools/game/new.d.ts +8 -0
  298. package/tools/game/new.js +39 -0
  299. package/tools/game/new.ts +38 -0
  300. package/tools/game/target.d.ts +7 -0
  301. package/tools/game/target.js +41 -0
  302. package/tools/game/target.ts +42 -0
  303. package/tools/game/template/resources.ts.tmpl +43 -0
  304. package/tools/game/template/rooms/1.room.yaml +9 -0
  305. package/tools/game/template/rooms/1.yarn +17 -0
  306. package/tools/game/template/scripts/0.sc +24 -0
  307. package/tools/game.d.ts +1 -0
  308. package/tools/game.js +77 -0
  309. package/tools/game.ts +70 -0
  310. package/tools/mod-build.d.ts +28 -0
  311. package/tools/mod-build.js +173 -0
  312. package/tools/mod-build.ts +179 -0
  313. package/tools/mod-target.d.ts +16 -0
  314. package/tools/mod-target.js +26 -0
  315. package/tools/mod-target.ts +32 -0
  316. package/tools/mod.d.ts +1 -0
  317. package/tools/mod.js +47 -0
  318. package/tools/mod.ts +45 -0
  319. package/tools/msg.d.ts +1 -0
  320. package/tools/msg.js +40 -0
  321. package/tools/msg.ts +36 -0
  322. package/tools/node-files.d.ts +3 -0
  323. package/tools/node-files.js +34 -0
  324. package/tools/node-files.ts +33 -0
  325. package/tools/patches.d.ts +3 -0
  326. package/tools/patches.js +13 -0
  327. package/tools/patches.ts +13 -0
  328. package/tools/pic-build.d.ts +9 -0
  329. package/tools/pic-build.js +26 -0
  330. package/tools/pic-build.ts +27 -0
  331. package/tools/pic.d.ts +1 -0
  332. package/tools/pic.js +64 -0
  333. package/tools/pic.ts +61 -0
  334. package/tools/play.d.ts +1 -0
  335. package/tools/play.js +54 -0
  336. package/tools/play.ts +54 -0
  337. package/tools/png.d.ts +16 -0
  338. package/tools/png.js +124 -0
  339. package/tools/png.ts +123 -0
  340. package/tools/res.d.ts +1 -0
  341. package/tools/res.js +48 -0
  342. package/tools/res.ts +50 -0
  343. package/tools/scenario.d.ts +1 -0
  344. package/tools/scenario.js +74 -0
  345. package/tools/scenario.ts +80 -0
  346. package/tools/site/build.d.ts +8 -0
  347. package/tools/site/build.js +110 -0
  348. package/tools/site/build.ts +116 -0
  349. package/tools/site/markdown.d.ts +11 -0
  350. package/tools/site/markdown.js +88 -0
  351. package/tools/site/markdown.ts +84 -0
  352. package/tools/view-build.d.ts +34 -0
  353. package/tools/view-build.js +47 -0
  354. package/tools/view-build.ts +71 -0
  355. package/tools/view.d.ts +1 -0
  356. package/tools/view.js +54 -0
  357. package/tools/view.ts +52 -0
@@ -0,0 +1,138 @@
1
+ import { type Script } from "../script/script.ts";
2
+ import { type Value } from "./value.ts";
3
+ /** A script loaded into the VM: its own segment, mutable locals and live objects. */
4
+ export interface LoadedScript {
5
+ number: number;
6
+ script: Script;
7
+ segment: number;
8
+ /** Segment used for pointers to this script's locals (from `lea`). */
9
+ localsSegment: number;
10
+ /** Local variables (script 0's locals are the game's globals). */
11
+ locals: Value[];
12
+ /** Live objects by heap offset. */
13
+ objects: Map<number, SciObject>;
14
+ code: Uint8Array;
15
+ codeView: DataView;
16
+ }
17
+ /**
18
+ * An object at runtime. Property slots are full Values (they can hold references),
19
+ * unlike the 16-bit words in the heap resource they're initialised from.
20
+ */
21
+ export interface SciObject {
22
+ address: Value;
23
+ name: string;
24
+ /** Script whose code implements this object's own methods. */
25
+ script: LoadedScript;
26
+ vars: Value[];
27
+ isClass: boolean;
28
+ /** Own methods: selector → code offset in `script`. Clones share their parent's. */
29
+ methods: Map<number, number>;
30
+ /** Selector → property slot. Shared by every object of a class. */
31
+ propIndex: Map<number, number>;
32
+ /** Class number where method lookup continues after `methods`. */
33
+ superclass: number;
34
+ /** For classes: own class number. For instances/clones: their class's. */
35
+ species: number;
36
+ isClone: boolean;
37
+ /** For clones: the script object whose methods/layout it uses (cloning a clone = cloning this). */
38
+ template: SciObject | undefined;
39
+ }
40
+ export type ArrayType = "int16" | "id" | "byte" | "string";
41
+ /** SCI32 dynamic array (kArray / kString). Byte and string arrays hold 0..255. */
42
+ export interface SciArray {
43
+ type: ArrayType;
44
+ data: Value[];
45
+ }
46
+ export interface ListNode {
47
+ address: Value;
48
+ value: Value;
49
+ key: Value;
50
+ prev: ListNode | undefined;
51
+ next: ListNode | undefined;
52
+ list: SciList | undefined;
53
+ }
54
+ export interface SciList {
55
+ address: Value;
56
+ first: ListNode | undefined;
57
+ last: ListNode | undefined;
58
+ }
59
+ /** SCI32 in-memory bitmap (text boxes and other script-drawn images), 8-bit indexed. */
60
+ export interface SciBitmap {
61
+ width: number;
62
+ height: number;
63
+ pixels: Uint8Array;
64
+ skipColor: number;
65
+ originX: number;
66
+ originY: number;
67
+ }
68
+ export type Segment = {
69
+ kind: "script";
70
+ script: LoadedScript;
71
+ } | {
72
+ kind: "locals";
73
+ script: LoadedScript;
74
+ } | {
75
+ kind: "clone";
76
+ object: SciObject;
77
+ } | {
78
+ kind: "stack";
79
+ } | {
80
+ kind: "array";
81
+ array: SciArray;
82
+ } | {
83
+ kind: "list";
84
+ list: SciList;
85
+ } | {
86
+ kind: "node";
87
+ node: ListNode;
88
+ } | {
89
+ kind: "bitmap";
90
+ bitmap: SciBitmap;
91
+ } | {
92
+ kind: "free";
93
+ };
94
+ /**
95
+ * The segment table. Every addressable thing gets its own segment, which keeps
96
+ * references stable and makes "what is this pointer?" a table lookup.
97
+ */
98
+ export declare class Memory {
99
+ readonly segments: Segment[];
100
+ private readonly freeSegments;
101
+ readonly objects: Map<number, SciObject>;
102
+ readonly stack: Value[];
103
+ readonly stackSegment: number;
104
+ /**
105
+ * `stack` can be handed over from a previous Memory: the interpreter loop holds on to the
106
+ * stack array, so restarting or restoring mid-instruction must keep the same array.
107
+ */
108
+ constructor(stack?: Value[]);
109
+ /** Puts a segment at a specific id (restoring a save), growing the table if needed. */
110
+ allocateAt(id: number, segment: Segment): void;
111
+ /** Free segment ids, for snapshots. */
112
+ get free_(): readonly number[];
113
+ setFreeSegments(ids: number[]): void;
114
+ allocate(segment: Segment): number;
115
+ free(id: number): void;
116
+ segment(v: Value): Segment | undefined;
117
+ object(v: Value): SciObject | undefined;
118
+ newArray(type: ArrayType, size: number): Value;
119
+ array(v: Value): SciArray | undefined;
120
+ newList(): SciList;
121
+ newNode(value: Value, key: Value): ListNode;
122
+ list(v: Value): SciList | undefined;
123
+ node(v: Value): ListNode | undefined;
124
+ newBitmap(width: number, height: number, fill: number, skipColor: number): Value;
125
+ bitmap(v: Value): SciBitmap | undefined;
126
+ /** Reads a string from a heap literal, a string/byte array, or a String object's data. */
127
+ string(v: Value): string;
128
+ /** Reads through a pointer to a variable (from `lea`): locals/globals or the stack. */
129
+ read(v: Value): Value;
130
+ write(v: Value, value: Value): void;
131
+ clone(parent: SciObject): SciObject;
132
+ disposeClone(obj: SciObject): void;
133
+ }
134
+ /**
135
+ * A clone of `template` (a script object) with the given property values. A clone of a class
136
+ * behaves like an instance of that class; a clone of an instance shares its methods.
137
+ */
138
+ export declare function cloneShape(template: SciObject, vars: Value[]): SciObject;
@@ -0,0 +1,168 @@
1
+ import { ObjectSlot, readString } from "../script/script.js";
2
+ import { makeRef, offsetOf, segmentOf } from "./value.js";
3
+ /**
4
+ * The segment table. Every addressable thing gets its own segment, which keeps
5
+ * references stable and makes "what is this pointer?" a table lookup.
6
+ */
7
+ export class Memory {
8
+ segments = [{ kind: "free" }]; // segment 0 = numbers
9
+ freeSegments = [];
10
+ objects = new Map();
11
+ stack;
12
+ stackSegment;
13
+ /**
14
+ * `stack` can be handed over from a previous Memory: the interpreter loop holds on to the
15
+ * stack array, so restarting or restoring mid-instruction must keep the same array.
16
+ */
17
+ constructor(stack = new Array(0x2000).fill(0)) {
18
+ this.stack = stack;
19
+ this.stackSegment = this.allocate({ kind: "stack" });
20
+ }
21
+ /** Puts a segment at a specific id (restoring a save), growing the table if needed. */
22
+ allocateAt(id, segment) {
23
+ while (this.segments.length <= id)
24
+ this.segments.push({ kind: "free" });
25
+ this.segments[id] = segment;
26
+ const i = this.freeSegments.indexOf(id);
27
+ if (i >= 0)
28
+ this.freeSegments.splice(i, 1);
29
+ }
30
+ /** Free segment ids, for snapshots. */
31
+ get free_() {
32
+ return this.freeSegments;
33
+ }
34
+ setFreeSegments(ids) {
35
+ this.freeSegments.length = 0;
36
+ this.freeSegments.push(...ids);
37
+ }
38
+ allocate(segment) {
39
+ const id = this.freeSegments.pop();
40
+ if (id !== undefined) {
41
+ this.segments[id] = segment;
42
+ return id;
43
+ }
44
+ this.segments.push(segment);
45
+ return this.segments.length - 1;
46
+ }
47
+ free(id) {
48
+ this.segments[id] = { kind: "free" };
49
+ this.freeSegments.push(id);
50
+ }
51
+ segment(v) {
52
+ return this.segments[segmentOf(v)];
53
+ }
54
+ object(v) {
55
+ return this.objects.get(v);
56
+ }
57
+ // --- Arrays ---------------------------------------------------------------
58
+ newArray(type, size) {
59
+ const seg = this.allocate({ kind: "array", array: { type, data: new Array(size).fill(0) } });
60
+ return makeRef(seg, 0);
61
+ }
62
+ array(v) {
63
+ const s = this.segment(v);
64
+ return s?.kind === "array" ? s.array : undefined;
65
+ }
66
+ // --- Lists ----------------------------------------------------------------
67
+ newList() {
68
+ const list = { address: 0, first: undefined, last: undefined };
69
+ list.address = makeRef(this.allocate({ kind: "list", list }), 0);
70
+ return list;
71
+ }
72
+ newNode(value, key) {
73
+ const node = { address: 0, value, key, prev: undefined, next: undefined, list: undefined };
74
+ node.address = makeRef(this.allocate({ kind: "node", node }), 0);
75
+ return node;
76
+ }
77
+ list(v) {
78
+ const s = this.segment(v);
79
+ return s?.kind === "list" ? s.list : undefined;
80
+ }
81
+ node(v) {
82
+ const s = this.segment(v);
83
+ return s?.kind === "node" ? s.node : undefined;
84
+ }
85
+ // --- Bitmaps ----------------------------------------------------------------
86
+ newBitmap(width, height, fill, skipColor) {
87
+ const bitmap = { width, height, pixels: new Uint8Array(width * height).fill(fill), skipColor, originX: 0, originY: 0 };
88
+ return makeRef(this.allocate({ kind: "bitmap", bitmap }), 0);
89
+ }
90
+ bitmap(v) {
91
+ const s = this.segment(v);
92
+ return s?.kind === "bitmap" ? s.bitmap : undefined;
93
+ }
94
+ // --- Strings and raw references -------------------------------------------
95
+ /** Reads a string from a heap literal, a string/byte array, or a String object's data. */
96
+ string(v) {
97
+ const s = this.segment(v);
98
+ if (!s)
99
+ return "";
100
+ if (s.kind === "script")
101
+ return readString(s.script.script.heap, offsetOf(v));
102
+ if (s.kind === "array") {
103
+ const chars = [];
104
+ for (let i = offsetOf(v); i < s.array.data.length; i++) {
105
+ const c = s.array.data[i] & 0xff;
106
+ if (c === 0)
107
+ break;
108
+ chars.push(c);
109
+ }
110
+ return String.fromCharCode(...chars);
111
+ }
112
+ return "";
113
+ }
114
+ /** Reads through a pointer to a variable (from `lea`): locals/globals or the stack. */
115
+ read(v) {
116
+ const s = this.segment(v);
117
+ const i = offsetOf(v) >> 1;
118
+ if (s?.kind === "locals")
119
+ return s.script.locals[i] ?? 0;
120
+ if (s?.kind === "stack")
121
+ return this.stack[i] ?? 0;
122
+ if (s?.kind === "array")
123
+ return s.array.data[offsetOf(v)] ?? 0;
124
+ throw new Error(`read through unsupported reference ${v.toString(16)}`);
125
+ }
126
+ write(v, value) {
127
+ const s = this.segment(v);
128
+ const i = offsetOf(v) >> 1;
129
+ if (s?.kind === "locals")
130
+ s.script.locals[i] = value;
131
+ else if (s?.kind === "stack")
132
+ this.stack[i] = value;
133
+ else if (s?.kind === "array")
134
+ s.array.data[offsetOf(v)] = value;
135
+ else
136
+ throw new Error(`write through unsupported reference ${v.toString(16)}`);
137
+ }
138
+ // --- Objects --------------------------------------------------------------
139
+ clone(parent) {
140
+ const obj = cloneShape(parent.template ?? parent, parent.vars.slice());
141
+ obj.address = makeRef(this.allocate({ kind: "clone", object: obj }), 0);
142
+ obj.vars[ObjectSlot.Info] = (obj.vars[ObjectSlot.Info] & ~0x8000) | 0x0001;
143
+ this.objects.set(obj.address, obj);
144
+ return obj;
145
+ }
146
+ disposeClone(obj) {
147
+ if (!obj.isClone)
148
+ return;
149
+ this.objects.delete(obj.address);
150
+ this.free(segmentOf(obj.address));
151
+ }
152
+ }
153
+ /**
154
+ * A clone of `template` (a script object) with the given property values. A clone of a class
155
+ * behaves like an instance of that class; a clone of an instance shares its methods.
156
+ */
157
+ export function cloneShape(template, vars) {
158
+ return {
159
+ ...template,
160
+ address: 0,
161
+ vars,
162
+ isClass: false,
163
+ isClone: true,
164
+ template,
165
+ superclass: template.isClass ? template.species : template.superclass,
166
+ methods: template.isClass ? new Map() : template.methods,
167
+ };
168
+ }
@@ -0,0 +1,266 @@
1
+ import { ObjectSlot, readString, type Script } from "../script/script.ts";
2
+ import { makeRef, offsetOf, segmentOf, type Value } from "./value.ts";
3
+
4
+ /** A script loaded into the VM: its own segment, mutable locals and live objects. */
5
+ export interface LoadedScript {
6
+ number: number;
7
+ script: Script;
8
+ segment: number;
9
+ /** Segment used for pointers to this script's locals (from `lea`). */
10
+ localsSegment: number;
11
+ /** Local variables (script 0's locals are the game's globals). */
12
+ locals: Value[];
13
+ /** Live objects by heap offset. */
14
+ objects: Map<number, SciObject>;
15
+ code: Uint8Array;
16
+ codeView: DataView;
17
+ }
18
+
19
+ /**
20
+ * An object at runtime. Property slots are full Values (they can hold references),
21
+ * unlike the 16-bit words in the heap resource they're initialised from.
22
+ */
23
+ export interface SciObject {
24
+ address: Value;
25
+ name: string;
26
+ /** Script whose code implements this object's own methods. */
27
+ script: LoadedScript;
28
+ vars: Value[];
29
+ isClass: boolean;
30
+ /** Own methods: selector → code offset in `script`. Clones share their parent's. */
31
+ methods: Map<number, number>;
32
+ /** Selector → property slot. Shared by every object of a class. */
33
+ propIndex: Map<number, number>;
34
+ /** Class number where method lookup continues after `methods`. */
35
+ superclass: number;
36
+ /** For classes: own class number. For instances/clones: their class's. */
37
+ species: number;
38
+ isClone: boolean;
39
+ /** For clones: the script object whose methods/layout it uses (cloning a clone = cloning this). */
40
+ template: SciObject | undefined;
41
+ }
42
+
43
+ export type ArrayType = "int16" | "id" | "byte" | "string";
44
+
45
+ /** SCI32 dynamic array (kArray / kString). Byte and string arrays hold 0..255. */
46
+ export interface SciArray {
47
+ type: ArrayType;
48
+ data: Value[];
49
+ }
50
+
51
+ export interface ListNode {
52
+ address: Value;
53
+ value: Value;
54
+ key: Value;
55
+ prev: ListNode | undefined;
56
+ next: ListNode | undefined;
57
+ list: SciList | undefined;
58
+ }
59
+
60
+ export interface SciList {
61
+ address: Value;
62
+ first: ListNode | undefined;
63
+ last: ListNode | undefined;
64
+ }
65
+
66
+ /** SCI32 in-memory bitmap (text boxes and other script-drawn images), 8-bit indexed. */
67
+ export interface SciBitmap {
68
+ width: number;
69
+ height: number;
70
+ pixels: Uint8Array;
71
+ skipColor: number;
72
+ originX: number;
73
+ originY: number;
74
+ }
75
+
76
+ export type Segment =
77
+ | { kind: "script"; script: LoadedScript }
78
+ | { kind: "locals"; script: LoadedScript }
79
+ | { kind: "clone"; object: SciObject }
80
+ | { kind: "stack" }
81
+ | { kind: "array"; array: SciArray }
82
+ | { kind: "list"; list: SciList }
83
+ | { kind: "node"; node: ListNode }
84
+ | { kind: "bitmap"; bitmap: SciBitmap }
85
+ | { kind: "free" };
86
+
87
+ /**
88
+ * The segment table. Every addressable thing gets its own segment, which keeps
89
+ * references stable and makes "what is this pointer?" a table lookup.
90
+ */
91
+ export class Memory {
92
+ readonly segments: Segment[] = [{ kind: "free" }]; // segment 0 = numbers
93
+ private readonly freeSegments: number[] = [];
94
+ readonly objects = new Map<Value, SciObject>();
95
+ readonly stack: Value[];
96
+ readonly stackSegment: number;
97
+
98
+ /**
99
+ * `stack` can be handed over from a previous Memory: the interpreter loop holds on to the
100
+ * stack array, so restarting or restoring mid-instruction must keep the same array.
101
+ */
102
+ constructor(stack: Value[] = new Array(0x2000).fill(0)) {
103
+ this.stack = stack;
104
+ this.stackSegment = this.allocate({ kind: "stack" });
105
+ }
106
+
107
+ /** Puts a segment at a specific id (restoring a save), growing the table if needed. */
108
+ allocateAt(id: number, segment: Segment): void {
109
+ while (this.segments.length <= id) this.segments.push({ kind: "free" });
110
+ this.segments[id] = segment;
111
+ const i = this.freeSegments.indexOf(id);
112
+ if (i >= 0) this.freeSegments.splice(i, 1);
113
+ }
114
+
115
+ /** Free segment ids, for snapshots. */
116
+ get free_(): readonly number[] {
117
+ return this.freeSegments;
118
+ }
119
+
120
+ setFreeSegments(ids: number[]): void {
121
+ this.freeSegments.length = 0;
122
+ this.freeSegments.push(...ids);
123
+ }
124
+
125
+ allocate(segment: Segment): number {
126
+ const id = this.freeSegments.pop();
127
+ if (id !== undefined) {
128
+ this.segments[id] = segment;
129
+ return id;
130
+ }
131
+ this.segments.push(segment);
132
+ return this.segments.length - 1;
133
+ }
134
+
135
+ free(id: number): void {
136
+ this.segments[id] = { kind: "free" };
137
+ this.freeSegments.push(id);
138
+ }
139
+
140
+ segment(v: Value): Segment | undefined {
141
+ return this.segments[segmentOf(v)];
142
+ }
143
+
144
+ object(v: Value): SciObject | undefined {
145
+ return this.objects.get(v);
146
+ }
147
+
148
+ // --- Arrays ---------------------------------------------------------------
149
+
150
+ newArray(type: ArrayType, size: number): Value {
151
+ const seg = this.allocate({ kind: "array", array: { type, data: new Array(size).fill(0) } });
152
+ return makeRef(seg, 0);
153
+ }
154
+
155
+ array(v: Value): SciArray | undefined {
156
+ const s = this.segment(v);
157
+ return s?.kind === "array" ? s.array : undefined;
158
+ }
159
+
160
+ // --- Lists ----------------------------------------------------------------
161
+
162
+ newList(): SciList {
163
+ const list: SciList = { address: 0, first: undefined, last: undefined };
164
+ list.address = makeRef(this.allocate({ kind: "list", list }), 0);
165
+ return list;
166
+ }
167
+
168
+ newNode(value: Value, key: Value): ListNode {
169
+ const node: ListNode = { address: 0, value, key, prev: undefined, next: undefined, list: undefined };
170
+ node.address = makeRef(this.allocate({ kind: "node", node }), 0);
171
+ return node;
172
+ }
173
+
174
+ list(v: Value): SciList | undefined {
175
+ const s = this.segment(v);
176
+ return s?.kind === "list" ? s.list : undefined;
177
+ }
178
+
179
+ node(v: Value): ListNode | undefined {
180
+ const s = this.segment(v);
181
+ return s?.kind === "node" ? s.node : undefined;
182
+ }
183
+
184
+ // --- Bitmaps ----------------------------------------------------------------
185
+
186
+ newBitmap(width: number, height: number, fill: number, skipColor: number): Value {
187
+ const bitmap: SciBitmap = { width, height, pixels: new Uint8Array(width * height).fill(fill), skipColor, originX: 0, originY: 0 };
188
+ return makeRef(this.allocate({ kind: "bitmap", bitmap }), 0);
189
+ }
190
+
191
+ bitmap(v: Value): SciBitmap | undefined {
192
+ const s = this.segment(v);
193
+ return s?.kind === "bitmap" ? s.bitmap : undefined;
194
+ }
195
+
196
+ // --- Strings and raw references -------------------------------------------
197
+
198
+ /** Reads a string from a heap literal, a string/byte array, or a String object's data. */
199
+ string(v: Value): string {
200
+ const s = this.segment(v);
201
+ if (!s) return "";
202
+ if (s.kind === "script") return readString(s.script.script.heap, offsetOf(v));
203
+ if (s.kind === "array") {
204
+ const chars: number[] = [];
205
+ for (let i = offsetOf(v); i < s.array.data.length; i++) {
206
+ const c = s.array.data[i]! & 0xff;
207
+ if (c === 0) break;
208
+ chars.push(c);
209
+ }
210
+ return String.fromCharCode(...chars);
211
+ }
212
+ return "";
213
+ }
214
+
215
+ /** Reads through a pointer to a variable (from `lea`): locals/globals or the stack. */
216
+ read(v: Value): Value {
217
+ const s = this.segment(v);
218
+ const i = offsetOf(v) >> 1;
219
+ if (s?.kind === "locals") return s.script.locals[i] ?? 0;
220
+ if (s?.kind === "stack") return this.stack[i] ?? 0;
221
+ if (s?.kind === "array") return s.array.data[offsetOf(v)] ?? 0;
222
+ throw new Error(`read through unsupported reference ${v.toString(16)}`);
223
+ }
224
+
225
+ write(v: Value, value: Value): void {
226
+ const s = this.segment(v);
227
+ const i = offsetOf(v) >> 1;
228
+ if (s?.kind === "locals") s.script.locals[i] = value;
229
+ else if (s?.kind === "stack") this.stack[i] = value;
230
+ else if (s?.kind === "array") s.array.data[offsetOf(v)] = value;
231
+ else throw new Error(`write through unsupported reference ${v.toString(16)}`);
232
+ }
233
+
234
+ // --- Objects --------------------------------------------------------------
235
+
236
+ clone(parent: SciObject): SciObject {
237
+ const obj = cloneShape(parent.template ?? parent, parent.vars.slice());
238
+ obj.address = makeRef(this.allocate({ kind: "clone", object: obj }), 0);
239
+ obj.vars[ObjectSlot.Info] = (obj.vars[ObjectSlot.Info]! & ~0x8000) | 0x0001;
240
+ this.objects.set(obj.address, obj);
241
+ return obj;
242
+ }
243
+
244
+ disposeClone(obj: SciObject): void {
245
+ if (!obj.isClone) return;
246
+ this.objects.delete(obj.address);
247
+ this.free(segmentOf(obj.address));
248
+ }
249
+ }
250
+
251
+ /**
252
+ * A clone of `template` (a script object) with the given property values. A clone of a class
253
+ * behaves like an instance of that class; a clone of an instance shares its methods.
254
+ */
255
+ export function cloneShape(template: SciObject, vars: Value[]): SciObject {
256
+ return {
257
+ ...template,
258
+ address: 0,
259
+ vars,
260
+ isClass: false,
261
+ isClone: true,
262
+ template,
263
+ superclass: template.isClass ? template.species : template.superclass,
264
+ methods: template.isClass ? new Map() : template.methods,
265
+ };
266
+ }
@@ -0,0 +1,11 @@
1
+ import type { ResourceId } from "../resource/types.ts";
2
+ import type { Vm } from "./vm.ts";
3
+ /**
4
+ * Swaps resources in a running game (a live editor's rebuild): the resource manager serves
5
+ * the new data from now on and parsed views, pictures and messages are forgotten. Scripts
6
+ * already loaded keep their old code until they're loaded again, so callers restore a
7
+ * snapshot taken outside the rebuilt rooms (or jump to a room that isn't loaded).
8
+ */
9
+ export declare function replaceResources(vm: Vm, resources: (ResourceId & {
10
+ data: Uint8Array;
11
+ })[]): void;
@@ -0,0 +1,14 @@
1
+ import { graphics } from "./kernels/graphics.js";
2
+ import { forgetMessages } from "./kernels/text.js";
3
+ /**
4
+ * Swaps resources in a running game (a live editor's rebuild): the resource manager serves
5
+ * the new data from now on and parsed views, pictures and messages are forgotten. Scripts
6
+ * already loaded keep their old code until they're loaded again, so callers restore a
7
+ * snapshot taken outside the rebuilt rooms (or jump to a room that isn't loaded).
8
+ */
9
+ export function replaceResources(vm, resources) {
10
+ for (const r of resources)
11
+ vm.resources.override(r, r.data);
12
+ graphics(vm).forgetResources();
13
+ forgetMessages(vm);
14
+ }
@@ -0,0 +1,16 @@
1
+ import type { ResourceId } from "../resource/types.ts";
2
+ import { graphics } from "./kernels/graphics.ts";
3
+ import { forgetMessages } from "./kernels/text.ts";
4
+ import type { Vm } from "./vm.ts";
5
+
6
+ /**
7
+ * Swaps resources in a running game (a live editor's rebuild): the resource manager serves
8
+ * the new data from now on and parsed views, pictures and messages are forgotten. Scripts
9
+ * already loaded keep their old code until they're loaded again, so callers restore a
10
+ * snapshot taken outside the rebuilt rooms (or jump to a room that isn't loaded).
11
+ */
12
+ export function replaceResources(vm: Vm, resources: (ResourceId & { data: Uint8Array })[]): void {
13
+ for (const r of resources) vm.resources.override(r, r.data);
14
+ graphics(vm).forgetResources();
15
+ forgetMessages(vm);
16
+ }