PPU: Mosaic effect support

This commit is contained in:
Sour 2019-02-20 17:39:14 -05:00
parent 30cb4f1dcc
commit 37b501122f
2 changed files with 35 additions and 1 deletions

View file

@ -93,6 +93,9 @@ void Ppu::Exec()
} else if(_scanline == 261) {
_regs->SetNmiFlag(false);
_scanline = 0;
if(_mosaicEnabled) {
_mosaicStartScanline = 0;
}
_console->GetDmaController()->InitHdmaChannels();
RenderScanline();
}
@ -378,12 +381,15 @@ void Ppu::RenderTilemap()
}
}
bool applyMosaic = forMainScreen && ((_mosaicEnabled >> layerIndex) & 0x01) != 0;
bool mosaicScanline = applyMosaic && (_scanline - _mosaicStartScanline) % _mosaicSize != 0;
uint8_t pixelFlags = PixelFlags::Filled | (((_colorMathEnabled >> layerIndex) & 0x01) ? PixelFlags::AllowColorMath : 0);
LayerConfig &config = _layerConfig[layerIndex];
uint16_t tilemapAddr = config.TilemapAddress >> 1;
uint16_t chrAddr = config.ChrAddress;
for(int x = 0; x < 256; x++) {
uint16_t row = (_scanline + config.VScroll) >> 3;
uint16_t column = (x + config.HScroll) >> 3;
@ -401,6 +407,13 @@ void Ppu::RenderTilemap()
}
}
if(mosaicScanline || (applyMosaic && x % _mosaicSize != 0)) {
//If this is not the top-left pixels in the mosaic pattern, override it with the top-left pixel data
_currentBuffer[(_scanline << 8) | x] = _mosaicColor[x];
_rowPixelFlags[x] = pixelFlags;
continue;
}
uint8_t palette = (_vram[addr + 1] >> 2) & 0x07;
uint16_t tileIndex = ((_vram[addr + 1] & 0x03) << 8) | _vram[addr];
bool vMirror = (_vram[addr + 1] & 0x80) != 0;
@ -430,6 +443,12 @@ void Ppu::RenderTilemap()
if(forMainScreen) {
_currentBuffer[(_scanline << 8) | x] = paletteColor;
_rowPixelFlags[x] = pixelFlags;
if(applyMosaic && x % _mosaicSize == 0) {
//This is the source for the mosaic pattern, store it for use in the next scanlines
for(int i = 0; i < _mosaicSize && x + i < 256; i++) {
_mosaicColor[x+i] = paletteColor;
}
}
} else {
_subScreenBuffer[(_scanline << 8) | x] = paletteColor;
_subScreenFilled[x] = true;
@ -588,6 +607,16 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_layerConfig[3].LargeTiles = (value & 0x40) != 0;
break;
case 0x2106:
//MOSAIC - Screen Pixelation
_mosaicSize = ((value & 0xF0) >> 4) + 1;
_mosaicEnabled = value & 0x0F;
if(_mosaicEnabled) {
//"If this register is set during the frame, the <20>estarting scanline<6E>f is the current scanline, otherwise it is the first visible scanline of the frame."
_mosaicStartScanline = _scanline;
}
break;
case 0x2107: case 0x2108: case 0x2109: case 0x210A:
//BG 1-4 Tilemap Address and Size (BG1SC, BG2SC, BG3SC, BG4SC)
_layerConfig[addr - 0x2107].TilemapAddress = (value & 0xFC) << 9;

View file

@ -78,6 +78,11 @@ private:
bool _subScreenFilled[256];
uint16_t *_subScreenBuffer;
uint16_t _mosaicColor[256] = {};
uint8_t _mosaicSize = 0;
uint8_t _mosaicEnabled = 0;
uint16_t _mosaicStartScanline = 0;
uint8_t _oamMode = 0;
uint16_t _oamBaseAddress = 0;
uint16_t _oamAddressOffset = 0;