From 702cce7d3e67a69261dc8d4c323e24575dc02ced Mon Sep 17 00:00:00 2001 From: niklascfw Date: Thu, 12 Nov 2026 22:50:20 +0100 Subject: [PATCH] Drop newlib printf: log via BDK s_vprintf, add debug.ini log switch log_write was the only vsnprintf user and pulled in newlib's printf, dtoa, malloc and soft-float code (~44 KB). The payload now fits the RCM limit again (146800 -> 102801 bytes); the build fails if it grows past it. debug.ini log=1 writes sd:/config/omninx/install.log. --- DEBUG_INI.md | 6 ++ Makefile | 2 +- bdk/utils/sprintf.c | 249 ++++++++++++++++++++++---------------------- bdk/utils/sprintf.h | 50 ++++----- source/fs.c | 20 ++-- source/fs.h | 1 + source/install.c | 33 +++++- 7 files changed, 205 insertions(+), 156 deletions(-) diff --git a/DEBUG_INI.md b/DEBUG_INI.md index fb297b9..ba91a46 100644 --- a/DEBUG_INI.md +++ b/DEBUG_INI.md @@ -45,6 +45,12 @@ Create the folder `sd:/config/omninx/` on the SD card if it does not exist. Same |-----|-----------------| | `skip_hekate_8gb_post_copy` | After a successful copy: the optional `hekate_8GB` / RAM menu and related file moves (see `install_hekate_8gb_post_copy` in `install.c`) | +### Logging + +| Key | Effect | +|-----|--------| +| `log` | Writes `sd:/config/omninx/install.log` with every deleted path, every copied file and the final result. Nothing is skipped. Slower on large packs; meant for test runs. | + ## Behaviour - On startup, if `debug.ini` exists and parses successfully, the payload prints a **DEBUG-MODUS** banner listing which skips are active. diff --git a/Makefile b/Makefile index 818e888..53245f0 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ OBJS_RAMTEST := $(filter-out $(BUILDDIR)/$(TARGET)/main.o,$(OBJS)) \ all: $(OUTPUTDIR)/$(OUTPUT_NAME) $(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(OUTPUT_NAME))) @echo "Payload size is $(BIN_SIZE) bytes (max $(MAX_PAYLOAD_SIZE) for RCM)" - @if [ $(BIN_SIZE) -gt $(MAX_PAYLOAD_SIZE) ]; then echo "WARNING: payload exceeds the RCM size limit"; fi + @if [ $(BIN_SIZE) -gt $(MAX_PAYLOAD_SIZE) ]; then echo "ERROR: payload exceeds the RCM size limit"; exit 1; fi clean: @rm -rf $(BUILDDIR) diff --git a/bdk/utils/sprintf.c b/bdk/utils/sprintf.c index c53f15c..0a6389b 100644 --- a/bdk/utils/sprintf.c +++ b/bdk/utils/sprintf.c @@ -1,123 +1,128 @@ -/* - * Copyright (c) 2019-2020 shchmue - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "sprintf.h" - -#include - -static void _putc(char *buffer, const char c) { - *buffer = c; -} - -static u32 _puts(char *buffer, const char *s) { - u32 count = 0; - for (; *s; s++, count++) - _putc(buffer + count, *s); - return count; -} - -static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) { - char buf[0x121]; - static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - char *p; - int c = fcnt; - - if (base > 36) - return 0; - - p = buf + 0x120; - *p = 0; - do { - c--; - *--p = digits[v % base]; - v /= base; - } while (v); - - if (fill != 0) { - while (c > 0) { - *--p = fill; - c--; - } - } - - return _puts(buffer, p); -} - -u32 s_printf(char *buffer, const char *fmt, ...) { - va_list ap; - int fill, fcnt; - u32 count = 0; - - va_start(ap, fmt); - while(*fmt) { - if (*fmt == '%') { - fmt++; - fill = 0; - fcnt = 0; - if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') { - fcnt = *fmt; - fmt++; - if (*fmt >= '0' && *fmt <= '9') { - fill = fcnt; - fcnt = *fmt - '0'; - fmt++; - } else { - fill = ' '; - fcnt -= '0'; - } - } - switch (*fmt) { - case 'c': - _putc(buffer + count, va_arg(ap, u32)); - count++; - break; - case 's': - count += _puts(buffer + count, va_arg(ap, char *)); - break; - case 'd': - count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt); - break; - case 'p': - case 'P': - case 'x': - case 'X': - count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt); - break; - case '%': - _putc(buffer + count, '%'); - count++; - break; - case '\0': - goto out; - default: - _putc(buffer + count, '%'); - count++; - _putc(buffer + count, *fmt); - count++; - break; - } - } else { - _putc(buffer + count, *fmt); - count++; - } - fmt++; - } - - out: - buffer[count] = 0; - va_end(ap); - return count; +/* + * Copyright (c) 2019-2020 shchmue + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sprintf.h" + +#include + +static void _putc(char *buffer, const char c) { + *buffer = c; +} + +static u32 _puts(char *buffer, const char *s) { + u32 count = 0; + for (; *s; s++, count++) + _putc(buffer + count, *s); + return count; +} + +static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) { + char buf[0x121]; + static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + char *p; + int c = fcnt; + + if (base > 36) + return 0; + + p = buf + 0x120; + *p = 0; + do { + c--; + *--p = digits[v % base]; + v /= base; + } while (v); + + if (fill != 0) { + while (c > 0) { + *--p = fill; + c--; + } + } + + return _puts(buffer, p); +} + +u32 s_vprintf(char *buffer, const char *fmt, va_list ap) { + int fill, fcnt; + u32 count = 0; + + while(*fmt) { + if (*fmt == '%') { + fmt++; + fill = 0; + fcnt = 0; + if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') { + fcnt = *fmt; + fmt++; + if (*fmt >= '0' && *fmt <= '9') { + fill = fcnt; + fcnt = *fmt - '0'; + fmt++; + } else { + fill = ' '; + fcnt -= '0'; + } + } + switch (*fmt) { + case 'c': + _putc(buffer + count, va_arg(ap, u32)); + count++; + break; + case 's': + count += _puts(buffer + count, va_arg(ap, char *)); + break; + case 'd': + count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt); + break; + case 'p': + case 'P': + case 'x': + case 'X': + count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt); + break; + case '%': + _putc(buffer + count, '%'); + count++; + break; + case '\0': + goto out; + default: + _putc(buffer + count, '%'); + count++; + _putc(buffer + count, *fmt); + count++; + break; + } + } else { + _putc(buffer + count, *fmt); + count++; + } + fmt++; + } + + out: + buffer[count] = 0; + return count; +} + +u32 s_printf(char *buffer, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + u32 count = s_vprintf(buffer, fmt, ap); + va_end(ap); + return count; } \ No newline at end of file diff --git a/bdk/utils/sprintf.h b/bdk/utils/sprintf.h index 0737775..7e2ef57 100644 --- a/bdk/utils/sprintf.h +++ b/bdk/utils/sprintf.h @@ -1,24 +1,26 @@ -/* - * Copyright (c) 2019-2020 shchmue - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _SPRINTF_H_ -#define _SPRINTF_H_ - -#include "types.h" - -u32 s_printf(char *buffer, const char *fmt, ...); - -#endif +/* + * Copyright (c) 2019-2020 shchmue + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _SPRINTF_H_ +#define _SPRINTF_H_ + +#include "types.h" +#include + +u32 s_printf(char *buffer, const char *fmt, ...); +u32 s_vprintf(char *buffer, const char *fmt, va_list ap); + +#endif diff --git a/source/fs.c b/source/fs.c index 62053b5..7002a34 100644 --- a/source/fs.c +++ b/source/fs.c @@ -9,14 +9,15 @@ #include #include #include -#include #define FS_BUFFER_SIZE 0x100000 // 1MB copy buffer -#define LOG_BUFFER_SIZE 512 +#define LOG_BUFFER_SIZE 1024 // fits two 255-char paths plus text +#define LOG_SYNC_EVERY 16 // Log file handle static FIL log_file; static bool log_enabled = false; +static u32 log_lines; static char log_buf[LOG_BUFFER_SIZE]; // Initialize log file @@ -24,6 +25,7 @@ void log_init(const char *path) { int res = f_open(&log_file, path, FA_WRITE | FA_CREATE_ALWAYS); if (res == FR_OK) { log_enabled = true; + log_lines = 0; log_write("=== OmniNX Installer Log ===\n\n"); } } @@ -44,15 +46,19 @@ void log_write(const char *fmt, ...) { va_list args; va_start(args, fmt); - // Format the message - vsnprintf(log_buf, LOG_BUFFER_SIZE, fmt, args); + // BDK formatter (no newlib printf). Callers keep paths <= 255 chars. + u32 len = s_vprintf(log_buf, fmt, args); va_end(args); - // Write to file UINT bw; - f_write(&log_file, log_buf, strlen(log_buf), &bw); - f_sync(&log_file); // Flush to ensure data is written + f_write(&log_file, log_buf, len, &bw); + if (++log_lines % LOG_SYNC_EVERY == 0) + f_sync(&log_file); +} + +bool log_is_enabled(void) { + return log_enabled; } // Convert FatFS error code to string diff --git a/source/fs.h b/source/fs.h index 9af9e22..2fb1309 100644 --- a/source/fs.h +++ b/source/fs.h @@ -18,3 +18,4 @@ int folder_delete(const char *path); void log_init(const char *path); void log_close(void); void log_write(const char *fmt, ...); +bool log_is_enabled(void); diff --git a/source/install.c b/source/install.c index e649c74..8dec1b9 100644 --- a/source/install.c +++ b/source/install.c @@ -289,7 +289,9 @@ int folder_copy_with_progress_v2(const char *src, const char *dst, const char *d install_set_color(COLOR_WHITE); // Perform the copy with progress updates + log_write("COPY TREE %s -> %s (%d Eintraege)\n", src, dst, (u32)total); res = folder_copy_progress_recursive(src, dst, &copied, total, start_x, start_y, display_name, &last_percent); + log_write("COPY TREE %s: %s\n", src, fs_error_str(res)); // Final update - overwrite the same line gfx_con_setpos(start_x, start_y); @@ -499,6 +501,7 @@ int delete_path_lists_grouped(const char *folder_display_name, ...) { res = f_unlink(path); } + log_write("DELETE %s: %s\n", path, fs_error_str(res)); if (res == FR_OK || res == FR_NO_FILE) deleted++; else @@ -1343,6 +1346,7 @@ static void install_extras_post_copy(void) } #define INSTALL_DEBUG_INI "sd:/config/omninx/debug.ini" +#define INSTALL_LOG_PATH "sd:/config/omninx/install.log" typedef struct { bool active; @@ -1356,6 +1360,7 @@ typedef struct { bool skip_update_staging_cleanup; bool skip_update_horizon_oc; bool skip_hekate_8gb_post_copy; + bool log; } install_debug_opts_t; static void install_debug_load(install_debug_opts_t *d) @@ -1397,6 +1402,8 @@ static void install_debug_load(install_debug_opts_t *d) d->skip_update_horizon_oc = install_ini_kv_truth(kv->val); else if (strcmp(kv->key, "skip_hekate_8gb_post_copy") == 0) d->skip_hekate_8gb_post_copy = install_ini_kv_truth(kv->val); + else if (strcmp(kv->key, "log") == 0) + d->log = install_ini_kv_truth(kv->val); } break; } @@ -1405,7 +1412,7 @@ static void install_debug_load(install_debug_opts_t *d) d->active = d->skip_clean_backup || d->skip_clean_wipe || d->skip_clean_restore || d->skip_clean_install || d->skip_clean_staging_cleanup || d->skip_update_cleanup || d->skip_update_install || d->skip_update_staging_cleanup || d->skip_update_horizon_oc - || d->skip_hekate_8gb_post_copy; + || d->skip_hekate_8gb_post_copy || d->log; } static void install_debug_print_banner(const install_debug_opts_t *d) @@ -1435,17 +1442,39 @@ static void install_debug_print_banner(const install_debug_opts_t *d) gfx_printf(" ueberspringe: HorizonOC Update (Backup/Restore)\n"); if (d->skip_hekate_8gb_post_copy) gfx_printf(" ueberspringe: extras RAM / Hekate-Auswahl / Post-Copy\n"); + if (d->log) + gfx_printf(" Log: %s\n", INSTALL_LOG_PATH); install_set_color(COLOR_WHITE); gfx_printf("\n"); } +static int perform_installation_steps(omninx_variant_t pack_variant, install_mode_t mode, const install_debug_opts_t *d); + // Main installation function int perform_installation(omninx_variant_t pack_variant, install_mode_t mode) { - int res; install_debug_opts_t dbg; install_debug_load(&dbg); install_debug_print_banner(&dbg); + if (dbg.log) { + log_init(INSTALL_LOG_PATH); + log_write("Version: %s\nModus: %s\nVariante: %d\n\n", VERSION, + mode == INSTALL_MODE_UPDATE ? "Update" : "Clean", (u32)pack_variant); + } + + int res = perform_installation_steps(pack_variant, mode, &dbg); + + if (log_is_enabled()) { + log_write("\n=== Ende: res=%d (%s) ===\n", (u32)res, fs_error_str(res)); + log_close(); + } + return res; +} + +static int perform_installation_steps(omninx_variant_t pack_variant, install_mode_t mode, const install_debug_opts_t *d) { + int res; + const install_debug_opts_t dbg = *d; + if (mode == INSTALL_MODE_UPDATE) { if (pack_variant == VARIANT_OC && !dbg.skip_update_horizon_oc) { bool had_horizon_cfg = install_path_exists(HORIZON_OC_CONFIG_PATH);