From 0d4345a9bf2623df079c50a3bc73cbb7deca1176 Mon Sep 17 00:00:00 2001 From: "John Wilbert M. Villamor" Date: Wed, 17 Jul 2019 11:30:07 +0800 Subject: Added C++ support, updated build instructions and makefiles, consolidated libc and libgcc (during build process), libraries now v0.12b and more --- libpsn00b/libc/_mem_init.s | 20 ++ libpsn00b/libc/abort.c | 9 + libpsn00b/libc/c++-support.cxx | 40 +++ libpsn00b/libc/makefile | 23 +- libpsn00b/libc/printf.c | 788 ----------------------------------------- libpsn00b/libc/start.c | 57 +++ libpsn00b/libc/start.s | 39 -- libpsn00b/libc/vsprintf.c | 788 +++++++++++++++++++++++++++++++++++++++++ libpsn00b/libc/vsprintf.c-old | 788 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1716 insertions(+), 836 deletions(-) create mode 100644 libpsn00b/libc/_mem_init.s create mode 100644 libpsn00b/libc/abort.c create mode 100644 libpsn00b/libc/c++-support.cxx delete mode 100644 libpsn00b/libc/printf.c create mode 100644 libpsn00b/libc/start.c delete mode 100644 libpsn00b/libc/start.s create mode 100644 libpsn00b/libc/vsprintf.c create mode 100644 libpsn00b/libc/vsprintf.c-old (limited to 'libpsn00b/libc') diff --git a/libpsn00b/libc/_mem_init.s b/libpsn00b/libc/_mem_init.s new file mode 100644 index 0000000..672ac2f --- /dev/null +++ b/libpsn00b/libc/_mem_init.s @@ -0,0 +1,20 @@ +.set noreorder + +.global _mem_init +.type _mem_init, @function +_mem_init: + +.section .text + +_mem_init: + la $a0, __bss_start + la $a1, _end +.Lclear_bss: + sb $0 , 0($a0) + blt $a0, $a1, .Lclear_bss + addiu $a0, 1 + la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc) + li $a1, 1572864 # Allocate 1.5MB at end of bss + j InitHeap + nop + \ No newline at end of file diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c new file mode 100644 index 0000000..ca5ab1d --- /dev/null +++ b/libpsn00b/libc/abort.c @@ -0,0 +1,9 @@ +#include + +void abort() { + + printf("abort()\n"); + + while(1); + +} \ No newline at end of file diff --git a/libpsn00b/libc/c++-support.cxx b/libpsn00b/libc/c++-support.cxx new file mode 100644 index 0000000..fcf7cfc --- /dev/null +++ b/libpsn00b/libc/c++-support.cxx @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +extern "C" + +void __cxa_pure_virtual(void) { + /* Pure C++ virtual call; abort! */ + assert(false); +} + +void* operator new(size_t size) { + return malloc(size); +} + +void* operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void* ptr) { + free(ptr); +} + +void operator delete[](void* ptr) { + free(ptr); +} + +/*- + * + * + * Called if a user-defined replacement is provided, except that it's + * unspecified whether other overloads or this overload is called when deleting + * objects of incomplete type and arrays of non-class and trivially-destructible + * class types. + * + * A memory allocator can use the given size to be more efficient */ +void operator delete(void* ptr, unsigned int) { + free(ptr); +} \ No newline at end of file diff --git a/libpsn00b/libc/makefile b/libpsn00b/libc/makefile index feadbdb..67f2284 100644 --- a/libpsn00b/libc/makefile +++ b/libpsn00b/libc/makefile @@ -2,20 +2,20 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libc.a -CFILES = $(notdir $(wildcard ./*.c)) -AFILES = $(notdir $(wildcard ./*.s)) -OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) +CFILES = $(notdir $(wildcard ./*.c)) +CXXFILES = $(notdir $(wildcard ./*.cxx)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CXXFILES:.cxx=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute -AFLAGS = -msoft-float -Wa,--strip-local-absolute +CFLAGS = -g -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float -Wa,--strip-local-absolute CC = $(PREFIX)gcc +CXX = $(PREFIX)g++ AS = $(PREFIX)as AR = $(PREFIX)ar RANLIB = $(PREFIX)ranlib @@ -23,12 +23,17 @@ RANLIB = $(PREFIX)ranlib all: $(TARGET) $(TARGET): $(OFILES) - $(AR) cr $(TARGET) $(OFILES) + cp $(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/libgcc.a ./$(TARGET) + $(AR) r $(TARGET) $(OFILES) $(RANLIB) $(TARGET) build/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.cxx + @mkdir -p $(dir $@) + $(CXX) $(CFLAGS) $(INCLUDE) -c $< -o $@ build/%.o: %.s @mkdir -p $(dir $@) diff --git a/libpsn00b/libc/printf.c b/libpsn00b/libc/printf.c deleted file mode 100644 index 7350648..0000000 --- a/libpsn00b/libc/printf.c +++ /dev/null @@ -1,788 +0,0 @@ -/* printf.c - * - * Inherited from the PSXSDK C library - */ - -#include -#include -#include - -#define SPRINTF_ALT_FLAG (1<<0) -#define SPRINTF_ZERO_FLAG (1<<1) -#define SPRINTF_NEGFIELD_FLAG (1<<2) -#define SPRINTF_SPACE_FLAG (1<<3) -#define SPRINTF_SIGN_FLAG (1<<4) - -// sprintf() macros to calculate the real padding and to write it -// these were made to not repeat the code in the function -// they can only be used in sprintf() - -// sprintf macros START - -#define calculate_real_padding() \ - y = 1; \ - \ - for(x=0;x<=19;x++) \ - { \ - if(x == 0) \ - pad_quantity--; \ - else \ - { \ - if(arg / y) \ - pad_quantity--; \ - } \ - \ - y *= 10; \ - } \ - \ - if(pad_quantity < 0) pad_quantity = 0; - -/*#define calculate_real_padding_hex() \ - for (x = 0; x < 8; x++) \ - { \ - if(x == 0) \ - pad_quantity--; \ - else \ - { \ - if((arg >> (x * 4)) & 0xf) \ - pad_quantity--; \ - } \ - }*/ - -#define calculate_real_padding_hex() \ - last = 0; \ - for (x = 0; x < 16; x++) \ - if((arg >> (x * 4)) & 0xf) \ - last = x; \ - \ - pad_quantity = (pad_quantity - 1) - last; \ - if(pad_quantity < 0) pad_quantity = 0; - -#define write_padding() \ - if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ - for(x = 0; x < pad_quantity; x++) \ - { \ - if(flags & SPRINTF_ZERO_FLAG) \ - put_in_string(string, ssz, '0', string_pos++); \ - else \ - put_in_string(string, ssz, ' ', string_pos++); \ - } - -#define write_neg_padding() \ - if(flags & SPRINTF_NEGFIELD_FLAG) \ - { \ - for(x = 0; x < pad_quantity; x++) \ - put_in_string(string, ssz, ' ', string_pos++);\ - } - -// sprintf macros END - -enum -{ - SPRINTF_SIZE_CHAR, - SPRINTF_SIZE_SHORT, - SPRINTF_SIZE_INT, - SPRINTF_SIZE_LONG, - SPRINTF_SIZE_LONG_LONG, -}; - -unsigned int get_arg_in_size(int size, unsigned long long *arg, unsigned int check_sign) -{ - int s = 0; - - switch(size) - { - case SPRINTF_SIZE_CHAR: - *arg &= 0xff; - - if(check_sign) - { - if(*arg & (1<<7)) - { - *arg |= 0xffffff00; - *arg = ~(*arg - 1); - s = 1; - } - } - break; - case SPRINTF_SIZE_SHORT: - *arg &= 0xffff; - - if(check_sign) - { - if(*arg & (1<<15)) - { - *arg |= 0xffff0000; - *arg = ~(*arg - 1); - s = 1; - } - } - break; - -// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx - - case SPRINTF_SIZE_INT: - case SPRINTF_SIZE_LONG: - *arg &= 0xffffffff; - - if(check_sign) - { - if(*arg & (1<<31)) - { - *arg |= (long long)0xffffffff00000000; - *arg = ~(*arg - 1); - s = 1; - } - } - break; - - case SPRINTF_SIZE_LONG_LONG: - if(check_sign) - { - if(*arg & ((long long)1<<63)) - { - *arg = ~(*arg - 1); - s = 1; - } - } - break; - } - - return s; -} - -int put_in_string(char *string, unsigned int sz, char c, int pos) -{ - if(pos>=sz) - return 0; - else - string[pos] = c; - - return 1; -} - -int libc_ulltoa(unsigned long long i, char *dst, int n) -{ - int x, y; - unsigned long long a, b; - int empty_digit = 1; - int sp=0; - int n2=0; - - for(x=20;x>=0;x--) - { - a = 1; - for(y = 0; y=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - { - i -= b*a; - - //put_in_string(string, ssz, b + '0', string_pos++); - if(n2!=n) - { - //printf("n2=%d\n",n2); - dst[sp++] = b + '0'; - n2++; - } - } - } - - if(n2!=n)dst[sp] = 0; - - return n2; -} - -void libc_float_to_string(float fl, char *dst, int n) -{ - unsigned int *p = (unsigned int*)&fl; - unsigned long long i = 0; - unsigned long long f = 0; - int e, m, s; - int x, y; - unsigned long long z; - - s = *p >> 31; - - e = (*p >> 23) & 0xff; - - m = *p & 0x7fffff; - - if(e == 255 && m == 0) // Infinity - { - if(s) strncpy(dst, "-inf", n); - else strncpy(dst, "inf", n); - }else if(e == 255 && m != 0) // NaN - { - strncpy(dst, "nan", n); - } - else - { - e -= 127; - m |= 1<<23; - - - - for(x = 23; x >= 0; x--) - { - if(m & (1<= 0) - { - z = 1; - for(y=0;y> 63; - - e = (*p >> 52) & 0x7ff; - //printf("%d\n", e); - - m = *p & 0xfffffffffffff; - - for(x=0;x<52;x++) - if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); - - if(e == 255 && m == 0) // Infinity - { - if(s) strncpy(dst, "-inf", n); - else strncpy(dst, "inf", n); - }else if(e == 255 && m != 0) // NaN - { - strncpy(dst, "nan", n); - } - else - { - e -= 1023; - m |= (unsigned long long)1<<52; - - for(x = 52; x >= 0; x--) - { - if(m & ((unsigned long long)1<= 0) - { - z = (long long)1<>= -(e + 1); - - f+=z; - } - } - e--; - } - - if(s && n) - { - *(dst++) = '-'; - n--; - } - - x = libc_ulltoa(i, dst, n); - n-=x; - dst+=x; - - if(n) - { - *(dst++) = '.'; - n--; - if(n) - libc_ulltoa(f, dst, n<6?n:6); - } - } -} - -char libc_sprintf_floatbuf[64]; - -int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap) -{ - int string_pos,fmt_pos; - int l; - unsigned long long arg; - unsigned char *argcp; - unsigned char *argcp_tmp; - int directive_coming = 0; - int alternate_form = 0; - int flags = 0; - int argsize = 2; // int - int x, y; - unsigned long long a, b; - int empty_digit; - int ssz = size - 1; - int zero_flag_imp = 0; - int pad_quantity = 0; - int last; - - l = strlen(fmt); - - string_pos = 0; - - for(fmt_pos=0;fmt_pos=0;x--) - { - a = 1; - for(y = 0; y=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - { - arg -= b*a; - - put_in_string(string, ssz, b + '0', string_pos++); - } - } - - /*if(flags & SPRINTF_NEGFIELD_FLAG) - { - for(x = 0; x < pad_quantity; x++) - put_in_string(string, ssz, ' ', string_pos++); - }*/ - write_neg_padding(); - - directive_coming = 0; - break; - case 'u': // unsigned decimal - empty_digit = 1; - - if(argsize < SPRINTF_SIZE_LONG_LONG) - arg = (unsigned long long)va_arg(ap, unsigned int); - else - arg = va_arg(ap, unsigned long long); - - get_arg_in_size(argsize, &arg, 0); - - calculate_real_padding(); - write_padding(); - - for(x=19;x>=0;x--) - { - a = 1; - for(y = 0; y=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - { - arg -= b*a; - - put_in_string(string, ssz, b + '0', string_pos++); - } - } - - write_neg_padding(); - - directive_coming = 0; - break; - case 'x': // Hexadecimal - case 'X': // Hexadecimal with big letters - case 'p': // Hexadecimal with small letters with '0x' prefix - empty_digit = 1; - - if(argsize < SPRINTF_SIZE_LONG_LONG) - arg = (unsigned long long)va_arg(ap, unsigned int); - else - arg = va_arg(ap, unsigned long long int); - - get_arg_in_size(argsize, &arg, 0); - - if(fmt_pos == 'p') - flags |= SPRINTF_ALT_FLAG; - - if(flags & SPRINTF_ALT_FLAG) - { - put_in_string(string, ssz, '0', string_pos++); - - if(fmt[fmt_pos] == 'X') - put_in_string(string, ssz, 'X', string_pos++); - else - put_in_string(string, ssz, 'x', string_pos++); - } - - calculate_real_padding_hex(); - write_padding(); - - for(x=15;x>=0;x--) - { - y = arg >> (x << 2); - y &= 0xf; - - if(y>=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - { - if(y>=0 && y<=9) - put_in_string(string, ssz, y + '0', string_pos++); - else if(y>=0xA && y<=0xF) - { - if(fmt[fmt_pos] == 'X') - put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); - else - put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); - } - } - } - - write_neg_padding(); - - directive_coming = 0; - break; - case 'c': // character - arg = va_arg(ap, int); - - put_in_string(string, ssz, arg & 0xff, string_pos++); - - directive_coming = 0; - break; - case 's': // string - argcp = va_arg(ap, char *); - argcp_tmp = argcp; - - if(argcp == NULL) - { - // Non standard extension, but supported by Linux and the BSDs. - - put_in_string(string, ssz, '(', string_pos++); - put_in_string(string, ssz, 'n', string_pos++); - put_in_string(string, ssz, 'u', string_pos++); - put_in_string(string, ssz, 'l', string_pos++); - put_in_string(string, ssz, 'l', string_pos++); - put_in_string(string, ssz, ')', string_pos++); - - directive_coming = 0; - break; - } - - while(*argcp_tmp) - { - if(pad_quantity > 0) pad_quantity--; - argcp_tmp++; - } - - if(!(flags & SPRINTF_NEGFIELD_FLAG)) - { - while(pad_quantity > 0) - { - put_in_string(string,ssz, ' ', string_pos++); - pad_quantity--; - } - } - - while(*argcp) - { - put_in_string(string, ssz, *argcp, string_pos++); - argcp++; - } - - if(flags & SPRINTF_NEGFIELD_FLAG) - { - while(pad_quantity > 0) - { - put_in_string(string,ssz, ' ', string_pos++); - pad_quantity--; - } - } - - directive_coming = 0; - break; - case 'o': // Octal - empty_digit = 1; - - if(argsize < SPRINTF_SIZE_LONG_LONG) - arg = (unsigned long long)va_arg(ap, unsigned int); - else - arg = va_arg(ap, unsigned long long); - - for(x=21;x>=0;x--) - { - y = arg >> (x * 3); - y &= 0x7; - - if(y>=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - put_in_string(string, ssz, y + '0', string_pos++); - } - - directive_coming = 0; - break; - case '@': // Binary - empty_digit = 1; - - if(argsize < SPRINTF_SIZE_LONG_LONG) - arg = (unsigned long long)va_arg(ap, unsigned int); - else - arg = va_arg(ap, unsigned long long); - - for(x=63;x>=0;x--) - { - y = (arg >> x); - y &= 1; - - if(y>=1) - empty_digit = 0; - - if(empty_digit == 0 || x == 0) - put_in_string(string, ssz, y + '0', string_pos++); - } - - directive_coming = 0; - break; - - case 'f': - libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64); - - for(x=0;libc_sprintf_floatbuf[x]!=0;x++) - put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); - - directive_coming = 0; - break; - case 'n': // Number of characters written - *(va_arg(ap,unsigned int*)) = string_pos; - - directive_coming = 0; - break; - // default - } - } - else - { - if(fmt[fmt_pos] == '%') - { - directive_coming = 1; - flags = 0; - argsize = 2; - pad_quantity = 0; - zero_flag_imp = 0; - } - else - put_in_string(string, ssz, fmt[fmt_pos], string_pos++); - } - } - string[string_pos] = 0; - return string_pos; -} - -int vsprintf(char *string, char *fmt, va_list ap) -{ - return vsnprintf(string, 0xffffffff, fmt, ap); -} - -int sprintf(char *string, char *fmt, ...) -{ - int r; - - va_list ap; - - va_start(ap, fmt); - - r = vsprintf(string, fmt, ap); - - va_end(ap); - - return r; -} - -int snprintf(char *string, unsigned int size, char *fmt, ...) -{ - int r; - - va_list ap; - - va_start(ap, fmt); - - r = vsnprintf(string, size, fmt, ap); - - va_end(ap); - - return r; -} diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c new file mode 100644 index 0000000..c234e03 --- /dev/null +++ b/libpsn00b/libc/start.c @@ -0,0 +1,57 @@ +#include +#include + +#define load_gp() __asm__ volatile ( \ + "la $gp, _gp;" ) + +extern int _end; +extern int main(int argc, const char* argv[]); + +void _mem_init(void); + + +static void _call_global_ctors(void) +{ + extern void (*__CTOR_LIST__[])(void); + + // Constructors are called in reverse order of the list + int i; + for (i = (int)__CTOR_LIST__[0]; i >= 1; i--) { + // Each function handles one or more destructor (within + // file scope) + __CTOR_LIST__[i](); + } +} + +static void _call_global_dtors(void) +{ + extern void (*__DTOR_LIST__[])(void); + + /* Destructors in forward order */ + int i; + for (i = 0; i < (int)__DTOR_LIST__[0]; i++) { + /* Each function handles one or more destructor (within + * file scope) */ + __DTOR_LIST__[i + 1](); + } +} + +void _start(void) { + + // Load GP address + load_gp(); + + // Mem init assembly function (clears BSS and InitHeap to _end which is + // not possible to do purely in C because the linker complains about + // relocation truncated to fit: R_MIPS_GPREL16 against `_end' + // Workaround is to do it in assembly because la pseudo-op doesn't use + // stupid gp relative addressing + _mem_init(); + + _call_global_ctors(); + + main(0, NULL); + + _call_global_dtors(); + +} \ No newline at end of file diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s deleted file mode 100644 index 2cf6ed0..0000000 --- a/libpsn00b/libc/start.s +++ /dev/null @@ -1,39 +0,0 @@ -# Start function! -# This is essentially the entry point of the PS-EXE - -.set noreorder - -.section .text - -.global _start -.type _start, @function -_start: - addiu $sp, -4 - sw $ra, 0($sp) - - la $gp, _gp # Very important! - - la $a0, .bss # What are the CORRECT symbols for BSS start and end? - la $a1, _end -.Lclear_bss: - sb $0 , 0($a0) - blt $a0, $a1, .Lclear_bss - addiu $a0, 1 - - la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc) - li $a1, 1572864 - jal InitHeap - nop - - move $a0, $0 # No support for arguments for now - move $a1, $0 - - jal main - addiu $sp, -8 - addiu $sp, 8 - - lw $ra, 0($sp) # Return - addiu $sp, 4 - jr $ra - nop - \ No newline at end of file diff --git a/libpsn00b/libc/vsprintf.c b/libpsn00b/libc/vsprintf.c new file mode 100644 index 0000000..153ca21 --- /dev/null +++ b/libpsn00b/libc/vsprintf.c @@ -0,0 +1,788 @@ +/* printf.c + * + * Inherited from the PSXSDK C library + */ + +#include +#include +#include + +#define SPRINTF_ALT_FLAG (1<<0) +#define SPRINTF_ZERO_FLAG (1<<1) +#define SPRINTF_NEGFIELD_FLAG (1<<2) +#define SPRINTF_SPACE_FLAG (1<<3) +#define SPRINTF_SIGN_FLAG (1<<4) + +// sprintf() macros to calculate the real padding and to write it +// these were made to not repeat the code in the function +// they can only be used in sprintf() + +// sprintf macros START + +#define calculate_real_padding() \ + y = 1; \ + \ + for(x=0;x<=19;x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if(arg / y) \ + pad_quantity--; \ + } \ + \ + y *= 10; \ + } \ + \ + if(pad_quantity < 0) pad_quantity = 0; + +/*#define calculate_real_padding_hex() \ + for (x = 0; x < 8; x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if((arg >> (x * 4)) & 0xf) \ + pad_quantity--; \ + } \ + }*/ + +#define calculate_real_padding_hex() \ + last = 0; \ + for (x = 0; x < 16; x++) \ + if((arg >> (x * 4)) & 0xf) \ + last = x; \ + \ + pad_quantity = (pad_quantity - 1) - last; \ + if(pad_quantity < 0) pad_quantity = 0; + +#define write_padding() \ + if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ + for(x = 0; x < pad_quantity; x++) \ + { \ + if(flags & SPRINTF_ZERO_FLAG) \ + put_in_string(string, ssz, '0', string_pos++); \ + else \ + put_in_string(string, ssz, ' ', string_pos++); \ + } + +#define write_neg_padding() \ + if(flags & SPRINTF_NEGFIELD_FLAG) \ + { \ + for(x = 0; x < pad_quantity; x++) \ + put_in_string(string, ssz, ' ', string_pos++);\ + } + +// sprintf macros END + +enum +{ + SPRINTF_SIZE_CHAR, + SPRINTF_SIZE_SHORT, + SPRINTF_SIZE_INT, + SPRINTF_SIZE_LONG, + SPRINTF_SIZE_LONG_LONG, +}; + +unsigned int get_arg_in_size(int size, unsigned long *arg, unsigned int check_sign) +{ + int s = 0; + + switch(size) + { + case SPRINTF_SIZE_CHAR: + *arg &= 0xff; + + if(check_sign) + { + if(*arg & (1<<7)) + { + *arg |= 0xffffff00; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + case SPRINTF_SIZE_SHORT: + *arg &= 0xffff; + + if(check_sign) + { + if(*arg & (1<<15)) + { + *arg |= 0xffff0000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + +// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx + + case SPRINTF_SIZE_INT: + case SPRINTF_SIZE_LONG: + *arg &= 0xffffffff; + + /*if(check_sign) + { + if(*arg & (1<<31)) + { + *arg |= (long long)0xffffffff00000000; + *arg = ~(*arg - 1); + s = 1; + } + }*/ + break; + + /*case SPRINTF_SIZE_LONG_LONG: + if(check_sign) + { + if(*arg & ((long long)1<<63)) + { + *arg = ~(*arg - 1); + s = 1; + } + } + break;*/ + } + + return s; +} + +int put_in_string(char *string, unsigned int sz, char c, int pos) +{ + if(pos>=sz) + return 0; + else + string[pos] = c; + + return 1; +} + +int libc_ulltoa(unsigned long i, char *dst, int n) +{ + int x, y; + unsigned long a, b; + int empty_digit = 1; + int sp=0; + int n2=0; + + for(x=20;x>=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + i -= b*a; + + //put_in_string(string, ssz, b + '0', string_pos++); + if(n2!=n) + { + //printf("n2=%d\n",n2); + dst[sp++] = b + '0'; + n2++; + } + } + } + + if(n2!=n)dst[sp] = 0; + + return n2; +} + +void libc_float_to_string(float fl, char *dst, int n) +{ + unsigned int *p = (unsigned int*)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + int e, m, s; + int x, y; + unsigned long long z; + + s = *p >> 31; + + e = (*p >> 23) & 0xff; + + m = *p & 0x7fffff; + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 127; + m |= 1<<23; + + + + for(x = 23; x >= 0; x--) + { + if(m & (1<= 0) + { + z = 1; + for(y=0;y> 63; + + e = (*p >> 52) & 0x7ff; + //printf("%d\n", e); + + m = *p & 0xfffffffffffff; + + for(x=0;x<52;x++) + if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 1023; + m |= (unsigned long long)1<<52; + + for(x = 52; x >= 0; x--) + { + if(m & ((unsigned long long)1<= 0) + { + z = (long long)1<>= -(e + 1); + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + libc_ulltoa(f, dst, n<6?n:6); + } + } +} + +char libc_sprintf_floatbuf[64]; + +int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap) +{ + int string_pos,fmt_pos; + int l; + unsigned long arg; + unsigned char *argcp; + unsigned char *argcp_tmp; + int directive_coming = 0; + int alternate_form = 0; + int flags = 0; + int argsize = 2; // int + int x, y; + unsigned long a, b; + int empty_digit; + int ssz = size - 1; + int zero_flag_imp = 0; + int pad_quantity = 0; + int last; + + l = strlen(fmt); + + string_pos = 0; + + for(fmt_pos=0;fmt_pos=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + /*if(flags & SPRINTF_NEGFIELD_FLAG) + { + for(x = 0; x < pad_quantity; x++) + put_in_string(string, ssz, ' ', string_pos++); + }*/ + write_neg_padding(); + + directive_coming = 0; + break; + case 'u': // unsigned decimal + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + //arg = va_arg(ap, unsigned long long); + + get_arg_in_size(argsize, &arg, 0); + + calculate_real_padding(); + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'x': // Hexadecimal + case 'X': // Hexadecimal with big letters + case 'p': // Hexadecimal with small letters with '0x' prefix + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long int); + + get_arg_in_size(argsize, &arg, 0); + + if(fmt_pos == 'p') + flags |= SPRINTF_ALT_FLAG; + + if(flags & SPRINTF_ALT_FLAG) + { + put_in_string(string, ssz, '0', string_pos++); + + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, 'X', string_pos++); + else + put_in_string(string, ssz, 'x', string_pos++); + } + + calculate_real_padding_hex(); + write_padding(); + + for(x=7;x>=0;x--) + { + y = arg >> (x << 2); + y &= 0xf; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + if(y>=0 && y<=9) + put_in_string(string, ssz, y + '0', string_pos++); + else if(y>=0xA && y<=0xF) + { + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); + else + put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); + } + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'c': // character + arg = va_arg(ap, int); + + put_in_string(string, ssz, arg & 0xff, string_pos++); + + directive_coming = 0; + break; + case 's': // string + argcp = va_arg(ap, char *); + argcp_tmp = argcp; + + if(argcp == NULL) + { + // Non standard extension, but supported by Linux and the BSDs. + + put_in_string(string, ssz, '(', string_pos++); + put_in_string(string, ssz, 'n', string_pos++); + put_in_string(string, ssz, 'u', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, ')', string_pos++); + + directive_coming = 0; + break; + } + + while(*argcp_tmp) + { + if(pad_quantity > 0) pad_quantity--; + argcp_tmp++; + } + + if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + while(*argcp) + { + put_in_string(string, ssz, *argcp, string_pos++); + argcp++; + } + + if(flags & SPRINTF_NEGFIELD_FLAG) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + directive_coming = 0; + break; + case 'o': // Octal + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long long); + + for(x=21;x>=0;x--) + { + y = arg >> (x * 3); + y &= 0x7; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + case '@': // Binary + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long long); + + for(x=31;x>=0;x--) + { + y = (arg >> x); + y &= 1; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + + case 'f': + libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64); + + for(x=0;libc_sprintf_floatbuf[x]!=0;x++) + put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); + + directive_coming = 0; + break; + case 'n': // Number of characters written + *(va_arg(ap,unsigned int*)) = string_pos; + + directive_coming = 0; + break; + // default + } + } + else + { + if(fmt[fmt_pos] == '%') + { + directive_coming = 1; + flags = 0; + argsize = 2; + pad_quantity = 0; + zero_flag_imp = 0; + } + else + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + } + } + string[string_pos] = 0; + return string_pos; +} + +int vsprintf(char *string, const char *fmt, va_list ap) +{ + return vsnprintf(string, 0xffffffff, fmt, ap); +} + +int sprintf(char *string, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsprintf(string, fmt, ap); + + va_end(ap); + + return r; +} + +int snprintf(char *string, unsigned int size, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsnprintf(string, size, fmt, ap); + + va_end(ap); + + return r; +} diff --git a/libpsn00b/libc/vsprintf.c-old b/libpsn00b/libc/vsprintf.c-old new file mode 100644 index 0000000..9c68a1f --- /dev/null +++ b/libpsn00b/libc/vsprintf.c-old @@ -0,0 +1,788 @@ +/* printf.c + * + * Inherited from the PSXSDK C library + */ + +#include +#include +#include + +#define SPRINTF_ALT_FLAG (1<<0) +#define SPRINTF_ZERO_FLAG (1<<1) +#define SPRINTF_NEGFIELD_FLAG (1<<2) +#define SPRINTF_SPACE_FLAG (1<<3) +#define SPRINTF_SIGN_FLAG (1<<4) + +// sprintf() macros to calculate the real padding and to write it +// these were made to not repeat the code in the function +// they can only be used in sprintf() + +// sprintf macros START + +#define calculate_real_padding() \ + y = 1; \ + \ + for(x=0;x<=19;x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if(arg / y) \ + pad_quantity--; \ + } \ + \ + y *= 10; \ + } \ + \ + if(pad_quantity < 0) pad_quantity = 0; + +/*#define calculate_real_padding_hex() \ + for (x = 0; x < 8; x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if((arg >> (x * 4)) & 0xf) \ + pad_quantity--; \ + } \ + }*/ + +#define calculate_real_padding_hex() \ + last = 0; \ + for (x = 0; x < 16; x++) \ + if((arg >> (x * 4)) & 0xf) \ + last = x; \ + \ + pad_quantity = (pad_quantity - 1) - last; \ + if(pad_quantity < 0) pad_quantity = 0; + +#define write_padding() \ + if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ + for(x = 0; x < pad_quantity; x++) \ + { \ + if(flags & SPRINTF_ZERO_FLAG) \ + put_in_string(string, ssz, '0', string_pos++); \ + else \ + put_in_string(string, ssz, ' ', string_pos++); \ + } + +#define write_neg_padding() \ + if(flags & SPRINTF_NEGFIELD_FLAG) \ + { \ + for(x = 0; x < pad_quantity; x++) \ + put_in_string(string, ssz, ' ', string_pos++);\ + } + +// sprintf macros END + +enum +{ + SPRINTF_SIZE_CHAR, + SPRINTF_SIZE_SHORT, + SPRINTF_SIZE_INT, + SPRINTF_SIZE_LONG, + SPRINTF_SIZE_LONG_LONG, +}; + +unsigned int get_arg_in_size(int size, unsigned long long *arg, unsigned int check_sign) +{ + int s = 0; + + switch(size) + { + case SPRINTF_SIZE_CHAR: + *arg &= 0xff; + + if(check_sign) + { + if(*arg & (1<<7)) + { + *arg |= 0xffffff00; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + case SPRINTF_SIZE_SHORT: + *arg &= 0xffff; + + if(check_sign) + { + if(*arg & (1<<15)) + { + *arg |= 0xffff0000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + +// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx + + case SPRINTF_SIZE_INT: + case SPRINTF_SIZE_LONG: + *arg &= 0xffffffff; + + if(check_sign) + { + if(*arg & (1<<31)) + { + *arg |= (long long)0xffffffff00000000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + + case SPRINTF_SIZE_LONG_LONG: + if(check_sign) + { + if(*arg & ((long long)1<<63)) + { + *arg = ~(*arg - 1); + s = 1; + } + } + break; + } + + return s; +} + +int put_in_string(char *string, unsigned int sz, char c, int pos) +{ + if(pos>=sz) + return 0; + else + string[pos] = c; + + return 1; +} + +int libc_ulltoa(unsigned long long i, char *dst, int n) +{ + int x, y; + unsigned long long a, b; + int empty_digit = 1; + int sp=0; + int n2=0; + + for(x=20;x>=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + i -= b*a; + + //put_in_string(string, ssz, b + '0', string_pos++); + if(n2!=n) + { + //printf("n2=%d\n",n2); + dst[sp++] = b + '0'; + n2++; + } + } + } + + if(n2!=n)dst[sp] = 0; + + return n2; +} + +void libc_float_to_string(float fl, char *dst, int n) +{ + unsigned int *p = (unsigned int*)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + int e, m, s; + int x, y; + unsigned long long z; + + s = *p >> 31; + + e = (*p >> 23) & 0xff; + + m = *p & 0x7fffff; + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 127; + m |= 1<<23; + + + + for(x = 23; x >= 0; x--) + { + if(m & (1<= 0) + { + z = 1; + for(y=0;y> 63; + + e = (*p >> 52) & 0x7ff; + //printf("%d\n", e); + + m = *p & 0xfffffffffffff; + + for(x=0;x<52;x++) + if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 1023; + m |= (unsigned long long)1<<52; + + for(x = 52; x >= 0; x--) + { + if(m & ((unsigned long long)1<= 0) + { + z = (long long)1<>= -(e + 1); + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + libc_ulltoa(f, dst, n<6?n:6); + } + } +} + +char libc_sprintf_floatbuf[64]; + +int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap) +{ + int string_pos,fmt_pos; + int l; + unsigned long long arg; + unsigned char *argcp; + unsigned char *argcp_tmp; + int directive_coming = 0; + int alternate_form = 0; + int flags = 0; + int argsize = 2; // int + int x, y; + unsigned long long a, b; + int empty_digit; + int ssz = size - 1; + int zero_flag_imp = 0; + int pad_quantity = 0; + int last; + + l = strlen(fmt); + + string_pos = 0; + + for(fmt_pos=0;fmt_pos=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + /*if(flags & SPRINTF_NEGFIELD_FLAG) + { + for(x = 0; x < pad_quantity; x++) + put_in_string(string, ssz, ' ', string_pos++); + }*/ + write_neg_padding(); + + directive_coming = 0; + break; + case 'u': // unsigned decimal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + get_arg_in_size(argsize, &arg, 0); + + calculate_real_padding(); + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'x': // Hexadecimal + case 'X': // Hexadecimal with big letters + case 'p': // Hexadecimal with small letters with '0x' prefix + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long int); + + get_arg_in_size(argsize, &arg, 0); + + if(fmt_pos == 'p') + flags |= SPRINTF_ALT_FLAG; + + if(flags & SPRINTF_ALT_FLAG) + { + put_in_string(string, ssz, '0', string_pos++); + + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, 'X', string_pos++); + else + put_in_string(string, ssz, 'x', string_pos++); + } + + calculate_real_padding_hex(); + write_padding(); + + for(x=15;x>=0;x--) + { + y = arg >> (x << 2); + y &= 0xf; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + if(y>=0 && y<=9) + put_in_string(string, ssz, y + '0', string_pos++); + else if(y>=0xA && y<=0xF) + { + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); + else + put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); + } + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'c': // character + arg = va_arg(ap, int); + + put_in_string(string, ssz, arg & 0xff, string_pos++); + + directive_coming = 0; + break; + case 's': // string + argcp = va_arg(ap, char *); + argcp_tmp = argcp; + + if(argcp == NULL) + { + // Non standard extension, but supported by Linux and the BSDs. + + put_in_string(string, ssz, '(', string_pos++); + put_in_string(string, ssz, 'n', string_pos++); + put_in_string(string, ssz, 'u', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, ')', string_pos++); + + directive_coming = 0; + break; + } + + while(*argcp_tmp) + { + if(pad_quantity > 0) pad_quantity--; + argcp_tmp++; + } + + if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + while(*argcp) + { + put_in_string(string, ssz, *argcp, string_pos++); + argcp++; + } + + if(flags & SPRINTF_NEGFIELD_FLAG) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + directive_coming = 0; + break; + case 'o': // Octal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=21;x>=0;x--) + { + y = arg >> (x * 3); + y &= 0x7; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + case '@': // Binary + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=63;x>=0;x--) + { + y = (arg >> x); + y &= 1; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + + case 'f': + libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64); + + for(x=0;libc_sprintf_floatbuf[x]!=0;x++) + put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); + + directive_coming = 0; + break; + case 'n': // Number of characters written + *(va_arg(ap,unsigned int*)) = string_pos; + + directive_coming = 0; + break; + // default + } + } + else + { + if(fmt[fmt_pos] == '%') + { + directive_coming = 1; + flags = 0; + argsize = 2; + pad_quantity = 0; + zero_flag_imp = 0; + } + else + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + } + } + string[string_pos] = 0; + return string_pos; +} + +int vsprintf(char *string, const char *fmt, va_list ap) +{ + return vsnprintf(string, 0xffffffff, fmt, ap); +} + +int sprintf(char *string, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsprintf(string, fmt, ap); + + va_end(ap); + + return r; +} + +int snprintf(char *string, unsigned int size, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsnprintf(string, size, fmt, ap); + + va_end(ap); + + return r; +} -- cgit v1.2.3