psxbios: handle direct bios table calls
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index 432b0e2..56239f2 100644 (file)
@@ -36,7 +36,7 @@
 #include "sio.h"
 #include "psxhle.h"
 #include "psxinterpreter.h"
-#include "new_dynarec/events.h"
+#include "psxevents.h"
 #include <zlib.h>
 
 #ifndef PSXBIOS_LOG
@@ -303,10 +303,10 @@ static u32 floodchk;
 #define A_CD_EVENTS     0xb9b8
 #define A_EXC_GP        0xf450
 
-#define A_A0_DUMMY      0x1010
-#define A_B0_DUMMY      0x2010
-#define A_C0_DUMMY      0x3010
-#define A_B0_5B_DUMMY   0x43d0
+#define A_A0_TRAPS      0x1010
+#define A_B0_TRAPS      0x2010
+#define A_C0_TRAPS      0x3010
+#define A_B0_5B_TRAP    0x43d0
 
 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
 
@@ -1479,13 +1479,15 @@ void psxBios_printf() { // 0x3f
 }
 
 static void psxBios_cd() { // 0x40
-       const char *p, *dir = castRam8ptr(a0);
+       const char *p, *dir = Ra0;
        PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
-       if ((p = strchr(dir, ':')))
-               dir = ++p;
-       if (*dir == '\\')
-               dir++;
-       snprintf(cdir, sizeof(cdir), "%s", dir);
+       if (dir != INVALID_PTR) {
+               if ((p = strchr(dir, ':')))
+                       dir = ++p;
+               if (*dir == '\\')
+                       dir++;
+               snprintf(cdir, sizeof(cdir), "%s", dir);
+       }
        mips_return_c(1, 100);
 }
 
