All files / src/web autoboot.js

100% Statements 37/37
100% Branches 4/4
100% Functions 11/11
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                  8x 8x 8x       6x       1x 1x     1x       3x 3x   3x 3x       1x 1x   1x 1x       1x 1x   1x 1x       1x 1x   1x 1x               2x 2x 2x   2x 2x 2x 4x 2x 2x 29x   2x 2x 1x          
import * as tokeniser from "../basic-tokenise.js";
import { installBasic } from "../basic-loader.js";
import { noteEvent } from "./analytics.js";
import { BBC } from "../keymap.js";
 
/** Booting and typing for the machine at startup: shift-break, *TAPE incantations and BASIC programs. */
export class Autoboot {
    /** @param {Function} deps.sendKeys sends a raw key sequence once the keyboard exists */
    constructor({ model, processor, sendKeys }) {
        this.model = model;
        this.processor = processor;
        this.sendKeys = sendKeys;
    }
 
    stringToMachineKeys(text) {
        return this.model.stringToKeys(text);
    }
 
    boot(image) {
        console.log("Autobooting disc");
        noteEvent("init", "autoboot", image);
 
        // Shift-break simulation, hold SHIFT for 1000ms.
        this.sendKeys([BBC.SHIFT, 1000], false);
    }
 
    type(keys) {
        console.log("Auto typing '" + keys + "'");
        noteEvent("init", "autochain");
 
        const bbcKeys = this.stringToMachineKeys(keys);
        this.sendKeys([1000].concat(bbcKeys), false);
    }
 
    chainTape() {
        console.log("Auto Chaining Tape");
        noteEvent("init", "autochain");
 
        const bbcKeys = this.stringToMachineKeys('*TAPE\nCH.""\n');
        this.sendKeys([1000].concat(bbcKeys), false);
    }
 
    runTape() {
        console.log("Auto Running Tape");
        noteEvent("init", "autorun");
 
        const bbcKeys = this.stringToMachineKeys("*TAPE\n*/\n");
        this.sendKeys([1000].concat(bbcKeys), false);
    }
 
    runBasic() {
        console.log("Auto Running basic");
        noteEvent("init", "autorunbasic");
 
        const bbcKeys = this.stringToMachineKeys("RUN\n");
        this.sendKeys([1000].concat(bbcKeys), false);
    }
 
    /**
     * Tokenises a BASIC program and installs it once the OS reaches its idle
     * loop, so it lands after the machine has finished starting up.
     */
    async insertBasic(getBasicPromise, needsRun) {
        const prog = await getBasicPromise;
        const t = await tokeniser.create();
        const tokenised = await t.tokenise(prog);
 
        const { processor } = this;
        const idleAddr = this.model.idleAddress;
        const hook = processor.debugInstruction.add((addr) => {
            if (addr !== idleAddr) return;
            installBasic(tokenised, {
                readByte: (a) => processor.readmem(a),
                writeByte: (a, value) => processor.writemem(a, value),
            });
            hook.remove();
            if (needsRun) {
                this.runBasic();
            }
        });
    }
}