diff --git a/Makefile b/Makefile index 4e6c63e804..dc5a45db43 100644 --- a/Makefile +++ b/Makefile @@ -138,10 +138,10 @@ update: meson skrewup $(MESON) subprojects update || true setup_release: $(BUILD)/build.ninja - $(MESON) configure build -Dgdb_debugging=false + $(MESON) configure build -Dgdb_debugging=false -Dlogging_enabled=false setup_debug: $(BUILD)/build.ninja - $(MESON) configure build -Dgdb_debugging=true + $(MESON) configure build -Dgdb_debugging=true -Dlogging_enabled=true configure: $(BUILD)/build.ninja diff --git a/docs/index.md b/docs/index.md index 26313eb005..35f029efc9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,3 +16,7 @@ For more detailed information about the project as a whole, please refer to its - [2D Graphics](2d_rendering.md) - [3D Graphics](3d_rendering.md) + +## Utilities + +- [Logging](logging.md) diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 0000000000..4efabc6bd0 --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,26 @@ +# Logging + +The repository includes a basic logger, that works with emulators such as MelonDS and No$GBA. + +To enable it, compile with `make debug` (or the `logging_enabled` meson option). + +## Usage + +Wherever you want to log something, just include the `debug.h` file, and call the `EmulatorLog` function. + +### Example + +```c +#include "debug.h" + +void someFunction(){ + EmulatorLog("This will get printed on your emulator's standard output"); + int aNumber = 5; + EmulatorLog("The function works just like printf, here's an integer : %d",aNumber); +} +``` + +## List of logging functions + +- EmulatorLog : Prints the message with printf formatting but adds `[GAME_LOG] ` to the front and a newline at the end. +- EmulatorPrintf : Just prints it's arguments to the emulator's output, with printf formatting. \ No newline at end of file diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000000..3b1fafcbca --- /dev/null +++ b/include/debug.h @@ -0,0 +1,23 @@ +#ifndef DEBUGGING_H +#define DEBUGGING_H + +#ifdef LOGGING_ENABLED + +#define LOG_MESSAGE_MAX_LENGTH 1024 +#include "charcode.h" +#include "strbuf.h" + +// Prints to the emulator's standard output, with printf formatting +__attribute__((format(printf, 1, 2))) void EmulatorPrintf(const char *text, ...); + +// Prints to the emulator's standard output, with printf formatting, but adds a marker prefix and a newline at the end +__attribute__((format(printf, 1, 2))) void EmulatorLog(const char *text, ...); + +#else + +#define EmulatorPrintf(text, ...) +#define EmulatorLog(text, ...) + +#endif + +#endif diff --git a/meson.build b/meson.build index 6f903234ae..b05fd50347 100644 --- a/meson.build +++ b/meson.build @@ -40,7 +40,7 @@ c_args = [ if get_option('gdb_debugging') c_args += [ '-O1,p', - '-inline', 'off' +# '-inline', 'off' todo: figure out why this makes the rom crash after the copyright screen ] else c_args += '-O4,p' @@ -61,6 +61,12 @@ if get_option('gdb_debugging') pokeplatinum_args += '-DGDB_DEBUGGING' endif +if get_option('logging_enabled') + pokeplatinum_args += [ + '-DLOGGING_ENABLED', + ] +endif + asm_args = [ '-proc', 'arm5TE', '-16', diff --git a/meson.options b/meson.options index fd78cd4ee3..9a727bbdad 100644 --- a/meson.options +++ b/meson.options @@ -1 +1,2 @@ -option('gdb_debugging', type : 'boolean', value : false) \ No newline at end of file +option('gdb_debugging', type : 'boolean', value : false) +option('logging_enabled', type: 'boolean', value: false) \ No newline at end of file diff --git a/platinum.us/main.lsf b/platinum.us/main.lsf index fff226a7f4..30dbb3ed7f 100644 --- a/platinum.us/main.lsf +++ b/platinum.us/main.lsf @@ -16,6 +16,7 @@ Static main Library libcps.a (.version) Library libssl.a (.version) Object main.nef.p/src_main.c.o + Object main.nef.p/src_debug.c.o Object main.nef.p/src_list_menu.c.o Object main.nef.p/src_game_version.c.o Object main.nef.p/src_menu.c.o diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000000..1cc764b5be --- /dev/null +++ b/src/debug.c @@ -0,0 +1,55 @@ +#ifdef LOGGING_ENABLED +#include "debug.h" + +#include "charcode.h" +#include "charmap.h" +#include "strbuf.h" +#define NOCASHGBAIDADDR 0x04FFFA00 +#define NOCASHGBAPRINTADDR1 0x04FFFA14 // does not automatically add the newline +#define NOCASHGBAPRINTADDR2 0x04FFFA18 // does automatically add the newline + +#define MELONDS_PRINT_MAX_LEN 120 + +volatile const char **noCashPrint = (volatile const char **)NOCASHGBAPRINTADDR1; + +static void EmulatorRawPrint(const char *fmt) +{ + *noCashPrint = fmt; +} + +char formattingBuffer[LOG_MESSAGE_MAX_LENGTH]; + +void EmulatorVPrintf(const char *text, va_list ap) +{ + + const int res = vsnprintf(formattingBuffer, LOG_MESSAGE_MAX_LENGTH, text, ap); + + int toprint = res >= LOG_MESSAGE_MAX_LENGTH - 1 ? LOG_MESSAGE_MAX_LENGTH - 1 : res; + const char *nextPrintStart = formattingBuffer; + while (toprint > 0) { + EmulatorRawPrint(nextPrintStart); + toprint -= MELONDS_PRINT_MAX_LEN; + nextPrintStart += MELONDS_PRINT_MAX_LEN; + } + if (res >= LOG_MESSAGE_MAX_LENGTH - 1) { + EmulatorRawPrint("\nlog truncated\n"); + } +} +void EmulatorPrintf(const char *text, ...) +{ + va_list args; + va_start(args, text); + EmulatorVPrintf(text, args); + va_end(args); +} + +void EmulatorLog(const char *text, ...) +{ + EmulatorPrintf("[GAME_LOG] "); + va_list args; + va_start(args, text); + EmulatorVPrintf(text, args); + va_end(args); + EmulatorPrintf("\n"); +} +#endif diff --git a/src/meson.build b/src/meson.build index 33c1183697..d613d72c43 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1017,5 +1017,6 @@ pokeplatinum_c = files( 'overlay119/ov119_021D0D80.c', 'overlay119/ov119_021D191C.c', 'library_tv/library_tv.c', - 'dw_warp/dw_warp.c' + 'dw_warp/dw_warp.c', + 'debug.c' ) diff --git a/tools/devtools/gen_compile_commands.py b/tools/devtools/gen_compile_commands.py index ae146c02bc..5e48b5151d 100755 --- a/tools/devtools/gen_compile_commands.py +++ b/tools/devtools/gen_compile_commands.py @@ -5,9 +5,12 @@ import pathlib homedir = pathlib.Path(__file__).resolve().parent.parent.parent builddir = homedir / "build" +generateddir = builddir / "generated" +meson_options_file = builddir / "meson-info" / "intro-buildoptions.json" cwsdkdir = homedir / "subprojects" / "metroskrew" / "lib" / "metroskrew" / "sdk" / "ds" / "2.0" / "sp2" cwlibcdir = cwsdkdir / "msl" / "MSL_C" / "MSL_Common" / "Include" +cwlibcarmdir = cwsdkdir / "msl" / "MSL_C" / "MSL_ARM" / "Include" cwextrasdir = cwsdkdir / "msl" / "MSL_Extras" / "MSL_Common" / "Include" arm7_c_flags = [ @@ -19,6 +22,7 @@ arm7_c_flags = [ "-mfloat-abi=soft", "-nostdinc", "-D_NITRO", + "-D__arm", "-DSDK_4M", "-DSDK_ARM7", "-DSDK_CODE_ARM", @@ -37,6 +41,7 @@ arm9_c_flags = [ "-mfloat-abi=soft", "-nostdinc", "-D_NITRO", + "-D__arm", "-DLINK_PPWLOBBY", "-DNNS_FINALROM", "-DSDK_4M", @@ -52,6 +57,21 @@ arm9_c_flags = [ "-DGAME_LANGUAGE=ENGLISH", ] +with open(meson_options_file, 'r') as optf: + meson_options = json.load(optf) + +def find_option(opt: str): + return [o["value"] for o in meson_options if o["name"] == opt][0] + +gdb_debugging = find_option("gdb_debugging") +logging_enabled = find_option("logging_enabled") + +if gdb_debugging: + arm9_c_flags.append("-DGDB_DEBUGGING") + +if logging_enabled: + arm9_c_flags.append("-DLOGGING_ENABLED") + asm_commands = [ { "directory": builddir, @@ -74,6 +94,7 @@ nitrosdk_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", "-o", @@ -92,6 +113,7 @@ nitrosystem_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -111,6 +133,7 @@ nitrowifi_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -131,6 +154,7 @@ nitrodwc_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -152,6 +176,7 @@ libvct_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -174,6 +199,7 @@ libcrypto_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -197,6 +223,7 @@ ppwlobby_c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include", @@ -221,6 +248,8 @@ c_commands = [ + [ f"-I{cwlibcdir}", f"-I{cwextrasdir}", + f"-I{cwlibcarmdir}", + f"-I{generateddir}", f"-I{homedir}/subprojects/NitroSDK-4.2.30001/include", f"-I{builddir}/subprojects/NitroSDK-4.2.30001/gen", f"-I{homedir}/subprojects/NitroSystem-071126.1/include",