psxbios: Add todigit implementation
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index fdc129e..924996a 100644 (file)
@@ -316,6 +316,85 @@ static inline void LoadRegs() {
 //                                           *
 //               System calls A0             */
 
+/* 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
+{
+       void *pa1 = Ra1;
+#ifdef PSXBIOS_LOG
+       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
+#endif
+       v0 = -1;
+
+       if (pa1) {
+               switch (a0) {
+                       case 2: buread(pa1, 1, 1); break;
+                       case 3: buread(pa1, 2, 1); break;
+               }
+       }
+
+       pc0 = ra;
+}
+
+/* Copy of psxBios_write, except size is 1. */
+void psxBios_putc(void) // 0x09, 0x3B
+{
+       void *pa1 = Ra1;
+#ifdef PSXBIOS_LOG
+       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
+#endif
+       v0 = -1;
+       if (!pa1) {
+               pc0 = ra;
+               return;
+       }
+
+       if (a0 == 1) { // stdout
+               char *ptr = (char *)pa1;
+
+               v0 = a2;
+               while (a2 > 0) {
+                       printf("%c", *ptr++); a2--;
+               }
+               pc0 = ra; return;
+       }
+
+       switch (a0) {
+               case 2: buwrite(pa1, 1, 1); break;
+               case 3: buwrite(pa1, 2, 1); break;
+       }
+
+       pc0 = ra;
+}
+
+void psxBios_todigit(void) // 0x0a
+{
+       int c = a0;
+#ifdef PSXBIOS_LOG
+       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
+#endif
+       c &= 0xFF;
+       if (c >= 0x30 && c < 0x3A) {
+               c -= 0x30;
+       }
+       else if (c > 0x60 && c < 0x7B) {
+               c -= 0x20;
+       }
+       else if (c > 0x40 && c < 0x5B) {
+               c = c - 0x41 + 10;
+       }
+       else if (c >= 0x80) {
+               c = -1;
+       }
+       else
+       {
+               c = 0x0098967F;
+       }
+       v0 = c;
+       pc0 = ra;
+}
 
 void psxBios_abs() { // 0x0e
        if ((s32)a0 < 0) v0 = -(s32)a0;
@@ -394,7 +473,12 @@ void psxBios_strcat() { // 0x15
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
 #endif
-
+       if (a0 == 0 || a1 == 0)
+       {
+               v0 = 0;
+               pc0 = ra;
+               return;
+       }
        while (*p1++);
        --p1;
        while ((*p1++ = *p2++) != '\0');
@@ -613,14 +697,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;
 }
@@ -630,7 +714,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;
@@ -643,15 +727,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;
 }
 
@@ -662,9 +747,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;
@@ -677,7 +762,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;
@@ -900,13 +985,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
@@ -955,12 +1043,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]) {
@@ -990,7 +1082,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':
@@ -1010,26 +1102,49 @@ _start:
        }
        *ptmp = 0;
 
-       memcpy((char*)PSXM(sp), save, 4 * 4);
+       if (psp)
+               memcpy(psp, save, 4 * 4);
 
        SysPrintf("%s", 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;
+}
+
 /*
  *     long Load(char *name, struct EXEC *header);
  */
 
 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;
 
@@ -1155,7 +1270,7 @@ void psxBios_sys_a0_4c() { // 0x4c GPU relate
        GPU_writeData(0x0400000);
        GPU_writeData(0x0200000);
        GPU_writeData(0x0100000);
-
+       v0 = 0x1f801814;
        pc0 = ra;
 }
 
@@ -1243,11 +1358,29 @@ void psxBios__card_info() { // ab
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
 #endif
-
+       u32 ret;
        card_active_chan = a0;
 
+       switch (card_active_chan) 
+       {
+       case 0x00: case 0x01: case 0x02: case 0x03:
+               ret = Config.Mcd1[0] ? 0x2 : 0x8;
+               break;
+       case 0x10: case 0x11: case 0x12: case 0x13:
+               ret = Config.Mcd2[0] ? 0x2 : 0x8;
+               break;
+       default:
+#ifdef PSXBIOS_LOG
+               PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
+#endif
+               ret = 0x11;
+               break;
+       }
+       
+//     DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
 //     DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
        DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
+       DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
 
        v0 = 1; pc0 = ra;
 }
@@ -1577,10 +1710,17 @@ void psxBios_PAD_init() { // 15
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
 #endif
+       if (!(a0 == 0x20000000 || a0 == 0x20000001))
+       {
+               v0 = 0;
+               pc0 = ra;
+               return;
+       }
        psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
        pad_buf = (int *)Ra1;
        *pad_buf = -1;
        psxRegs.CP0.n.Status |= 0x401;
+       v0 = 2;
        pc0 = ra;
 }
 
@@ -1638,43 +1778,70 @@ void psxBios_UnDeliverEvent() { // 0x20
        pc0 = ra;
 }
 
