wasmboy
Version:
Gameboy / Gameboy Color Emulator written for Web Assembly using AssemblyScript. Shell/Debugger in Preact
112 lines (106 loc) • 4.67 kB
text/typescript
// WasmBoy memory map:
// https://docs.google.com/spreadsheets/d/17xrEzJk5-sCB9J2mMJcVnzhbE-XH_NvczVSQH9OHvRk/edit?usp=sharing
import {
VIDEO_RAM_LOCATION,
WORK_RAM_LOCATION,
OTHER_GAMEBOY_INTERNAL_MEMORY_LOCATION,
CARTRIDGE_RAM_LOCATION,
BOOT_ROM_LOCATION,
CARTRIDGE_ROM_LOCATION
} from '../constants';
import { Memory } from './memory';
import { eightBitLoadFromGBMemory } from './load';
import { getRomBankAddress, getRamBankAddress } from './banking';
import { Cpu } from '../cpu/index';
// Private function to translate a offset meant for the gameboy memory map
// To the wasmboy memory map
// Following: http://gameboy.mongenel.com/dmg/asmmemmap.html
// And https://github.com/Dooskington/GameLad/wiki/Part-11---Memory-Bank-Controllers
// Performance help from @dcodeIO, and awesome-gbdev
export function getWasmBoyOffsetFromGameBoyOffset(gameboyOffset: i32): i32 {
// Get the top byte and switch
let gameboyOffsetHighByte = gameboyOffset >> 12;
switch (gameboyOffsetHighByte) {
case 0x00:
// Check if we are currently executing the boot rom
// Otherwise, bottom 0x0000 -> 0x03FF is Cartridge ROM Ram Bank 1
if (Cpu.BootROMEnabled) {
if (Cpu.GBCEnabled) {
// See: http://gbdev.gg8.se/wiki/articles/Gameboy_Bootstrap_ROM
// "The rom dump includes the 256 byte rom (0x0000-0x00FF) and the,
// 1792 byte rom (0x0200-0x08FF) which Dr. Decapitator observed,
// but not the 512 byte rom,
// which may be cpu microcode or lcd color lookup related."
// First 0xFF bytes are BOOT rom
if (gameboyOffset < 0x0100) {
return gameboyOffset + BOOT_ROM_LOCATION;
}
// 0x100 -> 0x1FF is the actual ROM
// Everything from 0x200 -> 0x8FF is BOOT ROM Again
if (gameboyOffset > 0x01ff && gameboyOffset < 0x0900) {
return gameboyOffset + BOOT_ROM_LOCATION;
}
} else if (!Cpu.GBCEnabled && gameboyOffset < 0x0100) {
return gameboyOffset + BOOT_ROM_LOCATION;
}
}
case 0x01:
case 0x02:
case 0x03:
// Cartridge ROM - Bank 0 (fixed)
// 0x0000 -> 0x0D2400
return gameboyOffset + CARTRIDGE_ROM_LOCATION;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
// Cartridge ROM - Switchable Banks 1-xx
// 0x4000 -> (0x0D2400 + 0x4000)
return getRomBankAddress(gameboyOffset) + CARTRIDGE_ROM_LOCATION;
case 0x08:
case 0x09:
// Video RAM
// 0x8000 -> 0x000400
let vramBankId = 0;
if (Cpu.GBCEnabled) {
// Find our current VRAM Bank
vramBankId = eightBitLoadFromGBMemory(Memory.memoryLocationGBCVRAMBank) & 0x01;
// Even though We added another 0x2000, the Cartridge ram is pulled out of our Internal Memory Space
// Therefore, we do not need to adjust for this extra 0x2000
}
return gameboyOffset - Memory.videoRamLocation + VIDEO_RAM_LOCATION + 0x2000 * vramBankId;
case 0x0a:
case 0x0b:
// Cartridge RAM - A.K.A External RAM
// 0xA000 -> 0x008400
return getRamBankAddress(gameboyOffset) + CARTRIDGE_RAM_LOCATION;
case 0x0c:
// Gameboy Ram Bank 0
// 0xC000 -> 0x000400
// Don't need to add head, since we move out 0x200 from the cartridge ram
return gameboyOffset - Memory.internalRamBankZeroLocation + WORK_RAM_LOCATION;
case 0x0d:
// Gameboy Ram Banks, Switchable in GBC Mode
// 0xD000 -> 0x000400
// In CGB Mode 32 KBytes internal RAM are available.
// This memory is divided into 8 banks of 4 KBytes each.
// Bank 0 is always available in memory at C000-CFFF,
// Bank 1-7 can be selected into the address space at D000-DFFF.
// http://gbdev.gg8.se/wiki/articles/CGB_Registers#FF70_-_SVBK_-_CGB_Mode_Only_-_WRAM_Bank
// Get the last 3 bits to find our wram ID
let wramBankId = 0;
if (Cpu.GBCEnabled) {
wramBankId = eightBitLoadFromGBMemory(Memory.memoryLocationGBCWRAMBank) & 0x07;
}
wramBankId = wramBankId < 1 ? 1 : wramBankId;
// (0x1000 * (wramBankId - 1)) -> To find the correct wram bank.
// wramBankId - 1, because we alreayd have the space for wramBank 1, and are currently in it
// So need to address space for 6 OTHER banks
return gameboyOffset - Memory.internalRamBankZeroLocation + WORK_RAM_LOCATION + 0x1000 * (wramBankId - 1);
default:
// Everything Else after Gameboy Ram Banks
// 0xE000 -> 0x000400
// 0x6000 For the Extra WRAM Banks
return gameboyOffset - Memory.echoRamLocation + OTHER_GAMEBOY_INTERNAL_MEMORY_LOCATION;
}
}