From 594ff262bc6e7f080a1661cee73a5060a47121a7 Mon Sep 17 00:00:00 2001 From: Agent X <44549182+AgentXLP@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:37:42 -0400 Subject: [PATCH] a bunch of fixes (#216) Nice job targeting the main branch Isaac Co-Authored-By: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> --- autogen/convert_structs.py | 2 + autogen/lua_definitions/structs.lua | 1 - docs/lua/structs.md | 5 +- src/game/behaviors/cap.inc.c | 2 + src/game/camera.c | 36 ++++++----- src/game/mario_actions_cutscene.c | 10 ++-- src/pc/djui/djui_hud_utils.c | 4 +- src/pc/djui/djui_interactable.c | 8 ++- src/pc/djui/djui_panel_pause.c | 1 + src/pc/djui/djui_panel_player.c | 11 ++++ src/pc/lua/smlua.h | 1 + src/pc/lua/smlua_cobject_autogen.c | 21 ++++--- src/pc/lua/utils/smlua_audio_utils.c | 89 +++++++++++++++------------- src/pc/lua/utils/smlua_audio_utils.h | 4 ++ src/pc/pc_main.c | 12 +++- 15 files changed, 122 insertions(+), 85 deletions(-) diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 65fe7866..531e26c4 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -86,6 +86,7 @@ override_field_invisible = { "NetworkPlayer": [ "gag", "moderator", "discordId" ], "GraphNode": [ "_guard1", "_guard2" ], "Object": [ "firstSurface" ], + "ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ], } override_field_deprecated = { @@ -116,6 +117,7 @@ override_field_immutable = { "AnimationTable": [ "count" ], "Controller": [ "controllerData", "statusData" ], "FirstPersonCamera": [ "enabled" ], + "ModAudio": [ "isStream", "loaded" ], } override_field_version_excludes = { diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 7470e2ca..0f5c66c4 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1075,7 +1075,6 @@ --- @field public file ModFile --- @field public isStream boolean --- @field public loaded boolean ---- @field public sampleCopiesTail ModAudioSampleCopies --- @class ModAudioSampleCopies --- @field public next ModAudioSampleCopies diff --git a/docs/lua/structs.md b/docs/lua/structs.md index b09ec30d..2146f235 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1456,9 +1456,8 @@ | ----- | ---- | ------ | | baseVolume | `number` | | | file | [ModFile](structs.md#ModFile) | | -| isStream | `boolean` | | -| loaded | `boolean` | | -| sampleCopiesTail | [ModAudioSampleCopies](structs.md#ModAudioSampleCopies) | | +| isStream | `boolean` | read-only | +| loaded | `boolean` | read-only | [:arrow_up_small:](#) diff --git a/src/game/behaviors/cap.inc.c b/src/game/behaviors/cap.inc.c index 78407f05..1c9ae210 100644 --- a/src/game/behaviors/cap.inc.c +++ b/src/game/behaviors/cap.inc.c @@ -196,6 +196,8 @@ void bhv_normal_cap_init(void) { } void normal_cap_set_save_flags(void) { + if (o->oBehParams - 1 != 0) { return; } + save_file_clear_flags(SAVE_FLAG_CAP_ON_GROUND); switch (gCurrCourseNum) { diff --git a/src/game/camera.c b/src/game/camera.c index 6325b15f..07c2ff45 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -3349,11 +3349,13 @@ void update_camera(struct Camera *c) { // Make sure the palette editor cutscene is properly reset struct MarioState *m = gMarioState; - if (c->paletteEditorCap && c->cutscene != CUTSCENE_PALETTE_EDITOR && m->action != ACT_PUTTING_ON_CAP) { - if (!(m->flags & MARIO_CAP_ON_HEAD)) { + if (c->paletteEditorCap) { + if (m->flags & MARIO_CAP_ON_HEAD) { + c->paletteEditorCap = false; + } else if (c->cutscene != CUTSCENE_PALETTE_EDITOR && m->action != ACT_PUTTING_ON_CAP) { cutscene_put_cap_on(m); + c->paletteEditorCap = false; } - c->paletteEditorCap = false; } } @@ -10856,6 +10858,7 @@ BAD_RETURN(s32) cutscene_door_mode(struct Camera *c) { } // coop specific +extern struct DjuiText* gDjuiPaletteToggle; void cutscene_palette_editor(struct Camera *c) { if (!c) { return; } struct MarioState* m = gMarioState; @@ -10879,23 +10882,14 @@ void cutscene_palette_editor(struct Camera *c) { return; } + // Press the Z bind to toggle cap static bool pressed = false; if (gInteractablePad.button & PAD_BUTTON_Z) { - if (!pressed && m->action != ACT_TAKING_OFF_CAP && m->action != ACT_PUTTING_ON_CAP) { + if (!pressed && m->action == ACT_IDLE) { if (m->flags & MARIO_CAP_ON_HEAD) { - if (m->action == ACT_IDLE) { - set_mario_action(m, ACT_TAKING_OFF_CAP, 1); // Add palette editor action arg - } else { - cutscene_take_cap_off(m); - gCamera->paletteEditorCap = true; - } + set_mario_action(m, ACT_TAKING_OFF_CAP, 1); // Add palette editor action arg } else { - if (m->action == ACT_IDLE) { - set_mario_action(m, ACT_PUTTING_ON_CAP, 0); - } else { - cutscene_put_cap_on(m); - gCamera->paletteEditorCap = false; - } + set_mario_action(m, ACT_PUTTING_ON_CAP, 0); } } pressed = true; @@ -10903,6 +10897,16 @@ void cutscene_palette_editor(struct Camera *c) { pressed = false; } + // Hide text if it is not possible to toggle cap + if (gDjuiPaletteToggle) { + djui_base_set_visible( + &gDjuiPaletteToggle->base, + m->action == ACT_IDLE || + m->action == ACT_TAKING_OFF_CAP || + m->action == ACT_PUTTING_ON_CAP + ); + } + c->pos[0] = m->pos[0] + (0x200 * sins(m->faceAngle[1])); c->pos[1] = m->pos[1] + 0x80; c->pos[2] = m->pos[2] + (0x200 * coss(m->faceAngle[1])); diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 07134069..7db25ecf 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -1895,12 +1895,10 @@ s32 act_taking_off_cap(struct MarioState *m) { cutscene_take_cap_off(m); if (m->actionArg == 1) { gCamera->paletteEditorCap = true; } break; - default: - if (animFrame >= 30 || gCamera->cutscene != CUTSCENE_PALETTE_EDITOR) { - set_mario_action(m, ACT_IDLE, 0); - disable_time_stop(); - } - break; + } + if (animFrame >= 30 || gCamera->cutscene != CUTSCENE_PALETTE_EDITOR) { + set_mario_action(m, ACT_IDLE, 0); + disable_time_stop(); } stationary_ground_step(m); diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c index f43dd454..1a4847bb 100644 --- a/src/pc/djui/djui_hud_utils.c +++ b/src/pc/djui/djui_hud_utils.c @@ -613,5 +613,7 @@ bool djui_hud_is_pause_menu_created(void) { } void djui_open_pause_menu(void) { - djui_panel_pause_create(NULL); + if (!gDjuiPanelPauseCreated) { + djui_panel_pause_create(NULL); + } } diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c index 0a971125..20c1254a 100644 --- a/src/pc/djui/djui_interactable.c +++ b/src/pc/djui/djui_interactable.c @@ -406,10 +406,14 @@ void djui_interactable_update(void) { u16 mainButtons = PAD_BUTTON_A | PAD_BUTTON_B; if ((mouseButtons & MOUSE_BUTTON_1) && !(sLastMouseButtons && MOUSE_BUTTON_1) && !djui_cursor_inside_base(gInteractableFocus)) { // clicked outside of focused - djui_interactable_set_input_focus(NULL); + if (!gDjuiChatBoxFocus && gInteractableFocus != &gDjuiChatBox->chatInput->base) { + djui_interactable_set_input_focus(NULL); + } } else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) { // pressed main face button - djui_interactable_set_input_focus(NULL); + if (!gDjuiChatBoxFocus && gInteractableFocus != &gDjuiChatBox->chatInput->base) { + djui_interactable_set_input_focus(NULL); + } } else { djui_interactable_on_focus(gInteractableFocus); } diff --git a/src/pc/djui/djui_panel_pause.c b/src/pc/djui/djui_panel_pause.c index 3636da3f..9c993053 100644 --- a/src/pc/djui/djui_panel_pause.c +++ b/src/pc/djui/djui_panel_pause.c @@ -52,6 +52,7 @@ static void djui_panel_pause_quit(struct DjuiBase* caller) { } void djui_panel_pause_create(struct DjuiBase* caller) { + if (gDjuiPanelPauseCreated) { return; } if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); } struct DjuiBase* defaultBase = NULL; diff --git a/src/pc/djui/djui_panel_player.c b/src/pc/djui/djui_panel_player.c index 23779bff..c1a4b606 100644 --- a/src/pc/djui/djui_panel_player.c +++ b/src/pc/djui/djui_panel_player.c @@ -25,6 +25,8 @@ static struct DjuiInputbox* sPalettePresetNameTextBox = NULL; static struct DjuiRect *sColorRect = NULL; +struct DjuiText* gDjuiPaletteToggle = NULL; + void djui_panel_player_create(struct DjuiBase* caller); //////////////////////// @@ -307,6 +309,14 @@ static void djui_panel_player_edit_palette_create(struct DjuiBase* caller) { } djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back); + + { + struct DjuiText *text = djui_text_create(body, DLANG(PLAYER, CAP_TOGGLE)); + djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); + djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&text->base, 1.0f, 64); + gDjuiPaletteToggle = text; + } } djui_panel_add(caller, panel, NULL); @@ -458,6 +468,7 @@ void djui_panel_player_create(struct DjuiBase* caller) { djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size(&text->base, 1.0f, 64); + gDjuiPaletteToggle = text; } } diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index 93761200..240af930 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -28,6 +28,7 @@ #define LUA_STACK_CHECK_BEGIN() int __LUA_STACK_TOP = lua_gettop(gLuaState) #define LUA_STACK_CHECK_END() if ((__LUA_STACK_TOP) != lua_gettop(gLuaState)) { smlua_dump_stack(); fflush(stdout); } assert((__LUA_STACK_TOP) == lua_gettop(gLuaState)) #else +#define LOG_LUA_LINE_WARNING(...) { snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, __VA_ARGS__), sys_swap_backslashes(gDjuiConsoleTmpBuffer), djui_console_message_create(gDjuiConsoleTmpBuffer, CONSOLE_MESSAGE_WARNING); } #define LUA_STACK_CHECK_BEGIN() #define LUA_STACK_CHECK_END() #endif diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index f384081c..ff46bc1f 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1203,22 +1203,21 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = { // { "size", LVT_???, offsetof(struct Mod, size), true, LOT_??? }, <--- UNIMPLEMENTED }; -#define LUA_MOD_AUDIO_FIELD_COUNT 5 +#define LUA_MOD_AUDIO_FIELD_COUNT 4 static struct LuaObjectField sModAudioFields[LUA_MOD_AUDIO_FIELD_COUNT] = { - { "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE }, - { "file", LVT_COBJECT_P, offsetof(struct ModAudio, file), false, LOT_MODFILE }, - { "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), false, LOT_NONE }, - { "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), false, LOT_NONE }, - { "sampleCopiesTail", LVT_COBJECT_P, offsetof(struct ModAudio, sampleCopiesTail), false, LOT_MODAUDIOSAMPLECOPIES }, -// { "sound", LVT_???, offsetof(struct ModAudio, sound), false, LOT_??? }, <--- UNIMPLEMENTED + { "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE }, + { "file", LVT_COBJECT_P, offsetof(struct ModAudio, file), false, LOT_MODFILE }, + { "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), true, LOT_NONE }, + { "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), true, LOT_NONE }, }; #define LUA_MOD_AUDIO_SAMPLE_COPIES_FIELD_COUNT 3 static struct LuaObjectField sModAudioSampleCopiesFields[LUA_MOD_AUDIO_SAMPLE_COPIES_FIELD_COUNT] = { - { "next", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, next), false, LOT_MODAUDIOSAMPLECOPIES }, - { "parent", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, parent), false, LOT_MODAUDIO }, - { "prev", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, prev), false, LOT_MODAUDIOSAMPLECOPIES }, -// { "sound", LVT_???, offsetof(struct ModAudioSampleCopies, sound), false, LOT_??? }, <--- UNIMPLEMENTED +// { "decoder", LVT_???, offsetof(struct ModAudioSampleCopies, decoder), false, LOT_??? }, <--- UNIMPLEMENTED + { "next", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, next), false, LOT_MODAUDIOSAMPLECOPIES }, + { "parent", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, parent), false, LOT_MODAUDIO }, + { "prev", LVT_COBJECT_P, offsetof(struct ModAudioSampleCopies, prev), false, LOT_MODAUDIOSAMPLECOPIES }, +// { "sound", LVT_???, offsetof(struct ModAudioSampleCopies, sound), false, LOT_??? }, <--- UNIMPLEMENTED }; #define LUA_MOD_FILE_FIELD_COUNT 3 diff --git a/src/pc/lua/utils/smlua_audio_utils.c b/src/pc/lua/utils/smlua_audio_utils.c index d8bca69e..acabf05c 100644 --- a/src/pc/lua/utils/smlua_audio_utils.c +++ b/src/pc/lua/utils/smlua_audio_utils.c @@ -178,8 +178,8 @@ static struct ModAudio* find_mod_audio(struct ModFile* file) { } static bool audio_sanity_check(struct ModAudio* audio, bool isStream, const char* action) { - if (audio == NULL) { - LOG_LUA_LINE("Tried to %s unloaded audio stream", action); + if (audio == NULL || !audio->loaded) { + LOG_LUA_LINE("Tried to %s unloaded audio %s", action, audio->isStream ? "stream" : "sample"); return false; } if (isStream && !audio->isStream) { @@ -283,28 +283,26 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) { f_delete(f); // decode the audio buffer - // note: buffer and decoder are not freed after a successful call, because ma_decoder_init_memory() does not make copies of them - ma_decoder *decoder = calloc(1, sizeof(ma_decoder)); - ma_result result = ma_decoder_init_memory(buffer, size, NULL, decoder); + ma_result result = ma_decoder_init_memory(buffer, size, NULL, &audio->decoder); if (result != MA_SUCCESS) { - free(decoder); free(buffer); LOG_ERROR("failed to load audio file '%s': failed to decode raw audio: %d", filename, result); return NULL; } result = ma_sound_init_from_data_source( - &sModAudioEngine, decoder, + &sModAudioEngine, &audio->decoder, isStream ? MA_SOUND_STREAM_FLAGS : MA_SOUND_SAMPLE_FLAGS, NULL, &audio->sound ); if (result != MA_SUCCESS) { - free(decoder); free(buffer); LOG_ERROR("failed to load audio file '%s': %d", filename, result); return NULL; } + audio->buffer = buffer; + audio->bufferSize = size; audio->isStream = isStream; audio->loaded = true; return audio; @@ -320,7 +318,7 @@ void audio_stream_destroy(struct ModAudio* audio) { } ma_sound_uninit(&audio->sound); - dynamic_pool_free(sModAudioPool, audio); + audio->loaded = false; } void audio_stream_play(struct ModAudio* audio, bool restart, f32 volume) { @@ -437,7 +435,7 @@ void audio_stream_set_volume(struct ModAudio* audio, f32 volume) { // Use mutexes to be sure we don't try to delete the same memory at the same time #include static pthread_mutex_t sSampleCopyMutex = PTHREAD_MUTEX_INITIALIZER; -static struct ModAudioSampleCopies *sSampleCopiesPendingUninitTail = NULL; +static struct ModAudioSampleCopies *sSampleCopyFreeTail = NULL; // Called whenever a sample copy finishes playback (called from the miniaudio thread) // removes the copy from it's linked list, and adds it to the pending list @@ -448,48 +446,45 @@ static void audio_sample_copy_end_callback(void* userData, UNUSED ma_sound* soun if (copy->next) { copy->next->prev = copy->prev; } if (copy->prev) { copy->prev->next = copy->next; } if (!copy->next && !copy->prev) { - copy->parent->sampleCopiesTail = NULL; // Clear the pointer to this copy + // This is the last copy of this sample, clear the pointer to it + copy->parent->sampleCopiesTail = NULL; } copy->next = NULL; copy->prev = NULL; // add copy to list - if (!sSampleCopiesPendingUninitTail) { - sSampleCopiesPendingUninitTail = copy; - } else { - copy->prev = sSampleCopiesPendingUninitTail; - sSampleCopiesPendingUninitTail->next = copy; - sSampleCopiesPendingUninitTail = copy; + if (sSampleCopyFreeTail) { + copy->prev = sSampleCopyFreeTail; + sSampleCopyFreeTail->next = copy; } + sSampleCopyFreeTail = copy; + pthread_mutex_unlock(&sSampleCopyMutex); } +void audio_destroy_copies(struct ModAudioSampleCopies* node) { + while (node) { + struct ModAudioSampleCopies* prev = node->prev; + ma_sound_uninit(&node->sound); + free(node); + node = prev; + } +} + // Called every frame in the main thread from smlua_update() // Frees all audio sample copies that are in the pending list void audio_sample_destroy_pending_copies(void) { - if (sSampleCopiesPendingUninitTail) { + if (sSampleCopyFreeTail) { pthread_mutex_lock(&sSampleCopyMutex); - for (struct ModAudioSampleCopies *node = sSampleCopiesPendingUninitTail; node;) { - struct ModAudioSampleCopies *prev = node->prev; - ma_sound_stop(&node->sound); - ma_sound_uninit(&node->sound); - free(node); - node = prev; - } - sSampleCopiesPendingUninitTail = NULL; + audio_destroy_copies(sSampleCopyFreeTail); + sSampleCopyFreeTail = NULL; pthread_mutex_unlock(&sSampleCopyMutex); } } static void audio_sample_destroy_copies(struct ModAudio* audio) { pthread_mutex_lock(&sSampleCopyMutex); - for (struct ModAudioSampleCopies* node = audio->sampleCopiesTail; node;) { - struct ModAudioSampleCopies* prev = node->prev; - ma_sound_stop(&node->sound); - ma_sound_uninit(&node->sound); - free(node); - node = prev; - } + audio_destroy_copies(audio->sampleCopiesTail); audio->sampleCopiesTail = NULL; pthread_mutex_unlock(&sSampleCopyMutex); } @@ -508,7 +503,7 @@ void audio_sample_destroy(struct ModAudio* audio) { } ma_sound_stop(&audio->sound); ma_sound_uninit(&audio->sound); - dynamic_pool_free(sModAudioPool, audio); + audio->loaded = false; } void audio_sample_stop(struct ModAudio* audio) { @@ -530,18 +525,21 @@ void audio_sample_play(struct ModAudio* audio, Vec3f position, f32 volume) { ma_sound *sound = &audio->sound; if (ma_sound_is_playing(sound)) { struct ModAudioSampleCopies* copy = calloc(1, sizeof(struct ModAudioSampleCopies)); - ma_sound_init_copy(&sModAudioEngine, sound, MA_SOUND_SAMPLE_FLAGS, NULL, ©->sound); + ma_result result = ma_decoder_init_memory(audio->buffer, audio->bufferSize, NULL, ©->decoder); + if (result != MA_SUCCESS) { return; } + result = ma_sound_init_from_data_source(&sModAudioEngine, ©->decoder, MA_SOUND_SAMPLE_FLAGS, NULL, ©->sound); + if (result != MA_SUCCESS) { return; } + ma_sound_set_end_callback(©->sound, audio_sample_copy_end_callback, copy); copy->parent = audio; - if (!audio->sampleCopiesTail) { - audio->sampleCopiesTail = copy; - } else { + // Add to list + if (audio->sampleCopiesTail) { copy->prev = audio->sampleCopiesTail; audio->sampleCopiesTail->next = copy; - audio->sampleCopiesTail = copy; } + audio->sampleCopiesTail = copy; + sound = ©->sound; - ma_sound_set_end_callback(sound, audio_sample_copy_end_callback, copy); } f32 dist = 0; @@ -590,9 +588,16 @@ void audio_custom_shutdown(void) { struct DynamicPoolNode* prev = node->prev; struct ModAudio* audio = node->ptr; if (audio->isStream) { - audio_stream_destroy(audio); + if (audio->loaded) { ma_sound_uninit(&audio->sound); } + dynamic_pool_free(sModAudioPool, audio); } else { - audio_sample_destroy(audio); + if (audio->loaded) { + if (audio->sampleCopiesTail) { + audio_sample_destroy_copies(audio); + } + ma_sound_uninit(&audio->sound); + } + dynamic_pool_free(sModAudioPool, audio); } node = prev; } diff --git a/src/pc/lua/utils/smlua_audio_utils.h b/src/pc/lua/utils/smlua_audio_utils.h index 9a51b0e4..b540a35f 100644 --- a/src/pc/lua/utils/smlua_audio_utils.h +++ b/src/pc/lua/utils/smlua_audio_utils.h @@ -13,6 +13,7 @@ void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolu struct ModAudioSampleCopies { ma_sound sound; + ma_decoder decoder; struct ModAudioSampleCopies *next; struct ModAudioSampleCopies *prev; struct ModAudio *parent; @@ -21,6 +22,9 @@ struct ModAudioSampleCopies { struct ModAudio { struct ModFile* file; ma_sound sound; + ma_decoder decoder; + void *buffer; + u32 bufferSize; struct ModAudioSampleCopies* sampleCopiesTail; bool isStream; f32 baseVolume; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index ee653eb8..f452c0d8 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -175,23 +175,29 @@ void produce_interpolation_frames_and_delay(void) { gRenderingInterpolated = true; + // sanity check target time to deal with hangs and such + if (fabs(sFrameTargetTime - curTime) > 1) { sFrameTargetTime = curTime - 0.01f; } + // interpolate and render while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) { gfx_start_frame(); - f32 delta = (!configUncappedFramerate && configFrameLimit == FRAMERATE) ? 1 : MAX(MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1), 0); + f32 delta = ((!configUncappedFramerate && configFrameLimit == FRAMERATE) + ? 1.0f + : MAX(MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1.0f), 0.0f) + ); gRenderingDelta = delta; if (!gSkipInterpolationTitleScreen) { patch_interpolations(delta); } send_display_list(gGfxSPTask); gfx_end_frame(); // delay - if (!configUncappedFramerate && !configWindow.vsync) { + if (!configUncappedFramerate) { f64 targetDelta = 1.0 / (f64) configFrameLimit; f64 now = clock_elapsed_f64(); f64 actualDelta = now - curTime; if (actualDelta < targetDelta) { f64 delay = ((targetDelta - actualDelta) * 1000.0); - if (delay > 0) { WAPI.delay((u32) delay * 0.9); } + if (delay > 0.0f) { WAPI.delay((u32) delay); } } }