X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxbios.c;h=df0550e8d71de0d770fe01a2d3aec3c41960b365;hb=002b2f7d98f8c543cd88cb453c88b09eb5e556ad;hp=90c11aeb33e1cfe2cc84f51f2272fbdf4cd77feb;hpb=f42e1e9003d052bcfcadd5955d2396f11ea0f3c5;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 90c11aeb..df0550e8 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -254,6 +254,7 @@ static EvCB *RcEV; // 0xf2 static EvCB *UeEV; // 0xf3 static EvCB *SwEV; // 0xf4 static EvCB *ThEV; // 0xff +static u32 heap_size = 0; static u32 *heap_addr = NULL; static u32 *heap_end = NULL; static u32 SysIntRP[8]; @@ -316,12 +317,38 @@ static inline void LoadRegs() { // * // System calls A0 */ + +#define buread(Ra1, mcd, length) { \ + SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \ + ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ + memcpy(Ra1, ptr, length); \ + DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ + DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ + if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + else v0 = length; \ + FDesc[1 + mcd].offset += v0; \ +} + +#define buwrite(Ra1, mcd, length) { \ + u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ + SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \ + ptr = Mcd##mcd##Data + offset; \ + memcpy(ptr, Ra1, length); \ + DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ + DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ + FDesc[1 + mcd].offset += length; \ + if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + else v0 = length; \ +} + + /* Internally redirects to "FileRead(fd,tempbuf,1)".*/ /* For some strange reason, the returned character is sign-expanded; */ /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */ /* TODO FIX ME : Properly implement this behaviour */ void psxBios_getc(void) // 0x03, 0x35 { + char *ptr; void *pa1 = Ra1; #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]); @@ -341,6 +368,7 @@ void psxBios_getc(void) // 0x03, 0x35 /* Copy of psxBios_write, except size is 1. */ void psxBios_putc(void) // 0x09, 0x3B { + char *ptr; void *pa1 = Ra1; #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]); @@ -583,7 +611,13 @@ void psxBios_strlen() { // 0x1b void psxBios_index() { // 0x1c char *p = (char *)Ra0; - + if (a0 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + do { if (*p == a1) { v0 = a0 + (p - (char *)Ra0); @@ -599,7 +633,11 @@ void psxBios_rindex() { // 0x1d char *p = (char *)Ra0; v0 = 0; - + if (a0 == 0) + { + pc0 = ra; + return; + } do { if (*p == a1) v0 = a0 + (p - (char *)Ra0); @@ -702,15 +740,34 @@ void psxBios_tolower() { // 0x26 void psxBios_bcopy() { // 0x27 char *p1 = (char *)Ra1, *p2 = (char *)Ra0; + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } while ((s32)a2-- > 0) *p1++ = *p2++; - + a2 = 0; pc0 = ra; } void psxBios_bzero() { // 0x28 char *p = (char *)Ra0; + v0 = a0; + /* Same as memset here (See memset below) */ + if (a1 > 0x7FFFFFFF || a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + else if (a0 == 0) + { + pc0 = ra; + return; + } while ((s32)a1-- > 0) *p++ = '\0'; - + a1 = 0; pc0 = ra; } @@ -732,22 +789,48 @@ void psxBios_bcmp() { // 0x29 void psxBios_memcpy() { // 0x2a char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - while ((s32)a2-- > 0) *p1++ = *p2++; - - v0 = a0; pc0 = ra; + s32 n=0; + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } + while ((s32)a2-- > 0) { + n++; + *p1++ = *p2++; + } + a2 = 0; + pc0 = ra; } void psxBios_memset() { // 0x2b char *p = (char *)Ra0; + v0 = a0; + if (a2 > 0x7FFFFFFF || a2 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + if (a0 == 0) + { + pc0 = ra; + return; + } while ((s32)a2-- > 0) *p++ = (char)a1; - a2 = 0; v0 = a0; pc0 = ra; } void psxBios_memmove() { // 0x2c char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } if (p2 <= p1 && p2 + a2 > p1) { a2++; // BUG: copy one more byte here p1 += a2; @@ -756,8 +839,7 @@ void psxBios_memmove() { // 0x2c } else { while ((s32)a2-- > 0) *p1++ = *p2++; } - - v0 = a0; pc0 = ra; + pc0 = ra; } void psxBios_memcmp() { // 0x2d @@ -902,6 +984,11 @@ void psxBios_malloc() { // 0x33 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]); #endif + if (!a0 || (!heap_size || !heap_addr)) { + v0 = 0; + pc0 = ra; + return; + } // scan through heap and combine free chunks of space chunk = heap_addr; @@ -911,6 +998,15 @@ void psxBios_malloc() { // 0x33 csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; + // most probably broken heap descriptor + // this fixes Burning Road + if (*chunk == 0) { + newchunk = chunk; + dsize = ((uptr)heap_end - (uptr)chunk) - 4; + colflag = 1; + break; + } + // it's a free chunk if(cstat == 1) { if(colflag == 0) { @@ -942,28 +1038,36 @@ void psxBios_malloc() { // 0x33 // exit on uninitialized heap if (chunk == NULL) { - SysPrintf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); + printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); v0 = 0; pc0 = ra; return; } // search an unused chunk that is big enough until the end of the heap - while ((dsize > csize || cstat == 0) && chunk < heap_end ) { + while ((dsize > csize || cstat==0) && chunk < heap_end ) { chunk = (u32*)((uptr)chunk + csize + 4); + + // catch out of memory + if(chunk >= heap_end) { + printf("malloc %x,%x: Out of memory error!\n", + v0, a0); + v0 = 0; pc0 = ra; + return; + } + csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; } - // catch out of memory - if(chunk >= heap_end) { SysPrintf("malloc %x,%x: Out of memory error!\n", v0, a0); v0 = 0; pc0 = ra; return; } - // allocate memory if(dsize == csize) { // chunk has same size *chunk &= 0xfffffffc; - } - else { + } else if (dsize > csize) { + v0 = 0; pc0 = ra; + return; + } else { // split free chunk *chunk = SWAP32(dsize); newchunk = (u32*)((uptr)chunk + dsize + 4); @@ -971,9 +1075,9 @@ void psxBios_malloc() { // 0x33 } // return pointer to allocated memory - v0 = ((unsigned long)chunk - (unsigned long)psxM) + 4; + v0 = ((uptr)chunk - (uptr)psxM) + 4; v0|= 0x80000000; - SysPrintf ("malloc %x,%x\n", v0, a0); + //printf ("malloc %x,%x\n", v0, a0); pc0 = ra; } @@ -1010,9 +1114,24 @@ void psxBios_realloc() { // 0x38 #endif a0 = block; - psxBios_free(); - a0 = size; - psxBios_malloc(); + /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */ + if (block == 0) + { + psxBios_malloc(); + } + /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */ + else if (size == 0) + { + psxBios_free(); + } + /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */ + /* Note that it is not quite implemented this way here. */ + else + { + psxBios_free(); + a0 = size; + psxBios_malloc(); + } } @@ -1547,14 +1666,27 @@ void psxBios_WaitEvent() { // 0a ev = a0 & 0xff; spec = (a0 >> 8) & 0xff; - #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec); #endif + if (Event[ev][spec].status == EvStUNUSED) + { + v0 = 0; + pc0 = ra; + return; + } - Event[ev][spec].status = EvStACTIVE; + if (Event[ev][spec].status == EvStALREADY) + { + /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */ + if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE; + v0 = 1; + pc0 = ra; + return; + } - v0 = 1; pc0 = ra; + v0 = 0; + pc0 = ra; } void psxBios_TestEvent() { // 0b @@ -1612,8 +1744,20 @@ void psxBios_OpenTh() { // 0e int th; for (th=1; th<8; th++) + { if (Thread[th].status == 0) break; + } + if (th == 8) { + // Feb 2019 - Added out-of-bounds fix caught by cppcheck: + // When no free TCB is found, return 0xffffffff according to Nocash doc. +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__); +#endif + v0 = 0xffffffff; + pc0 = ra; + return; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th); #endif @@ -1705,9 +1849,10 @@ void psxBios_StopPAD() { // 14 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); #endif - + if (pad_buf == 0){ pad_buf1 = NULL; pad_buf2 = NULL; + } pc0 = ra; } @@ -1903,18 +2048,6 @@ void psxBios_lseek() { // 0x33 pc0 = ra; } -#define buread(Ra1, mcd, length) { \ - SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \ - ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ - memcpy(Ra1, ptr, length); \ - DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ - DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ - if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ - else v0 = length; \ - FDesc[1 + mcd].offset += v0; \ -} - - /* * int read(int fd , void *buf , int nbytes); @@ -1940,18 +2073,6 @@ void psxBios_read() { // 0x34 pc0 = ra; } -#define buwrite(Ra1, mcd, length) { \ - u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ - SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \ - ptr = Mcd##mcd##Data + offset; \ - memcpy(ptr, Ra1, length); \ - DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ - DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ - FDesc[1 + mcd].offset += length; \ - if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ - else v0 = length; \ -} - /* * int write(int fd , void *buf , int nbytes); */ @@ -2066,15 +2187,16 @@ void psxBios_firstfile() { // 42 pfile = ffile+5; nfile = 1; if (!strncmp(pa0, "bu00", 4)) { + // firstfile() calls _card_read() internally, so deliver it's event + DeliverEvent(0x11, 0x2); bufile(1); } else if (!strncmp(pa0, "bu10", 4)) { + // firstfile() calls _card_read() internally, so deliver it's event + DeliverEvent(0x11, 0x2); bufile(2); } } - // firstfile() calls _card_read() internally, so deliver it's event - DeliverEvent(0x11, 0x2); - pc0 = ra; } @@ -2295,6 +2417,13 @@ void psxBios__new_card() { // 0x50 pc0 = ra; } +/* According to a user, this allows Final Fantasy Tactics to save/load properly */ +void psxBios__get_error(void) // 55 +{ + v0 = 0; + pc0 = ra; +} + void psxBios_Krom2RawAdd() { // 0x51 int i = 0; @@ -2717,7 +2846,7 @@ void psxBiosInit() { //biosB0[0x52] = psxBios_sys_b0_52; //biosB0[0x53] = psxBios_sys_b0_53; //biosB0[0x54] = psxBios__get_errno; - //biosB0[0x55] = psxBios__get_error; + biosB0[0x55] = psxBios__get_error; biosB0[0x56] = psxBios_GetC0Table; biosB0[0x57] = psxBios_GetB0Table; biosB0[0x58] = psxBios__card_chan; @@ -2786,6 +2915,7 @@ void psxBiosInit() { pad_buf1len = pad_buf2len = 0; heap_addr = NULL; heap_end = NULL; + heap_size = 0; CardState = -1; CurThread = 0; memset(FDesc, 0, sizeof(FDesc));