PPU: Direct color mode support

This commit is contained in:
Sour 2019-02-24 01:11:26 -05:00
parent 85f1333c3d
commit 16cc0653e9
2 changed files with 123 additions and 73 deletions

View file

@ -28,6 +28,8 @@ Ppu::Ppu(shared_ptr<Console> console)
_vram = new uint8_t[Ppu::VideoRamSize];
memset(_vram, 0, Ppu::VideoRamSize);
memset(_oamRam, 0, Ppu::SpriteRamSize);
memset(_cgram, 0, Ppu::CgRamSize);
_vramAddress = 0;
_vramIncrementValue = 1;
@ -365,13 +367,13 @@ void Ppu::RenderMode7()
RenderSprites<3, forMainScreen>();
RenderSprites<2, forMainScreen>();
if(_mode7.ExtBgEnabled) {
RenderTilemapMode7<1, forMainScreen, false, true>();
RenderTilemapMode7<1, forMainScreen, true>();
}
RenderSprites<1, forMainScreen>();
RenderTilemapMode7<0, forMainScreen, false, false>();
RenderTilemapMode7<0, forMainScreen, false>();
RenderSprites<0, forMainScreen>();
if(_mode7.ExtBgEnabled) {
RenderTilemapMode7<1, forMainScreen, false, false>();
RenderTilemapMode7<1, forMainScreen, false>();
}
RenderBgColor<forMainScreen>();
}
@ -385,6 +387,7 @@ void Ppu::RenderScanline()
if(_forcedVblank) {
RenderBgColor<true>();
ApplyHiResMode();
return;
}
@ -461,34 +464,42 @@ void Ppu::RenderBgColor()
}
}
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, bool largeTileWidth, bool largeTileHeight, uint16_t basePaletteOffset>
void Ppu::RenderTilemapLargeTiles()
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount, bool applyMosaic>
void Ppu::RenderTilemap()
{
if(_directColorMode) {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, activeWindowCount, applyMosaic, true>();
} else {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, activeWindowCount, applyMosaic, false>();
}
}
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount>
void Ppu::RenderTilemap()
{
bool applyMosaic = forMainScreen && ((_mosaicEnabled >> layerIndex) & 0x01) != 0;
if(applyMosaic) {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, activeWindowCount, true>();
} else {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, activeWindowCount, false>();
}
}
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight>
void Ppu::RenderTilemap()
{
uint8_t activeWindowCount = 0;
if((forMainScreen && _windowMaskMain[layerIndex]) || (!forMainScreen && _windowMaskSub[layerIndex])) {
activeWindowCount = (uint8_t)_window[0].ActiveLayers[layerIndex] + (uint8_t)_window[1].ActiveLayers[layerIndex];
}
bool applyMosaic = forMainScreen && ((_mosaicEnabled >> layerIndex) & 0x01) != 0;
if(activeWindowCount == 0) {
if(applyMosaic) {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 0, true>();
} else {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 0, false>();
}
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, 0>();
} else if(activeWindowCount == 1) {
if(applyMosaic) {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 1, true>();
} else {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 1, false>();
}
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, 1>();
} else {
if(applyMosaic) {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 2, true>();
} else {
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, largeTileWidth, largeTileHeight, basePaletteOffset, 2, false>();
}
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, largeTileWidth, largeTileHeight, 2>();
}
}
@ -500,20 +511,20 @@ void Ppu::RenderTilemap()
if(largeTileWidth) {
if(largeTileHeight) {
RenderTilemapLargeTiles<layerIndex, bpp, processHighPriority, forMainScreen, true, true, basePaletteOffset>();
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, true, true>();
} else {
RenderTilemapLargeTiles<layerIndex, bpp, processHighPriority, forMainScreen, true, false, basePaletteOffset>();
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, true, false>();
}
} else {
if(largeTileHeight) {
RenderTilemapLargeTiles<layerIndex, bpp, processHighPriority, forMainScreen, false, true, basePaletteOffset>();
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, false, true>();
} else {
RenderTilemapLargeTiles<layerIndex, bpp, processHighPriority, forMainScreen, false, false, basePaletteOffset>();
RenderTilemap<layerIndex, bpp, processHighPriority, forMainScreen, basePaletteOffset, false, false>();
}
}
}
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, bool largeTileWidth, bool largeTileHeight, uint16_t basePaletteOffset, uint8_t activeWindowCount, bool applyMosaic>
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount, bool applyMosaic, bool directColorMode>
void Ppu::RenderTilemap()
{
if(forMainScreen) {
@ -645,19 +656,54 @@ void Ppu::RenderTilemap()
}
if(color > 0) {
uint8_t palette = (_vram[addr + 1] >> 2) & 0x07;
uint16_t paletteRamOffset = basePaletteOffset + (palette * (1 << bpp) + color) * 2;
/* Ignore palette bits for 256-color layers */
uint16_t paletteColor;
if(bpp == 8 && directColorMode) {
uint8_t palette = (_vram[addr + 1] >> 2) & 0x07;
paletteColor = (
(((color & 0x07) | (palette & 0x01)) << 1) |
(((color & 0x38) | ((palette & 0x02) << 1)) << 3) |
(((color & 0xC0) | ((palette & 0x04) << 3)) << 7)
);
} else {
uint8_t palette = bpp == 8 ? 0 : (_vram[addr + 1] >> 2) & 0x07;
uint16_t paletteRamOffset = basePaletteOffset + (palette * (1 << bpp) + color) * 2;
paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
}
if(forMainScreen) {
DrawMainPixel<applyMosaic>(x, paletteRamOffset, pixelFlags);
DrawMainPixel<applyMosaic>(x, paletteColor, pixelFlags);
} else {
DrawSubPixel(x, paletteRamOffset);
DrawSubPixel(x, paletteColor);
}
}
}
}
template<uint8_t layerIndex, bool forMainScreen, bool applyMosaic, bool processHighPriority>
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority>
void Ppu::RenderTilemapMode7()
{
bool applyMosaic = forMainScreen && ((_mosaicEnabled >> layerIndex) & 0x01) != 0;
if(applyMosaic) {
RenderTilemapMode7<layerIndex, forMainScreen, processHighPriority, true>();
} else {
RenderTilemapMode7<layerIndex, forMainScreen, processHighPriority, false>();
}
}
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic>
void Ppu::RenderTilemapMode7()
{
if(_directColorMode) {
RenderTilemapMode7<layerIndex, forMainScreen, processHighPriority, applyMosaic, true>();
} else {
RenderTilemapMode7<layerIndex, forMainScreen, processHighPriority, applyMosaic, false>();
}
}
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic, bool directColorMode>
void Ppu::RenderTilemapMode7()
{
if(forMainScreen) {
@ -736,7 +782,7 @@ void Ppu::RenderTilemapMode7()
}
uint8_t tileIndex = _vram[(((yOffset & ~0x07) << 4) | (xOffset >> 3)) << 1] & tileMask;
uint16_t paletteRamOffset;
uint16_t colorIndex;
if(layerIndex == 1) {
uint8_t color = _vram[(((tileIndex << 6) + ((yOffset & 0x07) << 3) + (xOffset & 0x07)) << 1) + 1];
@ -744,41 +790,46 @@ void Ppu::RenderTilemapMode7()
//Wrong priority, skip this pixel
continue;
}
paletteRamOffset = (color & 0x7F) << 1;
colorIndex = (color & 0x7F);
} else {
paletteRamOffset = (_vram[(((tileIndex << 6) + ((yOffset & 0x07) << 3) + (xOffset & 0x07)) << 1) + 1]) << 1;
colorIndex = (_vram[(((tileIndex << 6) + ((yOffset & 0x07) << 3) + (xOffset & 0x07)) << 1) + 1]);
}
if(paletteRamOffset > 0) {
if(forMainScreen) {
DrawMainPixel<applyMosaic>(x, paletteRamOffset, pixelFlags);
if(colorIndex > 0) {
uint16_t paletteColor;
if(directColorMode) {
paletteColor = ((colorIndex & 0x07) << 2) | ((colorIndex & 0x38) << 4) | ((colorIndex & 0xC0) << 7);
} else {
DrawSubPixel(x, paletteRamOffset);
paletteColor = _cgram[colorIndex << 1] | (_cgram[(colorIndex << 1) + 1] << 8);
}
if(forMainScreen) {
DrawMainPixel<applyMosaic>(x, paletteColor, pixelFlags);
} else {
DrawSubPixel(x, paletteColor);
}
}
}
}
template<bool applyMosaic>
void Ppu::DrawMainPixel(uint8_t x, uint16_t paletteRamOffset, uint8_t flags)
void Ppu::DrawMainPixel(uint8_t x, uint16_t color, uint8_t flags)
{
_mainScreenBuffer[x] = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_mainScreenBuffer[x] = color;
_rowPixelFlags[x] = flags;
if(applyMosaic && x % _mosaicSize == 0) {
uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
//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;
_mosaicColor[x + i] = color;
}
}
_pixelsDrawn++;
}
void Ppu::DrawSubPixel(uint8_t x, uint16_t paletteRamOffset)
void Ppu::DrawSubPixel(uint8_t x, uint16_t color)
{
_subScreenBuffer[x] = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_subScreenBuffer[x] = color;
_subScreenFilled[x] = true;
_subPixelsDrawn++;
}

