Add support for 512 palette, new deepmhasis method

- Increase palette table from 256 to 1024. the 1st 256 colors are used
  by FCEUmm internally and for compatibility (PS2/PSP will use the old
  emphasis located in this area). New 512 colors with emphasis will be
  read from offset 256 of this palette table.
- Support loading of 512 palette, this will still use the same nes.pal
  filename.
This commit is contained in:
negativeExponent
2024-10-15 22:35:46 +08:00
committed by LibretroAdmin
parent ac798e1ba4
commit f72dac45e8
9 changed files with 141 additions and 69 deletions

View File

@@ -136,7 +136,7 @@ void FCEUI_SetBaseDirectory(const char *dir);
/* Tells FCE Ultra to copy the palette data pointed to by pal and use it. /* 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. Data pointed to by pal needs to be 64*3 bytes in length.
*/ */
void FCEUI_SetPaletteArray(uint8 *pal); void FCEUI_SetPaletteArray(uint8 *pal, int nEntries);
/* Sets up sound code to render sound at the specified rate, in samples /* 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 per second. Only sample rates of 44100, 48000, and 96000 are currently

View File

@@ -284,6 +284,12 @@ void FCEUD_SetPalette(uint16 index, uint8_t r, uint8_t g, uint8_t b)
} }
#endif #endif
#if defined(PSP) || defined(PS2)
/* PS2 / PSP will only have 256 colors */
if (index >= 256)
return;
#endif
#ifdef FRONTEND_SUPPORTS_RGB565 #ifdef FRONTEND_SUPPORTS_RGB565
retro_palette[index_to_write] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND); retro_palette[index_to_write] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND);
#else #else
@@ -368,8 +374,7 @@ void FCEUD_SoundToggle (void)
#define PAL_CUSTOM (PAL_INTERNAL + 3) #define PAL_CUSTOM (PAL_INTERNAL + 3)
#define PAL_TOTAL PAL_CUSTOM #define PAL_TOTAL PAL_CUSTOM
static int external_palette_exist = 0; static uint8 external_palette_exist = false;
extern int ipalette;
/* table for currently loaded palette */ /* table for currently loaded palette */
static uint8_t base_palette[192]; static uint8_t base_palette[192];
@@ -1163,13 +1168,13 @@ static void NTSCFilter_Setup(void)
} }
ntsc_setup.merge_fields = 0; ntsc_setup.merge_fields = 0;
if ((GameInfo->type != GIT_VSUNI) && (current_palette == PAL_DEFAULT || current_palette == PAL_RAW)) if (GameInfo && (GameInfo->type != GIT_VSUNI) && (current_palette == PAL_DEFAULT || current_palette == PAL_RAW))
/* use ntsc default palette instead of internal default palette for that "identity" effect */ /* use ntsc default palette instead of internal default palette for that "identity" effect */
ntsc_setup.base_palette = NULL; ntsc_setup.palette = NULL;
else else
/* use internal palette, this includes palette presets, external palette and custom palettes /* use internal palette, this includes palette presets, external palette and custom palettes
* for VS. System games */ * for VS. System games */
ntsc_setup.base_palette = (unsigned char const *)palo; ntsc_setup.palette = (unsigned char const *)palo;
nes_ntsc_init(&nes_ntsc, &ntsc_setup); nes_ntsc_init(&nes_ntsc, &ntsc_setup);
} }
@@ -1740,7 +1745,7 @@ static void retro_set_custom_palette(void)
{ {
unsigned i; unsigned i;
ipalette = 0; palette_game_available = 0;
use_raw_palette = false; use_raw_palette = false;
/* VS UNISystem uses internal palette presets regardless of options */ /* VS UNISystem uses internal palette presets regardless of options */
@@ -1750,13 +1755,13 @@ static void retro_set_custom_palette(void)
/* Reset and choose between default internal or external custom palette */ /* Reset and choose between default internal or external custom palette */
else if (current_palette == PAL_DEFAULT || current_palette == PAL_CUSTOM) else if (current_palette == PAL_DEFAULT || current_palette == PAL_CUSTOM)
{ {
ipalette = external_palette_exist && (current_palette == PAL_CUSTOM); palette_game_available = external_palette_exist && (current_palette == PAL_CUSTOM);
/* if ipalette is set to 1, external palette /* if palette_game_available is set to 1, external palette
* is loaded, else it will load default NES palette. * is loaded, else it will load default NES palette.
* FCEUI_SetPaletteArray() both resets the palette array to * FCEUI_SetPaletteArray() both resets the palette array to
* internal default palette and then chooses which one to use. */ * internal default palette and then chooses which one to use. */
FCEUI_SetPaletteArray( NULL ); FCEUI_SetPaletteArray( NULL, 0 );
} }
/* setup raw palette */ /* setup raw palette */
@@ -1793,7 +1798,7 @@ static void retro_set_custom_palette(void)
base_palette[ i * 3 + 1 ] = ( data >> 8 ) & 0xff; /* green */ base_palette[ i * 3 + 1 ] = ( data >> 8 ) & 0xff; /* green */
base_palette[ i * 3 + 2 ] = ( data >> 0 ) & 0xff; /* blue */ base_palette[ i * 3 + 2 ] = ( data >> 0 ) & 0xff; /* blue */
} }
FCEUI_SetPaletteArray( base_palette ); FCEUI_SetPaletteArray( base_palette, 64 );
} }
} }
@@ -1895,7 +1900,7 @@ static void check_variables(bool startup)
#ifdef HAVE_NTSC_FILTER #ifdef HAVE_NTSC_FILTER
var.key = "fceumm_ntsc_filter"; var.key = "fceumm_ntsc_filter";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GameInfo && GameInfo->type != GIT_NSF)
{ {
unsigned orig_value = use_ntsc; unsigned orig_value = use_ntsc;
if (strcmp(var.value, "disabled") == 0) if (strcmp(var.value, "disabled") == 0)
@@ -2896,24 +2901,25 @@ static void retro_run_blit(uint8_t *gfx)
pitch -= (crop_overscan_h_left + crop_overscan_h_right) * sizeof(uint16_t); pitch -= (crop_overscan_h_left + crop_overscan_h_right) * sizeof(uint16_t);
gfx += (crop_overscan_v_top * 256) + crop_overscan_h_left; gfx += (crop_overscan_v_top * 256) + crop_overscan_h_left;
if (use_raw_palette)
{ {
uint8_t *deemp = XDBuf + (gfx - XBuf); uint8_t *deemp = XDBuf + (gfx - XBuf);
for (y = 0; y < height; y++, gfx += incr, deemp += incr) for (y = 0; y < height; y++, gfx += incr, deemp += incr)
for (x = 0; x < width; x++, gfx++, deemp++) { {
if (*deemp != 0) { for (x = 0; x < width; x++, gfx++, deemp++)
{
if (*deemp != 0 && GameInfo->type != GIT_NSF)
{
fceu_video_out[y * width + x] = retro_palette[256 + (*gfx & 0x3F) + ((*deemp & 0x07) << 6)]; fceu_video_out[y * width + x] = retro_palette[256 + (*gfx & 0x3F) + ((*deemp & 0x07) << 6)];
} else {
fceu_video_out[y * width + x] = retro_palette[*gfx & 0x3F];
}
}
} }
else else
{ {
for (y = 0; y < height; y++, gfx += incr) uint8 pixel_mask = use_raw_palette ? 0x3F : 0xFF;
for (x = 0; x < width; x++, gfx++) fceu_video_out[y * width + x] = retro_palette[*gfx & pixel_mask];
fceu_video_out[y * width + x] = retro_palette[*gfx];
} }
}
}
}
video_cb(fceu_video_out, width, height, pitch); video_cb(fceu_video_out, width, height, pitch);
} }
#endif #endif
@@ -3583,7 +3589,7 @@ bool retro_load_game(const struct retro_game_info *info)
nes_input.type[i] = RETRO_DEVICE_JOYPAD; nes_input.type[i] = RETRO_DEVICE_JOYPAD;
} }
external_palette_exist = ipalette; external_palette_exist = palette_game_available;
if (external_palette_exist) if (external_palette_exist)
FCEU_printf(" Loading custom palette: %s%cnes.pal\n", FCEU_printf(" Loading custom palette: %s%cnes.pal\n",
system_dir, PATH_DEFAULT_SLASH_C()); system_dir, PATH_DEFAULT_SLASH_C());

