diff --git a/src/audio/external.c b/src/audio/external.c index 2f42500c..07366162 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -13,7 +13,7 @@ #include "seq_ids.h" #include "dialog_ids.h" #include "level_table.h" -#include "pc/thread.h" +#include "pc/pc_main.h" #ifdef VERSION_EU #define EU_FLOAT(x) x ## f @@ -776,13 +776,6 @@ void create_next_audio_buffer(s16 *samples, u32 num_samples) { sGameLoopTicked = 0; } - // If the game thread is resetting the sound, don't process any audio commands - pcthread_mutex_lock(&pcthread_game_mutex); bool reseting_sound = pcthread_game_reset_sound; pcthread_mutex_unlock(&pcthread_game_mutex); - if (reseting_sound) { - printf("Audio thread: Dropped 1 frame\n"); - return; - } - s32 writtenCmds; synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples); gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount); @@ -2358,9 +2351,8 @@ void sound_reset(u8 presetId) { } #endif // Wait for audio thread to finish rendering - pcthread_mutex_lock(&pcthread_game_mutex); pcthread_game_reset_sound = true; pcthread_mutex_unlock(&pcthread_game_mutex); - pcthread_mutex_lock(&pcthread_audio_mutex); bool rendering = pcthread_audio_rendering; pcthread_mutex_unlock(&pcthread_audio_mutex); - if (rendering) pcthread_semaphore_wait(&pcthread_audio_sema); + pc_wait_for_audio(); + pc_request_gameloop_wait(); sGameLoopTicked = 0; disable_all_sequence_players(); diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 4eb33f0e..d4cd815c 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -69,6 +69,7 @@ sem_t pcthread_audio_sema; pthread_mutex_t pcthread_game_mutex = PTHREAD_MUTEX_INITIALIZER; bool pcthread_game_loop_iterating = false; bool pcthread_game_reset_sound = false; +bool pcthread_wait_for_gameloop = false; sem_t pcthread_game_sema; extern void gfx_run(Gfx *commands); @@ -84,6 +85,28 @@ void dispatch_audio_sptask(struct SPTask *spTask) { void set_vblank_handler(s32 index, struct VblankHandler *handler, OSMesgQueue *queue, OSMesg *msg) { } +// Send a request for non-game threads to wait for the game thread to finish +void pc_request_gameloop_wait(void) { + pcthread_mutex_lock(&pcthread_game_mutex); pcthread_wait_for_gameloop = true; pcthread_mutex_unlock(&pcthread_game_mutex); +} + +// Wait for the audio thread to finish rendering audio +void pc_wait_for_audio(void) { + pcthread_semaphore_wait(&pcthread_audio_sema); +} + +// Check if the audio thread is currently rendering audio +bool pc_check_audio_rendering(void) { + pcthread_mutex_lock(&pcthread_audio_mutex); bool rendering = pcthread_audio_rendering; pcthread_mutex_unlock(&pcthread_audio_mutex); + return rendering; +} + +// Check if the game thread should finish before continuing +bool pc_check_gameloop_wait(void) { + pcthread_mutex_lock(&pcthread_game_mutex); bool waiting = pcthread_wait_for_gameloop; pcthread_mutex_unlock(&pcthread_game_mutex); + return waiting; +} + static bool inited = false; #include "game/display.h" // for gGlobalTimer @@ -100,19 +123,6 @@ void send_display_list(struct SPTask *spTask) { #define SAMPLES_LOW 528 #endif -void lock_game_loop(bool unlock) { - pcthread_mutex_lock(&pcthread_game_mutex); - pcthread_game_loop_iterating = unlock; - pcthread_mutex_unlock(&pcthread_game_mutex); -} - -bool game_loop_locked() { - pcthread_mutex_lock(&pcthread_game_mutex); - bool locked = pcthread_game_loop_iterating; - pcthread_mutex_unlock(&pcthread_game_mutex); - return locked; -} - void produce_one_frame(void) { gfx_start_frame(); @@ -120,9 +130,9 @@ void produce_one_frame(void) { // Post the game thread semaphore if the game requested a sound reset pcthread_mutex_lock(&pcthread_game_mutex); - if (pcthread_game_reset_sound) { + if (pcthread_wait_for_gameloop) { pcthread_semaphore_post(&pcthread_game_sema); - pcthread_game_reset_sound = false; + pcthread_wait_for_gameloop = false; } pcthread_mutex_unlock(&pcthread_game_mutex); @@ -156,10 +166,14 @@ void* audio_thread() { } u32 num_audio_samples = audio_cnt < 2 ? 528 : 544;*/ - pcthread_mutex_lock(&pcthread_audio_mutex); pcthread_audio_rendering = true; pcthread_mutex_unlock(&pcthread_audio_mutex); - create_next_audio_buffer(audio_buffer, num_audio_samples); - pcthread_semaphore_post(&pcthread_audio_sema); - pcthread_mutex_lock(&pcthread_audio_mutex); pcthread_audio_rendering = false; pcthread_mutex_unlock(&pcthread_audio_mutex); + if (!pc_check_gameloop_wait()) { + pcthread_mutex_lock(&pcthread_audio_mutex); pcthread_audio_rendering = true; pcthread_mutex_unlock(&pcthread_audio_mutex); + create_next_audio_buffer(audio_buffer, num_audio_samples); + pcthread_semaphore_post(&pcthread_audio_sema); + pcthread_mutex_lock(&pcthread_audio_mutex); pcthread_audio_rendering = false; pcthread_mutex_unlock(&pcthread_audio_mutex); + } /* else { + printf("Audio thread: dropped frame\n"); + } */ // printf("Audio samples before submitting: %d\n", audio_api->buffered()); audio_api->play((u8 *)audio_buffer, num_audio_samples * 4); diff --git a/src/pc/pc_main.h b/src/pc/pc_main.h index 79bff549..568f3a91 100644 --- a/src/pc/pc_main.h +++ b/src/pc/pc_main.h @@ -5,9 +5,16 @@ extern "C" { #endif +#include + void game_deinit(void); void game_exit(void); +void pc_request_gameloop_wait(void); +void pc_wait_for_audio(void); +bool pc_check_audio_rendering(void); +bool pc_check_gameloop_wait(void); + #ifdef __cplusplus } #endif diff --git a/src/pc/thread.c b/src/pc/thread.c index 11de23be..f205900a 100644 --- a/src/pc/thread.c +++ b/src/pc/thread.c @@ -1,5 +1,7 @@ #include "thread.h" +// TODO: Cross-platform stuff + void pcthread_mutex_lock(pthread_mutex_t *mutex) { pthread_mutex_lock(mutex); } diff --git a/src/pc/thread.h b/src/pc/thread.h index 1a0a5efc..eeda592a 100644 --- a/src/pc/thread.h +++ b/src/pc/thread.h @@ -5,17 +5,6 @@ #include #include -extern pthread_t pcthread_audio_id; -extern pthread_mutex_t pcthread_audio_mutex; -extern sem_t pcthread_audio_sema; -extern bool pcthread_audio_init; -extern bool pcthread_audio_rendering; - -extern pthread_mutex_t pcthread_game_mutex; -extern sem_t pcthread_game_sema; -extern bool pcthread_game_loop_iterating; -extern bool pcthread_game_reset_sound; - void pcthread_mutex_lock(pthread_mutex_t *mutex); void pcthread_mutex_unlock(pthread_mutex_t *mutex); void pcthread_semaphore_init(sem_t *sem, int pshared, unsigned int value);