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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | 9x 9441x 62x 668x 35x 35x 35x 35x 35x 35x 35x 35x 37x 35x 35x 35x 35x 491x 42x 42x 35x 35x 35x 31x 31x 35x 23x 23x 23x 16x 16x 8x 35x 4x 70x 3984x 226x 3169x 37x 6x 6x 31x 31x 31x 925x 66x 139x 139x 1949x 1949x 139x 139x 42x 43x 43x 47x 47x 47x 47x 47x 35x 35x 35x 35x | import { getFilterForMode, persistenceSettings } from "./canvas.js";
import { MasterAnfsRom } from "../econet.js";
import {
configForm,
controlId,
PersistenceField,
readoutId,
renderConfigForm,
settingFields,
showValue,
} from "./config-form.js";
import { Parameters } from "./parameters.js";
/**
* The sideways ROMs the optional fittings need, in the order they claim banks.
*
* @param {{model: object, hasEconet: boolean, hasMusic5000: boolean, hasTeletextAdaptor: boolean}} settings
* @returns {string[]}
*/
export function fittedRoms({ model, hasEconet, hasMusic5000, hasTeletextAdaptor }) {
return [
...(hasEconet && model.isMaster ? [MasterAnfsRom] : []),
...(hasMusic5000 ? ["ample.rom"] : []),
...(hasTeletextAdaptor ? ["ats-3.0.rom"] : []),
];
}
const restartRequired = (parameters) => Object.keys(parameters).filter((name) => parameters[name].field?.restart);
/** @returns {boolean} whether any of the changed settings only take effect on a freshly built machine. */
export function needsRestart(changed, parameters = Parameters) {
return restartRequired(parameters).some((name) => name in changed);
}
/** @returns {boolean} whether the saved settings differ from those the running machine was built with. */
export function restartPending(settings, running, parameters = Parameters) {
return restartRequired(parameters).some((name) => settings[name] !== running[name]);
}
/**
* The Settings dialog: shows the settings, applies the ones the machine can
* follow live as they are picked, and saves the rest when it closes. Dispatches
* "restart-required" after saving a change the running machine cannot follow.
*/
export class Config extends EventTarget {
constructor(settings) {
super();
this.settings = settings;
this.changed = {};
// The setting the display in use declares, which is the mode asked for
// unless that fell back; the page says which once the display exists.
this.persistenceSetting = undefined;
const form = configForm(settings.parameters);
this.fields = settingFields(form);
const configuration = document.getElementById("configuration");
configuration
.querySelector(".modal-body")
.append(...renderConfigForm(form, (field, value) => this.pick(field, value)));
// Built before anything can change, so this is what the running machine was built with.
this.runningSettings = this.proposedSettings();
this.setModel(settings.model);
this.showSaved();
for (const field of this.fields) {
settings.on(field.setting, () => {
showValue(field, this.proposedSettings()[field.setting]);
this.showDependents();
});
}
settings.on("displayMode", (displayMode) => this.setDisplayMode(displayMode));
this.setDisplayMode(settings.displayMode);
configuration.addEventListener("show.bs.modal", () => {
this.changed = {};
this.showSaved();
});
configuration.addEventListener("hide.bs.modal", () => {
const changed = this.changed;
this.changed = {};
if (Object.keys(changed).length === 0) return;
settings.set(changed);
// changed records which controls were touched, so a value in it can be what is already running.
if (
needsRestart(changed, settings.parameters) &&
restartPending(this.proposedSettings(), this.runningSettings, settings.parameters)
)
this.dispatchEvent(new Event("restart-required"));
});
document.getElementById(controlId(PersistenceField)).addEventListener("input", (e) => {
if (this.persistenceSetting) settings.set({ [this.persistenceSetting]: parseFloat(e.currentTarget.value) });
});
for (const { setting } of persistenceSettings()) settings.on(setting, () => this.setPersistenceSlider());
}
saved(setting) {
return this.settings.value(setting);
}
/** Every setting the dialog shows, as it would be saved if the dialog were closed now. */
proposedSettings() {
return Object.fromEntries(
this.fields.map(({ setting }) => [
setting,
setting in this.changed ? this.changed[setting] : this.saved(setting),
]),
);
}
pick(field, value) {
if (field.live) {
this.settings.set({ [field.setting]: value });
return;
}
this.changed[field.setting] = value;
showValue(field, value);
this.showDependents();
}
showSaved() {
for (const field of this.fields) showValue(field, this.saved(field.setting));
this.showDependents();
}
/** The parts of the dialog that follow from the settings as they would be saved. */
showDependents() {
const proposed = this.proposedSettings();
for (const field of this.fields) {
if (field.enabledWhen) document.getElementById(controlId(field)).disabled = !field.enabledWhen(proposed);
if (field.readout)
document.getElementById(readoutId(field)).textContent = field.readout(
proposed[field.setting],
proposed,
);
}
document
.getElementById("restart-pending")
.classList.toggle("d-none", !restartPending(proposed, this.runningSettings, this.settings.parameters));
}
setDisplayMode(mode) {
this.setPersistenceInUse(getFilterForMode(mode).getDisplayConfig().persistence?.setting);
}
/** The slider edits the persistence of the display in use, and is disabled for one without it. */
setPersistenceInUse(setting) {
this.persistenceSetting = setting;
this.setPersistenceSlider();
}
setPersistenceSlider() {
const slider = document.getElementById(controlId(PersistenceField));
const afterglowMs = this.persistenceSetting ? this.settings[this.persistenceSetting] : 0;
slider.disabled = !this.persistenceSetting;
slider.value = afterglowMs;
document.getElementById(readoutId(PersistenceField)).textContent = this.persistenceSetting
? PersistenceField.readout(afterglowMs)
: "not available";
}
/** Names the running machine everywhere the page shows it. */
setModel(model) {
for (const el of document.querySelectorAll(".bbc-model")) el.textContent = model.name;
for (const el of document.querySelectorAll(".bbc-model-short")) el.textContent = model.shortName;
const settingsLink = document.getElementById("model-settings");
Iif (settingsLink) settingsLink.title = `${model.name}: emulation settings`;
}
}
|