-#define buopen(mcd) { \
-       strcpy(FDesc[1 + mcd].name, Ra0+5); \
-       FDesc[1 + mcd].offset = 0; \
-       FDesc[1 + mcd].mode   = a1; \
- \
-       for (i=1; i<16; i++) { \
-               ptr = Mcd##mcd##Data + 128 * i; \
-               if ((*ptr & 0xF0) != 0x50) continue; \
-               if (strcmp(FDesc[1 + mcd].name, ptr+0xa)) continue; \
-               FDesc[1 + mcd].mcfile = i; \
-               SysPrintf("open %s\n", ptr+0xa); \
-               v0 = 1 + mcd; \
-               break; \
-       } \
-       if (a1 & 0x200 && v0 == -1) { /* FCREAT */ \
-               for (i=1; i<16; i++) { \
-                       int j, xor = 0; \
- \
-                       ptr = Mcd##mcd##Data + 128 * i; \
-                       if ((*ptr & 0xF0) == 0x50) continue; \
-                       ptr[0] = 0x50 | (u8)(a1 >> 16); \
-                       ptr[4] = 0x00; \
-                       ptr[5] = 0x20; \
-                       ptr[6] = 0x00; \
-                       ptr[7] = 0x00; \
-                       ptr[8] = 'B'; \
-                       ptr[9] = 'I'; \
-                       strcpy(ptr+0xa, FDesc[1 + mcd].name); \
-                       for (j=0; j<127; j++) xor^= ptr[j]; \
-                       ptr[127] = xor; \
-                       FDesc[1 + mcd].mcfile = i; \
-                       SysPrintf("openC %s\n", ptr); \
-                       v0 = 1 + mcd; \
-                       SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 128); \
-                       break; \
-               } \
-       } \
+char ffile[64], *pfile;
+int nfile;
+static void buopen(int mcd, u8 *ptr, u8 *cfg)
+{
+       int i;
+       u8 *fptr = ptr;
+
+       strcpy(FDesc[1 + mcd].name, Ra0+5);
+       FDesc[1 + mcd].offset = 0;
+       FDesc[1 + mcd].mode   = a1;
+
+       for (i=1; i<16; i++) {
+               fptr += 128;
+               if ((*fptr & 0xF0) != 0x50) continue;
+               if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
+               FDesc[1 + mcd].mcfile = i;
+               SysPrintf("open %s\n", fptr+0xa);
+               v0 = 1 + mcd;
+               break;
+       }
+       if (a1 & 0x200 && v0 == -1) { /* FCREAT */
+               fptr = ptr;
+               for (i=1; i<16; i++) {
+                       int j, xor, nblk = a1 >> 16;
+                       u8 *pptr, *fptr2;
+
+                       fptr += 128;
+                       if ((*fptr & 0xF0) != 0xa0) continue;
+
+                       FDesc[1 + mcd].mcfile = i;
+                       fptr[0] = 0x51;
+                       fptr[4] = 0x00;
+                       fptr[5] = 0x20 * nblk;
+                       fptr[6] = 0x00;
+                       fptr[7] = 0x00;
+                       strcpy(fptr+0xa, FDesc[1 + mcd].name);
+                       pptr = fptr2 = fptr;
+                       for(j=2; j<=nblk; j++) {
+                               int k;
+                               for(i++; i<16; i++) {
+                                       fptr2 += 128;
+                                       
+                                       memset(fptr2, 0, 128);
+                                       fptr2[0] = j < nblk ? 0x52 : 0x53;
+                                       pptr[8] = i - 1;
+                                       pptr[9] = 0;
+                                       for (k=0, xor=0; k<127; k++) xor^= pptr[k];
+                                       pptr[127] = xor;
+                                       pptr = fptr2;
+                                       break;
+                               }
+                               /* shouldn't this return ENOSPC if i == 16? */
+                       }
+                       pptr[8] = pptr[9] = 0xff;
+                       for (j=0, xor=0; j<127; j++) xor^= pptr[j];
+                       pptr[127] = xor;
+                       SysPrintf("openC %s %d\n", ptr, nblk);
+                       v0 = 1 + mcd;
+                       /* just go ahead and resave them all */
+                       SaveMcd(cfg, ptr, 128, 128 * 15);
+                       break;
+               }
+               /* shouldn't this return ENOSPC if i == 16? */
+       }
 }
 
 /*
@@ -1684,6 +1851,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);
@@ -1691,12 +1859,14 @@ void psxBios_open() { // 0x32
 
        v0 = -1;
 
-       if (!strncmp(Ra0, "bu00", 4)) {
-               buopen(1);
-       }
+       if (pa0) {
+               if (!strncmp(pa0, "bu00", 4)) {
+                       buopen(1, Mcd1Data, Config.Mcd1);
+               }
 
-       if (!strncmp(Ra0, "bu10", 4)) {
-               buopen(2);
+               if (!strncmp(pa0, "bu10", 4)) {
+                       buopen(2, Mcd2Data, Config.Mcd2);
+               }
        }
 
        pc0 = ra;
@@ -1728,23 +1898,26 @@ void psxBios_lseek() { // 0x33
        pc0 = ra;
 }
 
-#define buread(mcd) { \
+#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, a2); \
-       if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \
-       else v0 = a2; \
-       FDesc[1 + mcd].offset += v0; \
+       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);
  */
 
 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);
