fix #723 "NTSC filter fix" on windows and commit

This commit is contained in:
zeromus 2016-03-29 05:40:51 +00:00
parent 82397025b2
commit eb0eb43468
8 changed files with 104 additions and 49 deletions

View File

@ -24,7 +24,7 @@ nes_ntsc_setup_t const nes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1,
#define alignment_count 3
#define burst_count 3
#define rescale_in 8
#define rescale_out 6
#define rescale_out 7
#define artifacts_mid 1.0f
#define fringing_mid 1.0f
@ -81,14 +81,13 @@ static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out )
}
}
void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp, int multiplier )
void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp )
{
int merge_fields;
int entry;
init_t impl;
float gamma_factor;
OutputMultiplier = multiplier;
OutputDepth = bpp * 8;
if ( !setup )
@ -244,18 +243,12 @@ void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp, in
#ifndef NES_NTSC_NO_BLITTERS
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_row_width,
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
int burst_phase, int emphasis, int in_width, int in_height, void* rgb_out, long out_pitch )
{
int chunk_count = (in_width - 1) / nes_ntsc_in_chunk;
int TempMultiplier = OutputMultiplier * 3;
if (TempMultiplier > 7)
TempMultiplier = 7;
for ( ; in_height; --in_height )
{
int out;
for ( out = OutputMultiplier; out; --out ) {
NES_NTSC_IN_T const* line_in = input;
NES_NTSC_BEGIN_ROW( ntsc, burst_phase, nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in ) );
nes_ntsc_out_t* restrict line_out = (nes_ntsc_out_t*) rgb_out;
@ -297,7 +290,6 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_
NES_NTSC_RGB_OUT( 5, line_out [5], OutputDepth );
NES_NTSC_RGB_OUT( 6, line_out [6], OutputDepth );
rgb_out = (char*) rgb_out + out_pitch;
}
burst_phase = (burst_phase + 1) % nes_ntsc_burst_count;
input += in_row_width;

View File

@ -54,15 +54,16 @@ extern nes_ntsc_setup_t const nes_ntsc_monochrome;/* desaturated + artifacts */
/* Initializes and adjusts parameters. Can be called multiple times on the same
nes_ntsc_t object. Can pass NULL for either parameter. */
typedef struct nes_ntsc_t nes_ntsc_t;
void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp, int multiplier );
void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp );
/* Filters one or more rows of pixels. Input pixels are 6/9-bit palette indicies.
In_row_width is the number of pixels to get to the next input row. Out_pitch
In_row_width is the number of pixels to get to the next input row. Emphasis is
the emphasis bits to bitwise-OR with all pixels in the input data. Out_pitch
is the number of *bytes* to get to the next output row. Output pixel format
is set by NES_NTSC_OUT_DEPTH (defaults to 16-bit RGB). */
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in,
long in_row_width, int burst_phase, int in_width, int in_height,
void* rgb_out, long out_pitch );
long in_row_width, int burst_phase, int emphasis, int in_width,
int in_height, void* rgb_out, long out_pitch );
/* Number of output pixels written by blitter for given input width. Width might
be rounded down slightly; use NES_NTSC_IN_WIDTH() on result to find rounded

View File

@ -5,7 +5,7 @@
/* Uncomment to enable emphasis support and use a 512 color palette instead
of the base 64 color palette. */
/*#define NES_NTSC_EMPHASIS 1*/
#define NES_NTSC_EMPHASIS 1
/* The following affect the built-in blitter only; a custom blitter can
handle things however it wants. */
@ -21,7 +21,7 @@ if you enable emphasis above. */
// CUSTOM: (XBuf uses bit 0x80, and has palettes above 0x3f for LUA)
/* Each raw pixel input value is passed through this. You might want to mask
the pixel index if you use the high bits as flags, etc. */
#define NES_NTSC_ADJ_IN( in ) in & 0x3f
#define NES_NTSC_ADJ_IN( in ) ((in & 0x3f) | emphasis)
/* For each pixel, this is the basic operation:
output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */

View File

