diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index f8db7a8f7b..107f121674 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -80,6 +80,7 @@ void cpuReset() AllowParams1 = !VMManager::Internal::IsFastBootInProgress(); AllowParams2 = !VMManager::Internal::IsFastBootInProgress(); + ParamsRead = false; g_eeloadMain = 0; g_eeloadExec = 0; diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index 8ca8106105..2ebf43d94d 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -8,7 +8,6 @@ #include "R5900.h" #include "R5900OpcodeTables.h" #include "GS.h" -#include "CDVD/CDVD.h" #include "ps2/BiosTools.h" #include "DebugTools/DebugInterface.h" #include "DebugTools/Breakpoints.h" @@ -955,43 +954,67 @@ void SYSCALL() } break; case Syscall::SetOsdConfigParam: + // The whole thing gets written back to BIOS memory, so it'll be in the right place, no need to continue HLEing AllowParams1 = true; break; case Syscall::GetOsdConfigParam: - if(!NoOSD && !AllowParams1) + if (!NoOSD && !AllowParams1) { + ReadOSDConfigParames(); + u32 memaddr = cpuRegs.GPR.n.a0.UL[0]; - u8 params[16]; - cdvdReadLanguageParams(params); + memWrite32(memaddr, configParams1.UL[0]); + + // Call the set function, as we need to set this back to the BIOS storage position. + if (cpuRegs.GPR.n.v1.SL[0] < 0) + cpuRegs.GPR.n.v1.SL[0] = -Syscall::SetOsdConfigParam; + else + cpuRegs.GPR.n.v1.UC[0] = Syscall::SetOsdConfigParam; - u32 osdconf = 0; - u32 timezone = params[4] | ((u32)(params[3] & 0x7) << 8); - - osdconf |= params[1] & 0x1F; // SPDIF, Screen mode, RGB/Comp, Jap/Eng Switch (Early bios) - osdconf |= (u32)params[0] << 5; // PS1 Mode Settings - osdconf |= (u32)((params[2] & 0xE0) >> 5) << 13; // OSD Ver (Not sure but best guess) - osdconf |= (u32)(params[2] & 0x1F) << 16; // Language - osdconf |= timezone << 21; // Timezone - - memWrite32(memaddr, osdconf); - return; + AllowParams1 = true; } break; case Syscall::SetOsdConfigParam2: - AllowParams2 = true; + if (!AllowParams2) + { + ReadOSDConfigParames(); + + u32 memaddr = cpuRegs.GPR.n.a0.UL[0]; + u32 size = cpuRegs.GPR.n.a1.UL[0]; + u32 offset = cpuRegs.GPR.n.a2.UL[0]; + + if (offset == 0 && size >= 4) + AllowParams2 = true; + + for (u32 i = 0; i < size; i++) + { + if (offset >= 4) + break; + + configParams2.UC[offset++] = memRead8(memaddr++); + } + } break; case Syscall::GetOsdConfigParam2: if (!NoOSD && !AllowParams2) { + ReadOSDConfigParames(); + u32 memaddr = cpuRegs.GPR.n.a0.UL[0]; - u8 params[16]; + u32 size = cpuRegs.GPR.n.a1.UL[0]; + u32 offset = cpuRegs.GPR.n.a2.UL[0]; - cdvdReadLanguageParams(params); + if (offset + size > 2) + Console.Warning("Warning: GetOsdConfigParam2 Reading extended language/version configs, may be incorrect!"); - u32 osdconf2 = (((u32)params[3] & 0x78) << 9); // Daylight Savings, 24hr clock, Date format - - memWrite32(memaddr, osdconf2); + for (u32 i = 0; i < size; i++) + { + if (offset >= 4) + memWrite8(memaddr++, 0); + else + memWrite8(memaddr++, configParams2.UC[offset++]); + } return; } break; diff --git a/pcsx2/ps2/BiosTools.cpp b/pcsx2/ps2/BiosTools.cpp index 2822e01a45..2cefd68eec 100644 --- a/pcsx2/ps2/BiosTools.cpp +++ b/pcsx2/ps2/BiosTools.cpp @@ -7,6 +7,7 @@ #include "common/FileSystem.h" #include "common/Path.h" #include "common/StringUtil.h" +#include "CDVD/CDVD.h" #include "Common.h" #include "BiosTools.h" @@ -36,6 +37,9 @@ static_assert(sizeof(romdir) == DIRENTRY_SIZE, "romdir struct not packed to 16 b u32 BiosVersion; u32 BiosChecksum; u32 BiosRegion; +ConfigParam configParams1; +Config2Param configParams2; +bool ParamsRead; bool NoOSD; bool AllowParams1; bool AllowParams2; @@ -46,6 +50,29 @@ std::string BiosPath; BiosDebugInformation CurrentBiosInformation; std::vector BiosRom; +void ReadOSDConfigParames() +{ + if (ParamsRead) + return; + + ParamsRead = true; + + u8 params[16]; + cdvdReadLanguageParams(params); + + configParams1.UC[0] = params[1] & 0x1F; // SPDIF, Screen mode, RGB/Comp, Jap/Eng Switch (Early bios). + configParams1.ps1drvConfig = params[0]; // PS1 Mode Settings. + configParams1.version = (params[2] & 0xE0) >> 5; // OSD Ver (Not sure but best guess). + configParams1.language = params[2] & 0x1F; // Language. + configParams1.timezoneOffset = params[4] | ((u32)(params[3] & 0x7) << 8); // Timezone offset in minutes. + + // Region settings for time/date and extended language + configParams2.UC[1] = ((u32)params[3] & 0x78) << 1; // Daylight Savings, 24hr clock, Date format + // FIXME: format, version and language are set manually by the bios. Not sure if any game needs them, but it seems to set version to 2 and duplicate the language value. + configParams2.version = 2; + configParams2.language = configParams1.language; +} + static bool LoadBiosVersion(std::FILE* fp, u32& version, std::string& description, u32& region, std::string& zone, std::string& serial) { romdir rd; diff --git a/pcsx2/ps2/BiosTools.h b/pcsx2/ps2/BiosTools.h index 2eb3f97034..5cbd5aa9c7 100644 --- a/pcsx2/ps2/BiosTools.h +++ b/pcsx2/ps2/BiosTools.h @@ -20,11 +20,77 @@ struct BiosDebugInformation u32 iopModListAddr; }; +// Obained from the Open PS2SDK here https://github.com/ps2dev/ps2sdk/blob/master/ee/kernel/include/osd_config.h +// Only used for HLEing ConfigParam Syscalls in fast boot +typedef struct +{ + union + { + struct + { + /** 0=enabled, 1=disabled */ + /*00*/ u32 spdifMode : 1; + /** 0=4:3, 1=fullscreen, 2=16:9 */ + /*01*/ u32 screenType : 2; + /** 0=rgb(scart), 1=component */ + /*03*/ u32 videoOutput : 1; + /** 0=japanese, 1=english(non-japanese) */ + /*04*/ u32 japLanguage : 1; + /** Playstation driver settings. */ + /*05*/ u32 ps1drvConfig : 8; + /** 0 = early Japanese OSD, 1 = OSD2, 2 = OSD2 with extended languages. Early kernels cannot retain the value set in this field (Hence always 0). */ + /*13*/ u32 version : 3; + /** LANGUAGE_??? value */ + /*16*/ u32 language : 5; + /** timezone minutes offset from gmt */ + /*21*/ u32 timezoneOffset : 11; + }; + + u8 UC[4]; + u16 US[2]; + u32 UL[1]; + }; +} ConfigParam; + +typedef struct +{ + union + { + struct + { + // This value is unknown, seems to be set to zero by default + /*00*/ u8 format; + + /*00*/ u8 reserved : 4; + /** 0=standard(winter), 1=daylight savings(summer) */ + /*04*/ u8 daylightSaving : 1; + /** 0=24 hour, 1=12 hour */ + /*05*/ u8 timeFormat : 1; + /** 0=YYYYMMDD, 1=MMDDYYYY, 2=DDMMYYYY */ + /*06*/ u8 dateFormat : 2; + + // Only used if ConfigParam.version = 2 + /** Set to 2 */ + /*00*/ u8 version; + /** The true language, unlike the one from ConfigParam */ + /*00*/ u8 language; + }; + + u8 UC[4]; + u16 US[2]; + u32 UL[1]; + }; +} Config2Param; +// End of OpenSDK struct + // TODO: namespace this extern BiosDebugInformation CurrentBiosInformation; extern u32 BiosVersion; // Used by CDVD extern u32 BiosRegion; // Used by CDVD extern bool NoOSD; // Used for HLE OSD Config Params +extern ConfigParam configParams1; +extern Config2Param configParams2; +extern bool ParamsRead; extern bool AllowParams1; extern bool AllowParams2; extern u32 BiosChecksum; @@ -44,6 +110,8 @@ extern std::string BiosPath; // If we ever support read-only physical mappings, we can remove this. extern std::vector BiosRom; +extern void ReadOSDConfigParames(); + extern bool IsBIOS(const char* filename, u32& version, std::string& description, u32& region, std::string& zone); extern bool IsBIOSAvailable(const std::string& full_path);