E580
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -588,6 +590,8 @@ add_library(Core STATIC
HLE/sceUtility.h
HLE/sceVaudio.cpp
HLE/sceVaudio.h
HLE/sceVshBridge.cpp
HLE/sceVshBridge.h
HLE/scePspNpDrm_user.cpp
HLE/scePspNpDrm_user.h
HLE/sceNp.cpp
Expand All @@ -609,6 +613,8 @@ add_library(Core STATIC
HW/Camera.h
HW/Display.cpp
HW/Display.h
HW/GpioMMIO.cpp
HW/GpioMMIO.h
HW/MediaEngine.cpp
HW/MediaEngine.h
HW/MpegDemux.cpp
Expand Down
6 changes: 6 additions & 0 deletions Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@
<Cl 685C Compile Include="HW\BufferQueue.cpp" />
<ClCompile Include="HW\Camera.cpp" />
<ClCompile Include="HW\Display.cpp" />
<ClCompile Include="HW\GpioMMIO.cpp" />
<ClCompile Include="HW\GranularMixer.cpp" />
<ClCompile Include="Instance.cpp" />
<ClCompile Include="KeyMap.cpp" />
Expand Down Expand Up @@ -644,6 +645,7 @@
<ClCompile Include="HLE\sceNetAdhocMatching.cpp" />
<ClCompile Include="HLE\sceNp.cpp" />
<ClCompile Include="HLE\sceOpenPSID.cpp" />
<ClCompile Include="HLE\sceResmgr.cpp" />
<ClCompile Include="HLE\sceParseHttp.cpp" />
<ClCompile Include="HLE\sceParseUri.cpp" />
<ClCompile Include="HLE\scePauth.cpp" />
Expand All @@ -667,6 +669,7 @@
<ClCompile Include="HLE\sceUsbGps.cpp" />
<ClCompile Include="HLE\sceUtility.cpp" />
<ClCompile Include="HLE\sceVaudio.cpp" />
<ClCompile Include="HLE\sceVshBridge.cpp" />
<ClCompile Include="HLE\__sceAudio.cpp" />
<ClCompile Include="HW\MediaEngine.cpp" />
<ClCompile Include="HW\MemoryStick.cpp" />
Expand Down Expand Up @@ -1041,6 +1044,7 @@
<ClInclude Include="HW\Atrac3Standalone.h" />
<ClInclude Include="HW\Camera.h" />
<ClInclude Include="HW\Display.h" />
<ClInclude Include="HW\GpioMMIO.h" />
<ClInclude Include="HW\GranularMixer.h" />
<ClInclude Include="Instance.h" />
<ClInclude Include="KeyMap.h" />
Expand Down Expand Up @@ -1152,6 +1156,7 @@
<ClInclude Include="HLE\sceNetAdhocMatching.h" />
<ClInclude Include="HLE\sceNp.h" />
<ClInclude Include="HLE\sceOpenPSID.h" />
<ClInclude Include="HLE\sceResmgr.h" />
<ClInclude Include="HLE\sceParseHttp.h" />
<ClInclude Include="HLE\sceParseUri.h" />
<ClInclude Include="HLE\scePauth.h" />
Expand All @@ -1176,6 +1181,7 @@
<ClInclude Include="HLE\sceUtility.h" />
<ClInclude Include="HLE\sceKernelVTimer.h" />
<ClInclude Include="HLE\sceVaudio.h" />
<ClInclude Include="HLE\sceVshBridge.h" />
<ClInclude Include="HLE\ThreadQueueList.h" />
<ClInclude Include="HLE\__sceAudio.h" />
<ClInclude Include="HW\BufferQueue.h" />
Expand Down
18 changes: 18 additions & 0 deletions Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@
<ClCompile Include="HLE\sceOpenPSID.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="HLE\sceResmgr.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="HLE\sceParseUri.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
Expand All @@ -387,6 +390,9 @@
<ClCompile Include="HLE\sceVaudio.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="HLE\sceVshBridge.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="Dialog\PSPDialog.cpp">
<Filter>Dialog</Filter>
</ClCompile>
Expand Down Expand Up @@ -1204,6 +1210,9 @@
<ClCompile Include="HW\Display.cpp">
<Filter>HW</Filter>
</ClCompile>
<ClCompile Include="HW\GpioMMIO.cpp">
<Filter>HW</Filter>
</ClCompile>
<ClCompile Include="HLE\sceNp2.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
Expand Down Expand Up @@ -1692,6 +1701,9 @@
<ClInclude Include="HLE\sceOpenPSID.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="HLE\sceResmgr.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="HLE\sceParseUri.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
Expand All @@ -1704,6 +1716,9 @@
<ClInclude Include="HLE\sceVaudio.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="HLE\sceVshBridge.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="Dialog\PSPDialog.h">
<Filter>Dialog</Filter>
</ClInclude>
Expand Down Expand Up @@ -2163,6 +2178,9 @@
<ClInclude Include="HW\Display.h">
<Filter>HW</Filter>
</ClInclude>
<ClInclude Include="HW\GpioMMIO.h">
<Filter>HW</Filter>
</ClInclude>
<ClInclude Include="HLE\sceNp2.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
Expand Down
3 changes: 3 additions & 0 deletions Core/ELF/ParamSFO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ GameRegion DetectGameRegionFromID(std::string_view id_full) {
return GameRegion::TEST;
} else if (id_letters == "UMDT") {
return GameRegion::DIAGNOSTIC;
} else if (id_letters == "VSHM") { // this is just generated from vshmain.elf
return GameRegion::FIRMWARE;
}
}
return GameRegion::HOMEBREW;
Expand All @@ -474,6 +476,7 @@ std::string_view GameRegionToString(GameRegion region) {
case GameRegion::TEST: return "Test disc";
case GameRegion::DIAGNOSTIC: return "Diagnostic tool";
case GameRegion::FIRMWARE: return "Firmware update";
case GameRegion::VSH: return "VSH";
default: return "unknown region";
}
}
1 change: 1 addition & 0 deletions Core/ELF/ParamSFO.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ enum class GameRegion {
TEST,
DIAGNOSTIC,
FIRMWARE,
VSH,
};

