@soapbox.pub/wasmboy
Version:
Soapbox fork of Wasmboy.
103 lines (86 loc) • 2.8 kB
JavaScript
// Modules
import uzip from '../3p/UZIP';
// Collection of functions to parse roms
// Private function to fetch a game
export const fetchROMAsByteArray = (ROM, loadOptions) => {
const fetchROMAsByteArrayTask = async () => {
// Check if we were passed straight bytes
if (ArrayBuffer.isView(ROM) && ROM.constructor === Uint8Array) {
return {
ROM: ROM
};
} else if (typeof ROM === 'object' && ROM.size) {
// We were passed a file from HTML file input
// Read the file as a Uint8Array
let byteArray = await getROMFromFileReaderAsByteArray(ROM);
if (ROM.name.toLowerCase().endsWith('.zip')) {
byteArray = await parseByteArrayAsZip(byteArray);
}
return {
ROM: byteArray,
name: ROM.name
};
} else {
// We were passed a URL
// Fetch the file
// First check if we have headers
const fetchHeaders = {};
if (loadOptions && loadOptions.headers) {
fetchHeaders.headers = loadOptions.headers;
}
let bytes = await fetch(ROM, fetchHeaders).then(blob => {
if (!blob.ok) {
return Promise.reject(blob);
}
return blob.arrayBuffer();
});
let fileName = ROM;
if (loadOptions && loadOptions.fileName) {
fileName = loadOptions.fileName;
}
// Get our byteArray
let byteArray = new Uint8Array(bytes);
if (fileName.toLowerCase().endsWith('.zip')) {
byteArray = await parseByteArrayAsZip(byteArray);
}
return {
ROM: byteArray,
name: fileName
};
}
};
return fetchROMAsByteArrayTask();
};
const getROMFromFileReaderAsByteArray = async ROM => {
const fileReaderByteArray = await new Promise((resolve, reject) => {
// Read the file object
// https://www.javascripture.com/FileReader#readAsArrayBuffer_Blob
const fileReader = new FileReader();
fileReader.onload = () => {
const byteArray = new Uint8Array(fileReader.result);
resolve(byteArray);
};
fileReader.readAsArrayBuffer(ROM);
});
return fileReaderByteArray;
};
// Function to parse and find the gb files within an archive
const parseByteArrayAsZip = async byteArray => {
// Parse the zip using UZIP
const unzipObject = await uzip.parse(byteArray);
// Find the ROM in the output
let foundROM = false;
const unzipObjectKeys = Object.keys(unzipObject);
unzipObjectKeys.some(key => {
const lowercaseKey = key.toLowerCase();
if (lowercaseKey.includes('.gb') || lowercaseKey.includes('.gbc') || lowercaseKey.includes('.bin')) {
foundROM = unzipObject[key];
return true;
}
return false;
});
if (!foundROM) {
throw new Error('Could not find a ROM in zip...');
}
return foundROM;
};