@soapbox.pub/wasmboy
Version:
Soapbox fork of Wasmboy.
1,441 lines (1,138 loc) • 472 kB
JavaScript
(function () {
'use strict';
function getEventData(event) {
if (event.data) {
return event.data;
}
return event;
}
const isInBrowser = typeof self !== 'undefined'; // Function to read a base64 string as a buffer
// Isomorphic worker api to be imported by web workers
let parentPort;
if (!isInBrowser) {
parentPort = require('worker_threads').parentPort;
} // https://nodejs.org/api/worker_threads.html#worker_threads_worker_postmessage_value_transferlist
// https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage
function postMessage(message, transferArray) {
// Can't bind parentPort.postMessage, so we need to kinda copy code here :p
if (isInBrowser) {
self.postMessage(message, transferArray);
} else {
parentPort.postMessage(message, transferArray);
}
} // https://nodejs.org/api/worker_threads.html#worker_threads_worker_parentport
// https://developer.mozilla.org/en-US/docs/Web/API/Worker/onmessage
function onMessage(callback, port) {
if (!callback) {
console.error('workerapi: No callback was provided to onMessage!');
} // If we passed a port, use that
if (port) {
if (isInBrowser) {
// We are in the browser
port.onmessage = callback;
} else {
// We are in Node
port.on('message', callback);
}
return;
}
if (isInBrowser) {
// We are in the browser
self.onmessage = callback;
} else {
// We are in Node
parentPort.on('message', callback);
}
}
const WORKER_MESSAGE_TYPE = {
CONNECT: 'CONNECT',
INSTANTIATE_WASM: 'INSTANTIATE_WASM',
CLEAR_MEMORY: 'CLEAR_MEMORY',
CLEAR_MEMORY_DONE: 'CLEAR_MEMORY_DONE',
GET_MEMORY: 'GET_MEMORY',
SET_MEMORY: 'SET_MEMORY',
SET_MEMORY_DONE: 'SET_MEMORY_DONE',
GET_CONSTANTS: 'GET_CONSTANTS',
GET_CONSTANTS_DONE: 'GET_CONSTANTS_DONE',
CONFIG: 'CONFIG',
RESET_AUDIO_QUEUE: 'RESET_AUDIO_QUEUE',
PLAY: 'PLAY',
BREAKPOINT: 'BREAKPOINT',
PAUSE: 'PAUSE',
UPDATED: 'UPDATED',
CRASHED: 'CRASHED',
SET_JOYPAD_STATE: 'SET_JOYPAD_STATE',
AUDIO_LATENCY: 'AUDIO_LATENCY',
RUN_WASM_EXPORT: 'RUN_WASM_EXPORT',
GET_WASM_MEMORY_SECTION: 'GET_WASM_MEMORY_SECTION',
GET_WASM_CONSTANT: 'GET_WASM_CONSTANT',
FORCE_OUTPUT_FRAME: 'FORCE_OUTPUT_FRAME',
SET_SPEED: 'SET_SPEED',
IS_GBC: 'IS_GBC'
};
const WORKER_ID = {
LIB: 'LIB',
GRAPHICS: 'GRAPHICS',
MEMORY: 'MEMORY',
CONTROLLER: 'CONTROLLER',
AUDIO: 'AUDIO'
};
const MEMORY_TYPE = {
BOOT_ROM: 'BOOT_ROM',
CARTRIDGE_RAM: 'CARTRIDGE_RAM',
CARTRIDGE_ROM: 'CARTRIDGE_ROM',
CARTRIDGE_HEADER: 'CARTRIDGE_HEADER',
GAMEBOY_MEMORY: 'GAMEBOY_MEMORY',
PALETTE_MEMORY: 'PALETTE_MEMORY',
INTERNAL_STATE: 'INTERNAL_STATE'
};
// Smarter workers.
let idCounter = 0;
const generateId = () => {
const randomId = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
idCounter++;
const id = `${randomId}-${idCounter}`;
if (idCounter > 100000) {
idCounter = 0;
}
return id;
};
function getSmartWorkerMessage(message, messageId, workerId) {
if (!messageId) {
messageId = generateId();
}
return {
workerId,
messageId,
message
};
}
// to the lib worker
function graphicsWorkerOnMessage(libWorker, event) {
// Handle our messages from the main thread
const eventData = getEventData(event);
switch (eventData.message.type) {
case WORKER_MESSAGE_TYPE.GET_CONSTANTS:
{
libWorker.WASMBOY_CURRENT_FRAME_OUTPUT_LOCATION = libWorker.wasmInstance.exports.FRAME_LOCATION.valueOf();
libWorker.WASMBOY_CURRENT_FRAME_SIZE = libWorker.wasmInstance.exports.FRAME_SIZE.valueOf(); // Forward to our lib worker
libWorker.graphicsWorkerPort.postMessage(getSmartWorkerMessage({
type: WORKER_MESSAGE_TYPE.GET_CONSTANTS_DONE,
WASMBOY_CURRENT_FRAME_OUTPUT_LOCATION: libWorker.wasmInstance.exports.FRAME_LOCATION.valueOf()
}, eventData.messageId));
return;
}
}
}
function audioWorkerOnMessage(libWorker, event) {
// Handle our messages from the main thread
const eventData = getEventData(event);
switch (eventData.message.type) {
case WORKER_MESSAGE_TYPE.GET_CONSTANTS:
{
libWorker.WASMBOY_SOUND_OUTPUT_LOCATION = libWorker.wasmInstance.exports.AUDIO_BUFFER_LOCATION.valueOf();
libWorker.WASMBOY_CHANNEL_1_OUTPUT_LOCATION = libWorker.wasmInstance.exports.CHANNEL_1_BUFFER_LOCATION.valueOf();
libWorker.WASMBOY_CHANNEL_2_OUTPUT_LOCATION = libWorker.wasmInstance.exports.CHANNEL_2_BUFFER_LOCATION.valueOf();
libWorker.WASMBOY_CHANNEL_3_OUTPUT_LOCATION = libWorker.wasmInstance.exports.CHANNEL_3_BUFFER_LOCATION.valueOf();
libWorker.WASMBOY_CHANNEL_4_OUTPUT_LOCATION = libWorker.wasmInstance.exports.CHANNEL_4_BUFFER_LOCATION.valueOf(); // Forward to our lib worker
libWorker.audioWorkerPort.postMessage(getSmartWorkerMessage({
type: WORKER_MESSAGE_TYPE.GET_CONSTANTS_DONE,
WASMBOY_SOUND_OUTPUT_LOCATION: libWorker.wasmInstance.exports.AUDIO_BUFFER_LOCATION.valueOf()
}, eventData.messageId));
return;
}
case WORKER_MESSAGE_TYPE.AUDIO_LATENCY:
{
libWorker.currentAudioLatencyInSeconds = eventData.message.latency;
return;
}
}
}
function controllerWorkerOnMessage(libWorker, event) {
// Handle our messages from the main thread
const eventData = getEventData(event);
switch (eventData.message.type) {
case WORKER_MESSAGE_TYPE.SET_JOYPAD_STATE:
{
// Config will come in as an array, pass in values using apply
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
const setJoypadStateParamsAsArray = eventData.message.setJoypadStateParamsAsArray;
libWorker.wasmInstance.exports.setJoypadState.apply(libWorker, setJoypadStateParamsAsArray);
return;
}
}
}
// Function to get the boot ROM
function getBootRom(libWorker) {
if (!libWorker.wasmByteMemory) {
return new Uint8Array();
} // Header is at 0x0134 - 0x014F
// http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
const bootRomLocation = libWorker.wasmInstance.exports.BOOT_ROM_LOCATION.valueOf();
const bootRomSize = libWorker.wasmInstance.exports.BOOT_ROM_SIZE.valueOf();
const bootRom = libWorker.wasmByteMemory.slice(bootRomLocation, bootRomLocation + bootRomSize);
return bootRom;
}
// Private function to get the caretridge rom
function getCartridgeRom(libWorker) {
if (!libWorker.wasmByteMemory) {
return new Uint8Array();
} // Depening on the rom type, we will have different rom sizes.
// Due memory restrictions described in:
// https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/offline-for-pwa
// We will make sure to only store as much as we need per ROM :)
// Similar to `initializeCartridgeType()` in `wasm/memory/memory.ts`
// We will determine our cartridge type
// Get our game MBC type from the cartridge header
// http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
let cartridgeType = libWorker.wasmByteMemory[libWorker.WASMBOY_GAME_BYTES_LOCATION + 0x0147];
let romSize = undefined;
if (cartridgeType === 0x00) {
// ROM only, 32KB
romSize = 0x8000;
} else if (cartridgeType >= 0x01 && cartridgeType <= 0x03) {
// MBC1 2MB of ROM
romSize = 0x200000;
} else if (cartridgeType >= 0x05 && cartridgeType <= 0x06) {
// MBC2 256KB ROM
romSize = 0x40000;
} else if (cartridgeType >= 0x0f && cartridgeType <= 0x13) {
// MBC3 2MB of ROM
romSize = 0x200000;
} else if (cartridgeType >= 0x19 && cartridgeType <= 0x1e) {
// MBC5 8MB of ROM
romSize = 0x800000;
}
if (!romSize) {
return new Uint8Array();
} // Finally fill our cartridgeRam from the ram in memory
const cartridgeRom = libWorker.wasmByteMemory.slice(libWorker.WASMBOY_GAME_BYTES_LOCATION, libWorker.WASMBOY_GAME_BYTES_LOCATION + romSize);
return cartridgeRom;
}
// Private function to get the cartridge ram
function getCartridgeRam(libWorker) {
if (!libWorker.wasmByteMemory) {
return new Uint8Array();
} // Depening on the rom type, we will have different ram sizes.
// Due memory restrictions described in:
// https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/offline-for-pwa
// We will make sure to only store as much as we need per ROM :)
// Similar to `initializeCartridgeType()` in `wasm/memory/memory.ts`
// We will determine our cartridge type
// Get our game MBC type from the cartridge header
// http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
let cartridgeType = libWorker.wasmByteMemory[libWorker.WASMBOY_GAME_BYTES_LOCATION + 0x0147];
let ramSize = undefined;
if (cartridgeType === 0x00) {
// No memory for this rom type
return new Uint8Array();
} else if (cartridgeType >= 0x01 && cartridgeType <= 0x03) {
// MBC1 32KB of Ram
ramSize = 0x8000;
} else if (cartridgeType >= 0x05 && cartridgeType <= 0x06) {
// MBC2 512X4 Bytes, 2KB
ramSize = 0x800;
} else if (cartridgeType >= 0x0f && cartridgeType <= 0x13) {
// MBC3 32KB of Ram
ramSize = 0x8000;
} else if (cartridgeType >= 0x19 && cartridgeType <= 0x1e) {
// MBC5 128KB of Ram
ramSize = 0x20000;
}
if (!ramSize) {
return new Uint8Array();
} // Finally fill our cartridgeRam from the ram in memory
const cartridgeRam = libWorker.wasmByteMemory.slice(libWorker.WASMBOY_GAME_RAM_BANKS_LOCATION, libWorker.WASMBOY_GAME_RAM_BANKS_LOCATION + ramSize);
return cartridgeRam;
}
// Function to get the cartridge header
function getCartridgeHeader(libWorker) {
if (!libWorker.wasmByteMemory) {
return new Uint8Array();
} // Header is at 0x0134 - 0x014F
// http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
const headerLength = 0x014f - 0x0134;
const headerLocation = libWorker.WASMBOY_GAME_BYTES_LOCATION + 0x0134;
const headerArray = libWorker.wasmByteMemory.slice(headerLocation, headerLocation + headerLength);
return headerArray;
}
// Returns the standard 0xFFFF gameboy memory
// You will normally see in gameboy docs.
// This is returned from the core, and represents
// This wasmboy gameboy state
function getGameBoyMemory(libWorker) {
return libWorker.wasmByteMemory.slice(libWorker.WASMBOY_INTERNAL_MEMORY_LOCATION, libWorker.WASMBOY_INTERNAL_MEMORY_LOCATION + libWorker.WASMBOY_INTERNAL_MEMORY_SIZE);
}
// Function to get the current palette data for
// GBC in memory. This is needed to load state with
// The correct colors
function getPaletteMemory(libWorker) {
return libWorker.wasmByteMemory.slice(libWorker.WASMBOY_PALETTE_MEMORY_LOCATION, libWorker.WASMBOY_PALETTE_MEMORY_LOCATION + libWorker.WASMBOY_PALETTE_MEMORY_SIZE);
}
// Returns the internal savestate of the wasmboy core,
// To save all soft values held in memory
function getInternalState(libWorker) {
libWorker.wasmInstance.exports.saveState();
return libWorker.wasmByteMemory.slice(libWorker.WASMBOY_INTERNAL_STATE_LOCATION, libWorker.WASMBOY_INTERNAL_STATE_LOCATION + libWorker.WASMBOY_INTERNAL_STATE_SIZE);
}
// posts to lib Worker
function memoryWorkerOnMessage(libWorker, event) {
// Handle our messages from the main thread
const eventData = getEventData(event);
switch (eventData.message.type) {
case WORKER_MESSAGE_TYPE.CLEAR_MEMORY:
{
// Clear Wasm memory
// https://docs.google.com/spreadsheets/d/17xrEzJk5-sCB9J2mMJcVnzhbE-XH_NvczVSQH9OHvRk/edit?usp=sharing
for (let i = 0; i <= libWorker.wasmByteMemory.length; i++) {
libWorker.wasmByteMemory[i] = 0;
}
const wasmByteMemory = libWorker.wasmByteMemory.slice(0);
libWorker.memoryWorkerPort.postMessage(getSmartWorkerMessage({
type: WORKER_MESSAGE_TYPE.CLEAR_MEMORY_DONE,
wasmByteMemory: wasmByteMemory.buffer
}, eventData.messageId), [wasmByteMemory.buffer]);
return;
}
case WORKER_MESSAGE_TYPE.GET_CONSTANTS:
{
libWorker.WASMBOY_BOOT_ROM_LOCATION = libWorker.wasmInstance.exports.BOOT_ROM_LOCATION.valueOf();
libWorker.WASMBOY_GAME_BYTES_LOCATION = libWorker.wasmInstance.exports.CARTRIDGE_ROM_LOCATION.valueOf();
libWorker.WASMBOY_GAME_RAM_BANKS_LOCATION = libWorker.wasmInstance.exports.CARTRIDGE_RAM_LOCATION.valueOf(), libWorker.WASMBOY_INTERNAL_STATE_SIZE = libWorker.wasmInstance.exports.WASMBOY_STATE_SIZE.valueOf(), libWorker.WASMBOY_INTERNAL_STATE_LOCATION = libWorker.wasmInstance.exports.WASMBOY_STATE_LOCATION.valueOf(), libWorker.WASMBOY_INTERNAL_MEMORY_SIZE = libWorker.wasmInstance.exports.GAMEBOY_INTERNAL_MEMORY_SIZE.valueOf(), libWorker.WASMBOY_INTERNAL_MEMORY_LOCATION = libWorker.wasmInstance.exports.GAMEBOY_INTERNAL_MEMORY_LOCATION.valueOf(), libWorker.WASMBOY_PALETTE_MEMORY_SIZE = libWorker.wasmInstance.exports.GBC_PALETTE_SIZE.valueOf(), libWorker.WASMBOY_PALETTE_MEMORY_LOCATION = libWorker.wasmInstance.exports.GBC_PALETTE_LOCATION.valueOf(); // Forward to our lib worker
libWorker.memoryWorkerPort.postMessage(getSmartWorkerMessage({
type: WORKER_MESSAGE_TYPE.GET_CONSTANTS_DONE,
WASMBOY_BOOT_ROM_LOCATION: libWorker.wasmInstance.exports.BOOT_ROM_LOCATION.valueOf(),
WASMBOY_GAME_BYTES_LOCATION: libWorker.wasmInstance.exports.CARTRIDGE_ROM_LOCATION.valueOf(),
WASMBOY_GAME_RAM_BANKS_LOCATION: libWorker.wasmInstance.exports.CARTRIDGE_RAM_LOCATION.valueOf(),
WASMBOY_INTERNAL_STATE_SIZE: libWorker.wasmInstance.exports.WASMBOY_STATE_SIZE.valueOf(),
WASMBOY_INTERNAL_STATE_LOCATION: libWorker.wasmInstance.exports.WASMBOY_STATE_LOCATION.valueOf(),
WASMBOY_INTERNAL_MEMORY_SIZE: libWorker.wasmInstance.exports.GAMEBOY_INTERNAL_MEMORY_SIZE.valueOf(),
WASMBOY_INTERNAL_MEMORY_LOCATION: libWorker.wasmInstance.exports.GAMEBOY_INTERNAL_MEMORY_LOCATION.valueOf(),
WASMBOY_PALETTE_MEMORY_SIZE: libWorker.wasmInstance.exports.GBC_PALETTE_SIZE.valueOf(),
WASMBOY_PALETTE_MEMORY_LOCATION: libWorker.wasmInstance.exports.GBC_PALETTE_LOCATION.valueOf()
}, eventData.messageId));
return;
}
case WORKER_MESSAGE_TYPE.SET_MEMORY:
{
const memoryKeys = Object.keys(eventData.message);
if (memoryKeys.includes(MEMORY_TYPE.BOOT_ROM)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.BOOT_ROM]), libWorker.WASMBOY_BOOT_ROM_LOCATION);
}
if (memoryKeys.includes(MEMORY_TYPE.CARTRIDGE_ROM)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.CARTRIDGE_ROM]), libWorker.WASMBOY_GAME_BYTES_LOCATION);
}
if (memoryKeys.includes(MEMORY_TYPE.CARTRIDGE_RAM)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.CARTRIDGE_RAM]), libWorker.WASMBOY_GAME_RAM_BANKS_LOCATION);
}
if (memoryKeys.includes(MEMORY_TYPE.GAMEBOY_MEMORY)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.GAMEBOY_MEMORY]), libWorker.WASMBOY_INTERNAL_MEMORY_LOCATION);
}
if (memoryKeys.includes(MEMORY_TYPE.PALETTE_MEMORY)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.PALETTE_MEMORY]), libWorker.WASMBOY_PALETTE_MEMORY_LOCATION);
}
if (memoryKeys.includes(MEMORY_TYPE.INTERNAL_STATE)) {
libWorker.wasmByteMemory.set(new Uint8Array(eventData.message[MEMORY_TYPE.INTERNAL_STATE]), libWorker.WASMBOY_INTERNAL_STATE_LOCATION);
libWorker.wasmInstance.exports.loadState();
}
libWorker.memoryWorkerPort.postMessage(getSmartWorkerMessage({
type: WORKER_MESSAGE_TYPE.SET_MEMORY_DONE
}, eventData.messageId));
return;
}
case WORKER_MESSAGE_TYPE.GET_MEMORY:
{
// Construct our data object
const responseMemory = {
type: WORKER_MESSAGE_TYPE.GET_MEMORY
};
const responseTransferrables = [];
const memoryTypes = eventData.message.memoryTypes;
if (memoryTypes.includes(MEMORY_TYPE.BOOT_ROM)) {
const bootRom = getBootRom(libWorker).buffer;
responseMemory[MEMORY_TYPE.BOOT_ROM] = bootRom;
responseTransferrables.push(bootRom);
}
if (memoryTypes.includes(MEMORY_TYPE.CARTRIDGE_ROM)) {
const cartridgeRom = getCartridgeRom(libWorker).buffer;
responseMemory[MEMORY_TYPE.CARTRIDGE_ROM] = cartridgeRom;
responseTransferrables.push(cartridgeRom);
}
if (memoryTypes.includes(MEMORY_TYPE.CARTRIDGE_RAM)) {
const cartridgeRam = getCartridgeRam(libWorker).buffer;
responseMemory[MEMORY_TYPE.CARTRIDGE_RAM] = cartridgeRam;
responseTransferrables.push(cartridgeRam);
}
if (memoryTypes.includes(MEMORY_TYPE.CARTRIDGE_HEADER)) {
const cartridgeHeader = getCartridgeHeader(libWorker).buffer;
responseMemory[MEMORY_TYPE.CARTRIDGE_HEADER] = cartridgeHeader;
responseTransferrables.push(cartridgeHeader);
}
if (memoryTypes.includes(MEMORY_TYPE.GAMEBOY_MEMORY)) {
const gameboyMemory = getGameBoyMemory(libWorker).buffer;
responseMemory[MEMORY_TYPE.GAMEBOY_MEMORY] = gameboyMemory;
responseTransferrables.push(gameboyMemory);
}
if (memoryTypes.includes(MEMORY_TYPE.PALETTE_MEMORY)) {
const paletteMemory = getPaletteMemory(libWorker).buffer;
responseMemory[MEMORY_TYPE.PALETTE_MEMORY] = paletteMemory;
responseTransferrables.push(paletteMemory);
}
if (memoryTypes.includes(MEMORY_TYPE.INTERNAL_STATE)) {
libWorker.wasmInstance.exports.saveState();
const internalState = getInternalState(libWorker).buffer;
responseMemory[MEMORY_TYPE.INTERNAL_STATE] = internalState;
responseTransferrables.push(internalState);
}
libWorker.memoryWorkerPort.postMessage(getSmartWorkerMessage(responseMemory, eventData.messageId), responseTransferrables);
return;
}
}
}
// Banner placed by rollup to mock out some items on our esm build
// This is useful for things like wasmmemory
const wasmboyMemorySize = 0x8b0000; // Simply initialized to the size we need
const wasmByteMemory = new Uint8ClampedArray(wasmboyMemorySize); // Memory mock
const memory = {
size: () => {
return wasmboyMemorySize;
},
grow: () => {},
wasmByteMemory: wasmByteMemory
};
const load = offset => {
return wasmByteMemory[offset];
};
const store = (offset, value) => {
wasmByteMemory[offset] = value;
};
const abs = value => {
return Math.abs(value);
};
const ceil = value => {
return Math.ceil(value);
}; // Constants that will be shared by the wasm core of the emulator
// And libraries built around the wasm (such as the official JS), or @CryZe wasmboy-rs
// ----------------------------------
// Wasmboy Memory Map
// https://docs.google.com/spreadsheets/d/17xrEzJk5-sCB9J2mMJcVnzhbE-XH_NvczVSQH9OHvRk/edit?usp=sharing
// ----------------------------------
// AssemblyScript
var ASSEMBLYSCRIPT_MEMORY_LOCATION = 0x000000;
var ASSEMBLYSCRIPT_MEMORY_SIZE = 0x000400; // WasmBoy States
var WASMBOY_STATE_LOCATION = ASSEMBLYSCRIPT_MEMORY_LOCATION + ASSEMBLYSCRIPT_MEMORY_SIZE;
var WASMBOY_STATE_SIZE = 0x000400; // Gameboy Internal Memory
var VIDEO_RAM_LOCATION = WASMBOY_STATE_LOCATION + WASMBOY_STATE_SIZE;
var VIDEO_RAM_SIZE = 0x004000;
var WORK_RAM_LOCATION = VIDEO_RAM_LOCATION + VIDEO_RAM_SIZE;
var WORK_RAM_SIZE = 0x008000;
var OTHER_GAMEBOY_INTERNAL_MEMORY_LOCATION = WORK_RAM_LOCATION + WORK_RAM_SIZE;
var OTHER_GAMEBOY_INTERNAL_MEMORY_SIZE = 0x004000; // General Gameboy Internal Memory
var GAMEBOY_INTERNAL_MEMORY_LOCATION = VIDEO_RAM_LOCATION;
var GAMEBOY_INTERNAL_MEMORY_SIZE = OTHER_GAMEBOY_INTERNAL_MEMORY_LOCATION - VIDEO_RAM_LOCATION + OTHER_GAMEBOY_INTERNAL_MEMORY_SIZE; // Graphics Output
var GBC_PALETTE_LOCATION = OTHER_GAMEBOY_INTERNAL_MEMORY_LOCATION + OTHER_GAMEBOY_INTERNAL_MEMORY_SIZE;
var GBC_PALETTE_SIZE = 0x000080;
var BG_PRIORITY_MAP_LOCATION = GBC_PALETTE_LOCATION + GBC_PALETTE_SIZE;
var BG_PRIORITY_MAP_SIZE = 0x005c00;
var FRAME_LOCATION = BG_PRIORITY_MAP_LOCATION + BG_PRIORITY_MAP_SIZE;
var FRAME_SIZE = 0x016c00;
var BACKGROUND_MAP_LOCATION = FRAME_LOCATION + FRAME_SIZE;
var BACKGROUND_MAP_SIZE = 0x030000;
var TILE_DATA_LOCATION = BACKGROUND_MAP_LOCATION + BACKGROUND_MAP_SIZE;
var TILE_DATA_SIZE = 0x024000;
var OAM_TILES_LOCATION = TILE_DATA_LOCATION + TILE_DATA_SIZE;
var OAM_TILES_SIZE = 0x003c00; // General Graphics Output
var GRAPHICS_OUTPUT_LOCATION = GBC_PALETTE_LOCATION;
var GRAPHICS_OUTPUT_SIZE = OAM_TILES_LOCATION - GBC_PALETTE_LOCATION + OAM_TILES_SIZE; // Audio Output
var CHANNEL_1_BUFFER_LOCATION = OAM_TILES_LOCATION + OAM_TILES_SIZE;
var CHANNEL_1_BUFFER_SIZE = 0x020000;
var CHANNEL_2_BUFFER_LOCATION = CHANNEL_1_BUFFER_LOCATION + CHANNEL_1_BUFFER_SIZE;
var CHANNEL_2_BUFFER_SIZE = 0x020000;
var CHANNEL_3_BUFFER_LOCATION = CHANNEL_2_BUFFER_LOCATION + CHANNEL_2_BUFFER_SIZE;
var CHANNEL_3_BUFFER_SIZE = 0x020000;
var CHANNEL_4_BUFFER_LOCATION = CHANNEL_3_BUFFER_LOCATION + CHANNEL_3_BUFFER_SIZE;
var CHANNEL_4_BUFFER_SIZE = 0x020000;
var AUDIO_BUFFER_LOCATION = CHANNEL_4_BUFFER_LOCATION + CHANNEL_4_BUFFER_SIZE;
var AUDIO_BUFFER_SIZE = 0x020000; // Catridge Ram
var CARTRIDGE_RAM_LOCATION = AUDIO_BUFFER_LOCATION + AUDIO_BUFFER_SIZE;
var CARTRIDGE_RAM_SIZE = 0x020000; // Boot ROM
// http://gbdev.gg8.se/files/roms/bootroms/
// Largest Boot rom is GBC, at 2.5KB
var BOOT_ROM_LOCATION = CARTRIDGE_RAM_LOCATION + CARTRIDGE_RAM_SIZE;
var BOOT_ROM_SIZE = 0x000a00; // Cartridge ROM
var CARTRIDGE_ROM_LOCATION = BOOT_ROM_LOCATION + BOOT_ROM_SIZE;
var CARTRIDGE_ROM_SIZE = 0x7e0400; // Debug Memory
var DEBUG_GAMEBOY_MEMORY_LOCATION = CARTRIDGE_ROM_LOCATION + CARTRIDGE_ROM_SIZE;
var DEBUG_GAMEBOY_MEMORY_SIZE = 0xffff; // Final General Size
var WASMBOY_MEMORY_LOCATION = 0x000000;
var WASMBOY_MEMORY_SIZE = DEBUG_GAMEBOY_MEMORY_LOCATION + DEBUG_GAMEBOY_MEMORY_SIZE + 1;
var WASMBOY_WASM_PAGES = ceil(WASMBOY_MEMORY_SIZE / 1024 / 64) + 1;
var Config =
/** @class */
function () {
function Config() {} // Boot Rom
Config.enableBootRom = false; // GBC Options
Config.useGbcWhenAvailable = true; // Batch Processing
Config.audioBatchProcessing = false;
Config.graphicsBatchProcessing = false;
Config.timersBatchProcessing = false; // Scanline Rendering
Config.graphicsDisableScanlineRendering = false; // Acumulate Sound Samples
Config.audioAccumulateSamples = false; // Tile Rednering
Config.tileRendering = false;
Config.tileCaching = false; // Audio Debugging
Config.enableAudioDebugging = false;
return Config;
}(); // Portable Code for JS Wasm Benchmarking
// https://github.com/AssemblyScript/assemblyscript/wiki/Writing-portable-code
// https://github.com/AssemblyScript/assemblyscript/blob/master/std/portable/index.js
function u8Portable(param) {
return param & 0xff;
}
function u16Portable(param) {
return param & 0xffff;
}
function i8Portable(param) {
return param << 24 >> 24;
}
function i32Portable(param) {
return param | 0;
} // Set flag bit on on register F. For instance set zero flag to zero -> (7, 0)
function setFlagBit(flagBit, flagValue) {
var bitwiseOperand = u8Portable(1 << flagBit);
if (flagValue > 0) {
Cpu.registerF = Cpu.registerF | bitwiseOperand;
} else {
// XOR out the two ones
bitwiseOperand = 0xff ^ bitwiseOperand;
Cpu.registerF = Cpu.registerF & bitwiseOperand;
}
return Cpu.registerF;
} // Overload the set flag bit for ease of use
function setZeroFlag$$1(value) {
setFlagBit(7, value);
}
function setSubtractFlag(value) {
setFlagBit(6, value);
}
function setHalfCarryFlag(value) {
setFlagBit(5, value);
}
function setCarryFlag(value) {
setFlagBit(4, value);
} // Getters for flags
function getZeroFlag$$1() {
return Cpu.registerF >> 7 & 0x01;
}
function getSubtractFlag() {
return Cpu.registerF >> 6 & 0x01;
}
function getHalfCarryFlag() {
return Cpu.registerF >> 5 & 0x01;
}
function getCarryFlag$$1() {
return Cpu.registerF >> 4 & 0x01;
} // Must be run before the register actually performs the add
// amountToAdd i16, since max number can be an u8
function checkAndSetEightBitHalfCarryFlag(value, amountToAdd) {
if (amountToAdd >= 0) {
// https://robdor.com/2016/08/10/gameboy-emulator-half-carry-flag/
var result = u8Portable((value & 0x0f) + (amountToAdd & 0x0f)) & 0x10;
setHalfCarryFlag(result !== 0x00);
} else {
// From: https://github.com/djhworld/gomeboycolor/blob/master/src/cpu/index.go
// CTRL+F "subBytes(a, b byte)"
setHalfCarryFlag((abs(amountToAdd) & 0x0f) > (value & 0x0f));
}
}
function checkAndSetEightBitCarryFlag(value, amountToAdd) {
if (amountToAdd >= 0) {
var result = u8Portable(value + amountToAdd);
setCarryFlag(value > result);
} else {
setCarryFlag(abs(amountToAdd) > value);
}
} // Function to handle 16 bit addition overflow, and set the carry flags accordingly
// i32 on valueTwo to support passing signed immedaite values
function checkAndSetSixteenBitFlagsAddOverflow(valueOne, valueTwo, useStackPointerBits) {
// need to differentiate between HL and SP
// HL carries are at 11 and 15, SP carries are at 3 and 7 :p
if (useStackPointerBits) {
// Logic from : https://github.com/nakardo/node-gameboy/blob/master/lib/cpu/opcodes.js
// CTRL+F add_sp_n
// using the stack pointer bits means we can safely assume the value is signed
var signedValueOne = valueOne;
var result = signedValueOne + valueTwo;
var flagXor = signedValueOne ^ valueTwo ^ result;
setHalfCarryFlag((flagXor & 0x10) !== 0);
setCarryFlag((flagXor & 0x100) !== 0);
} else {
// Logic from: https://github.com/djhworld/gomeboycolor/blob/master/src/cpu/index.go
// CTRL+F addWords
// Value two is not signed
var result = u16Portable(valueOne + valueTwo); // Check the carry flag by allowing the overflow
setCarryFlag(result < valueOne); // To check for half carry flag (bit 15), by XOR'ing valyes, and and'ing the bit in question
var halfCarryXor = valueOne ^ valueTwo ^ result;
var halfCarryAnd = u16Portable(halfCarryXor & 0x1000);
setHalfCarryFlag(halfCarryAnd !== 0x00);
}
} // File for all of the colors for different GB Palletes
// https://i.imgur.com/HupBY.png
// https://www.libretro.com/index.php/gambatte-progress-report/
// https://tcrf.net/Notes:Game_Boy_Color_Bootstrap_ROM
// Our default wasmboy gb colors
var WasmBoyGBColors =
/** @class */
function () {
function WasmBoyGBColors() {} //Bg
WasmBoyGBColors.bgWhite = 0xf2f2f2;
WasmBoyGBColors.bgLightGrey = 0xa0a0a0;
WasmBoyGBColors.bgDarkGrey = 0x585858;
WasmBoyGBColors.bgBlack = 0x080808; // Obj 0
WasmBoyGBColors.obj0White = 0xf2f2f2;
WasmBoyGBColors.obj0LightGrey = 0xa0a0a0;
WasmBoyGBColors.obj0DarkGrey = 0x585858;
WasmBoyGBColors.obj0Black = 0x080808; // Obj1
WasmBoyGBColors.obj1White = 0xf2f2f2;
WasmBoyGBColors.obj1LightGrey = 0xa0a0a0;
WasmBoyGBColors.obj1DarkGrey = 0x585858;
WasmBoyGBColors.obj1Black = 0x080808;
return WasmBoyGBColors;
}(); // Action Button: Right
var GreenColors =
/** @class */
function () {
function GreenColors() {} //Bg
GreenColors.bgWhite = 0xffffff;
GreenColors.bgLightGrey = 0x52ff00;
GreenColors.bgDarkGrey = 0xff4200;
GreenColors.bgBlack = 0x000000; // Obj 0
GreenColors.obj0White = 0xffffff;
GreenColors.obj0LightGrey = 0x52ff00;
GreenColors.obj0DarkGrey = 0xff4200;
GreenColors.obj0Black = 0x000000; // Obj1
GreenColors.obj1White = 0xffffff;
GreenColors.obj1LightGrey = 0x52ff00;
GreenColors.obj1DarkGrey = 0xff4200;
GreenColors.obj1Black = 0x000000;
return GreenColors;
}(); // Action Button: A + Down
var OrangeColors =
/** @class */
function () {
function OrangeColors() {} //Bg
OrangeColors.bgWhite = 0xffffff;
OrangeColors.bgLightGrey = 0xffff00;
OrangeColors.bgDarkGrey = 0xff0000;
OrangeColors.bgBlack = 0x000000; // Obj 0
OrangeColors.obj0White = 0xffffff;
OrangeColors.obj0LightGrey = 0xffff00;
OrangeColors.obj0DarkGrey = 0xff0000;
OrangeColors.obj0Black = 0x000000; // Obj1
OrangeColors.obj1White = 0xffffff;
OrangeColors.obj1LightGrey = 0xffff00;
OrangeColors.obj1DarkGrey = 0xff0000;
OrangeColors.obj1Black = 0x000000;
return OrangeColors;
}(); // Action Button: Up
var BrownColors =
/** @class */
function () {
function BrownColors() {} //Bg
BrownColors.bgWhite = 0xffffff;
BrownColors.bgLightGrey = 0xffad63;
BrownColors.bgDarkGrey = 0x843100;
BrownColors.bgBlack = 0x000000; // Obj 0
BrownColors.obj0White = 0xffffff;
BrownColors.obj0LightGrey = 0xffad63;
BrownColors.obj0DarkGrey = 0x843100;
BrownColors.obj0Black = 0x000000; // Obj1
BrownColors.obj1White = 0xffffff;
BrownColors.obj1LightGrey = 0xffad63;
BrownColors.obj1DarkGrey = 0x843100;
BrownColors.obj1Black = 0x000000;
return BrownColors;
}(); // Action Button: B + Right
var InvertedColors =
/** @class */
function () {
function InvertedColors() {} //Bg
InvertedColors.bgWhite = 0x000000;
InvertedColors.bgLightGrey = 0x008484;
InvertedColors.bgDarkGrey = 0xffde00;
InvertedColors.bgBlack = 0xffffff; // Obj 0
InvertedColors.obj0White = 0x000000;
InvertedColors.obj0LightGrey = 0x008484;
InvertedColors.obj0DarkGrey = 0xffde00;
InvertedColors.obj0Black = 0xffffff; // Obj1
InvertedColors.obj1White = 0x000000;
InvertedColors.obj1LightGrey = 0x008484;
InvertedColors.obj1DarkGrey = 0xffde00;
InvertedColors.obj1Black = 0xffffff;
return InvertedColors;
}(); // Action Button: B + Left
var GrayscaleColors =
/** @class */
function () {
function GrayscaleColors() {} //Bg
GrayscaleColors.bgWhite = 0xffffff;
GrayscaleColors.bgLightGrey = 0xa5a5a5;
GrayscaleColors.bgDarkGrey = 0x525252;
GrayscaleColors.bgBlack = 0x000000; // Obj 0
GrayscaleColors.obj0White = 0xffffff;
GrayscaleColors.obj0LightGrey = 0xa5a5a5;
GrayscaleColors.obj0DarkGrey = 0x525252;
GrayscaleColors.obj0Black = 0x000000; // Obj1
GrayscaleColors.obj1White = 0xffffff;
GrayscaleColors.obj1LightGrey = 0xa5a5a5;
GrayscaleColors.obj1DarkGrey = 0x525252;
GrayscaleColors.obj1Black = 0x000000;
return GrayscaleColors;
}(); // Action Button: Down
var PastelMixColors =
/** @class */
function () {
function PastelMixColors() {} //Bg
PastelMixColors.bgWhite = 0xffffa5;
PastelMixColors.bgLightGrey = 0xff9494;
PastelMixColors.bgDarkGrey = 0x9494ff;
PastelMixColors.bgBlack = 0x000000; // Obj 0
PastelMixColors.obj0White = 0xffffa5;
PastelMixColors.obj0LightGrey = 0xff9494;
PastelMixColors.obj0DarkGrey = 0x9494ff;
PastelMixColors.obj0Black = 0x000000; // Obj1
PastelMixColors.obj1White = 0xffffa5;
PastelMixColors.obj1LightGrey = 0xff9494;
PastelMixColors.obj1DarkGrey = 0x9494ff;
PastelMixColors.obj1Black = 0x000000;
return PastelMixColors;
}(); // Action Button: B + Up
var DarkBrownColors =
/** @class */
function () {
function DarkBrownColors() {} //Bg
DarkBrownColors.bgWhite = 0xffe6c5;
DarkBrownColors.bgLightGrey = 0xce9c84;
DarkBrownColors.bgDarkGrey = 0x846b29;
DarkBrownColors.bgBlack = 0x5a3108; // Obj 0
DarkBrownColors.obj0White = 0xffffff;
DarkBrownColors.obj0LightGrey = 0xffad63;
DarkBrownColors.obj0DarkGrey = 0x843100;
DarkBrownColors.obj0Black = 0x000000; // Obj1
DarkBrownColors.obj1White = 0xffffff;
DarkBrownColors.obj1LightGrey = 0xffad63;
DarkBrownColors.obj1DarkGrey = 0x843100;
DarkBrownColors.obj1Black = 0x000000;
return DarkBrownColors;
}(); // Action Button: A + Right
var DarkGreenColors =
/** @class */
function () {
function DarkGreenColors() {} //Bg
DarkGreenColors.bgWhite = 0xffffff;
DarkGreenColors.bgLightGrey = 0x7bff31;
DarkGreenColors.bgDarkGrey = 0x0063c5;
DarkGreenColors.bgBlack = 0x000000; // Obj 0
DarkGreenColors.obj0White = 0xffffff;
DarkGreenColors.obj0LightGrey = 0xff8484;
DarkGreenColors.obj0DarkGrey = 0x943a3a;
DarkGreenColors.obj0Black = 0x000000; // Obj1
DarkGreenColors.obj1White = 0xffffff;
DarkGreenColors.obj1LightGrey = 0xff8484;
DarkGreenColors.obj1DarkGrey = 0x943a3a;
DarkGreenColors.obj1Black = 0x000000;
return DarkGreenColors;
}(); // Action Button: A + Left
var DarkBlueColors =
/** @class */
function () {
function DarkBlueColors() {} //Bg
DarkBlueColors.bgWhite = 0xffffff;
DarkBlueColors.bgLightGrey = 0x8c8cde;
DarkBlueColors.bgDarkGrey = 0x52528c;
DarkBlueColors.bgBlack = 0x000000; // Obj 0
DarkBlueColors.obj0White = 0xffffff;
DarkBlueColors.obj0LightGrey = 0xff8484;
DarkBlueColors.obj0DarkGrey = 0x943a3a;
DarkBlueColors.obj0Black = 0x000000; // Obj1
DarkBlueColors.obj1White = 0xffffff;
DarkBlueColors.obj1LightGrey = 0xffad63;
DarkBlueColors.obj1DarkGrey = 0x843100;
DarkBlueColors.obj1Black = 0x000000;
return DarkBlueColors;
}(); // Action Button: A + Up
var RedColors =
/** @class */
function () {
function RedColors() {} //Bg
RedColors.bgWhite = 0xffffff;
RedColors.bgLightGrey = 0xff8484;
RedColors.bgDarkGrey = 0x943a3a;
RedColors.bgBlack = 0x000000; // Obj 0
RedColors.obj0White = 0xffffff;
RedColors.obj0LightGrey = 0x7bff31;
RedColors.obj0DarkGrey = 0x008400;
RedColors.obj0Black = 0x000000; // Obj1
RedColors.obj1White = 0xffffff;
RedColors.obj1LightGrey = 0x63a5ff;
RedColors.obj1DarkGrey = 0x0000ff;
RedColors.obj1Black = 0x000000;
return RedColors;
}(); // Action Button: Left
var BlueColors =
/** @class */
function () {
function BlueColors() {} //Bg
BlueColors.bgWhite = 0xffffff;
BlueColors.bgLightGrey = 0x63a5ff;
BlueColors.bgDarkGrey = 0x0000ff;
BlueColors.bgBlack = 0x000000; // Obj 0
BlueColors.obj0White = 0xffffff;
BlueColors.obj0LightGrey = 0xff8484;
BlueColors.obj0DarkGrey = 0x943a3a;
BlueColors.obj0Black = 0x000000; // Obj1
BlueColors.obj1White = 0xffffff;
BlueColors.obj1LightGrey = 0x7bff31;
BlueColors.obj1DarkGrey = 0x008400;
BlueColors.obj1Black = 0x000000;
return BlueColors;
}(); // Action Button: B + Down
var YellowColors =
/** @class */
function () {
function YellowColors() {} //Bg
YellowColors.bgWhite = 0xffffff;
YellowColors.bgLightGrey = 0xffff00;
YellowColors.bgDarkGrey = 0x7b4a00;
YellowColors.bgBlack = 0x000000; // Obj 0
YellowColors.obj0White = 0xffffff;
YellowColors.obj0LightGrey = 0x63a5ff;
YellowColors.obj0DarkGrey = 0x0000ff;
YellowColors.obj0Black = 0x000000; // Obj1
YellowColors.obj1White = 0xffffff;
YellowColors.obj1LightGrey = 0x7bff31;
YellowColors.obj1DarkGrey = 0x008400;
YellowColors.obj1Black = 0x000000;
return YellowColors;
}(); // Assigned Color Palettes
// Alleyway
var Table00Entry08Colors =
/** @class */
function () {
function Table00Entry08Colors() {} //Bg
Table00Entry08Colors.bgWhite = 0xa59cff;
Table00Entry08Colors.bgLightGrey = 0xffff00;
Table00Entry08Colors.bgDarkGrey = 0x006300;
Table00Entry08Colors.bgBlack = 0x000000; // Obj 0
Table00Entry08Colors.obj0White = 0xa59cff;
Table00Entry08Colors.obj0LightGrey = 0xffff00;
Table00Entry08Colors.obj0DarkGrey = 0x006300;
Table00Entry08Colors.obj0Black = 0x000000; // Obj1
Table00Entry08Colors.obj1White = 0xa59cff;
Table00Entry08Colors.obj1LightGrey = 0xffff00;
Table00Entry08Colors.obj1DarkGrey = 0x006300;
Table00Entry08Colors.obj1Black = 0x000000;
return Table00Entry08Colors;
}(); // Pokemon Blue
var Table01Entry0BColors =
/** @class */
function () {
function Table01Entry0BColors() {} //Bg
Table01Entry0BColors.bgWhite = 0xffffff;
Table01Entry0BColors.bgLightGrey = 0x63a5ff;
Table01Entry0BColors.bgDarkGrey = 0x0000ff;
Table01Entry0BColors.bgBlack = 0x000000; // Obj 0
Table01Entry0BColors.obj0White = 0xffffff;
Table01Entry0BColors.obj0LightGrey = 0xff8484;
Table01Entry0BColors.obj0DarkGrey = 0x943a3a;
Table01Entry0BColors.obj0Black = 0x000000; // Obj1
Table01Entry0BColors.obj1White = 0xffffff;
Table01Entry0BColors.obj1LightGrey = 0x63a5ff;
Table01Entry0BColors.obj1DarkGrey = 0x0000ff;
Table01Entry0BColors.obj1Black = 0x000000;
return Table01Entry0BColors;
}(); // Pokemon Red
var Table01Entry10Colors =
/** @class */
function () {
function Table01Entry10Colors() {} //Bg
Table01Entry10Colors.bgWhite = 0xffffff;
Table01Entry10Colors.bgLightGrey = 0xff8484;
Table01Entry10Colors.bgDarkGrey = 0x943a3a;
Table01Entry10Colors.bgBlack = 0x000000; // Obj 0
Table01Entry10Colors.obj0White = 0xffffff;
Table01Entry10Colors.obj0LightGrey = 0x7bff31;
Table01Entry10Colors.obj0DarkGrey = 0x008400;
Table01Entry10Colors.obj0Black = 0x000000; // Obj1
Table01Entry10Colors.obj1White = 0xffffff;
Table01Entry10Colors.obj1LightGrey = 0xff8484;
Table01Entry10Colors.obj1DarkGrey = 0x943a3a;
Table01Entry10Colors.obj1Black = 0x000000;
return Table01Entry10Colors;
}(); // Super Mario Land
var Table03Entry0AColors =
/** @class */
function () {
function Table03Entry0AColors() {} //Bg
Table03Entry0AColors.bgWhite = 0xb5b5ff;
Table03Entry0AColors.bgLightGrey = 0xffff94;
Table03Entry0AColors.bgDarkGrey = 0xad5a42;
Table03Entry0AColors.bgBlack = 0x000000; // Obj 0
Table03Entry0AColors.obj0White = 0x000000;
Table03Entry0AColors.obj0LightGrey = 0xffffff;
Table03Entry0AColors.obj0DarkGrey = 0xff8484;
Table03Entry0AColors.obj0Black = 0x943a3a; // Obj1
Table03Entry0AColors.obj1White = 0x000000;
Table03Entry0AColors.obj1LightGrey = 0xffffff;
Table03Entry0AColors.obj1DarkGrey = 0xff8484;
Table03Entry0AColors.obj1Black = 0x943a3a;
return Table03Entry0AColors;
}(); // Super Mario Land 3 - WarioLand
var Table05Entry00Colors =
/** @class */
function () {
function Table05Entry00Colors() {} //Bg
Table05Entry00Colors.bgWhite = 0xffffff;
Table05Entry00Colors.bgLightGrey = 0xadad84;
Table05Entry00Colors.bgDarkGrey = 0x42737b;
Table05Entry00Colors.bgBlack = 0x000000; // Obj 0
Table05Entry00Colors.obj0White = 0xffffff;
Table05Entry00Colors.obj0LightGrey = 0xff7300;
Table05Entry00Colors.obj0DarkGrey = 0x944200;
Table05Entry00Colors.obj0Black = 0x000000; // Obj1
Table05Entry00Colors.obj1White = 0xffffff;
Table05Entry00Colors.obj1LightGrey = 0x5abdff;
Table05Entry00Colors.obj1DarkGrey = 0xff0000;
Table05Entry00Colors.obj1Black = 0x0000ff;
return Table05Entry00Colors;
}(); // Donkey Kong
var Table05Entry01Colors =
/** @class */
function () {
function Table05Entry01Colors() {} //Bg
Table05Entry01Colors.bgWhite = 0xffff9c;
Table05Entry01Colors.bgLightGrey = 0x94b5ff;
Table05Entry01Colors.bgDarkGrey = 0x639473;
Table05Entry01Colors.bgBlack = 0x003a3a; // Obj 0
Table05Entry01Colors.obj0White = 0xffc542;
Table05Entry01Colors.obj0LightGrey = 0xffd600;
Table05Entry01Colors.obj0DarkGrey = 0x943a00;
Table05Entry01Colors.obj0Black = 0x4a0000; // Obj1
Table05Entry01Colors.obj1White = 0xffffff;
Table05Entry01Colors.obj1LightGrey = 0xff8484;
Table05Entry01Colors.obj1DarkGrey = 0x943a3a;
Table05Entry01Colors.obj1Black = 0x000000;
return Table05Entry01Colors;
}(); // Tennis
var Table05Entry02Colors =
/** @class */
function () {
function Table05Entry02Colors() {} //Bg
Table05Entry02Colors.bgWhite = 0x6bff00;
Table05Entry02Colors.bgLightGrey = 0xffffff;
Table05Entry02Colors.bgDarkGrey = 0xff524a;
Table05Entry02Colors.bgBlack = 0x000000; // Obj 0
Table05Entry02Colors.obj0White = 0xffffff;
Table05Entry02Colors.obj0LightGrey = 0xffffff;
Table05Entry02Colors.obj0DarkGrey = 0x63a5ff;
Table05Entry02Colors.obj0Black = 0x0000ff; // Obj1
Table05Entry02Colors.obj1White = 0xffffff;
Table05Entry02Colors.obj1LightGrey = 0xffad63;
Table05Entry02Colors.obj1DarkGrey = 0x843100;
Table05Entry02Colors.obj1Black = 0x000000;
return Table05Entry02Colors;
}(); // Kirby's Dream Land
var Table05Entry08Colors =
/** @class */
function () {
function Table05Entry08Colors() {} //Bg
Table05Entry08Colors.bgWhite = 0xa59cff;
Table05Entry08Colors.bgLightGrey = 0xffff00;
Table05Entry08Colors.bgDarkGrey = 0x006300;
Table05Entry08Colors.bgBlack = 0x000000; // Obj 0
Table05Entry08Colors.obj0White = 0xff6352;
Table05Entry08Colors.obj0LightGrey = 0xd60000;
Table05Entry08Colors.obj0DarkGrey = 0x630000;
Table05Entry08Colors.obj0Black = 0x000000; // Obj1
Table05Entry08Colors.obj1White = 0x0000ff;
Table05Entry08Colors.obj1LightGrey = 0xffffff;
Table05Entry08Colors.obj1DarkGrey = 0xffff7b;
Table05Entry08Colors.obj1Black = 0x0084ff;
return Table05Entry08Colors;
}(); // Super Mario Land 2 BAYYYBEEE
var Table05Entry09Colors =
/** @class */
function () {
function Table05Entry09Colors() {} //Bg
Table05Entry09Colors.bgWhite = 0xffffce;
Table05Entry09Colors.bgLightGrey = 0x63efef;
Table05Entry09Colors.bgDarkGrey = 0x9c8431;
Table05Entry09Colors.bgBlack = 0x5a5a5a; // Obj 0
Table05Entry09Colors.obj0White = 0xffffff;
Table05Entry09Colors.obj0LightGrey = 0xff7300;
Table05Entry09Colors.obj0DarkGrey = 0x944200;
Table05Entry09Colors.obj0Black = 0x000000; // Obj1
Table05Entry09Colors.obj1White = 0xffffff;
Table05Entry09Colors.obj1LightGrey = 0x63a5ff;
Table05Entry09Colors.obj1DarkGrey = 0x0000ff;
Table05Entry09Colors.obj1Black = 0x000000;
return Table05Entry09Colors;
}(); // Link's Awakening
var Table05Entry11Colors =
/** @class */
function () {
function Table05Entry11Colors() {} // Bg
Table05Entry11Colors.bgWhite = 0xffffff;
Table05Entry11Colors.bgLightGrey = 0xff8484;
Table05Entry11Colors.bgDarkGrey = 0x943a3a;
Table05Entry11Colors.bgBlack = 0x000000; // Obj 0
Table05Entry11Colors.obj0White = 0xffffff;
Table05Entry11Colors.obj0LightGrey = 0x00ff00;
Table05Entry11Colors.obj0DarkGrey = 0x318400;
Table05Entry11Colors.obj0Black = 0x004a00; // Obj1
Table05Entry11Colors.obj1White = 0xffffff;
Table05Entry11Colors.obj1LightGrey = 0x63a5ff;
Table05Entry11Colors.obj1DarkGrey = 0x0000ff;
Table05Entry11Colors.obj1Black = 0x000000;
return Table05Entry11Colors;
}(); // Metroid 2
var Table05Entry14Colors =
/** @class */
function () {
function Table05Entry14Colors() {} //Bg
Table05Entry14Colors.bgWhite = 0xffffff;
Table05Entry14Colors.bgLightGrey = 0x63a5ff;
Table05Entry14Colors.bgDarkGrey = 0x0000ff;
Table05Entry14Colors.bgBlack = 0x000000; // Obj 0
Table05Entry14Colors.obj0White = 0xffff00;
Table05Entry14Colors.obj0LightGrey = 0xff0000;
Table05Entry14Colors.obj0DarkGrey = 0x630000;
Table05Entry14Colors.obj0Black = 0x000000; // Obj1
Table05Entry14Colors.obj1White = 0xffffff;
Table05Entry14Colors.obj1LightGrey = 0x7bff31;
Table05Entry14Colors.obj1DarkGrey = 0x008400;
Table05Entry14Colors.obj1Black = 0x000000;
return Table05Entry14Colors;
}(); // WarioLand 2
var Table05Entry15Colors =
/** @class */
function () {
function Table05Entry15Colors() {} //Bg
Table05Entry15Colors.bgWhite = 0xffffff;
Table05Entry15Colors.bgLightGrey = 0xadad84;
Table05Entry15Colors.bgDarkGrey = 0x42737b;
Table05Entry15Colors.bgBlack = 0x000000; // Obj 0
Table05Entry15Colors.obj0White = 0xffffff;
Table05Entry15Colors.obj0LightGrey = 0xffad63;
Table05Entry15Colors.obj0DarkGrey = 0xffad63;
Table05Entry15Colors.obj0Black = 0x000000; // Obj1
Table05Entry15Colors.obj1White = 0xffffff;
Table05Entry15Colors.obj1LightGrey = 0x63a5ff;
Table05Entry15Colors.obj1DarkGrey = 0x0000ff;
Table05Entry15Colors.obj1Black = 0x000000;
return Table05Entry15Colors;
}(); // File for all of the logic of setting gameboy color plaettes
// Current / exported color
var Colors =
/** @class */
function () {
function Colors() {} //Bg
Colors.bgWhite = WasmBoyGBColors.bgWhite;
Colors.bgLightGrey = WasmBoyGBColors.bgLightGrey;
Colors.bgDarkGrey = WasmBoyGBColors.bgDarkGrey;
Colors.bgBlack = WasmBoyGBColors.bgBlack; // Obj 0
Colors.obj0White = WasmBoyGBColors.obj0White;
Colors.obj0LightGrey = WasmBoyGBColors.obj0LightGrey;
Colors.obj0DarkGrey = WasmBoyGBColors.obj0DarkGrey;
Colors.obj0Black = WasmBoyGBColors.obj0Black; // Obj1
Colors.obj1White = WasmBoyGBColors.obj1White;
Colors.obj1LightGrey = WasmBoyGBColors.obj1LightGrey;
Colors.obj1DarkGrey = WasmBoyGBColors.obj1DarkGrey;
Colors.obj1Black = WasmBoyGBColors.obj1Black;
return Colors;
}(); // Inlined because closure compiler inlines
function initializeColors() {
setManualColorizationPalette(0);
if (Cpu.GBCEnabled) {
// Don't need to continue this if a GBC game
return;
}
if (Cpu.BootROMEnabled) {
if (!Cpu.GBCEnabled) {
// GB
return;
}
} // Do some automatic color palette swapping if we have a loaded ROM
var titleChecksum = 0x00;
for (var i = 0x0134; i <= 0x0143; i++) {
titleChecksum += eightBitLoadFromGBMemory(i);
} // Set the colorization for the game automatically if assigned
// https://tcrf.net/Notes:Game_Boy_Color_Bootstrap_ROM
var hash = titleChecksum & 0xff;
setHashColorizationPalette(hash);
}
function getRedFromHexColor(color) {
return (color & 0xff0000) >> 16;
}
function getGreenFromHexColor(color) {
return (color & 0x00ff00) >> 8;
}
function getBlueFromHexColor(color) {
return color & 0x0000ff;
} // Function to set the colorization
// By manually pressing buttons
function setManualColorizationPalette(colorizationId) {
// Set the colorizationId clockwise according to:
// https://en.wikipedia.org/wiki/Game_Boy_Color
switch (colorizationId) {
case 0:
Colors.bgWhite = WasmBoyGBColors.bgWhite;
Colors.bgLightGrey = WasmBoyGBColors.bgLightGrey;
Colors.bgDarkGrey = WasmBoyGBColors.bgDarkGrey;
Colors.bgBlack = WasmBoyGBColors.bgBlack;
Colors.obj0White = WasmBoyGBColors.obj0White;
Colors.obj0LightGrey = WasmBoyGBColors.obj0LightGrey;
Colors.obj0DarkGrey = WasmBoyGBColors.obj0DarkGrey;
Colors.obj0Black = WasmBoyGBColors.obj0Black;
Colors.obj1White = WasmBoyGBColors.obj1White;
Colors.obj1LightGrey = WasmBoyGBColors.obj1LightGrey;
Colors.obj1DarkGrey = WasmBoyGBColors.obj1DarkGrey;
Colors.obj1Black = WasmBoyGBColors.obj1Black;
break;
case 1:
// Up, Brown
Colors.bgWhite = BrownColors.bgWhite;
Colors.bgLightGrey = BrownColors.bgLightGrey;
Colors.bgDarkGrey = BrownColors.bgDarkGrey;
Colors.bgBlack = BrownColors.bgBlack;
Colors.obj0White = BrownColors.obj0White;
Colors.obj0LightGrey = BrownColors.obj0LightGrey;
Colors.obj0DarkGrey = BrownColors.obj0DarkGrey;
Colors.obj0Black = BrownColors.obj0Black;
Colors.obj1White = BrownColors.obj1White;
Colors.obj1LightGrey = BrownColors.obj1LightGrey;
Colors.obj1DarkGrey = BrownColors.obj1DarkGrey;
Colors.obj1Black = BrownColors.obj1Black;
break;
case 2:
// Up + A, Red
Colors.bgWhite = RedColors.bgWhite;
Colors.bgLightGrey = RedColors.bgLightGrey;
Colors.bgDarkGrey = RedColors.bgDarkGrey;
Colors.bgBlack = RedColors.bgBlack;
Colors.obj0White = RedColors.obj0White;
Colors.obj0LightGrey = RedColors.obj0LightGrey;
Colors.obj0DarkGrey = RedColors.obj0DarkGrey;
Colors.obj0Black = RedColors.obj0Black;
Colors.obj1White = RedColors.obj1White;
Colors.obj1LightGrey = RedColors.obj1LightGrey;
Colors.obj1DarkGrey = RedColors.obj1DarkGrey;
Colors.obj1Black = RedColors.obj1Black;
break;
case 3:
// Up + B, DarkBrown
Colors.bgWhite = DarkBrownColors.bgWhite;
Colors.bgLightGrey = DarkBrownColors.bgLightGrey;
Colors.bgDarkGrey = DarkBrownColors.bgDarkGrey;
Colors.bgBlack = DarkBrownColors.bgBlack;
Colors.obj0White = DarkBrownColors.obj0White;
Colors.o