Skip to content

Commit

Permalink
Optimization / Performance cleanup (#264)
Browse files Browse the repository at this point in the history
* Implemented all changes from #230 and #221

* Fixed off by one mentioned in #216

* Wrapped modulo in i32Portable as mentioned in #216

* issue #207, Allowed making closure builds for debugging, and then tried
to match its inlining

* Removed the legacy api

* Updated the package-lock for the branch
  • Loading branch information
torch2424 authored Feb 22, 2019
1 parent f678854 commit 1de7031
Show file tree
Hide file tree
Showing 45 changed files with 1,643 additions and 2,245 deletions.
1 change: 1 addition & 0 deletions core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export function isGBC(): i32 {
// Function to return an address to store into save state memory
// this is to regulate our 20 slots
// https://docs.google.com/spreadsheets/d/17xrEzJk5-sCB9J2mMJcVnzhbE-XH_NvczVSQH9OHvRk/edit?usp=sharing
// Inlined because closure compiler inlines
export function getSaveStateMemoryOffset(offset: i32, saveStateSlot: i32): i32 {
// 50 bytes per save state memory partiton sli32
return WASMBOY_STATE_LOCATION + offset + 50 * saveStateSlot;
Expand Down
1 change: 1 addition & 0 deletions core/cpu/cbOpcodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { u8Portable, u16Portable } from '../portable/portable';
// Handle CB Opcodes
// NOTE: Program stpes and cycles are standardized depending on the register type
// NOTE: Doing some funny stuff to get around not having arrays or objects
// Inlined because closure compiler inlines.
export function handleCbOpcode(cbOpcode: i32): i32 {
let numberOfCycles: i32 = -1;
let handledOpcode: boolean = false;
Expand Down
1 change: 1 addition & 0 deletions core/cpu/cpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export class Cpu {
}
}

// Inlined because closure compiler does so
export function initializeCpu(): void {
// Reset all stateful Cpu variables
// Cpu.GBCEnabled is done by core/initialize
Expand Down
8 changes: 8 additions & 0 deletions core/cpu/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export function cpARegister(register: u8): void {
setSubtractFlag(1);
}

// Inlined because closure compiler inlines
export function rotateRegisterLeft(register: u8): u8 {
// RLC register 8-bit
// Z 0 0 C
Expand All @@ -188,6 +189,7 @@ export function rotateRegisterLeft(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function rotateRegisterRight(register: u8): u8 {
// RLC register 8-bit
// Z 0 0 C
Expand All @@ -212,6 +214,7 @@ export function rotateRegisterRight(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function rotateRegisterLeftThroughCarry(register: u8): u8 {
// RL register 8-bit
// Z 0 0 C
Expand Down Expand Up @@ -240,6 +243,7 @@ export function rotateRegisterLeftThroughCarry(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function rotateRegisterRightThroughCarry(register: u8): u8 {
// RR register 8-bit
// Z 0 0 C
Expand Down Expand Up @@ -267,6 +271,7 @@ export function rotateRegisterRightThroughCarry(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function shiftLeftRegister(register: u8): u8 {
// SLA register 8-bit
// Z 0 0 C
Expand Down Expand Up @@ -295,6 +300,7 @@ export function shiftLeftRegister(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function shiftRightArithmeticRegister(register: u8): u8 {
// SRA register 8-bit
// Z 0 0 C
Expand Down Expand Up @@ -334,6 +340,7 @@ export function shiftRightArithmeticRegister(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function swapNibblesOnRegister(register: u8): u8 {
// SWAP register 8-bit
// Z 0 0 0
Expand All @@ -354,6 +361,7 @@ export function swapNibblesOnRegister(register: u8): u8 {
return register;
}

// Inlined because closure compiler inlines
export function shiftRightLogicalRegister(register: u8): u8 {
// SRA register 8-bit
// Z 0 0 C
Expand Down
2 changes: 2 additions & 0 deletions core/cycles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function getCycles(): i32 {
return Cycles.cycles;
}

// Inlined because closure compiler inlines
function trackCyclesRan(numberOfCycles: i32): void {
Cycles.cycles += numberOfCycles;
if (Cycles.cycles >= Cycles.cyclesPerCycleSet) {
Expand All @@ -39,6 +40,7 @@ function trackCyclesRan(numberOfCycles: i32): void {
}
}

// Inlined because closure compiler inlines
export function resetCycles(): void {
Cycles.cyclesPerCycleSet = 2000000000;
Cycles.cycleSets = 0;
Expand Down
2 changes: 2 additions & 0 deletions core/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function getSteps(): i32 {
return Execute.steps;
}

// Inlined because closure compiler inlines
function trackStepsRan(steps: i32): void {
Execute.steps += steps;
if (Execute.steps >= Execute.stepsPerStepSet) {
Expand All @@ -44,6 +45,7 @@ function trackStepsRan(steps: i32): void {
}
}

// Inlined because closure compiler inlines
export function resetSteps(): void {
Execute.stepsPerStepSet = 2000000000;
Execute.stepSets = 0;
Expand Down
27 changes: 19 additions & 8 deletions core/graphics/backgroundWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ import { TileCache, drawPixelsFromLineOfTile, getTileDataAddress } from './tiles
import { eightBitLoadFromGBMemory } from '../memory/load';
import { Memory } from '../memory/memory';
import { hexLog, checkBitOnByte, setBitOnByte, resetBitOnByte } from '../helpers/index';
import { u8Portable } from '../portable/portable';
import { u8Portable, i32Portable } from '../portable/portable';

// NOTE: i32Portable wraps modulo here as somehow it gets converted to a double:
// https://github.com/torch2424/wasmboy/issues/216

// Inlined because closure compiler inlines
export function renderBackground(scanlineRegister: i32, tileDataMemoryLocation: i32, tileMapMemoryLocation: i32): void {
// NOTE: Camera is reffering to what you can see inside the 160x144 viewport of the entire rendered 256x256 map.

Expand All @@ -45,6 +49,7 @@ export function renderBackground(scanlineRegister: i32, tileDataMemoryLocation:
drawBackgroundWindowScanline(scanlineRegister, tileDataMemoryLocation, tileMapMemoryLocation, pixelYPositionInMap, 0, scrollX);
}

// Inlined because closure compiler inlines
export function renderWindow(scanlineRegister: i32, tileDataMemoryLocation: i32, tileMapMemoryLocation: i32): void {
// Get our windowX and windowY
// let windowX: i32 = eightBitLoadFromGBMemory(Graphics.memoryLocationWindowX);
Expand All @@ -67,7 +72,9 @@ export function renderWindow(scanlineRegister: i32, tileDataMemoryLocation: i32,
let pixelYPositionInMap: i32 = scanlineRegister - windowY;

// xOffset is simply a neagative window x
let xOffset: i32 = -1 * windowX;
// NOTE: This can become negative zero?
// https://github.com/torch2424/wasmboy/issues/216
let xOffset: i32 = i32Portable(-1 * windowX);

// Draw the Background scanline
drawBackgroundWindowScanline(scanlineRegister, tileDataMemoryLocation, tileMapMemoryLocation, pixelYPositionInMap, windowX, xOffset);
Expand Down Expand Up @@ -178,6 +185,7 @@ function drawBackgroundWindowScanline(
}

// Function to draw a pixel for the standard GB
// Inlined because closure compiler inlines
function drawMonochromePixelFromTileId(
xPixel: i32,
yPixel: i32,
Expand All @@ -203,7 +211,7 @@ function drawMonochromePixelFromTileId(
// yPixel = 144. 144 % 8 = 0.
// 0 Represents last line of pixels in a tile, 1 represents first. 1 2 3 4 5 6 7 0.
// Because remember, we are counting lines on the display NOT including zero
let pixelYInTile: i32 = pixelYPositionInMap % 8;
let pixelYInTile: i32 = i32Portable(pixelYPositionInMap % 8);

// Remember to represent a single line of 8 pixels on a tile, we need two bytes.
// Therefore, we need to times our modulo by 2, to get the correct line of pixels on the tile.
Expand All @@ -217,7 +225,7 @@ function drawMonochromePixelFromTileId(
// Therefore, is pixelX was 2, then really is need to be 5
// So 2 - 7 = -5, * 1 = 5
// Or to simplify, 7 - 2 = 5 haha!
let pixelXInTile: i32 = pixelXPositionInMap % 8;
let pixelXInTile: i32 = i32Portable(pixelXPositionInMap % 8);
pixelXInTile = 7 - pixelXInTile;

// Now we can get the color for that pixel
Expand Down Expand Up @@ -259,6 +267,7 @@ function drawMonochromePixelFromTileId(

// Function to draw a pixel from a tile in C O L O R
// See above for more context on some variables
// Inlined because closure compiler inlines
function drawColorPixelFromTileId(
xPixel: i32,
yPixel: i32,
Expand All @@ -284,7 +293,7 @@ function drawColorPixelFromTileId(
let bgMapAttributes: i32 = loadFromVramBank(tileMapAddress, 1);

// See above for explanation
let pixelYInTile: i32 = pixelYPositionInMap % 8;
let pixelYInTile: i32 = i32Portable(pixelYPositionInMap % 8);
if (checkBitOnByte(6, bgMapAttributes)) {
// We are mirroring the tile, therefore, we need to opposite byte
// So if our pixel was 0 our of 8, it wild become 7 :)
Expand All @@ -303,7 +312,7 @@ function drawColorPixelFromTileId(

// Get our X pixel. Need to NOT reverse it if it was flipped.
// See above, you have to reverse this normally
let pixelXInTile: i32 = pixelXPositionInMap % 8;
let pixelXInTile: i32 = i32Portable(pixelXPositionInMap % 8);
if (!checkBitOnByte(5, bgMapAttributes)) {
pixelXInTile = 7 - pixelXInTile;
}
Expand Down Expand Up @@ -348,6 +357,7 @@ function drawColorPixelFromTileId(
}

// Function to attempt to draw the tile from the tile cache
// Inlined because closure compiler inlines
function drawLineOfTileFromTileCache(
xPixel: i32,
yPixel: i32,
Expand Down Expand Up @@ -406,7 +416,7 @@ function drawLineOfTileFromTileCache(
// Calculate when we should do the tileCache calculation again
if (xPixel >= TileCache.nextXIndexToPerformCacheCheck) {
TileCache.nextXIndexToPerformCacheCheck = xPixel + 8;
let xOffsetTileWidthRemainder: i32 = pixelXPositionInMap % 8;
let xOffsetTileWidthRemainder: i32 = i32Portable(pixelXPositionInMap % 8);
if (xPixel < xOffsetTileWidthRemainder) {
TileCache.nextXIndexToPerformCacheCheck += xOffsetTileWidthRemainder;
}
Expand All @@ -417,6 +427,7 @@ function drawLineOfTileFromTileCache(

// Function to draw a line of a tile in Color
// This is for tile rendering shortcuts
// Inlined because closure compiler inlines
function drawLineOfTileFromTileId(
xPixel: i32,
yPixel: i32,
Expand All @@ -427,7 +438,7 @@ function drawLineOfTileFromTileId(
tileIdFromTileMap: i32
): i32 {
// Get the which line of the tile we are rendering
let tileLineY: i32 = pixelYPositionInMap % 8;
let tileLineY: i32 = i32Portable(pixelYPositionInMap % 8);

// Now lets find our tileX start and end
// This is for the case where i = 0, but scroll X was 3.
Expand Down
2 changes: 2 additions & 0 deletions core/graphics/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class Colors {
static obj1Black: i32 = WasmBoyGBColors.obj1Black;
}

// Inlined because closure compiler inlines
export function initializeColors(): void {
setManualColorizationPalette(0);

Expand Down Expand Up @@ -310,6 +311,7 @@ export function setManualColorizationPalette(colorizationId: i32): void {
// By checksum of the title
// https://forums.nesdev.com/viewtopic.php?f=20&t=10226
// TODO: torch2424 need to find how to get the "disambiguation"
// Inlined because closure compiler inlines
export function setHashColorizationPalette(hash: i32): void {
switch (hash) {
case 0x88:
Expand Down
2 changes: 2 additions & 0 deletions core/graphics/graphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export function batchProcessGraphics(): void {
}
}

// Inlined because closure compiler inlines
export function initializeGraphics(): void {
// Reset Stateful Variables
Graphics.currentCycles = 0;
Expand Down Expand Up @@ -295,6 +296,7 @@ function _renderEntireFrame(): void {
}

// Function to get the start of a RGB pixel (R, G, B)
// Inlined because closure compiler inlines
export function getRgbPixelStart(x: i32, y: i32): i32 {
// Get the pixel number
// let pixelNumber: i32 = (y * 160) + x;
Expand Down
1 change: 1 addition & 0 deletions core/graphics/lcd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function resetLcd(shouldBlankScreen: boolean): void {
}

// Pass in the lcd status for performance
// Inlined because closure compiler inlines
export function setLcdStatus(): void {
// Check if the Lcd was disabled
if (!Lcd.enabled) {
Expand Down
5 changes: 5 additions & 0 deletions core/graphics/palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class Palette {
static readonly memoryLocationSpritePaletteTwo: i32 = 0xff49;
}

// Inlined because closure compiler inlines
export function initializePalette(): void {
if (Cpu.GBCEnabled) {
// GBC Palettes
Expand All @@ -38,6 +39,7 @@ export function initializePalette(): void {
// Simple get pallete color or monochrome GB
// shouldRepresentColorByColorId is good for debugging tile data for GBC games that don't have
// monochromePalettes
// Inlined because closure compiler inlines
export function getMonochromeColorFromPalette(
colorId: i32,
paletteMemoryLocation: i32,
Expand Down Expand Up @@ -135,6 +137,7 @@ export function getColorizedGbHexColorFromPalette(colorId: i32, paletteMemoryLoc
return hexColor;
}

// Inlined because closure compiler inlines
export function writeColorPaletteToMemory(offset: i32, value: i32): void {
// FF68
// Bit 0-5 Index (00-3F)
Expand All @@ -160,6 +163,7 @@ export function writeColorPaletteToMemory(offset: i32, value: i32): void {
// Functions to Handle Write to pallete data registers
// http://gbdev.gg8.se/wiki/articles/Video_Display#FF68_-_BCPS.2FBGPI_-_CGB_Mode_Only_-_Background_Palette_Index
// Function to handle incrementing the pallete index if required
// Inlined because closure compiler inlines
function incrementPaletteIndexIfSet(paletteIndex: i32, offset: i32): void {
// Check ther auto increment box
if (checkBitOnByte(7, paletteIndex)) {
Expand Down Expand Up @@ -217,6 +221,7 @@ export function loadPaletteByteFromWasmMemory(paletteIndexByte: i32, isSprite: b
}

// Function to store a byte to our Gbc Palette memory
// Inlined because closure compiler inlines
export function storePaletteByteInWasmMemory(paletteIndexByte: i32, value: i32, isSprite: boolean): void {
// Clear the top two bits to just get the bottom palette Index
let paletteIndex: i32 = paletteIndexByte & 0x3f;
Expand Down
3 changes: 3 additions & 0 deletions core/graphics/priority.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ export function addPriorityforPixel(x: i32, y: i32, colorId: i32 = 0, hasGbcBgPr
store<u8>(BG_PRIORITY_MAP_LOCATION + getPixelStart(x, y), <u8>bgPriorityByte);
}

// Inlined because closure compiler inlines
export function getPriorityforPixel(x: i32, y: i32): u8 {
return load<u8>(BG_PRIORITY_MAP_LOCATION + getPixelStart(x, y));
}

// Inlined because closure compiler inlines
export function clearPriorityMap(): void {
for (let y: i32 = 0; y < 144; y++) {
for (let x: i32 = 0; x < 160; x++) {
Expand All @@ -26,6 +28,7 @@ export function clearPriorityMap(): void {
}
}

// Inlined because closure compiler inlines
function getPixelStart(x: i32, y: i32): i32 {
// Get the pixel number
return y * 160 + x;
Expand Down
1 change: 1 addition & 0 deletions core/graphics/sprites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { getPriorityforPixel } from './priority';
import { eightBitLoadFromGBMemory } from '../memory/load';
import { checkBitOnByte, setBitOnByte, resetBitOnByte, hexLog } from '../helpers/index';

// Inlined because closure compiler inlines
export function renderSprites(scanlineRegister: i32, useLargerSprites: boolean): void {
// Need to loop through all 40 sprites to check their status
// Going backwards since lower sprites draw over higher ones
Expand Down
2 changes: 2 additions & 0 deletions core/graphics/tiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class TileCache {
static nextXIndexToPerformCacheCheck: i32 = -1;
}

// Inlined because closure compiler inlines
export function resetTileCache(): void {
TileCache.tileId = -1;
TileCache.nextXIndexToPerformCacheCheck = -1;
Expand Down Expand Up @@ -155,6 +156,7 @@ export function drawPixelsFromLineOfTile(
return pixelsDrawn;
}

// Inlined because closure compiler inlines
export function getTilePixelStart(outputLineX: i32, outputLineY: i32, outputWidth: i32): i32 {
// Finally Lets place a pixel in memory
let pixelStart: i32 = outputLineY * outputWidth + outputLineX;
Expand Down
20 changes: 0 additions & 20 deletions core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,3 @@ export {
export { getLY, drawBackgroundMapToWasmMemory, drawTileDataToWasmMemory, drawOamToWasmMemory } from './debug/debug-graphics';
export { getDIV, getTIMA, getTMA, getTAC } from './debug/debug-timer';
export { updateDebugGBMemory } from './debug/debug-memory';
export {
update,
emulationStep,
getAudioQueueIndex,
resetAudioQueue,
wasmMemorySize,
wasmBoyInternalStateLocation,
wasmBoyInternalStateSize,
gameBoyInternalMemoryLocation,
gameBoyInternalMemorySize,
videoOutputLocation,
frameInProgressVideoOutputLocation,
gameboyColorPaletteLocation,
gameboyColorPaletteSize,
backgroundMapLocation,
tileDataMap,
soundOutputLocation,
gameBytesLocation,
gameRamBanksLocation
} from './legacy';
Loading

0 comments on commit 1de7031

Please sign in to comment.