@@ -1752,25 +1925,26 @@ 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, a2); break;
+                       case 3: buread(pa1, 2, a2); break;
+               }
        }
                
        pc0 = ra;
 }
 
-#define buwrite(mcd) { \
+#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, a2); \
-       FDesc[1 + mcd].offset += a2; \
-       SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, a2); \
-       if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \
-       else v0 = a2; \
+       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; \
 }
 
 /*
@@ -1779,24 +1953,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, a2); break;
+               case 3: buwrite(pa1, 2, a2); break;
        }
 
        pc0 = ra;
@@ -1832,16 +2013,18 @@ int nfile;
        while (nfile < 16) { \
                int match=1; \
  \
-               ptr = Mcd##mcd##Data + 128 * nfile; \
+               ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
                nfile++; \
                if ((*ptr & 0xF0) != 0x50) continue; \
+               /* Bug link files show up as free block. */ \
+               if (!ptr[0xa]) 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]; \
-                               if (ptr[i] == 0) break; else continue; } \
+                                                               dir->name[i] = ptr[i]; continue; } \
                        if (pfile[i] == '?') { \
                                dir->name[i] = ptr[i]; continue; } \
                        if (pfile[i] == '*') { \
@@ -1849,7 +2032,7 @@ int nfile;
                        match = 0; break; \
                } \
                SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
-               if (match == 0) continue; \
+               if (match == 0) { continue; } \
                dir->size = 8192; \
                v0 = _dir; \
                break; \
@@ -1862,6 +2045,7 @@ int nfile;
  
 void psxBios_firstfile() { // 42
        struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
+       void *pa0 = Ra0;
        u32 _dir = a1;
        char *ptr;
        int i;
@@ -1872,13 +2056,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
@@ -1936,6 +2122,8 @@ void psxBios_nextfile() { // 43
  */
 
 void psxBios_rename() { // 44
+       void *pa0 = Ra0;
+       void *pa1 = Ra1;
        char *ptr;
        int i;
 
@@ -1945,12 +2133,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;
@@ -1975,6 +2165,7 @@ void psxBios_rename() { // 44
  */
 
 void psxBios_delete() { // 45
+       void *pa0 = Ra0;
        char *ptr;
        int i;
 
@@ -1984,12 +2175,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;
@@ -2026,21 +2219,30 @@ void psxBios_StopCARD() { // 4c
 }
 
 void psxBios__card_write() { // 0x4e
+       void *pa2 = Ra2;
        int port;
 
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
 #endif
-
+       /* Function also accepts sector 400h (a bug) */
+       if (!(a1 <= 0x400))
+       {
+               /* Invalid sectors */
+               v0 = 0; pc0 = ra;
+               return;
+       }
        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
@@ -2050,19 +2252,28 @@ void psxBios__card_write() { // 0x4e
 }
 
 void psxBios__card_read() { // 0x4f
+       void *pa2 = Ra2;
        int port;
 
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
 #endif
-
+       /* Function also accepts sector 400h (a bug) */
+       if (!(a1 <= 0x400))
+       {
+               /* Invalid sectors */
+               v0 = 0; pc0 = ra;
+               return;
+       }
        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
@@ -2246,9 +2457,9 @@ void psxBiosInit() {
        //biosA0[0x05] = psxBios_ioctl;
        //biosA0[0x06] = psxBios_exit;
        //biosA0[0x07] = psxBios_sys_a0_07;
-       //biosA0[0x08] = psxBios_getc;
-       //biosA0[0x09] = psxBios_putc;
-       //biosA0[0x0a] = psxBios_todigit;
+       biosA0[0x08] = psxBios_getc;
+       biosA0[0x09] = psxBios_putc;
+       biosA0[0x0a] = psxBios_todigit;
        //biosA0[0x0b] = psxBios_atof;
        //biosA0[0x0c] = psxBios_strtoul;
        //biosA0[0x0d] = psxBios_strtol;
@@ -2481,7 +2692,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;
@@ -2775,8 +2986,9 @@ void psxBiosException() {
 #endif
                        switch (a0) {
                                case 1: // EnterCritical - disable irq's
-                                       psxRegs.CP0.n.Status &= ~0x404; 
-v0=1;  // HDHOSHY experimental patch: Spongebob, Coldblood, fearEffect, Medievil2, Martian Gothic
+                                       /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
+                                       v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
+                                       psxRegs.CP0.n.Status &= ~0x404;
                                        break;
 
                                case 2: // ExitCritical - enable irq's