View File

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

View File

@@ -110,7 +110,7 @@ void FCEU_PutImageDummy(void);
#endif #endif
extern uint8 Exit; extern uint8 Exit;
extern uint8 pale; extern uint8 default_palette_selected;
extern uint8 vsdip; extern uint8 vsdip;
#define JOY_A 0x01 #define JOY_A 0x01

View File

@@ -34,15 +34,18 @@
#include "palettes/palettes.h" #include "palettes/palettes.h"
/* These are dynamically filled/generated palettes: */ /* These are dynamically filled/generated palettes: */
pal palettei[64]; /* Custom palette for an individual game. */ static pal palette_game[512]; /* Custom palette for an individual game. */
pal palettec[64]; /* Custom "global" palette. */ static pal palette_user[512]; /* Custom "global" palette. */
uint8 palette_game_available = false;
uint8 palette_user_available = false;
static void ChoosePalette(void); static void ChoosePalette(void);
static void WritePalette(void); static void WritePalette(void);
uint8 pale = 0; uint8 default_palette_selected = 0;
pal *palo; pal *palo;
static pal *palpoint[8] = static pal *default_palette[8] =
{ {
palette, palette,
rp2c04_0001, rp2c04_0001,
@@ -52,16 +55,57 @@ static pal *palpoint[8] =
rp2c03, rp2c03,
}; };
void FCEUI_SetPaletteArray(uint8 *pal) { static void ApplyDeemphasisClassic(int entry, uint8 *r, uint8 *g, uint8 *b) {
if (!pal) static const float rtmul[] = { 1.239f, 0.794f, 1.019f, 0.905f, 1.023f, 0.741f, 0.75f };
palpoint[0] = palette; static const float gtmul[] = { 0.915f, 1.086f, 0.98f, 1.026f, 0.908f, 0.987f, 0.75f };
static const float btmul[] = { 0.743f, 0.882f, 0.653f, 1.277f, 0.979f, 0.101f, 0.75f };
int nr, ng, nb, d;
int deemph_bits = entry >> 6;
if (deemph_bits == 0) return;
d = deemph_bits - 1;
nr = *r;
ng = *g;
nb = *b;
nr = (int)(nr * rtmul[d]);
ng = (int)(ng * gtmul[d]);
nb = (int)(nb * btmul[d]);
if (nr > 0xFF) nr = 0xFF;
if (ng > 0xFF) ng = 0xFF;
if (nb > 0xFF) nb = 0xFF;
*r = (uint8)nr;
*g = (uint8)ng;
*b = (uint8)nb;
}
static void ApplyDeemphasisComplete(pal *pal512) {
int i, p, idx;
/* for each deemph level beyond 0 */
for (i = 0, idx = 0; i < 8; i++) {
/* for each palette entry */
for (p = 0; p < 64; p++, idx++) {
pal512[idx] = pal512[p];
ApplyDeemphasisClassic(idx, &pal512[idx].r, &pal512[idx].g, &pal512[idx].b);
}
}
}
void FCEUI_SetPaletteArray(uint8 *pal, int nEntries) {
if (!pal || !nEntries)
palette_user_available = false;
else { else {
int x; int x;
palpoint[0] = palettec; palette_user_available = true;
for (x = 0; x < 64; x++) { for (x = 0; x < nEntries; x++) {
palpoint[0][x].r = *((uint8*)pal + x + x + x); palette_user[x].r = *((uint8*)pal + x + x + x);
palpoint[0][x].g = *((uint8*)pal + x + x + x + 1); palette_user[x].g = *((uint8*)pal + x + x + x + 1);
palpoint[0][x].b = *((uint8*)pal + x + x + x + 2); palette_user[x].b = *((uint8*)pal + x + x + x + 2);
}
if (nEntries != 512) {
ApplyDeemphasisComplete(palette_user);
} }
} }
FCEU_ResetPalette(); FCEU_ResetPalette();
@@ -124,14 +168,12 @@ void SetNESDeemph(uint8 d, int force) {
lastd = d; lastd = d;
} }
int ipalette = 0;
void FCEU_LoadGamePalette(void) { void FCEU_LoadGamePalette(void) {
uint8 ptmp[192]; uint8 ptmp[64 * 8 * 3];
RFILE *fp = NULL; RFILE *fp = NULL;
char *fn = NULL; char *fn = NULL;
ipalette = 0; palette_game_available = false;
fn = FCEU_MakeFName(FCEUMKF_PALETTE, 0, 0); fn = FCEU_MakeFName(FCEUMKF_PALETTE, 0, 0);
@@ -142,14 +184,18 @@ void FCEU_LoadGamePalette(void) {
if (fp) { if (fp) {
int x; int x;
filestream_read(fp, ptmp, 192); int ssize = filestream_get_size(fp);
int nEntries = ssize / 3;
filestream_read(fp, ptmp, nEntries);
filestream_close(fp); filestream_close(fp);
for (x = 0; x < 64; x++) { for (x = 0; x < 64; x++) {
palettei[x].r = ptmp[x + x + x]; palette_game[x].r = ptmp[x + x + x];
palettei[x].g = ptmp[x + x + x + 1]; palette_game[x].g = ptmp[x + x + x + 1];
palettei[x].b = ptmp[x + x + x + 2]; palette_game[x].b = ptmp[x + x + x + 2];
} }
ipalette = 1; if (nEntries != 512)
ApplyDeemphasisComplete(palette_game);
palette_game_available = true;
} }
free(fn); free(fn);
} }
@@ -162,23 +208,30 @@ void FCEU_ResetPalette(void) {
} }
static void ChoosePalette(void) { static void ChoosePalette(void) {
if (GameInfo->type == GIT_NSF) if (GameInfo->type == GIT_NSF) {
palo = 0; palo = default_palette[0];
else if (ipalette) } else if (palette_user_available) {
palo = palettei; palo = palette_user;
else } else if (palette_game_available) {
palo = palpoint[pale]; palo = palette_game;
} else {
palo = default_palette[default_palette_selected];
ApplyDeemphasisComplete(palo);
}
} }
void WritePalette(void) { void WritePalette(void) {
int x; int x;
int unvaried = sizeof(unvpalette) / sizeof(unvpalette[0]);
for (x = 0; x < 7; x++) for (x = 0; x < unvaried; x++)
FCEUD_SetPalette(x, unvpalette[x].r, unvpalette[x].g, unvpalette[x].b); FCEUD_SetPalette(x, unvpalette[x].r, unvpalette[x].g, unvpalette[x].b);
if (GameInfo->type == GIT_NSF) { for (x = unvaried; x < 256; x++)
} else { FCEUD_SetPalette(x, 205, 205, 205);
for (x = 0; x < 64; x++) for (x = 0; x < 64; x++)
FCEUD_SetPalette(128 + x, palo[x].r, palo[x].g, palo[x].b); FCEUD_SetPalette(128 + x, palo[x].r, palo[x].g, palo[x].b);
SetNESDeemph(lastd, 1); SetNESDeemph(lastd, 1);
for (x = 0; x < 512; x++) {
FCEUD_SetPalette(256 + x, palo[x].r, palo[x].g, palo[x].b);
} }
} }

View File

@@ -6,7 +6,7 @@ typedef struct {
} pal; } pal;
extern pal *palo; extern pal *palo;
extern int ipalette; extern uint8 palette_game_available;
void FCEU_ResetPalette(void); void FCEU_ResetPalette(void);
void FCEU_ResetPalette(void); void FCEU_ResetPalette(void);

