Initial commit

This commit is contained in:
Gericom
2025-11-22 17:21:45 +01:00
commit 5d6f67c612
517 changed files with 63025 additions and 0 deletions

32
common/logger/ILogger.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <stdarg.h>
enum class LogLevel
{
Off,
Fatal,
Error,
Warning,
Info,
Debug,
Trace,
All
};
class ILogger
{
public:
virtual ~ILogger() { }
void Log(LogLevel level, const char* fmt, ...)
{
va_list vlist;
va_start(vlist, fmt);
LogV(level, fmt, vlist);
va_end(vlist);
}
virtual void LogV(LogLevel level, const char* fmt, va_list vlist) = 0;
};

View File

@@ -0,0 +1,10 @@
#pragma once
class IOutputStream
{
public:
virtual ~IOutputStream() { }
virtual void Write(const char* str) = 0;
virtual void Flush() = 0;
};

View File

@@ -0,0 +1,47 @@
#include "common.h"
#include "NitroEmulatorOutputStream.h"
#define ISND_DBGINFO_ADDRESS 0x027FFF60
#define ISND_DBGINFO_AGB_ADDR_OFFSET 0x1C
#define ISND_DBGINFO_AGB_ADDR (*(u32*)(ISND_DBGINFO_ADDRESS + ISND_DBGINFO_AGB_ADDR_OFFSET))
#define ISND_AGB_PRINT_ARM9_WRITE_PTR_OFFSET 0x90
#define ISND_AGB_PRINT_ARM7_WRITE_PTR_OFFSET 0x92
#define ISND_AGB_PRINT_ARM9_READ_PTR_OFFSET 0x94
#define ISND_AGB_PRINT_ARM7_READ_PTR_OFFSET 0x96
#define ISND_AGB_SOMETHING_OFFSET 0xFE
#define ISND_AGB_PRINT_ARM9_RING_OFFSET 0x8000
#define ISND_AGB_PRINT_ARM7_RING_OFFSET 0xC000
#define ISND_AGB_PRINT_RING_LENGTH 0x4000
NitroEmulatorOutputStream::NitroEmulatorOutputStream()
{
#ifdef LIBTWL_ARM9
*(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_SOMETHING_OFFSET) = 0x202;
#endif
}
void NitroEmulatorOutputStream::Write(const char* str)
{
#ifdef LIBTWL_ARM9
char c;
vu16* ring = (vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_RING_OFFSET);
u32 writePtr = *(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_WRITE_PTR_OFFSET);
u32 readPtr = *(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_READ_PTR_OFFSET);
while ((c = *str++) != 0)
{
u32 newWritePtr = (writePtr + 1) & (ISND_AGB_PRINT_RING_LENGTH - 1);
while (newWritePtr == readPtr)
{
*(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_WRITE_PTR_OFFSET) = writePtr;
readPtr = *(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_READ_PTR_OFFSET);
}
if (writePtr & 1)
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF) | (c << 8);
else
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF00) | c;
writePtr = newWritePtr;
}
*(vu16*)(ISND_DBGINFO_AGB_ADDR + ISND_AGB_PRINT_ARM9_WRITE_PTR_OFFSET) = writePtr;
#endif
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "IOutputStream.h"
class NitroEmulatorOutputStream : public IOutputStream
{
public:
NitroEmulatorOutputStream();
void Write(const char* str) override;
void Flush() override { }
};

View File

@@ -0,0 +1,16 @@
#pragma once
#include "IOutputStream.h"
#define REG_NOCASH_STRING_OUT (*(vu32*)0x04FFFA10)
#define REG_NOCASH_CHAR_OUT (*(vu32*)0x04FFFA1C)
class NocashOutputStream : public IOutputStream
{
public:
void Write(const char* str) override
{
REG_NOCASH_STRING_OUT = (u32)str;
}
void Flush() override { }
};

View File

@@ -0,0 +1,8 @@
#pragma once
#include "ILogger.h"
class NullLogger : public ILogger
{
public:
void LogV(LogLevel level, const char* fmt, va_list vlist) override { }
};

View File

@@ -0,0 +1,9 @@
#pragma once
#include "IOutputStream.h"
class NullOutputStream : public IOutputStream
{
public:
void Write(const char* str) { }
void Flush() { }
};

View File

@@ -0,0 +1,28 @@
#include "common.h"
#include "picoAgbAdapter.h"
#include "PicoAgbAdapterOutputStream.h"
void PicoAgbAdapterOutputStream::Write(const char* str)
{
#ifdef LIBTWL_ARM9
char c;
vu16* ring = PICO_AGB_PRINT_ARM9_RING;
u32 writePtr = PICO_AGB_PRINT_ARM9_WRITE_PTR;
u32 readPtr = PICO_AGB_PRINT_ARM9_READ_PTR;
while ((c = *str++) != 0)
{
u32 newWritePtr = (writePtr + 1) & (PICO_AGB_PRINT_RING_LENGTH - 1);
while (newWritePtr == readPtr)
{
PICO_AGB_PRINT_ARM9_WRITE_PTR = writePtr;
readPtr = PICO_AGB_PRINT_ARM9_READ_PTR;
}
if (writePtr & 1)
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF) | (c << 8);
else
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF00) | c;
writePtr = newWritePtr;
}
PICO_AGB_PRINT_ARM9_WRITE_PTR = writePtr;
#endif
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "IOutputStream.h"
class PicoAgbAdapterOutputStream : public IOutputStream
{
public:
PicoAgbAdapterOutputStream() { }
void Write(const char* str) override;
void Flush() override { }
};

View File

@@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include "core/mini-printf.h"
#include "ILogger.h"
#include "IOutputStream.h"
class PlainLogger : public ILogger
{
LogLevel _maxLogLevel;
std::unique_ptr<IOutputStream> _outputStream;
char _logBuffer[512];
public:
PlainLogger(LogLevel maxLogLevel, std::unique_ptr<IOutputStream> outputStream)
: _maxLogLevel(maxLogLevel), _outputStream(std::move(outputStream))
{ }
void LogV(LogLevel level, const char* fmt, va_list vlist) override
{
if (level > _maxLogLevel)
return;
mini_vsnprintf(_logBuffer, sizeof(_logBuffer), fmt, vlist);
_outputStream->Write(_logBuffer);
}
};

View File

@@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <libtwl/rtos/rtosMutex.h>
#include "ILogger.h"
class ThreadSafeLogger : public ILogger
{
std::unique_ptr<ILogger> _logger;
rtos_mutex_t _mutex;
public:
explicit ThreadSafeLogger(std::unique_ptr<ILogger> logger)
: _logger(std::move(logger))
{
rtos_createMutex(&_mutex);
}
void LogV(LogLevel level, const char* fmt, va_list vlist) override
{
rtos_lockMutex(&_mutex);
{
_logger->LogV(level, fmt, vlist);
}
rtos_unlockMutex(&_mutex);
}
};