Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patches/PPU: Implement HLE/LLE/With-TOC function call patches #10859

Merged
merged 2 commits into from
Sep 26, 2021

Conversation

elad335
Copy link
Contributor

@elad335 elad335 commented Sep 11, 2021

This new patch type allows to insert function calls to exported functions and custom HLE functions. Not only this extends greatly the potential of functionality patches can do by itself by providing access to all PS3 firmware functions and custom PRX ones - you can register custom HLE functions in RPCS3 code with custom module name and use that in patches. In other words you can inject real C++ code into games! The downside of that is that you need to use a custom RPCS3 build which those functions exist in it, but @isJuhn had an idea a while ago that real DLL files can be used to inject such code without the need to use custom RPCS3 builds. So in the future we might see an "HLE" function loading DLL functions and injecting to games. Potential is basically endless here.

Ideas for such C++ patches for example:

  • Allow you to write code in a high level language which increases productivity x10. Access to standard library and other dependencies + logging and HLE things decrease headaches 10x
  • Allow access to host system which in turn can allow things like custom multiplayer implementations.
  • Due to complete RSX access, replace textures and shaders in real time.

Example patches:


 -  [ jumpf, 0x12340, "cellGcmSys:cellGcmSetFlip"] # Places a call to cellGcmSetFlip at 0x12340
 -  [ jumpf, 0x12340, "cellGcmSys:0xDC09357E"] # Same, using FNID

In addition, you can specify direct address of function OPD for calls with TOC by only specifying its addres, example:
Not to be confused with jumpl, even if changing R2 is not needed do not use it as jumpl.


    -  [ jumpf, 0x12340, 0x2345678 ] # Function OPD based call eading OPD at 0x2345678
  # -  [ jumpl, 0x12340, 0x2345678 ] # Places a direct call to an instruction at 0x2345678 with setting LR to CIA + 4. 

Notes:

  1. Function can be specified as either hexadecimal FNID (with '0x' prefix) or as raw string which the FNID will be generated from.
  2. The order of module/function is the opposite from what's used in our PPU disassembler by the debugger. Take that into account when making patches using the disassmbler information.
  3. You must always return to the caller with these patches in the right order so saved registers memory is cleaned. (unless thread execution is finished such as after sys_ppu_thread_exit)

@elad335 elad335 force-pushed the hle-patches branch 2 times, most recently from 32d92be to 975b0a8 Compare September 11, 2021 17:11
Utilities/bin_patch.cpp Outdated Show resolved Hide resolved
Utilities/bin_patch.cpp Outdated Show resolved Hide resolved
@isJuhn
Copy link
Contributor

isJuhn commented Sep 11, 2021

my personal opinion is that it should be module:function instead of the other way around

@elad335
Copy link
Contributor Author

elad335 commented Sep 11, 2021

Okay, note that this is the opposite from what's used in the PPU disassembler by the debugger. (was replaced so function name appears without widening view much)

@elad335 elad335 marked this pull request as draft September 11, 2021 17:54
@elad335 elad335 force-pushed the hle-patches branch 2 times, most recently from 34e12bd to 81e647d Compare September 11, 2021 18:30
@elad335
Copy link
Contributor Author

elad335 commented Sep 11, 2021

  • Made it no longer modify PPU LR and PPU R2, it now saves them at jump then sets LR to come back the original branch. Then with saved information restores registers and branches to CIA + 4 as if nothing happened.

@elad335 elad335 marked this pull request as ready for review September 11, 2021 18:32
@elad335 elad335 marked this pull request as draft September 13, 2021 18:01
@elad335 elad335 marked this pull request as ready for review September 18, 2021 07:34
@elad335
Copy link
Contributor Author

elad335 commented Sep 18, 2021

PR is ready.


if (all_info.return_and_restore)
{
// Save LR and R2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't you supposed to save them in PPU context of current thread?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@elad335 elad335 changed the title Patches/PPU: Implement HLE/LLE function call patches Patches/PPU: Implement HLE/LLE/With-TOC function call patches Sep 19, 2021
@elad335
Copy link
Contributor Author

elad335 commented Sep 19, 2021

Fresh from the oven, function calls with TOC:

You can specify direct address of function OPD for calls with TOC by only specifying its addres, example:
Not to be confused with jumpl, even if changing R2 is not needed do not use it as jumpl. See example in main decription.

Notes:

  1. Do not use 'jumpf' in direct recursion: target of the proceeding jumpf must be different only from it's first preceeding jumpf. This is because in order for R2 and LR to appear unchanged by this call LR is set to return to the function call patch address to restore R2/LR.
  2. You must always return to the caller with these patches in the right order so saved registers memory is cleaned.

@elad335 elad335 force-pushed the hle-patches branch 2 times, most recently from d514b36 to 54c1ad2 Compare September 19, 2021 17:18
@elad335 elad335 requested a review from Nekotekina September 19, 2021 17:18
if (ppu)
{
// This check checks if we need to either branch and save modified registers
// *** Notice how this check is not compatible with using the same call twice without any other in between! ***
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Can you elaborate on why call to next is handled in a special manner and what does this comment mean, that simple recursion is not allowed?

Copy link
Contributor Author

@elad335 elad335 Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion is not recommended but there are cases in which it's valid here such as if the HLE calls history stack looks like this:

  1. [caller CIA] jumpf funcA
  2. [funcA + 0x10] jumpf funcA // funcA + 0x10 != caller CIA (comparing 1.CIA and 2.CIA)
    // 3. [funcA + 0x10] jumpf funcA // Invalid, funcA + 0x10 == funcA + 0x10 (comparing 2.CIA and 3.CIA)
  3. [caller CIA] jumpf funcA // Same (comparing 2.CIA and 3.CIA)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using PPU stack with artificial call frames? It seems it could look more simple in the end, and easier to track the callstack.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a callstack, that's not the issue. Ok I think I need to reserve a special address for registers restoration callback, its address will be passed in LR. Using the same address for registers restoration was probably a mistake.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Example patches:
  [ jumpf, 0x12340, "cellGcmSys:cellGcmSetFlip"] // Places a call to cellGcmSetFlip at 0x12340
  [ jumpf, 0x12340, "cellGcmSys:0xDC09357E"] // Same, using FNID
  [ jumpf, 0x12340, 0x2345678 ] # Function OPD based call eading OPD at 0x2345678
@Nekotekina Nekotekina merged commit 65c9cd9 into RPCS3:master Sep 26, 2021
@elad335 elad335 deleted the hle-patches branch September 19, 2022 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants