diff --git a/trunk/src/drivers/common/vidblit.cpp b/trunk/src/drivers/common/vidblit.cpp index 6bc2b109..d3086f29 100644 --- a/trunk/src/drivers/common/vidblit.cpp +++ b/trunk/src/drivers/common/vidblit.cpp @@ -41,36 +41,49 @@ uint8 burst_phase = 0; static uint32 CBM[3]; static uint32 *palettetranslate=0; - -static uint16 *specbuf=NULL; // 8bpp -> 16bpp, pre hq2x/hq3x -static uint32 *specbuf32bpp = NULL; // Buffer to hold output of hq2x/hq3x when converting to 16bpp and 24bpp static int backBpp, backshiftr[3], backshiftl[3]; +static int silt; +static int Bpp; // BYTES per pixel +static int highefx; //static uint32 backmask[3]; +static uint16 *specbuf=NULL; // 8bpp -> 16bpp, pre hq2x/hq3x +static uint32 *specbuf32bpp= NULL; // Buffer to hold output of hq2x/hq3x when converting to 16bpp and 24bpp 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 = 100; -int palnotch = 100; -int palsharpness = 50; -bool palhdtv = 0; -bool palmonochrome = 0; -bool palupdate = 1; -bool paldeemphswap = 0; -static int silt; - -static int Bpp; // BYTES per pixel -static int highefx; +////////////////////// +// PAL filter start // +////////////////////// +#define PAL_PHASES 108 // full vertical subcarrier cycle for 3x resolution (18) * full horizontal cycle (6) +static uint32 *palrgb = NULL; // buffer for lookup values of RGB with applied moir phases +static uint32 *palrgb2 = NULL; // buffer for lookup values of blended moir phases +static float *moire = NULL; // modulated signal +const float phasex = (float) 5/18*2; +const float phasey = (float) 1/ 6*2; +const float pi = 3.14f; +int palnotch = 90; +int palsaturation = 100; +int palsharpness = 50; +int palcontrast = 100; +int palbrightness = 50; +bool palupdate = 1; +bool paldeemphswap = 0; static int Round(float value) { return (int) floor(value + 0.5); } +static int PAL_LUT(uint32 *buffer, int index, int x, int y) +{ + return buffer[index*PAL_PHASES + (x%18) + 18*(y%6)]; +} +//////////////////// +// PAL filter end // +//////////////////// + static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl) { int a,x,z,y; @@ -191,9 +204,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)); - palrgb2 = (uint32 *)FCEU_dmalloc((256+512)*16*sizeof(uint32)); - moire = (float *)FCEU_dmalloc( 16*sizeof(float)); + palrgb = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32)); + palrgb2 = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32)); + moire = (float *)FCEU_dmalloc( PAL_PHASES*sizeof(float)); paldeemphswap = 1; } @@ -466,53 +479,6 @@ 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; @@ -633,94 +599,74 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, } else if (palrgb) // pal moire { - // 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 + // skip usual palette translation, fill lookup array of RGB+moire values per palette update, and send directly to DX dest + // written by feos in 2015, credits to HardWareMan and r57shell if (palupdate) { uint8 *source = (uint8 *)palettetranslate; int16 R,G,B; float Y,U,V; + float alpha; float sat = (float) palsaturation/100; - bool hdtv = palhdtv; - bool monochrome = palmonochrome; + float contrast = (float) palcontrast/100; + int bright = palbrightness - 50; int notch = palnotch; int unnotch = 100 - palnotch; - int mixR[16], mixG[16], mixB[16]; + int mixR[PAL_PHASES], mixG[PAL_PHASES], mixB[PAL_PHASES]; for (int i=0; i<256+512; i++) { + // fetch color R = source[i*4 ]; G = source[i*4+1]; B = source[i*4+2]; - if (hdtv) // HDTV BT.709 + // rgb -> yuv, 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; + + // all variants of this color + for (int x=0; x<18; x++) { - 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 - { - 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; + for (y=0; y<6; y++) + { + alpha = (x*phasex + y*phasey)*pi; // 2*pi*freq*t + if (y%2 == 0) alpha = -alpha; // phase alternating line! + moire[x+y*18] = Y + U*sin(alpha) + V*cos(alpha); // modulated composite signal + } } - if (Y == 0) Y = 1; - if (monochrome) sat = 0; - - // WARNING: phase order is magical! - moire[0] = (U == 0 && V == 0) ? 1 : (Y + V)/Y; - moire[1] = (U == 0 && V == 0) ? 1 : (Y + U)/Y; - moire[2] = (U == 0 && V == 0) ? 1 : (Y - V)/Y; - moire[3] = (U == 0 && V == 0) ? 1 : (Y - U)/Y; - moire[4] = (U == 0 && V == 0) ? 1 : (Y - V)/Y; - moire[5] = (U == 0 && V == 0) ? 1 : (Y + U)/Y; - moire[6] = (U == 0 && V == 0) ? 1 : (Y + V)/Y; - moire[7] = (U == 0 && V == 0) ? 1 : (Y - U)/Y; - moire[8] = (U == 0 && V == 0) ? 1 : (Y - V)/Y; - moire[9] = (U == 0 && V == 0) ? 1 : (Y - U)/Y; - moire[10] = (U == 0 && V == 0) ? 1 : (Y + V)/Y; - moire[11] = (U == 0 && V == 0) ? 1 : (Y + U)/Y; - moire[12] = (U == 0 && V == 0) ? 1 : (Y + V)/Y; - 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; - - for (int j=0; j<16; j++) + for (int j=0; j rgb, sdtv bt.601 + R = Round(moire[j]*contrast+bright + 1.13983*V*sat); + G = Round(moire[j]*contrast+bright - 0.39465*U*sat - 0.58060*V*sat); + B = Round(moire[j]*contrast+bright + 2.03211*U*sat ); + // clamp if (R > 0xff) R = 0xff; else if (R < 0) R = 0; if (G > 0xff) G = 0xff; else if (G < 0) G = 0; if (B > 0xff) B = 0xff; else if (B < 0) B = 0; + // store colors to mix mixR[j] = R; mixG[j] = G; mixB[j] = B; - palrgb[i*16+j] = (B<<16)|(G<<8)|R; + // moirecolor + palrgb[i*PAL_PHASES+j] = (B<<16)|(G<<8)|R; } - for (int j=0; j<16; j++) + for (int j=0; j