GameRegion DetectGameRegionFromID(std::string_view id_version);
Expand Down
132 changes: 128 additions & 4 deletions Core/ELF/PrxDecrypter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -724,6 +732,43 @@ struct PRXType6
};
static_assert(sizeof(PRXType6) == 0x150, "inconsistent size of PRX Type 6");

// Same 0x150-byte layout as type 6 - the difference is that a type 9 PRX carries an ECDSA
// signature at 0x104..0x12C where type 6 has nothing, and the signature is *excluded* from the
// hash rather than fed into it. JPCSP zeroes buf2[0x34..0x5C), which is that same range once the
// header has been rearranged, so here the corresponding field is simply left zero.
struct PRXType9
{
explicit PRXType9(const u8 *prx)
{
memcpy(tag, prx+0xD0, sizeof(tag));
memset(empty, 0, sizeof(empty));
// Not copied from prx+0x10C, unlike type 6: it holds the tail of the signature.
memset(ecdsaSignatureTail, 0, sizeof(ecdsaSignatureTail));
memcpy(id, prx+0x140, sizeof(id));
memcpy(sha1, prx+0x12C, sizeof(sha1));
// kirk header is split between 0x80->0xB0 and 0xC0->0xD0
memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
memcpy(prxHeader, prx, sizeof(prxHeader));
}

void decrypt(int key)
{
kirk7(id, id, 0x60, key);
}

u8 tag[4];
u8 empty[0x38];
u8 ecdsaSignatureTail[0x20];
u8 id[0x10];
u8 sha1[0x14];
u8 kirkHeader[0x40];
u8 kirkMetadata[0x10];
u8 prxHeader[0x80];
};
static_assert(sizeof(PRXType9) == 0x150, "inconsistent size of PRX Type 9");

