Files
nostalgia/deps/ox/src/ox/std/tracehook.cpp

112 lines
2.9 KiB
C++

/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#if defined(OX_USE_STDLIB)
#include <iomanip>
#include <iostream>
static const auto OxPrintTrace = std::getenv("OXTRACE") != nullptr;
#endif
#include "strops.hpp"
#include "math.hpp"
#include "stringview.hpp"
#include "types.hpp"
#define REG_MGBA_DEBUG_ENABLE *reinterpret_cast<volatile uint16_t*>(0x4FFF780)
#define REG_MGBA_DEBUG_FLAGS *reinterpret_cast<volatile uint16_t*>(0x4FFF700)
#define REG_MGBA_DEBUG_STRING (reinterpret_cast<char*>(0x4FFF600))
inline void nullLog(ox::StringViewCR) {}
inline void (*infoLog)(ox::StringViewCR) = nullLog;
inline void (*debugLog)(ox::StringViewCR) = nullLog;
inline void (*errorLog)(ox::StringViewCR) = nullLog;
namespace mgba {
enum LogChan {
Fatal = 0,
Error = 1,
Warn = 2,
Info = 3,
Debug = 4,
};
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
template<LogChan chan>
static void log(ox::StringViewCR str) {
const auto sz = ox::min<std::size_t>(0x100, str.bytes());
ox::strncpy(REG_MGBA_DEBUG_STRING, str.data(), sz);
REG_MGBA_DEBUG_FLAGS = chan | 0x100;
}
void initConsole() {
REG_MGBA_DEBUG_ENABLE = 0xC0DE;
if (REG_MGBA_DEBUG_ENABLE == 0x1DEA) {
infoLog = log<LogChan::Info>;
debugLog = log<LogChan::Info>; // use INFO because mGBA disables DEBUG on start
errorLog = log<LogChan::Info>;
}
}
}
extern "C" {
void oxTraceInitHook() {
}
void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
[[maybe_unused]] const char *ch, [[maybe_unused]] const char *msg) {
#if defined(OX_USE_STDLIB)
auto const chv = ox::StringView{ch};
if (OxPrintTrace) {
auto m = std::string_view{msg};
if (m.ends_with('\n')) {
m = std::string_view{msg, m.size() - 1};
}
std::cout << std::setw(53) << std::left << ch << "| ";
std::cout << std::setw(65) << std::left << m << '|';
std::cout << " " << file << ':' << line << "\n";
} else if (chv == "debug" || chv == "info") {
printf("%s\n", msg);
std::ignore = fflush(stdout);
} else if (chv == "stdout") {
printf("%s", msg);
std::ignore = fflush(stdout);
} else if (chv == "stderr") {
std::ignore = fprintf(stderr, "%s", msg);
std::ignore = fflush(stderr);
} else if (chv == "error") {
//std::cerr << "\033[31;1;1mERROR:\033[0m (" << file << ':' << line << "): " << msg << '\n';
std::ignore = fprintf(stderr, "\033[31;1;1mERROR:\033[0m (%s:%d): %s\n", file, line, msg);
std::ignore = fflush(stderr);
}
#else
if (ox::strcmp(ch, "info") == 0) {
infoLog(msg);
} else if (ox::strcmp(ch, "debug") == 0) {
debugLog(msg);
} else if (ox::strcmp(ch, "stdout") == 0) {
infoLog(msg);
} else if (ox::strcmp(ch, "stderr") == 0) {
errorLog(msg);
} else if (ox::strcmp(ch, "error") == 0) {
errorLog(msg);
}
#endif
}
OX_ALLOW_UNSAFE_BUFFERS_END
}