cleanup and bug fixes

This commit is contained in:
Isaac0-dev 2024-03-19 19:48:48 +10:00
parent 5f81a88edd
commit f07b74c3d2
26 changed files with 141 additions and 100 deletions

View File

@ -868,8 +868,9 @@ else
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm $(BACKEND_LDFLAGS) -no-pie -lpthread LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm $(BACKEND_LDFLAGS) -no-pie -lpthread
endif endif
# used by crash handler and loading screen on linux
ifeq ($(WINDOWS_BUILD),0) ifeq ($(WINDOWS_BUILD),0)
LDFLAGS += -rdynamic LDFLAGS += -rdynamic -ldl -pthread
endif endif
# icon # icon

View File

@ -581,7 +581,7 @@ const BehaviorScript* get_behavior_from_id(enum BehaviorId id) {
const char* get_behavior_name_from_id(enum BehaviorId id) { const char* get_behavior_name_from_id(enum BehaviorId id) {
if (id < 0 || id >= id_bhv_max_count) { if (id < 0 || id >= id_bhv_max_count) {
return NULL; return smlua_get_name_from_hooked_behavior_id(id);
} }
return gBehaviorTable[id].name; return gBehaviorTable[id].name;

View File

@ -2,7 +2,7 @@
#include "src/pc/loading.h" #include "src/pc/loading.h"
void DynOS_Gfx_GeneratePacks(const char* directory) { void DynOS_Gfx_GeneratePacks(const char* directory) {
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In Path:\n\\#808080\\%s", directory)); } snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In Path:\n\\#808080\\%s", directory);
DIR *modsDir = opendir(directory); DIR *modsDir = opendir(directory);
if (!modsDir) { return; } if (!modsDir) { return; }
@ -40,7 +40,7 @@ void DynOS_Gfx_GeneratePacks(const char* directory) {
DynOS_Tex_GeneratePack(_TexturePackFolder, _TexturePackOutputFolder, true); DynOS_Tex_GeneratePack(_TexturePackFolder, _TexturePackOutputFolder, true);
} }
if (gIsThreaded) REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / (f32) pathCount); REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / (f32) pathCount);
} }
closedir(modsDir); closedir(modsDir);

View File

@ -588,6 +588,8 @@ void thread5_game_loop(UNUSED void *arg) {
play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0);
set_sound_mode(save_file_get_sound_mode()); set_sound_mode(save_file_get_sound_mode());
thread6_rumble_loop(NULL);
gGlobalTimer++; gGlobalTimer++;
} }

View File

@ -36,6 +36,8 @@
#include "pc/lua/smlua_hooks.h" #include "pc/lua/smlua_hooks.h"
#include "game/camera.h" #include "game/camera.h"
#include "level_info.h" #include "level_info.h"
#include "pc/lua/utils/smlua_text_utils.h"
#include "pc/lua/utils/smlua_math_utils.h"
u16 gDialogColorFadeTimer; u16 gDialogColorFadeTimer;
s8 gLastDialogLineNum; s8 gLastDialogLineNum;
@ -2513,8 +2515,9 @@ void render_pause_my_score_coins(void) {
u8 strCourseNum[4]; u8 strCourseNum[4];
u8 courseIndex = gCurrCourseNum - 1; u8 courseIndex = gCurrCourseNum - 1;
u8 starIndex = clamp(gDialogCourseActNum, 1, MAX_ACTS);
u8 *courseName = (u8*) get_level_name_sm64(gCurrCourseNum, gCurrLevelNum, gCurrAreaIndex, 1); u8 *courseName = (u8*) get_level_name_sm64(gCurrCourseNum, gCurrLevelNum, gCurrAreaIndex, 1);
u8 *actName = (u8*) get_star_name_sm64(gCurrCourseNum, gDialogCourseActNum, 1); u8 *actName = (u8*) get_star_name_sm64(gCurrCourseNum, starIndex, 1);
u8 starFlags; u8 starFlags;
starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1); starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1);
@ -2549,7 +2552,7 @@ void render_pause_my_score_coins(void) {
print_generic_string(CRS_NUM_X1, 157, strCourseNum); print_generic_string(CRS_NUM_X1, 157, strCourseNum);
#endif #endif
if (starFlags & (1 << (gDialogCourseActNum - 1))) { if (starFlags & (1 << (starIndex - 1))) {
print_generic_string(TXT_STAR_X, 140, textStar); print_generic_string(TXT_STAR_X, 140, textStar);
} else { } else {
print_generic_string(TXT_STAR_X, 140, textUnfilledStar); print_generic_string(TXT_STAR_X, 140, textUnfilledStar);

View File

@ -956,11 +956,8 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
} }
} }
for (s32 i = 0; i < MAX_PLAYERS; i++) { if (m->marioObj != NULL) {
struct MarioState* marioState = &gMarioStates[i]; spawn_object(m->marioObj, MODEL_NONE, bhvStarKeyCollectionPuffSpawner);
if (!is_player_active(marioState)) { continue; }
if (marioState->marioObj == NULL) { continue; }
spawn_object(marioState->marioObj, MODEL_NONE, bhvStarKeyCollectionPuffSpawner);
} }
o->oInteractStatus = INT_STATUS_INTERACTED; o->oInteractStatus = INT_STATUS_INTERACTED;

