From: retro-wertz Date: Mon, 29 Jul 2019 06:10:54 +0000 (+0800) Subject: HLE: Merge HLE BIOS improvements from upstream X-Git-Tag: r24l~714^2 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8ec1e4de88798ca548481773e49bb01a4de03139;p=pcsx_rearmed.git HLE: Merge HLE BIOS improvements from upstream - Merge update from https://github.com/libretro/pcsx_rearmed --- 8ec1e4de88798ca548481773e49bb01a4de03139 diff --cc libpcsxcore/psxbios.c index a6846017,928f0af0..388d6063 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@@ -1,5 -1,6 +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 * ++ * 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 +18,12 @@@ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * ***************************************************************************/ -/* Gameblabla 2018-2019 : ++/* 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. */ @@@ -211,7 -217,7 +218,7 @@@ typedef struct u32 func; } TCB; --typedef struct { ++typedef struct { u32 _pc0; u32 gp0; u32 t_addr; @@@ -495,7 -689,13 +690,13 @@@ void psxBios_strlen() { // 0x1 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); @@@ -678,7 -924,13 +925,13 @@@ void psxBios_memcmp() { // 0x2 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; v0 = a0 + (p - (char *)Ra0 - 1); @@@ -1131,7 -1423,7 +1424,7 @@@ void psxBios_GPU_dw() { // 0x4 } while(--size); pc0 = ra; --} ++} void psxBios_mem2vram() { // 0x47 int size; @@@ -1171,8 -1463,8 +1464,8 @@@ void psxBios_GPU_cwb() { // 0x4 pc0 = ra; } -- --void psxBios_GPU_SendPackets() { //4b: ++ ++void psxBios_GPU_SendPackets() { //4b: GPU_writeStatus(0x04000002); psxHwWrite32(0x1f8010f4,0); psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800); @@@ -1207,7 -1499,7 +1500,7 @@@ void psxBios_LoadExec() { // 5 #endif s_addr = a1; s_size = a2; -- a1 = 0xf000; ++ a1 = 0xf000; psxBios_Load(); header->S_addr = s_addr; @@@ -1262,7 -1554,7 +1555,7 @@@ void psxBios_SetMem() { // 9 psxHu32ref(0x1060) = SWAP32(new | 0x300); psxMu32ref(0x060) = a0; SysPrintf("Change effective memory : %d MBytes\n",a0); -- ++ default: SysPrintf("Effective memory must be 2/8 MBytes\n"); break; @@@ -1275,17 -1574,16 +1575,16 @@@ void psxBios__card_info() { // a #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0); #endif - - u32 ret; ++ u32 ret, port; 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; + port = card_active_chan >> 4; + + switch (port) { + case 0x0: + case 0x1: + ret = 0x2; + if (McdDisable[port & 1]) + ret = 0x8; break; default: #ifdef PSXBIOS_LOG @@@ -1294,14 -1592,9 +1593,13 @@@ ret = 0x11; break; } - - DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004 + + if (McdDisable[0] && McdDisable[1]) + ret = 0x8; + - // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 ++ DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 +// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004 - v0 = 1; pc0 = ra; } @@@ -1465,11 -1758,24 +1763,24 @@@ void psxBios_WaitEvent() { // 0 #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; ++ pc0 = ra; + return; + } - Event[ev][spec].status = EvStACTIVE; - if (Event[ev][spec].status == EvStALREADY) ++ 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; } void psxBios_TestEvent() { // 0b @@@ -1478,9 -1784,15 +1789,15 @@@ 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].status == EvStALREADY) + { + if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE; + v0 = 1; - } - else ++ } ++ else + { + v0 = 0; + } #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0); @@@ -1691,43 -2018,70 +2023,70 @@@ void psxBios_UnDeliverEvent() { // 0x2 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? */ + } } /* @@@ -1811,25 -2155,12 +2160,12 @@@ void psxBios_read() { // 0x3 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) { \ - 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; \ - DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ - DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ + pc0 = ra; } /* @@@ -1891,10 -2222,18 +2227,18 @@@ void psxBios_puts() { // 3e/3 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) ++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; \ \ @@@ -1926,7 -2266,7 +2271,7 @@@ /* * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir); */ -- ++ void psxBios_firstfile() { // 42 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1; void *pa0 = Ra0; @@@ -2162,6 -2521,13 +2526,13 @@@ void psxBios__new_card() { // 0x5 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; @@@ -2233,7 -2599,7 +2604,7 @@@ void psxBios__card_chan() { // 0x5 void psxBios_ChangeClearPad() { // 5b #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0); --#endif ++#endif pc0 = ra; } @@@ -2292,11 -2667,11 +2672,11 @@@ void psxBios_ChangeClearRCnt() { // 0 pc0 = ra; } --void psxBios_dummy() { ++void psxBios_dummy() { #ifdef PSXBIOS_LOG PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1); #endif -- pc0 = ra; ++ pc0 = ra; } void (*biosA0[256])(); @@@ -2307,7 -2682,7 +2687,7 @@@ void (*biosC0[256])() void psxBiosInit() { u32 base, size; -- u32 *ptr; ++ u32 *ptr; int i; uLongf len; @@@ -2390,7 -2765,7 +2770,7 @@@ biosA0[0x39] = psxBios_InitHeap; //biosA0[0x3a] = psxBios__exit; biosA0[0x3b] = psxBios_getchar; -- biosA0[0x3c] = psxBios_putchar; ++ biosA0[0x3c] = psxBios_putchar; //biosA0[0x3d] = psxBios_gets; //biosA0[0x40] = psxBios_sys_a0_40; //biosA0[0x41] = psxBios_LoadTest; @@@ -2406,7 -2781,7 +2786,7 @@@ biosA0[0x4b] = psxBios_GPU_SendPackets; biosA0[0x4c] = psxBios_sys_a0_4c; biosA0[0x4d] = psxBios_GPU_GetGPUStatus; -- //biosA0[0x4e] = psxBios_GPU_sync; ++ //biosA0[0x4e] = psxBios_GPU_sync; //biosA0[0x4f] = psxBios_sys_a0_4f; //biosA0[0x50] = psxBios_sys_a0_50; biosA0[0x51] = psxBios_LoadExec; @@@ -2458,10 -2833,10 +2838,10 @@@ //biosA0[0x7f] = psxBios_sys_a0_7f; //biosA0[0x80] = psxBios_sys_a0_80; //biosA0[0x81] = psxBios_sys_a0_81; -- //biosA0[0x82] = psxBios_sys_a0_82; ++ //biosA0[0x82] = psxBios_sys_a0_82; //biosA0[0x83] = psxBios_sys_a0_83; //biosA0[0x84] = psxBios_sys_a0_84; -- //biosA0[0x85] = psxBios__96_CdStop; ++ //biosA0[0x85] = psxBios__96_CdStop; //biosA0[0x86] = psxBios_sys_a0_86; //biosA0[0x87] = psxBios_sys_a0_87; //biosA0[0x88] = psxBios_sys_a0_88; @@@ -2613,7 -2988,7 +2993,7 @@@ //biosC0[0x07] = psxBios_InstallExeptionHandler; //biosC0[0x08] = psxBios_SysInitMemory; //biosC0[0x09] = psxBios_SysInitKMem; -- biosC0[0x0a] = psxBios_ChangeClearRCnt; ++ biosC0[0x0a] = psxBios_ChangeClearRCnt; //biosC0[0x0b] = psxBios_SystemError; //biosC0[0x0c] = psxBios_InitDefInt; //biosC0[0x0d] = psxBios_sys_c0_0d; @@@ -2679,7 -3056,9 +3061,9 @@@ */ // 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. ++ /* 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); @@@ -2705,6 -3084,22 +3089,22 @@@ 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. + 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. + */ - ++ + 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() { @@@ -2873,7 -3272,10 +3277,10 @@@ void psxBiosException() break; case 2: // ExitCritical - enable irq's -- psxRegs.CP0.n.Status |= 0x404; ++ 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;