#define NANOPRINTF_IMPLEMENTATION 1 // Remove what we don't need #define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0 #include "libstd_replacements.h" #include "libraries/nanoprintf/nanoprintf.h" #include #include #include #include "custom_malloc.h" // recommended for a 32 bit system to have at least 33 bytes available // source: https://cplusplus.com/reference/cstdlib/itoa/ // unfortunately itoa is not standardized, so we'll have to make do with snprintf static char conversion_buffer[33]; const char* ptgb::to_string(int intVal) { npf_snprintf(conversion_buffer, sizeof(conversion_buffer), "%d", intVal); return conversion_buffer; } const char* ptgb::to_string(unsigned int wordVal) { npf_snprintf(conversion_buffer, sizeof(conversion_buffer), "%u", wordVal); return conversion_buffer; } // when compiling with -nostdlib++, we need to provide our own operator new and delete implementations // Regular operator new void* operator new(std::size_t size) { void* ptr = malloc(size); if (!ptr) { // mimic standard behavior: throw std::bad_alloc // but we can't use std::bad_alloc without libstdc++ // so instead we can abort or return nullptr // You can also implement a custom exception if needed return NULL; } return ptr; } // nothrow version void* operator new(std::size_t size, const std::nothrow_t&) noexcept { return malloc(size); } // operator delete void operator delete(void* ptr) noexcept { free(ptr); } // nothrow delete void operator delete(void* ptr, const std::nothrow_t&) noexcept { free(ptr); } // sized delete (optional, for C++14 and newer) void operator delete(void* ptr, std::size_t size) noexcept { (void)size; free(ptr); }