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
endif
# used by crash handler and loading screen on linux
ifeq ($(WINDOWS_BUILD),0)
LDFLAGS += -rdynamic
LDFLAGS += -rdynamic -ldl -pthread
endif
# 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) {
if (id < 0 || id >= id_bhv_max_count) {
return NULL;
return smlua_get_name_from_hooked_behavior_id(id);
}
return gBehaviorTable[id].name;

View File

@ -2,7 +2,7 @@
#include "src/pc/loading.h"
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);
if (!modsDir) { return; }
@ -40,7 +40,7 @@ void DynOS_Gfx_GeneratePacks(const char* directory) {
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);

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);
set_sound_mode(save_file_get_sound_mode());
thread6_rumble_loop(NULL);
gGlobalTimer++;
}

View File

@ -36,6 +36,8 @@
#include "pc/lua/smlua_hooks.h"
#include "game/camera.h"
#include "level_info.h"
#include "pc/lua/utils/smlua_text_utils.h"
#include "pc/lua/utils/smlua_math_utils.h"
u16 gDialogColorFadeTimer;
s8 gLastDialogLineNum;
@ -2513,8 +2515,9 @@ void render_pause_my_score_coins(void) {
u8 strCourseNum[4];
u8 courseIndex = gCurrCourseNum - 1;
u8 starIndex = clamp(gDialogCourseActNum, 1, MAX_ACTS);
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;
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);
#endif
if (starFlags & (1 << (gDialogCourseActNum - 1))) {
if (starFlags & (1 << (starIndex - 1))) {
print_generic_string(TXT_STAR_X, 140, textStar);
} else {
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++) {
struct MarioState* marioState = &gMarioStates[i];
if (!is_player_active(marioState)) { continue; }
if (marioState->marioObj == NULL) { continue; }
spawn_object(marioState->marioObj, MODEL_NONE, bhvStarKeyCollectionPuffSpawner);
if (m->marioObj != NULL) {
spawn_object(m->marioObj, MODEL_NONE, bhvStarKeyCollectionPuffSpawner);
}
o->oInteractStatus = INT_STATUS_INTERACTED;
@ -2366,7 +2363,7 @@ void check_death_barrier(struct MarioState *m) {
if (!gLevelValues.bubbleOnDeathBarrierInCapStages){
break;
}
default:
default:
mario_set_bubbled(m);
return;
}

View File

@ -60,6 +60,7 @@ s16 gChangeLevel = -1;
s16 gChangeLevelTransition = -1;
s16 gChangeActNum = -1;
static bool sCancelNextActSelector = true; // Cancel the act selector after the main menu
static bool sFirstCastleGroundsMenu = true;
bool gIsDemoActive = false;
bool gInPlayerMenu = false;
@ -247,7 +248,7 @@ u16 level_control_timer(s32 timerOp) {
u32 pressed_pause(void) {
u32 dialogActive = get_dialog_id() >= 0;
u32 intangible = (gMarioState->action & ACT_FLAG_INTANGIBLE) != 0;
u32 firstPerson = gMarioState->action == ACT_FIRST_PERSON;
u32 firstPerson = gMarioState->action == ACT_FIRST_PERSON;
if (!intangible && !dialogActive && !firstPerson && !gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE
&& (gPlayer1Controller->buttonPressed & START_BUTTON)) {
@ -1637,6 +1638,7 @@ s32 update_level(void) {
if (gDjuiInMainMenu) {
update_menu_level();
}
sCancelNextActSelector = gDjuiInMainMenu;
if (gFanFareDebounce > 0) { gFanFareDebounce--; }
@ -1917,6 +1919,11 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) {
return 0;
}
if (sCancelNextActSelector) {
sCancelNextActSelector = false;
return 0;
}
return 1;
}

View File

@ -284,13 +284,10 @@ void bhv_mario_update(void) {
if ((stateIndex == 0) || (!is_player_active(gMarioState))) {
gMarioState->particleFlags = 0;
}
smlua_call_event_hooks_mario_param(HOOK_BEFORE_MARIO_UPDATE, gMarioState);
u32 particleFlags = 0;
s32 i;
particleFlags = execute_mario_action(gCurrentObject);
u32 particleFlags = execute_mario_action(gCurrentObject);
smlua_call_event_hooks_mario_param(HOOK_MARIO_UPDATE, gMarioState);
particleFlags |= gMarioState->particleFlags;
gCurrentObject->oMarioParticleFlags = particleFlags;
@ -320,14 +317,10 @@ void bhv_mario_update(void) {
// to sync it with the Mario object
copy_mario_state_to_object(gMarioState);
i = 0;
while (sParticleTypes[i].particleFlag != 0) {
for (s32 i = 0; sParticleTypes[i].particleFlag != 0; i++) {
if (particleFlags & sParticleTypes[i].particleFlag) {
spawn_particle(sParticleTypes[i].activeParticleFlag, sParticleTypes[i].model,
sParticleTypes[i].behavior);
spawn_particle(sParticleTypes[i].activeParticleFlag, sParticleTypes[i].model, sParticleTypes[i].behavior);
}
i++;
}
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;
}
// Cancel the act selector while on the main menu
if (gDjuiInMainMenu) { return 1; }
area_update_objects();
sActSelectorMenuTimer++;
return sLoadedActNum;

View File

@ -42,6 +42,8 @@ static CrashHandlerText sCrashHandlerText[128 + 256 + 4];
#define MEMNEW(typ, cnt) calloc(sizeof(typ), cnt)
#define STRING(str, size, fmt, ...) char str[size]; snprintf(str, size, fmt, __VA_ARGS__);
#define BACK_TRACE_SIZE 15
#ifdef _WIN32
#define OS_NAME "Windows"
@ -207,6 +209,7 @@ static void crash_handler_produce_one_frame(void) {
gfx_start_frame();
config_gfx_pool();
init_render_image();
create_dl_ortho_matrix();
float minAspectRatio = 1.743468f;
float aspectScale = 1.0f;
@ -306,7 +309,7 @@ static void crash_handler_add_info_int(CrashHandlerText** pTextP, f32 x, f32 y,
#ifdef _WIN32
static CRASH_HANDLER_TYPE crash_handler(EXCEPTION_POINTERS *ExceptionInfo) {
#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
printf("Game crashed! preparing crash screen...\n");
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] = "";
if (info->si_code == SEGV_MAPERR) {
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) {
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 {
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
crash_handler_set_text(8, 22, 0xFF, 0xFF, 0xFF, "%s", "Registers:");
#if defined(_WIN32) || (defined(__linux__) && defined(__x86_64__))
#ifdef _WIN32
if (ExceptionInfo && ExceptionInfo->ContextRecord) {
PCONTEXT cr = ExceptionInfo->ContextRecord;
@ -456,6 +462,9 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
} else {
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
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
s32 frames = CaptureStackWalkBackTrace(ExceptionInfo->ContextRecord, 0, 64, stack);
#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;
crash_handler_set_text( 8, y, 0xFF, 0xFF, 0x00, "0x%016llX", (PTR) stack[i]);
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__
void *trace[15];
int traceSize = backtrace(trace, 15);
void *trace[BACK_TRACE_SIZE];
u8 traceSize = backtrace(trace, BACK_TRACE_SIZE);
if (traceSize > 0) {
// Unwind and print call stack
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;
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", ": ");
@ -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());
s32 syncObjects = 0;
for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) {
if (so->o != NULL) { syncObjects++; }
if (gGameInited) {
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);
@ -664,10 +674,9 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont
}
#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);
djui_init();
djui_unicode_init();
if (!gGameInited) djui_unicode_init();
// Main loop
while (true) {

View File

@ -28,19 +28,28 @@ static bool sDjuiInited = false;
bool sDjuiRendered60fps = false;
void reset_djui_text(void);
void reset_djui(void) {
void djui_shutdown(void) {
sSavedDisplayListHead = NULL;
if (sDjuiPauseOptions) djui_base_destroy(&sDjuiPauseOptions->base);
if (sDjuiLuaError) djui_base_destroy(&sDjuiLuaError->base);
sDjuiPauseOptions = NULL;
sDjuiLuaError = NULL;
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;
sDjuiConsoleMessages = 0;
if (gDjuiRoot) {
djui_base_destroy(&gDjuiRoot->base);
}
djui_fps_display_destroy();
sDjuiInited = false;
}

View File

@ -47,4 +47,4 @@ void djui_lua_error(char* text);
void djui_render(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) {
if (gDjuiConsole != NULL) {
djui_base_destroy(&gDjuiConsole->base);
free(gDjuiConsole);
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) {
if (!sCursorMouseControlled) {
if (!sCursorMouseControlled && (!base || (base && base->interactable && base->interactable->enabled))) {
sInputControlledBase = base;
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) {
if (!base->visible) { return; }
if (base->interactable != NULL) {
if (base->interactable != NULL && base->interactable->enabled) {
f32 x1, y1, x2, y2;
x1 = base->elem.x;
y1 = base->elem.y;
@ -160,4 +160,4 @@ void djui_cursor_create(void) {
sMouseCursor = djui_image_create(NULL, gd_texture_hand_open, 32, 32, 16);
djui_base_set_location(&sMouseCursor->base, 0, 0);
djui_base_set_size(&sMouseCursor->base, 64, 64);
}
}

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) {
struct DjuiFpsDisplay *fpsDisplay = malloc(sizeof(struct DjuiFpsDisplay));
struct DjuiFpsDisplay *fpsDisplay = calloc(1, sizeof(struct DjuiFpsDisplay));
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_color(base, 0, 0, 0, 240);
djui_base_set_border_color(base, 0, 0, 0, 200);
@ -46,3 +50,9 @@ void djui_fps_display_create(void) {
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_render(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);
}
struct DjuiBase* djui_panel_find_first_interactable(struct DjuiBaseChild* child) {
static struct DjuiBase* djui_panel_find_first_interactable(struct DjuiBaseChild* child) {
while (child) {
if (child->base->interactable && child->base->interactable->enabled) {
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", "");
}
djui_panel_shutdown();
if (gPanelLanguageOnStartup) {
djui_panel_shutdown();
gDjuiInMainMenu = true;
djui_panel_main_create(NULL);
} else if (gDjuiInMainMenu) {
djui_panel_shutdown();
gDjuiInMainMenu = true;
djui_panel_main_create(NULL);
djui_panel_options_create(NULL);
djui_panel_misc_create(NULL);
} else if (gDjuiPanelPauseCreated) {
djui_panel_shutdown();
djui_panel_pause_create(NULL);
djui_panel_options_create(NULL);
djui_panel_misc_create(NULL);
} else {
djui_panel_shutdown();
}
}
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) {
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) {
djui_panel_confirm_create(caller,
@ -56,7 +56,7 @@ void djui_panel_pause_create(struct DjuiBase* caller) {
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(PAUSE, PAUSE_TITLE));
struct DjuiBase* body = djui_three_panel_get_body(panel);
{
struct DjuiRect* rect1 = djui_rect_container_create(body, 64);
{
djui_button_left_create(&rect1->base, DLANG(PAUSE, PLAYER), DJUI_BUTTON_STYLE_NORMAL, djui_panel_player_create);
@ -78,7 +78,7 @@ void djui_panel_pause_create(struct DjuiBase* caller) {
djui_button_create(body, DLANG(PAUSE, DISCONNECT), DJUI_BUTTON_STYLE_BACK, djui_panel_pause_quit);
}
}
djui_panel_add(caller, panel, defaultBase);
gInteractableOverridePad = true;
gDjuiPanelPauseCreated = true;

View File

@ -20,7 +20,7 @@ struct LoadingScreen {
struct DjuiProgressBar *loadingBar;
};
struct LoadingScreen* sLoading = NULL;
static struct LoadingScreen* sLoading = NULL;
pthread_t gLoadingThreadId;
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);
if (length > 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 {
snprintf(buffer, 256, "%s...", gCurrLoadingSegment.str);
}
@ -106,7 +106,7 @@ static void loading_screen_destroy(struct DjuiBase* base) {
}
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;
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);
gIsThreaded = false;
// reset some things after rendering the loading screen
reset_djui();
djui_base_destroy(base);
djui_shutdown();
alloc_display_list_reset();
gDisplayListHead = NULL;
djui_init();
djui_unicode_init();
rendering_init();
configWindow.settings_changed = true;
}

View File

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

View File

@ -1175,6 +1175,7 @@ struct LuaHookedBehavior {
u32 originalId;
BehaviorScript *behavior;
const BehaviorScript* originalBehavior;
const char* bhvName;
int initReference;
int loopReference;
bool replace;
@ -1235,6 +1236,15 @@ bool smlua_is_behavior_hooked(const BehaviorScript *behavior) {
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) {
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
LOG_ERROR("Hooked behaviors exceeded maximum references!");
@ -1392,6 +1402,7 @@ int smlua_hook_behavior(lua_State* L) {
hooked->overrideId = noOverrideId ? customBehaviorId : overrideBehaviorId;
hooked->originalId = customBehaviorId; // For LUA behaviors. The only behavior id they have IS their custom one.
hooked->originalBehavior = originalBehavior ? originalBehavior : hooked->behavior;
hooked->bhvName = bhvName;
hooked->initReference = initReference;
hooked->loopReference = loopReference;
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_get_hooked_behavior_from_id(enum BehaviorId id, bool returnOriginal);
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);
int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod);

View File

@ -45,7 +45,7 @@ u16 mods_get_enabled_count(void) {
if (!gLocalMods.entries[i]->enabled) { continue; }
enabled++;
}
return enabled;
}
@ -193,7 +193,7 @@ static u32 mods_count_directory(char* modsBasePath) {
}
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
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);
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
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[]
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
if (!mod_load(mods, modsBasePath, dir->d_name)) {
break;
}
if (gIsThreaded) { REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / count); }
REFRESH_MUTEX(gCurrLoadingSegment.percentage = (f32) i / count);
}
closedir(d);
if (gIsThreaded) { REFRESH_MUTEX(gCurrLoadingSegment.percentage = 1); }
REFRESH_MUTEX(gCurrLoadingSegment.percentage = 1);
}
void mods_refresh_local(void) {
@ -297,7 +297,7 @@ void mods_enable(char* relativePath) {
}
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
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(&gRemoteMods);
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();
camera_set_use_course_specific_settings(true);
free_vtx_scroll_targets();

View File

@ -258,6 +258,7 @@ void game_deinit(void) {
network_shutdown(true, true, false, false);
smlua_shutdown();
mods_shutdown();
djui_shutdown();
gGameInited = false;
}
@ -267,11 +268,13 @@ void game_exit(void) {
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();
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();
// load config
@ -288,12 +291,10 @@ void* main_game_init(UNUSED void* arg) {
mods_init();
enable_queued_mods();
if (gIsThreaded) {
REFRESH_MUTEX(
gCurrLoadingSegment.percentage = 0;
snprintf(gCurrLoadingSegment.str, 256, "Starting Game");
);
}
REFRESH_MUTEX(
gCurrLoadingSegment.percentage = 0;
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)
// 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; }
else if (gCLIOpts.fullscreen == 2) { configWindow.fullscreen = false; }
if (gCLIOpts.playerName[0] != '\0') {
snprintf(configPlayerName, MAX_PLAYER_STRING, "%s", gCLIOpts.playerName);
}
if (!gGfxInited) {
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);
}
#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();
sound_init();
bassh_init();
@ -352,21 +344,29 @@ int main(int argc, char *argv[]) {
// Start the thread for setting up the game
#ifndef WAPI_DXGI
if (pthread_mutex_init(&gLoadingThreadMutex, NULL) == 0 && pthread_create(&gLoadingThreadId, NULL, main_game_init, (void*) 1) == 0) {
gIsThreaded = true;
render_loading_screen(); // Render the loading screen while the game is setup
gIsThreaded = false;
} else {
#else
{
bool threadSuccess = false;
if (pthread_mutex_init(&gLoadingThreadMutex, NULL) == 0) {
if (pthread_create(&gLoadingThreadId, NULL, main_game_init, (void*) 1) == 0) {
render_loading_screen(); // Render the loading screen while the game is setup
threadSuccess = true;
}
pthread_mutex_destroy(&gLoadingThreadMutex);
}
if (!threadSuccess)
#endif
{
main_game_init(NULL); // Failsafe incase threading doesn't work
}
pthread_mutex_destroy(&gLoadingThreadMutex);
// initialize sm64 data and controllers
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
djui_init();
djui_unicode_init();