export const CRYSTAL_ROM = { name: "Pokémon Crystal · English US/Europe 1.1", sha1: "f2f52230b536214ef7c9924f483392993e226cfb", size: 2 * 1024 * 1024, } as const; export interface ValidatedRom { bytes: Uint8Array; sha1: string; name: string; } export async function validateRom(file: File): Promise { if (file.size !== CRYSTAL_ROM.size) { throw new Error( "Choose an uncompressed Pokémon Crystal English US/Europe 1.1 ROM (.gbc, 2 MiB).", ); } if (!globalThis.crypto?.subtle) { throw new Error( "ROM verification needs HTTPS or localhost. Open this player over a secure connection.", ); } const buffer = await file.arrayBuffer(); const digest = await crypto.subtle.digest("SHA-1", buffer); const sha1 = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0"), ).join(""); if (sha1 !== CRYSTAL_ROM.sha1) { throw new Error( "This ROM is not the supported English US/Europe revision 1.1. Other languages, revisions, and modified ROMs are not supported yet.", ); } return { bytes: new Uint8Array(buffer), sha1, name: CRYSTAL_ROM.name }; }