psxbios: Improve WaitEvent behaviour according to documentation
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index b13874e..139c8a5 100644 (file)
@@ -369,6 +369,33 @@ void psxBios_putc(void) // 0x09, 0x3B
        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;
        else v0 = a0;
@@ -466,7 +493,12 @@ void psxBios_strncat() { // 0x16
 #ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
 #endif
-
+       if (a0 == 0 || a1 == 0)
+       {
+               v0 = 0;
+               pc0 = ra;
+               return;
+       }
        while (*p1++);
        --p1;
        while ((*p1++ = *p2++) != '\0') {
@@ -978,9 +1010,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();
+       }
 }
 
 
@@ -1515,14 +1562,28 @@ 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;
+       ResetIoCycle();
 }
 
 void psxBios_TestEvent() { // 0b
@@ -2432,7 +2493,7 @@ void psxBiosInit() {
        //biosA0[0x07] = psxBios_sys_a0_07;
        biosA0[0x08] = psxBios_getc;
        biosA0[0x09] = psxBios_putc;
-       //biosA0[0x0a] = psxBios_todigit;
+       biosA0[0x0a] = psxBios_todigit;
        //biosA0[0x0b] = psxBios_atof;
        //biosA0[0x0c] = psxBios_strtoul;
        //biosA0[0x0d] = psxBios_strtol;