124 lines
2.8 KiB
C
124 lines
2.8 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "log/log.h"
|
|
#include "display/display.h"
|
|
#include <debug.h>
|
|
#include <fat.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#define LOG_DEBUG_PATH "/apps/Dusk/debug.log"
|
|
#define LOG_ERROR_PATH "/apps/Dusk/error.log"
|
|
|
|
static bool_t fatTried = false;
|
|
static bool_t fatReady = false;
|
|
|
|
static void logInitFAT(void) {
|
|
if(fatTried) return;
|
|
fatTried = true;
|
|
fatReady = fatInitDefault();
|
|
}
|
|
|
|
void logDebug(const char_t *message, ...) {
|
|
va_list args;
|
|
va_start(args, message);
|
|
|
|
// Print to stdout
|
|
va_list copy;
|
|
va_copy(copy, args);
|
|
vfprintf(stdout, message, copy);
|
|
va_end(copy);
|
|
fflush(stdout);
|
|
|
|
// Print to file
|
|
logInitFAT();
|
|
if(fatReady) {
|
|
FILE *file = fopen(LOG_DEBUG_PATH, "a");
|
|
if(file) {
|
|
va_copy(copy, args);
|
|
vfprintf(file, message, copy);
|
|
va_end(copy);
|
|
fclose(file);
|
|
}
|
|
}
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
void logError(const char_t *message, ...) {
|
|
va_list args;
|
|
va_start(args, message);
|
|
|
|
// Write to file before displaying on screen
|
|
logInitFAT();
|
|
if(fatReady) {
|
|
FILE *file = fopen(LOG_ERROR_PATH, "a");
|
|
if(file) {
|
|
va_list copy;
|
|
va_copy(copy, args);
|
|
vfprintf(file, message, copy);
|
|
va_end(copy);
|
|
fclose(file);
|
|
}
|
|
}
|
|
|
|
// Either create graphics, or hijack the displays' graphics.
|
|
GXRModeObj *rmode = NULL;
|
|
void *framebuffer;
|
|
|
|
if(DISPLAY.frameBuffer[0]) {
|
|
console_init(
|
|
DISPLAY.frameBuffer[0],
|
|
20,
|
|
20,
|
|
DISPLAY.screenMode->fbWidth,
|
|
DISPLAY.screenMode->xfbHeight,
|
|
DISPLAY.screenMode->fbWidth * VI_DISPLAY_PIX_SZ
|
|
);
|
|
} else {
|
|
VIDEO_Init();
|
|
rmode = VIDEO_GetPreferredMode(NULL);
|
|
framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
|
console_init(
|
|
framebuffer,
|
|
20,
|
|
20,
|
|
rmode->fbWidth,
|
|
rmode->xfbHeight,
|
|
rmode->fbWidth*VI_DISPLAY_PIX_SZ
|
|
);
|
|
VIDEO_Configure(rmode);
|
|
VIDEO_SetNextFramebuffer(framebuffer);
|
|
VIDEO_SetBlack(FALSE);
|
|
VIDEO_Flush();
|
|
VIDEO_WaitVSync();
|
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
|
}
|
|
|
|
// Printf
|
|
va_list copy;
|
|
va_copy(copy, args);
|
|
vprintf(message, copy);
|
|
va_end(copy);
|
|
va_end(args);
|
|
|
|
// PAD_Init is idempotent — safe to call even if inputInit already called it,
|
|
// and handles the case where the error occurred before inputInit ran.
|
|
PAD_Init();
|
|
while(SYS_MainLoop()) {
|
|
PAD_ScanPads();
|
|
// START button matches the RAGEQUIT bind — allows exit on GC controller
|
|
// when there is no Wiimote HOME button available.
|
|
if(PAD_ButtonsDown(0) & PAD_BUTTON_START) break;
|
|
VIDEO_WaitVSync();
|
|
}
|
|
|
|
// Exit cleanly to HBC regardless of engine state. engineDispose() is not
|
|
// called here because the engine may be partially initialized.
|
|
exit(0);
|
|
} |