All files / src machine-spec.js

91.66% Statements 11/12
100% Branches 14/14
87.5% Functions 7/8
88.88% Lines 8/9

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              88x     12x       88x                                           6658x 854x 6656x 852x                                   835x                      
import { Cmos } from "./cmos.js";
import { FakeDdNoise } from "./ddnoise.js";
import { FakeMusic5000 } from "./music5000.js";
import { FakeRelayNoise } from "./relaynoise.js";
import { FakeSoundChip } from "./soundchip.js";
import { FakeVideo } from "./video.js";
 
const NullUserPort = {
    write() {},
    read() {
        return 0xff;
    },
};
 
const SpecDefaults = {
    keyLayout: "physical",
    cpuMultiplier: 1,
    tubeCpuMultiplier: 1,
    videoCyclesBatch: 0,
    tube: null,
    hasMusic5000: false,
    hasTeletextAdaptor: false,
    fittedRoms: [],
    bankRoms: [],
    extraRoms: [],
    userPort: NullUserPort,
    printerPort: null,
    getGamepads: () => [],
};
 
/**
 * What a machine is fitted with and how it is driven, complete and frozen:
 * every field is present, an unknown one is an error, and an undefined
 * override means the default. It is the `config` a CPU is built with.
 */
export function machineSpec(overrides = {}) {
    const unknown = Object.keys(overrides).filter((field) => !Object.hasOwn(SpecDefaults, field));
    if (unknown.length) throw new Error(`Unknown machine spec fields: ${unknown.join(", ")}`);
    const given = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== undefined));
    return Object.freeze({
        ...SpecDefaults,
        ...given,
        fittedRoms: Object.freeze([...(given.fittedRoms ?? SpecDefaults.fittedRoms)]),
        bankRoms: Object.freeze([...(given.bankRoms ?? SpecDefaults.bankRoms)]),
        extraRoms: Object.freeze([...(given.extraRoms ?? SpecDefaults.extraRoms)]),
    });
}
 
/** Peripherals that go nowhere, for a machine run headless; `econet` is fitted if given, a
 * given `model` has its CMOS override applied and the CMOS keeps its settings in `cmosPersistence` if given. */
export function nullIo({
    video = new FakeVideo(),
    soundChip = new FakeSoundChip(),
    econet = null,
    model = null,
    cmosPersistence,
} = {}) {
    return {
        dbgr: { setCpu() {} },
        video,
        soundChip,
        ddNoise: new FakeDdNoise(),
        relayNoise: new FakeRelayNoise(),
        music5000: new FakeMusic5000(),
        cmos: new Cmos(cmosPersistence, model?.cmosOverride, econet),
        econet,
    };
}