support 512 color palettes, add support for proper deemph emulation on some codepaths. need to fix png saving and maybe other stuff

This commit is contained in:
zeromus 2015-09-12 03:44:08 +00:00
parent 314aaff2e1
commit 96078b99ac
16 changed files with 291 additions and 174 deletions

View File

@ -68,7 +68,7 @@ void FCEUI_NTSCSELTINT(void);
void FCEUI_NTSCDEC(void);
void FCEUI_NTSCINC(void);
void FCEUI_GetNTSCTH(int *tint, int *hue);
void FCEUI_SetNTSCTH(int n, int tint, int hue);
void FCEUI_SetNTSCTH(bool en, int tint, int hue);
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
@ -141,9 +141,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
void FCEUI_SetBaseDirectory(std::string const & dir);
//Tells FCE Ultra to copy the palette data pointed to by pal and use it.
//Data pointed to by pal needs to be 64*3 bytes in length.
void FCEUI_SetPaletteArray(uint8 *pal);
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
//Sets up sound code to render sound at the specified rate, in samples
//per second. Only sample rates of 44100, 48000, and 96000 are currently supported.

View File

@ -25,9 +25,16 @@
#include "hq3x.h"
#include "../../types.h"
#include "../../palette.h"
#include "../../utils/memory.h"
#include "nes_ntsc.h"
extern u8 *XBuf;
extern u8 *XBackBuf;
extern u8 *XDBuf;
extern u8 *XDBackBuf;
extern pal *palo;
nes_ntsc_t* nes_ntsc;
uint8 burst_phase = 0;
@ -203,17 +210,17 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
if(efx&FVB_BLUR)
{
if(Bpp==2)
palettetranslate=(uint32 *)FCEU_dmalloc(65536*4);
else if(Bpp>=3)
//if(Bpp==2)
// palettetranslate=(uint32 *)FCEU_dmalloc(65536*4);
//else if(Bpp>=3)
palettetranslate=(uint32 *)FCEU_dmalloc(65536*4);
}
else
{
if(Bpp==2)
palettetranslate=(uint32*)FCEU_dmalloc(65536*4);
else if(Bpp>=3)
palettetranslate=(uint32*)FCEU_dmalloc(256*4);
//if(Bpp==2)
// palettetranslate=(uint32*)FCEU_dmalloc(65536*4);
//else if(Bpp>=3)
palettetranslate=(uint32*)FCEU_dmalloc(256*4 + 512*4);
}
if(!palettetranslate)
@ -340,6 +347,7 @@ void SetPaletteBlitToHigh(uint8 *src)
palettetranslate[x]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
}
else
{
for(y=0;y<256;y++)
{
r=src[x<<2]*(100-BLUR_RED);
@ -359,6 +367,17 @@ void SetPaletteBlitToHigh(uint8 *src)
palettetranslate[x|(y<<8)]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
}
}
}
//full size deemph palette (breaks blur shit)
for(x=0;x<512;x++)
{
uint32 r,g,b;
r=palo[x].r;
g=palo[x].g;
b=palo[x].b;
palettetranslate[256+x]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
}
break;
}
@ -507,6 +526,25 @@ void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, in
/* Todo: Make sure 24bpp code works right with big-endian cpus */
//takes a pointer to XBuf and applies fully modern deemph palettizing
u32 ModernDeemphColorMap(u8* src)
{
u8 pixel = *src;
//look up the legacy translation
u32 color = palettetranslate[pixel];
//find out which deemph bitplane value we're on
int ofs = src-XBuf;
uint8 deemph = XDBuf[ofs];
//if it was a deemph'd value, grab it from the deemph palette
if(deemph != 0)
color = palettetranslate[256+(pixel&0x3F)+deemph*64];
return color;
}
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale)
{
int x,y;
@ -1036,7 +1074,8 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
{
for(x=xr;x;x--)
{
*(uint32 *)dest=palettetranslate[(uint32)*src];
//THE MAIN BLITTING CODEPATH (there may be others that are important)
*(uint32 *)dest = ModernDeemphColorMap(src);
dest+=4;
src++;
}

View File

@ -35,7 +35,7 @@ extern int eoptions;
#define EO_BGRUN 1
#define EO_CPALETTE 4
#define EO_CPALETTE 4 //this is bad, it is desynchronized from other state management in palette.cpp
#define EO_NOSPRLIM 8
#define EO_FSAFTERLOAD 32
#define EO_FOAFTERSTART 64

View File

@ -174,7 +174,7 @@ static CFGSTRUCT fceuconfig[] =
ACS(ResumeROM),
AC(gNoBGFillColor),
AC(ntsccol),AC(ntsctint),AC(ntschue),
AC(ntsccol_enable),AC(ntsctint),AC(ntschue),
AC(force_grayscale),
AC(dendy),
AC(extrascanlines),
@ -470,7 +470,7 @@ void LoadConfig(const char *filename)
LoadFCEUConfig(filename, fceuconfig);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
//adelikat:Hacky fix for Ram Watch recent menu
for (int x = 0; x < 5; x++)

View File

@ -683,10 +683,11 @@ int main(int argc,char *argv[])
DoVideoConfigFix();
DoTimingConfigFix();
if(eoptions & EO_CPALETTE)
{
FCEUI_SetPaletteArray(cpalette);
}
//TODO - how can this do anything? we havent set a palette yet
//if(eoptions & EO_CPALETTE)
//{
// FCEUI_SetUserPalette(cpalette);
//}
if(!t)
{

View File

@ -107,13 +107,14 @@ extern int soundquality;
extern bool muteTurbo;
extern bool swapDuty;
extern uint8 cpalette[192];
extern uint8 cpalette[64*8*3];
extern int srendlinen;
extern int erendlinen;
extern int srendlinep;
extern int erendlinep;
extern int ntsccol, ntsctint, ntschue;
extern int ntsctint, ntschue;
extern bool ntsccol_enable;
extern bool force_grayscale;
//mbg merge 7/17/06 did these have to be unsigned?

View File

@ -4,7 +4,7 @@
#include "window.h"
#include "gui.h"
uint8 cpalette[192] = {0};
u8 cpalette[64*8*3] = {0};
extern int palhue;
extern bool palhdtv;
extern bool palprecision;
@ -15,9 +15,9 @@ bool SetPalette(const char* nameo)
FILE *fp;
if((fp = FCEUD_UTF8fopen(nameo, "rb")))
{
fread(cpalette, 1, 192, fp);
int readed = fread(cpalette, 1, sizeof(cpalette), fp);
fclose(fp);
FCEUI_SetPaletteArray(cpalette);
FCEUI_SetUserPalette(cpalette,readed/3);
eoptions |= EO_CPALETTE;
return true;
}
@ -71,7 +71,7 @@ BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
{
case WM_INITDIALOG:
if(ntsccol)
if(ntsccol_enable)
CheckDlgButton(hwndDlg, CHECK_PALETTE_ENABLED, BST_CHECKED);
SendDlgItemMessage(hwndDlg, CTL_TINT_TRACKBAR, TBM_SETRANGE, 1, MAKELONG(0, 128));
@ -106,7 +106,7 @@ BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
ntsctint = SendDlgItemMessage(hwndDlg, CTL_TINT_TRACKBAR, TBM_GETPOS, 0, (LPARAM)(LPSTR)0);
ntschue = SendDlgItemMessage(hwndDlg, CTL_HUE_TRACKBAR, TBM_GETPOS, 0, (LPARAM)(LPSTR)0);
palhue = SendDlgItemMessage(hwndDlg, CTL_PALHUE_TRACKBAR, TBM_GETPOS, 0, (LPARAM)(LPSTR)0);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
sprintf(text, "Hue: %d%%", palhue);
SendDlgItemMessage(hwndDlg, STATIC_HUEVALUE, WM_SETTEXT, 0, (LPARAM) text);
break;
@ -121,13 +121,13 @@ BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
switch(wParam&0xFFFF)
{
case CHECK_PALETTE_ENABLED:
ntsccol ^= 1;
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue); // it recalculates everything, use it for PAL block too!
ntsccol_enable ^= true;
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue); // it recalculates everything, use it for PAL block too!
break;
case CHECK_PALETTE_GRAYSCALE:
force_grayscale ^= 1;
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
break;
case BTN_PALETTE_LOAD:
@ -140,30 +140,30 @@ BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
SendDlgItemMessage(hwndDlg, CTL_PALHUE_TRACKBAR, TBM_SETPOS, 1, palhue);
sprintf(text, "Hue: %d%%", palhue);
SendDlgItemMessage(hwndDlg, STATIC_HUEVALUE, WM_SETTEXT, 0, (LPARAM) text);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
break;
case CHECK_PALETTE_MONOCHROME:
palmonochrome ^= 1;
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
break;
case CHECK_PALETTE_HDTV:
palhdtv ^= 1;
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
FCEUI_SetNTSCTH(ntsccol_enable, ntsctint, ntschue);
break;
case CHECK_PALETTE_CUSTOM:
{
if (eoptions & EO_CPALETTE)
{
// switch back to default palette
FCEUI_SetPaletteArray(0);
//disable user palette
FCEUI_SetUserPalette(0,0);
eoptions &= ~EO_CPALETTE;
} else
{
// switch to custom, even if it isn't loaded yet
FCEUI_SetPaletteArray(cpalette);
//switch to user palette (even if it isn't loaded yet!?)
FCEUI_SetUserPalette(cpalette,64); //just have to guess the size I guess
eoptions |= EO_CPALETTE;
}
break;

View File

@ -227,27 +227,8 @@ static int InitBPPStuff(int fs)
break;
}
if(bpp >= 16)
{
InitBlitToHigh(bpp >> 3, CBM[0], CBM[1], CBM[2], 0, fs?vmodes[vmod].special:winspecial,specfilteropt);
}
else if(bpp==8)
{
ddrval=IDirectDraw7_CreatePalette( lpDD7, DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,color_palette,&lpddpal,NULL);
if (ddrval != DD_OK)
{
//ShowDDErr("Error creating palette object.");
FCEU_printf("Error creating palette object.\n");
return 0;
}
ddrval=IDirectDrawSurface7_SetPalette(lpDDSPrimary, lpddpal);
if (ddrval != DD_OK)
{
//ShowDDErr("Error setting palette object.");
FCEU_printf("Error setting palette object.\n");
return 0;
}
}
InitBlitToHigh(bpp >> 3, CBM[0], CBM[1], CBM[2], 0, fs?vmodes[vmod].special:winspecial,specfilteropt);
return 1;
}
@ -394,7 +375,8 @@ int SetVideoMode(int fs)
if(!GetBPP())
return 0;
if(bpp!=16 && bpp!=24 && bpp!=32)
//only 24 and 32bpp are supported now
if(bpp!=24 && bpp!=32)
{
//ShowDDErr("Current bit depth not supported!");
FCEU_printf("Current bit depth not supported!\n");

View File

@ -395,7 +395,7 @@ void ResetGameLoaded(void) {
MMC5Hack = 0;
PEC586Hack = 0;
PAL &= 1;
pale = 0;
default_palette_selection = 0;
}
int UNIFLoad(const char *name, FCEUFILE *fp);

View File

@ -129,7 +129,7 @@ void FCEU_DispMessage(char *format, int disppos, ...);
void FCEU_DispMessageOnMovie(char *format, ...);
void FCEU_TogglePPU();
void SetNESDeemph(uint8 d, int force);
void SetNESDeemph_OldHacky(uint8 d, int force);
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
void FCEU_PutImage(void);
#ifdef FRAMESKIP
@ -142,7 +142,7 @@ extern void PushCurrentVideoSettings();
#endif
extern uint8 Exit;
extern uint8 pale;
extern int default_palette_selection;
extern uint8 vsdip;
//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles

View File

@ -31,8 +31,6 @@
#include "palette.h"
#include "palettes/palettes.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
@ -42,24 +40,25 @@
#include <cmath>
#include <cstring>
static int ntsccol=0;
static int ntsctint=46+10;
static int ntschue=72;
bool force_grayscale = false;
/* These are dynamically filled/generated palettes: */
pal palettei[64]; // Custom palette for an individual game.
pal palettec[64]; // Custom "global" palette.
pal paletten[64]; // Mathematically generated palette.
pal palette_game[64*8]; //custom palette for an individual game. (formerly palettei)
pal palette_user[64*8]; //user's overridden palette (formerly palettec)
pal palette_ntsc[64*8]; //mathematically generated NTSC palette (formerly paletten)
static void CalculatePalette(void);
static void ChoosePalette(void);
static void WritePalette(void);
uint8 pale=0;
static bool palette_game_available; //whether palette_game is available
static bool palette_user_available; //whether palette_user is available
pal *palo;
static pal *palpoint[8]=
//ntsc parameters:
bool ntsccol_enable = false; //whether NTSC palette is selected
static int ntsctint = 46+10;
static int ntschue = 72;
//the default basic palette
int default_palette_selection = 0;
//library of default palettes
static pal *default_palette[8]=
{
palette,
rp2c04001,
@ -68,35 +67,99 @@ static pal *palpoint[8]=
rp2c05004,
};
void FCEUI_SetPaletteArray(uint8 *pal)
static void CalculatePalette(void);
static void ChoosePalette(void);
static void WritePalette(void);
//points to the actually selected current palette
pal *palo;
static float rtmul[] = { 1.239f, 0.794f, 1.019f, 0.905f, 1.023f, 0.741f, 0.75f };
static float gtmul[] = { 0.915f, 1.086f, 0.98f, 1.026f, 0.908f, 0.987f, 0.75f };
static float btmul[] = { 0.743f, 0.882f, 0.653f, 1.277f, 0.979f, 0.101f, 0.75f };
static void ApplyDeemphasis(u8& r, u8& g, u8& b, int deemph_bits)
{
//DEEMPH BITS MAY BE ORDERED WRONG. PLEASE CHECK
if (deemph_bits == 0) return;
int d = deemph_bits - 1;
int nr = (int)(r * rtmul[d]);
int ng = (int)(g * gtmul[d]);
int nb = (int)(b * btmul[d]);
if (nr > 0xFF) nr = 0xFF;
if (ng > 0xFF) ng = 0xFF;
if (nb > 0xFF) nb = 0xFF;
r = (u8)nr;
g = (u8)ng;
b = (u8)nb;
}
static void ApplyDeemphasisComplete(pal* pal512)
{
if(!pal)
palpoint[0]=palette;
else
{
int x;
palpoint[0]=palettec;
for(x=0;x<64;x++)
{
palpoint[0][x].r=*((uint8 *)pal+x+x+x);
palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);
palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);
//for each deemph level beyond 0
for(int i=1,idx=64;i<8;i++)
{
//for each palette entry
for(int p=0;p<64;p++,idx++)
{
pal512[idx] = pal512[p];
ApplyDeemphasis(pal512[idx].r,pal512[idx].g,pal512[idx].b,i);
}
}
}
void FCEUI_SetUserPalette(uint8 *pal, int nEntries)
{
if(!pal)
{
palette_user_available = false;
return;
}
palette_user_available = true;
memcpy(palette_user,pal,nEntries*3);
//if palette is incomplete, generate deemph entries
if(nEntries != 512)
ApplyDeemphasisComplete(palette_user);
FCEU_ResetPalette();
}
void FCEU_LoadGamePalette(void)
{
palette_game_available = false;
std::string path = FCEU_MakeFName(FCEUMKF_PALETTE,0,0);
FILE* fp = FCEUD_UTF8fopen(path,"rb");
if(fp)
{
int readed = fread(palette_game,1,64*8*3,fp);
int nEntries = readed/3;
fclose(fp);
void FCEUI_SetNTSCTH(int n, int tint, int hue)
//if palette is incomplete, generate deemph entries
if(nEntries != 512)
ApplyDeemphasisComplete(palette_game);
palette_game_available = true;
}
//not sure whether this is needed
FCEU_ResetPalette();
}
void FCEUI_SetNTSCTH(bool en, int tint, int hue)
{
ntsctint=tint;
ntschue=hue;
ntsccol=n;
ntsccol_enable = en;
FCEU_ResetPalette();
}
//this prepares the 'deemph' palette which was a horrible idea to jam a single deemph palette into 0xC0-0xFF of the 8bpp palette.
//its needed for GUI and lua and stuff, so we're leaving it, despite having a newer codepath for applying deemph
static uint8 lastd=0;
void SetNESDeemph(uint8 d, int force)
void SetNESDeemph_OldHacky(uint8 d, int force)
{
static uint16 rtmul[]={
static_cast<uint16>(32768*1.239),
@ -194,6 +257,10 @@ void SetNESDeemph(uint8 d, int force)
// Converted from Kevin Horton's qbasic palette generator.
static void CalculatePalette(void)
{
//PRECONDITION: ntsc palette is enabled
if(!ntsccol_enable)
return;
int x,z;
int r,g,b;
double s,luma,theta;
@ -229,39 +296,14 @@ static void CalculatePalette(void)
if(g<0) g=0;
if(b<0) b=0;
paletten[(x<<4)+z].r=r;
paletten[(x<<4)+z].g=g;
paletten[(x<<4)+z].b=b;
palette_ntsc[(x<<4)+z].r=r;
palette_ntsc[(x<<4)+z].g=g;
palette_ntsc[(x<<4)+z].b=b;
}
WritePalette();
}
static int ipalette=0;
void FCEU_LoadGamePalette(void)
{
uint8 ptmp[192];
FILE *fp;
char *fn;
ipalette=0;
fn=strdup(FCEU_MakeFName(FCEUMKF_PALETTE,0,0).c_str());
if((fp=FCEUD_UTF8fopen(fn,"rb")))
{
int x;
fread(ptmp,1,192,fp);
fclose(fp);
for(x=0;x<64;x++)
{
palettei[x].r=ptmp[x+x+x];
palettei[x].g=ptmp[x+x+x+1];
palettei[x].b=ptmp[x+x+x+2];
}
ipalette=1;
}
free(fn);
//can't call FCEU_ResetPalette(), it would be re-entrant
//see precondition for this function
WritePalette();
}
void FCEU_ResetPalette(void)
@ -275,38 +317,51 @@ void FCEU_ResetPalette(void)
static void ChoosePalette(void)
{
//if it's an NSF, there's NO palette? that's right, only the 'unvarying' palette will get used
if(GameInfo->type==GIT_NSF)
palo=0;
else if(ipalette)
palo=palettei;
else if(ntsccol && !PAL && GameInfo->type!=GIT_VSUNI)
palo = NULL;
//user palette takes priority over others
else if(palette_user_available)
palo = palette_user;
//NTSC takes priority next, if it's appropriate
else if(ntsccol_enable && !PAL && GameInfo->type!=GIT_VSUNI)
{
palo=paletten;
//for NTSC games, we can actually use the NTSC palette
palo = palette_ntsc;
CalculatePalette();
}
//select the game's overridden palette if available
else if(palette_game_available)
palo = palette_game;
//finally, use a default built-in palette
else
palo=palpoint[pale];
{
palo = default_palette[default_palette_selection];
//need to calcualte a deemph on the fly.. sorry. maybe support otherwise later
ApplyDeemphasisComplete(palo);
}
}
void WritePalette(void)
{
int x;
//set the 'unvarying' palettes to low < 128 palette entries
for(x=0;x<7;x++)
FCEUD_SetPalette(x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);
FCEUD_SetPalette(x,palette_unvarying[x].r,palette_unvarying[x].g,palette_unvarying[x].b);
if(GameInfo->type==GIT_NSF)
{
#ifdef _S9XLUA_H
FCEU_LuaUpdatePalette();
#endif
//for(x=0;x<128;x++)
// FCEUD_SetPalette(x,x,0,x);
}
else
{
//sets palette entries >= 128 with the 64 selected main colors
for(x=0;x<64;x++)
FCEUD_SetPalette(128+x,palo[x].r,palo[x].g,palo[x].b);
SetNESDeemph(lastd,1);
SetNESDeemph_OldHacky(lastd,1);
}
}
@ -321,7 +376,7 @@ static int controllength=0;
void FCEUI_NTSCDEC(void)
{
if(ntsccol && GameInfo->type!=GIT_VSUNI &&!PAL && GameInfo->type!=GIT_NSF)
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI &&!PAL && GameInfo->type!=GIT_NSF)
{
int which;
if(controlselect)
@ -343,7 +398,7 @@ void FCEUI_NTSCDEC(void)
void FCEUI_NTSCINC(void)
{
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF)
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF)
if(controlselect)
{
if(controllength)
@ -366,12 +421,12 @@ void FCEUI_NTSCINC(void)
void FCEUI_NTSCSELHUE(void)
{
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=1;controllength=360;}
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=1;controllength=360;}
}
void FCEUI_NTSCSELTINT(void)
{
if(ntsccol && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=2;controllength=360;}
if(ntsccol_enable && GameInfo->type!=GIT_VSUNI && !PAL && GameInfo->type!=GIT_NSF){controlselect=2;controllength=360;}
}
void FCEU_DrawNTSCControlBars(uint8 *XBuf)

View File

@ -1,19 +1,30 @@
pal rp2c04001[64] = {
#define EMPTY_PALETTE_1 {0,0,0},
#define EMPTY_PALETTE_4 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1 EMPTY_PALETTE_1
#define EMPTY_PALETTE_16 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4 EMPTY_PALETTE_4
#define EMPTY_PALETTE_64 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16
#define EMPTY_PALETTE_DEEMPH_X_7 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64
pal rp2c04001[512] = {
#include "rp2c04001.h"
EMPTY_PALETTE_DEEMPH_X_7
};
pal rp2c04002[64] = {
pal rp2c04002[512] = {
#include "rp2c04002.h"
EMPTY_PALETTE_DEEMPH_X_7
};
pal rp2c04003[64] = {
pal rp2c04003[512] = {
#include "rp2c04003.h"
EMPTY_PALETTE_DEEMPH_X_7
};
pal rp2c05004[64] = {
pal rp2c05004[512] = {
#include "rp2c05004.h"
EMPTY_PALETTE_DEEMPH_X_7
};
pal unvpalette[7] = {
//I think these are used for 'unvarying' palette entries, for the gui
pal palette_unvarying[7] = {
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
{ 0x3F<<2,0x3F<<2,0x34<<2}, // White
{ 0x00<<2,0x00<<2,0x00<<2}, // Black
@ -25,7 +36,7 @@ pal unvpalette[7] = {
// Default palette
pal palette[64] = {
pal palette[512] = {
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
@ -292,4 +303,6 @@ slightly better but too dark:
*/
EMPTY_PALETTE_DEEMPH_X_7
};

View File

@ -1223,6 +1223,7 @@ static void DoLine(void) {
// send all future writes to the invisible sanline. the easiest way to "skip" them altogether in old ppu
// todo: figure out what exactly should be skipped. it's known that there's no activity on PPU bus
uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8);
u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8);
if (MMC5Hack) MMC5_hb(scanline);
@ -1236,19 +1237,23 @@ static void DoLine(void) {
col = Pal[0];
else col = gNoBGFillColor;
tem = col | (col << 8) | (col << 16) | (col << 24);
tem |= 0x40404040;
tem |= 0x40404040;
FCEU_dwmemset(target, tem, 256);
}
if (SpriteON)
CopySprites(target);
if (ScreenON || SpriteON) { // Yes, very el-cheapo.
//greyscale handling (mask some bits off the color) ? ? ?
if (ScreenON || SpriteON)
{
if (PPU[1] & 0x01) {
for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030;
}
}
//some pathetic attempts at deemph
if ((PPU[1] >> 5) == 0x7) {
for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0;
@ -1259,6 +1264,10 @@ static void DoLine(void) {
for (x = 63; x >= 0; x--)
*(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080;
//write the actual deemph
for (x = 63; x >= 0; x--)
*(uint32*)&dtarget[x << 2] = ((PPU[1]>>5)<<0)|((PPU[1]>>5)<<8)|((PPU[1]>>5)<<16)|((PPU[1]>>5)<<24);
sphitx = 0x100;
if (ScreenON || SpriteON)
@ -1785,7 +1794,6 @@ int FCEUPPU_Loop(int skip) {
}
#endif
else {
int x, max, maxref;
deemp = PPU[1] >> 5;
// manual samples can't play correctly with overclocking
@ -1803,14 +1811,16 @@ int FCEUPPU_Loop(int skip) {
DMC_7bit = 0;
if (MMC5Hack) MMC5_hb(scanline);
for (x = 1, max = 0, maxref = 0; x < 7; x++) {
//deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation)
for (int x = 1, max = 0, maxref = 0; x < 7; x++) {
if (deempcnt[x] > max) {
max = deempcnt[x];
maxref = x;
}
deempcnt[x] = 0;
}
SetNESDeemph(maxref, 0);
SetNESDeemph_OldHacky(maxref, 0);
}
} //else... to if(ppudead)
@ -2079,7 +2089,9 @@ int FCEUX_PPU_Loop(int skip) {
int xstart = xt << 3;
oamcount = oamcounts[renderslot];
uint8 * const target = XBuf + (yp << 8) + xstart;
uint8 * const dtarget = XDBuf + (yp << 8) + xstart;
uint8 *ptr = target;
uint8 *dptr = dtarget;
int rasterpos = xstart;
//check all the conditions that can cause things to render in these 8px
@ -2147,6 +2159,7 @@ int FCEUX_PPU_Loop(int skip) {
}
*ptr++ = PaletteAdjustPixel(pixelcolor);
*dptr++= PPU[1]>>5; //grap deemph
}
}
}

View File

@ -56,10 +56,17 @@
#include <cstdarg>
#include <zlib.h>
uint8 *XBuf=NULL;
uint8 *XBackBuf=NULL;
//XBuf:
//0-63 is reserved for 7 special colours used by FCEUX (overlay, etc.)
//64-127 is the most-used emphasis setting per frame
//128-195 is the palette with no emphasis
//196-255 is the palette with all emphasis bits on
u8 *XBuf=NULL; //used for current display
u8 *XBackBuf=NULL; //ppu output is stashed here before drawing happens
u8 *XDBuf=NULL; //corresponding to XBuf but with deemph bits
u8 *XDBackBuf=NULL; //corresponding to XBackBuf but with deemph bits
int ClipSidesOffset=0; //Used to move displayed messages when Clips left and right sides is checked
static uint8 *xbsave=NULL;
static u8 *xbsave=NULL;
GUIMESSAGE guiMessage;
GUIMESSAGE subtitleMessage;
@ -105,29 +112,35 @@ void FCEU_KillVirtualVideo(void)
**/
int FCEU_InitVirtualVideo(void)
{
if(!XBuf) /* Some driver code may allocate XBuf externally. */
/* 256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
*/
if(!(XBuf= (uint8*) (FCEU_malloc(256 * 256 + 16))) ||
!(XBackBuf= (uint8*) (FCEU_malloc(256 * 256 + 16))))
{
return 0;
}
xbsave = XBuf;
if( sizeof(uint8*) == 4 )
{
uintptr_t m = (uintptr_t)XBuf;
m = ( 8 - m) & 7;
XBuf+=m;
}
memset(XBuf,128,256*256); //*240);
memset(XBackBuf,128,256*256);
//Some driver code may allocate XBuf externally.
//256 bytes per scanline, * 240 scanline maximum, +16 for alignment,
if(XBuf)
return 1;
XBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBuf = (u8*)FCEU_malloc(256 * 256 + 16);
XDBackBuf = (u8*)FCEU_malloc(256 * 256 + 16);
if(!XBuf || !XBackBuf || !XDBuf || !XDBackBuf)
{
return 0;
}
xbsave = XBuf;
if( sizeof(uint8*) == 4 )
{
uintptr_t m = (uintptr_t)XBuf;
m = ( 8 - m) & 7;
XBuf+=m;
}
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
memset(XBuf,128,256*256);
memset(XBackBuf,128,256*256);
return 1;
}
#ifdef FRAMESKIP

View File

@ -9,6 +9,8 @@ uint32 GetScreenPixel(int x, int y, bool usebackup);
int GetScreenPixelPalette(int x, int y, bool usebackup);
extern uint8 *XBuf;
extern uint8 *XBackBuf;
extern uint8 *XDBuf;
extern uint8 *XDBackBuf;
extern int ClipSidesOffset;
extern struct GUIMESSAGE
{

View File

@ -301,7 +301,7 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) {
while (vs->name) {
if (md5partial == vs->md5partial) {
if (vs->ppu < RCP2C03B) pale = vs->ppu;
if (vs->ppu < RCP2C03B) default_palette_selection = vs->ppu;
*MapperNo = vs->mapper;
*Mirroring = vs->mirroring;
GameInfo->type = GIT_VSUNI;