Skip to content

Commit

Permalink
(libretro) Force enable g_Config.bRenderDuplicateFrames + minor audio…
Browse files Browse the repository at this point in the history
… buffer tweaks
  • Loading branch information
jdgleaver committed Dec 7, 2021
1 parent d3d8789 commit cdbebc1
Showing 1 changed file with 18 additions and 42 deletions.
60 changes: 18 additions & 42 deletions libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@
// to calculating the average for the last 180
// frames, or 3 seconds of runtime...
#define AUDIO_FRAMES_MOVING_AVG_ALPHA (1.0f / 180.0f)
// Workaround for a RetroArch audio driver
// limitation: a maximum of 1024 frames
// can be written per call of audio_batch_cb()
#define AUDIO_BATCH_FRAMES_MAX 1024

static bool libretro_supports_bitmasks = false;

Expand All @@ -89,6 +85,9 @@ namespace Libretro
static int16_t *audioOutBuffer = NULL;
static uint32_t audioOutBufferSize = 0;
static float audioOutFramesAvg = 0.0f;
// Set this to an arbitrarily large value,
// it will be fine tuned in AudioUploadSamples()
static uint32_t audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;

static void AudioBufferFlush()
{
Expand All @@ -103,6 +102,7 @@ namespace Libretro
audioOutFramesAvg = (float)SAMPLERATE / (60.0f / 1.001f);
audioOutBufferSize = ((uint32_t)audioOutFramesAvg + 1) * 2;
audioOutBuffer = (int16_t *)malloc(audioOutBufferSize * sizeof(int16_t));
audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;

AudioBufferFlush();
}
Expand All @@ -114,6 +114,7 @@ namespace Libretro
audioOutBuffer = NULL;
audioOutBufferSize = 0;
audioOutFramesAvg = 0.0f;
audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;

AudioBufferFlush();
}
Expand Down Expand Up @@ -166,34 +167,14 @@ namespace Libretro