View File

@ -60,6 +60,7 @@ s16 gChangeLevel = -1;
s16 gChangeLevelTransition = -1; s16 gChangeLevelTransition = -1;
s16 gChangeActNum = -1; s16 gChangeActNum = -1;
static bool sCancelNextActSelector = true; // Cancel the act selector after the main menu
static bool sFirstCastleGroundsMenu = true; static bool sFirstCastleGroundsMenu = true;
bool gIsDemoActive = false; bool gIsDemoActive = false;
bool gInPlayerMenu = false; bool gInPlayerMenu = false;
@ -1637,6 +1638,7 @@ s32 update_level(void) {
if (gDjuiInMainMenu) { if (gDjuiInMainMenu) {
update_menu_level(); update_menu_level();
} }
sCancelNextActSelector = gDjuiInMainMenu;
if (gFanFareDebounce > 0) { gFanFareDebounce--; } if (gFanFareDebounce > 0) { gFanFareDebounce--; }
@ -1917,6 +1919,11 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) {
return 0; return 0;
} }
if (sCancelNextActSelector) {
sCancelNextActSelector = false;
return 0;
}
return 1; return 1;
} }

View File

@ -287,10 +287,7 @@ void bhv_mario_update(void) {
smlua_call_event_hooks_mario_param(HOOK_BEFORE_MARIO_UPDATE, gMarioState); smlua_call_event_hooks_mario_param(HOOK_BEFORE_MARIO_UPDATE, gMarioState);
u32 particleFlags = 0; u32 particleFlags = execute_mario_action(gCurrentObject);
s32 i;
particleFlags = execute_mario_action(gCurrentObject);
smlua_call_event_hooks_mario_param(HOOK_MARIO_UPDATE, gMarioState); smlua_call_event_hooks_mario_param(HOOK_MARIO_UPDATE, gMarioState);
particleFlags |= gMarioState->particleFlags; particleFlags |= gMarioState->particleFlags;
gCurrentObject->oMarioParticleFlags = particleFlags; gCurrentObject->oMarioParticleFlags = particleFlags;
@ -320,14 +317,10 @@ void bhv_mario_update(void) {
// to sync it with the Mario object // to sync it with the Mario object
copy_mario_state_to_object(gMarioState); copy_mario_state_to_object(gMarioState);
i = 0; for (s32 i = 0; sParticleTypes[i].particleFlag != 0; i++) {
while (sParticleTypes[i].particleFlag != 0) {
if (particleFlags & sParticleTypes[i].particleFlag) { if (particleFlags & sParticleTypes[i].particleFlag) {
spawn_particle(sParticleTypes[i].activeParticleFlag, sParticleTypes[i].model, spawn_particle(sParticleTypes[i].activeParticleFlag, sParticleTypes[i].model, sParticleTypes[i].behavior);
sParticleTypes[i].behavior);
} }
i++;
} }
update_character_anim_offset(gMarioState); update_character_anim_offset(gMarioState);

View File

@ -469,6 +469,9 @@ s32 lvl_update_obj_and_load_act_button_actions(UNUSED s32 arg, UNUSED s32 unused
sReceivedLoadedActNum = 0; sReceivedLoadedActNum = 0;
} }
// Cancel the act selector while on the main menu
if (gDjuiInMainMenu) { return 1; }
area_update_objects(); area_update_objects();
sActSelectorMenuTimer++; sActSelectorMenuTimer++;
return sLoadedActNum; return sLoadedActNum;

View File

@ -42,6 +42,8 @@ static CrashHandlerText sCrashHandlerText[128 + 256 + 4];
#define MEMNEW(typ, cnt) calloc(sizeof(typ), cnt) #define MEMNEW(typ, cnt) calloc(sizeof(typ), cnt)
#define STRING(str, size, fmt, ...) char str[size]; snprintf(str, size, fmt, __VA_ARGS__); #define STRING(str, size, fmt, ...) char str[size]; snprintf(str, size, fmt, __VA_ARGS__);
#define BACK_TRACE_SIZE 15
#ifdef _WIN32 #ifdef _WIN32
#define OS_NAME "Windows" #define OS_NAME "Windows"
@ -207,6 +209,7 @@ static void crash_handler_produce_one_frame(void) {
gfx_start_frame(); gfx_start_frame();
config_gfx_pool(); config_gfx_pool();
init_render_image(); init_render_image();
create_dl_ortho_matrix();
float minAspectRatio = 1.743468f; float minAspectRatio = 1.743468f;
float aspectScale = 1.0f; float aspectScale = 1.0f;
@ -306,7 +309,7 @@ static void crash_handler_add_info_int(CrashHandlerText** pTextP, f32 x, f32 y,
#ifdef _WIN32 #ifdef _WIN32
static CRASH_HANDLER_TYPE crash_handler(EXCEPTION_POINTERS *ExceptionInfo) { static CRASH_HANDLER_TYPE crash_handler(EXCEPTION_POINTERS *ExceptionInfo) {
#elif __linux__ #elif __linux__
static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *context) { static void crash_handler(const int signalNum, siginfo_t *info, UNUSED ucontext_t *context) {
#endif #endif
printf("Game crashed! preparing crash screen...\n"); printf("Game crashed! preparing crash screen...\n");
memset(sCrashHandlerText, 0, sizeof(sCrashHandlerText)); memset(sCrashHandlerText, 0, sizeof(sCrashHandlerText));
@ -352,8 +355,10 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
char segFaultStr[255] = ""; char segFaultStr[255] = "";
if (info->si_code == SEGV_MAPERR) { if (info->si_code == SEGV_MAPERR) {
snprintf(segFaultStr, 255, "The game tried to read unmapped memory at address %p", info->si_addr); snprintf(segFaultStr, 255, "The game tried to read unmapped memory at address %p", info->si_addr);
#ifdef __x86_64__
} else if (info->si_code == SEGV_ACCERR) { } else if (info->si_code == SEGV_ACCERR) {
snprintf(segFaultStr, 255, "The game tried to %s at address %016llX", ((context->uc_mcontext.gregs[REG_ERR] & 0x2) != 0 ? "write" : "read"), (u64) info->si_addr); snprintf(segFaultStr, 255, "The game tried to %s at address %016llX", ((context->uc_mcontext.gregs[REG_ERR] & 0x2) != 0 ? "write" : "read"), (u64) info->si_addr);
#endif
} else { } else {
snprintf(segFaultStr, 255, "Unknown segmentation fault at address %p", info->si_addr); snprintf(segFaultStr, 255, "Unknown segmentation fault at address %p", info->si_addr);
} }
@ -373,6 +378,7 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
// Registers // Registers
crash_handler_set_text(8, 22, 0xFF, 0xFF, 0xFF, "%s", "Registers:"); crash_handler_set_text(8, 22, 0xFF, 0xFF, 0xFF, "%s", "Registers:");
#if defined(_WIN32) || (defined(__linux__) && defined(__x86_64__))
#ifdef _WIN32 #ifdef _WIN32
if (ExceptionInfo && ExceptionInfo->ContextRecord) { if (ExceptionInfo && ExceptionInfo->ContextRecord) {
PCONTEXT cr = ExceptionInfo->ContextRecord; PCONTEXT cr = ExceptionInfo->ContextRecord;
@ -456,6 +462,9 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
} else { } else {
crash_handler_set_text(8, 30, 0x80, 0x80, 0x80, "%s", "Unable to access the registers."); crash_handler_set_text(8, 30, 0x80, 0x80, 0x80, "%s", "Unable to access the registers.");
} }
#else
crash_handler_set_text(8, 30, 0x80, 0x80, 0x80, "%s", "Cannot access the registers on this system.");
#endif
// Stack trace // Stack trace
crash_handler_set_text(8, 72, 0xFF, 0xFF, 0xFF, "%s", "Stack trace:"); crash_handler_set_text(8, 72, 0xFF, 0xFF, 0xFF, "%s", "Stack trace:");
@ -542,7 +551,7 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
#else #else
s32 frames = CaptureStackWalkBackTrace(ExceptionInfo->ContextRecord, 0, 64, stack); s32 frames = CaptureStackWalkBackTrace(ExceptionInfo->ContextRecord, 0, 64, stack);
#endif #endif
for (s32 i = 1, j = 0; i < frames && j < 15; ++i) { for (s32 i = 1, j = 0; i < frames && j < BACK_TRACE_SIZE; ++i) {
s32 y = 80 + j++ * 8; s32 y = 80 + j++ * 8;
crash_handler_set_text( 8, y, 0xFF, 0xFF, 0x00, "0x%016llX", (PTR) stack[i]); crash_handler_set_text( 8, y, 0xFF, 0xFF, 0x00, "0x%016llX", (PTR) stack[i]);
crash_handler_set_text(-1, y, 0xFF, 0xFF, 0xFF, "%s", ": "); crash_handler_set_text(-1, y, 0xFF, 0xFF, 0xFF, "%s", ": ");
@ -563,13 +572,12 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
} }
} }
#elif __linux__ #elif __linux__
void *trace[15]; void *trace[BACK_TRACE_SIZE];
int traceSize = backtrace(trace, 15); u8 traceSize = backtrace(trace, BACK_TRACE_SIZE);
if (traceSize > 0) { if (traceSize > 0) {
// Unwind and print call stack // Unwind and print call stack
char **messages = backtrace_symbols(trace, traceSize); char **messages = backtrace_symbols(trace, traceSize);
for (s32 i = 1, j = 0; i < traceSize && j < 15; ++i) { for (s32 i = 1, j = 0; i < traceSize && j < BACK_TRACE_SIZE; ++i) {
s32 y = 80 + j++ * 8; s32 y = 80 + j++ * 8;
crash_handler_set_text( 8, y, 0xFF, 0xFF, 0x00, "0x%016llX", (u64) strtoul(strstr(messages[i], "[") + 1, NULL, 16)); crash_handler_set_text( 8, y, 0xFF, 0xFF, 0x00, "0x%016llX", (u64) strtoul(strstr(messages[i], "[") + 1, NULL, 16));
crash_handler_set_text(-1, y, 0xFF, 0xFF, 0xFF, "%s", ": "); crash_handler_set_text(-1, y, 0xFF, 0xFF, 0xFF, "%s", ": ");
@ -595,8 +603,10 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
crash_handler_add_info_int(&pText, 315, -4 + (8 * 3), "Players", network_player_connected_count()); crash_handler_add_info_int(&pText, 315, -4 + (8 * 3), "Players", network_player_connected_count());
s32 syncObjects = 0; s32 syncObjects = 0;
for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (gGameInited) {
if (so->o != NULL) { syncObjects++; } for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) {
if (so->o != NULL) { syncObjects++; }
}
} }
crash_handler_add_info_int(&pText, 315, -4 + (8 * 4), "SyncObj", syncObjects); crash_handler_add_info_int(&pText, 315, -4 + (8 * 4), "SyncObj", syncObjects);
@ -664,10 +674,9 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
} }
#endif #endif
// Incase it crashed before the game window opened // In case the game crashed before the game window opened
if (!gGfxInited) gfx_init(&WAPI, &RAPI, TITLE); if (!gGfxInited) gfx_init(&WAPI, &RAPI, TITLE);
djui_init(); if (!gGameInited) djui_unicode_init();
djui_unicode_init();
// Main loop // Main loop
while (true) { while (true) {

View File

@ -28,19 +28,28 @@ static bool sDjuiInited = false;
bool sDjuiRendered60fps = false; bool sDjuiRendered60fps = false;
void reset_djui_text(void); void djui_shutdown(void) {
void reset_djui(void) {
sSavedDisplayListHead = NULL; sSavedDisplayListHead = NULL;
if (sDjuiPauseOptions) djui_base_destroy(&sDjuiPauseOptions->base);
if (sDjuiLuaError) djui_base_destroy(&sDjuiLuaError->base);
sDjuiPauseOptions = NULL; sDjuiPauseOptions = NULL;
sDjuiLuaError = NULL; sDjuiLuaError = NULL;
sDjuiLuaErrorTimeout = 0; sDjuiLuaErrorTimeout = 0;
if (gDjuiRoot) djui_base_destroy(&gDjuiRoot->base);
if (gDjuiConsole) djui_base_destroy(&gDjuiConsole->base); if (gDjuiConsole) {
djui_base_destroy(&gDjuiConsole->base);
free(gDjuiConsole);
gDjuiConsole = NULL;
}
extern u32 sDjuiConsoleMessages; extern u32 sDjuiConsoleMessages;
sDjuiConsoleMessages = 0; sDjuiConsoleMessages = 0;
if (gDjuiRoot) {
djui_base_destroy(&gDjuiRoot->base);
}
djui_fps_display_destroy();
sDjuiInited = false; sDjuiInited = false;
} }

View File

@ -47,4 +47,4 @@ void djui_lua_error(char* text);
void djui_render(void); void djui_render(void);
void djui_reset_hud_params(void); void djui_reset_hud_params(void);
void reset_djui(void); void djui_shutdown(void);

View File

@ -161,6 +161,7 @@ void djui_console_message_create(const char* message, enum ConsoleMessageLevel l
struct DjuiConsole* djui_console_create(void) { struct DjuiConsole* djui_console_create(void) {
if (gDjuiConsole != NULL) { if (gDjuiConsole != NULL) {
djui_base_destroy(&gDjuiConsole->base); djui_base_destroy(&gDjuiConsole->base);
free(gDjuiConsole);
gDjuiConsole = NULL; gDjuiConsole = NULL;
} }

View File

@ -48,7 +48,7 @@ static void djui_cursor_base_hover_location(struct DjuiBase* base, f32* x, f32*
} }
void djui_cursor_input_controlled_center(struct DjuiBase* base) { void djui_cursor_input_controlled_center(struct DjuiBase* base) {
if (!sCursorMouseControlled) { if (!sCursorMouseControlled && (!base || (base && base->interactable && base->interactable->enabled))) {
sInputControlledBase = base; sInputControlledBase = base;
djui_cursor_set_visible(base != NULL); djui_cursor_set_visible(base != NULL);
} }
@ -65,7 +65,7 @@ static f32 djui_cursor_base_distance(struct DjuiBase* base, f32 xScale, f32 ySca
static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase** pick, struct DjuiBase* base) { static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase** pick, struct DjuiBase* base) {
if (!base->visible) { return; } if (!base->visible) { return; }
if (base->interactable != NULL) { if (base->interactable != NULL && base->interactable->enabled) {
f32 x1, y1, x2, y2; f32 x1, y1, x2, y2;
x1 = base->elem.x; x1 = base->elem.x;
y1 = base->elem.y; y1 = base->elem.y;

View File

@ -23,10 +23,14 @@ void djui_fps_display_render(void) {
} }
} }
void djui_fps_display_on_destroy(UNUSED struct DjuiBase* base) {
free(sFpsDisplay);
}
void djui_fps_display_create(void) { void djui_fps_display_create(void) {
struct DjuiFpsDisplay *fpsDisplay = malloc(sizeof(struct DjuiFpsDisplay)); struct DjuiFpsDisplay *fpsDisplay = calloc(1, sizeof(struct DjuiFpsDisplay));
struct DjuiBase* base = &fpsDisplay->base; struct DjuiBase* base = &fpsDisplay->base;
djui_base_init(NULL, base, NULL, NULL); djui_base_init(NULL, base, NULL, djui_fps_display_on_destroy);
djui_base_set_size(base, 150, 50); djui_base_set_size(base, 150, 50);
djui_base_set_color(base, 0, 0, 0, 240); djui_base_set_color(base, 0, 0, 0, 240);
djui_base_set_border_color(base, 0, 0, 0, 200); djui_base_set_border_color(base, 0, 0, 0, 200);
@ -46,3 +50,9 @@ void djui_fps_display_create(void) {
sFpsDisplay = fpsDisplay; sFpsDisplay = fpsDisplay;
} }
void djui_fps_display_destroy(void) {
if (sFpsDisplay) {
djui_base_destroy(&sFpsDisplay->base);
}
}

View File

@ -4,3 +4,4 @@
void djui_fps_display_update(s16 fps); void djui_fps_display_update(s16 fps);
void djui_fps_display_render(void); void djui_fps_display_render(void);
void djui_fps_display_create(void); void djui_fps_display_create(void);
void djui_fps_display_destroy(void);

View File

@ -18,7 +18,7 @@ bool djui_panel_is_active(void) {
return (sPanelList != NULL); return (sPanelList != NULL);
} }
struct DjuiBase* djui_panel_find_first_interactable(struct DjuiBaseChild* child) { static struct DjuiBase* djui_panel_find_first_interactable(struct DjuiBaseChild* child) {
while (child) { while (child) {
if (child->base->interactable && child->base->interactable->enabled) { if (child->base->interactable && child->base->interactable->enabled) {
return child->base; return child->base;

View File

@ -48,23 +48,19 @@ static void djui_panel_language_destroy(UNUSED struct DjuiBase* caller) {
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", ""); snprintf(configLanguage, MAX_CONFIG_STRING, "%s", "");
} }
djui_panel_shutdown();
if (gPanelLanguageOnStartup) { if (gPanelLanguageOnStartup) {
djui_panel_shutdown();
gDjuiInMainMenu = true; gDjuiInMainMenu = true;
djui_panel_main_create(NULL); djui_panel_main_create(NULL);
} else if (gDjuiInMainMenu) { } else if (gDjuiInMainMenu) {
djui_panel_shutdown();
gDjuiInMainMenu = true; gDjuiInMainMenu = true;
djui_panel_main_create(NULL); djui_panel_main_create(NULL);
djui_panel_options_create(NULL); djui_panel_options_create(NULL);
djui_panel_misc_create(NULL); djui_panel_misc_create(NULL);
} else if (gDjuiPanelPauseCreated) { } else if (gDjuiPanelPauseCreated) {
djui_panel_shutdown();
djui_panel_pause_create(NULL); djui_panel_pause_create(NULL);
djui_panel_options_create(NULL); djui_panel_options_create(NULL);
djui_panel_misc_create(NULL); djui_panel_misc_create(NULL);
} else {
djui_panel_shutdown();
} }
} }
if (configLanguage[0] == '\0') { if (configLanguage[0] == '\0') {

View File

@ -34,7 +34,7 @@ void djui_panel_pause_disconnect_key_update(int scancode) {
} }
static void djui_panel_pause_quit(struct DjuiBase* caller) { static void djui_panel_pause_quit(struct DjuiBase* caller) {
if (find_object_with_behavior(bhvActSelector) != NULL || gMarioStates[0].action == ACT_PUSHING_DOOR || gMarioStates[0].action == ACT_PULLING_DOOR) { return; } if (gMarioStates[0].action == ACT_PUSHING_DOOR || gMarioStates[0].action == ACT_PULLING_DOOR) { return; }
if (gNetworkType == NT_SERVER) { if (gNetworkType == NT_SERVER) {
djui_panel_confirm_create(caller, djui_panel_confirm_create(caller,

View File

@ -20,7 +20,7 @@ struct LoadingScreen {
struct DjuiProgressBar *loadingBar; struct DjuiProgressBar *loadingBar;
}; };
struct LoadingScreen* sLoading = NULL; static struct LoadingScreen* sLoading = NULL;
pthread_t gLoadingThreadId; pthread_t gLoadingThreadId;
pthread_mutex_t gLoadingThreadMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t gLoadingThreadMutex = PTHREAD_MUTEX_INITIALIZER;
@ -77,7 +77,7 @@ static bool loading_screen_on_render(struct DjuiBase* base) {
u32 length = strlen(gCurrLoadingSegment.str); u32 length = strlen(gCurrLoadingSegment.str);
if (length > 0) { if (length > 0) {
if (gCurrLoadingSegment.percentage > 0) { if (gCurrLoadingSegment.percentage > 0) {
snprintf(buffer, 256, "%s\n\\#c8c8c8\\%d%%", gCurrLoadingSegment.str, (u8)floor(gCurrLoadingSegment.percentage * 100)); snprintf(buffer, 256, "%s\n\\#dcdcdc\\%d%%", gCurrLoadingSegment.str, (u8)floor(gCurrLoadingSegment.percentage * 100));
} else { } else {
snprintf(buffer, 256, "%s...", gCurrLoadingSegment.str); snprintf(buffer, 256, "%s...", gCurrLoadingSegment.str);
} }
@ -106,7 +106,7 @@ static void loading_screen_destroy(struct DjuiBase* base) {
} }
void render_loading_screen(void) { void render_loading_screen(void) {
struct LoadingScreen* load = malloc(sizeof(struct LoadingScreen)); struct LoadingScreen* load = calloc(1, sizeof(struct LoadingScreen));
struct DjuiBase* base = &load->base; struct DjuiBase* base = &load->base;
djui_base_init(NULL, base, loading_screen_on_render, loading_screen_destroy); djui_base_init(NULL, base, loading_screen_on_render, loading_screen_destroy);
@ -156,13 +156,13 @@ void render_loading_screen(void) {
} }
pthread_join(gLoadingThreadId, NULL); pthread_join(gLoadingThreadId, NULL);
gIsThreaded = false;
// reset some things after rendering the loading screen // reset some things after rendering the loading screen
reset_djui(); djui_base_destroy(base);
djui_shutdown();
alloc_display_list_reset(); alloc_display_list_reset();
gDisplayListHead = NULL; gDisplayListHead = NULL;
djui_init();
djui_unicode_init();
rendering_init(); rendering_init();
configWindow.settings_changed = true; configWindow.settings_changed = true;
} }

View File

@ -10,16 +10,18 @@ struct LoadingSegment {
extern struct LoadingSegment gCurrLoadingSegment; extern struct LoadingSegment gCurrLoadingSegment;
extern bool gIsThreaded;
#define REFRESH_MUTEX(...) \ #define REFRESH_MUTEX(...) \
if (gIsThreaded) { \
pthread_mutex_lock(&gLoadingThreadMutex); \ pthread_mutex_lock(&gLoadingThreadMutex); \
__VA_ARGS__; \ __VA_ARGS__; \
pthread_mutex_unlock(&gLoadingThreadMutex); \ pthread_mutex_unlock(&gLoadingThreadMutex); \
} \
extern pthread_t gLoadingThreadId; extern pthread_t gLoadingThreadId;
extern pthread_mutex_t gLoadingThreadMutex; extern pthread_mutex_t gLoadingThreadMutex;
extern bool gIsThreaded;
void render_loading_screen(void); void render_loading_screen(void);
#endif #endif

View File

@ -1175,6 +1175,7 @@ struct LuaHookedBehavior {
u32 originalId; u32 originalId;
BehaviorScript *behavior; BehaviorScript *behavior;
const BehaviorScript* originalBehavior; const BehaviorScript* originalBehavior;
const char* bhvName;
int initReference; int initReference;
int loopReference; int loopReference;
bool replace; bool replace;
@ -1235,6 +1236,15 @@ bool smlua_is_behavior_hooked(const BehaviorScript *behavior) {
return false; return false;
} }
const char* smlua_get_name_from_hooked_behavior_id(enum BehaviorId id) {
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &sHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
return hooked->bhvName;
}
return NULL;
}
int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) { int smlua_hook_custom_bhv(BehaviorScript *bhvScript, const char *bhvName) {
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) { if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
LOG_ERROR("Hooked behaviors exceeded maximum references!"); LOG_ERROR("Hooked behaviors exceeded maximum references!");
@ -1392,6 +1402,7 @@ int smlua_hook_behavior(lua_State* L) {
hooked->overrideId = noOverrideId ? customBehaviorId : overrideBehaviorId; hooked->overrideId = noOverrideId ? customBehaviorId : overrideBehaviorId;
hooked->originalId = customBehaviorId; // For LUA behaviors. The only behavior id they have IS their custom one. hooked->originalId = customBehaviorId; // For LUA behaviors. The only behavior id they have IS their custom one.
hooked->originalBehavior = originalBehavior ? originalBehavior : hooked->behavior; hooked->originalBehavior = originalBehavior ? originalBehavior : hooked->behavior;
hooked->bhvName = bhvName;
hooked->initReference = initReference; hooked->initReference = initReference;
hooked->loopReference = loopReference; hooked->loopReference = loopReference;
hooked->replace = replaceBehavior; hooked->replace = replaceBehavior;

View File

@ -152,6 +152,7 @@ enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior);
const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior); const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior);
const BehaviorScript* smlua_get_hooked_behavior_from_id(enum BehaviorId id, bool returnOriginal); const BehaviorScript* smlua_get_hooked_behavior_from_id(enum BehaviorId id, bool returnOriginal);
bool smlua_is_behavior_hooked(const BehaviorScript *behavior); bool smlua_is_behavior_hooked(const BehaviorScript *behavior);
const char* smlua_get_name_from_hooked_behavior_id(enum BehaviorId id);
bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* object, bool before); bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* object, bool before);
int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod); int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod);

View File

@ -193,7 +193,7 @@ static u32 mods_count_directory(char* modsBasePath) {
} }
static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath) { static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath) {
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath)); } REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath));
// generate bins // generate bins
dynos_generate_packs(modsBasePath); dynos_generate_packs(modsBasePath);
@ -223,7 +223,7 @@ static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath)
} }
f32 count = (f32) mods_count_directory(modsBasePath); f32 count = (f32) mods_count_directory(modsBasePath);
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mods In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath)); } REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mods In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath));
// iterate // iterate
char path[SYS_MAX_PATH] = { 0 }; char path[SYS_MAX_PATH] = { 0 };
@ -232,18 +232,18 @@ static void mods_load(struct Mods* mods, char* modsBasePath, bool isUserModPath)
// sanity check / fill path[] // sanity check / fill path[]
if (!directory_sanity_check(dir, modsBasePath, path)) { continue; } if (!directory_sanity_check(dir, modsBasePath, path)) { continue; }
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mod:\n\\#808080\\%s/%s", modsBasePath, dir->d_name)); } REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mod:\n\\#808080\\%s/%s", modsBasePath, dir->d_name));
// load the mod // load the mod
if (!mod_load(mods, modsBasePath, dir->d_name)) { if (!mod_load(mods, modsBasePath, dir->d_name)) {
break; break;
} }
if (gIsThreaded) { REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / count); } REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / count);
} }
closedir(d); closedir(d);
if (gIsThreaded) { REFRESH_MUTEX(gCurrLoadingSegment.percentage = 1); } REFRESH_MUTEX(gCurrLoadingSegment.percentage = 1);
} }
void mods_refresh_local(void) { void mods_refresh_local(void) {
@ -297,7 +297,7 @@ void mods_enable(char* relativePath) {
} }
void mods_init(void) { void mods_init(void) {
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Caching Mods")); } REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Caching Mods"));
// load mod cache // load mod cache
mod_cache_load(); mod_cache_load();

View File

@ -683,11 +683,6 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect
mods_clear(&gActiveMods); mods_clear(&gActiveMods);
mods_clear(&gRemoteMods); mods_clear(&gRemoteMods);
smlua_shutdown(); smlua_shutdown();
extern s16 gChangeLevel;
gChangeLevel = LEVEL_CASTLE_GROUNDS;
if (gSkipInterpolationTitleScreen || find_object_with_behavior(bhvActSelector) != NULL) {
dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 0);
}
network_player_init(); network_player_init();
camera_set_use_course_specific_settings(true); camera_set_use_course_specific_settings(true);
free_vtx_scroll_targets(); free_vtx_scroll_targets();

