Skip to content

Commit 6a081a5

Browse files
committed
Auto-load using typing into the emulator (should work better)
1 parent 508d2db commit 6a081a5

1 file changed

Lines changed: 61 additions & 6 deletions

File tree

packages/emulator/src/Emulator.js

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export class Emulator extends EventEmitter {
6565
break;
6666
case 'frameCompleted':
6767
// benchmarkRunCount++;
68+
this.advanceAutoType();
6869
if ('audioBufferLeft' in e.data) {
6970
this.audioHandler.frameCompleted(e.data.audioBufferLeft, e.data.audioBufferRight);
7071
}
@@ -86,12 +87,24 @@ export class Emulator extends EventEmitter {
8687
break;
8788
case 'fileOpened':
8889
if (e.data.mediaType == 'tape' && this.autoLoadTapes) {
89-
const TAPE_LOADERS_BY_MACHINE = {
90-
'48': {'default': '../tapeloaders/tape_48.szx', 'usr0': '../tapeloaders/tape_48.szx'},
91-
'128': {'default': '../tapeloaders/tape_128.szx', 'usr0': '../tapeloaders/tape_128_usr0.szx'},
92-
'5': {'default': '../tapeloaders/tape_pentagon.szx', 'usr0': '../tapeloaders/tape_pentagon_usr0.szx'},
93-
};
94-
this.openUrl(new URL(TAPE_LOADERS_BY_MACHINE[this.machineType][this.tapeAutoLoadMode], scriptUrl));
90+
if (this.machineType == 48) {
91+
/* 48K boots to BASIC, so cold-boot and type LOAD ""
92+
ourselves. The tapeloader snapshots park the machine
93+
in a captured state that breaks some games' loaders
94+
(e.g. report 5 "Out of screen"); a cold boot matches a
95+
real load. */
96+
this.reset();
97+
this.beginAutoTypeLoad();
98+
} else {
99+
/* 128K/Pentagon boot to a menu where a typed LOAD ""
100+
wouldn't apply, so drive them via the per-machine
101+
tapeloader snapshot. */
102+
const TAPE_LOADERS_BY_MACHINE = {
103+
'128': {'default': '../tapeloaders/tape_128.szx', 'usr0': '../tapeloaders/tape_128_usr0.szx'},
104+
'5': {'default': '../tapeloaders/tape_pentagon.szx', 'usr0': '../tapeloaders/tape_pentagon_usr0.szx'},
105+
};
106+
this.openUrl(new URL(TAPE_LOADERS_BY_MACHINE[this.machineType][this.tapeAutoLoadMode], scriptUrl));
107+
}
95108
if (!this.tapeTrapsEnabled) {
96109
this.playTape();
97110
}
@@ -214,6 +227,48 @@ export class Emulator extends EventEmitter {
214227
this.worker.postMessage({message: 'reset'});
215228
}
216229

230+
/* Cold-boot autoload for 48K: type LOAD "" + ENTER by injecting the matrix
231+
keypresses. Driven off completed emulator frames (not wall-clock time), so
232+
the keystrokes only advance while the CPU is actually executing - they wait
233+
for the machine to start and the ROM to boot rather than guessing. Tune the
234+
frame counts if the keystrokes land before the ROM is ready or get merged. */
235+
beginAutoTypeLoad() {
236+
const BOOT_FRAMES = 120; // ~2.4s of execution for the ROM to reach the input loop
237+
const HOLD_FRAMES = 5; // frames each key/chord is held down
238+
const GAP_FRAMES = 5; // frames between keystrokes so the ROM debounces
239+
240+
const SYMBOL_SHIFT = {row: 7, mask: 0x02};
241+
const P = {row: 5, mask: 0x01};
242+
const J = {row: 6, mask: 0x08};
243+
const ENTER = {row: 6, mask: 0x01};
244+
245+
/* LOAD "" : J = the LOAD keyword, " = symbol-shift + P (x2), then ENTER */
246+
const chords = [[J], [SYMBOL_SHIFT, P], [SYMBOL_SHIFT, P], [ENTER]];
247+
248+
const actions = [];
249+
let frame = BOOT_FRAMES;
250+
for (const chord of chords) {
251+
actions.push({frame, message: 'keyDown', keys: chord});
252+
frame += HOLD_FRAMES;
253+
actions.push({frame, message: 'keyUp', keys: chord});
254+
frame += GAP_FRAMES;
255+
}
256+
this.autoTypeActions = actions;
257+
this.autoTypeFrame = 0;
258+
}
259+
260+
advanceAutoType() {
261+
if (!this.autoTypeActions) return;
262+
this.autoTypeFrame++;
263+
while (this.autoTypeActions.length && this.autoTypeActions[0].frame <= this.autoTypeFrame) {
264+
const action = this.autoTypeActions.shift();
265+
for (const k of action.keys) {
266+
this.worker.postMessage({message: action.message, row: k.row, mask: k.mask});
267+
}
268+
}
269+
if (!this.autoTypeActions.length) this.autoTypeActions = null;
270+
}
271+
217272
loadSnapshot(snapshot) {
218273
const fileID = this.nextFileOpenID++;
219274
this.worker.postMessage({

0 commit comments

Comments
 (0)