X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxbios.c;h=e654f7c9c5d62e8469cf18ee062134454dc4cafe;hb=dcaa32ddfd2c74db639452d6aee456d41d502700;hp=af3c55fb061f8bfd8cea6b70fdf4a18a59631ff9;hpb=9a0a61d27586bfb93aa443cc59d9588d2b9cf992;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index af3c55fb..e654f7c9 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -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)); @@ -532,12 +532,8 @@ void psxBios_putc(void) // 0x09, 0x3B pc0 = ra; } -void psxBios_todigit(void) // 0x0a +static u32 do_todigit(u32 c) { - int c = a0; -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]); -#endif c &= 0xFF; if (c >= 0x30 && c < 0x3A) { c -= 0x30; @@ -549,14 +545,73 @@ void psxBios_todigit(void) // 0x0a c = c - 0x41 + 10; } else if (c >= 0x80) { + log_unhandled("todigit %02x\n", c); c = -1; } else { c = 0x0098967F; } - v0 = c; - pc0 = ra; + use_cycles(40); + return c; +} + +static void psxBios_todigit(void) // 0x0a +{ + mips_return(do_todigit(a0)); + PSXBIOS_LOG("psxBios_%s '%c' -> %u\n", biosA0n[0x0a], a0, v0); +} + +static void do_strtol(char *p, void *end_, u32 base, int can_neg) { + s32 n = 0, f = 0, t; + u32 *end = end_; + + use_cycles(12); + if (p == INVALID_PTR) { + mips_return(0); + return; + } + + for (; (0x09 <= *p && *p <= '\r') || *p == ' '; p++) + use_cycles(9); + if (can_neg) { + for (; *p == '-'; f = 1, p++) + use_cycles(4); + } + if (base == 0 || base > 36) + base = 10; + if (*p == '0') { + switch (*p++) { + case 'b': case 'B': base = 2; break; + case 'x': case 'X': base = 16; break; + } + } + else if (*p == 'o' || *p == 'O') { + base = 8; + p++; + } + + for (; (t = do_todigit(*p)) < base; p++) { + n = n * base + t; + use_cycles(12); + } + + n = (f ? -n : n); + if (end != INVALID_PTR) + *end = SWAP32(a0 + (p - Ra0)); + mips_return_c(n, 100); +} + +static void psxBios_strtoul() { // 0x0c + do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 0); + PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n", + biosA0n[0x0c], a0 ? Ra0 : NULL, a0, a1, a2, v0); +} + +static void psxBios_strtol() { // 0x0d + do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 1); + PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n", + biosA0n[0x0d], a0 ? Ra0 : NULL, a0, a1, a2, v0); } void psxBios_abs() { // 0x0e @@ -3322,7 +3377,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++) @@ -3383,8 +3437,8 @@ void psxBiosInit() { biosA0[0x09] = psxBios_putc; biosA0[0x0a] = psxBios_todigit; //biosA0[0x0b] = psxBios_atof; - //biosA0[0x0c] = psxBios_strtoul; - //biosA0[0x0d] = psxBios_strtol; + biosA0[0x0c] = psxBios_strtoul; + biosA0[0x0d] = psxBios_strtol; biosA0[0x0e] = psxBios_abs; biosA0[0x0f] = psxBios_labs; biosA0[0x10] = psxBios_atoi; @@ -3753,18 +3807,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 @@ -3775,15 +3836,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); @@ -4098,7 +4161,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); @@ -4117,10 +4181,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); @@ -4139,7 +4204,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); @@ -4153,6 +4219,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(); @@ -4174,7 +4281,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, @@ -4185,6 +4292,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)