View File

@ -258,6 +258,7 @@ void game_deinit(void) {
network_shutdown(true, true, false, false); network_shutdown(true, true, false, false);
smlua_shutdown(); smlua_shutdown();
mods_shutdown(); mods_shutdown();
djui_shutdown();
gGameInited = false; gGameInited = false;
} }
@ -267,11 +268,13 @@ void game_exit(void) {
exit(0); exit(0);
} }
void* main_game_init(UNUSED void* arg) { void* main_game_init(void* isThreaded) {
gIsThreaded = isThreaded != NULL;
const char *userpath = gCLIOpts.savePath[0] ? gCLIOpts.savePath : sys_user_path(); const char *userpath = gCLIOpts.savePath[0] ? gCLIOpts.savePath : sys_user_path();
fs_init(sys_ropaths, FS_BASEDIR, userpath); fs_init(sys_ropaths, FS_BASEDIR, userpath);
if (gIsThreaded) { REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading")); } REFRESH_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading"));
dynos_gfx_init(); dynos_gfx_init();
// load config // load config
@ -288,12 +291,10 @@ void* main_game_init(UNUSED void* arg) {
mods_init(); mods_init();
enable_queued_mods(); enable_queued_mods();
if (gIsThreaded) { REFRESH_MUTEX(
REFRESH_MUTEX( gCurrLoadingSegment.percentage = 0;
gCurrLoadingSegment.percentage = 0; snprintf(gCurrLoadingSegment.str, 256, "Starting game");
snprintf(gCurrLoadingSegment.str, 256, "Starting Game"); );
);
}
// If coop_custom_palette_* values are not found in sm64config.txt, the custom palette config will use the default values (Mario's palette) // If coop_custom_palette_* values are not found in sm64config.txt, the custom palette config will use the default values (Mario's palette)
// But if no preset is found, that means the current palette is a custom palette // But if no preset is found, that means the current palette is a custom palette
@ -308,20 +309,11 @@ void* main_game_init(UNUSED void* arg) {
if (gCLIOpts.fullscreen == 1) { configWindow.fullscreen = true; } if (gCLIOpts.fullscreen == 1) { configWindow.fullscreen = true; }
else if (gCLIOpts.fullscreen == 2) { configWindow.fullscreen = false; } else if (gCLIOpts.fullscreen == 2) { configWindow.fullscreen = false; }
if (gCLIOpts.playerName[0] != '\0') {
snprintf(configPlayerName, MAX_PLAYER_STRING, "%s", gCLIOpts.playerName);
}
if (!gGfxInited) { if (!gGfxInited) {
gfx_init(&WAPI, &RAPI, TITLE); gfx_init(&WAPI, &RAPI, TITLE);
WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input); WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input);
} }
#if defined(AAPI_SDL1) || defined(AAPI_SDL2)
if (audio_api == NULL && audio_sdl.init()) { audio_api = &audio_sdl; }
#endif
if (audio_api == NULL) { audio_api = &audio_null; }
audio_init(); audio_init();
sound_init(); sound_init();
bassh_init(); bassh_init();
@ -352,21 +344,29 @@ int main(int argc, char *argv[]) {
// Start the thread for setting up the game // Start the thread for setting up the game
#ifndef WAPI_DXGI #ifndef WAPI_DXGI
if (pthread_mutex_init(&gLoadingThreadMutex, NULL) == 0 && pthread_create(&gLoadingThreadId, NULL, main_game_init, (void*) 1) == 0) { bool threadSuccess = false;
gIsThreaded = true; if (pthread_mutex_init(&gLoadingThreadMutex, NULL) == 0) {
render_loading_screen(); // Render the loading screen while the game is setup if (pthread_create(&gLoadingThreadId, NULL, main_game_init, (void*) 1) == 0) {
gIsThreaded = false; render_loading_screen(); // Render the loading screen while the game is setup
} else { threadSuccess = true;
#else }
{ pthread_mutex_destroy(&gLoadingThreadMutex);
}
if (!threadSuccess)
#endif #endif
{
main_game_init(NULL); // Failsafe incase threading doesn't work main_game_init(NULL); // Failsafe incase threading doesn't work
} }
pthread_mutex_destroy(&gLoadingThreadMutex);
// initialize sm64 data and controllers // initialize sm64 data and controllers
thread5_game_loop(NULL); thread5_game_loop(NULL);
// Initialize sound outside threads
#if defined(AAPI_SDL1) || defined(AAPI_SDL2)
if (!audio_api && audio_sdl.init()) { audio_api = &audio_sdl; }
#endif
if (!audio_api) { audio_api = &audio_null; }
// Initialize djui // Initialize djui
djui_init(); djui_init();
djui_unicode_init(); djui_unicode_init();