@ -36,6 +36,8 @@ extern u8 *XDBuf;
extern u8 *XDBackBuf;
extern pal *palo;
#include "../../ppu.h" // for PPU[]
nes_ntsc_t* nes_ntsc;
uint8 burst_phase = 0;
@ -110,7 +112,6 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
// -Video Modes Tag-
if(specfilt == 3) // NTSC 2x
{
int multi = (2 * 2);
//nes_ntsc variables
nes_ntsc_setup_t ntsc_setup = nes_ntsc_composite;
@ -134,8 +135,8 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
if ( nes_ntsc )
{
nes_ntsc_init( nes_ntsc, &ntsc_setup, b, 2 );
ntscblit = (uint8*)FCEU_dmalloc(256*257*b*multi); //Need to add multiplier for larger sizes
nes_ntsc_init( nes_ntsc, &ntsc_setup, b );
ntscblit = (uint8*)FCEU_dmalloc(602*257*b);
}
} // -Video Modes Tag-
@ -799,14 +800,19 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
{
case 4:
if ( nes_ntsc && GameInfo->type!=GIT_NSF) {
int outxr = 301;
//if(xr == 282) outxr = 282; //hack for windows
burst_phase ^= 1;
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, xr, burst_phase, xr, yr, ntscblit, xr * Bpp * xscale );
//Multiply 4 by the multiplier on output, because it's 4 bpp
//Top 2 lines = line 3, due to distracting flicker
//memcpy(dest,ntscblit+(Bpp * xscale)+(Bpp * xr * xscale),(Bpp * xr * xscale));
//memcpy(dest+(Bpp * xr * xscale),ntscblit+(Bpp * xscale)+(Bpp * xr * xscale * 2),(Bpp * xr * xscale));
memcpy(dest+(Bpp * xr * xscale),ntscblit+(Bpp * xscale),(xr*yr*Bpp*xscale*yscale));
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, xr, burst_phase, (PPU[1] >> 5) << 6, xr, yr, ntscblit, (2*outxr) * Bpp );
const uint8 *in = ntscblit + (Bpp * xscale);
uint8 *out = dest;
const int in_stride = Bpp * outxr * 2;
const int out_stride = Bpp * outxr * xscale;
for( int y = 0; y < yr; y++, in += in_stride, out += 2*out_stride ) {
memcpy(out, in, Bpp * outxr * xscale);
memcpy(out + out_stride, in, Bpp * outxr * xscale);
}
} else {
pinc=pitch-((xr*xscale)<<2);
for(y=yr;y;y--,src+=256-xr)

View File

@ -342,7 +342,7 @@ InitVideo(FCEUGI *gi)
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
g_config->getOption("SDL.SpecialFX", &s_eefx);
// -Video Modes Tag-
if(s_sponge) {
if(s_sponge <= 3 && s_sponge >= 1)
@ -363,12 +363,20 @@ InitVideo(FCEUGI *gi)
{
s_exs = s_eys = 1;
}
if(s_sponge == 3) {
xres = 301 * s_exs;
}
s_eefx = 0;
if(s_sponge == 1 || s_sponge == 4) {
desbpp = 32;
}
}
int scrw = NWIDTH * s_exs;
if(s_sponge == 3) {
scrw = 301 * s_exs;
}
#ifdef OPENGL
if(!s_useOpenGL) {
s_exs = (int)s_exs;
@ -412,8 +420,7 @@ InitVideo(FCEUGI *gi)
}
#endif
s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs),
(int)(s_tlines * s_eys),
s_screen = SDL_SetVideoMode(scrw, (int)(s_tlines * s_eys),
desbpp, flags);
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
@ -691,6 +698,13 @@ BlitScreen(uint8 *XBuf)
SDL_UnlockSurface(TmpScreen);
}
int scrw;
if(s_sponge == 3) { // NTSC 2x
scrw = 301;
} else {
scrw = NWIDTH;
}
// if we have a hardware video buffer, do a fast video->video copy
if(s_BlitBuf) {
SDL_Rect srect;
@ -698,12 +712,12 @@ BlitScreen(uint8 *XBuf)
srect.x = 0;
srect.y = 0;
srect.w = NWIDTH;
srect.w = scrw;
srect.h = s_tlines;
drect.x = 0;
drect.y = 0;
drect.w = (Uint16)(s_exs * NWIDTH);
drect.w = (Uint16)(s_exs * scrw);
drect.h = (Uint16)(s_eys * s_tlines);
SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect);
@ -714,7 +728,7 @@ BlitScreen(uint8 *XBuf)
//TODO - SDL2
#else
SDL_UpdateRect(s_screen, xo, yo,
(Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys));
(Uint32)(scrw * s_exs), (Uint32)(s_tlines * s_eys));
#endif
#ifdef CREATE_AVI

View File

@ -11,6 +11,7 @@
#define VNSCLIP ((eoptions&EO_CLIPSIDES)?8:0)
#define VNSWID ((eoptions&EO_CLIPSIDES)?240:256)
#define VNSWID_NU(XR) (VNSWID==256?XR:((int)(XR/256.f*240)))
#define SO_FORCE8BIT 1
#define SO_SECONDARY 2