View file

@ -139,48 +139,47 @@ private:
template<uint8_t priority, bool forMainScreen>
void RenderSprites();
template<bool forMainScreen>
void RenderMode0();
template<bool forMainScreen>
void RenderMode1();
template<bool forMainScreen>
void RenderMode2();
template<bool forMainScreen>
void RenderMode3();
template<bool forMainScreen>
void RenderMode4();
template<bool forMainScreen>
void RenderMode5();
template<bool forMainScreen>
void RenderMode7();
template<bool forMainScreen> void RenderMode0();
template<bool forMainScreen> void RenderMode1();
template<bool forMainScreen> void RenderMode2();
template<bool forMainScreen> void RenderMode3();
template<bool forMainScreen> void RenderMode4();
template<bool forMainScreen> void RenderMode5();
template<bool forMainScreen> void RenderMode7();
void RenderScanline();
template<bool forMainScreen>
void RenderBgColor();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, bool largeTileWidth, bool largeTileHeight, uint16_t basePaletteOffset>
void RenderTilemapLargeTiles();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset = 0>
__forceinline void RenderTilemap();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight>
__forceinline void RenderTilemap();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount>
__forceinline void RenderTilemap();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount, bool applyMosaic>
__forceinline void RenderTilemap();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount, bool applyMosaic, bool directColorMode>
void RenderTilemap();
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, bool largeTileWidth, bool largeTileHeight, uint16_t basePaletteOffset, uint8_t activeWindowCount, bool applyMosaic>
void RenderTilemap();
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority>
__forceinline void RenderTilemapMode7();
template<uint8_t layerIndex, bool forMainScreen, bool applyMosaic, bool processHighPriority>
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic>
__forceinline void RenderTilemapMode7();
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic, bool directColorMode>
void RenderTilemapMode7();
template<bool applyMosaic>
__forceinline void DrawMainPixel(uint8_t x, uint16_t paletteRamOffset, uint8_t flags);
__forceinline void DrawMainPixel(uint8_t x, uint16_t color, uint8_t flags);
__forceinline void DrawSubPixel(uint8_t x, uint16_t paletteRamOffset);
__forceinline void DrawSubPixel(uint8_t x, uint16_t color);
void ApplyColorMath();