psxbios: Add checks for bzero.
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index 90c11ae..c362a75 100644 (file)
@@ -316,12 +316,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 +367,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 +610,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 +632,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 +739,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;
 }
 
@@ -1010,9 +1066,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 +1618,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 +1696,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 +1801,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 +2000,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 +2025,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 +2139,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;
 }