mirror of https://github.com/mgba-emu/mgba.git
GUI: Add fast-forward key
This commit is contained in:
parent
400ac04d42
commit
9eb8faf1ba
1
CHANGES
1
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*);
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ 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) {
|
||||
|
|
Loading…
Reference in New Issue