@moonbase-machines/player 0.12.0 → 0.13.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.
- package/README.md +3 -1
- package/audio.js +11 -3
- package/data.js +16 -1
- package/dist/moonbase-player.js +20 -14
- package/dist/moonbase-player.js.map +4 -4
- package/engines/original.js +35 -24
- package/engines/scenes.js +5 -1
- package/keys.js +18 -0
- package/package.json +6 -6
- package/play.js +11 -2
- package/test/play.test.js +20 -1
package/README.md
CHANGED
|
@@ -36,7 +36,9 @@ No title is named in it. A title is a folder of its own, kept with the title, wh
|
|
|
36
36
|
- its scenes (`<name>.scene`) and `compiled/` (`moonbase-compile`); `remake/README.md` says what a scene is, how it
|
|
37
37
|
is compiled and run, and the two engines.
|
|
38
38
|
|
|
39
|
-
Beside it the game's data, `<name>.json` (its disks' files, its kind,
|
|
39
|
+
Beside it the game's data, `<name>.json` (its disks' files, its kind, where it saves, `saves`, and its demonstrations,
|
|
40
|
+
`demonstrations`, where its sheet has some: each a name and the steps a person types to see it, which the Original
|
|
41
|
+
types into a Commodore 64 game at a button of that name; `data.js` makes the file and checks every step).
|
|
40
42
|
|
|
41
43
|
```html
|
|
42
44
|
<link rel="stylesheet" href="/packages/player/player.css">
|
package/audio.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
// The speaker. The Apple II makes sound by clicking the speaker, a toggle at $C030, and the
|
|
2
2
|
// machine keeps the cycle of each click. `Speaker` turns a run of cycles into a square wave
|
|
3
3
|
// at the sound card's rate and plays it through a worklet, which keeps a queue of what it has
|
|
4
|
-
// been given and holds the last level when the queue runs dry.
|
|
4
|
+
// been given and holds the last level when the queue runs dry. The queue keeps a quarter of a
|
|
5
|
+
// second at most, the oldest dropped: sound made faster than it plays (a machine catching up a
|
|
6
|
+
// hitch, a pause in a hidden tab) would otherwise put the sound behind the picture for good.
|
|
5
7
|
const CYCLES_PER_SECOND = 1020484;
|
|
6
8
|
|
|
7
9
|
const WORKLET = `
|
|
8
10
|
class SpeakerProcessor extends AudioWorkletProcessor {
|
|
9
|
-
constructor() {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(); this.queue = []; this.at = 0; this.level = 0; this.queued = 0;
|
|
13
|
+
this.port.onmessage = e => {
|
|
14
|
+
this.queue.push(e.data); this.queued += e.data.length;
|
|
15
|
+
while (this.queued > sampleRate / 4 && this.queue.length > 1) { this.queued -= this.queue[0].length - this.at; this.queue.shift(); this.at = 0; }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
10
18
|
process(inputs, outputs) {
|
|
11
19
|
const out = outputs[0][0];
|
|
12
20
|
for (let i = 0; i < out.length; i++) {
|
|
13
21
|
while (this.queue.length && this.at >= this.queue[0].length) { this.queue.shift(); this.at = 0; }
|
|
14
|
-
if (this.queue.length) this.level = this.queue[0][this.at++];
|
|
22
|
+
if (this.queue.length) { this.level = this.queue[0][this.at++]; this.queued--; }
|
|
15
23
|
out[i] = this.level;
|
|
16
24
|
}
|
|
17
25
|
return true;
|
package/data.js
CHANGED
|
@@ -4,15 +4,21 @@
|
|
|
4
4
|
// whole as well, for a machine with Apple's own ROMs, which boots them (`images`, @moonbase-machines/apple2e/disk2.js,
|
|
5
5
|
// blocks.js), the data naming them.
|
|
6
6
|
//
|
|
7
|
-
// const { data, images } = gameData(slug, { title, kind, disks, system, call, loads, wait, start, saves })
|
|
7
|
+
// const { data, images } = gameData(slug, { title, kind, disks, system, call, loads, wait, start, saves, demonstrations })
|
|
8
8
|
// kind 'prodos', 'dos33' or 'c64'
|
|
9
9
|
// disks each disk image's bytes, in order (a 140K .dsk, a .2mg; a C64's .d64)
|
|
10
10
|
// saves where the game saves, { volume, dos } (@moonbase-machines/apple2e/saves.js), if it does
|
|
11
|
+
// demonstrations
|
|
12
|
+
// what the game's own sheet has a person type to see it work, each a name and its steps, typed into the
|
|
13
|
+
// game by the player's button of that name (play.js): [{ name, steps: [{ key: 'return' }, { key: 'f4' },
|
|
14
|
+
// { type: '1 PISTONS' }, ...] }] (keys.js `typing` says what a step is); a C64 game's, whose engine types
|
|
15
|
+
// them (engines/original.js); refused for another kind
|
|
11
16
|
// data the game's data, for <slug>.json
|
|
12
17
|
// images an Apple game's disks, [{ name: <slug>-<n>.dsk or .2mg, bytes }]
|
|
13
18
|
import { prodos } from '@moonbase-machines/apple2e/prodos-disk.js';
|
|
14
19
|
import { dos33 } from '@moonbase-machines/apple2e/dos33-disk.js';
|
|
15
20
|
import { read as d64 } from '@moonbase-machines/c64/d64.js';
|
|
21
|
+
import { typing } from './keys.js';
|
|
16
22
|
|
|
17
23
|
const b64 = bytes => Buffer.from(bytes).toString('base64');
|
|
18
24
|
|
|
@@ -35,5 +41,14 @@ export function gameData(slug, game) {
|
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
if (game.saves) data.saves = game.saves;
|
|
44
|
+
if (game.demonstrations) {
|
|
45
|
+
if (game.kind !== 'c64') throw new Error(`${slug}: a demonstration is typed into a C64 game only`);
|
|
46
|
+
if (!Array.isArray(game.demonstrations)) throw new Error(`${slug}: demonstrations is a list`);
|
|
47
|
+
data.demonstrations = game.demonstrations.map(d => {
|
|
48
|
+
if (typeof d?.name !== 'string' || !d.name) throw new Error(`${slug}: a demonstration has a name`);
|
|
49
|
+
typing(d.steps, game.kind); // (checked here, once, so that the player never meets a step it cannot type)
|
|
50
|
+
return { name: d.name, steps: d.steps };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
38
53
|
return { data, images };
|
|
39
54
|
}
|