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:
parent
314aaff2e1
commit
96078b99ac
|
@ -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.
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue