taisei/src/main.c

324 lines
7.1 KiB
C
Raw Normal View History

/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
2018-01-04 18:14:31 +01:00
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
*/
#include "taisei.h"
2017-03-12 21:14:32 +01:00
#include <locale.h>
#include "global.h"
2012-07-28 22:53:53 +02:00
#include "video.h"
#include "audio.h"
#include "stage.h"
#include "menu/mainmenu.h"
#include "menu/savereplay.h"
2012-08-15 02:41:21 +02:00
#include "gamepad.h"
2017-01-24 14:40:57 +01:00
#include "resource/bgm.h"
#include "progress.h"
#include "hashtable.h"
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#include "log.h"
2017-04-02 09:38:50 +02:00
#include "cli.h"
#include "vfs/setup.h"
#include "version.h"
2017-10-23 12:48:30 +02:00
#include "credits.h"
2017-04-18 21:48:18 +02:00
static void taisei_shutdown(void) {
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_info("Shutting down");
2017-04-18 21:48:18 +02:00
config_save();
progress_save();
2017-03-29 22:17:39 +02:00
progress_unload();
free_all_refs();
free_resources(true);
uninit_fonts();
audio_shutdown();
2012-07-28 22:53:53 +02:00
video_shutdown();
2012-08-15 02:41:21 +02:00
gamepad_shutdown();
2017-02-15 13:53:24 +01:00
stage_free_array();
config_shutdown();
vfs_shutdown();
events_shutdown();
time_shutdown();
log_info("Good bye");
SDL_Quit();
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_shutdown();
}
2017-04-18 21:48:18 +02:00
static void init_log(void) {
LogLevel lvls_console = log_parse_levels(LOG_DEFAULT_LEVELS_CONSOLE, getenv("TAISEI_LOGLVLS_CONSOLE"));
LogLevel lvls_stdout = lvls_console & log_parse_levels(LOG_DEFAULT_LEVELS_STDOUT, getenv("TAISEI_LOGLVLS_STDOUT"));
LogLevel lvls_stderr = lvls_console & log_parse_levels(LOG_DEFAULT_LEVELS_STDERR, getenv("TAISEI_LOGLVLS_STDERR"));
LogLevel lvls_backtrace = log_parse_levels(LOG_DEFAULT_LEVELS_BACKTRACE, getenv("TAISEI_LOGLVLS_BACKTRACE"));
log_init(LOG_DEFAULT_LEVELS, lvls_backtrace);
log_add_output(lvls_stdout, SDL_RWFromFP(stdout, false));
log_add_output(lvls_stderr, SDL_RWFromFP(stderr, false));
2017-04-18 21:48:18 +02:00
}
2017-04-18 21:48:18 +02:00
static void init_log_file(void) {
LogLevel lvls_file = log_parse_levels(LOG_DEFAULT_LEVELS_FILE, getenv("TAISEI_LOGLVLS_FILE"));
log_add_output(lvls_file, vfs_open("storage/log.txt", VFS_MODE_WRITE));
}
#ifdef CRC32_BENCHMARK
// TODO: move all this crap somewhere
static void hash_test_run(const char *str, uint32_t init, uint32_t (*hashfunc)(uint32_t, const char*)) {
hrtime_t begin = time_get();
for(int i = 0; i < 341346740; ++i) {
init = hashfunc(init, str);
}
log_debug("%08x %f", init, (double)(time_get() - begin));
}
static int hash_test(void) {
time_init();
const char *s;
s = "reimu";
log_info("-> %s", s);
hash_test_run(s, 0, crc32str);
hash_test_run(s, 0, crc32str_sse42);
s = "sphereness";
log_info("-> %s", s);
hash_test_run(s, 0, crc32str);
hash_test_run(s, 0, crc32str_sse42);
s = "res/textures/rabu_raibu.png";
log_info("-> %s", s);
hash_test_run(s, 0, crc32str);
hash_test_run(s, 0, crc32str_sse42);
return 1;
}
#else
static int hash_test(void) {
return 0;
}
#endif
2017-04-18 21:48:18 +02:00
static int run_tests(void) {
if(tsrand_test()) {
return 1;
}
2017-02-22 21:52:25 +01:00
if(zrwops_test()) {
return 1;
}
if(hashtable_test()) {
return 1;
}
2017-02-26 21:59:51 +01:00
if(color_test()) {
return 1;
}
if(hash_test()) {
return 1;
}
return 0;
}
static void init_sdl(void) {
SDL_version v;
if(SDL_Init(SDL_INIT_EVENTS) < 0)
log_fatal("SDL_Init() failed: %s", SDL_GetError());
log_info("SDL initialized");
SDL_VERSION(&v);
log_info("Compiled against SDL %u.%u.%u", v.major, v.minor, v.patch);
SDL_GetVersion(&v);
log_info("Using SDL %u.%u.%u", v.major, v.minor, v.patch);
}
static void log_lib_versions(void) {
log_info("Compiled against zlib %s", ZLIB_VERSION);
log_info("Using zlib %s", zlibVersion());
log_info("Compiled against libpng %s", PNG_LIBPNG_VER_STRING);
log_info("Using libpng %s", png_get_header_ver(NULL));
}
void log_system_specs(void) {
log_info("CPU count: %d", SDL_GetCPUCount());
// log_info("CPU type: %s", SDL_GetCPUType());
// log_info("CPU name: %s", SDL_GetCPUName());
log_info("CacheLine size: %d", SDL_GetCPUCacheLineSize());
log_info("RDTSC: %d", SDL_HasRDTSC());
log_info("Altivec: %d", SDL_HasAltiVec());
log_info("MMX: %d", SDL_HasMMX());
log_info("3DNow: %d", SDL_Has3DNow());
log_info("SSE: %d", SDL_HasSSE());
log_info("SSE2: %d", SDL_HasSSE2());
log_info("SSE3: %d", SDL_HasSSE3());
log_info("SSE4.1: %d", SDL_HasSSE41());
log_info("SSE4.2: %d", SDL_HasSSE42());
log_info("AVX: %d", SDL_HasAVX());
log_info("AVX2: %d", SDL_HasAVX2());
2017-11-24 00:42:23 +01:00
#if SDL_VERSION_ATLEAST(2, 0, 6)
log_info("NEON: %d", SDL_HasNEON());
2017-11-24 00:42:23 +01:00
#endif
log_info("RAM: %d MB", SDL_GetSystemRAM());
}
int main(int argc, char **argv) {
2017-03-12 21:14:32 +01:00
setlocale(LC_ALL, "C");
Replay replay = {0};
2017-04-04 11:10:54 +02:00
int replay_idx = 0;
init_log();
if(run_tests()) {
return 0;
}
2017-04-03 01:50:48 +02:00
stage_init_array(); // cli_args depends on this
2017-04-03 01:10:16 +02:00
// commandline arguments should be parsed as early as possible
CLIAction a;
cli_args(argc, argv, &a); // stage_init_array goes first!
if(a.type == CLI_Quit) {
free_cli_action(&a);
2017-04-03 01:10:16 +02:00
return 1;
}
2017-04-03 01:10:16 +02:00
if(a.type == CLI_DumpStages) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
2017-12-31 09:08:07 +01:00
tsfprintf(stdout, "%X %s: %s\n", stg->id, stg->title, stg->subtitle);
2017-04-03 01:10:16 +02:00
}
free_cli_action(&a);
2017-04-03 01:10:16 +02:00
return 0;
} else if(a.type == CLI_PlayReplay) {
2017-04-18 21:48:18 +02:00
if(!replay_load_syspath(&replay, a.filename, REPLAY_READ_ALL)) {
free_cli_action(&a);
2017-04-03 01:10:16 +02:00
return 1;
}
2017-04-04 11:10:54 +02:00
replay_idx = a.stageid ? replay_find_stage_idx(&replay, a.stageid) : 0;
2017-04-04 11:10:54 +02:00
if(replay_idx < 0) {
free_cli_action(&a);
2017-04-04 11:10:54 +02:00
return 1;
}
2017-04-18 21:48:18 +02:00
} else if(a.type == CLI_DumpVFSTree) {
vfs_setup(true);
2017-04-03 01:10:16 +02:00
2017-04-18 21:48:18 +02:00
SDL_RWops *rwops = SDL_RWFromFP(stdout, false);
2017-04-07 15:10:47 +02:00
2017-04-18 21:48:18 +02:00
if(!rwops) {
log_fatal("SDL_RWFromFP() failed: %s", SDL_GetError());
}
2017-04-18 21:48:18 +02:00
if(!vfs_print_tree(rwops, a.filename)) {
log_warn("VFS error: %s", vfs_get_error());
SDL_RWclose(rwops);
free_cli_action(&a);
2017-04-18 21:48:18 +02:00
return 1;
}
2017-04-18 21:48:18 +02:00
SDL_RWclose(rwops);
vfs_shutdown();
2017-04-30 13:10:03 +02:00
free_cli_action(&a);
2017-04-18 21:48:18 +02:00
return 0;
}
2017-04-18 21:48:18 +02:00
free_cli_action(&a);
vfs_setup(false);
2017-04-18 21:48:18 +02:00
init_log_file();
log_info("%s %s", TAISEI_VERSION_FULL, TAISEI_VERSION_BUILD_TYPE);
log_system_specs();
2017-04-18 21:48:18 +02:00
config_load();
log_lib_versions();
2017-04-02 09:38:50 +02:00
init_sdl();
time_init();
init_global(&a);
events_init();
init_fonts();
2012-07-28 22:53:53 +02:00
video_init();
2017-02-28 18:47:47 +01:00
init_resources();
2012-08-18 09:44:38 +02:00
draw_loading_screen();
audio_init();
load_resources();
2012-08-15 02:41:21 +02:00
gamepad_init();
2017-04-03 01:50:48 +02:00
progress_load();
2017-02-25 14:23:22 +01:00
set_transition(TransLoader, 0, FADE_TIME*2);
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_info("Initialization complete");
2012-04-05 20:31:16 +02:00
atexit(taisei_shutdown);
2017-04-02 09:38:50 +02:00
if(a.type == CLI_PlayReplay) {
2017-04-04 11:10:54 +02:00
replay_play(&replay, replay_idx);
replay_destroy(&replay);
return 0;
}
2017-10-23 12:48:30 +02:00
if(a.type == CLI_Credits) {
credits_loop();
return 0;
}
2017-04-02 10:16:52 +02:00
#ifdef DEBUG
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_warn("Compiled with DEBUG flag!");
2017-04-02 09:38:50 +02:00
if(a.type == CLI_SelectStage) {
2017-12-31 09:08:07 +01:00
log_info("Entering stage skip mode: Stage %X", a.stageid);
2017-04-02 09:38:50 +02:00
StageInfo* stg = stage_get(a.stageid);
assert(stg); // properly checked before this
global.diff = stg->difficulty;
global.is_practice_mode = (stg->type != STAGE_EXTRA);
2017-04-02 09:38:50 +02:00
if(a.diff) {
global.diff = a.diff;
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_info("Setting difficulty to %s", difficulty_name(global.diff));
} else if(!global.diff) {
global.diff = D_Easy;
2012-07-13 18:44:56 +02:00
}
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
log_info("Entering %s", stg->title);
do {
2018-01-08 22:23:07 +01:00
global.replay_stage = NULL;
replay_init(&global.replay);
global.game_over = 0;
player_init(&global.plr);
if(a.plrmode) {
global.plr.mode = a.plrmode;
}
2017-02-26 13:17:48 +01:00
stage_loop(stg);
2018-01-08 22:23:07 +01:00
if(global.game_over == GAMEOVER_RESTART) {
replay_destroy(&global.replay);
}
} while(global.game_over == GAMEOVER_RESTART);
ask_save_replay();
return 0;
2012-04-06 17:50:17 +02:00
}
2017-04-02 10:16:52 +02:00
#endif
MenuData menu;
create_main_menu(&menu);
menu_loop(&menu);
2012-08-16 15:50:28 +02:00
return 0;
}