hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
11.02k stars 2.15k forks source link

Killzone Liberation DLC crash #12343

Open Levan7 opened 4 years ago

Levan7 commented 4 years ago

Using PPSSPP v1.8.0-630-g5a53570b3 build 64 bit

I downloaded the dlc from here https://www.killzone.com/fr_CA/blog/news/2011-06-06_kzl-welcome-back.html

The game crashes after game developer logos. I even tried taking out data from my psp 1000 and punting it in ppsspp same thing happened it crashed at the same point.

DebugLog.txt InfoLog.txt

kz

LunaMoo commented 4 years ago

As far as I recall Killzone Liberation DLC uses some weird and unique to this game "DLC installation", it also might be encrypted in a way which will always require real PSP. Either way it's known to not work on PPSSPP, just as it doesn't work on other emulators(including official Sony's ones) and this will never change until some fan of it figures out how to make it work.

Most likely:

Sanaki commented 4 years ago

I've been poking at this recently, while I don't have a solution and doubt an easy one exists, I can verify that if encryption is used at all, it's not the standard sort, as npdecrypter doesn't see anything to attempt decryption on. Based on the error output, it seems to be a kernel incompatibility. But yeah, unfortunately with the likely difficulty of a fix and the relatively low usefulness, I'm not expecting anything to come of this.

Error log 59:41:272 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2353 0=sceKernelTerminateThread(277) 59:41:272 user_main W[SCEKERNEL]: HLE/sceKernelThread.cpp:3610 sceKernelRegisterExitCallback(0): invalid callback id 59:41:272 user_main I[SCEMODULE]: HLE/sceKernelModule.cpp:1916 sceKernelStartModule(0,asize=0000000b,aptr=09f0ce20,retptr=09fff510,00000000): error 8002012e 59:41:272 user_main E[SCEMODULE]: HLE/sceKernelModule.cpp:2169 UNIMPL sceKernelStopUnloadSelfModuleWithStatus(00000001, 00000000, 00000000, 00000000, 00000000): game has likely crashed 59:41:272 user_main E[JIT]: x86/CompBranch.cpp:606 Jump to invalid address: 00000000 PC 09f00420 LR 09f00420 59:41:273 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2004 284=sceKernelCreateThread(CheckExitGame, 09f03264, 00000020, 2048, 00000000, 00000000) 59:41:273 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2095 0=sceKernelStartThread(284, 0, 00000000) 59:41:752 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2004 290=sceKernelCreateThread(Thread for LoadModule, 09f01994, 0000006f, 2048, 00000000, 00000000) 59:41:752 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2095 0=sceKernelStartThread(290, 32, 09f0cd0c) 59:41:752 Thread for L E[SCEMODULE]: HLE/sceKernelModule.cpp:2346 UNIMPL 0=sceKernelLoadModuleDNAS() 59:41:752 Thread for L I[SCEKERNEL]: HLE/sceKernelThread.cpp:2150 sceKernelExitThread(0) 59:42:246 user_main I[SCEKERNEL]: HLE/sceKernelThread.cpp:2353 0=sceKernelTerminateThread(284) 59:42:247 user_main W[SCEKERNEL]: HLE/sceKernelThread.cpp:3610 sceKernelRegisterExitCallback(0): invalid callback id 59:42:247 user_main I[SCEMODULE]: HLE/sceKernelModule.cpp:1916 sceKernelStartModule(0,asize=0000000b,aptr=09f0ce20,retptr=09fff510,00000000): error 8002012e 59:42:247 user_main E[MEMMAP]: Core/MemMapFunctions.cpp:56 Unknown GetPointer deadbeef PC deadbeef LR 09f0a1c4
unknownbrackets commented 4 years ago

8002012e means "module not found". sceKernelStartModule(0 is weird, because it's trying to start module ID = 0.

Possibly it's because this function simply returns 0: https://github.com/hrydgard/ppsspp/blob/29950c0ad5c04df091a298e8ee727dc54c4f79db/Core/HLE/sceKernelModule.cpp#L2346

I don't know what the arguments are (maybe the placeholder in the code is correct) or how it's supposed to be used, though. JPCSP accepts more args but still returns 0:

https://github.com/jpcsp/jpcsp/blob/bced50f31d911cc5059251c40f022bc235dc0685/src/jpcsp/HLE/modules/ModuleMgrForUser.java#L1080

If you want to debug this further, the thing to figure out is where the 0 passed to the first sceKernelStartModule call that fails is coming from (via looking at the disassembly.) It could be a race condition (maybe some other thread is supposed to fill that field) as well.

-[Unknown]

Linblow commented 1 year ago

Killzone's patch is a two-layers file created from the PSP install utility API (uses the psheet driver under the hood). The first layer is a PGD file which uses a private key that is unique to the PSP it was created from. When decrypted, appears the second layer, the type 3 PRX that is encrypted using a private key that is also unique to each PSP.

There is currently no way to extract those two private and unique keys (at least, for the average user). Therefore, the only way to decrypt this kind of patch file is with the PSP it was created and installed to. I did decrypt it and retreived the original plain PRX file.

I made an updated Killzone: Liberation ISO for both the EU and US versions (see change log below). It doesn't exactly fix this thread's issue, but at least people can play the latest version + DLC with PPSSPP/PSP.

Regarding a DRM BB install package (the patch EBOOT.PBP that the PSP install utility API requires): I fully reversed its structure and know how to create and install one from scratch, but there's a missing component which prevents me from creating a small part of the "authored" type 3 PRX (which gets embedded in the final package). This small part is the input data for the kirk 2 command. Kirk 2 checks the intregity of the input data, re-encrypts it, and re-signs it. All the keys in that process are unknown, and sadly, it appears we cannot dump them. There may be a way to forge the authored type 3 PRX in such a way that the input data remains the same and valid for different PRX contents, I haven't tested yet.

I'll eventually make a PR that adds the PSP install utility API, the psheet driver, and implements sceKernelLoadModuleDNAS. Then we'll be able to install DRM BB install packages, and load this kind of patch. Unless kirk 2 is fully reversed (very unlikely), then the installed files will only be loadable by the emulator (ie. invalid for the PSP). Better than nothing though! Stay tuned.

Edit: for the updated game, ask me for the link in Discord.

KZL Change Log

2022-09-28

Added

Changed

Fixed

LunaMoo commented 1 year ago

In regard to #12344 since you linked this there, do you mean it would work on game updates as well? Or only mentioned it there since side loading of decrypted files would not do anything to help in this case?

Edit: I updated your post and removed the link. Please don't link to any sites which include warez. Edit2: I thought the link I removed looked suspiciously familiar, @hrydgard are you ok with PPSSPP default adhoc server being as it is now if it's subdomain is hosting warez files?

hrydgard commented 1 year ago

Hm, not too happy about that no :(.

And with regards to the modified ISO that includes the game DLC, what we need is some tool that can combine the DLC and the ISO, not the actual ISO itself because of the obvious copyright issue.

Linblow commented 1 year ago

It's not a warez hosting subdomain. Originally, there was only a patched ISO for SOCOM FTB 2/1 (ie. the most played PSP infrastructure game). Then some players crashed using the patched ISO with the PSP, so I put the original ISO for convenience since everyone had the game anyway. The SOCOM patched ISO is deprecated. Both the patched and original ISO will be removed when I release my (external) patch for the game.

As for Killzone, there is currently no other way to play the DLC + latest patch on emulators (and Vita). than to use this updated ISO. It's faster, and easier, to provide an updated ISO than a tool that patches a user's original game dump. Copyright wise, I agree a tool is the best option. Until I take the time to make a proper tool, I'll keep the updated ISOs. Now, if that's really an issue for PPSSPP (ethics wise), I can move these files to a completely different and unrelated domain than *.socom.cc

Regarding the game updates, the PSP provides two mechanisms:

  1. DRM BB install packages. This is an EBOOT.PBP archive file that contains file(s) to install to the MemoryStick. Each file in the archive is encrypted, and decrypted on the fly during the install process. The install process for each file depends on its name extension (case-sensitive):

    1. *.PRX program file: This is the updated game module. The module MUST be an "authored" type 3 PRX with decrypt mode set to 18 or 19. Part of the PRX ~PSP header will be encrypted and signed with kirk2, thus tying the module to this specific PSP only. The whole PRX will then be encrypted (again) as a protected PGD file. Uses the DRM key 2 as the vkey to compute the PGD headerMac80.
    2. EBOOT.PBP system file: This is the non-bootable informative package for the XMB. It MUST exist. The function will return failure otherwise, even when all the other files have been successfully installed. The data will be written as is to the MemoryStick (ie. not encrypted). The file is written as _TEMP.PBP. It will be renamed to EBOOT.PBP before the function returns.
    3. Normal file (game data): This is game specific data to protect. The data will be encrypted back as a protected PGD file. Uses the DRM key 1 as the vkey to compute the PGD headerMac80.

    In both cases (1) and (3), the created PGD file is specific to this PSP device only (DNAS). It cannot be decrypted with another device. It's the game's responsibility to check whether a patch (PRX) was installed, and to load it with sceKernelLoadModuleDNAS, or fallback to loading the default game module. Despite being more secure, this API was deprecated in favour of the second mechanism decribed below.

  2. Patch package (PBOOT.PBP) Unlike a DRM BB install package, this only needs to be copied to PSP/GAME/<game_id> to work. The patch package contains the updated game's boot module to run upon booting the game. It's also encrypted with known and shared private keys (ie. any PSP/emu can decrypt it). When VSH boots a game, it checks for the existence of a PSP/GAME/<game_id>/PBOOT.PBP file. It then proceeds to verify whether the patch is newer than the game's version, and if so, decrypt the updated game boot module, and run it instead of the game's default EBOOT.BIN. Therefore, this mechanism is 100% handled by the PSP.

We can quite easily implement these two mechanisms in PPSSPP, especially the second one since we don't need to reinstall a patch (just copy from PSP and paste to PPSSPP memstick). I'll PR for the 1st mechanism in due time, and will probably do the 2nd one afterwards.

hrydgard commented 1 year ago

I understand the reasoning that providing the ISO is more convenient and interested people already have it, but given the pretty high profile of the PPSSPP project, a bit of strictness with a domain we link to prominently like that is the only sensible option, I know you understand, even if it's annoying.

Thanks for the overview of the game update methods, that's great info and sounds promising.

Linblow commented 1 year ago

Alright, I'll move everything to a seperate unrelated domain

Linblow commented 1 year ago

Done, I moved them to my personal domain

hrydgard commented 1 year ago

Thanks!

LunaMoo commented 1 year ago

Patch package (...) encrypted with known and shared private keys

If that's true, then real PSP will become obsolete for most people as that was the last thing we really had to use it for, last time I talked with someone about it required keys for standard updates were still unknown and we don't have them in PPSSPP.

Linblow commented 1 year ago

This is the function that decrypts the encrypted module within a (retail) PBOOT.PBP archive: kernel func I didn't check if the tags/keys used in this function are present in PPSSPP/prxDecrypter, but everything's can be found in mesg_led.prx. The PRX type can be 10 (tag 2E5E90F0), 7 (tag 2E5E80F0), or 5 (tag 2E5E11F0 or 2E5E10F0). Edit: only the tag 2E5E10F0 is currently present in PrxDecrypter.cpp