psxbios: don't crash on negative length
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index cad69b3..292d80d 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "psxbios.h"
 #include "psxhw.h"
+#include "gpu.h"
+#include <zlib.h>
 
 #undef SysPrintf
 #define SysPrintf if (Config.PsxOut) printf
@@ -611,14 +613,14 @@ void psxBios_tolower() { // 0x26
 
 void psxBios_bcopy() { // 0x27
        char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
-       while (a2-- > 0) *p1++ = *p2++;
+       while ((s32)a2-- > 0) *p1++ = *p2++;
 
        pc0 = ra;
 }
 
 void psxBios_bzero() { // 0x28
        char *p = (char *)Ra0;
-       while (a1-- > 0) *p++ = '\0';
+       while ((s32)a1-- > 0) *p++ = '\0';
 
        pc0 = ra;
 }
@@ -628,7 +630,7 @@ void psxBios_bcmp() { // 0x29
 
        if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
 
-       while (a2-- > 0) {
+       while ((s32)a2-- > 0) {
                if (*p1++ != *p2++) {
                        v0 = *p1 - *p2; // BUG: compare the NEXT byte
                        pc0 = ra;
@@ -641,15 +643,16 @@ void psxBios_bcmp() { // 0x29
 
 void psxBios_memcpy() { // 0x2a
        char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-       while (a2-- > 0) *p1++ = *p2++;
+       while ((s32)a2-- > 0) *p1++ = *p2++;
 
        v0 = a0; pc0 = ra;
 }
 
 void psxBios_memset() { // 0x2b
        char *p = (char *)Ra0;
-       while (a2-- > 0) *p++ = (char)a1;
+       while ((s32)a2-- > 0) *p++ = (char)a1;
 
+       a2 = 0;
        v0 = a0; pc0 = ra;
 }
 
@@ -660,9 +663,9 @@ void psxBios_memmove() { // 0x2c
                a2++; // BUG: copy one more byte here
                p1 += a2;
                p2 += a2;
-               while (a2-- > 0) *--p1 = *--p2;
+               while ((s32)a2-- > 0) *--p1 = *--p2;
        } else {
-               while (a2-- > 0) *p1++ = *p2++;
+               while ((s32)a2-- > 0) *p1++ = *p2++;
        }
 
        v0 = a0; pc0 = ra;
@@ -675,7 +678,7 @@ void psxBios_memcmp() { // 0x2d
 void psxBios_memchr() { // 0x2e
        char *p = (char *)Ra0;
 
-       while (a2-- > 0) {
+       while ((s32)a2-- > 0) {
                if (*p++ != (s8)a1) continue;
                v0 = a0 + (p - (char *)Ra0 - 1);
                pc0 = ra;
@@ -804,8 +807,8 @@ void psxBios_qsort() { // 0x31
 }
 
 void psxBios_malloc() { // 0x33
-       unsigned int *chunk, *newchunk;
-       unsigned int dsize, csize, cstat;
+       unsigned int *chunk, *newchunk = NULL;
+       unsigned int dsize = 0, csize, cstat;
        int colflag;
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
@@ -875,7 +878,7 @@ void psxBios_malloc() { // 0x33
                // split free chunk
                *chunk = SWAP32(dsize);
                newchunk = (u32*)((uptr)chunk + dsize + 4);
-               *newchunk = SWAP32((csize - dsize - 4) & 0xfffffffc | 1);
+               *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
        }
 
        // return pointer to allocated memory
@@ -898,13 +901,16 @@ void psxBios_free() { // 0x34
 }
 
 void psxBios_calloc() { // 0x37
+       void *pv0;
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
 #endif
 
        a0 = a0 * a1;
        psxBios_malloc();
-       memset(Rv0, 0, a0);
+       pv0 = Rv0;
+       if (pv0)
+               memset(pv0, 0, a0);
 }
 
 void psxBios_realloc() { // 0x38
@@ -938,7 +944,7 @@ void psxBios_InitHeap() { // 0x39
        heap_end = (u32 *)((u8 *)heap_addr + size);
        *heap_addr = SWAP32(size | 1);
 
-       SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (uptr)heap_addr-(uptr)psxM, size);
+       SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
 
        pc0 = ra;
 }
@@ -953,12 +959,16 @@ void psxBios_printf() { // 0x3f
        u32 save[4];
        char *ptmp = tmp;
        int n=1, i=0, j;
-
-       memcpy(save, (char*)PSXM(sp), 4 * 4);
-       psxMu32ref(sp) = SWAP32((u32)a0);
-       psxMu32ref(sp + 4) = SWAP32((u32)a1);
-       psxMu32ref(sp + 8) = SWAP32((u32)a2);
-       psxMu32ref(sp + 12) = SWAP32((u32)a3);
+       void *psp;
+
+       psp = PSXM(sp);
+       if (psp) {
+               memcpy(save, psp, 4 * 4);
+               psxMu32ref(sp) = SWAP32((u32)a0);
+               psxMu32ref(sp + 4) = SWAP32((u32)a1);
+               psxMu32ref(sp + 8) = SWAP32((u32)a2);
+               psxMu32ref(sp + 12) = SWAP32((u32)a3);
+       }
 
        while (Ra0[i]) {
                switch (Ra0[i]) {
@@ -988,7 +998,7 @@ _start:
                                        case 'g': case 'G':
                                                ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
                                        case 'p':
-                                       case 'i':
+                                       case 'i': case 'u':
                                        case 'd': case 'D':
                                        case 'o': case 'O':
                                        case 'x': case 'X':
@@ -1008,10 +1018,31 @@ _start:
        }
        *ptmp = 0;
 
-       memcpy((char*)PSXM(sp), save, 4 * 4);
+       if (psp)
+               memcpy(psp, save, 4 * 4);
+
+       SysPrintf("%s", tmp);
 
-       SysPrintf(tmp);
+       pc0 = ra;
+}
 
+void psxBios_format() { // 0x41
+       if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
+       {
+               CreateMcd(Config.Mcd1);
+               LoadMcd(1, Config.Mcd1);
+               v0 = 1;
+       }
+       else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
+       {
+               CreateMcd(Config.Mcd2);
+               LoadMcd(2, Config.Mcd2);
+               v0 = 1;
+       }
+       else
+       {
+               v0 = 0;
+       }
        pc0 = ra;
 }
 
@@ -1021,13 +1052,15 @@ _start:
 
 void psxBios_Load() { // 0x42
        EXE_HEADER eheader;
+       void *pa1;
 
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
 #endif
 
-       if (LoadCdromFile(Ra0, &eheader) == 0) {
-               memcpy(Ra1, ((char*)&eheader)+16, sizeof(EXEC));
+       pa1 = Ra1;
+       if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
+               memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
                v0 = 1;
        } else v0 = 0;
 
@@ -1118,6 +1151,7 @@ void psxBios_mem2vram() { // 0x47
 
 void psxBios_SendGPU() { // 0x48
        GPU_writeStatus(a0);
+       gpuSyncPluginSR();
        pc0 = ra;
 }
 
@@ -1681,6 +1715,7 @@ void psxBios_UnDeliverEvent() { // 0x20
 void psxBios_open() { // 0x32
        int i;
        char *ptr;
+       void *pa0 = Ra0;
 
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
@@ -1688,12 +1723,14 @@ void psxBios_open() { // 0x32
 
        v0 = -1;
 
-       if (!strncmp(Ra0, "bu00", 4)) {
-               buopen(1);
-       }
+       if (pa0) {
+               if (!strncmp(pa0, "bu00", 4)) {
+                       buopen(1);
+               }
 
-       if (!strncmp(Ra0, "bu10", 4)) {
-               buopen(2);
+               if (!strncmp(pa0, "bu10", 4)) {
+                       buopen(2);
+               }
        }
 
        pc0 = ra;
@@ -1725,7 +1762,7 @@ void psxBios_lseek() { // 0x33
        pc0 = ra;
 }
 
-#define buread(mcd) { \
+#define buread(Ra1, mcd) { \
        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, a2); \
@@ -1742,6 +1779,7 @@ void psxBios_lseek() { // 0x33
 
 void psxBios_read() { // 0x34
        char *ptr;
+       void *pa1 = Ra1;
 
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
@@ -1749,15 +1787,17 @@ void psxBios_read() { // 0x34
 
        v0 = -1;
 
-       switch (a0) {
-               case 2: buread(1); break;
-               case 3: buread(2); break;
+       if (pa1) {
+               switch (a0) {
+                       case 2: buread(pa1, 1); break;
+                       case 3: buread(pa1, 2); break;
+               }
        }
                
        pc0 = ra;
 }
 
-#define buwrite(mcd) { \
+#define buwrite(Ra1, mcd) { \
        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; \
@@ -1776,24 +1816,31 @@ void psxBios_read() { // 0x34
 
 void psxBios_write() { // 0x35/0x03
        char *ptr;
+       void *pa1 = Ra1;
+
+#ifdef PSXBIOS_LOG
+       PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
+#endif
+
+       v0 = -1;
+       if (!pa1) {
+               pc0 = ra;
+               return;
+       }
 
        if (a0 == 1) { // stdout
-               char *ptr = Ra1;
+               char *ptr = pa1;
 
+               v0 = a2;
                while (a2 > 0) {
                        SysPrintf("%c", *ptr++); a2--;
                }
                pc0 = ra; return;
        }
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
-#endif
-
-       v0 = -1;
 
        switch (a0) {
-               case 2: buwrite(1); break;
-               case 3: buwrite(2); break;
+               case 2: buwrite(pa1, 1); break;
+               case 3: buwrite(pa1, 2); break;
        }
 
        pc0 = ra;
@@ -1818,7 +1865,7 @@ void psxBios_putchar() { // 3d
 }
 
 void psxBios_puts() { // 3e/3f
-       SysPrintf(Ra0);
+       SysPrintf("%s", Ra0);
        pc0 = ra;
 }
 
@@ -1834,7 +1881,8 @@ int nfile;
                if ((*ptr & 0xF0) != 0x50) continue; \
                ptr+= 0xa; \
                if (pfile[0] == 0) { \
-                       strcpy(dir->name, ptr); \
+                       strncpy(dir->name, ptr, sizeof(dir->name)); \
+                       dir->name[sizeof(dir->name) - 1] = '\0'; \
                } else for (i=0; i<20; i++) { \
                        if (pfile[i] == ptr[i]) { \
                                dir->name[i] = ptr[i]; \
@@ -1859,6 +1907,7 @@ int nfile;
  
 void psxBios_firstfile() { // 42
        struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
+       void *pa0 = Ra0;
        u32 _dir = a1;
        char *ptr;
        int i;
@@ -1869,13 +1918,15 @@ void psxBios_firstfile() { // 42
 
        v0 = 0;
 
-       strcpy(ffile, Ra0);
-       pfile = ffile+5;
-       nfile = 1;
-       if (!strncmp(Ra0, "bu00", 4)) {
-               bufile(1);
-       } else if (!strncmp(Ra0, "bu10", 4)) {
-               bufile(2);
+       if (pa0) {
+               strcpy(ffile, pa0);
+               pfile = ffile+5;
+               nfile = 1;
+               if (!strncmp(pa0, "bu00", 4)) {
+                       bufile(1);
+               } else if (!strncmp(pa0, "bu10", 4)) {
+                       bufile(2);
+               }
        }
 
        // firstfile() calls _card_read() internally, so deliver it's event
@@ -1933,6 +1984,8 @@ void psxBios_nextfile() { // 43
  */
 
 void psxBios_rename() { // 44
+       void *pa0 = Ra0;
+       void *pa1 = Ra1;
        char *ptr;
        int i;
 
@@ -1942,12 +1995,14 @@ void psxBios_rename() { // 44
 
        v0 = 0;
 
-       if (!strncmp(Ra0, "bu00", 4) && !strncmp(Ra1, "bu00", 4)) {
-               burename(1);
-       }
+       if (pa0 && pa1) {
+               if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
+                       burename(1);
+               }
 
-       if (!strncmp(Ra0, "bu10", 4) && !strncmp(Ra1, "bu10", 4)) {
-               burename(2);
+               if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
+                       burename(2);
+               }
        }
 
        pc0 = ra;
@@ -1972,6 +2027,7 @@ void psxBios_rename() { // 44
  */
 
 void psxBios_delete() { // 45
+       void *pa0 = Ra0;
        char *ptr;
        int i;
 
@@ -1981,12 +2037,14 @@ void psxBios_delete() { // 45
 
        v0 = 0;
 
-       if (!strncmp(Ra0, "bu00", 4)) {
-               budelete(1);
-       }
+       if (pa0) {
+               if (!strncmp(pa0, "bu00", 4)) {
+                       budelete(1);
+               }
 
-       if (!strncmp(Ra0, "bu10", 4)) {
-               budelete(2);
+               if (!strncmp(pa0, "bu10", 4)) {
+                       budelete(2);
+               }
        }
 
        pc0 = ra;
@@ -2023,6 +2081,7 @@ void psxBios_StopCARD() { // 4c
 }
 
 void psxBios__card_write() { // 0x4e
+       void *pa2 = Ra2;
        int port;
 
 #ifdef PSXBIOS_LOG
@@ -2032,12 +2091,14 @@ void psxBios__card_write() { // 0x4e
        card_active_chan = a0;
        port = a0 >> 4;
 
-       if (port == 0) {
-               memcpy(Mcd1Data + a1 * 128, Ra2, 128);
-               SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
-       } else {
-               memcpy(Mcd2Data + a1 * 128, Ra2, 128);
-               SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
+       if (pa2) {
+               if (port == 0) {
+                       memcpy(Mcd1Data + a1 * 128, pa2, 128);
+                       SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
+               } else {
+                       memcpy(Mcd2Data + a1 * 128, pa2, 128);
+                       SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
+               }
        }
 
        DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
@@ -2047,6 +2108,7 @@ void psxBios__card_write() { // 0x4e
 }
 
 void psxBios__card_read() { // 0x4f
+       void *pa2 = Ra2;
        int port;
 
 #ifdef PSXBIOS_LOG
@@ -2056,10 +2118,12 @@ void psxBios__card_read() { // 0x4f
        card_active_chan = a0;
        port = a0 >> 4;
 
-       if (port == 0) {
-               memcpy(Ra2, Mcd1Data + a1 * 128, 128);
-       } else {
-               memcpy(Ra2, Mcd2Data + a1 * 128, 128);
+       if (pa2) {
+               if (port == 0) {
+                       memcpy(pa2, Mcd1Data + a1 * 128, 128);
+               } else {
+                       memcpy(pa2, Mcd2Data + a1 * 128, 128);
+               }
        }
 
        DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
@@ -2478,7 +2542,7 @@ void psxBiosInit() {
        biosB0[0x3c] = psxBios_getchar;
        //biosB0[0x3e] = psxBios_gets;
        //biosB0[0x40] = psxBios_cd;
-       //biosB0[0x41] = psxBios_format;
+       biosB0[0x41] = psxBios_format;
        biosB0[0x42] = psxBios_firstfile;
        biosB0[0x43] = psxBios_nextfile;
        biosB0[0x44] = psxBios_rename;