@@ -2566,7 +2568,7 @@ void psxBios_puts() { // 3e/3f
 }
 
 static void bufile(const u8 *mcd_data, u32 dir_) {
-       struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
+       struct DIRENTRY *dir = (struct DIRENTRY *)PSXM(dir_);
        const char *pfile = ffile + 5;
        const u8 *data = mcd_data;
        int i = 0, match = 0;
@@ -2574,6 +2576,9 @@ static void bufile(const u8 *mcd_data, u32 dir_) {
        u32 head = 0;
 
        v0 = 0;
+       if (dir == INVALID_PTR)
+               return;
+
        for (; nfile <= 15 && !match; nfile++) {
                const char *name;
 
@@ -2627,11 +2632,12 @@ static void bufile(const u8 *mcd_data, u32 dir_) {
  */
 
 static void psxBios_firstfile() { // 42
-       char *pa0 = castRam8ptr(a0);
+       char *pa0 = Ra0;
 
        PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
        v0 = 0;
 
+       if (pa0 != INVALID_PTR)
        {
                snprintf(ffile, sizeof(ffile), "%s", pa0);
                if (ffile[5] == 0)
@@ -3316,7 +3322,6 @@ void psxBiosSetupBootState(void)
                GPU_writeStatus(gpu_ctl_def[i]);
        for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
                GPU_writeData(gpu_data_def[i]);
-       HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
 
        // spu
        for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
@@ -3747,18 +3752,25 @@ void psxBiosInit() {
 
        // fill the api jumptables with fake entries as some games patch them
        // (or rather the funcs listed there)
+       // also trap the destination as some "Cheats Edition" thing overrides the
+       // dispatcher with a wrapper and then jumps to the table entries directly
        ptr = (u32 *)&psxM[A_A0_TABLE];
-       for (i = 0; i < 256; i++)
-               ptr[i] = SWAP32(A_A0_DUMMY);
-
+       for (i = 0; i < 256; i++) {
+               ptr[i] = SWAP32(A_A0_TRAPS + i*4);
+               ram32[A_A0_TRAPS/4 + i] = HLEOP(hleop_a0t);
+       }
        ptr = (u32 *)&psxM[A_B0_TABLE];
-       for (i = 0; i < 256; i++)
-               ptr[i] = SWAP32(A_B0_DUMMY);
+       for (i = 0; i < 256; i++) {
+               ptr[i] = SWAP32(A_B0_TRAPS + i*4);
+               ram32[A_B0_TRAPS/4 + i] = HLEOP(hleop_b0t);
+       }
        // B(5b) is special because games patch (sometimes even jump to)
        // code at fixed offsets from it, nocash lists offsets:
        //  patch: +3d8, +4dc, +594, +62c, +9c8, +1988
        //  call:  +7a0=4b70, +884=4c54, +894=4c64
-       ptr[0x5b] = SWAP32(A_B0_5B_DUMMY);    // 0x43d0
+       ptr[0x5b] = SWAP32(A_B0_5B_TRAP);     // 0x43d0
+       ram32[A_B0_5B_TRAP/4] = HLEOP(hleop_b0t);
+
        ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
 
        ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
@@ -3769,15 +3781,17 @@ void psxBiosInit() {
        ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
 
        ptr = (u32 *)&psxM[A_C0_TABLE];
-       for (i = 0; i < 256/2; i++)
-               ptr[i] = SWAP32(A_C0_DUMMY);
+       for (i = 0; i < 256/2; i++) {
+               ptr[i] = SWAP32(A_C0_TRAPS + i*4);
+               ram32[A_C0_TRAPS/4 + i] = HLEOP(hleop_c0t);
+       }
        ptr[6] = SWAP32(A_EXCEPTION);
 
        // more HLE traps
-       ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
-       ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
-       ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
-       ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
+       ram32[A_A0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
+       ram32[A_B0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
+       ram32[A_C0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
+       ram32[0x7ffc/4] = HLEOP(hleop_dummy);
        ram32[0x8000/4] = HLEOP(hleop_execret);
 
        ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
@@ -4092,7 +4106,8 @@ static void hleA0() {
        u32 call = t1 & 0xff;
        u32 entry = loadRam32(A_A0_TABLE + call * 4);
 
-       if (call < 192 && entry != A_A0_DUMMY) {
+       use_cycles(4+7);
+       if (call < 192 && entry != A_A0_TRAPS + call * 4) {
                PSXBIOS_LOG("custom A%02x %s(0x%x, )  addr=%08x ra=%08x\n",
                        call, biosA0n[call], a0, entry, ra);
                softCall(entry);
@@ -4111,10 +4126,11 @@ static void hleB0() {
        u32 entry = loadRam32(A_B0_TABLE + call * 4);
        int is_custom = 0;
 
+       use_cycles(4+7);
        if (call == 0x5b)
-               is_custom = entry != A_B0_5B_DUMMY;
+               is_custom = entry != A_B0_5B_TRAP;
        else
-               is_custom = entry != A_B0_DUMMY;
+               is_custom = entry != A_B0_TRAPS + call * 4;
        if (is_custom) {
                PSXBIOS_LOG("custom B%02x %s(0x%x, )  addr=%08x ra=%08x\n",
                        call, biosB0n[call], a0, entry, ra);
@@ -4133,7 +4149,8 @@ static void hleC0() {
        u32 call = t1 & 0xff;
        u32 entry = loadRam32(A_C0_TABLE + call * 4);
 
-       if (call < 128 && entry != A_C0_DUMMY) {
+       use_cycles(4+7);
+       if (call < 128 && entry != A_C0_TRAPS + call * 4) {
                PSXBIOS_LOG("custom C%02x %s(0x%x, )  addr=%08x ra=%08x\n",
                        call, biosC0n[call], a0, entry, ra);
                softCall(entry);
@@ -4147,6 +4164,47 @@ static void hleC0() {
        psxBranchTest();
 }
 
+static void hleA0t() {
+       u32 call = (pc0 - A_A0_TRAPS) / 4 - 1;
+       if (call >= 256u || !biosA0[call]) {
+               log_unhandled("unexpected A trap @%08x ra=%08x\n", pc0 - 4, ra);
+               mips_return_void_c(1000);
+       }
+       else
+               biosA0[call]();
+
+       //printf("A(%02x) -> %x\n", call, v0);
+       psxBranchTest();
+}
+
+static void hleB0t() {
+       u32 call = (pc0 - A_B0_TRAPS) / 4 - 1;
+       if (pc0 - 4 == A_B0_5B_TRAP)
+               call = 0x5b;
+       if (call >= 256u || !biosB0[call]) {
+               log_unhandled("unexpected B trap @%08x ra=%08x\n", pc0 - 4, ra);
+               mips_return_void_c(1000);
+       }
+       else
+               biosB0[call]();
+
+       //printf("B(%02x) -> %x\n", call, v0);
+       psxBranchTest();
+}
+
+static void hleC0t() {
+       u32 call = (pc0 - A_C0_TRAPS) / 4 - 1;
+       if (call >= 128u || !biosC0[call]) {
+               log_unhandled("unexpected C trap @%08x ra=%08x\n", pc0 - 4, ra);
+               mips_return_void_c(1000);
+       }
+       else
+               biosC0[call]();
+
+       //printf("C(%02x) -> %x\n", call, v0);
+       psxBranchTest();
+}
+
 // currently not used
 static void hleBootstrap() {
        CheckCdrom();
@@ -4168,7 +4226,7 @@ static void hleExecRet() {
        psxRegs.pc = ra;
 }
 
-void (* const psxHLEt[24])() = {
+void (* const psxHLEt[hleop_count_])() = {
        hleDummy, hleA0, hleB0, hleC0,
        hleBootstrap, hleExecRet, psxBiosException, hleDummy,
        hleExc0_0_1, hleExc0_0_2,
@@ -4179,6 +4237,7 @@ void (* const psxHLEt[24])() = {
        hleExc1_3_1, hleExc1_3_2,
        hleExc3_0_2_defint,
        hleExcPadCard1, hleExcPadCard2,
+       hleA0t, hleB0t, hleC0t,
 };
 
 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)