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:
Agent X 2024-07-17 08:37:42 -04:00
parent 2b6a173f8b
commit 594ff262bc
15 changed files with 122 additions and 85 deletions

View file

@ -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 = {

View file

@ -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

View file

@ -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:](#)

View file

@ -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) {

View file

@ -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]));

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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, &copy->sound);
ma_result result = ma_decoder_init_memory(audio->buffer, audio->bufferSize, NULL, &copy->decoder);
if (result != MA_SUCCESS) { return; }
result = ma_sound_init_from_data_source(&sModAudioEngine, &copy->decoder, MA_SOUND_SAMPLE_FLAGS, NULL, &copy->sound);
if (result != MA_SUCCESS) { return; }
ma_sound_set_end_callback(&copy->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 = &copy->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;
}

View file

@ -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;

View file

@ -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); }
}
}