static int pspDecryptType0(KirkState *kirk, const u8 *inbuf, u8 *outbuf, u32 size)
{
INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
Expand Down Expand Up @@ -1033,6 +1078,78 @@ static int pspDecryptType6(KirkState *kirk, const u8 *inbuf, u8 *outbuf, u32 siz
return decryptSize;
}

// Used by sceResmgr for flash0:/vsh/etc/index_XXg.dat. Identical to type 6 except for the ECDSA
// signature at 0x104..0x12C - so the "must be empty" check stops short of it, the signature is
// left out of the hash (see PRXType9), and it is not written back over the output header the way
// type 6 writes its tail there.
static int pspDecryptType9(KirkState *kirk, const u8 *inbuf, u8 *outbuf, u32 size)
{
INFO_LOG(Log::Loader, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);

if (!pti)
{
return -1;
}

// Only up to 0x104 - past that is the signature, which is present rather than empty here.
if (std::any_of(inbuf+0xD4, inbuf+0x104, [](u8 x) { return x != 0; }))
{
return -2;
}

// expand the seed into a xor buffer
auto xorbuf = expandSeed(pti->key, pti->code);

PRXType9 type9(inbuf);
type9.decrypt(pti->code);

SHA_CTX ctx;
SHAInit(&ctx);
SHAUpdate(&ctx, type9.tag, sizeof(type9.tag));
SHAUpdate(&ctx, xorbuf.data(), 0x10);
SHAUpdate(&ctx, type9.empty, sizeof(type9.empty));
SHAUpdate(&ctx, type9.ecdsaSignatureTail, sizeof(type9.ecdsaSignatureTail));
SHAUpdate(&ctx, type9.id, sizeof(type9.id));
SHAUpdate(&ctx, type9.kirkHeader, sizeof(type9.kirkHeader));
SHAUpdate(&ctx, type9.kirkMetadata, sizeof(type9.kirkMetadata));
SHAUpdate(&ctx, type9.prxHeader, sizeof(type9.prxHeader));

u8 sha1[0x14];
SHAFinal(sha1, &ctx);

if (memcmp(sha1, type9.sha1, sizeof(sha1)) != 0)
{
return -3;
}

constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_ECDSA_HEADER)-sizeof(type9.prxHeader);
KIRK_CMD1_ECDSA_HEADER *header = reinterpret_cast<KIRK_CMD1_ECDSA_HEADER *>(outbuf+offset);

if (outbuf != inbuf)
{
memcpy(outbuf, inbuf, size);
}

memset(header, 0, sizeof(KIRK_CMD1_ECDSA_HEADER));
memcpy(reinterpret_cast<u8*>(&header->data_size), type9.kirkMetadata, sizeof(type9.kirkMetadata));
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_ECDSA_HEADER), type9.prxHeader, sizeof(type9.prxHeader));
decryptKirkHeader(reinterpret_cast<u8*>(header), type9.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
header->mode = 1;
// Left at 0, unlike type 6/7 which set it: type 9 carries a real ECDSA signature that was
// verified separately, so KIRK is not asked to hash-check this block. JPCSP's equivalent
// branch only writes the mode word and zeroes the rest of that region.
header->ecdsa_hash = 0;

if (kirk_sceUtilsBufferCopyWithRange(kirk, outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
{
return -4;
}

return decryptSize;
}

int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)
{
// Every type below reads the tag at 0xD0, the size at 0xB0 and key data as far as 0x150, and
Expand Down Expand Up @@ -1070,6 +1187,13 @@ int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)

if (res >= 0)
return res;

return pspDecryptType6(&kirk, inbuf, outbuf, size);

res = pspDecryptType6(&kirk, inbuf, outbuf, size);

if (res >= 0)
return res;

// Last, because its header check is a subset of type 6's - a genuine type 6 PRX would pass it
// and then fail on the hash, so trying it earlier would shadow the real answer.
return pspDecryptType9(&kirk, inbuf, outbuf, size);
}
16 changes: 14 additions & 2 deletions Core/HLE/HLETables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -78,6 +79,7 @@
#include "sceUsbMic.h"
#include "sceUtility.h"
#include "sceVaudio.h"
#include "sceVshBridge.h"
#include "sceMt19937.h"
#include "sceSha256.h"
#include "sceAdler.h"
Expand Down Expand Up @@ -163,6 +165,14 @@ static const HLEFunction LoadCoreForKernel[] = {
{0XB95FA50D, nullptr, "LoadCoreForKernel_B95FA50D", '?', "" },
};


// sceKernelSm1ReferOperations() returns a pointer to a driver-registered "SM1 operations"
// table (set up via the sibling sceKernelSm1RegisterOperations(), also unimplemented here),
// or NULL if nothing has registered one.
static u32 sceKernelSm1ReferOperations() {
return hleLogDebug(Log::sceKernel, 0);
}

static const HLEFunction KDebugForKernel[] = {
{0XE7A3874D, nullptr, "sceKernelRegisterAssertHandler", '?', "" },
{0X2FF4E9F9, nullptr, "sceKernelAssert", '?', "" },
Expand All @@ -181,7 +191,7 @@ static const HLEFunction KDebugForKernel[] = {
{0X5282DD5E, nullptr, "sceKernelDipswSet", '?', "" },
{0X9F8703E4, nullptr, "sceKernelDipswCpTime", '?', "" },
{0X333DCEC7, nullptr, "sceKernelSm1RegisterOperations", '?', "" },
{0XE892D9A1, nullptr, "sceKernelSm1ReferOperations", '?', "" },
{0XE892D9A1, &WrapU_V<sceKernelSm1ReferOperations>, "sceKernelSm1ReferOperations", 'x', "" },
{0XA126F497, nullptr, "KDebugForKernel_A126F497", '?', "" },
{0XB7251823, nullptr, "sceKernelAcceptMbogoSig", '?', "" },
};
Expand Down Expand Up @@ -315,9 +325,11 @@ void RegisterAllModules() {
Register_sceImpose_driver();
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.
// Register_sceNpMatching2();
}

2 changes: 1 addition & 1 deletion Core/HLE/sceCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ static int sceCtrlGetIdleCancelThreshold(u32 idleResetPtr, u32 idleBackPtr)
return hleLogDebug(Log::sceCtrl, 0);
}

static int sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs)
int sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs)
{
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, false);
hleEatCycles(330);
Expand Down
3 changes: 3 additions & 0 deletions Core/HLE/sceCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ bool __CtrlGetRapidFire();

// For use by internal UI like MsgDialog
u32 __CtrlPeekButtons();

// Exposed so sceVshBridge can reuse it directly for vshCtrlReadBufferPositive, matching JPCSP.
int sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs);
u32 __CtrlPeekButtonsVisual(); // also incorporates rapid-fire
void __CtrlPeekAnalog(int stick, float *x, float *y);
u32 __CtrlReadLatch();
Expand Down
Loading
Loading
0