diff --git a/Common/printk.c b/Common/printk.c new file mode 100644 index 0000000..10fbfde --- /dev/null +++ b/Common/printk.c @@ -0,0 +1,385 @@ +/* + * + * printk.c + * + * printk for bootbox + * + * support format: + * %c + * %s + * %[[0]n]x + * %[[0]n]X + * %[[0]n]d + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct pthread_mlock_t { + volatile unsigned long l; + unsigned int c; + int thread_id; +}; + +typedef struct pthread_mlock_t MLOCK_T; + +static MLOCK_T lock; + +extern void printk_lock(void); +extern void printk_unlock(void); + +static int itostr(char *buf, int in_data, int base, int upper, int sign) +{ + int res, len, i; + unsigned int data; + char *str; + + if(base==10 && sign && in_data<0){ + data = -in_data; + }else{ + data = in_data; + } + + str = buf; + do{ + res = data%base; + data = data/base; + if(res<10){ + res += '0'; + }else{ + if(upper){ + res += 'A'-10; + }else{ + res += 'a'-10; + } + } + *str++ = res; + }while(data); + len = str-buf; + + /* reverse digital order */ + for(i=0; i'0' && *fmt<='9'){ + field_width = field_width*10+(*fmt-'0'); + fmt++; + } + if(*fmt && *fmt=='.'){ + fmt++; + /* skip n */ + while(*fmt && *fmt>'0' && *fmt<='9'){ + fmt++; + } + } + + /* get format char */ + upper = 0; + base = 0; + sign = 0; + len = 0; + s = digital_buf; + while((ch=*fmt)){ + fmt++; + switch(ch){ + /* hexadecimal */ + case 'p': + case 'X': + upper = 1; + case 'x': + base = 16; + break; + + /* decimal */ + case 'd': + case 'i': + sign = 1; + case 'u': + base = 10; + break; + + /* octal */ + case 'o': + base = 8; + break; + + /* character */ + case 'c': + digital_buf[0] = (unsigned char) va_arg(args, int); + len = 1; + break; + + /* string */ + case 's': + s = va_arg(args, char *); + if(!s) s = ""; + len = strlen(s); + break; + + /* float format, skip it */ + case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': + va_arg(args, double); + s = NULL; + break; + + /* length modifier */ + case 'l': case 'L': case 'h': case 'j': case 'z': case 't': + /* skip it */ + continue; + + /* bad format */ + default: + s = sstr; + len = fmt-sstr; + break; + } + break; + } + + if(base){ + i = va_arg(args, int); + if(base==10 && sign){ + if(i<0){ + add_sign = '-'; + } + }else{ + add_sign = 0; + } + + len = itostr(digital_buf, i, base, upper, sign); + }else{ + zero_pad = ' '; + add_sign = 0; + } + + if(s){ + if(len>=field_width){ + field_width = len; + if(add_sign) + field_width++; + } + for(i=0; i= 0) { + if (printk_memory_log_ptr != printk_memory_log) { + // flush debug output + sceIoWrite(fd, printk_memory_log, printk_memory_log_ptr - printk_memory_log); + memset(printk_memory_log, 0, sizeof(printk_memory_log)); + printk_memory_log_ptr = printk_memory_log; + } + + sceIoWrite(fd, printk_buf, printed_len); + sceIoClose(fd); + } else { + // log to memory buf + + if (printk_memory_log_ptr + printed_len < printk_memory_log + sizeof(printk_memory_log)) { + memcpy(printk_memory_log_ptr, printk_buf, printed_len); + printk_memory_log_ptr += printed_len; + } + } + } + + sceKernelDelayThread(10000); + printk_unlock(); + + return printed_len; +} + +static unsigned long my_InterlockedExchange(unsigned long volatile *dst, unsigned long exchange) +{ + unsigned int flags = pspSdkDisableInterrupts(); + unsigned long origvalue = *dst; + + *dst = exchange; + pspSdkEnableInterrupts(flags); + + return origvalue; +} + +static inline int psp_mutex_lock(MLOCK_T *s) +{ + for (;;) { + if (s->l != 0) { + if (s->thread_id == sceKernelGetThreadId()) { + ++s->c; + return 0; + } + } else { + if (!my_InterlockedExchange(&s->l, 1)) { + s->thread_id = sceKernelGetThreadId(); + s->c = 1; + return 0; + } + } + + sceKernelDelayThread(1000); + } + + return 0; +} + +static inline void psp_mutex_unlock(MLOCK_T *s) +{ + if (--s->c == 0) { + s->thread_id = 0; + my_InterlockedExchange(&s->l, 0); + } +} + +void printk_lock(void) +{ + psp_mutex_lock(&lock); +} + +void printk_unlock(void) +{ + psp_mutex_unlock(&lock); +} + +int printk_init(void) +{ + MLOCK_T *s = &lock; + + s->l = 0; + s->c = 0; + s->thread_id = sceKernelGetThreadId(); + + return 0; +} diff --git a/Common/printk.h b/Common/printk.h new file mode 100644 index 0000000..b3944cb --- /dev/null +++ b/Common/printk.h @@ -0,0 +1,17 @@ +#ifndef PRINTK_H +#define PRINTK_H + +#ifdef DEBUG +int printk_init(void); +int printk(char *fmt, ...)__attribute__((format (printf, 1, 2))); +int printk_lock(void); +int printk_unlock(void); +#else +#define printk_init() +#define printk(...) +#define printk_lock() +#define printk_unlock() +#endif + +#endif +