diff --git a/trunk/src/drivers/common/vidblit.cpp b/trunk/src/drivers/common/vidblit.cpp index 8a7ed715..4450ed42 100644 --- a/trunk/src/drivers/common/vidblit.cpp +++ b/trunk/src/drivers/common/vidblit.cpp @@ -50,9 +50,11 @@ static uint8 *specbuf8bpp = NULL; // For 2xscale, 3xscale. static uint8 *ntscblit = NULL; // For nes_ntsc static uint32 *prescalebuf = NULL; // Prescale pointresizes to 2x-4x to allow less blur with hardware acceleration. static uint32 *palrgb = NULL; // PAL filter buffer for lookup values of RGB with applied moir phases +static uint32 *palrgb2 = NULL; // PAL filter buffer for lookup values of blended moir phases static float *moire = NULL; -int palsaturation = 200; -int palnotch = 64; +int palsaturation = 100; +int palnotch = 100; +int palsharpness = 50; bool palhdtv = 0; bool palmonochrome = 0; bool palupdate = 1; @@ -188,8 +190,9 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int } else if (specfilt == 9) { - palrgb = (uint32 *)FCEU_dmalloc((256+512)*16*sizeof(uint32)); - moire = (float *)FCEU_dmalloc( 16*sizeof(float)); + palrgb = (uint32 *)FCEU_dmalloc((256+512)*16*sizeof(uint32)); + palrgb2 = (uint32 *)FCEU_dmalloc((256+512)*16*sizeof(uint32)); + moire = (float *)FCEU_dmalloc( 16*sizeof(float)); paldeemphswap = 1; } @@ -255,6 +258,10 @@ void KillBlitToHigh(void) if (palrgb) { free(palrgb); palrgb = NULL; + free(palrgb2); + palrgb2 = NULL; + free(moire); + moire = NULL; } } @@ -458,6 +465,53 @@ u32 ModernDeemphColorMap(u8* src) return color; } +int PAL_LUT(uint32 *buffer, int index, int x, int y) +{ + int color = 0; + + switch (y&3) + { + case 0: + switch (x&3) + { + case 0: color = buffer[index*16 ]; break; + case 1: color = buffer[index*16+ 1]; break; + case 2: color = buffer[index*16+ 2]; break; + case 3: color = buffer[index*16+ 3]; break; + } + break; + case 1: + switch (x&3) + { + case 0: color = buffer[index*16+ 4]; break; + case 1: color = buffer[index*16+ 5]; break; + case 2: color = buffer[index*16+ 6]; break; + case 3: color = buffer[index*16+ 7]; break; + } + break; + case 2: + switch (x&3) + { + case 0: color = buffer[index*16+ 8]; break; + case 1: color = buffer[index*16+ 9]; break; + case 2: color = buffer[index*16+10]; break; + case 3: color = buffer[index*16+11]; break; + } + break; + case 3: + switch (x&3) + { + case 0: color = buffer[index*16+12]; break; + case 1: color = buffer[index*16+13]; break; + case 2: color = buffer[index*16+14]; break; + case 3: color = buffer[index*16+15]; break; + } + break; + } + + return color; +} + void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale) { int x,y; @@ -581,30 +635,39 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, // skip usual palette translation, fill lookup array of RGB+moire values per palette update, and send directly to DX dest. // hardcoded resolution is 768x240, makes moire mask cleaner, even though PAL consoles generate it at native res. // source of this whole idea: http://forum.emu-russia.net/viewtopic.php?p=9410#p9410 - if (palupdate) { + if (palupdate) + { uint8 *source = (uint8 *)palettetranslate; int16 R,G,B; float Y,U,V; float sat = (float) palsaturation/100; bool hdtv = palhdtv; bool monochrome = palmonochrome; + int notch = palnotch; + int unnotch = 100 - palnotch; + int mixR[16], mixG[16], mixB[16]; - for (int i=0; i<256+512; i++) { + for (int i=0; i<256+512; i++) + { R = source[i*4 ]; G = source[i*4+1]; B = source[i*4+2]; - if (hdtv) { // HDTV BT.709 + if (hdtv) // HDTV BT.709 + { Y = 0.2126 *R + 0.7152 *G + 0.0722 *B; // Y' U = -0.09991*R - 0.33609*G + 0.436 *B; // B-Y V = 0.615 *R - 0.55861*G - 0.05639*B; // R-Y - } else { // SDTV BT.601 + } + else // SDTV BT.601 + { Y = 0.299 *R + 0.587 *G + 0.114 *B; U = -0.14713*R - 0.28886*G + 0.436 *B; V = 0.615 *R - 0.51499*G - 0.10001*B; } if (Y == 0) Y = 1; + if (monochrome) sat = 0; // WARNING: phase order is magical! moire[0] = (U == 0 && V == 0) ? 1 : (Y + V)/Y; @@ -623,16 +686,17 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, moire[13] = (U == 0 && V == 0) ? 1 : (Y - U)/Y; moire[14] = (U == 0 && V == 0) ? 1 : (Y - V)/Y; moire[15] = (U == 0 && V == 0) ? 1 : (Y + U)/Y; - - if (monochrome) - sat = 0; - for (int j=0; j<16; j++) { - if (hdtv) { // HDTV BT.709 + for (int j=0; j<16; j++) + { + if (hdtv) // HDTV BT.709 + { R = Round((Y + 1.28033*V*sat)*moire[j]); G = Round((Y - 0.21482*U*sat - 0.38059*V*sat)*moire[j]); B = Round((Y + 2.12798*U*sat )*moire[j]); - } else { // SDTV BT.601 + } + else // SDTV BT.601 + { R = Round((Y + 1.13983*V*sat)*moire[j]); G = Round((Y - 0.39465*U*sat - 0.58060*V*sat)*moire[j]); B = Round((Y + 2.03211*U*sat )*moire[j]); @@ -642,109 +706,114 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, if (G > 0xff) G = 0xff; else if (G < 0) G = 0; if (B > 0xff) B = 0xff; else if (B < 0) B = 0; + mixR[j] = R; + mixG[j] = G; + mixB[j] = B; + palrgb[i*16+j] = (B<<16)|(G<<8)|R; } + + for (int j=0; j<16; j++) + { + R = (mixR[j]*unnotch + (mixR[0]+mixR[1]+mixR[2]+mixR[3])/4*notch)/100; + G = (mixG[j]*unnotch + (mixG[0]+mixG[1]+mixG[2]+mixG[3])/4*notch)/100; + B = (mixB[j]*unnotch + (mixB[0]+mixB[1]+mixB[2]+mixB[3])/4*notch)/100; + + palrgb2[i*16+j] = (B<<16)|(G<<8)|R; + } } palupdate = 0; } - if (Bpp == 4) { + if (Bpp == 4) + { uint32 *d = (uint32 *)dest; - uint8 xsub = 0; - uint8 xabs = 0; - uint32 index = 0; + uint8 xsub = 0; + uint8 xabs = 0; + uint32 index = 0; uint32 lastindex = 0; - uint32 newindex = 0; - uint32 color, lastcolor, realcolor; - int notch = palnotch; - int unnotch = 100 - palnotch; - int rmask = 0xff0000; - int gmask = 0x00ff00; - int bmask = 0x0000ff; - int r, g, b; + uint32 newindex = 0; + int sharp = palsharpness; + int unsharp = 100 - palsharpness; + int rmask = 0xff0000; + int gmask = 0x00ff00; + int bmask = 0x0000ff; + int r, g, b, ofs; + uint8 deemph; + uint32 color, moirecolor, notchcolor, finalcolor, lastcolor = 0; - for (y=0; y