mirror of https://github.com/snes9xgit/snes9x.git
libretro: Fix audio when video rendering is disabled
In commit 6628042fe3
, audio upload was
moved from retro_run() to S9xDeinitUpdate(). This breaks audio when
runahead is enabled in RetroArch.
With second-instance runahead, S9xDeinitUpdate() is not called when
video rendering is disabled and thus the core instance responsible for
audio is not uploading the audio. With single-instance runahead, audio
is uploaded twice because video rendering is always enabled and thus
S9xDeinitUpdate() gets called twice per frame.
Fix this by introducing a callback that gets called at the end of every
screen refresh, regardless of whether or not rendering is active for
this frame. We can then decide in the callback whether or not audio
should be uploaded.
This commit is contained in:
parent
6628042fe3
commit
1ea6ef5061
15
gfx.cpp
15
gfx.cpp
|
@ -98,6 +98,9 @@ bool8 S9xGraphicsInit (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GFX.EndScreenRefreshCallback = NULL;
|
||||||
|
GFX.EndScreenRefreshCallbackData = NULL;
|
||||||
|
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +110,9 @@ void S9xGraphicsDeinit (void)
|
||||||
if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; }
|
if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; }
|
||||||
if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; }
|
if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; }
|
||||||
if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; }
|
if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; }
|
||||||
|
|
||||||
|
GFX.EndScreenRefreshCallback = NULL;
|
||||||
|
GFX.EndScreenRefreshCallbackData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xGraphicsScreenResize (void)
|
void S9xGraphicsScreenResize (void)
|
||||||
|
@ -263,6 +269,15 @@ void S9xEndScreenRefresh (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GFX.EndScreenRefreshCallback)
|
||||||
|
GFX.EndScreenRefreshCallback(GFX.EndScreenRefreshCallbackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void S9xSetEndScreenRefreshCallback(const SGFX::Callback cb, void *const data)
|
||||||
|
{
|
||||||
|
GFX.EndScreenRefreshCallback = cb;
|
||||||
|
GFX.EndScreenRefreshCallbackData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderLine (uint8 C)
|
void RenderLine (uint8 C)
|
||||||
|
|
6
gfx.h
6
gfx.h
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
struct SGFX
|
struct SGFX
|
||||||
{
|
{
|
||||||
|
typedef void (*Callback)(void *);
|
||||||
|
|
||||||
const uint32 Pitch = sizeof(uint16) * MAX_SNES_WIDTH;
|
const uint32 Pitch = sizeof(uint16) * MAX_SNES_WIDTH;
|
||||||
const uint32 RealPPL = MAX_SNES_WIDTH; // true PPL of Screen buffer
|
const uint32 RealPPL = MAX_SNES_WIDTH; // true PPL of Screen buffer
|
||||||
const uint32 ScreenSize = MAX_SNES_WIDTH * SNES_HEIGHT_EXTENDED;
|
const uint32 ScreenSize = MAX_SNES_WIDTH * SNES_HEIGHT_EXTENDED;
|
||||||
|
@ -67,6 +69,9 @@ struct SGFX
|
||||||
const char *InfoString;
|
const char *InfoString;
|
||||||
uint32 InfoStringTimeout;
|
uint32 InfoStringTimeout;
|
||||||
char FrameDisplayString[256];
|
char FrameDisplayString[256];
|
||||||
|
|
||||||
|
Callback EndScreenRefreshCallback;
|
||||||
|
void *EndScreenRefreshCallbackData;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SBG
|
struct SBG
|
||||||
|
@ -202,6 +207,7 @@ struct COLOR_SUB
|
||||||
|
|
||||||
void S9xStartScreenRefresh (void);
|
void S9xStartScreenRefresh (void);
|
||||||
void S9xEndScreenRefresh (void);
|
void S9xEndScreenRefresh (void);
|
||||||
|
void S9xSetEndScreenRefreshCallback(SGFX::Callback cb, void *data);
|
||||||
void S9xBuildDirectColourMaps (void);
|
void S9xBuildDirectColourMaps (void);
|
||||||
void RenderLine (uint8);
|
void RenderLine (uint8);
|
||||||
void S9xComputeClipWindows (void);
|
void S9xComputeClipWindows (void);
|
||||||
|
|
|
@ -753,6 +753,24 @@ static void update_variables(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void S9xEndScreenRefreshCallback(void*)
|
||||||
|
{
|
||||||
|
if (Settings.Mute) {
|
||||||
|
S9xClearSamples();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<int16_t> audio_buffer;
|
||||||
|
|
||||||
|
size_t avail = S9xGetSampleCount();
|
||||||
|
|
||||||
|
if (audio_buffer.size() < avail)
|
||||||
|
audio_buffer.resize(avail);
|
||||||
|
|
||||||
|
S9xMixSamples((uint8*)&audio_buffer[0], avail);
|
||||||
|
audio_batch_cb(&audio_buffer[0], avail >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
void retro_get_system_info(struct retro_system_info *info)
|
void retro_get_system_info(struct retro_system_info *info)
|
||||||
{
|
{
|
||||||
memset(info,0,sizeof(retro_system_info));
|
memset(info,0,sizeof(retro_system_info));
|
||||||
|
@ -1358,6 +1376,7 @@ void retro_init(void)
|
||||||
ntsc_screen_buffer = (uint16*) calloc(1, MAX_SNES_WIDTH_NTSC * 2 * (MAX_SNES_HEIGHT + 16));
|
ntsc_screen_buffer = (uint16*) calloc(1, MAX_SNES_WIDTH_NTSC * 2 * (MAX_SNES_HEIGHT + 16));
|
||||||
snes_ntsc_buffer = ntsc_screen_buffer + (MAX_SNES_WIDTH_NTSC >> 1) * 16;
|
snes_ntsc_buffer = ntsc_screen_buffer + (MAX_SNES_WIDTH_NTSC >> 1) * 16;
|
||||||
S9xGraphicsInit();
|
S9xGraphicsInit();
|
||||||
|
S9xSetEndScreenRefreshCallback(S9xEndScreenRefreshCallback, NULL);
|
||||||
|
|
||||||
S9xInitInputDevices();
|
S9xInitInputDevices();
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
|
@ -2057,16 +2076,6 @@ bool8 S9xDeinitUpdate(int width, int height)
|
||||||
video_cb(GFX.Screen + ((int)(GFX.Pitch >> 1) * overscan_offset), width, height, GFX.Pitch);
|
video_cb(GFX.Screen + ((int)(GFX.Pitch >> 1) * overscan_offset), width, height, GFX.Pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<int16_t> audio_buffer;
|
|
||||||
|
|
||||||
size_t avail = S9xGetSampleCount();
|
|
||||||
|
|
||||||
if (audio_buffer.size() < avail)
|
|
||||||
audio_buffer.resize(avail);
|
|
||||||
|
|
||||||
S9xMixSamples((uint8*)&audio_buffer[0], avail);
|
|
||||||
audio_batch_cb(&audio_buffer[0], avail >> 1);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue