From bee52312d06313957cfe73dacdb1717d1c8bcddb Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:09:21 +0200 Subject: psxbios: Add checks to strcat Nocash documentation says that function fails if src or dst is 0. If so, then it must return 0. This fix is required for fixing crash on bootup in Digimon World. --- libpcsxcore/psxbios.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 292d80d..4624bf4 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -394,7 +394,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'); -- cgit v1.2.3 From a824e83d363ce167068e497a97b25f6d637807d6 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:10:33 +0200 Subject: psxbios: Add checks to PAD_init Nocash documentation says that function fails if type is not 0x20000000 or 0x20000001. In case of failure, it should return 0. If not, then it should return 2. This fixes input in Digimon World. --- libpcsxcore/psxbios.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 4624bf4..42926c2 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1613,10 +1613,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; } -- cgit v1.2.3 From 595a136b9285a14046cfb7e09eedabed844f5b2c Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:44:03 +0200 Subject: psxbios: Merging fixes from upstream. DeliverEvent functions are executed right after writing/reading instead of after setting v0. This fixes saving in games like LEGO Racers. --- libpcsxcore/psxbios.c | 145 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 58 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 42926c2..fd60955 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1681,43 +1681,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? */ + } } /* @@ -1737,11 +1764,11 @@ void psxBios_open() { // 0x32 if (pa0) { if (!strncmp(pa0, "bu00", 4)) { - buopen(1); + buopen(1, Mcd1Data, Config.Mcd1); } if (!strncmp(pa0, "bu10", 4)) { - buopen(2); + buopen(2, Mcd2Data, Config.Mcd2); } } @@ -1774,17 +1801,19 @@ void psxBios_lseek() { // 0x33 pc0 = ra; } -#define buread(Ra1, 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); */ @@ -1801,25 +1830,24 @@ void psxBios_read() { // 0x34 if (pa1) { switch (a0) { - case 2: buread(pa1, 1); break; - case 3: buread(pa1, 2); break; + case 2: buread(pa1, 1, a2); break; + case 3: buread(pa1, 2, a2); break; } } pc0 = ra; } -#define buwrite(Ra1, 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; \ } /* @@ -1851,8 +1879,8 @@ void psxBios_write() { // 0x35/0x03 } switch (a0) { - case 2: buwrite(pa1, 1); break; - case 3: buwrite(pa1, 2); break; + case 2: buwrite(pa1, 1, a2); break; + case 3: buwrite(pa1, 2, a2); break; } pc0 = ra; @@ -1888,17 +1916,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) { \ 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] == '*') { \ @@ -1906,7 +1935,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; \ -- cgit v1.2.3 From 76b81516963f0f50049be59172c651b559d9fabf Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:54:58 +0200 Subject: psxbios: Merging improved card_info function from upstream It should be closer to the real thing, and this commit and the previous one definitely fixes the save issues in Digimon World. --- libpcsxcore/psxbios.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index fd60955..265dbfd 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1279,11 +1279,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; } -- cgit v1.2.3 From bd48ba5ea8c87bf8c771550bc5320f7e6f73c9a6 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:55:57 +0200 Subject: psxbios: Add checks for card_write, card_read This also implements a bug which allows writes to 0x400 (Is supposed to only accept sector number between 0..3FFh). Function should return 0 if sector is invalid. --- libpcsxcore/psxbios.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 265dbfd..d4a38e1 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2146,7 +2146,13 @@ void psxBios__card_write() { // 0x4e #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; @@ -2173,7 +2179,13 @@ void psxBios__card_read() { // 0x4f #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; -- cgit v1.2.3 From 79dad1b3ff35061e16f7bc160955df6990cbef18 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:57:08 +0200 Subject: psxbios: Better EnterCiritcal implementation Nocash documentation says it should return 0 if one or none of the bits were changed and return 1 of both bits were set. This fixes Medievil 2, which would freeze upon starting up a game and this properly fixes Digimon World crashing (with fixed strcat implementation). It also possibly fix other games. --- libpcsxcore/psxbios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index d4a38e1..58581e9 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2907,8 +2907,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 -- cgit v1.2.3 From cd1ea24508e604743ad8d9c67199510c7498ef29 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:57:53 +0200 Subject: psxbios: Return 0x1f801814 for gpu_abort_dma Nocash documentation says that it returns the I/O address. I doubt any games use it so but it doesn't hurt to have it. --- libpcsxcore/psxbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 58581e9..775fba7 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1191,7 +1191,7 @@ void psxBios_sys_a0_4c() { // 0x4c GPU relate GPU_writeData(0x0400000); GPU_writeData(0x0200000); GPU_writeData(0x0100000); - + v0 = 0x1f801814; pc0 = ra; } -- cgit v1.2.3 From 324cec89343c216ad232fbcaf50faed6e528beef Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:58:44 +0200 Subject: psxbios: Adds putc and getc implementation getc will need to be fixed later but this should do as it is. No issues with putc. Both are similar to psxBios_read and psxBios_write, except size is 1. --- libpcsxcore/psxbios.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 775fba7..b13874e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -316,6 +316,58 @@ 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_abs() { // 0x0e if ((s32)a0 < 0) v0 = -(s32)a0; @@ -2378,8 +2430,8 @@ 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[0x08] = psxBios_getc; + biosA0[0x09] = psxBios_putc; //biosA0[0x0a] = psxBios_todigit; //biosA0[0x0b] = psxBios_atof; //biosA0[0x0c] = psxBios_strtoul; -- cgit v1.2.3 From ba11675ca958088f3c5c1e60a5d437f0c1683514 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 01:59:35 +0200 Subject: psxbios: Add todigit implementation Based on CTRX's code : https://github.com/machinamentum/CTRX/blob/master/bios/source/libc.c#L152 I'm not aware of any games using it but it doesn't hurt to have it and it should work fine. --- libpcsxcore/psxbios.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index b13874e..924996a 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -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; @@ -2432,7 +2459,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; -- cgit v1.2.3 From f42e1e9003d052bcfcadd5955d2396f11ea0f3c5 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:00:11 +0200 Subject: psxbios : Add checks for strncat Returns 0 if src or dst is 0x00. --- libpcsxcore/psxbios.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 924996a..90c11ae 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -493,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') { -- cgit v1.2.3 From 391b1d5b1fe4f68676835058af609535feb798a9 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:01:34 +0200 Subject: psxbios: Better realloc implementation This should be closer to the real behaviour as described by nocash. It doesn't do any bcopy though but it shouldn't be too much different other than that. --- libpcsxcore/psxbios.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 90c11ae..fc28ff8 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1010,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(); + } } -- cgit v1.2.3 From d95c9dcb57f71bf0b8b7bff8579763080c7a10af Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:02:48 +0200 Subject: psxbios: Improve WaitEvent behaviour according to documentation Nocash says it should return 0 if Event is unused, which it already does so it might be safe to remove the warning about it. (see why below) Then, it says that it should return 1 if event is ready (EvStALREADY). When that happens, it should also set it to ready (EvStACTIVE), unless event mode is EvMdINTR. (aka Callback Events) If it is a callback event, then documentation says it should be stuck in a loop forever. It also says that it can sometime return 0 (a BUG according to nocash), especially if it switched from EvStALREADY to EvStACTIVE. Said return value was previously set to 1, for some reasons. Now that we are covering all the corner cases, we should be returning 0 instead by default to cover the BUG. This should cover how most games expects it to behave now and should make it more robust. --- libpcsxcore/psxbios.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index fc28ff8..139c8a5 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1562,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 -- cgit v1.2.3 From d99f60685038ed3771d888284283fad04be3cdac Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:07:56 +0200 Subject: Fixup buread & buwrite being undefined. --- libpcsxcore/psxbios.c | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 139c8a5..044a19a 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -316,12 +316,38 @@ static inline void LoadRegs() { // * // System calls A0 */ + +#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, 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; \ +} + +#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, 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; \ +} + + /* 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 { + char *ptr; void *pa1 = Ra1; #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]); @@ -341,6 +367,7 @@ void psxBios_getc(void) // 0x03, 0x35 /* Copy of psxBios_write, except size is 1. */ void psxBios_putc(void) // 0x09, 0x3B { + char *ptr; void *pa1 = Ra1; #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]); @@ -1932,18 +1959,6 @@ void psxBios_lseek() { // 0x33 pc0 = ra; } -#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, 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); @@ -1969,18 +1984,6 @@ void psxBios_read() { // 0x34 pc0 = ra; } -#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, 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; \ -} - /* * int write(int fd , void *buf , int nbytes); */ -- cgit v1.2.3 From b29f3be0ac3fb01453eae2dabf8471b262881b30 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:08:32 +0200 Subject: Only PCSX4ALL uses ResetIoCycle. Remove it for now. --- libpcsxcore/psxbios.c | 1 - 1 file changed, 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 044a19a..9341b0d 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1610,7 +1610,6 @@ void psxBios_WaitEvent() { // 0a v0 = 0; pc0 = ra; - ResetIoCycle(); } void psxBios_TestEvent() { // 0b -- cgit v1.2.3 From a66d30585863c4fabbb724a69e30e3282c39bdc3 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:09:56 +0200 Subject: psxbios: Fix out-of-bounds issue. Make sure to return 0xff is no TCBs are available. Thanks senquack for the proper fix. --- libpcsxcore/psxbios.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 9341b0d..5bff23e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1667,8 +1667,20 @@ void psxBios_OpenTh() { // 0e int th; for (th=1; th<8; th++) + { if (Thread[th].status == 0) break; + } + if (th == 8) { + // Feb 2019 - Added out-of-bounds fix caught by cppcheck: + // When no free TCB is found, return 0xffffffff according to Nocash doc. +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__); +#endif + v0 = 0xffffffff; + pc0 = ra; + return; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th); #endif -- cgit v1.2.3 From 8a0245bbfe36003c7c42778844eb617ce710d449 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:10:43 +0200 Subject: psxbios: Should fix input issues in some games. Someone reported that this fixed Negcon controls in Ridge Racer Revolution and Grand Tour Racing. I doubt this will suffer from regressions ? --- libpcsxcore/psxbios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 5bff23e..83e5518 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1772,9 +1772,10 @@ void psxBios_StopPAD() { // 14 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); #endif - + if (pad_buf == 0){ pad_buf1 = NULL; pad_buf2 = NULL; + } pc0 = ra; } -- cgit v1.2.3 From 857fabead1b570fcf4b1097b9549e0c54530d5e9 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:11:40 +0200 Subject: psxbios: Merge upstream fix for Deliverevent in firstfile Looks like it is only executed for memory cards, that makes sense i guess. --- libpcsxcore/psxbios.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 83e5518..010a229 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2110,15 +2110,16 @@ void psxBios_firstfile() { // 42 pfile = ffile+5; nfile = 1; if (!strncmp(pa0, "bu00", 4)) { + // firstfile() calls _card_read() internally, so deliver it's event + DeliverEvent(0x11, 0x2); bufile(1); } else if (!strncmp(pa0, "bu10", 4)) { + // firstfile() calls _card_read() internally, so deliver it's event + DeliverEvent(0x11, 0x2); bufile(2); } } - // firstfile() calls _card_read() internally, so deliver it's event - DeliverEvent(0x11, 0x2); - pc0 = ra; } -- cgit v1.2.3 From fcf7ec6c12723009e4ad683841b46d0346c73934 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:12:23 +0200 Subject: psxbios : Add checks to index and rindex calls Return 0 for index/rindex if src is 0x00. --- libpcsxcore/psxbios.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 010a229..67a01e5 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -610,7 +610,13 @@ void psxBios_strlen() { // 0x1b void psxBios_index() { // 0x1c char *p = (char *)Ra0; - + if (a0 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + do { if (*p == a1) { v0 = a0 + (p - (char *)Ra0); @@ -626,7 +632,11 @@ void psxBios_rindex() { // 0x1d char *p = (char *)Ra0; v0 = 0; - + if (a0 == 0) + { + pc0 = ra; + return; + } do { if (*p == a1) v0 = a0 + (p - (char *)Ra0); -- cgit v1.2.3 From 0148ffb739a05e87ed9eaaf623c754d3d50ee2ab Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:13:13 +0200 Subject: psxbios: Add checks for bcopy Nocash documentation say that function refuses to copy any data if dst is NULL or len greater than 0x7FFFFFFF. (In any cases, return value is always dst) --- libpcsxcore/psxbios.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 67a01e5..4019234 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -739,15 +739,20 @@ void psxBios_tolower() { // 0x26 void psxBios_bcopy() { // 0x27 char *p1 = (char *)Ra1, *p2 = (char *)Ra0; + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } while ((s32)a2-- > 0) *p1++ = *p2++; - + a2 = 0; pc0 = ra; } void psxBios_bzero() { // 0x28 char *p = (char *)Ra0; while ((s32)a1-- > 0) *p++ = '\0'; - pc0 = ra; } -- cgit v1.2.3 From 01724d23d3e65e6ca12f3800d79c7de6ec241ea2 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:15:27 +0200 Subject: psxbios: Add checks for bzero. Only return 0 if size is invalid. (0 or 0x7FFFFFFF), return dst if not. --- libpcsxcore/psxbios.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 4019234..c362a75 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -752,7 +752,21 @@ void psxBios_bcopy() { // 0x27 void psxBios_bzero() { // 0x28 char *p = (char *)Ra0; + v0 = a0; + /* Same as memset here (See memset below) */ + if (a1 > 0x7FFFFFFF || a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + else if (a0 == 0) + { + pc0 = ra; + return; + } while ((s32)a1-- > 0) *p++ = '\0'; + a1 = 0; pc0 = ra; } -- cgit v1.2.3 From ef1da3dc02d5c3683cca34f1f5c59ca1b2134c72 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:16:41 +0200 Subject: psxbios: Add checks to memcpy. Always returns dst --- libpcsxcore/psxbios.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index c362a75..b327632 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -788,9 +788,19 @@ void psxBios_bcmp() { // 0x29 void psxBios_memcpy() { // 0x2a char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - while ((s32)a2-- > 0) *p1++ = *p2++; - - v0 = a0; pc0 = ra; + s32 n=0; + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } + while ((s32)a2-- > 0) { + n++; + *p1++ = *p2++; + } + a2 = 0; + pc0 = ra; } void psxBios_memset() { // 0x2b -- cgit v1.2.3 From 3f28b64fb1baeedec76a150ee40eaec0b9095d92 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:17:35 +0200 Subject: psxbios : Add checks to memset. This now can be a tricky pony and an improper memset implementation means that you can't play Tomb Raider 4 properly. (Trying to put in the eye of horus will just result in Lara sidestepping) This should hopefully be fixed (and follows nocash doc). --- libpcsxcore/psxbios.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index b327632..97c7951 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -805,8 +805,19 @@ void psxBios_memcpy() { // 0x2a void psxBios_memset() { // 0x2b char *p = (char *)Ra0; + v0 = a0; + if (a2 > 0x7FFFFFFF || a2 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + if (a0 == 0) + { + pc0 = ra; + return; + } while ((s32)a2-- > 0) *p++ = (char)a1; - a2 = 0; v0 = a0; pc0 = ra; } -- cgit v1.2.3 From 112dddf5f26989d55b257f51bdcb9236bc7c1de0 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:19:07 +0200 Subject: psxbios: Add checks for memmove. Always returns dst per documentation. --- libpcsxcore/psxbios.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 97c7951..399df9a 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -824,7 +824,12 @@ void psxBios_memset() { // 0x2b void psxBios_memmove() { // 0x2c char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - + v0 = a0; + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } if (p2 <= p1 && p2 + a2 > p1) { a2++; // BUG: copy one more byte here p1 += a2; @@ -833,8 +838,7 @@ void psxBios_memmove() { // 0x2c } else { while ((s32)a2-- > 0) *p1++ = *p2++; } - - v0 = a0; pc0 = ra; + pc0 = ra; } void psxBios_memcmp() { // 0x2d -- cgit v1.2.3 From 26b964b587007caace43f0dda8db1ac4a8c97e3d Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:21:53 +0200 Subject: psxbios : Several fixes to malloc. - Don't allow malloc to init memory if heap is invalid According to nocash documentation, malloc will not allocate if heap size is too small or invalid. - Also merge some fixes from PCSX4ALL fork by senquack in order to allow Burning Road to run. --- libpcsxcore/psxbios.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 399df9a..e9a13f9 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -254,6 +254,7 @@ static EvCB *RcEV; // 0xf2 static EvCB *UeEV; // 0xf3 static EvCB *SwEV; // 0xf4 static EvCB *ThEV; // 0xff +static u32 heap_size = 0; static u32 *heap_addr = NULL; static u32 *heap_end = NULL; static u32 SysIntRP[8]; @@ -983,6 +984,11 @@ void psxBios_malloc() { // 0x33 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]); #endif + if (!a0 || (!heap_size || !heap_addr)) { + v0 = 0; + pc0 = ra; + return; + } // scan through heap and combine free chunks of space chunk = heap_addr; @@ -992,6 +998,15 @@ void psxBios_malloc() { // 0x33 csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; + // most probably broken heap descriptor + // this fixes Burning Road + if (*chunk == 0) { + newchunk = chunk; + dsize = ((uptr)heap_end - (uptr)chunk) - 4; + colflag = 1; + break; + } + // it's a free chunk if(cstat == 1) { if(colflag == 0) { @@ -1023,28 +1038,36 @@ void psxBios_malloc() { // 0x33 // exit on uninitialized heap if (chunk == NULL) { - SysPrintf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); + printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); v0 = 0; pc0 = ra; return; } // search an unused chunk that is big enough until the end of the heap - while ((dsize > csize || cstat == 0) && chunk < heap_end ) { + while ((dsize > csize || cstat==0) && chunk < heap_end ) { chunk = (u32*)((uptr)chunk + csize + 4); + + // catch out of memory + if(chunk >= heap_end) { + printf("malloc %x,%x: Out of memory error!\n", + v0, a0); + v0 = 0; pc0 = ra; + return; + } + csize = ((u32)*chunk) & 0xfffffffc; cstat = ((u32)*chunk) & 1; } - // catch out of memory - if(chunk >= heap_end) { SysPrintf("malloc %x,%x: Out of memory error!\n", v0, a0); v0 = 0; pc0 = ra; return; } - // allocate memory if(dsize == csize) { // chunk has same size *chunk &= 0xfffffffc; - } - else { + } else if (dsize > csize) { + v0 = 0; pc0 = ra; + return; + } else { // split free chunk *chunk = SWAP32(dsize); newchunk = (u32*)((uptr)chunk + dsize + 4); @@ -1052,9 +1075,9 @@ void psxBios_malloc() { // 0x33 } // return pointer to allocated memory - v0 = ((unsigned long)chunk - (unsigned long)psxM) + 4; + v0 = ((uptr)chunk - (uptr)psxM) + 4; v0|= 0x80000000; - SysPrintf ("malloc %x,%x\n", v0, a0); + //printf ("malloc %x,%x\n", v0, a0); pc0 = ra; } @@ -2885,6 +2908,7 @@ void psxBiosInit() { pad_buf1len = pad_buf2len = 0; heap_addr = NULL; heap_end = NULL; + heap_size = 0; CardState = -1; CurThread = 0; memset(FDesc, 0, sizeof(FDesc)); -- cgit v1.2.3 From 002b2f7d98f8c543cd88cb453c88b09eb5e556ad Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:23:24 +0200 Subject: psxbios: Stub for get_error According to a user on PCSX-Reloaded codeplex (now dead), this fixed loading/saving in Final Fantasy Tactics. --- libpcsxcore/psxbios.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index e9a13f9..df0550e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2417,6 +2417,13 @@ void psxBios__new_card() { // 0x50 pc0 = ra; } +/* According to a user, this allows Final Fantasy Tactics to save/load properly */ +void psxBios__get_error(void) // 55 +{ + v0 = 0; + pc0 = ra; +} + void psxBios_Krom2RawAdd() { // 0x51 int i = 0; @@ -2839,7 +2846,7 @@ void psxBiosInit() { //biosB0[0x52] = psxBios_sys_b0_52; //biosB0[0x53] = psxBios_sys_b0_53; //biosB0[0x54] = psxBios__get_errno; - //biosB0[0x55] = psxBios__get_error; + biosB0[0x55] = psxBios__get_error; biosB0[0x56] = psxBios_GetC0Table; biosB0[0x57] = psxBios_GetB0Table; biosB0[0x58] = psxBios__card_chan; -- cgit v1.2.3 From c044e3e5d62089a53f1eacf99be9ecc1bb7cd012 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:26:18 +0200 Subject: psxbios: Add checks for strcmp & strncmp. Yes, it's supposed to have a lot of checks like these. Also merge some more fixes from PCSX4ALL. (upstream did not have these as far as i know) --- libpcsxcore/psxbios.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index df0550e..44711b5 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -541,13 +541,35 @@ void psxBios_strncat() { // 0x16 void psxBios_strcmp() { // 0x17 char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - + s32 n=0; + if (a0 == 0 && a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + else if (a0 == 0 && a1 != 0) + { + v0 = -1; + pc0 = ra; + return; + } + else if (a0 != 0 && a1 == 0) + { + v0 = 1; + pc0 = ra; + return; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1); #endif while (*p1 == *p2++) { + n++; if (*p1++ == '\0') { + v1=n-1; + a0+=n; + a1+=n; v0 = 0; pc0 = ra; return; @@ -555,6 +577,9 @@ void psxBios_strcmp() { // 0x17 } v0 = (*p1 - *--p2); + v1 = n; + a0+=n; + a1+=n; pc0 = ra; } -- cgit v1.2.3 From ba4ecb8c6e99104da806fa6455346f5a4890d1c4 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:27:11 +0200 Subject: psxbios: Fixup free. This is needed for Burning Road. Fix comes from PCSX4ALL by dmitryssmagin. --- libpcsxcore/psxbios.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 44711b5..be3abb8 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -586,7 +586,24 @@ void psxBios_strcmp() { // 0x17 void psxBios_strncmp() { // 0x18 char *p1 = (char *)Ra0, *p2 = (char *)Ra1; s32 n = a2; - + if (a0 == 0 && a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } + else if (a0 == 0 && a1 != 0) + { + v0 = -1; + pc0 = ra; + return; + } + else if (a0 != 0 && a1 == 0) + { + v0 = 1; + pc0 = ra; + return; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2); #endif @@ -595,12 +612,20 @@ void psxBios_strncmp() { // 0x18 if (*p1++ == '\0') { v0 = 0; pc0 = ra; + v1 = a2 - ((a2-n) - 1); + a0 += (a2-n) - 1; + a1 += (a2-n) - 1; + a2 = n; return; } } v0 = (n < 0 ? 0 : *p1 - *--p2); pc0 = ra; + v1 = a2 - ((a2-n) - 1); + a0 += (a2-n) - 1; + a1 += (a2-n) - 1; + a2 = n; } void psxBios_strcpy() { // 0x19 @@ -1114,7 +1139,8 @@ void psxBios_free() { // 0x34 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4)); - *(u32*)(Ra0-4) |= 1; // set chunk to free + if (a0) + *(u32*)(Ra0-4) |= 1; // set chunk to free pc0 = ra; } -- cgit v1.2.3 From c3d791f109093fb502a6674c13bd1196d94bca14 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:28:22 +0200 Subject: psxbios: Add checks for strcpy & strncpy. This should be closer to documentation. --- libpcsxcore/psxbios.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index be3abb8..13cfe73 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -630,6 +630,12 @@ void psxBios_strncmp() { // 0x18 void psxBios_strcpy() { // 0x19 char *p1 = (char *)Ra0, *p2 = (char *)Ra1; + if (a0 == 0 || a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } while ((*p1++ = *p2++) != '\0'); v0 = a0; pc0 = ra; @@ -638,7 +644,12 @@ void psxBios_strcpy() { // 0x19 void psxBios_strncpy() { // 0x1a char *p1 = (char *)Ra0, *p2 = (char *)Ra1; s32 n = a2, i; - + if (a0 == 0 || a1 == 0) + { + v0 = 0; + pc0 = ra; + return; + } for (i = 0; i < n; i++) { if ((*p1++ = *p2++) == '\0') { while (++i < n) { -- cgit v1.2.3 From 2c6a5df89dfba9a54f3bb09d145ef13081c76bf1 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:28:55 +0200 Subject: psxbios: Add checks for strlen. Per what Nocash documentation says. --- libpcsxcore/psxbios.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 13cfe73..cd2fb0c 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -666,6 +666,11 @@ void psxBios_strncpy() { // 0x1a void psxBios_strlen() { // 0x1b char *p = (char *)Ra0; v0 = 0; + if (a0 == 0) + { + pc0 = ra; + return; + } while (*p++) v0++; pc0 = ra; } -- cgit v1.2.3 From a946d159bfc8e85d5ff2bcb08fc940830d5acbf4 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:29:49 +0200 Subject: psxbios: Support other syscalls Since they don't do anything however, let's just add a default and break; instead. Interestingly, trying to implement SYS(04h+ can actually crash the HLE bios. Nocash documentation said that it should crash it but due to other reasons, it doesn't and returns to main program instead. --- libpcsxcore/psxbios.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index cd2fb0c..288e33b 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3196,6 +3196,9 @@ void psxBiosException() { case 2: // ExitCritical - enable irq's psxRegs.CP0.n.Status |= 0x404; break; + /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */ + default: + break; } pc0 = psxRegs.CP0.n.EPC + 4; -- cgit v1.2.3 From b4ae2532030fa15ca2009eb239ab2e50b2231000 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:30:31 +0200 Subject: psxbios: Callback Events should not set event status to busy in TestEvent. We are already doing that in WaitEvent. According to nocash documentation, this also applies to TestEvent as well so let's implement it. --- libpcsxcore/psxbios.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 288e33b..829deb0 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1762,9 +1762,15 @@ void psxBios_TestEvent() { // 0b ev = a0 & 0xff; spec = (a0 >> 8) & 0xff; - if (Event[ev][spec].status == EvStALREADY) { - Event[ev][spec].status = EvStACTIVE; v0 = 1; - } else v0 = 0; + if (Event[ev][spec].status == EvStALREADY) + { + if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE; + v0 = 1; + } + else + { + v0 = 0; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0); -- cgit v1.2.3 From f15146144475b363f46500c171ffd6555f585502 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:34:31 +0200 Subject: psxbios: Fixes save issues on Parasite Eve II, Parasite Eve I and others Merging never-merged fix by Solus for Parasite Eve. I also fixed some GCC warnings about dir->name going out of bounds too. We also make sure to only add '/0' if string is not full and right after the last character in the dir array. This fixes saving/loading in Parasite Eve II, Parasite Eve. It also fixed regressions for the LEGO Racers where other games would break, meaning this should be the proper fix for saves. We're also using our own strlen implementation to avoid any issues or relying on the libc's own strlen. --- libpcsxcore/psxbios.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 829deb0..fbc0002 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -322,9 +322,10 @@ static inline void LoadRegs() { 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, length); \ + if (FDesc[1 + mcd].mode & 0x8000) { \ DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ - if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + v0 = 0; } \ else v0 = length; \ FDesc[1 + mcd].offset += v0; \ } @@ -334,10 +335,11 @@ static inline void LoadRegs() { SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \ ptr = Mcd##mcd##Data + offset; \ memcpy(ptr, Ra1, length); \ + FDesc[1 + mcd].offset += length; \ + if (FDesc[1 + mcd].mode & 0x8000) { \ DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ - FDesc[1 + mcd].offset += length; \ - if (FDesc[1 + mcd].mode & 0x8000) v0 = 0; \ + v0 = 0; } \ else v0 = length; \ } @@ -2208,7 +2210,18 @@ void psxBios_puts() { // 3e/3f char ffile[64], *pfile; int nfile; + +/* To avoid any issues with different behaviour when using the libc's own strlen instead. + * We want to mimic the PSX's behaviour in this case for bufile. */ +static size_t strlen_internal(char* p) +{ + size_t size_of_array = 0; + while (*p++) size_of_array++; + return size_of_array; +} + #define bufile(mcd) { \ + size_t size_of_name = strlen_internal(dir->name); \ while (nfile < 16) { \ int match=1; \ \ @@ -2219,8 +2232,8 @@ int nfile; if (!ptr[0xa]) continue; \ ptr+= 0xa; \ if (pfile[0] == 0) { \ - strncpy(dir->name, ptr, sizeof(dir->name)); \ - dir->name[sizeof(dir->name) - 1] = '\0'; \ + strncpy(dir->name, ptr, sizeof(dir->name) - 1); \ + if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \ } else for (i=0; i<20; i++) { \ if (pfile[i] == ptr[i]) { \ dir->name[i] = ptr[i]; continue; } \ -- cgit v1.2.3 From 21af3ff6a2e100cd956525978808f35127dde843 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:35:47 +0200 Subject: psxbios.cpp: Add psxBios_card_status(); doesn't seem to affect anything --- libpcsxcore/psxbios.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index fbc0002..394dddc 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2586,6 +2586,15 @@ void psxBios_ChangeClearPad() { // 5b pc0 = ra; } +void psxBios__card_status() { // 5c +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0); +#endif + + v0 = 1; + pc0 = ra; +} + /* System calls C0 */ /* @@ -2939,7 +2948,7 @@ void psxBiosInit() { //biosB0[0x59] = psxBios_sys_b0_59; //biosB0[0x5a] = psxBios_sys_b0_5a; biosB0[0x5b] = psxBios_ChangeClearPad; - //biosB0[0x5c] = psxBios__card_status; + biosB0[0x5c] = psxBios__card_status; //biosB0[0x5d] = psxBios__card_wait; //*******************C0 CALLS**************************** //biosC0[0x00] = psxBios_InitRCnt; -- cgit v1.2.3 From f25c285bec9371ff3f48a140bf1e4a88bd6f779d Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:38:32 +0200 Subject: psxbios: Merge PCSX4ALL pad_stopped fix. --- libpcsxcore/psxbios.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 394dddc..98943b0 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -245,6 +245,7 @@ static u32 *jmp_int = NULL; static int *pad_buf = NULL; static char *pad_buf1 = NULL, *pad_buf2 = NULL; static int pad_buf1len, pad_buf2len; +static int pad_stopped = 0; static u32 regs[35]; static EvCB *Event; @@ -1914,7 +1915,7 @@ void psxBios_StartPAD() { // 13 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]); #endif - + pad_stopped = 0; psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1)); psxRegs.CP0.n.Status |= 0x401; pc0 = ra; @@ -1924,6 +1925,7 @@ void psxBios_StopPAD() { // 14 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); #endif + pad_stopped = 1; if (pad_buf == 0){ pad_buf1 = NULL; pad_buf2 = NULL; @@ -3138,12 +3140,14 @@ void biosInterrupt() { if (NET_recvPadData(pad_buf2, 2) == -1) netError(); } else { - if (pad_buf1) { - psxBios_PADpoll(1); - } + if (!pad_stopped) { + if (pad_buf1) { + psxBios_PADpoll(1); + } - if (pad_buf2) { - psxBios_PADpoll(2); + if (pad_buf2) { + psxBios_PADpoll(2); + } } } @@ -3271,6 +3275,7 @@ void psxBiosException() { void psxBiosFreeze(int Mode) { u32 base = 0x40000; + pad_stopped = 0; bfreezepsxMptr(jmp_int, u32); bfreezepsxMptr(pad_buf, int); bfreezepsxMptr(pad_buf1, char); -- cgit v1.2.3 From 832f0c3ce33b886112c7277700dd3b9f6bfdb549 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:40:13 +0200 Subject: psxbios: Init some vars just to be sure. --- libpcsxcore/psxbios.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 98943b0..ebb5957 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3005,6 +3005,7 @@ void psxBiosInit() { memset(Thread, 0, sizeof(Thread)); Thread[0].status = 2; // main thread + pad_stopped = 1; jmp_int = NULL; pad_buf = NULL; pad_buf1 = NULL; @@ -3016,6 +3017,7 @@ void psxBiosInit() { CardState = -1; CurThread = 0; memset(FDesc, 0, sizeof(FDesc)); + card_active_chan = 0; psxMu32ref(0x0150) = SWAPu32(0x160); psxMu32ref(0x0154) = SWAPu32(0x320); -- cgit v1.2.3 From a85ffa0ee71d19e297cd8bc3710d4c24330881e1 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:42:41 +0200 Subject: psxbios: Merge heap fix from PCSX4ALL. --- libpcsxcore/psxbios.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index ebb5957..856d561 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1219,8 +1219,10 @@ void psxBios_InitHeap() { // 0x39 size &= 0xfffffffc; heap_addr = (u32 *)Ra0; - heap_end = (u32 *)((u8 *)heap_addr + size); - *heap_addr = SWAP32(size | 1); + heap_size = size; + heap_end = (u32 *)((u8 *)heap_addr + heap_size); + /* HACKFIX: Commenting out this line fixes GTA2 crash */ + //*heap_addr = SWAP32(size | 1); SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size); -- cgit v1.2.3 From 8254b5a7f550a9f859ce2211560d8ca2f12a32ca Mon Sep 17 00:00:00 2001 From: gameblabla Date: Thu, 18 Jul 2019 02:51:25 +0200 Subject: psxbios: Add note and update copyright. --- libpcsxcore/psxbios.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 856d561..1f6c342 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1,5 +1,6 @@ /*************************************************************************** - * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, * + * dmitrysmagin, senquack * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -17,6 +18,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * ***************************************************************************/ +/* Gameblabla 2018-2019 : + * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings + * for the PSX bios calls. Thanks senquack for helping out with some of the changes + * and helping to spot issues and refine my patches. + * */ + /* * Internal simulated HLE BIOS. */ -- cgit v1.2.3 From 44e9fa8b2308539ad19fb948d64e2339adb7835a Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 01:26:10 +0200 Subject: psxbios : Fix a few mistakes : - Remove extra ffile, pfile.. as it is declared elsewhere. - Remove extra condition as it's already being handled by pad_stopped. - Remove n variable from function (pcsx4all did this) as it's useless and documentation doesn't seem to specify it's needed. --- libpcsxcore/psxbios.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 1f6c342..8b9c99a 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -865,7 +865,6 @@ void psxBios_bcmp() { // 0x29 void psxBios_memcpy() { // 0x2a char *p1 = (char *)Ra0, *p2 = (char *)Ra1; - s32 n=0; v0 = a0; if (a0 == 0 || a2 > 0x7FFFFFFF) { @@ -873,7 +872,6 @@ void psxBios_memcpy() { // 0x2a return; } while ((s32)a2-- > 0) { - n++; *p1++ = *p2++; } a2 = 0; @@ -1935,10 +1933,8 @@ void psxBios_StopPAD() { // 14 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); #endif pad_stopped = 1; - if (pad_buf == 0){ pad_buf1 = NULL; pad_buf2 = NULL; - } pc0 = ra; } @@ -2218,9 +2214,6 @@ void psxBios_puts() { // 3e/3f pc0 = ra; } -char ffile[64], *pfile; -int nfile; - /* To avoid any issues with different behaviour when using the libc's own strlen instead. * We want to mimic the PSX's behaviour in this case for bufile. */ -- cgit v1.2.3 From 5f652aa973201284e3da8cbea5bd0f1f83b73d19 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 01:28:56 +0200 Subject: psxbios : Implement stub for wait_card. Pretty much identical to get_card_status except it's supposed to wait until a non-busy state occurs. --- libpcsxcore/psxbios.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 8b9c99a..4c953df 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2599,6 +2599,15 @@ void psxBios__card_status() { // 5c pc0 = ra; } +void psxBios__card_wait() { // 5d +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0); +#endif + + v0 = 1; + pc0 = ra; +} + /* System calls C0 */ /* @@ -2953,7 +2962,7 @@ void psxBiosInit() { //biosB0[0x5a] = psxBios_sys_b0_5a; biosB0[0x5b] = psxBios_ChangeClearPad; biosB0[0x5c] = psxBios__card_status; - //biosB0[0x5d] = psxBios__card_wait; + biosB0[0x5d] = psxBios__card_wait; //*******************C0 CALLS**************************** //biosC0[0x00] = psxBios_InitRCnt; //biosC0[0x01] = psxBios_InitException; -- cgit v1.2.3 From a15f3544923a9d2ca3baa2dd9ced9f040ce197e8 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 01:31:24 +0200 Subject: psxbios : Use bfreezel for pad_stopped instead of setting it to 0. --- libpcsxcore/psxbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 4c953df..98e467a 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3288,7 +3288,6 @@ void psxBiosException() { void psxBiosFreeze(int Mode) { u32 base = 0x40000; - pad_stopped = 0; bfreezepsxMptr(jmp_int, u32); bfreezepsxMptr(pad_buf, int); bfreezepsxMptr(pad_buf1, char); @@ -3303,4 +3302,5 @@ void psxBiosFreeze(int Mode) { bfreezel(&CurThread); bfreezes(FDesc); bfreezel(&card_active_chan); + bfreezel(&pad_stopped); } -- cgit v1.2.3 From 17b2d969c7806101207076ab1431d1e38425f6f5 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 02:10:27 +0200 Subject: psxbios: Do the same for heap_size. --- libpcsxcore/psxbios.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 98e467a..b27d195 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3303,4 +3303,5 @@ void psxBiosFreeze(int Mode) { bfreezes(FDesc); bfreezel(&card_active_chan); bfreezel(&pad_stopped); + bfreezel(&heap_size); } -- cgit v1.2.3 From f23c22410abc88088a33ddf391c9fae8a1705dac Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 02:13:34 +0200 Subject: psxbios: Merge interrupt_r26 fix from PCSX4ALL. Thanks DmitrySmagin for the fix. --- libpcsxcore/psxbios.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index b27d195..6a52d7e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -307,6 +307,8 @@ static inline void DeliverEvent(u32 ev, u32 spec) { } else Event[ev][spec].status = EvStALREADY; } +static unsigned interrupt_r26=0x8004E8B0; + static inline void SaveRegs() { memcpy(regs, psxRegs.GPR.r, 32*4); regs[32] = psxRegs.GPR.n.lo; @@ -1968,6 +1970,7 @@ void psxBios_ReturnFromException() { // 17 LoadRegs(); pc0 = psxRegs.CP0.n.EPC; + k0 = interrupt_r26; if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4; psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | @@ -3190,6 +3193,7 @@ void psxBiosException() { switch (psxRegs.CP0.n.Cause & 0x3c) { case 0x00: // Interrupt + interrupt_r26=psxRegs.CP0.n.EPC; #ifdef PSXCPU_LOG // PSXCPU_LOG("interrupt\n"); #endif -- cgit v1.2.3 From cf1af0ed3ca53d0d7092e87f1d090eb3b9b5b128 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 02:30:15 +0200 Subject: psxbios: Fix card_status function as to use card_active_chan. --- libpcsxcore/psxbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 6a52d7e..ee307e3 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2598,7 +2598,7 @@ void psxBios__card_status() { // 5c PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0); #endif - v0 = 1; + v0 = card_active_chan; pc0 = ra; } -- cgit v1.2.3 From 8f3b2bd3184c6d23e6297270eeec897cb72c7b7a Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 02:38:32 +0200 Subject: psxbios: Make HLE bios start from block 1, not 2. I already fixed this for bufile : ptr = Mcd##mcd##Data + 128 * (nfile + 1); \ instead of ptr = Mcd##mcd##Data + 128 * nfile; \ But i forgot to also fix psxBios_firstfile accordingly. So nfile would still start from block 2 and it would cause all kinds of issues. This was the original comment on pcsxr codeplex as my patch was based on it : "The HLE-Bios start to read memory card blocks at block 2. You need to change ptr = Mcd##mcd##Data + 128 * nfile; \ to ptr = Mcd##mcd##Data + 128 * (nfile + 1); \ for #define bufile(mcd) { \ and changing nfile = 1; to nfile = 0; for psxBios_firstfile() { // 42 Starts numbering slots in the right position." --- libpcsxcore/psxbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index ee307e3..59471f1 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2278,7 +2278,7 @@ void psxBios_firstfile() { // 42 if (pa0) { strcpy(ffile, pa0); pfile = ffile+5; - nfile = 1; + nfile = 0; if (!strncmp(pa0, "bu00", 4)) { // firstfile() calls _card_read() internally, so deliver it's event DeliverEvent(0x11, 0x2); -- cgit v1.2.3 From 18dd7e9e0fa02a4aaf7ce553c4706c60bca312c3 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 02:45:58 +0200 Subject: psxbios: Implement get_cd_status stub according to nocash doc. --- libpcsxcore/psxbios.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 59471f1..ca15943 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1557,6 +1557,13 @@ void psxBios_SetMem() { // 9f pc0 = ra; } +/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */ +void psxBios_get_cd_status(void) //a6 +{ + v0 = 1; + pc0 = ra; +} + void psxBios__card_info() { // ab #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0); @@ -2858,7 +2865,7 @@ void psxBiosInit() { //biosA0[0xa3] = psxBios_DequeueCdIntr; //biosA0[0xa4] = psxBios_sys_a0_a4; //biosA0[0xa5] = psxBios_ReadSector; - //biosA0[0xa6] = psxBios_get_cd_status; + biosA0[0xa6] = psxBios_get_cd_status; //biosA0[0xa7] = psxBios_bufs_cb_0; //biosA0[0xa8] = psxBios_bufs_cb_1; //biosA0[0xa9] = psxBios_bufs_cb_2; -- cgit v1.2.3 From bf643fd9c59939266ee95021292a08b5d20a250e Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 05:39:55 +0200 Subject: psxbios: Some games read from address 0, fix that. See Garbage Area at Address 00000000h in Nocash PSX Specifications for more inf> R-types will refuse to boot if psxM[0] is zero. Fade to Black can crash upon memory card access if psxM[5] is set to the wrong > Crash Team Racing will refuse to boot if psxM[2] and psxM[3] are not zero. (Previously, that region of memory would be overwritten above. No explanation why.) It's set as such according to nocash : [00000000h]=3C1A0000h ;<-- but overwritten by 00000003h after soon [00000004h]=275A0C80h ;<-- or 275A0C50h (in older BIOS) [00000008h]=03400008h [0000000Ch]=00000000h Note that setting 00000000h to 00000003h doesn't work for R-types. --- libpcsxcore/psxbios.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index ca15943..7b2c05f 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3052,7 +3052,9 @@ void psxBiosInit() { */ // opcode HLE psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4); - psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0); + /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch. + Normally games shouldn't read from address 0 yet they do. See explanation below in details. */ + //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0); psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1); psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2); psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3); @@ -3078,6 +3080,21 @@ void psxBiosInit() { psxHu32ref(0x1060) = SWAPu32(0x00000b88); hleSoftCall = FALSE; + + /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers. + See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information. + R-type will work if PsxM[0] is non-zero. (Meaning that it should not be 00000003h as he implies). + Crash Team Racing will refuse to boot if psxM[2] and psx[3] are not set to 0. + Fade to Black can crash upon memory card access if byte 5 is set to the wrong value. + */ + psxM[0] = SWAPu32(0x3C); + psxM[1] = SWAPu32(0x1A); + psxM[2] = SWAPu32(0x00); + psxM[3] = SWAPu32(0x00); + psxM[4] = SWAPu32(0x27); + psxM[5] = SWAPu32(0x5A); + psxM[6] = SWAPu32(0x0C); + psxM[7] = SWAPu32(0x80); } void psxBiosShutdown() { -- cgit v1.2.3 From 0f598f20d1c618933ffd1a02207912915fcd454e Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 07:43:56 +0200 Subject: psxbios: Add checks for memchr. --- libpcsxcore/psxbios.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 7b2c05f..3247402 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -924,6 +924,12 @@ void psxBios_memcmp() { // 0x2d void psxBios_memchr() { // 0x2e char *p = (char *)Ra0; + + if (a0 == 0 || a2 > 0x7FFFFFFF) + { + pc0 = ra; + return; + } while ((s32)a2-- > 0) { if (*p++ != (s8)a1) continue; -- cgit v1.2.3 From 9ee77db131fbb7708c0fdf2dda91dd92c277c20b Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 17:31:48 +0200 Subject: psxbios: Return value is always 1 for CloseTh and ChangeTh. According to nocash PSX doc, ChangeThread and CloseThread should always return 1. Fix it accordingly. --- libpcsxcore/psxbios.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 3247402..7c908e3 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1878,12 +1878,10 @@ void psxBios_CloseTh() { // 0f #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th); #endif - - if (Thread[th].status == 0) { - v0 = 0; - } else { + /* The return value is always 1 (even if the handle was already closed). */ + v0 = 1; + if (Thread[th].status != 0) { Thread[th].status = 0; - v0 = 1; } pc0 = ra; @@ -1899,14 +1897,11 @@ void psxBios_ChangeTh() { // 10 #ifdef PSXBIOS_LOG // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th); #endif - + /* The return value is always 1. */ + v0 = 1; if (Thread[th].status == 0 || CurThread == th) { - v0 = 0; - pc0 = ra; } else { - v0 = 1; - if (Thread[CurThread].status == 2) { Thread[CurThread].status = 1; Thread[CurThread].func = ra; -- cgit v1.2.3 From c2360853ed4794a964e972d4837a83578ac01d04 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Sun, 21 Jul 2019 20:57:57 +0200 Subject: psxbios: Fixup mistake in card_info function. This fixes Looney Tunes Sheep Raiders. --- libpcsxcore/psxbios.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 7c908e3..93a4057 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1593,11 +1593,8 @@ void psxBios__card_info() { // ab break; } -// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 -// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 - DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004 - v0 = 1; pc0 = ra; } -- cgit v1.2.3 From 339cc5b6c622b9e4544e67239c048d39f245390b Mon Sep 17 00:00:00 2001 From: gameblabla Date: Mon, 22 Jul 2019 04:39:41 +0200 Subject: psxbios: Properly fix garbage area code. This should work as intended now. --- libpcsxcore/psxbios.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 93a4057..8c8093b 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -3081,18 +3081,19 @@ void psxBiosInit() { /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers. See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information. - R-type will work if PsxM[0] is non-zero. (Meaning that it should not be 00000003h as he implies). - Crash Team Racing will refuse to boot if psxM[2] and psx[3] are not set to 0. - Fade to Black can crash upon memory card access if byte 5 is set to the wrong value. + Here are some examples of games not working with this fix in place : + R-type won't get past the Irem logo if not implemented. + Crash Team Racing will softlock after the Sony logo. */ - psxM[0] = SWAPu32(0x3C); - psxM[1] = SWAPu32(0x1A); - psxM[2] = SWAPu32(0x00); - psxM[3] = SWAPu32(0x00); - psxM[4] = SWAPu32(0x27); - psxM[5] = SWAPu32(0x5A); - psxM[6] = SWAPu32(0x0C); - psxM[7] = SWAPu32(0x80); + + psxMu32ref(0x0000) = SWAPu32(0x00000003); + /* + But overwritten by 00000003h after soon. + psxMu32ref(0x0000) = SWAPu32(0x00001A3C); + */ + psxMu32ref(0x0004) = SWAPu32(0x800C5A27); + psxMu32ref(0x0008) = SWAPu32(0x08000403); + psxMu32ref(0x000C) = SWAPu32(0x00000000); } void psxBiosShutdown() { -- cgit v1.2.3 From 1059caaf959bf28d2cd1020b8bc30d33fb71ed93 Mon Sep 17 00:00:00 2001 From: gameblabla Date: Mon, 22 Jul 2019 23:25:49 +0200 Subject: psxbios: Don't accept 400h as a valid sector. Notaz said this could corrupt the emulator (even though the console allowed this and it was a bug) so limit it to 0x3FF. --- libpcsxcore/psxbios.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'libpcsxcore/psxbios.c') diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 8c8093b..928f0af 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -2450,8 +2450,11 @@ void psxBios__card_write() { // 0x4e #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)) + /* + Function also accepts sector 400h (a bug). + But notaz said we shouldn't allow sector 400h because it can corrupt the emulator. + */ + if (!(a1 <= 0x3FF)) { /* Invalid sectors */ v0 = 0; pc0 = ra; @@ -2483,8 +2486,11 @@ void psxBios__card_read() { // 0x4f #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]); #endif - /* Function also accepts sector 400h (a bug) */ - if (!(a1 <= 0x400)) + /* + Function also accepts sector 400h (a bug). + But notaz said we shouldn't allow sector 400h because it can corrupt the emulator. + */ + if (!(a1 <= 0x3FF)) { /* Invalid sectors */ v0 = 0; pc0 = ra; -- cgit v1.2.3