UNPKG

nes-emu

Version:

A NES emulator

71 lines (63 loc) 3.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = renderBackground; var _constants = _interopRequireDefault(require("../../constants")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const NAME_TABLE_OFFSETS = [1, -1, 1, -1]; // (for `scrolledX` overflow) const FULL_ALPHA = 0xff000000; /** Renders the background from the Name tables. */ function renderBackground(_ref) { let { ppu } = _ref; const { registers, loopy } = ppu; const y = ppu.scanline; const scrolledY = registers.ppuScroll.scrolledY(); const transparentColor = ppu.framePalette.getColorOf(0, 0); for (let x = 0; x < _constants.default.SCREEN_WIDTH; x++) { const cycle = x + 1; const scrolledX = registers.ppuScroll.scrolledX(x); // skip masked pixels if (!registers.ppuMask.showBackgroundInLeftmost8PixelsOfScreen && x < 8) { ppu.frameBuffer[y * _constants.default.SCREEN_WIDTH + x] = FULL_ALPHA | registers.ppuMask.transform(transparentColor); ppu.paletteIndexes[y * _constants.default.SCREEN_WIDTH + x] = 0; loopy.onVisibleLine(cycle); continue; } // background coordinates based on scroll const baseNameTableId = loopy.vAddress.nameTableId; const nameTableOffset = // (switch horizontal Name table if scrolledX has overflowed) scrolledX >= _constants.default.SCREEN_WIDTH ? NAME_TABLE_OFFSETS[baseNameTableId] : 0; const nameTableId = baseNameTableId + nameTableOffset; const nameTableX = scrolledX % _constants.default.SCREEN_WIDTH; const nameTableY = scrolledY % _constants.default.SCREEN_HEIGHT; // tile id and palette fetch const tileId = ppu.nameTable.getTileIdOf(nameTableId, nameTableX, nameTableY); const paletteId = ppu.attributeTable.getPaletteIdOf(nameTableId, nameTableX, nameTableY); const paletteColors = [ppu.framePalette.getColorOf(paletteId, 0), ppu.framePalette.getColorOf(paletteId, 1), ppu.framePalette.getColorOf(paletteId, 2), ppu.framePalette.getColorOf(paletteId, 3)]; // tile row fetch const patternTableId = registers.ppuCtrl.patternTableAddressIdForBackground; const tileStartX = nameTableX % _constants.default.TILE_LENGTH; const tileStartY = nameTableY % _constants.default.TILE_LENGTH; const patternLowByte = ppu.patternTable.getLowByteOf(patternTableId, tileId, tileStartY); const patternHighByte = ppu.patternTable.getHighByteOf(patternTableId, tileId, tileStartY); // partially draw tile (from `tileStartX` until its end or the end of the Name table) const remainingNameTablePixels = _constants.default.SCREEN_WIDTH - nameTableX; const tilePixels = Math.min(_constants.default.TILE_LENGTH - tileStartX, remainingNameTablePixels); for (let i = 0; i < tilePixels; i++) { const paletteIndex = ppu.patternTable.getPaletteIndexFromBytes(patternLowByte, patternHighByte, tileStartX + i); const color = paletteIndex !== _constants.default.COLOR_TRANSPARENT ? paletteColors[paletteIndex] : transparentColor; ppu.frameBuffer[y * _constants.default.SCREEN_WIDTH + x + i] = FULL_ALPHA | registers.ppuMask.transform(color); ppu.paletteIndexes[y * _constants.default.SCREEN_WIDTH + x + i] = paletteIndex; loopy.onVisibleLine(cycle + i); } // (the x++ of the for loop will do the last increment) x += tilePixels - 1; } }