diff --git a/src/game/mario.c b/src/game/mario.c index 76b0c80fc..ecb6ed3c3 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1834,8 +1834,8 @@ static u8 prevent_hang(u32 hangPreventionActions[], u8* hangPreventionIndex) { dumped = TRUE; // open the log - FILE* f = NULL; - if (!logfile_open(&f)) { return TRUE; } + FILE* f = logfile_open(LFT_HANG); + if (f == NULL) { return TRUE; } // complain to console printf("#######################################\n"); @@ -1850,7 +1850,7 @@ static u8 prevent_hang(u32 hangPreventionActions[], u8* hangPreventionIndex) { } fprintf(f, "(gMarioState->action: hang prevention end)\n"); - logfile_close(); + logfile_close(LFT_HANG); // force the crash in debug mode #ifdef DEBUG diff --git a/src/pc/debuglog.h b/src/pc/debuglog.h index 46f689b65..14e234231 100644 --- a/src/pc/debuglog.h +++ b/src/pc/debuglog.h @@ -1,3 +1,6 @@ +#ifndef DEBUGLOG_H +#define DEBUGLOG_H + #include #include #include "pc/network/network.h" @@ -43,3 +46,5 @@ static void _debuglog_print_log(char* logType, char* filename) { #define LOG_INFO(...) #define LOG_ERROR(...) #endif + +#endif \ No newline at end of file diff --git a/src/pc/logfile.c b/src/pc/logfile.c index d301daa9d..ef2fdf740 100644 --- a/src/pc/logfile.c +++ b/src/pc/logfile.c @@ -5,37 +5,37 @@ #include #include #include "pc/fs/fs.h" +#include "pc/debuglog.h" +#include "logfile.h" -#define LOGFILE_NAME "errorlog.txt" +struct LogFile gLogFiles[LFT_MAX] = { + { .fileName = "hanglog.txt", .active = false, .firstOpen = true, .file = NULL }, + { .fileName = "discordlog.txt", .active = false, .firstOpen = true, .file = NULL } +}; -static bool firstOpen = true; -static bool active = false; -static FILE* logfile = NULL; - -bool logfile_open(FILE** f) { - if (active) { - *f = logfile; - return true; +FILE* logfile_open(enum LogFileType logFileType) { + struct LogFile* logfile = &gLogFiles[logFileType]; + if (logfile->active) { + return logfile->file; } - printf("Initiating logfile to '%s'\n", LOGFILE_NAME); + LOG_INFO("opening log file '%s'", logfile->fileName); + logfile->file = fopen(fs_get_write_path(logfile->fileName), logfile->firstOpen ? "w+" : "a"); + logfile->firstOpen = false; - logfile = fopen(fs_get_write_path(LOGFILE_NAME), "a"); - if (logfile == NULL) { return false; } - *f = logfile; + if (logfile->file == NULL) { return NULL; } - if (firstOpen) { - fprintf(logfile, "--- new run ---\n"); - firstOpen = false; - } - - active = true; - return logfile; + logfile->active = true; + return logfile->file; } -void logfile_close(void) { - if (!active) { return; } - fflush(logfile); - fclose(logfile); - active = false; -} \ No newline at end of file +void logfile_close(enum LogFileType logFileType) { + struct LogFile* logfile = &gLogFiles[logFileType]; + if (!logfile->active) { return; } + + fflush(logfile->file); + fclose(logfile->file); + + logfile->file = NULL; + logfile->active = false; +} diff --git a/src/pc/logfile.h b/src/pc/logfile.h index 89cee3d26..218f2e59f 100644 --- a/src/pc/logfile.h +++ b/src/pc/logfile.h @@ -1,7 +1,58 @@ #ifndef LOGFILE_H #define LOGFILE_H -bool logfile_open(FILE** f); -void logfile_close(void); +#include +#include "pc/debuglog.h" + +#pragma pack(1) +struct LogFile { + const char* fileName; + bool active; + bool firstOpen; + FILE* file; +}; + +enum LogFileType { + LFT_HANG, + LFT_DISCORD, + LFT_MAX +}; + +extern struct LogFile gLogFiles[]; + +FILE* logfile_open(enum LogFileType logFileType); +void logfile_close(enum LogFileType logFileType); + +static void _logfile_print_timestamp(enum LogFileType logFileType) { + FILE* f = gLogFiles[logFileType].file; + time_t ltime = time(NULL); + char* str = asctime(localtime(<ime)); + fprintf(f, "%.*s", (int)strlen(str) - 1, str); +} + +static void _logfile_print_log_type(enum LogFileType logFileType, char* logType) { + FILE* f = gLogFiles[logFileType].file; + fprintf(f, "\t[%s]\t", logType); +} + +static void _logfile_print_short_filename(enum LogFileType logFileType, char* filename, int fileLine) { + FILE* f = gLogFiles[logFileType].file; + char* last = strrchr(filename, '/'); + if (last != NULL) { + fprintf(f, "%s:%d\t\t", last + 1, fileLine); + } else { + fprintf(f, "???:%d\t\t", fileLine); + } +} + +static void _logfile_print_log(enum LogFileType logFileType, char* logType, char* filename, int fileLine) { + logfile_open(logFileType); + _logfile_print_timestamp(logFileType); + _logfile_print_log_type(logFileType, logType); + _logfile_print_short_filename(logFileType, filename, fileLine); +} + +#define LOGFILE_INFO(_LFT, ...) ( _logfile_print_log(_LFT, "INFO ", __FILE__, __LINE__), fprintf(gLogFiles[_LFT].file, __VA_ARGS__), fprintf(gLogFiles[_LFT].file, "\n"), LOG_INFO (__VA_ARGS__)) +#define LOGFILE_ERROR(_LFT, ...) ( _logfile_print_log(_LFT, "ERROR", __FILE__, __LINE__), fprintf(gLogFiles[_LFT].file, __VA_ARGS__), fprintf(gLogFiles[_LFT].file, "\n"), LOG_ERROR(__VA_ARGS__)) #endif diff --git a/src/pc/network/discord/activity.c b/src/pc/network/discord/activity.c index 8a0f8d656..5436996a4 100644 --- a/src/pc/network/discord/activity.c +++ b/src/pc/network/discord/activity.c @@ -1,24 +1,24 @@ #include "activity.h" #include "lobby.h" #include "discord_network.h" -#include "pc/debuglog.h" #include "pc/network/network.h" #include "pc/network/version.h" #include "pc/djui/djui.h" +#include "pc/logfile.h" #define HASH_LENGTH 8 struct DiscordActivity gCurActivity = { 0 }; static void on_activity_update_callback(UNUSED void* data, enum EDiscordResult result) { - LOG_INFO("> on_activity_update_callback returned %d", result); + LOGFILE_INFO(LFT_DISCORD, "> on_activity_update_callback returned %d", result); DISCORD_REQUIRE(result); } static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordLobby* lobby) { - LOG_INFO("> on_activity_join_callback returned %d, lobby %lld, owner %lld", result, lobby->id, lobby->owner_id); + LOGFILE_INFO(LFT_DISCORD, "> on_activity_join_callback returned %d, lobby %lld, owner %lld", result, lobby->id, lobby->owner_id); DISCORD_REQUIRE(result); if (gNetworkType != NT_NONE) { - LOG_ERROR("Joined lobby when already connected somewhere!"); + LOGFILE_ERROR(LFT_DISCORD, "Joined lobby when already connected somewhere!"); exit(0); return; } @@ -43,17 +43,18 @@ static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult res } static void on_activity_join(UNUSED void* data, const char* secret) { - LOG_INFO("> on_activity_join, secret: %s", secret); + LOGFILE_INFO(LFT_DISCORD, "> on_activity_join, secret: %s", secret); djui_connect_menu_open(); app.lobbies->connect_lobby_with_activity_secret(app.lobbies, (char*)secret, NULL, on_activity_join_callback); } static void on_activity_join_request_callback(UNUSED void* data, enum EDiscordResult result) { - LOG_INFO("> on_activity_join_request_callback returned %d", (int)result); + LOGFILE_INFO(LFT_DISCORD, "> on_activity_join_request_callback returned %d", (int)result); + DISCORD_REQUIRE(result); } static void on_activity_join_request(UNUSED void* data, struct DiscordUser* user) { - LOG_INFO("> on_activity_join_request from %lld", user->id); + LOGFILE_INFO(LFT_DISCORD, "> on_activity_join_request from %lld", user->id); //app.activities->send_request_reply(app.activities, user->id, DiscordActivityJoinRequestReply_Yes, NULL, on_activity_join_request_callback); } @@ -85,7 +86,7 @@ void discord_activity_update(bool hosting) { } app.activities->update_activity(app.activities, &gCurActivity, NULL, on_activity_update_callback); - LOG_INFO("set activity"); + LOGFILE_INFO(LFT_DISCORD, "set activity"); } struct IDiscordActivityEvents* discord_activity_initialize(void) { diff --git a/src/pc/network/discord/discord.c b/src/pc/network/discord/discord.c index 8f6529b9e..81085a8f8 100644 --- a/src/pc/network/discord/discord.c +++ b/src/pc/network/discord/discord.c @@ -3,9 +3,9 @@ #include "activity.h" #include "lobby.h" #include "discord_network.h" -#include "pc/debuglog.h" #include "pc/network/version.h" #include "pc/djui/djui.h" +#include "pc/logfile.h" #if defined(_WIN32) || defined(_WIN64) #include @@ -22,10 +22,18 @@ struct DiscordApplication app = { 0 }; bool gDiscordInitialized = false; bool gDiscordFailed = false; +static void discord_sdk_log_callback(void* hook_data, enum EDiscordLogLevel level, const char* message) { + LOGFILE_INFO(LFT_DISCORD, "callback (%d): %s", level, message); +} + void discord_fatal(int rc) { #if defined(_WIN32) || defined(_WIN64) char errorMessage[132] = { 0 }; snprintf(errorMessage, 132, "Discord threw an error.\r\n\r\nTo fix: \r\n1. Close the game.\r\n2. Restart Discord.\r\n3. Start the game.\r\n\r\nRC: %d", rc); + fflush(stdout); + fflush(stderr); + LOGFILE_ERROR(LFT_DISCORD, "discord fatal %d", rc); + logfile_close(LFT_DISCORD); int msgboxID = MessageBox(NULL, errorMessage, "Fatal Discord Error", @@ -84,13 +92,13 @@ static void set_instance_env_variable(void) { int instance = (gCLIOpts.Discord == 0) ? 0 : (gCLIOpts.Discord - 1); sprintf(environmentVariables, "DISCORD_INSTANCE_ID=%d", instance); putenv(environmentVariables); - LOG_INFO("set environment variables: %s", environmentVariables); + LOGFILE_INFO(LFT_DISCORD, "set environment variables: %s", environmentVariables); } static void get_oauth2_token_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordOAuth2Token* token) { - LOG_INFO("> get_oauth2_token_callback returned %d", result); + LOGFILE_INFO(LFT_DISCORD, "> get_oauth2_token_callback returned %d", result); if (result != DiscordResult_Ok) { return; } - LOG_INFO("OAuth2 token: %s", token->access_token); + LOGFILE_INFO(LFT_DISCORD, "OAuth2 token: %s", token->access_token); } static void register_launch_command(void) { @@ -99,7 +107,7 @@ static void register_launch_command(void) { #if defined(_WIN32) || defined(_WIN64) HMODULE hModule = GetModuleHandle(NULL); if (hModule == NULL) { - LOG_ERROR("unable to retrieve absolute path!"); + LOGFILE_ERROR(LFT_DISCORD, "unable to retrieve absolute path!"); return; } GetModuleFileName(hModule, cmd, sizeof(cmd)); @@ -108,17 +116,17 @@ static void register_launch_command(void) { snprintf(path, MAX_LAUNCH_CMD - 1, "/proc/%d/exe", getpid()); rc = readlink(path, cmd, MAX_LAUNCH_CMD - 1); if (rc <= 0) { - LOG_ERROR("unable to retrieve absolute path! rc = %d", rc); + LOGFILE_ERROR(LFT_DISCORD, "unable to retrieve absolute path! rc = %d", rc); return; } #endif strncat(cmd, " --discord 1", MAX_LAUNCH_CMD - 1); rc = app.activities->register_command(app.activities, cmd); if (rc != DiscordResult_Ok) { - LOG_ERROR("register command failed %d", rc); + LOGFILE_ERROR(LFT_DISCORD, "register command failed %d", rc); return; } - LOG_INFO("cmd: %s", cmd); + LOGFILE_INFO(LFT_DISCORD, "cmd: %s", cmd); } static void ns_discord_update(void) { @@ -132,6 +140,10 @@ static bool ns_discord_initialize(enum NetworkType networkType) { set_instance_env_variable(); #endif + if (app.core != NULL) { + app.core->set_log_hook(app.core, DiscordLogLevel_Debug, NULL, discord_sdk_log_callback); + } + if (!gDiscordInitialized) { // set up discord params struct DiscordCreateParams params; @@ -144,11 +156,14 @@ static bool ns_discord_initialize(enum NetworkType networkType) { params.lobby_events = discord_lobby_initialize(); int rc = DiscordCreate(DISCORD_VERSION, ¶ms, &app.core); + if (app.core != NULL) { + app.core->set_log_hook(app.core, DiscordLogLevel_Debug, NULL, discord_sdk_log_callback); + } gDiscordFailed = false; if (networkType != NT_NONE) { DISCORD_REQUIRE(rc); } else if (rc) { - LOG_ERROR("DiscordCreate failed: %d", rc); + LOGFILE_ERROR(LFT_DISCORD, "DiscordCreate failed: %d", rc); djui_popup_create("\\#ffa0a0\\Error:\\#c8c8c8\\ Could not detect Discord.\n\\#a0a0a0\\Try closing the game, restarting Discord, and opening the game again.", 3); gDiscordFailed = true; return false; @@ -175,7 +190,7 @@ static bool ns_discord_initialize(enum NetworkType networkType) { if (networkType == NT_SERVER) { discord_lobby_create(); } gDiscordInitialized = true; - LOG_INFO("initialized"); + LOGFILE_INFO(LFT_DISCORD, "initialized"); return true; } @@ -183,7 +198,7 @@ static bool ns_discord_initialize(enum NetworkType networkType) { static void ns_discord_shutdown(void) { if (!gDiscordInitialized) { return; } discord_lobby_leave(); - LOG_INFO("shutdown"); + LOGFILE_INFO(LFT_DISCORD, "shutdown"); } struct NetworkSystem gNetworkSystemDiscord = { diff --git a/src/pc/network/discord/discord_network.c b/src/pc/network/discord/discord_network.c index 03e80004a..2eac58b0b 100644 --- a/src/pc/network/discord/discord_network.c +++ b/src/pc/network/discord/discord_network.c @@ -1,6 +1,6 @@ #include "discord_network.h" #include "lobby.h" -#include "pc/debuglog.h" +#include "pc/logfile.h" int64_t gNetworkUserIds[MAX_PLAYERS] = { 0 }; @@ -46,25 +46,25 @@ void ns_discord_save_id(u8 localId, s64 networkId) { assert(localId > 0); assert(localId < MAX_PLAYERS); gNetworkUserIds[localId] = (networkId == 0) ? gNetworkUserIds[0] : networkId; - LOG_INFO("saved user id %d == %lld", localId, gNetworkUserIds[localId]); + LOGFILE_INFO(LFT_DISCORD, "saved user id %d == %lld", localId, gNetworkUserIds[localId]); } void ns_discord_clear_id(u8 localId) { if (localId == 0) { return; } assert(localId < MAX_PLAYERS); gNetworkUserIds[localId] = 0; - LOG_INFO("cleared user id %d == %lld", localId, gNetworkUserIds[localId]); + LOGFILE_INFO(LFT_DISCORD, "cleared user id %d == %lld", localId, gNetworkUserIds[localId]); } void discord_network_init(int64_t lobbyId) { DISCORD_REQUIRE(app.lobbies->connect_network(app.lobbies, lobbyId)); DISCORD_REQUIRE(app.lobbies->open_network_channel(app.lobbies, lobbyId, 0, false)); - LOG_INFO("network initialized"); + LOGFILE_INFO(LFT_DISCORD, "network initialized"); } void discord_network_shutdown(void) { app.lobbies->flush_network(app.lobbies); if (gCurLobbyId == 0) { return; } app.lobbies->disconnect_network(app.lobbies, gCurLobbyId); - LOG_INFO("shutdown network, lobby = %lld", gCurLobbyId); + LOGFILE_INFO(LFT_DISCORD, "shutdown network, lobby = %lld", gCurLobbyId); } \ No newline at end of file diff --git a/src/pc/network/discord/lobby.c b/src/pc/network/discord/lobby.c index 1d2561f3f..6858644fa 100644 --- a/src/pc/network/discord/lobby.c +++ b/src/pc/network/discord/lobby.c @@ -1,19 +1,20 @@ #include "lobby.h" #include "activity.h" #include "discord_network.h" -#include "pc/debuglog.h" +#include "pc/logfile.h" static bool isHosting = false; DiscordLobbyId gCurLobbyId = 0; static void on_lobby_create_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordLobby* lobby) { - LOG_INFO("> on_lobby_update returned %d", (int)result); - LOG_INFO("Lobby id: %lld", lobby->id); - LOG_INFO("Lobby type: %u", lobby->type); - LOG_INFO("Lobby owner id: %lld", lobby->owner_id); - LOG_INFO("Lobby secret: %s", lobby->secret); - LOG_INFO("Lobby capacity: %u", lobby->capacity); - LOG_INFO("Lobby locked: %d", lobby->locked); + LOGFILE_INFO(LFT_DISCORD, "> on_lobby_create returned %d", (int)result); + DISCORD_REQUIRE(result); + LOGFILE_INFO(LFT_DISCORD, "Lobby id: %lld", lobby->id); + LOGFILE_INFO(LFT_DISCORD, "Lobby type: %u", lobby->type); + LOGFILE_INFO(LFT_DISCORD, "Lobby owner id: %lld", lobby->owner_id); + LOGFILE_INFO(LFT_DISCORD, "Lobby secret: %s", lobby->secret); + LOGFILE_INFO(LFT_DISCORD, "Lobby capacity: %u", lobby->capacity); + LOGFILE_INFO(LFT_DISCORD, "Lobby locked: %d", lobby->locked); gCurActivity.type = DiscordActivityType_Playing; snprintf(gCurActivity.party.id, 128, "%lld", lobby->id); @@ -32,21 +33,21 @@ static void on_lobby_create_callback(UNUSED void* data, enum EDiscordResult resu } static void on_lobby_update(UNUSED void* data, int64_t lobbyId) { - LOG_INFO("> on_lobby_update id: %lld", lobbyId); + LOGFILE_INFO(LFT_DISCORD, "> on_lobby_update id: %lld", lobbyId); } static void on_member_connect(UNUSED void* data, int64_t lobbyId, int64_t userId) { - LOG_INFO("> on_member_connect lobby: %lld, user: %lld", lobbyId, userId); + LOGFILE_INFO(LFT_DISCORD, "> on_member_connect lobby: %lld, user: %lld", lobbyId, userId); gCurActivity.party.size.current_size++; discord_activity_update(true); } static void on_member_update(UNUSED void* data, int64_t lobbyId, int64_t userId) { - LOG_INFO("> on_member_update lobby: %lld, user: %lld", lobbyId, userId); + LOGFILE_INFO(LFT_DISCORD, "> on_member_update lobby: %lld, user: %lld", lobbyId, userId); } static void on_member_disconnect(UNUSED void* data, int64_t lobbyId, int64_t userId) { - LOG_INFO("> on_member_disconnect lobby: %lld, user: %lld", lobbyId, userId); + LOGFILE_INFO(LFT_DISCORD, "> on_member_disconnect lobby: %lld, user: %lld", lobbyId, userId); u8 localIndex = discord_user_id_to_local_index(userId); if (localIndex != UNKNOWN_LOCAL_INDEX && gNetworkPlayers[localIndex].connected) { network_player_disconnected(gNetworkPlayers[localIndex].globalIndex); @@ -67,7 +68,8 @@ void discord_lobby_create(void) { } static void on_lobby_leave_callback(UNUSED void* data, enum EDiscordResult result) { - LOG_INFO("> on_lobby_leave returned %d", result); + LOGFILE_INFO(LFT_DISCORD, "> on_lobby_leave returned %d", result); + DISCORD_REQUIRE(result); } void discord_lobby_leave(void) { @@ -80,7 +82,7 @@ void discord_lobby_leave(void) { app.lobbies->disconnect_lobby(app.lobbies, gCurLobbyId, NULL, on_lobby_leave_callback); } - LOG_INFO("left lobby %lld", gCurLobbyId); + LOGFILE_INFO(LFT_DISCORD, "left lobby %lld", gCurLobbyId); isHosting = false; gCurLobbyId = 0; diff --git a/src/pc/network/discord/user.c b/src/pc/network/discord/user.c index 2c0efcc6a..2600d36e5 100644 --- a/src/pc/network/discord/user.c +++ b/src/pc/network/discord/user.c @@ -1,9 +1,9 @@ #include "user.h" -#include "pc/debuglog.h" #include "pc/configfile.h" +#include "pc/logfile.h" static void on_current_user_update(UNUSED void* data) { - LOG_INFO("> on_current_user_update"); + LOGFILE_INFO(LFT_DISCORD, "> on_current_user_update"); struct DiscordUser user; app.users->get_current_user(app.users, &user); app.userId = user.id; @@ -23,7 +23,7 @@ static void on_current_user_update(UNUSED void* data) { } struct IDiscordUserEvents* discord_user_initialize(void) { - LOG_INFO("> discord_user_intitialize"); + LOGFILE_INFO(LFT_DISCORD, "> discord_user_intitialize"); static struct IDiscordUserEvents events = { 0 }; events.on_current_user_update = on_current_user_update; return &events;