HD Packs: Added support for grayscale and emphasis bits

This commit is contained in:
Sour 2018-03-11 22:42:32 -04:00
parent dac2af2294
commit fda119afca
4 changed files with 61 additions and 0 deletions

View file

@ -96,6 +96,8 @@ struct HdPpuPixelInfo
uint16_t TmpVideoRamAddr;
uint8_t XScroll;
uint8_t EmphasisBits;
bool Grayscale;
HdPpuPixelInfo()
{

View file

@ -358,9 +358,65 @@ void HdNesPack::Process(HdScreenInfo *hdScreenInfo, uint32_t* outputBuffer, Over
for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) {
OnLineStart(hdScreenInfo->ScreenTiles[i << 8]);
uint32_t bufferIndex = (i - overscan.Top) * screenWidth * hdScale;
uint32_t lineStartIndex = bufferIndex;
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
GetPixels(j, i, hdScreenInfo->ScreenTiles[i * 256 + j], outputBuffer + bufferIndex, screenWidth);
bufferIndex += hdScale;
}
ProcessGrayscaleAndEmphasis(hdScreenInfo->ScreenTiles[i * 256], outputBuffer + lineStartIndex, screenWidth);
}
}
void HdNesPack::ProcessGrayscaleAndEmphasis(HdPpuPixelInfo &pixelInfo, uint32_t* outputBuffer, uint32_t hdScreenWidth)
{
//Apply grayscale/emphasis bits on a scanline level (less accurate, but shouldn't cause issues and simpler to implement)
uint32_t scale = GetScale();
if(pixelInfo.Grayscale) {
uint32_t* out = outputBuffer;
for(uint32_t y = 0; y < scale; y++) {
for(uint32_t x = 0; x < hdScreenWidth; x++) {
uint32_t &rgbValue = out[x];
uint8_t average = (((rgbValue >> 16) & 0xFF) + ((rgbValue >> 8) & 0xFF) + (rgbValue & 0xFF)) / 3;
rgbValue = (rgbValue & 0xFF000000) | (average << 16) | (average << 8) | average;
}
out += hdScreenWidth;
}
}
if(pixelInfo.EmphasisBits) {
uint8_t emphasisBits = pixelInfo.EmphasisBits;
double red = 1.0, green = 1.0, blue = 1.0;
if(emphasisBits & 0x01) {
//Intensify red
red *= 1.1;
green *= 0.9;
blue *= 0.9;
}
if(emphasisBits & 0x02) {
//Intensify green
green *= 1.1;
red *= 0.9;
blue *= 0.9;
}
if(emphasisBits & 0x04) {
//Intensify blue
blue *= 1.1;
red *= 0.9;
green *= 0.9;
}
uint32_t* out = outputBuffer;
for(uint32_t y = 0; y < scale; y++) {
for(uint32_t x = 0; x < hdScreenWidth; x++) {
uint32_t &rgbValue = out[x];
rgbValue = 0xFF000000 |
(std::min<uint16_t>((uint16_t)(((rgbValue >> 16) & 0xFF) * red), 255) << 16) |
(std::min<uint16_t>((uint16_t)(((rgbValue >> 8) & 0xFF) * green), 255) << 8) |
std::min<uint16_t>((uint16_t)((rgbValue & 0xFF) * blue), 255);
}
out += hdScreenWidth;
}
}
}

View file

@ -30,6 +30,7 @@ private:
void OnLineStart(HdPpuPixelInfo &lineFirstPixel);
void OnBeforeApplyFilter();
__forceinline void GetPixels(uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uint32_t *outputBuffer, uint32_t screenWidth);
__forceinline void ProcessGrayscaleAndEmphasis(HdPpuPixelInfo &pixelInfo, uint32_t* outputBuffer, uint32_t hdScreenWidth);
public:
static const uint32_t CurrentVersion = 101;

View file

@ -36,6 +36,8 @@ protected:
HdPpuPixelInfo &tileInfo = _info->ScreenTiles[bufferOffset];
tileInfo.Grayscale = _paletteRamMask == 0x30;
tileInfo.EmphasisBits = _intensifyColorBits >> 6;
tileInfo.Tile.PpuBackgroundColor = ReadPaletteRAM(0);
tileInfo.Tile.BgColorIndex = backgroundColor;
if(backgroundColor == 0) {