msgba-web/templates/static/index.html.ep

171 lines
6.8 KiB
Plaintext

<!DOCTYPE html>
<html>
<head>
<style>
body {
min-height: 100vh;
}
.center-content {
display: flex;
justify-content: center;
}
form label, form input {
display: block;
}
</style>
</head>
<body>
<div class="center-content">
<h2>msGBA Emulator Online for GBA.</h2>
</div>
<div class="center-content">
<canvas id="emulator" width="240" height="160">
</canvas>
</div>
<div class="center-content" id="form-select-files">
<form>
<label for="rom">
Rom file
<input type="file" id="rom" name="rom"/>
</label
<label for="savestate">
Savestate (A ss file from mgba...)
<input type="file" id="savestate" name="savestate"/>
</label>
<input type="button" value="Start emulation" id="start-emulation-button">
</form>
</div>
<script>
"use strict";
const MIN_WIDTH = 240;
const MIN_HEIGHT = 160;
const canvas = document.querySelector('#emulator');
const ctx = canvas.getContext('2d');
const emulator_dimensions = { width: MIN_WIDTH, height: MIN_HEIGHT };
const start_emulation_button = document.querySelector('#start-emulation-button');
const rom_file_selector = document.querySelector('#rom');
const savestate_file_selector = document.querySelector('#savestate');
const PACKET_ID_HELLO = 0n;
// Send is sent from server, so it is get here but whatever, it is the bad naming of the protocol.
const PACKET_ID_SEND_FRAME = 1n;
let websocket = null;
let is_little_endian = true;
(()=>{
let buf = new ArrayBuffer(4);
let buf8 = new Uint8ClampedArray(buf);
let data = new Uint32Array(buf);
data[0] = 0xdeadbeef;
if(buf8[0] === 0xde){
is_little_endian = false;
}
})();
console.log((is_little_endian ? 'Little endian' : 'Big endian') + " Detected");
function u64ToByteArrayBigEndian(input_number) {
const buffer = new ArrayBuffer(8);
const buffer8 = new Uint8Array(buffer);
const buffer64 = new BigUint64Array(buffer);
buffer64[0] = input_number;
if (is_little_endian) {
buffer8.reverse();
}
return buffer8;
}
function concatU8Array(array1, array2) {
const final_array = new Uint8Array(array1.length + array2.length);
final_array.set(array1);
final_array.set(array2, array1.length);
return final_array;
}
start_emulation_button.addEventListener('click', () => {
if (rom_file_selector.files.length == 0) {
alert('There is no rom still');
return;
}
if (savestate_file_selector.files.length == 0) {
alert('There is no savestate still');
return;
}
const rom_file = rom_file_selector.files[0];
const savestate_file = savestate_file_selector.files[0];
rom_file.arrayBuffer().then((rom_buffer) => {
savestate_file.arrayBuffer().then((savestate_buffer) => {
const rom_array = new Uint8Array(rom_buffer);
const savestate_array = new Uint8Array(savestate_buffer);
websocket = new WebSocket(`ws://${location.host}/ws`);
websocket.addEventListener('open', () => {
console.log('Opened websocket.');
sendHello(websocket, rom_array, savestate_array);
});
});
});
});
function sendHello(websocket, rom_array, savestate_array) {
console.log('Sending hello.');
const length_rom = BigInt(rom_array.length);
const length_savestate = BigInt(savestate_array.length);
const raw_data =
concatU8Array(
concatU8Array(
concatU8Array(u64ToByteArrayBigEndian(length_rom), rom_array),
u64ToByteArrayBigEndian(length_savestate)
),
savestate_array
);
sendPacket(websocket, PACKET_ID_HELLO, raw_data);
}
function sendPacket(websocket, id, raw_data) {
const packet_u8 = concatU8Array(
concatU8Array(u64ToByteArrayBigEndian(BigInt(id)), u64ToByteArrayBigEndian(BigInt(raw_data.length))),
raw_data
);
const packet_blob = packet_u8.buffer;
console.log('Sending packet');
websocket.send(packet_blob);
}
function resizeEmulator(canvas) {
const width = document.body.clientWidth;
const height = document.body.clientHeight;
if (width < MIN_WIDTH || height < MIN_HEIGHT) {
alert('Size too small.');
return;
}
const ratio_width = Math.floor(width / MIN_WIDTH);
const ratio_height = Math.floor(height / MIN_HEIGHT);
if (ratio_width < ratio_height) {
emulator_dimensions.width = MIN_WIDTH * ratio_width;
emulator_dimensions.height = MIN_HEIGHT * ratio_width;
} else {
emulator_dimensions.height = MIN_HEIGHT * ratio_height;
emulator_dimensions.width = MIN_WIDTH * ratio_height;
}
canvas.width = emulator_dimensions.width;
canvas.height = emulator_dimensions.height;
fillBlack(ctx);
}
function fillBlack(ctx) {
ctx.beginPath();
ctx.rect(0, 0, emulator_dimensions.width, emulator_dimensions.height);
ctx.fillStyle = 'black';
ctx.fill();
}
function connectWebsocket(rom, savestate) {
}
window.addEventListener('resize', () => {
resizeEmulator(canvas);
});
resizeEmulator(canvas);
</script>
</body>
</html>