From 417b8c60228d9e828d14c89dd0a4d5b9b94b3e6f Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 22 Feb 2016 18:36:09 +0100 Subject: [PATCH] Add overclocking - backported from FCEUX with mods --- src/drivers/libretro/libretro.c | 91 ++++++++++++++++++++++++--------- src/fceu.c | 4 ++ src/fceu.h | 8 +++ src/ppu.c | 15 +++++- src/sound.c | 15 +++++- src/video.c | 4 +- src/x6502.c | 6 ++- src/x6502.h | 4 ++ 8 files changed, 114 insertions(+), 33 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 457eea1..ae22c7d 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -22,8 +22,8 @@ #include "../../unif.h" #include "../../fds.h" #include "../../vsuni.h" +#include "../../video.h" -#include #include "../../memstream.h" #if defined(_3DS) @@ -41,6 +41,15 @@ static bool use_raw_palette; /* emulator-specific variables */ +/* overclock the console by adding dummy scanlines to PPU loop + * disables DMC DMA and WaveHi filling for these dummies + * doesn't work with new PPU */ +unsigned overclocked = 0; +/* 7-bit samples have priority over overclocking */ +unsigned skip_7bit_overclocking = 1; +unsigned normal_scanlines = 240; +unsigned extrascanlines = 0; + int FCEUnetplay; #ifdef PSP #include "pspgu.h" @@ -52,9 +61,6 @@ static uint16_t* fceu_video_out; /* Some timing-related variables. */ -static int maxconbskip = 9; /* Maximum consecutive blit skips. */ -static int ffbskip = 9; /* Blit skips per blit when FF-ing */ - static int soundo = 1; static volatile int nofocus = 0; @@ -467,8 +473,9 @@ void retro_set_controller_port_device(unsigned a, unsigned b) void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { - { "nes_palette", "Color Palette; asqrealc|loopy|quor|chris|matt|pasofami|crashman|mess|zaphod-cv|zaphod-smb|vs-drmar|vs-cv|vs-smb|nintendo-vc|raw" }, - { "nes_nospritelimit", "No Sprite Limit; disabled|enabled" }, + { "fceumm_palette", "Color Palette; asqrealc|loopy|quor|chris|matt|pasofami|crashman|mess|zaphod-cv|zaphod-smb|vs-drmar|vs-cv|vs-smb|nintendo-vc|raw" }, + { "fceumm_nospritelimit", "No Sprite Limit; disabled|enabled" }, + { "fceumm_overclocking", "Overclocking; disabled|2x" }, { NULL, NULL }, }; @@ -608,57 +615,91 @@ static const keymap bindmap[] = { static void check_variables(void) { + static int overclock_state = -1; struct retro_variable var = {0}; - var.key = "nes_palette"; + var.key = "fceumm_palette"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { unsigned orig_value = current_palette; - if (strcmp(var.value, "asqrealc") == 0) + if (!strcmp(var.value, "asqrealc")) current_palette = 0; - else if (strcmp(var.value, "loopy") == 0) + else if (!strcmp(var.value, "loopy")) current_palette = 1; - else if (strcmp(var.value, "quor") == 0) + else if (!strcmp(var.value, "quor")) current_palette = 2; - else if (strcmp(var.value, "chris") == 0) + else if (!strcmp(var.value, "chris")) current_palette = 3; - else if (strcmp(var.value, "matt") == 0) + else if (!strcmp(var.value, "matt")) current_palette = 4; - else if (strcmp(var.value, "matt") == 0) + else if (!strcmp(var.value, "matt")) current_palette = 5; - else if (strcmp(var.value, "pasofami") == 0) + else if (!strcmp(var.value, "pasofami")) current_palette = 6; - else if (strcmp(var.value, "crashman") == 0) + else if (!strcmp(var.value, "crashman")) current_palette = 7; - else if (strcmp(var.value, "mess") == 0) + else if (!strcmp(var.value, "mess")) current_palette = 8; - else if (strcmp(var.value, "zaphod-cv") == 0) + else if (!strcmp(var.value, "zaphod-cv")) current_palette = 9; - else if (strcmp(var.value, "zaphod-smb") == 0) + else if (!strcmp(var.value, "zaphod-smb")) current_palette = 10; - else if (strcmp(var.value, "vs-drmar") == 0) + else if (!strcmp(var.value, "vs-drmar")) current_palette = 11; - else if (strcmp(var.value, "vs-cv") == 0) + else if (!strcmp(var.value, "vs-cv")) current_palette = 12; - else if (strcmp(var.value, "vs-smb") == 0) + else if (!strcmp(var.value, "vs-smb")) current_palette = 13; - else if (strcmp(var.value, "nintendo-vc") == 0) + else if (!strcmp(var.value, "nintendo-vc")) current_palette = 14; - else if (strcmp(var.value, "raw") == 0) + else if (!strcmp(var.value, "raw")) current_palette = 15; if (current_palette != orig_value) retro_set_custom_palette(); } - var.key = "nes_nospritelimit"; + + var.key = "fceumm_nospritelimit"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - int no_sprite_limit = (strcmp(var.value, "enabled") == 0) ? 1 : 0; + int no_sprite_limit = (!strcmp(var.value, "enabled")) ? 1 : 0; FCEUI_DisableSpriteLimitation(no_sprite_limit); } + + var.key = "fceumm_overclocking"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + bool do_reinit = false; + + if (!strcmp(var.value, "disabled") + && overclock_state != 0) + { + overclocked = 0; + skip_7bit_overclocking = 1; + extrascanlines = 0; + overclock_state = 0; + do_reinit = true; + } + else if (!strcmp(var.value, "2x") + && overclock_state != 1) + { + overclocked = 1; + skip_7bit_overclocking = 1; + extrascanlines = 266; + overclock_state = 1; + do_reinit = true; + } + + if (do_reinit) + { + FCEU_KillVirtualVideo(); + FCEU_InitVirtualVideo(); + } + } } /* diff --git a/src/fceu.c b/src/fceu.c index d2c20cb..5c87d9e 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -23,6 +23,7 @@ #include #include +#include "fceu.h" #include "fceu-types.h" #include "x6502.h" #include "fceu.h" @@ -48,6 +49,7 @@ uint64 timestampbase; +extern int totalscanlines; FCEUGI *GameInfo = NULL; void (*GameInterface)(int h); @@ -460,6 +462,8 @@ void FCEU_ResetVidSys(void) PAL = w ? 1 : 0; + totalscanlines = normal_scanlines + (overclocked ? extrascanlines : 0); + FCEUPPU_SetVideoSystem(w); SetSoundVariables(); } diff --git a/src/fceu.h b/src/fceu.h index 6f08aac..4825307 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -4,6 +4,14 @@ #include "fceu-types.h" extern int fceuindbg; + +extern unsigned overclocked; +extern unsigned skip_7bit_overclocking; +extern unsigned DMC_7bit; + +extern unsigned normal_scanlines; +extern unsigned extrascanlines; + void ResetGameLoaded(void); #define DECLFR(x) uint8 FP_FASTAPASS(1) x(uint32 A) diff --git a/src/ppu.c b/src/ppu.c index ce0fda3..c44dfb6 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -127,6 +127,8 @@ static int maxsprites = 8; int scanline; static uint32 scanlines_per_frame; +int totalscanlines; + uint8 PPU[4]; uint8 PPUSPL; uint8 NTARAM[0x800], PALRAM[0x20], SPRAM[0x100], SPRBUF[0x100]; @@ -1180,7 +1182,7 @@ int FCEUPPU_Loop(int skip) { kook ^= 1; } if (GameInfo->type == GIT_NSF) - X6502_Run((256 + 85) * 240); + X6502_Run((256 + 85) * normal_scanlines); #ifdef FRAMESKIP else if (skip) { int y; @@ -1209,11 +1211,20 @@ int FCEUPPU_Loop(int skip) { int x, max, maxref; deemp = PPU[1] >> 5; - for (scanline = 0; scanline < 240; ) { //scanline is incremented in DoLine. Evil. :/ + + // manual samples can't play correctly with overclocking + if (DMC_7bit && skip_7bit_overclocking) + totalscanlines = normal_scanlines; + else + totalscanlines = normal_scanlines + (overclocked ? extrascanlines : 0); + + for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/ deempcnt[deemp]++; if ((PPUViewer) && (scanline == PPUViewScanline)) UpdatePPUView(1); DoLine(); } + DMC_7bit = 0; + if (MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); for (x = 1, max = 0, maxref = 0; x < 7; x++) { if (deempcnt[x] > max) { diff --git a/src/sound.c b/src/sound.c index f60083e..14025d3 100644 --- a/src/sound.c +++ b/src/sound.c @@ -61,6 +61,7 @@ typedef struct { int reloaddec; } ENVUNIT; +unsigned DMC_7bit = 0; // used to skip overclocking static ENVUNIT EnvUnits[3]; static const int RectDuties[4] = { 1, 2, 4, 6 }; @@ -276,9 +277,19 @@ static DECLFW(Write_DMCRegs) { break; case 0x01: DoPCM(); RawDALatch = V & 0x7F; + if (RawDALatch) + DMC_7bit = 1; break; - case 0x02: DMCAddressLatch = V; break; - case 0x03: DMCSizeLatch = V; break; + case 0x02: + DMCAddressLatch = V; + if (V) + DMC_7bit = 0; + break; + case 0x03: + DMCSizeLatch = V; + if (V) + DMC_7bit = 0; + break; } } diff --git a/src/video.c b/src/video.c index 076579a..5db5b86 100644 --- a/src/video.c +++ b/src/video.c @@ -48,7 +48,7 @@ int FCEU_InitVirtualVideo(void) { // 256 bytes per scanline, * 240 scanline maximum, +8 for alignment, if (!XBuf) - XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8)); + XBuf = (uint8*)(FCEU_malloc(256 * (256 + extrascanlines + 8))); if (!XBuf) return 0; @@ -60,7 +60,7 @@ int FCEU_InitVirtualVideo(void) m = (4 - m) & 3; XBuf += m; } - memset(XBuf, 128, 256 * 256); + memset(XBuf, 128, 256 * (256 + extrascanlines)); return 1; } diff --git a/src/x6502.c b/src/x6502.c index bf1e49d..3415744 100644 --- a/src/x6502.c +++ b/src/x6502.c @@ -20,6 +20,7 @@ #include +#include "fceu.h" #include "fceu-types.h" #include "x6502.h" #include "fceu.h" @@ -51,7 +52,7 @@ void FP_FASTAPASS(1) (*MapIRQHook)(int a); int __x = x; \ _tcount += __x; \ _count -= __x * 48; \ - timestamp += __x; \ + if (scanline < normal_scanlines || scanline == totalscanlines) timestamp+= __x; \ } static INLINE uint8 RdMemNorm(uint32 A) { @@ -509,7 +510,8 @@ static void X6502_RunDebug(int32 cycles) { _tcount = 0; if (MapIRQHook) MapIRQHook(temp); - FCEU_SoundCPUHook(temp); + if (scanline < normal_scanlines || scanline == totalscanlines) + FCEU_SoundCPUHook(temp); _PC++; switch (b1) { diff --git a/src/x6502.h b/src/x6502.h index 0e9813f..d0520d2 100644 --- a/src/x6502.h +++ b/src/x6502.h @@ -23,6 +23,10 @@ #include "x6502struct.h" +extern int scanline; +extern unsigned normal_scanlines; +extern int totalscanlines; + #ifdef FCEUDEF_DEBUGGER void X6502_Debug(void (*CPUHook)(X6502 *), uint8 (*ReadHook)(X6502 *, uint32),