nes-emu
Version:
A NES emulator
71 lines (63 loc) • 3.41 kB
JavaScript
"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;
}
}