From 695405ce56bd424c8e67bdcf5288be7da963622d Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Tue, 25 Feb 2020 07:13:42 +0800 Subject: [PATCH 1/3] Fix colour emphasis when using palette presets This is an issue i found when implementing the NTSC filters. Currently when using palette presets, no clour emphasis is seen on games that supports it. This is cause because the palette table is fille with the same 64*3 colour info. Using custom palette (palette file) and default both creates the emphasis as expected. So internally, fceumm is able to support such feature. The fix is to generate the base palette (64 * 3 with each triplet representing rgb colour), and then send this internally using FCEUI_SetPaletteArray() to fill the colour table with emphasis instead. --- src/drivers/libretro/libretro.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 8118900..30298b6 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -157,7 +157,6 @@ static unsigned use_ntsc = 0; static unsigned burst_phase; static nes_ntsc_t nes_ntsc; static nes_ntsc_setup_t ntsc_setup; -static pal base_palette[64]; static uint8_t *ntsc_video_out = NULL; /* for ntsc blit buffer */ static void nes_ntsc_cleanup(void) @@ -295,9 +294,13 @@ FILE *FCEUD_UTF8fopen(const char *n, const char *m) #define PAL_DEFAULT (PAL_TOTAL + 1) #define PAL_RAW (PAL_TOTAL + 2) #define PAL_CUSTOM (PAL_TOTAL + 3) + static int external_palette_exist = 0; extern int ipalette; +/* table for currently loaded palette */ +static uint8_t base_palette[192]; + struct st_palettes { char name[32]; char desc[32]; @@ -913,9 +916,7 @@ void retro_init(void) static void retro_set_custom_palette(void) { - unsigned i; - unsigned palette_changed; - pal color; + unsigned i, palette_changed; ipalette = 0; use_raw_palette = false; @@ -941,6 +942,7 @@ static void retro_set_custom_palette(void) /* setup raw palette */ else if (current_palette == PAL_RAW) { + pal color; use_raw_palette = true; for (i = 0; i < 64; i++) { @@ -958,23 +960,12 @@ static void retro_set_custom_palette(void) for ( i = 0; i < 64; i++ ) { unsigned data = palette_data[i]; - color.r = ( data >> 16 ) & 0xff; - color.g = ( data >> 8 ) & 0xff; - color.b = ( data & 0xff ); - FCEUD_SetPalette( i, color.r, color.g, color.b); - FCEUD_SetPalette( i + 64, color.r, color.g, color.b); - FCEUD_SetPalette( i + 128, color.r, color.g, color.b); - FCEUD_SetPalette( i + 192, color.r, color.g, color.b); -#ifdef HAVE_NTSC_FILTER - palette_changed = 1; - if (use_ntsc) - { - base_palette[i].r = color.r; - base_palette[i].g = color.g; - base_palette[i].b = color.b; - } -#endif + base_palette[ i * 3 + 0 ] = ( data >> 16 ) & 0xff; /* red */ + base_palette[ i * 3 + 1 ] = ( data >> 8 ) & 0xff; /* green */ + base_palette[ i * 3 + 2 ] = ( data >> 0 ) & 0xff; /* blue */ } + FCEUI_SetPaletteArray( base_palette ); + palette_changed = 1; } #ifdef HAVE_NTSC_FILTER @@ -2333,10 +2324,10 @@ bool retro_load_game(const struct retro_game_info *game) #ifdef HAVE_NTSC_FILTER use_ntsc = 0; - memset(base_palette, 0, sizeof(base_palette)); memset(&nes_ntsc, 0, sizeof(nes_ntsc)); ntsc_video_out = (uint8_t*)malloc(NES_NTSC_OUT_WIDTH(NES_WIDTH) * (NES_HEIGHT * 2) * sizeof(uint16_t)); #endif + memset(base_palette, 0, sizeof(base_palette)); FCEUI_Initialize(); From 4f599a77f90a32e9d0105d1bfd6a2b4f9e0e0465 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Tue, 25 Feb 2020 09:08:44 +0800 Subject: [PATCH 2/3] NtscFilter: Fix palette for VS. System games and cleanup - fix palette for vs. system - move most of the ntsc filter code to its own branch - use fixed value for ntsc width and when its cropped --- src/drivers/libretro/libretro.c | 158 +++++++++++++++++++------------- 1 file changed, 95 insertions(+), 63 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 30298b6..a31d019 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -144,29 +144,6 @@ extern CartInfo UNIFCart; extern int show_crosshair; extern int option_ramstate; -#ifdef HAVE_NTSC_FILTER -/* ntsc */ -#include "nes_ntsc.h" -#define NTSC_NONE 0 -#define NTSC_COMPOSITE 1 -#define NTSC_SVIDEO 2 -#define NTSC_RGB 3 -#define NTSC_MONOCHROME 4 - -static unsigned use_ntsc = 0; -static unsigned burst_phase; -static nes_ntsc_t nes_ntsc; -static nes_ntsc_setup_t ntsc_setup; -static uint8_t *ntsc_video_out = NULL; /* for ntsc blit buffer */ - -static void nes_ntsc_cleanup(void) -{ - if (ntsc_video_out) - free(ntsc_video_out); - ntsc_video_out = NULL; -} -#endif /* HAVE_NTSC_FILTER */ - /* emulator-specific callback functions */ void UpdatePPUView(int refreshchr) { } @@ -300,6 +277,7 @@ extern int ipalette; /* table for currently loaded palette */ static uint8_t base_palette[192]; +static unsigned palette_changed; struct st_palettes { char name[32]; @@ -598,6 +576,85 @@ struct st_palettes palettes[] = { } }; +#ifdef HAVE_NTSC_FILTER +/* ntsc */ +#include "nes_ntsc.h" +#define NTSC_NONE 0 +#define NTSC_COMPOSITE 1 +#define NTSC_SVIDEO 2 +#define NTSC_RGB 3 +#define NTSC_MONOCHROME 4 + +#define NTSC_WIDTH 602 + +static unsigned use_ntsc = 0; +static unsigned burst_phase; +static nes_ntsc_t nes_ntsc; +static nes_ntsc_setup_t ntsc_setup; +static uint8_t *ntsc_video_out = NULL; /* for ntsc blit buffer */ + +static void NTSCFilter_Cleanup(void) +{ + if (ntsc_video_out) + free(ntsc_video_out); + ntsc_video_out = NULL; +} + +static void NTSCFilter_Init(void) +{ + memset(&nes_ntsc, 0, sizeof(nes_ntsc)); + memset(&ntsc_setup, 0, sizeof(ntsc_setup)); + ntsc_video_out = (uint8_t*)malloc(NTSC_WIDTH * NES_HEIGHT * sizeof(uint16_t)); +} + +static void NTSCFilter_Setup(void) +{ + if (ntsc_video_out == NULL) + NTSCFilter_Init(); + + switch (use_ntsc) { + case NTSC_COMPOSITE: + ntsc_setup = nes_ntsc_composite; + break; + case NTSC_SVIDEO: + ntsc_setup = nes_ntsc_svideo; + break; + case NTSC_RGB: + ntsc_setup = nes_ntsc_rgb; + break; + case NTSC_MONOCHROME: + ntsc_setup = nes_ntsc_monochrome; + break; + default: + break; + } + + if (palette_changed) + { + if ((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 */ + ntsc_setup.base_palette = NULL; + else + /* use internal palette, this includes palette presets, external palette and custom palettes + * for VS. System games */ + ntsc_setup.base_palette = (unsigned char const*)palo; + } + + nes_ntsc_init(&nes_ntsc, &ntsc_setup); +} +#endif /* HAVE_NTSC_FILTER */ + +static void ResetPalette(void); +static void retro_set_custom_palette(void); + +static void ResetPalette(void) +{ + retro_set_custom_palette(); +#ifdef HAVE_NTSC_FILTER + NTSCFilter_Setup(); +#endif +} + static bool libretro_supports_bitmasks = false; unsigned retro_api_version(void) @@ -872,7 +929,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) height = NES_HEIGHT - (overscan_v ? 16 : 0); #endif #ifdef HAVE_NTSC_FILTER - maxwidth = NES_NTSC_OUT_WIDTH(NES_WIDTH); + maxwidth = NTSC_WIDTH; #else maxwidth = NES_WIDTH; #endif @@ -916,7 +973,7 @@ void retro_init(void) static void retro_set_custom_palette(void) { - unsigned i, palette_changed; + unsigned i; ipalette = 0; use_raw_palette = false; @@ -937,6 +994,7 @@ static void retro_set_custom_palette(void) * else it will load default NES palette. * VS Unisystem should always use default palette. */ + palette_changed = 1; } /* setup raw palette */ @@ -968,32 +1026,6 @@ static void retro_set_custom_palette(void) palette_changed = 1; } -#ifdef HAVE_NTSC_FILTER - if (use_ntsc) { - switch (use_ntsc) { - case NTSC_COMPOSITE: - ntsc_setup = nes_ntsc_composite; - break; - case NTSC_SVIDEO: - ntsc_setup = nes_ntsc_svideo; - break; - case NTSC_RGB: - ntsc_setup = nes_ntsc_rgb; - break; - case NTSC_MONOCHROME: - ntsc_setup = nes_ntsc_monochrome; - break; - default: - break; - } - if (palette_changed) - ntsc_setup.base_palette = (unsigned char const*)base_palette; - else - ntsc_setup.base_palette = ipalette ? (unsigned char const*)palo : NULL; - nes_ntsc_init(&nes_ntsc, &ntsc_setup); - } -#endif - #if defined(RENDER_GSKIT_PS2) if (ps2) { ps2->updatedPalette = true; @@ -1033,7 +1065,7 @@ void FCEUD_RegionOverride(unsigned region) normal_scanlines = dendy ? 290 : 240; totalscanlines = normal_scanlines + (overclock_enabled ? extrascanlines : 0); FCEUI_SetVidSystem(pal); - retro_set_custom_palette(); + ResetPalette(); } void retro_deinit (void) @@ -1054,7 +1086,7 @@ void retro_deinit (void) libretro_supports_bitmasks = false; DPSW_Cleanup(); #ifdef HAVE_NTSC_FILTER - nes_ntsc_cleanup(); + NTSCFilter_Cleanup(); #endif } @@ -1176,7 +1208,7 @@ static void check_variables(bool startup) } if (palette_updated) - retro_set_custom_palette(); + ResetPalette(); var.key = "fceumm_up_down_allowed"; @@ -1817,14 +1849,16 @@ static void retro_run_blit(uint8_t *gfx) width = overscan_h ? 240 : 256; height = overscan_v ? 224 : 240; - out_width = NES_NTSC_OUT_WIDTH(width); + out_width = overscan_h ? 560 : 602; out_height = height; out_pitch = out_width * sizeof(uint16_t); gfx += (overscan_v ? ((overscan_h ? 8 : 0) + 256 * 8) : (overscan_h ? 8 : 0)); nes_ntsc_blit(&nes_ntsc, (const unsigned char*)gfx, NES_WIDTH, burst_phase, width, height, ntsc_video_out, out_pitch); -#if 0 /* this doubles the height for proper scaling, disabled for performance reasons */ +#if 0 + /* this doubles the height for proper scaling, disabled for performance reasons */ + * NOTE: buffer height needs to be doubled as well */ out_height <<= 1; for (y = out_height / 2; --y >= 0;) { @@ -2322,11 +2356,6 @@ bool retro_load_game(const struct retro_game_info *game) if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &sav_dir) && sav_dir) FCEUI_SetSaveDirectory(sav_dir); -#ifdef HAVE_NTSC_FILTER - use_ntsc = 0; - memset(&nes_ntsc, 0, sizeof(nes_ntsc)); - ntsc_video_out = (uint8_t*)malloc(NES_NTSC_OUT_WIDTH(NES_WIDTH) * (NES_HEIGHT * 2) * sizeof(uint16_t)); -#endif memset(base_palette, 0, sizeof(base_palette)); FCEUI_Initialize(); @@ -2360,7 +2389,10 @@ bool retro_load_game(const struct retro_game_info *game) /* Save region and dendy mode for region-auto detect */ systemRegion = (dendy << 1) | (retro_get_region() & 1); - retro_set_custom_palette(); + current_palette = 0; + palette_changed = 0; + + ResetPalette(); FCEUD_SoundToggle(); set_variables(); check_variables(true); @@ -2485,7 +2517,7 @@ void retro_unload_game(void) ps2 = NULL; #endif #ifdef HAVE_NTSC_FILTER - nes_ntsc_cleanup(); + NTSCFilter_Cleanup(); #endif } From fa74a364dedeae71c3b70d0e58fe076e7d92a815 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Tue, 25 Feb 2020 11:51:41 +0800 Subject: [PATCH 3/3] Fix colour emphasis support for NTSC filter & raw palette + nes decoder shader - this implementation is based on a more accurate colour emphasis from fceux. - The raw palette + nes decoder shader was kinda incomplete since the implementation was based on a per-frame basis which means that the emphasis bits were read once and applied to the whole frame. This means that some games that uses a per pixel or per scanline emphasis would not appear correct. The more accurate implementation reads emphasis bits from bits 5-7 of PPU[1] and saves this info in a separate frame. - The same implementation is also used to fix emphasis for the ntsc filter. --- src/drivers/libretro/libretro.c | 79 +++++++++++++++------------------ src/ntsc/nes_ntsc.c | 15 ++++--- src/ntsc/nes_ntsc.h | 4 +- src/ntsc/nes_ntsc_config.h | 2 +- src/ppu.c | 18 +++++--- src/video.c | 11 ++++- src/video.h | 1 + 7 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index a31d019..8825218 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -277,7 +277,6 @@ extern int ipalette; /* table for currently loaded palette */ static uint8_t base_palette[192]; -static unsigned palette_changed; struct st_palettes { char name[32]; @@ -629,16 +628,14 @@ static void NTSCFilter_Setup(void) break; } - if (palette_changed) - { - if ((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 */ - ntsc_setup.base_palette = NULL; - else - /* use internal palette, this includes palette presets, external palette and custom palettes + ntsc_setup.merge_fields = 0; + if ((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 */ + ntsc_setup.base_palette = NULL; + else + /* use internal palette, this includes palette presets, external palette and custom palettes * for VS. System games */ - ntsc_setup.base_palette = (unsigned char const*)palo; - } + ntsc_setup.base_palette = (unsigned char const *)palo; nes_ntsc_init(&nes_ntsc, &ntsc_setup); } @@ -977,7 +974,6 @@ static void retro_set_custom_palette(void) ipalette = 0; use_raw_palette = false; - palette_changed = 0; if ((current_palette == PAL_DEFAULT) || (current_palette == PAL_CUSTOM) || @@ -994,7 +990,6 @@ static void retro_set_custom_palette(void) * else it will load default NES palette. * VS Unisystem should always use default palette. */ - palette_changed = 1; } /* setup raw palette */ @@ -1023,7 +1018,6 @@ static void retro_set_custom_palette(void) base_palette[ i * 3 + 2 ] = ( data >> 0 ) & 0xff; /* blue */ } FCEUI_SetPaletteArray( base_palette ); - palette_changed = 1; } #if defined(RENDER_GSKIT_PS2) @@ -1841,11 +1835,12 @@ static void retro_run_blit(uint8_t *gfx) #ifdef HAVE_NTSC_FILTER if (use_ntsc) { - int y; + uint8_t *deemp; unsigned out_width, out_height, out_pitch; + int y; - /*burst_phase ^= 1; - if (ntsc_setup.merge_fields) burst_phase = 0;*/ + burst_phase ^= 1; + if (ntsc_setup.merge_fields) burst_phase = 0; width = overscan_h ? 240 : 256; height = overscan_v ? 224 : 240; @@ -1853,33 +1848,35 @@ static void retro_run_blit(uint8_t *gfx) out_height = height; out_pitch = out_width * sizeof(uint16_t); gfx += (overscan_v ? ((overscan_h ? 8 : 0) + 256 * 8) : (overscan_h ? 8 : 0)); + deemp = XDBuf + (gfx - XBuf); /* get colour emphasis */ - nes_ntsc_blit(&nes_ntsc, (const unsigned char*)gfx, NES_WIDTH, burst_phase, width, height, ntsc_video_out, out_pitch); - + nes_ntsc_blit(&nes_ntsc, (unsigned char const*)gfx, (unsigned char const*)deemp, NES_WIDTH, burst_phase, width, height, ntsc_video_out, out_pitch); #if 0 - /* this doubles the height for proper scaling, disabled for performance reasons */ - * NOTE: buffer height needs to be doubled as well */ - out_height <<= 1; - for (y = out_height / 2; --y >= 0;) + if (!retain_height) { - uint8_t const *in = ntsc_video_out + y * out_pitch; - uint8_t *out = ntsc_video_out + y * 2 * out_pitch; - int n; - for (n = out_width; n; --n) + /* this doubles the height for proper scaling, disabled for performance reasons. + * NOTE: buffer height needs to be doubled as well */ + out_height <<= 1; + for (y = out_height / 2; --y >= 0;) { - unsigned prev = *(uint16_t*)in; - unsigned next = *(uint16_t*)(in + out_pitch); - /* mix 16-bit rgb without losing low bits */ - unsigned mixed = prev + next + ((prev ^ next) & 0x0821); - /* darken by 12% */ - *(uint16_t*)out = prev; - *(uint16_t*)(out + out_pitch) = (mixed >> 1) - (mixed >> 4 & 0x18E3); - in += 2; - out += 2; + uint8_t const *in = ntsc_video_out + y * out_pitch; + uint8_t *out = ntsc_video_out + y * 2 * out_pitch; + int n; + for (n = out_width; n; --n) + { + unsigned prev = *(uint16_t *)in; + unsigned next = *(uint16_t *)(in + out_pitch); + /* mix 16-bit rgb without losing low bits */ + unsigned mixed = prev + next + ((prev ^ next) & 0x0821); + /* darken by 12% */ + *(uint16_t *)out = prev; + *(uint16_t *)(out + out_pitch) = (mixed >> 1) - (mixed >> 4 & 0x18E3); + in += 2; + out += 2; + } } } #endif - video_cb(ntsc_video_out, out_width, out_height, out_pitch); } else @@ -1893,11 +1890,10 @@ static void retro_run_blit(uint8_t *gfx) if (use_raw_palette) { - extern uint8 PPU[4]; - int deemp = (PPU[1] >> 5) << 2; - for (y = 0; y < height; y++, gfx += incr) - for (x = 0; x < width; x++, gfx++) - fceu_video_out[y * width + x] = retro_palette[*gfx & 0x3F] | deemp; + uint8_t *deemp = XDBuf + (gfx - XBuf); + for (y = 0; y < height; y++, gfx += incr, deemp += incr) + for (x = 0; x < width; x++, gfx++, deemp++) + fceu_video_out[y * width + x] = retro_palette[*gfx & 0x3F] | (*deemp << 2); } else { @@ -2390,7 +2386,6 @@ bool retro_load_game(const struct retro_game_info *game) systemRegion = (dendy << 1) | (retro_get_region() & 1); current_palette = 0; - palette_changed = 0; ResetPalette(); FCEUD_SoundToggle(); diff --git a/src/ntsc/nes_ntsc.c b/src/ntsc/nes_ntsc.c index 004abb6..df57cb0 100644 --- a/src/ntsc/nes_ntsc.c +++ b/src/ntsc/nes_ntsc.c @@ -233,15 +233,16 @@ void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup ) #ifndef NES_NTSC_NO_BLITTERS -void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_row_width, +void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, NES_NTSC_IN_T const* inputD, long in_row_width, int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) { int chunk_count = (in_width - 1) / nes_ntsc_in_chunk; for ( ; in_height; --in_height ) { NES_NTSC_IN_T const* line_in = input; + NES_NTSC_IN_T const* line_inD = inputD; NES_NTSC_BEGIN_ROW( ntsc, burst_phase, - nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in ) ); + nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in, *line_inD ) ); nes_ntsc_out_t* restrict line_out = (nes_ntsc_out_t*) rgb_out; int n; ++line_in; @@ -249,20 +250,21 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_ for ( n = chunk_count; n; --n ) { /* order of input and output pixels must not be altered */ - NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0] ) ); + NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0], line_inD[0] ) ); NES_NTSC_RGB_OUT( 0, line_out [0], NES_NTSC_OUT_DEPTH ); NES_NTSC_RGB_OUT( 1, line_out [1], NES_NTSC_OUT_DEPTH ); - NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1] ) ); + NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1], line_inD[1] ) ); NES_NTSC_RGB_OUT( 2, line_out [2], NES_NTSC_OUT_DEPTH ); NES_NTSC_RGB_OUT( 3, line_out [3], NES_NTSC_OUT_DEPTH ); - NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2] ) ); + NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2], line_inD[2] ) ); NES_NTSC_RGB_OUT( 4, line_out [4], NES_NTSC_OUT_DEPTH ); NES_NTSC_RGB_OUT( 5, line_out [5], NES_NTSC_OUT_DEPTH ); NES_NTSC_RGB_OUT( 6, line_out [6], NES_NTSC_OUT_DEPTH ); line_in += 3; + line_inD += 3; line_out += 7; } @@ -281,7 +283,8 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_ NES_NTSC_RGB_OUT( 6, line_out [6], NES_NTSC_OUT_DEPTH ); burst_phase = (burst_phase + 1) % nes_ntsc_burst_count; - input += in_row_width; + input += in_row_width; + inputD += in_row_width; rgb_out = (char*) rgb_out + out_pitch; } } diff --git a/src/ntsc/nes_ntsc.h b/src/ntsc/nes_ntsc.h index 6bfa8f1..12568f4 100644 --- a/src/ntsc/nes_ntsc.h +++ b/src/ntsc/nes_ntsc.h @@ -61,8 +61,8 @@ In_row_width is the number of pixels to get to the next input row. 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 ); + NES_NTSC_IN_T const* nes_inD, long in_row_width, int burst_phase, 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 diff --git a/src/ntsc/nes_ntsc_config.h b/src/ntsc/nes_ntsc_config.h index ed5942b..1a89293 100644 --- a/src/ntsc/nes_ntsc_config.h +++ b/src/ntsc/nes_ntsc_config.h @@ -19,7 +19,7 @@ if you enable emphasis above. */ /* 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, deemp ) ( in & 0x3F ) | ( deemp << 6 ) /* For each pixel, this is the basic operation: output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */ diff --git a/src/ppu.c b/src/ppu.c index e45e1f8..187a96c 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -656,10 +656,12 @@ static void Fixit1(void) { void MMC5_hb(int); /* Ugh ugh ugh. */ static void DoLine(void) { - int x; - uint8 *target = NULL; - if (scanline >= 240 && scanline != totalscanlines) - { + int x, colour_emphasis; + uint8 *target = NULL; + uint8 *dtarget = NULL; + + if (scanline >= 240 && scanline != totalscanlines) + { X6502_Run(256 + 69); scanline++; X6502_Run(16); @@ -667,6 +669,7 @@ static void DoLine(void) } target = XBuf + ((scanline < 240 ? scanline : 240) << 8); + dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8); if (MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); @@ -699,7 +702,12 @@ static void DoLine(void) for (x = 63; x >= 0; x--) *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; - sphitx = 0x100; + //write the actual colour emphasis + colour_emphasis = ((PPU[1] >> 5) << 24) | ((PPU[1] >> 5) << 16) | ((PPU[1] >> 5) << 8) | ((PPU[1] >> 5) << 0); + for (x = 63; x >= 0; x--) + *(uint32*)&dtarget[x << 2] = colour_emphasis; + + sphitx = 0x100; if (ScreenON || SpriteON) FetchSpriteData(); diff --git a/src/video.c b/src/video.c index 099ba80..0017fc1 100644 --- a/src/video.c +++ b/src/video.c @@ -36,6 +36,7 @@ #include "vsuni.h" uint8 *XBuf = NULL; +uint8 *XDBuf = NULL; int show_crosshair = 0; void FCEU_KillVirtualVideo(void) @@ -43,6 +44,9 @@ void FCEU_KillVirtualVideo(void) if (XBuf) free(XBuf); XBuf = 0; + if (XDBuf) + free(XDBuf); + XDBuf = 0; } int FCEU_InitVirtualVideo(void) @@ -50,11 +54,14 @@ int FCEU_InitVirtualVideo(void) /* 256 bytes per scanline, * 240 scanline maximum, +8 for alignment, */ if (!XBuf) XBuf = (uint8*)(FCEU_malloc(256 * (256 + extrascanlines + 8))); + if (!XDBuf) + XDBuf = (uint8*)(FCEU_malloc(256 * (256 + extrascanlines + 8))); - if (!XBuf) + if (!XBuf || !XDBuf) return 0; - memset(XBuf, 128, 256 * (256 + extrascanlines)); + memset(XBuf, 128, 256 * (256 + extrascanlines + 8)); + memset(XDBuf, 128, 256 * (256 + extrascanlines + 8)); return 1; } diff --git a/src/video.h b/src/video.h index 55a5189..9eef95b 100644 --- a/src/video.h +++ b/src/video.h @@ -5,6 +5,7 @@ int FCEU_InitVirtualVideo(void); void FCEU_KillVirtualVideo(void); int SaveSnapshot(void); extern uint8 *XBuf; +extern uint8 *XDBuf; extern int show_crosshair; void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur);