mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 05:25:14 +00:00
a bunch of fixes (#216)
Nice job targeting the main branch Isaac Co-Authored-By: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com>
This commit is contained in:
parent
2b6a173f8b
commit
594ff262bc
15 changed files with 122 additions and 85 deletions
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:](#)
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)) {
|
||||
cutscene_put_cap_on(m);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
} else {
|
||||
if (m->action == ACT_IDLE) {
|
||||
set_mario_action(m, ACT_PUTTING_ON_CAP, 0);
|
||||
} else {
|
||||
cutscene_put_cap_on(m);
|
||||
gCamera->paletteEditorCap = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
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]));
|
||||
|
|
|
@ -1895,13 +1895,11 @@ 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;
|
||||
}
|
||||
|
||||
stationary_ground_step(m);
|
||||
return FALSE;
|
||||
|
|
|
@ -613,5 +613,7 @@ bool djui_hud_is_pause_menu_created(void) {
|
|||
}
|
||||
|
||||
void djui_open_pause_menu(void) {
|
||||
if (!gDjuiPanelPauseCreated) {
|
||||
djui_panel_pause_create(NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
if (!gDjuiChatBoxFocus && gInteractableFocus != &gDjuiChatBox->chatInput->base) {
|
||||
djui_interactable_set_input_focus(NULL);
|
||||
}
|
||||
} else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) {
|
||||
// pressed main face button
|
||||
if (!gDjuiChatBoxFocus && gInteractableFocus != &gDjuiChatBox->chatInput->base) {
|
||||
djui_interactable_set_input_focus(NULL);
|
||||
}
|
||||
} else {
|
||||
djui_interactable_on_focus(gInteractableFocus);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1203,18 +1203,17 @@ 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
|
||||
{ "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] = {
|
||||
// { "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 },
|
||||
|
|
|
@ -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 <pthread.h>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue