Fix the ZFP dialog desync bug introduced post 0.7.

The core issue is that the sound-advancement callbacks (used only
for altering the ZFP dialog locations) were altered to be launched
asynchronously from the main thread. This meant that new dialog
could be detected before the waiting callbacks had run.

This patch moves audio callbacks back into the audio decoding thread
and protects them with the speech-channel mutex. This should
guarantee that cur_sub_chunk only appears as a value when consulting
the current subtitles after the callback has run completely.

Logic has also been added to CheckSubtitles to raise a warning in
the logs if the values get out of sync.
This commit is contained in:
Michael Martin
2020-09-27 18:01:14 -07:00
parent 6dff21ef52
commit 8da99fc5d1
2 changed files with 20 additions and 5 deletions
+3 -1
View File
@@ -198,10 +198,12 @@ StopTrack (void)
static void
DoTrackTag (TFB_SoundChunk *chunk)
{
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
if (chunk->callback)
Callback_add(chunk->callback, 0);
chunk->callback(0);
cur_sub_chunk = chunk;
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
}
// This func is called by PlayStream() when stream is about
+17 -4
View File
@@ -532,7 +532,7 @@ UpdateAnimations (bool paused)
BatchGraphics ();
// Advance and draw ambient, transit and talk animations
change = ProcessCommAnimations (clear_subtitles, paused);
if (change)
if (change || clear_subtitles)
RedrawSubtitles ();
UnbatchGraphics ();
clear_subtitles = FALSE;
@@ -1608,15 +1608,28 @@ static void
CheckSubtitles (void)
{
const UNICODE *pStr;
POINT baseline;
TEXT_ALIGN align;
pStr = GetTrackSubtitle ();
baseline = CommData.AlienTextBaseline;
align = CommData.AlienTextAlign;
if (pStr != SubtitleText.pStr)
if (pStr != SubtitleText.pStr ||
SubtitleText.baseline.x != baseline.x ||
SubtitleText.baseline.y != baseline.y ||
SubtitleText.align != align)
{ // Subtitles changed
clear_subtitles = TRUE;
// Baseline may be updated by the ZFP
SubtitleText.baseline = CommData.AlienTextBaseline;
SubtitleText.align = CommData.AlienTextAlign;
SubtitleText.baseline = baseline;
SubtitleText.align = align;
// Make a note in the logs if the update was multiframe
if (SubtitleText.pStr == pStr)
{
log_add (log_Warning, "Dialog text and location changed out of sync");
}
SubtitleText.pStr = pStr;
// may have been cleared too
if (pStr)