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 | 3x 5x 5x 1x 4x 4x 1x 4x 2x 27x 27x 6x 4x 2x 2x 2x 2x 1x 1x | import { unzipDiscImage } from "./archive.js";
import { failingFor, fetchBytes, LoadFailures } from "./loader.js";
// Always https, whatever the page was loaded over: the mirror redirects plain
// http, so following the page's protocol would cost a redirect on every request
// when developing over http, and Electron reports "file:" anyway.
const mirrorBase = "https://bbc.xania.org/archive/sth";
async function _fetchManifest(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Network response was not ok (${response.status})`);
}
const data = await response.json();
if (!Array.isArray(data?.files)) {
throw new Error("Invalid manifest: missing files array");
}
return data.files.map((f) => f.path).sort();
}
// Each path component is encoded individually so slashes survive but special
// characters in filenames (e.g. brackets in "Daxis[droids]-demo.zip") don't
// produce a malformed URL.
function encodePath(path) {
return path.split("/").map(encodeURIComponent).join("/");
}
export class StairwayToHell {
/** @param {{tapes?: boolean}} [what] the tape images rather than the disc images */
constructor({ tapes = false } = {}) {
this._baseUrl = `${mirrorBase}/${tapes ? "tape" : "disk"}images/`;
this._catalog = [];
}
/** @returns {Promise<string[]>} every path in the archive, fetched the first time it is asked for */
async catalogue() {
if (this._catalog.length === 0) this._catalog = await _fetchManifest(this._baseUrl + "manifest.json");
return this._catalog;
}
async fetch(file) {
const url = this._baseUrl + encodePath(file);
const data = await fetchBytes(url);
try {
return await failingFor(LoadFailures.badImage, () => unzipDiscImage(data));
} catch (error) {
console.error("Failed to fetch file:", error);
throw error;
}
}
}
|