Please note that you are required to have a exploited PlayStation 4 console to run the patches mentioned in this article.
I recently saw a video from Digital Foundry where they covered a Modded Nintendo Switch running the Witcher 3 at up to 60FPS. Albeit with compermise of course. And the fact that no one up to this point has ported the patch to PlayStation 4 it’s my time to shine!
Part 1 - Resolution and Framerate Unlocking
Let’s get this out of the way first, since it’s all basic stuff by this point for those following my blog for the last few months.
LAB_01e88385 XREF: 01e88250(j) 01e883ad b9 80 07 MOV ECX,0x780 ; 1920 00 00 01e883b2 41 b8 38 MOV R8D,0x438 ; 1080 04 00 00
Base console resolution setup.
01e8823c e8 7f 7d CALL sceKernelIsNeoMode fb 00 01e8824e 84 c0 TEST AL,AL 01e88250 0f 84 2f JZ LAB_01e88385 01 00 00 ... 01e8828b b9 80 07 MOV ECX,0x780 ; 1920 00 00 01e88290 41 b8 70 MOV R8D,0x870 ; 2160 08 00 00
PS4 Pro resolution setup.
A simple change to 1280x720 on Base does the trick nicely, although I have not tested much of the game. So issues may crop up.
You may be wondering why PS4 Pro is using 1920x2160 for its back buffer resolutio. It’s likely for Checkerboarding, halving it’s Horizontal resolution and keeping Vertical resolution native.
Framerate? Same story.
0227361c be 01 00 MOV ESI,0x1 00 00 02273621 e8 7a e2 CALL sceVideoOutSetFlipRate bc 00
MOV ESI with 0x0 gives us an unlocked framerate with triple buffered VSync.
Part 2 - Additional Graphics Options and Framerate Stats
A few things I noticed that is, there’s native In-Game Frame Statistics and additional Graphics Options.
FPS String search comes up with.. no results but in Unicode, it does.
u_FPS:_%1.3f_(longest_frame:_%1.3f_030141b4 XREF: FUN_01f1a860:01f1ab0f(*) 030141b4 46 00 50 unicode u"FPS: %1.3f (longest frame: %1.3f ms) VSync: 00 53 00 3a 00 20 ... 01f1aa4a 41 80 bd CMP byte ptr [R13 + 0xb319],0x0 19 b3 00 00 00 01f1aa55 0f 84 33 JZ LAB_01f1ab8e 01 00 00 ... 01f1aab4 eb 3c JMP LAB_01f1aaf2 ... LAB_01f1aaf2 XREF: 01f1aab4(j) 01f1aaf2 48 8d 05 LEA RAX,[DAT_03b21fe0] e7 74 c0 01 01f1ab0f 48 8d 35 LEA RSI,[u_FPS:_%1.3f_(longest_frame:_%1.3f_030141 9e 96 0f 01
A simple change from
Jump Zero to
Jump not Zero gives us framerate stats.
What about Graphics Options? A simple drop in of the
rendering.xml file from GBAtemp Switch Modding Section gives us Grahpical Options seen in various Witcher 3 Switch Modded Videos.
Part 3 - Experimental Graphics Patches through Executable Patching
This is mostly my own findings before I discovered the modified XML file described above.
I started toggling the motion blur option found in the settings menu and landed at
0x3b21e89 memory address.
DAT_03b21e89 XREF: FUN_015b53c0:015b74b0(*), FUN_015b53c0:015b74b7(*), FUN_015b53c0:015b74ca(W), FUN_01f61d80:01f62344(R) 03b21e89 00 undefined1 00h
A read and write reference, hmm.
015b7489 4c 8d 25 LEA R12,[s_PostProcess_02ee8903] 73 14 93 01 015b7490 48 8d 15 LEA RDX,[s_AllowMotionBlur_02ee89cd] 36 15 93 01 ... 015b74ca c6 43 29 01 MOV byte ptr [RBX + 0x29]=>DAT_03b21e89,0x1
How curious, A text ref next to the actual byte. At least it makes my life easier.
What about the read?
01f62344 44 0f b6 MOVZX R15D,byte ptr [RSI + 0x29]=>DAT_03b21e89 7e 29
It reads from
RSI + 0x29 to get the final address in memory.
As a test,
R15W permanently disables motion blur.
Completely pointless but hey, at least we know how the RED Engine lays out it’s graphics settings in the executable.
Thanks to the patrons who supported me on various platforms! You guys are awesome!
- Jeff Eberlin