@emu198x/zx-spectrum 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -1
- package/emu198x_spectrum_web.d.ts +140 -3
- package/emu198x_spectrum_web.js +288 -2
- package/emu198x_spectrum_web_bg.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,10 @@ The permission is Cliff Lawson's, for Amstrad plc, on comp.sys.sinclair,
|
|
|
73
73
|
31 August 1999:
|
|
74
74
|
<https://web.archive.org/web/20180828125931/http://www.worldofspectrum.org/permits/amstrad-roms.txt>
|
|
75
75
|
|
|
76
|
-
The ROM image is included unmodified, and no charge is made for it.
|
|
76
|
+
The ROM image is included unmodified, and no charge is made for it. Versions
|
|
77
|
+
0.1.0 to 0.4.0 carried a 48K image with 272 bytes changed in the ROM's unused
|
|
78
|
+
area, from address `0x386E`; use 0.4.1 or later, which carries the unmodified
|
|
79
|
+
image (SHA1 `5ea7c2b824672e914525d1d5c419d71b84a426a2`). The
|
|
77
80
|
permission covers the Sinclair 48K and 128K ROMs and Amstrad's +2/+2A/+3
|
|
78
81
|
machines. It does not extend to the ZX80, ZX81, Interface 1 or 2, Timex
|
|
79
82
|
machines, or Spectrum clones.
|
|
@@ -83,3 +86,78 @@ machines, or Spectrum clones.
|
|
|
83
86
|
The emulator is licensed under the terms in the Emu198x repository. The ROM is
|
|
84
87
|
copyright Amstrad plc and is redistributed under the permission above; it is
|
|
85
88
|
not covered by that licence.
|
|
89
|
+
|
|
90
|
+
### Running inside a Web Worker
|
|
91
|
+
|
|
92
|
+
`Spectrum.createHeadless(rom)` and, in a firmware-bundled build,
|
|
93
|
+
`Spectrum.createHeadlessBundled()` create the same 48K machine without a DOM
|
|
94
|
+
canvas. Run `autoload()` and `tick(elapsedMs)` in the worker, then transfer the
|
|
95
|
+
`frameRgba()` buffer and `frameSize()` dimensions to the page for presentation.
|
|
96
|
+
The existing canvas-based constructors remain available.
|
|
97
|
+
|
|
98
|
+
Boot and turbo tape loading are synchronous operations. Keeping them in a worker
|
|
99
|
+
prevents those operations from blocking editing and other page interactions; it
|
|
100
|
+
does not remove their emulation cost. Keep at most one tick request in flight,
|
|
101
|
+
terminate the previous worker when starting a new run, and pause requests when
|
|
102
|
+
the page is hidden. The caller owns worker lifecycle, frame transfer and audio
|
|
103
|
+
presentation. No snapshot injection or tape-loading shortcut is implied.
|
|
104
|
+
|
|
105
|
+
## Numbered BASIC listings
|
|
106
|
+
|
|
107
|
+
The additive `basicTape(source, name)` export converts a numbered ASCII listing
|
|
108
|
+
into a self-starting BASIC TAP. It uses the format crate's `tokenise_listing`
|
|
109
|
+
path and the shared TAP writer, preserving expression text rather than passing
|
|
110
|
+
it through the analysis AST. Line numbers are sorted; duplicate line numbers,
|
|
111
|
+
empty programs, unsupported characters, unterminated strings and out-of-range
|
|
112
|
+
numbers return errors. This is tokenisation, not a BASIC grammar validator:
|
|
113
|
+
the ROM still reports execution and syntax errors when the tape runs.
|
|
114
|
+
|
|
115
|
+
This route is currently a bounded Code198x browser trial (Meet BASIC greeting
|
|
116
|
+
and Sonar). DEF FN parameter markers, embedded graphics/control codes and broader
|
|
117
|
+
source-notation compatibility remain outside it. The listing and headless worker APIs are available from npm version 0.4.0.
|
|
118
|
+
|
|
119
|
+
### Direct program execution
|
|
120
|
+
|
|
121
|
+
On a fresh 48K instance, `runBasic(source)` installs the tokenised listing in
|
|
122
|
+
RAM through the shared native BASIC loader, updates its system variables, and
|
|
123
|
+
types RUN through the ROM. It mounts no tape. `basicTape(source, name)` remains
|
|
124
|
+
the independent download/export path.
|
|
125
|
+
|
|
126
|
+
`runCode(bytes, origin, entry)` boots the ROM, installs the machine code and a
|
|
127
|
+
small BASIC launcher, then executes CLEAR followed by RANDOMIZE USR. This
|
|
128
|
+
preserves ROM services and a return stack. Code must start at or above 24576,
|
|
129
|
+
fit below 65536, and contain its entry point. Use a fresh instance for each run.
|
|
130
|
+
Both APIs are synchronous: worker hosts keep boot work off the page thread.
|
|
131
|
+
These APIs are available from npm version 0.4.0.
|
|
132
|
+
|
|
133
|
+
`readMemory(address, length)` reads the current visible address space for lesson
|
|
134
|
+
inspectors. It is read-only and rejects ranges outside the 64 KiB address space.
|
|
135
|
+
This API is available from npm version 0.4.0.
|
|
136
|
+
|
|
137
|
+
For lesson replay, call `enableScreenWriteTrace(address, length)` on a fresh machine before
|
|
138
|
+
`runCode()`, then read `screenWriteTrace()`. Choose a narrow bitmap range to avoid filling the capture with ROM clearing.
|
|
139
|
+
It returns captured writes within that range
|
|
140
|
+
(including ROM writes) and a `full` flag when the shared 8192-record cap is
|
|
141
|
+
reached. The caller can filter by program PC range. A replay is a recording,
|
|
142
|
+
not live stepping; a full capture must not be presented as complete. These
|
|
143
|
+
APIs are available from npm version 0.4.0.
|
|
144
|
+
|
|
145
|
+
For the bounded routine lesson, call `enableRoutineTrace(stop)` before
|
|
146
|
+
`runCode()`, then `routineTrace()`. The JSON recording contains actual unconditional
|
|
147
|
+
CALL/RET transitions and bitmap writes in $4000–$47FF, with before/after register
|
|
148
|
+
snapshots. Existing debugger stepping stops at the supplied PC, on leaving the
|
|
149
|
+
program, or after 4096 steps. Check `complete`: only reaching the supplied stop
|
|
150
|
+
address makes it true. The intended stop is the lesson's `hold` label. This is
|
|
151
|
+
bounded teaching instrumentation, not a general instruction trace. It is available
|
|
152
|
+
from npm version 0.4.0.
|
|
153
|
+
|
|
154
|
+
### Debugger controls
|
|
155
|
+
|
|
156
|
+
`debugState()` serialises shared debugger CPU state and disassembly/bytes at PC.
|
|
157
|
+
`debugStep()` invokes the existing bounded native step; `debugRunTo(address)`
|
|
158
|
+
runs to an instruction boundary with a fixed 14-million-half-cycle budget and
|
|
159
|
+
returns whether it reached the address. Invalid addresses are rejected. Both
|
|
160
|
+
execution methods deliver queued input first. Suspend normal frame ticks before
|
|
161
|
+
using them; no implicit rendering or real-time playback runs while paused.
|
|
162
|
+
A failed run-to is not a breakpoint hit, and a step at HALT can remain waiting.
|
|
163
|
+
These exports are available from npm version 0.4.0.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* A ZX Spectrum
|
|
5
|
+
* A ZX Spectrum with optional canvas presentation.
|
|
6
6
|
*/
|
|
7
7
|
export class Spectrum {
|
|
8
8
|
private constructor();
|
|
@@ -73,6 +73,61 @@ export class Spectrum {
|
|
|
73
73
|
* Returns a JavaScript error if the canvas has no 2-D context.
|
|
74
74
|
*/
|
|
75
75
|
static createBundled(canvas: HTMLCanvasElement): Promise<Spectrum>;
|
|
76
|
+
/**
|
|
77
|
+
* Builds a canvas-free 48K suitable for a Web Worker.
|
|
78
|
+
*
|
|
79
|
+
* Use `tick`, `frameSize` and `frameRgba` to run the same machine and
|
|
80
|
+
* transfer completed frames to a presenter. No DOM object is accessed.
|
|
81
|
+
*
|
|
82
|
+
* # Errors
|
|
83
|
+
*
|
|
84
|
+
* Returns an error if the supplied firmware cannot build a 48K machine.
|
|
85
|
+
*/
|
|
86
|
+
static createHeadless(rom: Uint8Array): Spectrum;
|
|
87
|
+
/**
|
|
88
|
+
* Builds a canvas-free 48K with the package's bundled ROM.
|
|
89
|
+
*
|
|
90
|
+
* # Errors
|
|
91
|
+
*
|
|
92
|
+
* Returns an error if the bundled firmware cannot build the machine.
|
|
93
|
+
*/
|
|
94
|
+
static createHeadlessBundled(): Spectrum;
|
|
95
|
+
/**
|
|
96
|
+
* Run to an instruction boundary, bounded to 14 million half-cycles.
|
|
97
|
+
* Suspend the host frame loop before calling this method.
|
|
98
|
+
*
|
|
99
|
+
* # Errors
|
|
100
|
+
* Rejects invalid addresses and input delivery errors.
|
|
101
|
+
*/
|
|
102
|
+
debugRunTo(address: number): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Inspect shared debugger registers and disassembly at PC.
|
|
105
|
+
*
|
|
106
|
+
* # Errors
|
|
107
|
+
* Returns an error if state cannot be serialised.
|
|
108
|
+
*/
|
|
109
|
+
debugState(): string;
|
|
110
|
+
/**
|
|
111
|
+
* Use the existing bounded native step; suspend the host frame loop first.
|
|
112
|
+
*
|
|
113
|
+
* # Errors
|
|
114
|
+
* Returns an error if pending input cannot be delivered.
|
|
115
|
+
*/
|
|
116
|
+
debugStep(): bigint;
|
|
117
|
+
/**
|
|
118
|
+
* Enables a bounded debugger recording of CALL nn, RET and bitmap writes,
|
|
119
|
+
* stopping before the named hold address. Use on a fresh machine.
|
|
120
|
+
*/
|
|
121
|
+
enableRoutineTrace(stop: number): void;
|
|
122
|
+
/**
|
|
123
|
+
* Records writes in a selected bitmap range during the next direct code run.
|
|
124
|
+
* Call on a fresh machine. Narrow ranges leave room for the program's writes
|
|
125
|
+
* after the ROM clears the display.
|
|
126
|
+
*
|
|
127
|
+
* # Errors
|
|
128
|
+
* Rejects empty ranges or ranges outside bitmap RAM ($4000..$5800).
|
|
129
|
+
*/
|
|
130
|
+
enableScreenWriteTrace(address: number, length: number): void;
|
|
76
131
|
/**
|
|
77
132
|
* The machine's picture as RGBA bytes, for a page that wants to present
|
|
78
133
|
* it itself.
|
|
@@ -82,6 +137,10 @@ export class Spectrum {
|
|
|
82
137
|
* Width and height of the machine's picture, as `[width, height]`.
|
|
83
138
|
*/
|
|
84
139
|
frameSize(): Uint32Array;
|
|
140
|
+
/**
|
|
141
|
+
* Frame period derived from the machine profile.
|
|
142
|
+
*/
|
|
143
|
+
frame_ms(): number;
|
|
85
144
|
/**
|
|
86
145
|
* Presses a key, from a DOM `KeyboardEvent.code`.
|
|
87
146
|
*
|
|
@@ -144,10 +203,63 @@ export class Spectrum {
|
|
|
144
203
|
* Returns a JavaScript error if the machine does not know the path.
|
|
145
204
|
*/
|
|
146
205
|
query(path: string): string;
|
|
206
|
+
/**
|
|
207
|
+
* Reads visible memory for a lesson's live inspection panel.
|
|
208
|
+
*
|
|
209
|
+
* # Errors
|
|
210
|
+
* Rejects ranges extending beyond the 64 KiB address space.
|
|
211
|
+
*/
|
|
212
|
+
readMemory(address: number, length: number): Uint8Array;
|
|
213
|
+
/**
|
|
214
|
+
* Restores compatible machine state, clearing pending host input/audio.
|
|
215
|
+
*/
|
|
216
|
+
restore_state(bytes: Uint8Array): void;
|
|
217
|
+
/**
|
|
218
|
+
* Returns the executed routine events and whether the stop was reached.
|
|
219
|
+
*
|
|
220
|
+
* # Errors
|
|
221
|
+
* Returns a JSON serialisation error if the recording cannot be encoded.
|
|
222
|
+
*/
|
|
223
|
+
routineTrace(): string;
|
|
224
|
+
/**
|
|
225
|
+
* Installs a numbered BASIC listing directly into RAM and asks the ROM
|
|
226
|
+
* to RUN it. Call on a fresh 48K; no tape is mounted or played.
|
|
227
|
+
*
|
|
228
|
+
* # Errors
|
|
229
|
+
* Returns conversion, boot or editor-prompt errors.
|
|
230
|
+
*/
|
|
231
|
+
runBasic(source: string): void;
|
|
232
|
+
/**
|
|
233
|
+
* Installs machine code in a fresh 48K and calls it through the ROM's
|
|
234
|
+
* RANDOMIZE USR, with CLEAR reserving its RAM and a valid return stack.
|
|
235
|
+
*
|
|
236
|
+
* # Errors
|
|
237
|
+
* Rejects empty code, overlap with BASIC/system RAM, overflow, entry
|
|
238
|
+
* outside the code, and ROM boot or prompt failures.
|
|
239
|
+
*/
|
|
240
|
+
runCode(bytes: Uint8Array, origin: number, entry: number): void;
|
|
241
|
+
/**
|
|
242
|
+
* Exports the current machine state.
|
|
243
|
+
*/
|
|
244
|
+
save_state(): Uint8Array;
|
|
245
|
+
/**
|
|
246
|
+
* Returns captured writes (including ROM writes) and saturation status.
|
|
247
|
+
* Consumers can select the program's PC range without inventing a trace.
|
|
248
|
+
*
|
|
249
|
+
* # Errors
|
|
250
|
+
* Returns a serialisation error if the capture cannot be encoded.
|
|
251
|
+
*/
|
|
252
|
+
screenWriteTrace(): string;
|
|
147
253
|
/**
|
|
148
254
|
* Starts or stops machine audio.
|
|
149
255
|
*/
|
|
150
256
|
setAudioEnabled(enabled: boolean): void;
|
|
257
|
+
/**
|
|
258
|
+
* Advances exactly one frame without drawing to a canvas.
|
|
259
|
+
* # Errors
|
|
260
|
+
* Returns the runtime's execution error.
|
|
261
|
+
*/
|
|
262
|
+
step(): void;
|
|
151
263
|
/**
|
|
152
264
|
* Runs the machine for `elapsed_ms` of real time and draws the result.
|
|
153
265
|
*
|
|
@@ -168,25 +280,50 @@ export class Spectrum {
|
|
|
168
280
|
tick(elapsed_ms: number): number;
|
|
169
281
|
}
|
|
170
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Tokenise source and create an auto-starting BASIC TAP, without a machine.
|
|
285
|
+
*
|
|
286
|
+
* # Errors
|
|
287
|
+
* Returns a JavaScript error for unsupported or malformed listing input.
|
|
288
|
+
*/
|
|
289
|
+
export function basicTape(source: string, name: string): Uint8Array;
|
|
290
|
+
|
|
171
291
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
172
292
|
|
|
173
293
|
export interface InitOutput {
|
|
174
294
|
readonly memory: WebAssembly.Memory;
|
|
175
295
|
readonly __wbg_spectrum_free: (a: number, b: number) => void;
|
|
296
|
+
readonly basicTape: (a: number, b: number, c: number, d: number) => [number, number, number, number];
|
|
176
297
|
readonly spectrum_audioDrain: (a: number) => [number, number];
|
|
177
298
|
readonly spectrum_autoload: (a: number, b: number) => [number, number, number];
|
|
178
299
|
readonly spectrum_configureAudio: (a: number, b: number, c: number, d: number) => void;
|
|
179
300
|
readonly spectrum_create: (a: any, b: number, c: number) => any;
|
|
180
301
|
readonly spectrum_createBundled: (a: any) => any;
|
|
302
|
+
readonly spectrum_createHeadless: (a: number, b: number) => [number, number, number];
|
|
303
|
+
readonly spectrum_createHeadlessBundled: () => [number, number, number];
|
|
304
|
+
readonly spectrum_debugRunTo: (a: number, b: number) => [number, number, number];
|
|
305
|
+
readonly spectrum_debugState: (a: number) => [number, number, number, number];
|
|
306
|
+
readonly spectrum_debugStep: (a: number) => [bigint, number, number];
|
|
307
|
+
readonly spectrum_enableRoutineTrace: (a: number, b: number) => void;
|
|
308
|
+
readonly spectrum_enableScreenWriteTrace: (a: number, b: number, c: number) => [number, number];
|
|
181
309
|
readonly spectrum_frameRgba: (a: number) => [number, number];
|
|
182
310
|
readonly spectrum_frameSize: (a: number) => [number, number];
|
|
311
|
+
readonly spectrum_frame_ms: (a: number) => number;
|
|
183
312
|
readonly spectrum_keyDown: (a: number, b: number, c: number) => number;
|
|
184
313
|
readonly spectrum_keyUp: (a: number, b: number, c: number) => number;
|
|
185
314
|
readonly spectrum_load: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
186
315
|
readonly spectrum_loadSnapshot: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
187
316
|
readonly spectrum_mediaSlots: (a: number) => [number, number];
|
|
188
317
|
readonly spectrum_query: (a: number, b: number, c: number) => [number, number, number, number];
|
|
318
|
+
readonly spectrum_readMemory: (a: number, b: number, c: number) => [number, number, number, number];
|
|
319
|
+
readonly spectrum_restore_state: (a: number, b: number, c: number) => [number, number];
|
|
320
|
+
readonly spectrum_routineTrace: (a: number) => [number, number, number, number];
|
|
321
|
+
readonly spectrum_runBasic: (a: number, b: number, c: number) => [number, number];
|
|
322
|
+
readonly spectrum_runCode: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
323
|
+
readonly spectrum_save_state: (a: number) => [number, number, number, number];
|
|
324
|
+
readonly spectrum_screenWriteTrace: (a: number) => [number, number, number, number];
|
|
189
325
|
readonly spectrum_setAudioEnabled: (a: number, b: number) => void;
|
|
326
|
+
readonly spectrum_step: (a: number) => [number, number];
|
|
190
327
|
readonly spectrum_tick: (a: number, b: number) => [number, number, number];
|
|
191
328
|
readonly wasm_bindgen_d6cb7d81ec28c0ae___convert__closures_____invoke___wasm_bindgen_d6cb7d81ec28c0ae___JsValue__core_f0fd674eaa06beef___result__Result_____wasm_bindgen_d6cb7d81ec28c0ae___JsError___true_: (a: number, b: number, c: any) => [number, number];
|
|
192
329
|
readonly wasm_bindgen_d6cb7d81ec28c0ae___convert__closures_____invoke___js_sys_e5668971ffde892f___Function_fn_wasm_bindgen_d6cb7d81ec28c0ae___JsValue_____wasm_bindgen_d6cb7d81ec28c0ae___sys__Undefined___js_sys_e5668971ffde892f___Function_fn_wasm_bindgen_d6cb7d81ec28c0ae___JsValue_____wasm_bindgen_d6cb7d81ec28c0ae___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
|
|
@@ -194,10 +331,10 @@ export interface InitOutput {
|
|
|
194
331
|
readonly __externref_table_alloc: () => number;
|
|
195
332
|
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
196
333
|
readonly __wbindgen_destroy_closure: (a: number, b: number) => void;
|
|
197
|
-
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
198
|
-
readonly __externref_table_dealloc: (a: number) => void;
|
|
199
334
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
200
335
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
336
|
+
readonly __externref_table_dealloc: (a: number) => void;
|
|
337
|
+
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
201
338
|
readonly __externref_drop_slice: (a: number, b: number) => void;
|
|
202
339
|
readonly __wbindgen_start: () => void;
|
|
203
340
|
}
|
package/emu198x_spectrum_web.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @ts-self-types="./emu198x_spectrum_web.d.ts" */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* A ZX Spectrum
|
|
4
|
+
* A ZX Spectrum with optional canvas presentation.
|
|
5
5
|
*/
|
|
6
6
|
export class Spectrum {
|
|
7
7
|
static __wrap(ptr) {
|
|
@@ -117,6 +117,121 @@ export class Spectrum {
|
|
|
117
117
|
const ret = wasm.spectrum_createBundled(canvas);
|
|
118
118
|
return ret;
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Builds a canvas-free 48K suitable for a Web Worker.
|
|
122
|
+
*
|
|
123
|
+
* Use `tick`, `frameSize` and `frameRgba` to run the same machine and
|
|
124
|
+
* transfer completed frames to a presenter. No DOM object is accessed.
|
|
125
|
+
*
|
|
126
|
+
* # Errors
|
|
127
|
+
*
|
|
128
|
+
* Returns an error if the supplied firmware cannot build a 48K machine.
|
|
129
|
+
* @param {Uint8Array} rom
|
|
130
|
+
* @returns {Spectrum}
|
|
131
|
+
*/
|
|
132
|
+
static createHeadless(rom) {
|
|
133
|
+
const ptr0 = passArray8ToWasm0(rom, wasm.__wbindgen_malloc);
|
|
134
|
+
const len0 = WASM_VECTOR_LEN;
|
|
135
|
+
const ret = wasm.spectrum_createHeadless(ptr0, len0);
|
|
136
|
+
if (ret[2]) {
|
|
137
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
138
|
+
}
|
|
139
|
+
return Spectrum.__wrap(ret[0]);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Builds a canvas-free 48K with the package's bundled ROM.
|
|
143
|
+
*
|
|
144
|
+
* # Errors
|
|
145
|
+
*
|
|
146
|
+
* Returns an error if the bundled firmware cannot build the machine.
|
|
147
|
+
* @returns {Spectrum}
|
|
148
|
+
*/
|
|
149
|
+
static createHeadlessBundled() {
|
|
150
|
+
const ret = wasm.spectrum_createHeadlessBundled();
|
|
151
|
+
if (ret[2]) {
|
|
152
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
153
|
+
}
|
|
154
|
+
return Spectrum.__wrap(ret[0]);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Run to an instruction boundary, bounded to 14 million half-cycles.
|
|
158
|
+
* Suspend the host frame loop before calling this method.
|
|
159
|
+
*
|
|
160
|
+
* # Errors
|
|
161
|
+
* Rejects invalid addresses and input delivery errors.
|
|
162
|
+
* @param {number} address
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
debugRunTo(address) {
|
|
166
|
+
const ret = wasm.spectrum_debugRunTo(this.__wbg_ptr, address);
|
|
167
|
+
if (ret[2]) {
|
|
168
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
169
|
+
}
|
|
170
|
+
return ret[0] !== 0;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Inspect shared debugger registers and disassembly at PC.
|
|
174
|
+
*
|
|
175
|
+
* # Errors
|
|
176
|
+
* Returns an error if state cannot be serialised.
|
|
177
|
+
* @returns {string}
|
|
178
|
+
*/
|
|
179
|
+
debugState() {
|
|
180
|
+
let deferred2_0;
|
|
181
|
+
let deferred2_1;
|
|
182
|
+
try {
|
|
183
|
+
const ret = wasm.spectrum_debugState(this.__wbg_ptr);
|
|
184
|
+
var ptr1 = ret[0];
|
|
185
|
+
var len1 = ret[1];
|
|
186
|
+
if (ret[3]) {
|
|
187
|
+
ptr1 = 0; len1 = 0;
|
|
188
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
189
|
+
}
|
|
190
|
+
deferred2_0 = ptr1;
|
|
191
|
+
deferred2_1 = len1;
|
|
192
|
+
return getStringFromWasm0(ptr1, len1);
|
|
193
|
+
} finally {
|
|
194
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Use the existing bounded native step; suspend the host frame loop first.
|
|
199
|
+
*
|
|
200
|
+
* # Errors
|
|
201
|
+
* Returns an error if pending input cannot be delivered.
|
|
202
|
+
* @returns {bigint}
|
|
203
|
+
*/
|
|
204
|
+
debugStep() {
|
|
205
|
+
const ret = wasm.spectrum_debugStep(this.__wbg_ptr);
|
|
206
|
+
if (ret[2]) {
|
|
207
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
208
|
+
}
|
|
209
|
+
return BigInt.asUintN(64, ret[0]);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Enables a bounded debugger recording of CALL nn, RET and bitmap writes,
|
|
213
|
+
* stopping before the named hold address. Use on a fresh machine.
|
|
214
|
+
* @param {number} stop
|
|
215
|
+
*/
|
|
216
|
+
enableRoutineTrace(stop) {
|
|
217
|
+
wasm.spectrum_enableRoutineTrace(this.__wbg_ptr, stop);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Records writes in a selected bitmap range during the next direct code run.
|
|
221
|
+
* Call on a fresh machine. Narrow ranges leave room for the program's writes
|
|
222
|
+
* after the ROM clears the display.
|
|
223
|
+
*
|
|
224
|
+
* # Errors
|
|
225
|
+
* Rejects empty ranges or ranges outside bitmap RAM ($4000..$5800).
|
|
226
|
+
* @param {number} address
|
|
227
|
+
* @param {number} length
|
|
228
|
+
*/
|
|
229
|
+
enableScreenWriteTrace(address, length) {
|
|
230
|
+
const ret = wasm.spectrum_enableScreenWriteTrace(this.__wbg_ptr, address, length);
|
|
231
|
+
if (ret[1]) {
|
|
232
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
120
235
|
/**
|
|
121
236
|
* The machine's picture as RGBA bytes, for a page that wants to present
|
|
122
237
|
* it itself.
|
|
@@ -138,6 +253,14 @@ export class Spectrum {
|
|
|
138
253
|
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
139
254
|
return v1;
|
|
140
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Frame period derived from the machine profile.
|
|
258
|
+
* @returns {number}
|
|
259
|
+
*/
|
|
260
|
+
frame_ms() {
|
|
261
|
+
const ret = wasm.spectrum_frame_ms(this.__wbg_ptr);
|
|
262
|
+
return ret;
|
|
263
|
+
}
|
|
141
264
|
/**
|
|
142
265
|
* Presses a key, from a DOM `KeyboardEvent.code`.
|
|
143
266
|
*
|
|
@@ -268,6 +391,135 @@ export class Spectrum {
|
|
|
268
391
|
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
269
392
|
}
|
|
270
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Reads visible memory for a lesson's live inspection panel.
|
|
396
|
+
*
|
|
397
|
+
* # Errors
|
|
398
|
+
* Rejects ranges extending beyond the 64 KiB address space.
|
|
399
|
+
* @param {number} address
|
|
400
|
+
* @param {number} length
|
|
401
|
+
* @returns {Uint8Array}
|
|
402
|
+
*/
|
|
403
|
+
readMemory(address, length) {
|
|
404
|
+
const ret = wasm.spectrum_readMemory(this.__wbg_ptr, address, length);
|
|
405
|
+
if (ret[3]) {
|
|
406
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
407
|
+
}
|
|
408
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
409
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
410
|
+
return v1;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Restores compatible machine state, clearing pending host input/audio.
|
|
414
|
+
* @param {Uint8Array} bytes
|
|
415
|
+
*/
|
|
416
|
+
restore_state(bytes) {
|
|
417
|
+
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
|
|
418
|
+
const len0 = WASM_VECTOR_LEN;
|
|
419
|
+
const ret = wasm.spectrum_restore_state(this.__wbg_ptr, ptr0, len0);
|
|
420
|
+
if (ret[1]) {
|
|
421
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Returns the executed routine events and whether the stop was reached.
|
|
426
|
+
*
|
|
427
|
+
* # Errors
|
|
428
|
+
* Returns a JSON serialisation error if the recording cannot be encoded.
|
|
429
|
+
* @returns {string}
|
|
430
|
+
*/
|
|
431
|
+
routineTrace() {
|
|
432
|
+
let deferred2_0;
|
|
433
|
+
let deferred2_1;
|
|
434
|
+
try {
|
|
435
|
+
const ret = wasm.spectrum_routineTrace(this.__wbg_ptr);
|
|
436
|
+
var ptr1 = ret[0];
|
|
437
|
+
var len1 = ret[1];
|
|
438
|
+
if (ret[3]) {
|
|
439
|
+
ptr1 = 0; len1 = 0;
|
|
440
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
441
|
+
}
|
|
442
|
+
deferred2_0 = ptr1;
|
|
443
|
+
deferred2_1 = len1;
|
|
444
|
+
return getStringFromWasm0(ptr1, len1);
|
|
445
|
+
} finally {
|
|
446
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Installs a numbered BASIC listing directly into RAM and asks the ROM
|
|
451
|
+
* to RUN it. Call on a fresh 48K; no tape is mounted or played.
|
|
452
|
+
*
|
|
453
|
+
* # Errors
|
|
454
|
+
* Returns conversion, boot or editor-prompt errors.
|
|
455
|
+
* @param {string} source
|
|
456
|
+
*/
|
|
457
|
+
runBasic(source) {
|
|
458
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
459
|
+
const len0 = WASM_VECTOR_LEN;
|
|
460
|
+
const ret = wasm.spectrum_runBasic(this.__wbg_ptr, ptr0, len0);
|
|
461
|
+
if (ret[1]) {
|
|
462
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Installs machine code in a fresh 48K and calls it through the ROM's
|
|
467
|
+
* RANDOMIZE USR, with CLEAR reserving its RAM and a valid return stack.
|
|
468
|
+
*
|
|
469
|
+
* # Errors
|
|
470
|
+
* Rejects empty code, overlap with BASIC/system RAM, overflow, entry
|
|
471
|
+
* outside the code, and ROM boot or prompt failures.
|
|
472
|
+
* @param {Uint8Array} bytes
|
|
473
|
+
* @param {number} origin
|
|
474
|
+
* @param {number} entry
|
|
475
|
+
*/
|
|
476
|
+
runCode(bytes, origin, entry) {
|
|
477
|
+
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
|
|
478
|
+
const len0 = WASM_VECTOR_LEN;
|
|
479
|
+
const ret = wasm.spectrum_runCode(this.__wbg_ptr, ptr0, len0, origin, entry);
|
|
480
|
+
if (ret[1]) {
|
|
481
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Exports the current machine state.
|
|
486
|
+
* @returns {Uint8Array}
|
|
487
|
+
*/
|
|
488
|
+
save_state() {
|
|
489
|
+
const ret = wasm.spectrum_save_state(this.__wbg_ptr);
|
|
490
|
+
if (ret[3]) {
|
|
491
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
492
|
+
}
|
|
493
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
494
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
495
|
+
return v1;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Returns captured writes (including ROM writes) and saturation status.
|
|
499
|
+
* Consumers can select the program's PC range without inventing a trace.
|
|
500
|
+
*
|
|
501
|
+
* # Errors
|
|
502
|
+
* Returns a serialisation error if the capture cannot be encoded.
|
|
503
|
+
* @returns {string}
|
|
504
|
+
*/
|
|
505
|
+
screenWriteTrace() {
|
|
506
|
+
let deferred2_0;
|
|
507
|
+
let deferred2_1;
|
|
508
|
+
try {
|
|
509
|
+
const ret = wasm.spectrum_screenWriteTrace(this.__wbg_ptr);
|
|
510
|
+
var ptr1 = ret[0];
|
|
511
|
+
var len1 = ret[1];
|
|
512
|
+
if (ret[3]) {
|
|
513
|
+
ptr1 = 0; len1 = 0;
|
|
514
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
515
|
+
}
|
|
516
|
+
deferred2_0 = ptr1;
|
|
517
|
+
deferred2_1 = len1;
|
|
518
|
+
return getStringFromWasm0(ptr1, len1);
|
|
519
|
+
} finally {
|
|
520
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
271
523
|
/**
|
|
272
524
|
* Starts or stops machine audio.
|
|
273
525
|
* @param {boolean} enabled
|
|
@@ -275,6 +527,17 @@ export class Spectrum {
|
|
|
275
527
|
setAudioEnabled(enabled) {
|
|
276
528
|
wasm.spectrum_setAudioEnabled(this.__wbg_ptr, enabled);
|
|
277
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* Advances exactly one frame without drawing to a canvas.
|
|
532
|
+
* # Errors
|
|
533
|
+
* Returns the runtime's execution error.
|
|
534
|
+
*/
|
|
535
|
+
step() {
|
|
536
|
+
const ret = wasm.spectrum_step(this.__wbg_ptr);
|
|
537
|
+
if (ret[1]) {
|
|
538
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
278
541
|
/**
|
|
279
542
|
* Runs the machine for `elapsed_ms` of real time and draws the result.
|
|
280
543
|
*
|
|
@@ -303,6 +566,29 @@ export class Spectrum {
|
|
|
303
566
|
}
|
|
304
567
|
}
|
|
305
568
|
if (Symbol.dispose) Spectrum.prototype[Symbol.dispose] = Spectrum.prototype.free;
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Tokenise source and create an auto-starting BASIC TAP, without a machine.
|
|
572
|
+
*
|
|
573
|
+
* # Errors
|
|
574
|
+
* Returns a JavaScript error for unsupported or malformed listing input.
|
|
575
|
+
* @param {string} source
|
|
576
|
+
* @param {string} name
|
|
577
|
+
* @returns {Uint8Array}
|
|
578
|
+
*/
|
|
579
|
+
export function basicTape(source, name) {
|
|
580
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
581
|
+
const len0 = WASM_VECTOR_LEN;
|
|
582
|
+
const ptr1 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
583
|
+
const len1 = WASM_VECTOR_LEN;
|
|
584
|
+
const ret = wasm.basicTape(ptr0, len0, ptr1, len1);
|
|
585
|
+
if (ret[3]) {
|
|
586
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
587
|
+
}
|
|
588
|
+
var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
589
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
590
|
+
return v3;
|
|
591
|
+
}
|
|
306
592
|
function __wbg_get_imports() {
|
|
307
593
|
const import0 = {
|
|
308
594
|
__proto__: null,
|
|
@@ -417,7 +703,7 @@ function __wbg_get_imports() {
|
|
|
417
703
|
return ret;
|
|
418
704
|
},
|
|
419
705
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
420
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
706
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 30, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
421
707
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_d6cb7d81ec28c0ae___convert__closures_____invoke___wasm_bindgen_d6cb7d81ec28c0ae___JsValue__core_f0fd674eaa06beef___result__Result_____wasm_bindgen_d6cb7d81ec28c0ae___JsError___true_);
|
|
422
708
|
return ret;
|
|
423
709
|
},
|
|
Binary file
|
package/package.json
CHANGED