X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fpsxbios.c;h=7b2c05fc3cb0523209a9cdb12bc4e16fe5a10424;hp=288e33b3060284c2cb421652e6fe091b979aaed4;hb=bf643fd9c59939266ee95021292a08b5d20a250e;hpb=a946d159bfc8e85d5ff2bcb08fc940830d5acbf4 diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 288e33b3..7b2c05fc 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. */ @@ -245,6 +252,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; @@ -299,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; @@ -322,9 +332,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 +345,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; \ } @@ -855,7 +867,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) { @@ -863,7 +874,6 @@ void psxBios_memcpy() { // 0x2a return; } while ((s32)a2-- > 0) { - n++; *p1++ = *p2++; } a2 = 0; @@ -1216,8 +1226,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); @@ -1545,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); @@ -1762,9 +1781,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); @@ -1906,7 +1931,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; @@ -1916,10 +1941,9 @@ void psxBios_StopPAD() { // 14 #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); #endif - if (pad_buf == 0){ + pad_stopped = 1; pad_buf1 = NULL; pad_buf2 = NULL; - } pc0 = ra; } @@ -1953,6 +1977,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) | @@ -2199,10 +2224,18 @@ 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. */ +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; \ \ @@ -2213,8 +2246,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; } \ @@ -2252,7 +2285,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); @@ -2567,6 +2600,24 @@ 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 = card_active_chan; + 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 */ /* @@ -2814,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; @@ -2920,8 +2971,8 @@ void psxBiosInit() { //biosB0[0x59] = psxBios_sys_b0_59; //biosB0[0x5a] = psxBios_sys_b0_5a; biosB0[0x5b] = psxBios_ChangeClearPad; - //biosB0[0x5c] = psxBios__card_status; - //biosB0[0x5d] = psxBios__card_wait; + biosB0[0x5c] = psxBios__card_status; + biosB0[0x5d] = psxBios__card_wait; //*******************C0 CALLS**************************** //biosC0[0x00] = psxBios_InitRCnt; //biosC0[0x01] = psxBios_InitException; @@ -2975,6 +3026,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; @@ -2986,6 +3038,7 @@ void psxBiosInit() { CardState = -1; CurThread = 0; memset(FDesc, 0, sizeof(FDesc)); + card_active_chan = 0; psxMu32ref(0x0150) = SWAPu32(0x160); psxMu32ref(0x0154) = SWAPu32(0x320); @@ -2999,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); @@ -3025,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() { @@ -3110,12 +3180,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); + } } } @@ -3145,6 +3217,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 @@ -3257,4 +3330,6 @@ void psxBiosFreeze(int Mode) { bfreezel(&CurThread); bfreezes(FDesc); bfreezel(&card_active_chan); + bfreezel(&pad_stopped); + bfreezel(&heap_size); }