const frame_rate = (0x400000 / 70224.0); const ms_per_frame = 1000 / frame_rate; let last_frame_time = 0; const stringHash = str => { let hash = 0; if (str.length === 0) return hash; for (let i = 0; i < str.length; i++) { let chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; // Convert to 32bit integer } return hash; } const run_frame = time => { window.requestAnimationFrame(run_frame); const delta = time - last_frame_time; if (delta > ms_per_frame) { Module._run_frame(); last_frame_time = time - (delta % ms_per_frame); } } const loadRomFromMemory = (name, data) => { const pos = name.lastIndexOf('.'); const battery_name = name.substr(0, pos < 0 ? name.length : pos) + '.sav'; try { // try to create the virtual ROM folder FS.mkdir('/rom'); } catch (e) { } try { // try to delete all previous ROM files for (let file of FS.readdir('/rom').filter(f => f != '.' && f != '..')) { FS.unlink(`/rom/${file}`) } } catch (e) { } // create a new virtual file from memory Module['FS_createDataFile']('/rom/', name, new Uint8Array(data), true, true); const rom_path = allocate(intArrayFromString(`/rom/${name}`), 'i8', ALLOC_NORMAL); const battery_path = allocate(intArrayFromString(`/persist/${battery_name}`), 'i8', ALLOC_NORMAL); Module._load_rom_from_file(rom_path, battery_path); // The ROM has been read into memory, we can unlink the file now FS.unlink(`/rom/${name}`) window.requestAnimationFrame(run_frame) } const loadROM = f => { const reader = new FileReader(); reader.onload = (file => { return event => { loadRomFromMemory(file.name, event.target.result) }; })(f); reader.readAsArrayBuffer(f); } const loadRemoteRom = url => { const request = new Request(url); const name = (_ => { const name = url.substring(url.lastIndexOf('/') + 1); if (name.endsWith('.gb') || name.endsWith('.gbc')) { return name } else if (name.length) { return `${name}.gb` } return stringHash(url) })() return fetch(request).then(response => { if (!response.ok) { throw new Error('HTTP error, status = ' + response.status); } return response.arrayBuffer(); }).then(buf => { loadRomFromMemory(name, buf) }) } const handleFileSelect = (evt, files) => { evt.stopPropagation(); evt.preventDefault(); if (files.length) { loadROM(files[0]); } } const handleDragOver = evt => { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } window.addEventListener('dragover', handleDragOver, false); window.addEventListener('drop', e => { handleFileSelect(e, e.dataTransfer.files); }, false); document.getElementById('file').addEventListener('change', e => { handleFileSelect(e, e.target.files); }, false); Module.onRuntimeInitialized = _ => { console.log(Module.get_models()); console.log(Module.get_sgb_revisions()); FS.mkdir('/persist'); FS.mount(IDBFS, { }, '/persist'); FS.syncfs(true, function (err) { if (!err) { console.log('Successfully loaded FS from persistent storage') } else { console.error(err) } // Call the exported init function Module._init(); }) }; const romClickHandler = event => { event.stopPropagation(); event.preventDefault(); loadRemoteRom(event.target.href); } for (const anchor of document.querySelectorAll('#demo-roms a')) { anchor.addEventListener('click', romClickHandler); }