diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 316cec432c..0e938539bc 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -538,6 +538,8 @@ add_library(Core STATIC HLE/proAdhocServer.cpp HLE/sceOpenPSID.cpp HLE/sceOpenPSID.h + HLE/sceResmgr.cpp + HLE/sceResmgr.h HLE/sceP3da.cpp HLE/sceP3da.h HLE/sceMt19937.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 574123cdad..f493c40f25 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -645,6 +645,7 @@ + @@ -1155,6 +1156,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 7b7bf9c5cf..c26c14f463 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -375,6 +375,9 @@ HLE\Libraries + + HLE\Libraries + HLE\Libraries @@ -1698,6 +1701,9 @@ HLE\Libraries + + HLE\Libraries + HLE\Libraries diff --git a/Core/ELF/PrxDecrypter.cpp b/Core/ELF/PrxDecrypter.cpp index 795dab1865..c199970e6f 100644 --- a/Core/ELF/PrxDecrypter.cpp +++ b/Core/ELF/PrxDecrypter.cpp @@ -293,8 +293,13 @@ static const u32 g_keyUPDATER_PSAR[] = { 0x62E86C81, 0x03299B96, 0x73AFAE5A, 0x40A05320, 0x10664BE8, 0xE5B76A99, 0x29E0DD70, 0xEA602428, 0x2042AE30, 0x946F8D32, 0xA29E5F71, 0x7C0C7FD5}; -struct TAG_INFO -{ +// Used by sceResmgr_9DC14891, which is how the VSH decrypts flash0:/vsh/etc/index_XXg.dat - the +// XMB item index, and the only thing on the boot path that needs these. +static const u8 keys_9DC14891_1[] = {0x39, 0xF7, 0xDF, 0x19, 0xD7, 0x10, 0xEA, 0x9F, 0x02, 0xDB, 0x3F, 0xB1, 0x10, 0x9F, 0x26, 0x6B}; +static const u8 keys_9DC14891_2[] = {0x46, 0x1D, 0xC9, 0xC2, 0x1D, 0x44, 0xA6, 0x68, 0xF2, 0x06, 0x37, 0xBF, 0x62, 0xCD, 0x11, 0x9E}; +static const u8 keys_9DC14891_3[] = {0x11, 0x0D, 0x1A, 0x4C, 0x8A, 0x19, 0x17, 0xDC, 0xD0, 0x5A, 0x65, 0x47, 0xA5, 0x03, 0x85, 0x22}; + +struct TAG_INFO { u32 tag; // 4 byte value at offset 0xD0 in the PRX file const u32 *key; // "step1_result" use for XOR step u8 code; @@ -347,6 +352,9 @@ struct TAG_INFO2 static const TAG_INFO2 g_tagInfo2[] = { + { 0x0B2B90F0, keys_9DC14891_1, 0x5C }, + { 0x0B2B91F0, keys_9DC14891_2, 0x5C }, + { 0x0B2B92F0, keys_9DC14891_3, 0x5C }, { 0x4C9494F0, keys660_k1, 0x43 }, { 0x4C9495F0, keys660_k2, 0x43 }, { 0x4C9490F0, keys660_k3, 0x43 }, diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index 03b4318dfe..d76e9eb3ac 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -58,6 +58,7 @@ #include "sceNp.h" #include "sceMpeg.h" #include "sceOpenPSID.h" +#include "sceResmgr.h" #include "sceP3da.h" #include "sceParseHttp.h" #include "sceParseUri.h" @@ -332,6 +333,8 @@ void RegisterAllModules() { Register_sceHprm_driver(); Register_sceChkreg(); Register_sceVshBridge(); + Register_sceResmgr(); + // add new modules here. // Not ready to enable this due to apparent softlocks in Patapon 3. diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index d01be2228a..7ac71c349a 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -153,7 +153,7 @@ static int sceImpose_driver_B497314D(int param, u32 resultAddr) { // The settings sceImposeGetParam/SetParam address, as a bitfield - sceImposeChanges reports which // of them have been changed since it was last asked, so the VSH can refresh only what moved. -enum { +enum : u32 { PSP_IMPOSE_MAIN_VOLUME = 0x1, PSP_IMPOSE_BACKLIGHT_BRIGHTNESS = 0x2, PSP_IMPOSE_EQUALIZER_MODE = 0x4, @@ -162,16 +162,33 @@ enum { PSP_IMPOSE_TIME_FORMAT = 0x20, PSP_IMPOSE_DATE_FORMAT = 0x40, PSP_IMPOSE_LANGUAGE = 0x80, + PSP_IMPOSE_00000100 = 0x100, PSP_IMPOSE_BACKLIGHT_OFF_INTERVAL = 0x200, PSP_IMPOSE_SOUND_REDUCTION = 0x400, + // Named after their own values, as in JPCSP - real meanings unknown. + PSP_IMPOSE_20000000 = 0x20000000, + PSP_IMPOSE_80000001 = 0x80000001, + PSP_IMPOSE_80000002 = 0x80000002, + PSP_IMPOSE_80000003 = 0x80000003, + PSP_IMPOSE_80000004 = 0x80000004, + PSP_IMPOSE_80000005 = 0x80000005, + PSP_IMPOSE_80000006 = 0x80000006, + PSP_IMPOSE_80000007 = 0x80000007, + PSP_IMPOSE_80000008 = 0x80000008, + PSP_IMPOSE_80000009 = 0x80000009, + PSP_IMPOSE_8000000A = 0x8000000A, + PSP_IMPOSE_8000000B = 0x8000000B, }; // Returns the current value of one setting. Values follow JPCSP's, which are the plausible -// defaults for a console with nothing unusual configured. Anything we don't model reads as 0 -// rather than failing - the VSH polls this every frame for its indicators, so returning an error -// would be far more disruptive than returning a quiet default. +// defaults for a console with nothing unusual configured. +// +// The split between the last two cases matters and matches JPCSP: a parameter that exists but that +// we don't model reads as 0, while one that isn't a parameter at all is rejected. Answering 0 to +// everything tells a caller probing for a feature that the feature is there and switched off, +// which is a different thing from "no such setting". static int sceImposeGetParam(int param) { - switch (param) { + switch ((u32)param) { case PSP_IMPOSE_MAIN_VOLUME: return hleLogDebug(Log::sceUtility, 30); // Full, on a 0-30 scale. case PSP_IMPOSE_BACKLIGHT_BRIGHTNESS: @@ -182,8 +199,26 @@ static int sceImposeGetParam(int param) { case PSP_IMPOSE_SOUND_REDUCTION: case PSP_IMPOSE_BACKLIGHT_OFF_INTERVAL: return hleLogDebug(Log::sceUtility, 0); + case PSP_IMPOSE_EQUALIZER_MODE: + case PSP_IMPOSE_TIME_FORMAT: + case PSP_IMPOSE_DATE_FORMAT: + case PSP_IMPOSE_LANGUAGE: + case PSP_IMPOSE_00000100: + case PSP_IMPOSE_20000000: + case PSP_IMPOSE_80000001: + case PSP_IMPOSE_80000002: + case PSP_IMPOSE_80000003: + case PSP_IMPOSE_80000004: + case PSP_IMPOSE_80000005: + case PSP_IMPOSE_80000006: + case PSP_IMPOSE_80000007: + case PSP_IMPOSE_80000008: + case PSP_IMPOSE_80000009: + case PSP_IMPOSE_8000000A: + case PSP_IMPOSE_8000000B: + return hleLogDebug(Log::sceUtility, 0, "param %08x not modelled", param); default: - return hleLogDebug(Log::sceUtility, 0, "unmodelled param %08x", param); + return hleLogWarning(Log::sceUtility, SCE_KERNEL_ERROR_INVALID_MODE, "invalid param %08x", param); } } diff --git a/Core/HLE/sceResmgr.cpp b/Core/HLE/sceResmgr.cpp new file mode 100644 index 0000000000..e816c4ddd5 --- /dev/null +++ b/Core/HLE/sceResmgr.cpp @@ -0,0 +1,76 @@ +// Copyright (c) 2012- PPSSPP Project. + +// 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 +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include + +// MemMap.h first: PrxDecrypter.h's PSP_Header is written in u32_le and friends, and doesn't pull +// in the header that defines them. +#include "Core/MemMap.h" +#include "Core/Debugger/MemBlockInfo.h" +#include "Core/ELF/PrxDecrypter.h" +#include "Core/HLE/FunctionWrappers.h" +#include "Core/HLE/HLE.h" +#include "Core/HLE/sceResmgr.h" + +// The resource manager. Games never touch this - it exists for the VSH, which uses the one +// function below to decrypt flash0:/vsh/etc/index_XXg.dat, the index of what the XMB shows. With +// this unresolved the call traps, the index stays encrypted, the job thread building the top menu +// gives up, and the shell ends on an error screen instead. + +// Decrypts a buffer in place. Named after its NID, as in JPCSP - the real name isn't known, though +// the index file is the only caller we've seen. +// +// Parameters: +// - bufferAddr: encrypted data in, decrypted data out. +// - bufferSize: how much is there. +// - resultLengthAddr: receives the decrypted length, which is smaller - the header goes away. +static int sceResmgr_9DC14891(u32 bufferAddr, int bufferSize, u32 resultLengthAddr) { + if (bufferSize < 0 || !Memory::IsValidRange(bufferAddr, bufferSize)) + return hleLogError(Log::sceMisc, -1, "bad buffer"); + + u8 *buffer = Memory::GetPointerWriteUnchecked(bufferAddr); + + // Already plaintext - the check JPCSP uses, and cheap insurance against decrypting twice. + if (bufferSize >= 8 && !memcmp(buffer, "release:", 8)) { + if (Memory::IsValidAddress(resultLengthAddr)) + Memory::WriteUnchecked_U32(bufferSize, resultLengthAddr); + return hleLogDebug(Log::sceMisc, 0, "already decrypted"); + } + + // Decrypting in place is fine for the caller, but pspDecryptPRX walks the input while writing + // the output, so give it somewhere separate to write and copy back on success. On failure the + // guest buffer is left exactly as it was. + std::vector decrypted(bufferSize); + const int decryptedSize = pspDecryptPRX(buffer, decrypted.data(), bufferSize); + if (decryptedSize <= 0) { + return hleLogError(Log::sceMisc, -1, "failed to decrypt %d bytes", bufferSize); + } + + memcpy(buffer, decrypted.data(), decryptedSize); + NotifyMemInfo(MemBlockFlags::WRITE, bufferAddr, decryptedSize, "sceResmgrDecrypt"); + if (Memory::IsValidAddress(resultLengthAddr)) + Memory::WriteUnchecked_U32(decryptedSize, resultLengthAddr); + return hleLogInfo(Log::sceMisc, 0, "decrypted %d bytes to %d", bufferSize, decryptedSize); +} + +const HLEFunction sceResmgr[] = { + {0X9DC14891, &WrapI_UIU, "sceResmgr_9DC14891", 'i', "xix"}, +}; + +void Register_sceResmgr() { + RegisterHLEModule("sceResmgr", ARRAY_SIZE(sceResmgr), sceResmgr); +} diff --git a/Core/HLE/sceResmgr.h b/Core/HLE/sceResmgr.h new file mode 100644 index 0000000000..c8f911d5fc --- /dev/null +++ b/Core/HLE/sceResmgr.h @@ -0,0 +1,20 @@ +// Copyright (c) 2012- PPSSPP Project. + +// 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 +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +void Register_sceResmgr(); diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 0bf4da7707..75b29f0a7d 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -227,6 +227,7 @@ + @@ -506,6 +507,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 7b40a69b42..918fc06cb4 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -136,6 +136,7 @@ + @@ -562,6 +563,7 @@ + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6467be4647..02f45dcd91 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -761,6 +761,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/HLE/sceNetInet.cpp \ $(SRC)/Core/HLE/sceNetResolver.cpp \ $(SRC)/Core/HLE/sceOpenPSID.cpp \ + $(SRC)/Core/HLE/sceResmgr.cpp \ $(SRC)/Core/HLE/sceP3da.cpp \ $(SRC)/Core/HLE/sceMt19937.cpp \ $(SRC)/Core/HLE/sceParseHttp.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 69f4c31415..fb201a2080 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -812,6 +812,7 @@ SOURCES_CXX += \ $(COREDIR)/HLE/proAdhocServer.cpp \ $(COREDIR)/HLE/proAdhoc.cpp \ $(COREDIR)/HLE/sceOpenPSID.cpp \ + $(COREDIR)/HLE/sceResmgr.cpp \ $(COREDIR)/HLE/sceP3da.cpp \ $(COREDIR)/HLE/sceMt19937.cpp \ $(COREDIR)/HLE/sceMd5.cpp \