msgba-web/js-src/packet.ts

73 lines
2.8 KiB
TypeScript

import Endian from '/endian';
import {MIN_WIDTH, MIN_HEIGHT, PACKET_ID_HELLO, PACKET_ID_SEND_FRAME, PACKET_ID_KEY_DOWN} from '/constants';
function concatU8Array(array1: Uint8Array, array2: Uint8Array) {
const final_array = new Uint8Array(array1.length + array2.length);
final_array.set(array1);
final_array.set(array2, array1.length);
return final_array;
}
export function sendHello(websocket: WebSocket, rom_array: Uint8Array, savestate_array: Uint8Array) {
console.log('Sending hello.');
const length_rom = BigInt(rom_array.length);
const length_savestate = BigInt(savestate_array.length);
const raw_data =
concatU8Array(
concatU8Array(
concatU8Array(Endian.u64ToByteArrayBigEndian(length_rom), rom_array),
Endian.u64ToByteArrayBigEndian(length_savestate)
),
savestate_array
);
sendPacket(websocket, PACKET_ID_HELLO, raw_data);
}
export function sendKeyDown(websocket: WebSocket, isDown: boolean, key: number) {
console.log('Sending keyDown.');
console.log(PACKET_ID_KEY_DOWN);
const isDownArray = new Uint8Array(1);
isDownArray[0] = isDown ? 1: 0;
const rawData = concatU8Array(isDownArray, Endian.u32ToByteArrayBigEndian(key));
console.log(rawData.length);
sendPacket(websocket, PACKET_ID_KEY_DOWN, rawData);
}
export function sendPacket(websocket: WebSocket, id: bigint, raw_data: Uint8Array) {
const packet_u8 = concatU8Array(
concatU8Array(Endian.u64ToByteArrayBigEndian(id), Endian.u64ToByteArrayBigEndian(BigInt(raw_data.length))),
raw_data
);
const packet_buffer = packet_u8.buffer;
console.log('Sending packet');
websocket.send(packet_buffer);
}
export function handleSendFrame(raw_data: Uint8Array, canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, printingFrame: boolean, setPrintingFrame: (c: boolean) => void) {
if (printingFrame) {
return;
}
setPrintingFrame(true);
let data: Uint8Array | null = raw_data;
const stride = Endian.byteArrayToU32BigEndian(data.slice(0, 4));
data = data.slice(4, data.length);
const output_buffer_size = Endian.byteArrayToU64BigEndian(data.slice(0, 8));
data = data.slice(8, data.length);
const img_data = ctx.createImageData(MIN_WIDTH, MIN_HEIGHT);
const img_data_u8 = new Uint8Array(img_data.data.buffer);
for (let i = 0; i<data.length; i++) {
if (i % 4 == 3) {
img_data_u8[i] = 255;
continue;
}
img_data_u8[i] = data[i];
}
data = null;
createImageBitmap(img_data).then((bitmap) => drawBitmap(bitmap, canvas, ctx, printingFrame));
}
function drawBitmap(bitmap: ImageBitmap, canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, printingFrame: boolean) {
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
printingFrame = false;
}