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);