diff options
| author | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2021-08-17 11:36:50 +0000 |
|---|---|---|
| committer | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2021-08-17 11:36:50 +0000 |
| commit | 5f5461879c73720359e87fa41cbfe8c452f5155e (patch) | |
| tree | 9de8b0dcfcffa70fac7da91792772679af8341bb | |
| parent | acc1a959fe3c4bc5d5e91f1f31e182ff967008ca (diff) | |
| download | psn00bsdk-5f5461879c73720359e87fa41cbfe8c452f5155e.tar.gz | |
Added missing header declarations, FlushCache, misc library bugfixes
| -rw-r--r-- | libpsn00b/include/psxapi.h | 1 | ||||
| -rw-r--r-- | libpsn00b/include/psxgpu.h | 2 | ||||
| -rw-r--r-- | libpsn00b/include/stdio.h | 3 | ||||
| -rw-r--r-- | libpsn00b/libc/_mem_init.s | 20 | ||||
| -rw-r--r-- | libpsn00b/libc/malloc.s | 11 | ||||
| -rw-r--r-- | libpsn00b/libc/start.c | 181 | ||||
| -rw-r--r-- | libpsn00b/psxapi/sys/flushcache.s | 10 | ||||
| -rw-r--r-- | libpsn00b/psxspu/transfer.s | 3 |
8 files changed, 121 insertions, 110 deletions
diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h index c366702..9e92568 100644 --- a/libpsn00b/include/psxapi.h +++ b/libpsn00b/include/psxapi.h @@ -180,6 +180,7 @@ void ChangeClearRCnt(int t, int m); // Executable functions int Exec(struct EXEC *exec, int argc, char **argv); +void FlushCache(void); void _boot(void); diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index ddb4522..f50b841 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -1,6 +1,8 @@ #ifndef __PSXGPU_H #define __PSXGPU_H +#include <sys/types.h> + // Low-level display parameters for DISPENV_RAW. A leftover from prototyping #define DISP_WIDTH_256 0 #define DISP_WIDTH_320 1 diff --git a/libpsn00b/include/stdio.h b/libpsn00b/include/stdio.h index cf1909d..97a2f5a 100644 --- a/libpsn00b/include/stdio.h +++ b/libpsn00b/include/stdio.h @@ -56,6 +56,9 @@ int vsprintf(char *string, const char *fmt, va_list ap); int sprintf(char *string, const char *fmt, ...); int snprintf(char *string, unsigned int size, const char *fmt, ...); +int vsscanf(const char *str, const char *format, va_list ap); +int sscanf(const char *str, const char *fmt, ...); + #ifdef __cplusplus } #endif diff --git a/libpsn00b/libc/_mem_init.s b/libpsn00b/libc/_mem_init.s deleted file mode 100644 index 672ac2f..0000000 --- a/libpsn00b/libc/_mem_init.s +++ /dev/null @@ -1,20 +0,0 @@ -.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/malloc.s b/libpsn00b/libc/malloc.s index 90f9bd4..e441bbe 100644 --- a/libpsn00b/libc/malloc.s +++ b/libpsn00b/libc/malloc.s @@ -1,5 +1,10 @@ # Custom first-fit malloc routines by Lameguy64 # Part of the PSn00bSDK Project +# +# NOTE: there reportedly is a GCC bug which messes up .weak functions written +# in assembly if LTO is enabled. I haven't tested but, according to the +# internet, this bug has never been fixed. +# https://gcc.gnu.org/legacy-ml/gcc-help/2019-10/msg00092.html .set noreorder @@ -10,7 +15,6 @@ .section .text - # Stupid small function just to get bss end # due to GCC insisting externs to be gp relative .global GetBSSend @@ -27,6 +31,7 @@ GetBSSend: # .global InitHeap .type InitHeap, @function +.weak InitHeap InitHeap: la $v0, _malloc_addr sw $a0, 0($v0) @@ -43,6 +48,7 @@ InitHeap: # a0 - Size of memory heap in bytes .global SetHeapSize .type SetHeapSize, @function +.weak SetHeapSize SetHeapSize: la $v1, _malloc_size lw $v0, 0($v1) @@ -55,6 +61,7 @@ SetHeapSize: # .global malloc .type malloc, @function +.weak malloc malloc: addiu $a0, 3 # Round size to a multiple of 4 srl $a0, 2 @@ -170,6 +177,7 @@ malloc: # .global calloc .type calloc, @function +.weak calloc calloc: mult $a0, $a1 addiu $sp, -4 @@ -199,6 +207,7 @@ calloc: # .global free .type free, @function +.weak free free: addiu $a0, -ND_HSIZ diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c index 354ebb9..c5872df 100644 --- a/libpsn00b/libc/start.c +++ b/libpsn00b/libc/start.c @@ -1,110 +1,115 @@ -#include <stdio.h> +/* + * PSn00bSDK startup code + * (C) 2021 Lameguy64, spicyjpeg - MPL licensed + */ + +#include <sys/types.h> #include <string.h> #include <malloc.h> -#define load_gp() __asm__ volatile ( \ - "la $gp, _gp;" ) - -extern int _end; -extern int main(int argc, const char* argv[]); +#define KERNEL_ARG_STRING ((const char *) 0x80000180) +#define KERNEL_RETURN_VALUE ((volatile int *) 0x8000dffc) -void _mem_init(void); +/* Argument parsing */ -int __argc; +int32_t __argc; const char **__argv; -static const char *_arg_ptrs_int[8]; -static char _arg_buff[132]; +#define ARGC_MAX 16 -static void _call_global_ctors(void) -{ - extern void (*__CTOR_LIST__[])(void); +static const char *_argv_buffer[ARGC_MAX]; +static char _arg_string_buffer[132]; - // 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 _parse_kernel_args() { + // Copy the argument string from kernel memory into a private buffer (which + // won't be cleared or deallocated) and trim it at the first newline. + memset(_arg_string_buffer, 0, 132); + strncpy(_arg_string_buffer, KERNEL_ARG_STRING, 128); + + for (char *ptr = _arg_string_buffer; *ptr; ptr++) { + if ((*ptr == '\r') || (*ptr == '\n')) { + *ptr = 0; + break; + } } -} -static void _call_global_dtors(void) -{ - extern void (*__DTOR_LIST__[])(void); + __argv = _argv_buffer; + for (__argc = 0; __argc < ARGC_MAX; __argc++) { + const char *ptr; + if (!__argc) + ptr = strtok(_arg_string_buffer, " "); + else + ptr = strtok(0, " "); - /* 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](); + _argv_buffer[__argc] = ptr; + if (!ptr) + break; } } -void _parse_args( int argc, const char *args[] ) -{ - int i; - char *c,*s; - - memset( _arg_buff, 0, 132 ); - - if( !args ) - { - // Use arguments from kernel if args is NULL - strncpy( _arg_buff, (char*)0x180, 128 ); - - // Clean-up args froom stray line-ends - while( ( c = strrchr( _arg_buff, '\r' ) ) || - ( c = strrchr( _arg_buff, '\n' ) ) ) - *c = 0; - } - else - { - __argc = argc; - __argv = args; - return; - } - - __argc = 0; - for( i=0; i<8; i++ ) - _arg_ptrs_int[i] = 0; - - s = _arg_buff; - while( c = strtok( s, " " ) ) - { - _arg_ptrs_int[__argc] = c; - __argc++; - s = NULL; - if( __argc >= 8 ) - break; - } - - __argv = _arg_ptrs_int; - -} /* parse_args */ +/* Main */ + +// How much space at the end of RAM to leave for the stack (instead of using it +// as heap). By default 128 KB are reserved for the stack, but this constant +// can be overridden in main.c (or anywhere else) simply by redeclaring it +// without the weak attribute. +const int32_t __attribute__((weak)) STACK_MAX_SIZE = 0x20000; -void _start( int argc, const char *args[] ) -{ - // Load GP address - load_gp(); +// These are defined by the linker script. Note that these are *NOT* pointers, +// they are virtual symbols whose location matches their value. The simplest +// way to turn them into pointers is to declare them as arrays, so here we go. +extern uint8_t __text_start[]; +extern uint8_t __bss_start[]; +extern uint8_t _end[]; +//extern uint8_t _gp[]; + +extern void (*__CTOR_LIST__[])(void); +extern void (*__DTOR_LIST__[])(void); + +extern int32_t main(int32_t argc, const char* argv[]); + +// Even though _start() usually takes no arguments, this implementation allows +// parent executables to pass args directly to child executables without having +// to overwrite the arg strings in kernel RAM. +void _start(int32_t override_argc, const char **override_argv) { + __asm__ volatile("la $gp, _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(); - - // process command line arguments - _parse_args( argc, args ); - - _call_global_ctors(); - - *((int*)0x8000DFFC) = main( __argc, __argv ); - - _call_global_dtors(); - - // Set return value to kernel return value area - -} /* _start */
\ No newline at end of file + //_mem_init(); + + // Clear BSS 4 bytes at a time. BSS is always aligned to 4 bytes by the + // linker script. + for (uint32_t *i = (uint32_t *) __bss_start; i < (uint32_t *) _end; i++) + *i = 0; + + // Calculate how much RAM is available after the loaded executable and + // initialize heap accordingly. + void *exe_end = _end + 4; + unsigned int exe_size = (unsigned int) exe_end - (unsigned int) __text_start; + InitHeap(exe_end, 0x200000 - (exe_size + STACK_MAX_SIZE)); + + if (override_argv) { + __argc = override_argc; + __argv = override_argv; + } else { + _parse_kernel_args(); + } + + // Call the global constructors (if any) to initialize global objects + // before calling main(). Constructors are put by the linker script in a + // length-prefixed array in reverse order. + for (uint32_t i = (uint32_t) __CTOR_LIST__[0]; i >= 1; i--) + __CTOR_LIST__[i](); + + // Store main()'s return value into the kernel return value area (for child + // executables). + *KERNEL_RETURN_VALUE = main(__argc, __argv); + + // Call global destructors (in forward order). + for (uint32_t i = 0; i < (uint32_t) __DTOR_LIST__[0]; i++) + __DTOR_LIST__[i + 1](); +} diff --git a/libpsn00b/psxapi/sys/flushcache.s b/libpsn00b/psxapi/sys/flushcache.s new file mode 100644 index 0000000..7eeb510 --- /dev/null +++ b/libpsn00b/psxapi/sys/flushcache.s @@ -0,0 +1,10 @@ +.set noreorder + +.section .text + +.global FlushCache +.type FlushCache, @function +FlushCache: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x44 diff --git a/libpsn00b/psxspu/transfer.s b/libpsn00b/psxspu/transfer.s index 086bb3b..5b62c28 100644 --- a/libpsn00b/psxspu/transfer.s +++ b/libpsn00b/psxspu/transfer.s @@ -20,7 +20,8 @@ SpuSetTransferStartAddr: li $v0, 0x1000 # Check if value is valid blt $a0, $v0, .Lbad_value nop - li $v0, 0xffff + lui $v0, 8 # 0x7ffff = (8<<16)-1 + addiu $v0, -1 bgt $a0, $v0, .Lbad_value nop |