View File

@ -237,7 +237,13 @@ void recalculateBestFitRect(int width, int height)
if (!lpDD7)
return; // DirectDraw isn't initialized yet
double screen_width = VNSWID;
int xres = 256;
if(fullscreen && vmodes[0].special==3)
xres=301;
if(!fullscreen && winspecial==3)
xres=301;
double screen_width = VNSWID_NU(xres);
double screen_height = FSettings.TotalScanlines();
if (eoptions & EO_TVASPECT)
screen_width = ceil(screen_height * (screen_width / 256) * (tvAspectX / tvAspectY));
@ -314,6 +320,7 @@ int SetVideoMode(int fs)
if(!fs)
{
int xres = 256;
// -Video Modes Tag-
if(winspecial <= 3 && winspecial >= 1)
specmul = 2;
@ -326,6 +333,9 @@ int SetVideoMode(int fs)
else
specmul = 1;
if(winspecial == 3)
xres = 301;
ShowCursorAbs(1);
windowedfailed=1;
HideFWindow(0);
@ -357,7 +367,7 @@ int SetVideoMode(int fs)
ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
ddsdback.dwWidth=256 * specmul;
ddsdback.dwWidth=xres*specmul;
ddsdback.dwHeight=FSettings.TotalScanlines() * ((winspecial == 9) ? 1 : specmul);
if (directDrawModeWindowed == DIRECTDRAW_MODE_SURFACE_IN_RAM)
@ -414,6 +424,8 @@ int SetVideoMode(int fs)
}
else
{
int xres = 256;
//Following is full-screen
if(vmod == 0) // Custom mode
{
@ -428,6 +440,9 @@ int SetVideoMode(int fs)
specmul = 3;
else
specmul = 1;
if(vmodes[0].special==3)
xres = 301;
}
HideFWindow(1);
@ -453,7 +468,7 @@ int SetVideoMode(int fs)
ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
ddsdback.dwWidth=256 * specmul; //vmodes[vmod].srect.right;
ddsdback.dwWidth=xres * specmul; //vmodes[vmod].srect.right;
ddsdback.dwHeight=FSettings.TotalScanlines() * ((vmodes[0].special == 9) ? 1 : specmul); //vmodes[vmod].srect.bottom;
if (directDrawModeFullscreen == DIRECTDRAW_MODE_SURFACE_IN_RAM)
@ -586,6 +601,7 @@ static void BlitScreenWindow(unsigned char *XBuf)
if (!lpDDSBack) return;
// -Video Modes Tag-
int xres = 256;
if(winspecial <= 3 && winspecial >= 1)
specialmul = 2;
else if(winspecial >= 4 && winspecial <= 5)
@ -596,8 +612,11 @@ static void BlitScreenWindow(unsigned char *XBuf)
specialmul = 3;
else specialmul = 1;
if(winspecial == 3)
xres = 301;
srect.top=srect.left=0;
srect.right=VNSWID * specialmul;
srect.right=VNSWID_NU(xres) * specialmul;
srect.bottom=FSettings.TotalScanlines() * ((winspecial == 9) ? 1 : specialmul);
if(PaletteChanged==1)
@ -625,7 +644,10 @@ static void BlitScreenWindow(unsigned char *XBuf)
memset(ScreenLoc,0,pitch*ddsdback.dwHeight);
veflags&=~1;
}
Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,specialmul,specialmul);
//NOT VNSWID_NU ON PURPOSE! this is where 256 gets turned to 301
//we'll actually blit a subrectangle later if we clipped the sides
//MOREOVER: we order this to scale the whole area no matter what; a subrectangle will come out later (right?)
Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,ScreenLoc, 256, FSettings.TotalScanlines(), pitch,specialmul,specialmul);
IDirectDrawSurface7_Unlock(lpDDSBack, NULL);
@ -727,6 +749,7 @@ static void BlitScreenFull(uint8 *XBuf)
//uint8 y; //mbg merge 7/17/06 removed
RECT srect, drect;
LPDIRECTDRAWSURFACE7 lpDDSVPrimary;
int xres = 256;
int specmul; // Special scaler size multiplier
// -Video Modes Tag-
if(vmodes[0].special <= 3 && vmodes[0].special >= 1)
@ -740,6 +763,9 @@ static void BlitScreenFull(uint8 *XBuf)
else
specmul = 1;
if(vmodes[0].special == 3)
xres = 301;
if(fssync==3)
lpDDSVPrimary=lpDDSDBack;
else
@ -778,7 +804,7 @@ static void BlitScreenFull(uint8 *XBuf)
srect.top=0;
srect.left=0;
srect.right=VNSWID * specmul;
srect.right=VNSWID_NU(xres) * specmul;
srect.bottom=FSettings.TotalScanlines() * ((vmodes[0].special == 9) ? 1 : specmul);
//if(vmodes[vmod].flags&VMDF_STRFS)
@ -955,21 +981,21 @@ static void BlitScreenFull(uint8 *XBuf)
if(vmodes[vmod].special)
ScreenLoc += (vmodes[vmod].drect.left*(bpp>>3)) + ((vmodes[vmod].drect.top)*pitch);
else
ScreenLoc+=((vmodes[vmod].x-VNSWID)>>1)*(bpp>>3)+(((vmodes[vmod].y-FSettings.TotalScanlines())>>1))*pitch;
ScreenLoc+=((vmodes[vmod].x-VNSWID_NU(xres))>>1)*(bpp>>3)+(((vmodes[vmod].y-FSettings.TotalScanlines())>>1))*pitch;
}
if(bpp>=16)
{
Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,specmul,specmul); //mbg merge 7/17/06 added cast
Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,(uint8*)ScreenLoc, VNSWID_NU(xres), FSettings.TotalScanlines(), pitch,specmul,specmul); //mbg merge 7/17/06 added cast
}
else
{
XBuf+=FSettings.FirstSLine*256+VNSCLIP;
// -Video Modes Tag-
if(vmodes[vmod].special)
Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,vmodes[vmod].xscale,vmodes[vmod].yscale,0,vmodes[vmod].special); //mbg merge 7/17/06 added cast
Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID_NU(xres), FSettings.TotalScanlines(), pitch,vmodes[vmod].xscale,vmodes[vmod].yscale,0,vmodes[vmod].special); //mbg merge 7/17/06 added cast
else
Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,1,1,0,0); //mbg merge 7/17/06 added cast
Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID_NU(xres), FSettings.TotalScanlines(), pitch,1,1,0,0); //mbg merge 7/17/06 added cast
}
}
@ -1115,6 +1141,9 @@ static int RecalcCustom(void)
{
vmdef *cmode = &vmodes[0];
//don't see how ntsc could make it through here
int xres = 256;
if ((cmode->x <= 0) || (cmode->y <= 0))
ResetCustomMode();
@ -1140,7 +1169,7 @@ static int RecalcCustom(void)
cmode->flags|=VMDF_DXBLT;
if(VNSWID*cmode->xscale>cmode->x)
if(VNSWID_NU(xres)*cmode->xscale>cmode->x)
{
if(cmode->special)
{
@ -1175,8 +1204,8 @@ static int RecalcCustom(void)
cmode->drect.top=(cmode->y-(FSettings.TotalScanlines()*cmode->yscale))>>1;
cmode->drect.bottom=cmode->drect.top+FSettings.TotalScanlines()*cmode->yscale;
cmode->drect.left=(cmode->x-(VNSWID*cmode->xscale))>>1;
cmode->drect.right=cmode->drect.left+VNSWID*cmode->xscale;
cmode->drect.left=(cmode->x-(VNSWID_NU(xres)*cmode->xscale))>>1;
cmode->drect.right=cmode->drect.left+VNSWID_NU(xres)*cmode->xscale;
}
// -Video Modes Tag-
@ -1187,7 +1216,7 @@ static int RecalcCustom(void)
//return(0);
}
if(cmode->x<VNSWID)
if(cmode->x<VNSWID_NU(xres))
{
FCEUD_PrintError("Horizontal resolution is too low.");
return(0);

View File

@ -335,7 +335,13 @@ static void ConvertFCM(HWND hwndOwner)
void CalcWindowSize(RECT *al)
{
double screen_width = VNSWID;
int xres = 256;
if(fullscreen && vmodes[0].special==3)
xres=301;
if(!fullscreen && winspecial==3)
xres=301;
double screen_width = VNSWID_NU(xres);
double screen_height = FSettings.TotalScanlines();
if (eoptions & EO_TVASPECT)
screen_width = ceil(screen_height * (screen_width / 256) * (tvAspectX / tvAspectY));
@ -1129,7 +1135,13 @@ void GetMouseData(uint32 (&md)[3])
{
extern RECT bestfitRect;
double screen_width = VNSWID;
int xres = 256;
if(fullscreen && vmodes[0].special==3)
xres=301;
if(!fullscreen && winspecial==3)
xres=301;
double screen_width = VNSWID_NU(xres);
double screen_height = FSettings.TotalScanlines();
if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left))