mirror of
https://github.com/GearsProgress/Poke_Transporter_GB.git
synced 2026-03-22 01:44:36 -05:00
This commit removes all references to things in the libstdc++ library to remove a decent chunk of bloat. This means every std::to_string() call, std::string and std::vector. (as well as iostream related stuff). I replaced those with my own versions ptgb::to_string() and ptgb::vector. Especially the latter is not exactly the same, but close enough. I also replaced operator new and delete with my own implementation to avoid pulling in everything related to exceptions from libstdc++ Another problem was the fact that libtonc uses siscanf, which pulls in everything related to the scanf family of functions and locale support. The worst part of that was that it included a 13KB "categories" symbol from libc_a-categories.o, which was pulled in because of the locale support integrated into newlibc's siscanf() function. To fix that, I created a custom, extremely restricted implementation of siscanf. libtonc only used this function to parse at most 2 integers from a string anyway.
117 lines
3.4 KiB
C++
117 lines
3.4 KiB
C++
#define NANOPRINTF_IMPLEMENTATION 1
|
|
|
|
#include "libstd_replacements.h"
|
|
#include "libraries/nanoprintf/nanoprintf.h"
|
|
#include <cstdlib>
|
|
#include <stdarg.h>
|
|
#include <ctype.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];
|
|
|
|
extern "C"
|
|
{
|
|
// HACK:
|
|
// Unfortunately, libtonc references siscanf, which in turn causes a "lot" of binary bloat from newlibc (in regards to locale support)
|
|
// to be pulled in by the linker.
|
|
// However, if you look at what it is actually used for (in libtonc's tte_iohook.c), is just to extract 1 or 2 integers from a string
|
|
// by specifying a custom -extremely simplified- version, we can avoid pulling in the version from libc (alongside all the symbols IT references)
|
|
// Obviously it doesn't support everything it should. Just enough to support libtonc's current iteration.
|
|
//
|
|
// Anyway, doing this optimizes away a lot of scanf related functions from newlib and locale support among which a 13KB "categories" symbol.
|
|
int siscanf(const char *str, const char *format, ...)
|
|
{
|
|
bool expectingFormatSpecifier = false;
|
|
va_list args;
|
|
int* resultVal;
|
|
int ret = 0;
|
|
va_start(args, format);
|
|
|
|
while(*format != '\0')
|
|
{
|
|
if(*str == '\0')
|
|
{
|
|
//EOF encountered.
|
|
return -1;
|
|
}
|
|
|
|
if(expectingFormatSpecifier)
|
|
{
|
|
if(*format == 'd')
|
|
{
|
|
resultVal = va_arg(args, int*);
|
|
(*resultVal) = 0;
|
|
while(isdigit(*str))
|
|
{
|
|
(*resultVal) *= 10;
|
|
(*resultVal) += (*str) - '0';
|
|
++str;
|
|
}
|
|
// go back to the last character of the int, because we'll forward by one again at the end of the outer loop
|
|
--str;
|
|
++ret;
|
|
}
|
|
expectingFormatSpecifier = false;
|
|
}
|
|
else if((*format) == '%')
|
|
{
|
|
expectingFormatSpecifier = true;
|
|
}
|
|
|
|
++format;
|
|
++str;
|
|
}
|
|
|
|
va_end(args);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
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 = std::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
|
|
std::abort();
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
// nothrow version
|
|
void* operator new(std::size_t size, const std::nothrow_t&) noexcept {
|
|
return std::malloc(size);
|
|
}
|
|
|
|
// operator delete
|
|
void operator delete(void* ptr) noexcept {
|
|
std::free(ptr);
|
|
}
|
|
|
|
// nothrow delete
|
|
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
|
|
std::free(ptr);
|
|
}
|
|
|
|
// sized delete (optional, for C++14 and newer)
|
|
void operator delete(void* ptr, std::size_t size) noexcept {
|
|
(void)size;
|
|
std::free(ptr);
|
|
} |