refactor(launcher): Use new core thread and log modules

Keep this a separate commit because this also removes
launcher's own logging engine (which was a copy-paste
from inject's) and replaces it with the
streamlined core API. The core API provides all the
features of launcher's own logging engine which also
performed horribly. The entire logging operation
was locked which included expensive operations
that formatted the log messages and required
memory allocations and copying around data.
This also resulted in switching to AVS's
logging engine to perform badly which likely
is the/one root cause for reports of game's
stuttering and even de-syncing.
This commit is contained in:
icex2
2024-02-19 23:27:11 +01:00
parent e7c8cfef26
commit 1a9a2f7858
19 changed files with 172 additions and 477 deletions
+1 -1
View File
@@ -11,6 +11,7 @@ deplibs_launcher := \
libs_launcher := \
avs-util \
core \
hook \
util \
dwarfstack \
@@ -28,7 +29,6 @@ src_launcher := \
hook.c \
launcher-config.c \
launcher.c \
logger.c \
main.c \
module.c \
options.c \
+11 -6
View File
@@ -4,12 +4,13 @@
#include "avs-util/error.h"
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/avs-config.h"
#include "launcher/property-util.h"
#include "util/log.h"
#include "util/str.h"
#define AVS_CONFIG_ROOT_NODE "/config"
@@ -254,26 +255,30 @@ void avs_config_log_count_set(struct property_node *node, uint16_t count)
}
void avs_config_set_log_level(
struct property_node *node, enum log_level loglevel)
struct property_node *node, enum core_log_bt_log_level loglevel)
{
const char *str;
log_assert(node);
switch (loglevel) {
case LOG_LEVEL_FATAL:
case CORE_LOG_BT_LOG_LEVEL_OFF:
str = "disable";
break;
case CORE_LOG_BT_LOG_LEVEL_FATAL:
str = "fatal";
break;
case LOG_LEVEL_WARNING:
case CORE_LOG_BT_LOG_LEVEL_WARNING:
str = "warn";
break;
case LOG_LEVEL_INFO:
case CORE_LOG_BT_LOG_LEVEL_INFO:
str = "info";
break;
case LOG_LEVEL_MISC:
case CORE_LOG_BT_LOG_LEVEL_MISC:
str = "misc";
break;
+17 -3
View File
@@ -6,16 +6,17 @@
#include <stdint.h>
#include <stdlib.h>
#include "core/log-bt.h"
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/avs-config.h"
#include "launcher/avs.h"
#include "launcher/logger.h"
#include "launcher/property-util.h"
#include "util/codepage.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
@@ -84,7 +85,7 @@ static AVS_LOG_WRITER(_avs_context_log_writer, chars, nchars, ctx)
utf8[utf8_len] = '\0';
// Write to launcher's dedicated logging backend
logger_log_avs_log_message(utf8, utf8_len);
core_log_bt_direct_sink_write(utf8, utf8_len);
/* Clean up */
@@ -92,6 +93,17 @@ static AVS_LOG_WRITER(_avs_context_log_writer, chars, nchars, ctx)
free(utf16);
}
static void _avs_switch_log_engine()
{
// Switch the logging backend now that AVS is booted to use a single logging
// engine which avoids concurrency issues as AVS runs it's own async logger
// thread
core_log_impl_set(
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
log_misc("Switched logging engine to AVS");
}
void avs_fs_assert_root_device_exists(struct property_node *node)
{
char root_device_path[PATH_MAX];
@@ -242,6 +254,8 @@ void avs_init(
node, avs_heap, avs_heap_size, NULL, _avs_context_log_writer, NULL);
#endif
_avs_switch_log_engine();
log_misc("init done");
}
+2 -1
View File
@@ -2,6 +2,8 @@
#include <string.h>
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/avs-config.h"
@@ -10,7 +12,6 @@
#include "util/defs.h"
#include "util/hex.h"
#include "util/log.h"
#include "util/str.h"
// clang-format off
+46 -19
View File
@@ -1,5 +1,12 @@
#define LOG_MODULE "bootstrap"
#include "core/log-bt.h"
#include "core/log-sink-file.h"
#include "core/log-sink-list.h"
#include "core/log-sink-null.h"
#include "core/log-sink-std.h"
#include "core/log.h"
#include "launcher/avs-config.h"
#include "launcher/avs.h"
#include "launcher/bootstrap-config.h"
@@ -7,11 +14,9 @@
#include "launcher/eamuse-config.h"
#include "launcher/eamuse.h"
#include "launcher/launcher-config.h"
#include "launcher/logger.h"
#include "launcher/module.h"
#include "launcher/property-util.h"
#include "util/log.h"
#include "util/str.h"
static bool _bootstrap_log_property_configs;
@@ -61,22 +66,22 @@ static void _bootstrap_avs_config_log_overrides_apply(
avs_config_log_count_set(node, log_config->count);
}
static enum logger_level _bootstrap_log_map_level(const char *level)
static enum core_log_bt_log_level _bootstrap_log_map_level(const char *level)
{
if (str_eq(level, "fatal")) {
return LOGGER_LEVEL_FATAL;
return CORE_LOG_BT_LOG_LEVEL_FATAL;
} else if (str_eq(level, "warning")) {
return LOGGER_LEVEL_WARNING;
return CORE_LOG_BT_LOG_LEVEL_WARNING;
} else if (str_eq(level, "info")) {
return LOGGER_LEVEL_INFO;
return CORE_LOG_BT_LOG_LEVEL_INFO;
} else if (str_eq(level, "misc")) {
return LOGGER_LEVEL_MISC;
return CORE_LOG_BT_LOG_LEVEL_MISC;
} else if (str_eq(level, "all")) {
return LOGGER_LEVEL_ALL;
return CORE_LOG_BT_LOG_LEVEL_MISC;
} else if (str_eq(level, "disable")) {
return LOGGER_LEVEL_OFF;
return CORE_LOG_BT_LOG_LEVEL_OFF;
} else if (str_eq(level, "default")) {
return LOGGER_LEVEL_DEFAULT;
return CORE_LOG_BT_LOG_LEVEL_WARNING;
} else {
log_fatal("Unknown log level string %s", level);
}
@@ -93,22 +98,44 @@ void bootstrap_init(bool log_property_configs)
void bootstrap_log_init(const struct bootstrap_log_config *config)
{
enum logger_level level;
struct core_log_sink sinks[2];
struct core_log_sink sink_composed;
enum core_log_bt_log_level level;
log_assert(config);
log_info("log init");
logger_init(
config->file,
config->enable_console,
config->enable_file,
config->rotate,
config->append,
config->count);
// Shutdown old setup
core_log_bt_fini();
if (config->enable_file && strlen(config->file) > 0 &&
config->enable_console) {
core_log_sink_std_out_open(true, &sinks[0]);
core_log_sink_file_open(
config->file,
config->append,
config->rotate,
config->count,
&sinks[1]);
core_log_sink_list_open(sinks, 2, &sink_composed);
} else if (config->enable_file && strlen(config->file) > 0) {
core_log_sink_file_open(
config->file,
config->append,
config->rotate,
config->count,
&sink_composed);
} else if (config->enable_console) {
core_log_sink_std_out_open(true, &sink_composed);
} else {
core_log_sink_null_open(&sink_composed);
}
core_log_bt_init(&sink_composed);
level = _bootstrap_log_map_level(config->level);
logger_level_set(level);
core_log_bt_level_set(level);
log_misc("log init done");
}
+2 -2
View File
@@ -4,9 +4,9 @@
#include <stdbool.h>
#include <windows.h>
#include "launcher/debug.h"
#include "core/log.h"
#include "util/log.h"
#include "launcher/debug.h"
void debug_remote_debugger_trap()
{
+2 -1
View File
@@ -2,6 +2,8 @@
#include <string.h>
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/ea3-ident-config.h"
@@ -9,7 +11,6 @@
#include "util/defs.h"
#include "util/hex.h"
#include "util/log.h"
#include "util/str.h"
#define ROOT_NODE "/ea3_conf"
+2 -2
View File
@@ -2,14 +2,14 @@
#include <stdlib.h>
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/ea3-ident-config.h"
#include "launcher/eamuse-config.h"
#include "launcher/property-util.h"
#include "util/log.h"
#define EAMUSE_CONFIG_ROOT_NODE "/ea3"
struct property *eamuse_config_avs_load(const char *path)
+2 -2
View File
@@ -1,8 +1,8 @@
#define LOG_MODULE "eamuse"
#include "imports/avs-ea3.h"
#include "core/log.h"
#include "util/log.h"
#include "imports/avs-ea3.h"
void eamuse_init(struct property_node *node)
{
+2 -2
View File
@@ -2,9 +2,9 @@
#include <windows.h>
#include "launcher/hook.h"
#include "core/log.h"
#include "util/log.h"
#include "launcher/hook.h"
void hook_load_dll(const char *path)
{
+2 -1
View File
@@ -2,12 +2,13 @@
#include <string.h>
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/launcher-config.h"
#include "launcher/property-util.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
+67 -21
View File
@@ -7,6 +7,13 @@
#include <stdio.h>
#include <stdlib.h>
#include "core/log-bt-ext.h"
#include "core/log-bt.h"
#include "core/log-sink-file.h"
#include "core/log-sink-list.h"
#include "core/log-sink-std.h"
#include "core/log.h"
#include "imports/avs-ea3.h"
#include "imports/avs.h"
@@ -20,40 +27,63 @@
#include "launcher/eamuse.h"
#include "launcher/hook.h"
#include "launcher/launcher-config.h"
#include "launcher/logger.h"
#include "launcher/module.h"
#include "launcher/options.h"
#include "launcher/property-util.h"
#include "launcher/stubs.h"
#include "launcher/version.h"
#include "procmon-lib/procmon.h"
#include "util/debug.h"
#include "util/defs.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/os.h"
#include "util/proc.h"
#include "util/signal.h"
#include "util/str.h"
static void _launcher_signal_shutdown_handler()
static void _launcher_log_header()
{
logger_finit();
ExitProcess(EXIT_FAILURE);
log_info(
"\n"
" .__ .__ \n"
" | | _____ __ __ ____ ____ | |__ ___________ \n"
" | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n"
" | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n"
" |____(____ /____/|___| /\\___ >___| /\\___ >__| \n"
" \\/ \\/ \\/ \\/ \\/ ");
log_info(
"launcher build date %s, gitrev %s",
launcher_build_date,
launcher_gitrev);
}
static void _launcher_logger_early_init(const struct options_log *options)
void _launcher_log_init(
const char *log_file_path, enum core_log_bt_log_level level)
{
log_assert(options);
struct core_log_sink sinks[2];
struct core_log_sink sink_composed;
// Early logging pre AVS setup depend entirely on command args
// We don't even have the bootstrap configuration loaded at this point
logger_early_init(options->file_path);
core_log_bt_ext_impl_set();
if (options->level) {
log_set_level(*(options->level));
if (log_file_path) {
core_log_sink_std_out_open(true, &sinks[0]);
core_log_sink_file_open(log_file_path, false, true, 10, &sinks[1]);
core_log_sink_list_open(sinks, 2, &sink_composed);
} else {
core_log_sink_std_out_open(true, &sink_composed);
}
core_log_bt_init(&sink_composed);
core_log_bt_level_set(level);
}
static void _launcher_signal_shutdown_handler()
{
core_log_bt_fini();
ExitProcess(EXIT_FAILURE);
}
static void _launcher_env_game_dir_verify()
@@ -243,7 +273,7 @@ static void _launcher_procmon_init(
if (procmon_available()) {
procmon_load(procmon);
procmon->set_loggers(log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
core_log_impl_assign(procmon->set_loggers);
procmon->init();
if (config->procmon_file) {
@@ -283,19 +313,23 @@ static void _launcher_bootstrap_log_config_options_override(
"Command line override bootstrap log level: %d", *(options->level));
switch (*(options->level)) {
case LOG_LEVEL_FATAL:
case CORE_LOG_BT_LOG_LEVEL_OFF:
str_cpy(config->level, sizeof(config->level), "disable");
break;
case CORE_LOG_BT_LOG_LEVEL_FATAL:
str_cpy(config->level, sizeof(config->level), "fatal");
break;
case LOG_LEVEL_WARNING:
case CORE_LOG_BT_LOG_LEVEL_WARNING:
str_cpy(config->level, sizeof(config->level), "warn");
break;
case LOG_LEVEL_INFO:
case CORE_LOG_BT_LOG_LEVEL_INFO:
str_cpy(config->level, sizeof(config->level), "info");
break;
case LOG_LEVEL_MISC:
case CORE_LOG_BT_LOG_LEVEL_MISC:
str_cpy(config->level, sizeof(config->level), "misc");
break;
@@ -421,6 +455,11 @@ static void _launcher_debugger_break()
}
}
void _launcher_log_reinit()
{
core_log_bt_ext_impl_set();
}
void _launcher_init(
const struct options *options,
struct launcher_config *launcher_config,
@@ -435,9 +474,12 @@ void _launcher_init(
log_assert(bootstrap_config);
log_assert(ea3_ident_config);
_launcher_logger_early_init(&options->log);
// Early logging pre AVS setup depend entirely on command args
// We don't even have the bootstrap configuration loaded at this point
_launcher_log_init(options->log.file_path, *(options->log.level));
_launcher_log_header();
debug_init();
debug_init(core_log_fatal_impl_get());
signal_exception_handler_init(_launcher_signal_shutdown_handler);
signal_register_shutdown_handler(&_launcher_signal_shutdown_handler);
@@ -453,7 +495,9 @@ void _launcher_init(
launcher_config_init(launcher_config);
if (options->launcher.config_path) {
log_info("Loading launcher configuration from file: %s", options->launcher.config_path);
log_info(
"Loading launcher configuration from file: %s",
options->launcher.config_path);
launcher_property = property_util_load(options->launcher.config_path);
launcher_config_load(launcher_property, launcher_config);
@@ -550,6 +594,8 @@ void _launcher_fini(
bootstrap_avs_fini();
_launcher_log_reinit();
bootstrap_module_game_fini();
if (procmon->module != NULL) {
@@ -560,7 +606,7 @@ void _launcher_fini(
log_info("Shutdown complete");
logger_finit();
core_log_bt_fini();
}
void launcher_main(const struct options *options)
-365
View File
@@ -1,365 +0,0 @@
#define LOG_MODULE "launcher-logger"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include "launcher/logger.h"
#include "launcher/version.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/mem.h"
static FILE *log_file;
static HANDLE log_mutex;
static const char *logger_get_formatted_timestamp(void)
{
static char buffer[64];
time_t cur = 0;
struct tm *tm = NULL;
cur = time(NULL);
tm = localtime(&cur);
strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tm);
return buffer;
}
static char logger_console_determine_color(const char *str)
{
log_assert(str);
/* Add some color to make spotting warnings/errors easier.
Based on debug output level identifier. */
/* Avoids colored output on strings like "Windows" */
if (str[1] != ':') {
return 15;
}
switch (str[0]) {
/* green */
case 'M':
return 10;
/* blue */
case 'I':
return 9;
/* yellow */
case 'W':
return 14;
/* red */
case 'F':
return 12;
/* default console color */
default:
return 15;
}
}
static size_t logger_msg_coloring_len(const char *str)
{
// Expected format example: "I:boot: my log message"
const char *ptr;
size_t len;
int colon_count;
ptr = str;
len = 0;
colon_count = 0;
while (true) {
// End of string = invalid log format
if (*ptr == '\0') {
return 0;
}
if (*ptr == ':') {
colon_count++;
}
if (colon_count == 2) {
// Skip current colon, next char is a space
return len + 1;
}
len++;
ptr++;
}
return 0;
}
static void logger_console(
void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
{
char color;
size_t color_len;
// See "util/log.c", has to align
char buffer[65536];
char tmp;
color_len = logger_msg_coloring_len(chars);
// Check if we could detect which part to color, otherwise just write the
// whole log message without any coloring logic
if (color_len > 0) {
color = logger_console_determine_color(chars);
strcpy(buffer, chars);
// Mask start of log message for coloring
tmp = buffer[color_len];
buffer[color_len] = '\0';
printf("%s", timestamp_str);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
printf("%s", buffer);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
// Write actual message non colored
buffer[color_len] = tmp;
printf("%s", buffer + color_len);
} else {
printf("%s", chars);
}
}
static void logger_console_avs(const char *chars)
{
char color;
size_t color_len;
// See "util/log.c", has to align
char buffer[65536];
char tmp;
const char *timestamp;
const char *msg;
static const size_t timestamp_len = strlen("[----/--/-- --:--:--]");
timestamp = chars;
msg = timestamp + timestamp_len + 1; // +1 is the space
color_len = logger_msg_coloring_len(msg);
// Check if we could detect which part to color, otherwise just write the
// whole log message without any coloring logic
if (color_len > 0) {
color = logger_console_determine_color(msg);
strcpy(buffer, msg);
// Mask start of log message for coloring
tmp = buffer[color_len];
buffer[color_len] = '\0';
printf("%.21s ", timestamp);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
printf("%s", buffer);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
// Write actual message non colored
buffer[color_len] = tmp;
printf("%s\n", buffer + color_len);
} else {
printf("%s\n", chars);
}
}
static void logger_file(
void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
{
if (ctx) {
fwrite(timestamp_str, 1, strlen(timestamp_str), (FILE *) ctx);
fwrite(chars, 1, nchars, (FILE *) ctx);
fflush((FILE *) ctx);
}
}
static void logger_file_avs(const char *chars, size_t len)
{
if (log_file) {
fwrite(chars, 1, len, log_file);
fflush(log_file);
}
}
static void logger_writer(void *ctx, const char *chars, size_t nchars)
{
const char *timestamp_str;
// Different threads logging the same destination, e.g. debugger thread,
// main thread
WaitForSingleObject(log_mutex, INFINITE);
timestamp_str = logger_get_formatted_timestamp();
logger_console(ctx, chars, nchars, timestamp_str);
logger_file(ctx, chars, nchars, timestamp_str);
ReleaseMutex(log_mutex);
}
static void logger_log_header()
{
log_info(
"\n"
" .__ .__ \n"
" | | _____ __ __ ____ ____ | |__ ___________ \n"
" | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n"
" | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n"
" |____(____ /____/|___| /\\___ >___| /\\___ >__| \n"
" \\/ \\/ \\/ \\/ \\/ ");
log_info(
"launcher build date %s, gitrev %s",
launcher_build_date,
launcher_gitrev);
}
void logger_early_init(const char *log_file_path)
{
if (log_file_path) {
log_file = fopen(log_file_path, "w+");
} else {
log_file = NULL;
}
log_to_writer(logger_writer, log_file);
logger_log_header();
if (log_file_path) {
log_info("Log file: %s", log_file_path);
if (!log_file) {
log_fatal(
"ERROR: Opening log file %s failed: %s",
log_file_path,
strerror(errno));
}
}
log_mutex = CreateMutex(NULL, FALSE, NULL);
}
void logger_init(
const char *filename,
bool enable_console,
bool enable_file,
bool rotate_file,
bool append_file,
uint16_t count_file)
{
// Remark: very basic implementation for now, logger needs a proper cleanup
// anyway before implementing more features such as rotation
if (enable_file) {
if (log_file) {
// Log file stitching of early log output
fseek(log_file, 0, SEEK_END);
size_t file_size = ftell(log_file);
fseek(log_file, 0, SEEK_SET);
void *buffer = xmalloc(file_size);
fread(buffer, file_size, 1, log_file);
fclose(log_file);
log_file = fopen(filename, "w+");
fwrite(buffer, file_size, 1, log_file);
fflush(log_file);
free(buffer);
}
} else {
if (log_file) {
fclose(log_file);
log_file = NULL;
}
}
}
void logger_level_set(enum logger_level level)
{
enum log_level internal_level;
switch (level) {
case LOGGER_LEVEL_OFF:
case LOGGER_LEVEL_FATAL:
internal_level = LOG_LEVEL_FATAL;
break;
case LOGGER_LEVEL_WARNING:
internal_level = LOG_LEVEL_WARNING;
break;
case LOGGER_LEVEL_DEFAULT:
case LOGGER_LEVEL_INFO:
internal_level = LOG_LEVEL_INFO;
break;
case LOGGER_LEVEL_MISC:
case LOGGER_LEVEL_ALL:
internal_level = LOG_LEVEL_MISC;
break;
default:
internal_level = LOG_LEVEL_FATAL;
log_assert(false);
}
log_set_level(internal_level);
}
void logger_log_avs_log_message(char *str, size_t len)
{
bool use_crlf;
#if AVS_VERSION >= 1500
use_crlf = true;
#else
use_crlf = false;
#endif
// Different threads logging the same destination, e.g. debugger thread,
// main thread
WaitForSingleObject(log_mutex, INFINITE);
// Write to file first, tokenizing trashes the string
logger_file_avs(str, len);
// The character stream provided here can contain multiple lines as AVS
// manages buffered writes to the logger backend. We need to split them
// up for the logging backend to allow for further enhancements
char *line = strtok(str, use_crlf ? "\r\n" : "\n");
while (line) {
logger_console_avs(line);
line = strtok(NULL, use_crlf ? "\r\n" : "\n");
}
ReleaseMutex(log_mutex);
}
void logger_finit()
{
log_misc("Logger finit");
if (log_file) {
fflush(log_file);
fclose(log_file);
}
CloseHandle(log_mutex);
}
-42
View File
@@ -1,42 +0,0 @@
#ifndef LAUNCHER_LOGGER_H
#define LAUNCHER_LOGGER_H
#include <stdbool.h>
#include <stdint.h>
enum logger_level {
LOGGER_LEVEL_OFF = 0,
LOGGER_LEVEL_FATAL = 1,
LOGGER_LEVEL_WARNING = 2,
LOGGER_LEVEL_INFO = 3,
LOGGER_LEVEL_MISC = 4,
LOGGER_LEVEL_ALL = 5,
LOGGER_LEVEL_DEFAULT = 6
};
void logger_early_init(const char *log_file_path);
void logger_init(
const char *filename,
bool enable_console,
bool enable_file,
bool rotate_file,
bool append_file,
uint16_t count_file);
void logger_level_set(enum logger_level level);
/**
* Write a log message from AVS to the logging backend.
*
* @param str String to log
* @param len Total length of the log string
*/
void logger_log_avs_log_message(char *str, size_t len);
/**
* Shutdown and cleanup the logging backend.
*/
void logger_finit();
#endif
+2 -1
View File
@@ -2,6 +2,8 @@
#include <windows.h>
#include "core/log.h"
#include "hook/pe.h"
#include "imports/avs.h"
@@ -10,7 +12,6 @@
#include "launcher/module.h"
#include "launcher/property-util.h"
#include "util/log.h"
#include "util/str.h"
#define MM_ALLOCATION_GRANULARITY 0x10000
+5 -3
View File
@@ -107,12 +107,14 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
long tmp = strtol(argv[++i], NULL, 0);
if (tmp < LOG_LEVEL_FATAL || tmp > LOG_LEVEL_MISC) {
if (tmp < CORE_LOG_BT_LOG_LEVEL_OFF ||
tmp > CORE_LOG_BT_LOG_LEVEL_MISC) {
return false;
}
options->log.level = xmalloc(sizeof(enum log_level));
*(options->log.level) = (enum log_level) tmp;
options->log.level =
xmalloc(sizeof(enum core_log_bt_log_level));
*(options->log.level) = (enum core_log_bt_log_level) tmp;
break;
+5 -3
View File
@@ -4,11 +4,13 @@
#include <stdbool.h>
#include <stddef.h>
#include "util/array.h"
#include "util/log.h"
#include "core/log-bt.h"
#include "core/log.h"
#include "launcher/bootstrap-config.h"
#include "util/array.h"
// Launcher options (cmd params) are limited to:
// - Options to run a (vanilla) game without additional launcher features, e.g.
// hooking
@@ -28,7 +30,7 @@ struct options {
} bootstrap;
struct options_log {
enum log_level *level;
enum core_log_bt_log_level *level;
const char *file_path;
} log;
+2 -1
View File
@@ -9,11 +9,12 @@
#include "avs-util/error.h"
#include "core/log.h"
#include "imports/avs.h"
#include "launcher/property-util.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
+2 -1
View File
@@ -7,12 +7,13 @@
#include <string.h>
#include <wchar.h>
#include "core/log.h"
#include "hook/table.h"
#include "launcher/stubs.h"
#include "util/defs.h"
#include "util/log.h"
struct ikey_status {
uint32_t field_0;