View File

@@ -1,20 +1,31 @@
pal rp2c04_0001[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 rp2c04_0001[512] = {
#include "rp2c04-0001.h" #include "rp2c04-0001.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c04_0002[64] = { pal rp2c04_0002[512] = {
#include "rp2c04-0002.h" #include "rp2c04-0002.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c04_0003[64] = { pal rp2c04_0003[512] = {
#include "rp2c04-0003.h" #include "rp2c04-0003.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c04_0004[64] = { pal rp2c04_0004[512] = {
#include "rp2c04-0004.h" #include "rp2c04-0004.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
pal rp2c03[64] = { pal rp2c03[512] = {
#include "rp2c03.h" #include "rp2c03.h"
EMPTY_PALETTE_DEEMPH_X_7
}; };
@@ -30,7 +41,7 @@ pal unvpalette[7] = {
/* Default palette */ /* Default palette */
pal palette[64] = { pal palette[512] = {
{ 117, 117, 117 }, /* Value 0 */ { 117, 117, 117 }, /* Value 0 */
{ 36, 24, 142 }, /* Value 1 */ { 36, 24, 142 }, /* Value 1 */
{ 0, 0, 170 }, /* Value 2 */ { 0, 0, 170 }, /* Value 2 */
@@ -95,4 +106,6 @@ pal palette[64] = {
{ 199, 199, 199 }, /* Value 61 */ { 199, 199, 199 }, /* Value 61 */
{ 0, 0, 0 }, /* Value 62 */ { 0, 0, 0 }, /* Value 62 */
{ 0, 0, 0 }, /* Value 63 */ { 0, 0, 0 }, /* Value 63 */
EMPTY_PALETTE_DEEMPH_X_7
}; };

View File

@@ -61,7 +61,7 @@ int FCEU_InitVirtualVideo(void)
return 0; return 0;
memset(XBuf, 128, 256 * (256 + extrascanlines + 8)); memset(XBuf, 128, 256 * (256 + extrascanlines + 8));
memset(XDBuf, 128, 256 * (256 + extrascanlines + 8)); memset(XDBuf, 0, 256 * (256 + extrascanlines + 8));
return 1; return 1;
} }

View File

@@ -292,8 +292,8 @@ void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, int *Mirroring) {
while (vs->name) { while (vs->name) {
if (md5partial == vs->md5partial) { if (md5partial == vs->md5partial) {
if (vs->ppu < RCP2C03B) pale = vs->ppu; if (vs->ppu < RCP2C03B) default_palette_selected = vs->ppu;
else pale = 5; else default_palette_selected = 5;
*MapperNo = vs->mapper; *MapperNo = vs->mapper;
*Mirroring = vs->mirroring; *Mirroring = vs->mirroring;
GameInfo->type = GIT_VSUNI; GameInfo->type = GIT_VSUNI;