GUI: Add fast-forward key
@@ -63,7 +63,9 @@ "Left",
"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 @@ break;
} #endif uint32_t guiKeys; - GUIPollInput(&runner->params, &guiKeys, 0); + uint32_t heldKeys; + GUIPollInput(&runner->params, &guiKeys, &heldKeys); if (guiKeys & (1 << GUI_INPUT_CANCEL)) { break; }@@ -360,6 +363,14 @@ }
} 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) {
@@ -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 @@ void (*drawScreenshot)(struct mGUIRunner*, const uint32_t* pixels, unsigned width, unsigned height, bool faded);
void (*paused)(struct mGUIRunner*); void (*unpaused)(struct mGUIRunner*); void (*incrementScreenMode)(struct mGUIRunner*); + void (*setFrameLimiter)(struct mGUIRunner*, bool limit); uint16_t (*pollGameInput)(struct mGUIRunner*); };
@@ -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 @@ ctrFinalize();
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 @@ unsigned mode;
if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + frameLimiter = true; runner->core->setAudioBufferSize(runner->core, AUDIO_SAMPLES); }@@ -300,6 +304,7 @@ CSND_SetPlayState(9, 0);
csndExecCmds(false); } osSetSpeedupEnable(false); + frameLimiter = true; switch (runner->core->platform(runner->core)) { #ifdef M_CORE_GBA@@ -460,6 +465,11 @@ C3D_RenderBufClear(&bottomScreen);
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 @@ .drawScreenshot = _drawScreenshot,
.paused = _gameUnloaded, .unpaused = _gameLoaded, .incrementScreenMode = _incrementScreenMode, + .setFrameLimiter = _setFrameLimiter, .pollGameInput = _pollGameInput };
@@ -31,10 +31,11 @@ }
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 @@ .drawScreenshot = mPSP2DrawScreenshot,
.paused = mPSP2Paused, .unpaused = mPSP2Unpaused, .incrementScreenMode = mPSP2IncrementScreenMode, + .setFrameLimiter = mPSP2SetFrameLimiter, .pollGameInput = mPSP2PollInput };
@@ -58,11 +58,12 @@ struct mRumble d;
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 @@ }
struct GBAStereoSample* buffer = audio->buffer.readPtr; RingFIFORead(&audio->buffer, NULL, len * 4); audio->samples -= len; + ConditionWake(&audio->cond); MutexUnlock(&audio->mutex); sceAudioOutOutput(audioPort, buffer);@@ -161,6 +163,11 @@ if (angles != GBA_KEY_NONE) {
activeKeys |= 1 << angles; } return activeKeys; +} + +void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + frameLimiter = limit; } void mPSP2Setup(struct mGUIRunner* runner) {@@ -200,6 +207,7 @@ rumble.d.setRumble = _setRumble;
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 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 @@ while (blip_samples_avail(runner->core->getAudioChannel(runner->core, 0)) >= PSP2_SAMPLES) {
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,8 +305,8 @@ 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;
@@ -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
@@ -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 @@ .drawFrame = _drawFrame,
.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);@@ -452,6 +457,11 @@ u32 level = 0;
_CPU_ISR_Disable(level); ++referenceRetraceCount; _CPU_ISR_Restore(level); +} + +static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + frameLimiter = limit; } static uint32_t _pollInput(const struct mInputMap* map) {@@ -585,11 +595,14 @@
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) {