mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-03-03 14:05:53 +01:00
110 lines
3.3 KiB
C
110 lines
3.3 KiB
C
#include <types.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
#if defined(__PORT_mos6502)
|
|
typedef void (*emitter_t)(char, char **) REENTRANT;
|
|
#else
|
|
typedef void (*emitter_t)(char, char **) OLDCALL;
|
|
#endif
|
|
|
|
static const char _hex[] = "0123456789ABCDEF";
|
|
|
|
inline void _printhex(uint16_t u, emitter_t emitter, char ** pData)
|
|
{
|
|
(*emitter)(_hex[(uint8_t)(u >> 8) >> 4], pData);
|
|
(*emitter)(_hex[(uint8_t)(u >> 8) & 0x0fu], pData);
|
|
(*emitter)(_hex[((uint8_t)u >> 4) & 0x0fu], pData);
|
|
(*emitter)(_hex[(uint8_t)u & 0x0fu], pData);
|
|
}
|
|
|
|
inline void _printhexbyte(uint8_t u, emitter_t emitter, char ** pData)
|
|
{
|
|
(*emitter)(_hex[u >> 4], pData);
|
|
(*emitter)(_hex[u & 0x0fu], pData);
|
|
}
|
|
|
|
static void _printbuf(char * buf, emitter_t emitter, char ** pData) {
|
|
for (char *s = buf; *s; s++) (*emitter)(*s, pData);
|
|
}
|
|
|
|
void __printf(const char *format, emitter_t emitter, char **pData, va_list va)
|
|
{
|
|
char buf[16];
|
|
while ((uint8_t)(*format)) {
|
|
if ((uint8_t)(*format) == '%') {
|
|
format++;
|
|
|
|
// 0 Padding is not supported, ignore
|
|
if ((uint8_t)(*format) == '0') format++;
|
|
|
|
// Width Specifier is not supported, ignore 1 digit worth
|
|
if ((uint8_t)((uint8_t)(*format) - '1') < 9u) format++;
|
|
|
|
switch ((uint8_t)(*format)) {
|
|
case 'h':
|
|
switch ((uint8_t)(*++format)) {
|
|
case 'X' :
|
|
case 'x' :
|
|
_printhexbyte(va_arg(va, char), emitter, pData);
|
|
break;
|
|
case 'u':
|
|
uitoa((unsigned char)va_arg(va, char), buf, 10);
|
|
_printbuf(buf, emitter, pData);
|
|
break;
|
|
case 'd':
|
|
itoa((signed char)va_arg(va, char), buf, 10);
|
|
_printbuf(buf, emitter, pData);
|
|
break;
|
|
}
|
|
break;
|
|
case 'u':
|
|
uitoa(va_arg(va, int), buf, 10);
|
|
_printbuf(buf, emitter, pData);
|
|
break;
|
|
case 'd':
|
|
itoa(va_arg(va, int), buf, 10);
|
|
_printbuf(buf, emitter, pData);
|
|
break;
|
|
case 's':
|
|
_printbuf(va_arg(va, char *), emitter, pData);
|
|
break;
|
|
case 'c':
|
|
char c = va_arg(va, char);
|
|
(*emitter)(c, pData);
|
|
break;
|
|
case 'X':
|
|
case 'x':
|
|
_printhex(va_arg(va, int), emitter, pData);
|
|
break;
|
|
default:
|
|
(*emitter)(*format, pData);
|
|
break;
|
|
}
|
|
} else {
|
|
(*emitter)(*format, pData);
|
|
}
|
|
format++;
|
|
}
|
|
}
|
|
|
|
#if defined(__PORT_mos6502)
|
|
static void _sprintf_emitter(char c, char ** pData) REENTRANT
|
|
#else
|
|
static void _sprintf_emitter(char c, char ** pData) OLDCALL
|
|
#endif
|
|
{
|
|
**pData = c;
|
|
(*pData)++;
|
|
}
|
|
|
|
void sprintf(char *into, const char *format, ...) {
|
|
va_list va;
|
|
va_start(va, format);
|
|
|
|
__printf(format, _sprintf_emitter, &into, va);
|
|
_sprintf_emitter('\0', &into);
|
|
}
|