static void AudioUploadSamples()
{
// This is a gruesome hack...
// - The core specifies a fixed frame rate of (60.0f / 1.001f)
// and a fixed sample rate of 44100
// - This means the frontend expects exactly 735.735
// sample frames per call of retro_run()
// - But the core doesn't work like that...
// - Each call of UpdateSound() generates 512 sample
// frames at 44100 Hz
// - When a game runs internally at ~60 fps,
// this does indeed translate to 735.735 sample frames
// per call of retro_run()
// - When a game runs internally at ~30 fps, UpdateSound()
// gets called at *twice* the expected rate - so we
// get double the expected number of sample frames
// - By pushing twice the number of frames, we effectively
// force the frontend to run in slow motion
// (2x sample buffer size == 1/2 running speed)
// - The PSP can run at a variety of framerates; in each
// case, the core is abusing the frontend by sending
// too many/too few audio samples in order to force the
// correct run speed
// - The core should instead be notifying the frontend of
// framerate changes, and at each framerate it should be
// sending (44100 / framerate) audio sample frames
// - But doing this is a non-trivial task...
// - So the best we can do is keep a running average of the
// current ring buffer occupancy, and drain this amount
// on each call of retro_run()...
// - Provided that g_Config.bRenderDuplicateFrames is
// force enabled and frameskip is disabled, the mean
// of the buffer occupancy will approximate to this
// value in most cases
uint32_t framesAvailable = AudioBufferOccupancy();

if (framesAvailable > 0)
Expand All @@ -220,10 +201,15 @@ namespace Libretro
int16_t *audioOutBufferPtr = audioOutBuffer;
while (frames > 0)
{
uint32_t framesToWrite = (frames > AUDIO_BATCH_FRAMES_MAX) ?
AUDIO_BATCH_FRAMES_MAX : frames;
uint32_t framesToWrite = (frames > audioBatchFramesMax) ?
audioBatchFramesMax : frames;
uint32_t framesWritten = audio_batch_cb(audioOutBufferPtr,
framesToWrite);

if ((framesWritten < framesToWrite) &&
(framesWritten > 0))
audioBatchFramesMax = framesWritten;

audio_batch_cb(audioOutBufferPtr, framesToWrite);
frames -= framesToWrite;
audioOutBufferPtr += framesToWrite << 1;
}
Expand Down Expand Up @@ -386,7 +372,6 @@ static RetroOption<bool> ppsspp_gpu_hardware_transform("ppsspp_gpu_hardware_tran
static RetroOption<bool> ppsspp_vertex_cache("ppsspp_vertex_cache", "Vertex Cache (Speedhack)", false);
static RetroOption<bool> ppsspp_cheats("ppsspp_cheats", "Internal Cheats Support", false);
static RetroOption<IOTimingMethods> ppsspp_io_timing_method("ppsspp_io_timing_method", "IO Timing Method", { { "Fast", IOTimingMethods::IOTIMING_FAST }, { "Host", IOTimingMethods::IOTIMING_HOST }, { "Simulate UMD delays", IOTimingMethods::IOTIMING_REALISTIC } });
static RetroOption<bool> ppsspp_frame_duplication("ppsspp_frame_duplication", "Duplicate frames in 30hz games", false);
static RetroOption<bool> ppsspp_software_skinning("ppsspp_software_skinning", "Software Skinning", true);
static RetroOption<bool> ppsspp_ignore_bad_memory_access("ppsspp_ignore_bad_memory_access", "Ignore bad memory accesses", true);
static RetroOption<bool> ppsspp_lazy_texture_caching("ppsspp_lazy_texture_caching", "Lazy texture caching (Speedup)", false);
Expand All @@ -410,7 +395,6 @@ void retro_set_environment(retro_environment_t cb)
vars.push_back(ppsspp_auto_frameskip.GetOptions());
vars.push_back(ppsspp_frameskip.GetOptions());
vars.push_back(ppsspp_frameskiptype.GetOptions());
vars.push_back(ppsspp_frame_duplication.GetOptions());
vars.push_back(ppsspp_vertex_cache.GetOptions());
vars.push_back(ppsspp_fast_memory.GetOptions());
vars.push_back(ppsspp_block_transfer_gpu.GetOptions());
Expand Down Expand Up @@ -532,7 +516,6 @@ static void check_variables(CoreParameter &coreParam)
ppsspp_cpu_core.Update((CPUCore *)&g_Config.iCpuCore);
ppsspp_io_timing_method.Update((IOTimingMethods *)&g_Config.iIOTimingMethod);
ppsspp_lower_resolution_for_effects.Update(&g_Config.iBloomHack);
ppsspp_frame_duplication.Update(&g_Config.bRenderDuplicateFrames);
ppsspp_software_skinning.Update(&g_Config.bSoftwareSkinning);
ppsspp_ignore_bad_memory_access.Update(&g_Config.bIgnoreBadMemAccess);
ppsspp_lazy_texture_caching.Update(&g_Config.bTextureBackoffCache);
Expand Down Expand Up @@ -629,6 +612,7 @@ void retro_init(void)
g_Config.Load("", "");
g_Config.iInternalResolution = 0;
g_Config.sMACAddress = "12:34:56:78:9A:BC";
g_Config.bRenderDuplicateFrames = true;

const char* nickname = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_USERNAME, &nickname) && nickname)
Expand Down Expand Up @@ -937,14 +921,6 @@ void retro_run(void)
environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, nullptr);
return;
}

// Due to the fact that this core abuses the
// frontend audio buffer, we set a high(ish)
// frontend audio latency to help smooth
// things out...
unsigned audioLatency = 128;
environ_cb(RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY,
&audioLatency);
}

check_variables(PSP_CoreParameter());
Expand Down

0 comments on commit cdbebc1

Please sign in to comment.