This repository has been archived on 2024-06-01. You can view files and clone it, but cannot push or open issues or pull requests.
rustboyadvance-ng/platform/rustboyadvance-wasm/app/index.js

236 lines
6.4 KiB
JavaScript
Raw Normal View History

import * as wasm from "rustboyadvance-wasm";
var fps_text = document.getElementById('fps');
var canvas = document.getElementById("screen");
var ctx = canvas.getContext('2d');
var intervalId = 0;
var romData = null;
var biosData = null;
let emulator = null;
document.getElementById("skipBios").checked = JSON.parse(localStorage.getItem("skipBios"));
var shouldSkipBios = document.getElementById("skipBios").checked;
console.log("Calling wasm init routine");
wasm.init();
function loadLocalFile(localFile, callback) {
var reader = new FileReader();
reader.onload = function(e) {
var data = reader.result;
var array = new Uint8Array(data);
callback(array);
};
reader.readAsArrayBuffer(localFile);
}
function ensureFilesLoaded() {
var bios = localStorage.getItem("bios");
if (null == biosData) {
alert("please load bios first!");
return false;
}
if (null == romData) {
alert("rom not loaded");
return false;
}
return true;
}
const convertAudioBuffer = buffer => {
let length = buffer.length;
const floatArray = new Float32Array(length);
for (let i = 0; i < length; i++) {
floatArray[i] = (buffer[i] - 32767) / 32767;
}
return floatArray;
}
var fpsCounter = (function() {
var lastLoop = (new Date).getMilliseconds();
var count = 0;
var fps = 0;
return function() {
var currentLoop = (new Date).getMilliseconds();
if (lastLoop > currentLoop) {
fps = count;
count = 0;
} else {
count += 1;
}
lastLoop = currentLoop;
return fps;
}
}());
// Create our audio context
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
console.log("audio context " + audioContext);
const playAudio = emulator => {
let audioData = emulator.collect_audio_samples();
let frameCount = audioData.length / 2;
const audioBuffer = audioContext.createBuffer(
2,
frameCount,
audioContext.sampleRate
);
for (let channel = 0; channel < 2; channel++) {
let nowBuffering = audioBuffer.getChannelData(channel);
for (let i = 0; i < frameCount; i++) {
// audio data frames are interleaved
nowBuffering[i] = audioData[i*2 + channel];
}
}
const audioSource = audioContext.createBufferSource();
audioSource.buffer = audioBuffer;
audioSource.connect(audioContext.destination);
audioSource.start();
}
const emulatorLoop = function() {
emulator.run_frame(ctx);
fps_text.innerHTML = fpsCounter();
playAudio(emulator);
}
function startEmulator() {
if (!ensureFilesLoaded()) {
return;
}
if (intervalId != 0) {
console.log("killing emulator");
clearInterval(intervalId);
intervalId = 0;
emulator = null;
}
emulator = new wasm.Emulator(biosData, romData);
if (shouldSkipBios) {
emulator.skip_bios();
}
intervalId = setInterval(emulatorLoop, 16);
}
const biosCached = localStorage.getItem("biosCached");
if (biosCached) {
console.log("found cached bios!");
document.getElementById("bios-file-input").parentNode.style.display = "none";
document.getElementById("reloadBios").classList.remove("hidden");
biosData = new Uint8Array(JSON.parse(biosCached));
} else {
console.log("Bios is not cached");
var loadBios = biosFile => {
console.log("loaded file " + biosFile)
loadLocalFile(biosFile, result => {
console.log("Loaded bios (" + result.length + " bytes )");
biosData = result;
console.log("Caching to localStorage");
localStorage.setItem("biosCached", JSON.stringify(Array.from(biosData)));
document.getElementById("bios-file-input").parentNode.style.display = "none";
});
};
document.getElementById("bios-file-input").addEventListener('change', event => {
loadBios(event.target.files[0])
}, false);
}
document.getElementById("reloadBios").addEventListener('click', function() {
this.classList.add("hidden");
document.getElementById("bios-file-input").parentNode.style.display = "block";
localStorage.removeItem("biosCached");
}, false);
function loadRom(romFile) {
var promise = new Promise(function(resolve, reject) {
loadLocalFile(romFile, result => {
console.log('Loaded "' + romFile.name + '" ! length: ' + result.length);
var rom_info = wasm.parse_rom_header(result);
var rom_info2 = wasm.parse_rom_header(result);
console.log("Game Code" + rom_info.get_game_code());
console.log("Game Title" + rom_info.get_game_title());
romData = result;
resolve();
});
});
return promise;
};
let dropArea = document.getElementById('screen');
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName,
e => {
// prevent default events
e.preventDefault();
e.stopPropagation();
}, false)
});
dropArea.addEventListener('dragover', e => {
dropArea.classList.add('hover');
}, false);
dropArea.addEventListener('dragleave', e => {
dropArea.classList.remove('hover');
}, false);
dropArea.addEventListener('drop', e => {
dropArea.classList.remove('hover');
var files = e.dataTransfer.files;
loadRom(files[0]).then(startEmulator);
}, true);
document.getElementById("skipBios").addEventListener('change', e => {
shouldSkipBios = e.target.checked;
localStorage.setItem("skipBios", JSON.stringify(shouldSkipBios));
});
document.getElementById("rom-file-input").addEventListener('change', e => {
loadRom(e.target.files[0]).then(startEmulator);
}, false);
document.getElementById("startEmulator").addEventListener('click', e => {
if (null == emulator) {
startEmulator();
}
}, false);
document.getElementById("maxFps").addEventListener('change', e => {
if (intervalId != 0) {
let checked = e.target.checked;
clearInterval(intervalId);
if (checked) {
intervalId = setInterval(emulatorLoop, 0);
} else {
intervalId = setInterval(emulatorLoop, 16);
}
}
})
document.addEventListener("keydown", e => {
if (null != emulator) {
emulator.key_down(e.key)
}
}, false);
document.addEventListener("keyup", e => {
if (null != emulator) {
emulator.key_up(e.key)
}
}, false);