From 9eb8faf1bab99e69e7c62fb8d7daa85a5cc07adf Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 16 Aug 2016 23:24:07 -0700 Subject: [PATCH] GUI: Add fast-forward key --- CHANGES | 1 + src/feature/gui/gui-runner.c | 15 +++++++++++++-- src/feature/gui/gui-runner.h | 3 +++ src/platform/3ds/main.c | 13 ++++++++++++- src/platform/psp2/main.c | 4 +++- src/platform/psp2/psp2-context.c | 18 ++++++++++++++---- src/platform/psp2/psp2-context.h | 1 + src/platform/wii/main.c | 17 +++++++++++++++-- 8 files changed, 62 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 80ef8f455..80de3beb6 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Features: - Threaded rendering mode - Libretro: Memory map and achievement support (leiradel) - GUI: Add UI control remapping + - GUI: Add fast-forward Bugfixes: - SDL: Fix axes being mapped wrong - GBA Memory: Fix mirror on non-overdumped Classic NES games diff --git a/src/feature/gui/gui-runner.c b/src/feature/gui/gui-runner.c index 7922edb43..ce0e2ae60 100644 --- a/src/feature/gui/gui-runner.c +++ b/src/feature/gui/gui-runner.c @@ -63,7 +63,9 @@ static const struct mInputPlatformInfo _mGUIKeyInfo = { "Right", [mGUI_INPUT_INCREASE_BRIGHTNESS] = "Increase solar brightness", [mGUI_INPUT_DECREASE_BRIGHTNESS] = "Decrease solar brightness", - [mGUI_INPUT_SCREEN_MODE] = "Screen mode" + [mGUI_INPUT_SCREEN_MODE] = "Screen mode", + [mGUI_INPUT_SCREENSHOT] = "Take screenshot", + [mGUI_INPUT_FAST_FORWARD] = "Fast forward", }, .nKeys = GUI_INPUT_MAX }; @@ -344,7 +346,8 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) { } #endif uint32_t guiKeys; - GUIPollInput(&runner->params, &guiKeys, 0); + uint32_t heldKeys; + GUIPollInput(&runner->params, &guiKeys, &heldKeys); if (guiKeys & (1 << GUI_INPUT_CANCEL)) { break; } @@ -361,6 +364,14 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) { if (guiKeys & (1 << mGUI_INPUT_SCREEN_MODE) && runner->incrementScreenMode) { runner->incrementScreenMode(runner); } + if (guiKeys & (1 << mGUI_INPUT_SCREENSHOT)) { + mCoreTakeScreenshot(runner->core); + } + if (heldKeys & (1 << mGUI_INPUT_FAST_FORWARD)) { + runner->setFrameLimiter(runner, false); + } else { + runner->setFrameLimiter(runner, true); + } uint16_t keys = runner->pollGameInput(runner); if (runner->prepareForFrame) { runner->prepareForFrame(runner); diff --git a/src/feature/gui/gui-runner.h b/src/feature/gui/gui-runner.h index 5e5fc13b8..e6b77a2b7 100644 --- a/src/feature/gui/gui-runner.h +++ b/src/feature/gui/gui-runner.h @@ -18,6 +18,8 @@ enum mGUIInput { mGUI_INPUT_INCREASE_BRIGHTNESS = GUI_INPUT_USER_START, mGUI_INPUT_DECREASE_BRIGHTNESS, mGUI_INPUT_SCREEN_MODE, + mGUI_INPUT_SCREENSHOT, + mGUI_INPUT_FAST_FORWARD, }; struct mGUIBackground { @@ -64,6 +66,7 @@ struct mGUIRunner { void (*paused)(struct mGUIRunner*); void (*unpaused)(struct mGUIRunner*); void (*incrementScreenMode)(struct mGUIRunner*); + void (*setFrameLimiter)(struct mGUIRunner*, bool limit); uint16_t (*pollGameInput)(struct mGUIRunner*); }; diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 83f1ba1ae..d4121d6ba 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -64,6 +64,7 @@ static size_t audioPos = 0; static C3D_Tex outputTexture; static ndspWaveBuf dspBuffer[DSP_BUFFERS]; static int bufferId = 0; +static bool frameLimiter = true; static C3D_RenderBuf bottomScreen; static C3D_RenderBuf topScreen; @@ -182,7 +183,9 @@ static void _drawEnd(void) { C3D_RenderBufTransfer(&topScreen, (u32*) gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_RenderBufTransfer(&bottomScreen, (u32*) gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); gfxSwapBuffersGpu(); - gspWaitForEvent(GSPGPU_EVENT_VBlank0, false); + if (frameLimiter) { + gspWaitForEvent(GSPGPU_EVENT_VBlank0, false); + } } static int _batteryState(void) { @@ -245,6 +248,7 @@ static void _setup(struct mGUIRunner* runner) { if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + frameLimiter = true; runner->core->setAudioBufferSize(runner->core, AUDIO_SAMPLES); } @@ -300,6 +304,7 @@ static void _gameUnloaded(struct mGUIRunner* runner) { csndExecCmds(false); } osSetSpeedupEnable(false); + frameLimiter = true; switch (runner->core->platform(runner->core)) { #ifdef M_CORE_GBA @@ -460,6 +465,11 @@ static void _incrementScreenMode(struct mGUIRunner* runner) { C3D_RenderBufClear(&topScreen); } +static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + frameLimiter = limit; +} + static uint32_t _pollInput(const struct mInputMap* map) { hidScanInput(); int activeKeys = hidKeysHeld(); @@ -689,6 +699,7 @@ int main() { .paused = _gameUnloaded, .unpaused = _gameLoaded, .incrementScreenMode = _incrementScreenMode, + .setFrameLimiter = _setFrameLimiter, .pollGameInput = _pollGameInput }; diff --git a/src/platform/psp2/main.c b/src/platform/psp2/main.c index 9095ce288..e0f09c9cf 100644 --- a/src/platform/psp2/main.c +++ b/src/platform/psp2/main.c @@ -31,10 +31,11 @@ static void _drawStart(void) { static void _drawEnd(void) { static int oldVCount = 0; + extern bool frameLimiter; int vcount = oldVCount; vita2d_end_drawing(); oldVCount = sceDisplayGetVcount(); - vita2d_set_vblank_wait(oldVCount + 1 >= vcount); + vita2d_set_vblank_wait(frameLimiter && oldVCount + 1 >= vcount); vita2d_swap_buffers(); } @@ -146,6 +147,7 @@ int main() { .paused = mPSP2Paused, .unpaused = mPSP2Unpaused, .incrementScreenMode = mPSP2IncrementScreenMode, + .setFrameLimiter = mPSP2SetFrameLimiter, .pollGameInput = mPSP2PollInput }; diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index 1a328b1d1..3ae015532 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -58,11 +58,12 @@ static struct mSceRumble { struct CircleBuffer history; int current; } rumble; +bool frameLimiter = true; extern const uint8_t _binary_backdrop_png_start[]; static vita2d_texture* backdrop = 0; -#define PSP2_SAMPLES 64 +#define PSP2_SAMPLES 128 #define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 40) static struct mPSP2AudioContext { @@ -89,6 +90,7 @@ static THREAD_ENTRY _audioThread(void* context) { struct GBAStereoSample* buffer = audio->buffer.readPtr; RingFIFORead(&audio->buffer, NULL, len * 4); audio->samples -= len; + ConditionWake(&audio->cond); MutexUnlock(&audio->mutex); sceAudioOutOutput(audioPort, buffer); @@ -163,6 +165,11 @@ uint16_t mPSP2PollInput(struct mGUIRunner* runner) { return activeKeys; } +void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + frameLimiter = limit; +} + void mPSP2Setup(struct mGUIRunner* runner) { mCoreConfigSetDefaultIntValue(&runner->config, "threadedVideo", 1); mCoreLoadForeignConfig(runner->core, &runner->config); @@ -200,6 +207,7 @@ void mPSP2Setup(struct mGUIRunner* runner) { CircleBufferInit(&rumble.history, RUMBLE_PWM); runner->core->setRumble(runner->core, &rumble.d); + frameLimiter = true; backdrop = vita2d_load_PNG_buffer(_binary_backdrop_png_start); unsigned mode; @@ -210,7 +218,7 @@ void mPSP2Setup(struct mGUIRunner* runner) { void mPSP2LoadROM(struct mGUIRunner* runner) { scePowerSetArmClockFrequency(444); - double ratio = GBAAudioCalculateRatio(1, 60, 1); + double ratio = GBAAudioCalculateRatio(1, 60.0 / 1.001, 1); blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); @@ -246,7 +254,9 @@ void mPSP2PrepareForFrame(struct mGUIRunner* runner) { struct GBAStereoSample* samples = audioContext.buffer.writePtr; blip_read_samples(runner->core->getAudioChannel(runner->core, 0), &samples[0].left, PSP2_SAMPLES, true); blip_read_samples(runner->core->getAudioChannel(runner->core, 1), &samples[0].right, PSP2_SAMPLES, true); - RingFIFOWrite(&audioContext.buffer, NULL, PSP2_SAMPLES * 4); + if (!RingFIFOWrite(&audioContext.buffer, NULL, PSP2_SAMPLES * 4)) { + break; + } audioContext.samples += PSP2_SAMPLES; } ConditionWake(&audioContext.cond); @@ -295,9 +305,9 @@ void mPSP2Teardown(struct mGUIRunner* runner) { CircleBufferDeinit(&rumble.history); vita2d_free_texture(tex); vita2d_free_texture(screenshot); + frameLimiter = true; } - void _drawTex(vita2d_texture* t, unsigned width, unsigned height, bool faded) { unsigned w = width; unsigned h = height; diff --git a/src/platform/psp2/psp2-context.h b/src/platform/psp2/psp2-context.h index 2c61690b9..a4723e3c4 100644 --- a/src/platform/psp2/psp2-context.h +++ b/src/platform/psp2/psp2-context.h @@ -22,6 +22,7 @@ void mPSP2Unpaused(struct mGUIRunner* runner); void mPSP2Draw(struct mGUIRunner* runner, bool faded); void mPSP2DrawScreenshot(struct mGUIRunner* runner, const uint32_t* pixels, unsigned width, unsigned height, bool faded); void mPSP2IncrementScreenMode(struct mGUIRunner* runner); +void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit); uint16_t mPSP2PollInput(struct mGUIRunner* runner); #endif diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 363e93494..362c16efa 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -71,6 +71,7 @@ static void _gameUnloaded(struct mGUIRunner* runner); static void _unpaused(struct mGUIRunner* runner); static void _drawFrame(struct mGUIRunner* runner, bool faded); static uint16_t _pollGameInput(struct mGUIRunner* runner); +static void _setFrameLimiter(struct mGUIRunner* runner, bool limit); static void _incrementScreenMode(struct mGUIRunner* runner); static s8 WPAD_StickX(u8 chan, u8 right); @@ -88,6 +89,7 @@ static int32_t tiltY; static int32_t gyroZ; static uint32_t retraceCount; static uint32_t referenceRetraceCount; +static bool frameLimiter = true; static int scaleFactor; static unsigned corew, coreh; @@ -363,6 +365,7 @@ int main(int argc, char* argv[]) { .paused = _gameUnloaded, .unpaused = _unpaused, .incrementScreenMode = _incrementScreenMode, + .setFrameLimiter = _setFrameLimiter, .pollGameInput = _pollGameInput }; mGUIInit(&runner, "wii"); @@ -429,9 +432,11 @@ static void _drawStart(void) { u32 level = 0; _CPU_ISR_Disable(level); if (referenceRetraceCount >= retraceCount) { - VIDEO_WaitVSync(); + if (frameLimiter) { + VIDEO_WaitVSync(); + } + referenceRetraceCount = retraceCount; } - referenceRetraceCount = retraceCount; _CPU_ISR_Restore(level); GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); @@ -454,6 +459,11 @@ static void _drawEnd(void) { _CPU_ISR_Restore(level); } +static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + frameLimiter = limit; +} + static uint32_t _pollInput(const struct mInputMap* map) { PAD_ScanPads(); u16 padkeys = PAD_ButtonsHeld(0); @@ -585,11 +595,14 @@ void _setup(struct mGUIRunner* runner) { double ratio = GBAAudioCalculateRatio(1, 60 / 1.001, 1); blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); + + frameLimiter = true; } void _gameUnloaded(struct mGUIRunner* runner) { UNUSED(runner); AUDIO_StopDMA(); + frameLimiter = true; } void _gameLoaded(struct mGUIRunner* runner) {