Editing PSP Emulation

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
== Official games ==
=== PSP games available on PS4 PS Store ===
<pre>
Jeanne d'Arc (2006) UP9000-CUSA41018_00-UCUS987000000000 (PS5: UP9000-PPSA13995_00-UCUS987000000000) 2024-07-16
Ratchet & Clank: Size Matters (2007) UP9000-CUSA41395_00-UCUS986330000000 (PS5: UP9000-PPSA14431_00-UCUS986330000000) 2024-07-16 PS4 11.50
LEGO Star Wars II: The Original Trilogy UP1082-CUSA41250_00-ULUS101550000000 or EP1006-CUSA41251_00-ULES004790000000 (PS5: UP1082-PPSA14300_00-ULUS101550000000 or UP1082-PPSA14300_00-0804842924824650) 2024-06-18 patch 1.01 requires PS4 11.50 or PS5 9.20
GODS EATER BURST PS4® & PS5® (PS5: UP0700-PPSA07715_00-GODEATERBURST000 or JP0700-PPSA07713_00-GODEATERBURST000) 2024-03-19
Daxter UP9000-CUSA36097_00-NPUG803290000000 (PS5: UP9000-PPSA09695_00-NPUG803290000000) 2024-06-18 patch 1.01 requires PS4 11.50 or PS5 9.20
Jak and Daxter: The Lost Frontier UP9000-CUSA41282_00-NPUG803300000000 (PS5: UP9000-PPSA14325_00-NPUG803300000000) 2024-03-19 patch 1.02 requires PS4 11.50 or PS5 9.00
Thrillville EP1006-CUSA41330_00-ULES006460000000 or UP1082-CUSA41329_00-ULUS101910000000 (PS5: UP1082-PPSA14358_00-0724668029168071) 2023-12-19
Thrillville: Off the Rails (PS5: UP1082-PPSA14360_00-0645898243839752) 2023-12-19
Tekken 6 PS4® & PS5® UP0700-CUSA33754_00-TEKKEN6000000000 or JP0700-CUSA33752_00-TEKKEN6000000000 (PS5: UP0700-PPSA07707_00-ULUS104660000000) 2023-10-17
Soulcalibur: Broken Destiny PS4® & PS5® UP0700-CUSA33758_00-SOULCALIBURBD000 or JP0700-CUSA33756_00-SOULCALIBURBD000 2023-10-17
Disney•Pixar Up UP1082-CUSA41345_00-0227660722516578 2023-11-21
MediEvil Resurrection™ UP9000-CUSA33589_00-UCUS986200000000 2023-08-15
Ridge Racer 2 PS4 & PS5 UP0700-CUSA33740_00-RIDGERACER200000 or JP0700-CUSA33738_00-RIDGERACER200000 2022-12-20
Gravity Crash Portable UP9000-CUSA40479_00-NPUG803210000000 or JP9000-CUSA40480_00-NPJG000440000000 2023-07-18
Killzone: Liberation (2006) EP9000-CUSA37875_00-UCES002790000000 or UP9000-CUSA37874_00-UCUS986460000000 (PS5: UP9000-PPSA11141_00-UCUS986460000000) 2023-06-20 PS5 7.40
Pursuit Force (2005) UP9000-CUSA37191_00-UCUS986400000000 or EP9000-CUSA37192_00-UCES000190000000 or JP9000-CUSA37932_00-ULJM050970000000 or HP9000-CUSA37193_00-UCKS450160000000 (PS5: UP9000-PPSA10609_00-UCUS986400000000) 2023-05-16
Pursuit Force: Extreme Justice UP9000-CUSA34853_00-UCUS987030000000 (PS5: UP9000-PPSA08696_00-UCUS987030000000) 2023-08-15
Blade Dancer: Lineage of Light UP9000-CUSA37870_00-ULUS101240000000 or JP9000-CUSA37872_00-UCJS100210000000 2023-05-16
Pinball Heroes UP9000-CUSA33617_00-0000000000000000 2022-12-20
Disney•Pixar Toy Story 3 UP1082-CUSA33343_00-4838282977086414 2022-09-20
Kingdom of Paradise UP9000-CUSA33573_00-UCUS986230000000 or JP9000-CUSA33575_00-UCJS100100000000 or HP9000-CUSA34893_00-UCAS400230000000 2022-09-20
No Heroes Allowed! UP9000-CUSA33595_00-NPUG804600000000 2022-07-19
LocoRoco Midnight Carnival UP9000-CUSA32639_00-0000000000000000 or JP9000-CUSA32641_00-0000000000000000 2022-07-19
Ape Escape: On the Loose UP9000-CUSA37860_00-UCUS986090000000 or EP9000-CUSA37861_00-UCES000450000000 or JP9000-CUSA37862_00-UCJS100040000000 2023-08-15 PS4 10.70
Ape Escape Academy UP9000-CUSA33020_00-UCUS986190000000 or JP9000-CUSA33022_00-UCJS100030000000 2023-10-17
Ape Academy 2 UP9000-CUSA37900_00-UCES003020000000 or JP9000-CUSA37866_00-UCJS100200000000 2023-03-21
Secret Agent Clank UP9000-CUSA41276_00-UCUS986970000000 (PS5: UP9000-PPSA14319_00-UCUS986970000000) 2024-09-17
Syphon Filter: Logan's Shadow (2007) EP9000-CUSA32631_00-UCES007100000000 or UP9000-CUSA32630_00-UCUS986060000000 (PS5: UP9000-PPSA06782_00-UCUS986060000000) 2023-05-16 PS5 9.00
Syphon Filter: Dark Mirror UP9000-CUSA32633_00-UCUS986410000000 2023-03-21
echochrome UP9000-CUSA32644_00-NPUG801350000000 or JP9000-CUSA32646_00-UCJS100810000000 2022-06-13
Super Stardust Portable (2007) EP9000-CUSA33036_00-NPEG000080000000 or UP9000-CUSA33035_00-NPUG802210000000 or JP9000-CUSA33037_00-NPJG000130000000 (PS5: UP9000-PPSA07135_00-NPUG802210000000 or EP9000-PPSA07136_00-NPEG000080000000) 2022-06-13
echoshift UP9000-CUSA33585_00-NPUG803030000000 or JP9000-CUSA33587_00-UCJS100960000000 2022-07-19
Resistance: Retribution (2009) EP9000-CUSA32637_00-UCES011840000000 or UP9000-CUSA32636_00-UCUS986680000000 (PS5: EP9000-PPSA06789_00-UCES011840000000 or UP9000-PPSA06788_00-UCUS986680000000 or JP9000-PPSA06790_00-UCJS100900000000) 2024-02-20
勇者のくせになまいきだ:3D (What Did I Do to Deserve This, My Lord? 3D) JP9000-CUSA33597_00-UCJS101090000000 2022-07-19
Coded Soul JP9000-CUSA33571_00-UCJS100610000000 or HP9000-CUSA34502_00-UCAS401800000000 2023-06-20
Ore no Shikabane o Koete Yuke (PS5: JP9000-PPSA09382_00-UCJS101170000000) 2024-04-16
</pre>
=== PSP remaster games available on PS4 PS Store ===
* LocoRoco™ Remastered UP9000-CUSA06090_00-UCUS986620000001 2017-05-09
* LocoRoco™ 2 Remastered UP9000-CUSA06091_00-UCUS987310000001 2017-12-09
* LUMINES REMASTERED UP0751-CUSA11624_00-LUMINESREMASTERE or JP1049-CUSA11673_00-LUMINESREMASTERE 2018-07-10
* Patapon™ Remastered UP9000-CUSA06171_00-UCUS987110000001 2017-08-01
* Patapon 2 Remastered UP9000-CUSA07321_00-UCES011770000001 2020-01-30
* Metal Slug Double X JP0576-CUSA11717_00-METALSLUGXX00001 2018-05-30
* PaRappa The Rapper™ Remastered UP9000-CUSA05289_00-UCUS987020000001 2017-04-04
=='''PSPHD'''==
=='''PSPHD'''==
 
The new ps plus psp emulator has a lot of undiscovered functionalities. It even allows patches directly to the emulated Allegrex cpu.
The PSP emulator for PlayStation 4 includes plenty of undiscovered functionalities. It even allows patches directly to the emulated Allegrex CPU. Not many CLI commands were added this time around. Very few commands have a description to their usage inside of the eboot.bin, everything else is just guesswork from the scene. Plenty of Lua commands need to be understood before the compatibility of games can improve. The PSP emulator has not gained the same popularity in the scene as the PS2 emulator due to the existence of an unofficial PPSSPP core in the unofficial Retroarch port for hacked PS4. As far as the compatibility and performance go, the Retroarch core is yet to be bested. This official emulator may hold potential, but the potential can only go so far as it seems not to have support for gamedata installation, which in turn will render many games unplayable.
Sadly sony has not made it easy for users to use CLI commands. Since sony mostly uses lua patches for the psp releases, not many cli commands were added. Very few commands have a description to their usage inside of the eboot.bin. Everything else is just guesswork from the scene. The psp emulator has not gained the same popularity as the ps2 emulator because currently, there is an unofficial PPSSPP core in the unofficial retroarch port for the ps4. and as far as the compatibility and performance goes, the retroarch core is second to no one. This emulator may still hold potential, though sadly it does not seem to have support for gamedata installation. and that has led to many games becoming currently unusable. with an official retroarch release coming into ps4's way it seems delving deeper into the PSPHD emulator and the PS1's new psplus emulator is pretty useless.


== Commands ==
== Commands ==
'''Known functions:''' Require cleanup.
'''Known functions:''' Require cleanup.
 
<br>The rest of the cli and lua commands can all be found inside of an emu's decrypted '''eboot.bin'''.
<br>The rest of the CLI and Lua commands can all be found inside of any PSP emulator's decrypted '''eboot.bin'''.
=== config-emu-ps4.txt commands ===
 
''General purpose CLI commands, or unknown usage''
=== CLI commands ===
These commands can be added to any of these files:
* '''config-title.txt'''
* '''package-ps4.conf'''
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Command !! Values !! Notes !! Usage  
! Command !! Values !! Notes !! Usage  
Line 74: Line 16:
|-
|-
| --notrophies || || Enable/disable trophies||  
| --notrophies || || Enable/disable trophies||  
|-
| --ps4-trophies  || || ||
|-
|-
| --locale || || ||
| --locale || || ||
Line 85: Line 25:
| --addon || || ||
| --addon || || ||
|-
|-
| --host || Sets host directory || --host="/hostapp/" ||
| --host || || Sets host directory || --host="/hostapp/"
|-
|-
| --loglevel || none, all, warn, info, error, debug, trace || debug logging ||
| --loglevel || none, all, warn, info, error, debug, trace || debug logging  
|-
|-
| --xobuttonmode || oenter, ocancel || Switcher between x and circle button, made specifically for japanese gamers ||
| --xobuttonmode || oenter, ocancel || Switcher between x and circle button, made specifically for japanese gamers  
|-
|-
| --lang || Including but not limited to "en" "jp" "fr" "it"  || Language selector || --lang="en"
| --lang || Including but not limited to "en" "jp" "fr" "it"  || Language selector || --lang="en"
Line 100: Line 40:
|-
|-
| --samplesave || ? || ? ||
| --samplesave || ? || ? ||
|-
| --vramcopyback || 0, 10000000 || for games that download data from GPU to Allegrex || --vramcopyback=45
|-
| --msxxadhoc || true?, false? || ad hoc support ? ||
|-style="background-color:#ff99c2"
|-style="background-color:#ff99c2"
| || Graphical fixes || ||
| || Graphical fixes || ||
|-
| --parappareplacecolor || The command expects 8 Hex values || (rgb?) ||
|-
|-
| --antialias || off, MSAA4x, SSAA4x|| Anti-aliasing options || --antialias=off
| --antialias || off, MSAA4x, SSAA4x|| Anti-aliasing options || --antialias=off
|-
| --clamp-line-thickness-min || ? || ? ||
|-
| --clamp-line-thickness-max || ? || ? ||
|-
|-
| --texcachemode || patchworkheroes drawbounds, drawboundsloco, patchworkheroes, locoroco2, rondo, full || for issues with texture cache (modes lower than full possibly read some textures directly without cache). || --texcachemode=patchworkheroes
| --texcachemode || patchworkheroes drawbounds, drawboundsloco, patchworkheroes, locoroco2, rondo, full || for issues with texture cache (modes lower than full possibly read some textures directly without cache). || --texcachemode=patchworkheroes
Line 113: Line 63:
| --depthscalehack || true?, false? || ||--depthscalehack=true
| --depthscalehack || true?, false? || ||--depthscalehack=true
|-
|-
| --depthscalehack || true?, false? || ||--depthscalehack=true
| --texloadcores || 0, 100 || textures to load || texloadcores=2
|-
|-
| --locorocomeshsmooth || true, false || Custom mesh smoothing for loco roco games(?)|| --locorocomeshsmooth=true
| --smoothlevel || 0, 100 || Mesh smoothing level? || --smoothlevel=0
|-
|-
| --locorocomeshsmoothnonindexed || true, false || Turns "locorocomeshsmooth" mesh smoothing into non-indexed(?) ||--locorocomeshsmoothnonindexed=true
| --anisolevel || 0, 100 || Anisotropic filtering level?? ||
|-
|-
| --forcenobilinear || true, false || Turn bilinear filtering on/off, setting it to True will fix many graphical glitches in games that use 2D Images ||--forcenobilinear=true
| --parappajapanesefonthack || true?, false? || Enables Support For Japanese Fonts ??|| --parappajapanesefonthack=true
|-style="background-color:#D7EF54"
|  || Game fixes || ||
|-
|-
| --godofwarhack || true, false || Likely a performance patch for games that go way above the fps cap. Managed to help '''God Of War - Ghost Of Sparta''' skip intro freeze. it could possibly be used as a speedhack.  [https://github.com/hrydgard/ppsspp/pull/15640 Might be this?]|| --godofwarhack=true
| --depthscalehack || true?, false? || ||--depthscalehack=true
|-style="background-color:#03fcc2"
|  || No effect / unknown values || ||
|-
|-
| --texloadcores || 0, 100 || textures to load || texloadcores=2
| --locorocomeshsmooth || true, false || Custom mesh smoothing for loco roco games|| --locorocomeshsmooth=true
|-
|-
| --smoothlevel || 0, 100 || Mesh smoothing level? || --smoothlevel=0
| --locorocomeshsmoothnonindexed || true, false || Non-indexed mesh smoothing ||--locorocomeshsmoothnonindexed=true
|-
|-
| --anisolevel || 0, 100 || Anisotropic filtering level?? ||
| --forcenobilinear || true, false || Turn bilinear filtering on/off, setting it to True will fix many graphical glitches in games that use 2D Images ||--forcenobilinear=true
|-style="background-color:#D7EF54"
|  || Game fixes || ||
|-
|-
| --parappajapanesefonthack || true?, false? || Enables Support For Japanese Fonts ??|| --parappajapanesefonthack=true
| --umddelay || ? || Seems to be I/O timing method, Some games need a delay to work properly. [https://github.com/hrydgard/ppsspp/issues/7647 More here]  ||
|-
|-
| --clamp-line-thickness-min || ? || ? ||
| --godofwarhack || true?, false? || Seems specifically made for god of war, unknown effect || --godofwarhack=true
|-
|-
| --clamp-line-thickness-max || ? || ? ||
| --parappaalphahack || true?, false? || || --parappaalphahack=true
|-
|-
| --parappareplacecolor || The command expects 8 Hex values || (rgb?) ||
|  || Speedhacks || ||
|-
| --msxxadhoc || true?, false? || ad hoc support ? ||
|-
| --parappaalphahack || true?, false? || Doesn't seem to have any effect.|| --parappaalphahack=true
|-
| --umddelay || ? || Seems to be I/O timing method. Doesn't seem to have any effect  ||
|-
| --vramcopyback || 0, 10000000 || for games that download data from GPU to Allegrex || --vramcopyback=45
|-
|-style="background-color:#7698FF"
|  || Speedhacks / Possible duplicates|| ||
|-
|-
| --antialias || off || Turning Anti-Alias Off Improves Performance||--antialias=off
| --antialias || off || Turning Anti-Alias Off Improves Performance||--antialias=off
Line 166: Line 103:
| --anisolevel || 0, 100 || Anisotropic filtering level?? ||
| --anisolevel || 0, 100 || Anisotropic filtering level?? ||
|-
|-
| --present || vblankstart, setframebuf, drawsync|| set when frame is presented. Sync issues, flickering screen, tearing, input lag, etc. Doesn't seem to have any effect. ||--present=setframebuf
| --present || vblankstart, setframebuf, drawsync|| set when frame is presented. Sync issues, flickering screen, tearing, input lag, etc. ||--present=setframebuf
|-
|-
| --texrecent || true || Optimize texture hashes ||--texrecent=true
| --texrecent || true || Optimize texture hashes ||--texrecent=true
|}
|}
====Syphon Filter Dark Mirror====
 
====Texture replacement====
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Command !! Values !! Notes !! Usage   
! Command !! Values !! Notes !! Usage   
|-
|-
| --force-native-aspect-ratio || || ||
| --texswitch||true, false|| Enables Texture replacement || --texswitch=true
|-
|-
| --use-higher-precision-depth || || ||
| --texsave || || ||
|-
|-
| --optimize-fb-self-resolves || || ||
| --texmissingsave || || ||
|-
|-
| --force-dsf-present || || ||
| --autoresampler || true, false|| Turns on the auto-resampler. Assumes textures in texreplace are at 8x resolution and resamples them at load, May only work on new LocoRoco Midnight Carnival emu || --autoresampler=true
|-
| --bend-30hz-lock|| || ||
|-
| --setframebuf-auto-vblank-wait-threshold|| || ||
|-
| --gpu-renderthread|| || ||
|-
| --force-triangle-clip-off|| || ||
|-
| --hack-use-sku-vms|| || ||
|-
| --active-sku || || ||
|-
| --psp-right-stick-action || 0,1 || ||--psp-right-stick-action=1
|-
| --psp-right-stick-deadzone-x || || ||--psp-right-stick-deadzone-x=15
|-
| --psp-right-stick-deadzone-y || || ||--psp-right-stick-deadzone-y=15
|-
| --psp-right-stick-deadzone-semicircle-arc || || ||--psp-right-stick-deadzone-semicircle-arc=40
|-
|}
 
====Texture replacement====
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Command !! Values !! Notes !! Usage 
|-
| --texswitch||true, false|| Enables Texture replacement || --texswitch=true
|-
| --texsave || || ||
|-
| --texmissingsave || || ||
|-
| --autoresampler || true, false|| Turns on the auto-resampler. Assumes textures in texreplace are at 8x resolution and resamples them at load, May only work on new LocoRoco Midnight Carnival emu || --autoresampler=true
|-
|-
| --texreplace || Directory || Set directory of texture replacement folder || --texreplace="host0:texreplace"
| --texreplace || Directory || Set directory of texture replacement folder || --texreplace="host0:texreplace"
Line 225: Line 129:


===XXXXYYYYY_patches.lua===
===XXXXYYYYY_patches.lua===
The lua can be placed as: '''scripts\XXXXYYYYY_patches.lua'''  
Your lua can be placed as '''scripts\XXXXYYYYY_patches.lua'''  
<br>'''Requires Cleanup'''.


====Emulator commands====
====Emulator commands====
Line 233: Line 138:
|getEmuObject || '''local emuObj = getEmuObject()''' || Required for all functions using emuObj
|getEmuObject || '''local emuObj = getEmuObject()''' || Required for all functions using emuObj
|-
|-
|LoadSlideshow ||emuObj.LoadSlideshow()||
| AddVsyncHook ||emuObj.AddVsyncHook()|| Set function to be done on every vsync
|-
| RemoveVsyncHook ||emuObj.RemoveVsyncHook()|| Remove vsynchook
|-
| AddBootHook ||emuObj.AddBootHook()|| Set function to be done when the game boots up
|-
|RemoveBootHook||emuObj.RemoveBootHook()|| remove function to be done when the game boots up
|-
|LoadSlideshow ||emuObj.LoadSlideshow()||
|-
|-
|StartSlideshow ||emuObj.StartSlideshow()||
|StartSlideshow ||emuObj.StartSlideshow()||
Line 259: Line 172:
| SaveState ||emuObj.SaveState()||  
| SaveState ||emuObj.SaveState()||  
|-
|-
| SetFDExtraDelay ||emuObj.SetFDExtraDelay()|| 0? 1?
| SetFDExtraDelay ||emuObj.SetFDExtraDelay()||
|-
|-
| MeshSmooth ||emuObj.MeshSmooth()||
| MeshSmooth ||emuObj.MeshSmooth()||
Line 292: Line 205:
|-
|-
| PlayVideo||emuObj.PlayVideo()||
| PlayVideo||emuObj.PlayVideo()||
|-
| AddGPUHook ||emuObj.AddGPUHook()||
|-
|-
| RescaleUForUpscale ||emuObj.RescaleUForUpscale()||
| RescaleUForUpscale ||emuObj.RescaleUForUpscale()||
Line 328: Line 243:
|-
|-
| CopyFB || emuObj.CopyFB() ||
| CopyFB || emuObj.CopyFB() ||
|-style="background-color:#c6ecd9"
| Hooks  || ||
|-
| AddVsyncHook ||emuObj.AddVsyncHook()|| Set function to be done on every vsync
|-
| RemoveVsyncHook ||emuObj.RemoveVsyncHook()|| Remove vsynchook
|-
| AddBootHook ||emuObj.AddBootHook()|| Set function to be done when the game boots up
|-
|RemoveBootHook||emuObj.RemoveBootHook()|| remove function to be done when the game boots up
|-
| AddGPUHook ||emuObj.AddGPUHook()||
|-
|-style="background-color:#D7EF54"
|-style="background-color:#D7EF54"
|  Pad || ||  
|  Pad || ||  
Line 347: Line 249:
|-
|-
|PadRead || emuObj.PadRead() ||
|PadRead || emuObj.PadRead() ||
<br>L3        = 0x00000002
<br>R3        = 0x00000004
<br>OPTIONS  = 0x00000008
<br>UP        = 0x00000010
<br>RIGHT    = 0x00000020
<br>DOWN      = 0x00000040
<br>LEFT      = 0x00000080
<br>L2        = 0x00000100
<br>R2        = 0x00000200
<br>L1        = 0x00000400
<br>R1        = 0x00000800
<br>TRIANGLE  = 0x00001000
<br>CIRCLE    = 0x00002000
<br>CROSS    = 0x00004000
<br>SQUARE    = 0x00008000
<br>SELECT    = 0x00010000
<br>START    = 0x00020000
|-
|-
|PadReadPitch || emuObj.PadReadPitch() ||
|PadReadPitch || emuObj.PadReadPitch() ||
Line 371: Line 256:
|PadRegisterSamples || emuObj.PadRegisterSamples()||
|PadRegisterSamples || emuObj.PadRegisterSamples()||
|-
|-
| PadSetButtonsMode || emuObj.PadSetButtonsMode() ||  
| PadSetButtonsMode || emuObj.PadSetButtonsMode() || emuObj.PadSetButtonsMode(pad.BUTTONS_MODE_OPTION_IS_SELECT)
<br>0 = Touch bar is split in two for Start/Select. Option is unmapped (default behaviour)
<br>1 = Touch bar is Start. Option is Select
<br>2 = Touch bar is Select. Option is Start
|-
|-
| PadVibrate|| emuObj.PadVibrate() || emuObj.PadVibrate(5,180,180)
| PadVibrate|| emuObj.PadVibrate() || emuObj.PadVibrate(5,180,180)
Line 424: Line 306:
|GetReg||axObj.GetReg()||
|GetReg||axObj.GetReg()||
|-style="background-color:#D7EF54"
|-style="background-color:#D7EF54"
| Memory editing || || Do note that the offsets on PPSSPP are mapped differently than the ones on the PS4  
| Memory editing || || Do note that the offsets on PPSSPP are different than the ones on the PS4  
|-
|-
| ReadMem32 || axObj.ReadMem32() || Read 4 bytes from offset
| ReadMem32 || axObj.ReadMem32() || Read 4 bytes from offset
Line 460: Line 342:
|}
|}


=====User-made examples=====
====Examples====
<br>'''Coconut Dodge'''  
<br>'''''LUA example:'''''
<br>"NPEZ00164"
<br>
<br>Coconut Dodge "NPEZ00164"
<pre>
<pre>
local axObj = getAXObject()
local axObj = getAXObject()
Line 469: Line 352:
local patcher = function()
local patcher = function()
--Infinite lives
--Infinite lives
axObj.WriteMem32(0x8ACA1A4, 0x3) --0x08ACE1A4 on PPSSPP. PPSSPP addresses need to be reduced by 0x4000 in order to work on PS4
axObj.WriteMem32(0x8ACA1A4, 0x3)
end
end


emuObj.AddVsyncHook(patcher)
emuObj.AddVsyncHook(patcher)
</pre>
</pre>
<br>'''Daxter'''
 
<br>"NPUG80329"
=====Patches.lua=====
'''An official lua created by sony for Patapon 2'''
<pre>
<pre>
local axObj = getAXObject()
-- Lua 5.3
local emuObj = getEmuObject()
-- Title:  Patapon 2 PSP - UCUS-98732 (USA)


local patcher = function()
apiRequest(1.0) -- request version 1.0 API. Calling apiRequest() is mandatory.
--Performance patch
axObj.WriteMem32(0x08862E40, 0x10000019) --0x08866E40 on PPSSPP. PPSSPP addresses need to be reduced by 0x4000 in order to work on PS4
axObj.WriteMem32(0x08862EAC, 0x0) --0x08866EAC on PPSSPP. PPSSPP addresses need to be reduced by 0x4000 in order to work on PS4
end


emuObj.AddVsyncHook(patcher)
local gpr = require( "ax-gpr-alias" ) -- you can access Allegrex GPR by alias (gpr.a0 / gpr["a0"])
</pre>
local emuObj = getEmuObject() -- emulator
local axObj = getAXObject() -- allegrex
local pad = require("pad")


[https://www.psdevwiki.com/ps4/Talk:PSP_Emulator_Compatibility_List#Official_PSPemu_Configuration_Files More patches can be found here]
-- Hook memcpy to catch framebuffer effects
axFuncReplace(0x881D194, "patapon_memcpy")


====Patches.lua====
-- Accelerate some functions
======Syphon Filter: Dark Mirror======
axFuncReplace(0x8804670, "__ptmf_scall")
 
axFuncReplace(0x8892230, "Renderer__makeWorldMatrix__4psysFv")
<pre>
axFuncReplace(0x88209A8, "patapon_strcmp")
-- Lua 5.3
axFuncReplace(0x8815130, "sceGupSetStatus")
-- Title: Syphon Filter: Dark Mirror
axFuncReplace(0x8851D84, "FMtx44__setRow__3PydFv")
 
axFuncReplace(0x88437F0, "Script__Talk__Controller__setDeltaTime__3PydFv")
-- Patches for fixing issues with post fx in games using the Syphon Filter/Resistance engine
axFuncReplace(0x8843B6C, "Script__Talk__Controller__setCmdId__3PydFv")
 
axFuncReplace(0x88441DC, "Script__Talk__Controller__getArgValuePtr__3PydFv_0")
apiRequest(1.0) -- request version 1.0 API. Calling apiRequest() is mandatory.
axFuncReplace(0x89B25B0, "sceGmoCol4Multiply")
 
axFuncReplace(0x8910A60, "Gfx__CacheModel__getNodeMtx__6SystemFv")
local emuObj = getEmuObject()
axFuncReplace(0x8911440, "Gfx__StaticGmoModel__getNodeIdx__6SystemFv")
local cpu = getAXObject()  
axFuncReplace(0x89114C8, "Gfx__StaticGmoModel__getNodeMtx__6SystemFv")
 
axFuncReplace(0x891157C, "Gfx__StaticGmoModel__getNodeMtx__6SystemFv_0")
-- The bloom filter uses 1.5 pixel jitter to make a ghetto blur. When up-ressed, this doesn't look good.
axFuncReplace(0x881462C, "sceGuEnable", 0x8B3C050) -- param = gupbase pointer
-- To compensate, reduce the jitter amount before rendering.
axFuncReplace(0x8814684, "sceGuDisable", 0x8B3C050) -- param = gupbase pointer
function BloomJitterPlusAdjust()
axFuncReplace(0x89B2D84, "sceGmoFCurveEval_fastpath", 0x89B2D88) -- param = function entry if not fast path
-- 1.5 pixel "+" pattern
--axFuncReplace(0x88D0788, "Game__Map__Weather__WindLocus__update__4LaboFv_loop", 0x88D0864) -- param = continue address
emuObj.AdjustUVJitter(0, 4, 0.0, 1.5)
axFuncReplace(0x890FCBC, "convertLowerString__6SystemFv")
emuObj.AdjustUVJitter(4, 4, 0.0, -1.5)
axFuncReplace(0x8877104, "convertLowerString__6SystemFv") -- convertLowerString__21@unnamed@BNDFile_cpp@Fv, same functionality
emuObj.AdjustUVJitter(8, 4, 1.5, 0.0)
axFuncReplace(0x897927C, "__extendsfdf2")
emuObj.AdjustUVJitter(12, 4, -1.5, 0.0)
axFuncReplace(0x8979AF8, "__muldf3")
end
axFuncReplace(0x8979A8C, "__adddf3")
axFuncReplace(0x897A750, "__truncdfsf2")
axFuncReplace(0x88CBD64, "RemapPacket", 0x8ACC394) -- param comes from RemapPacketAddr24 & RemapPacketAddr16
axFuncReplace(0x890FEA0, "patapon_strcmp") -- strcmpFast__6SystemFv ('fast' strcmp)


function BloomJitterCrossAdjust()
-- Switch Select command to "Options" button.
-- 1.5 pixel "x" pattern
emuObj.PadSetButtonsMode(pad.BUTTONS_MODE_OPTION_IS_SELECT)
emuObj.AdjustUVJitter(0, 4, 1.5, 1.5)
emuObj.AdjustUVJitter(4, 4, -1.5, 1.5)
emuObj.AdjustUVJitter(8, 4, 1.5, -1.5)
emuObj.AdjustUVJitter(12, 4, -1.5, -1.5)
end


local jitterFixPlus = emuObj.AddGPUHook(0x40dc000, 0, 16, 0x40d4000, BloomJitterPlusAdjust)
-- Remove "Transfer Patapon Saved Data" option from New Game option
local jitterFixCross = emuObj.AddGPUHook(0x40d4000, 0, 16, 0x40dc000, BloomJitterCrossAdjust)
--axInsnReplace(0x8A46660, 0x24070002, 0x24070001) -- li  a3,0x2  (change 2 menu options to 1)
emuObj.RemapSavedata("UCUS98711", "CUSA06171", "504e802b04a1838c32b616abbe0b475fbea1c823825ef0df06cc2bad129ce2f7")


function depthquery()
-- Fix "Tree of Life" unaligned lines and shadows
local querystruct = 0x8eda968 -- this is always in a fixed location
axObj.AddHook(0x884600C, 0x8c850010, function() -- PSP::Gfx::PrimitiveContext::setVertex2f
-- the depth query struct is fixed to 24 entries
local context = axObj.GetGpr(gpr.a0)
-- 0..15 seem to be always used for lights, 16..23 are for npcs
local cmdCount = axObj.ReadMem32(context + 0x14)
for i=0,23 do
if (cmdCount & 1) == 1 then -- we have at least 2 commands
local querytype = cpu.ReadMem32(querystruct+0)
local cmdBuffer = axObj.ReadMem32(context + 0x10)
local valid = cpu.ReadMem32(querystruct+1*4)
local cx = axObj.GetFpr(12)
if valid ~= 0xffffffff then
local cy = axObj.GetFpr(13)
--local queryx = cpu.ReadMem32(querystruct+2*4)
local ox = axObj.ReadMemFloat(cmdBuffer-12)
--local queryy = cpu.ReadMem32(querystruct+3*4)
local oy = axObj.ReadMemFloat(cmdBuffer-8)
--local querydepth = cpu.ReadMem32(querystruct+4*4)
--local querywidth = cpu.ReadMem32(querystruct+5*4)
if cx == ox then
--local queryheight = cpu.ReadMem32(querystruct+6*4)
axObj.SetFpr(12, cx + 0.5)
--local param1c = cpu.ReadMem32(querystruct+7*4)
axObj.WriteMemFloat(cmdBuffer-12, ox + 0.5)
--local param20 = cpu.ReadMem32(querystruct+8*4)
elseif cy == oy then
local param24 = cpu.ReadMem32(querystruct+9*4)
axObj.SetFpr(13, cy + 0.5)
--local result = cpu.ReadMemFloat(querystruct+10*4)
axObj.WriteMemFloat(cmdBuffer-8, oy + 0.5)
if param24 <= 0 then
end
cpu.WriteMem32(querystruct+1*4, 0xffffffff) -- to be removed from the list -> mark as invalid
else
if querytype == 3 then -- n x n coverage based occlusion used by lights. Object opacity is set to (visible_samples / total_samples)
cpu.WriteMemFloat(querystruct+10*4, 0.0) -- always hide lights
else -- Enemies use a 5-point (corners + center) occlusion check. Object is visible if any of the points is visible.
cpu.WriteMemFloat(querystruct+10*4, 1.0) -- set always visible
end
end
end
querystruct = querystruct + 0x2c
end
end
end
end)


cpu.AddHook(0x8c163d4, 0x27bdff80, depthquery) -- = addiu sp, sp, -0x80
-- LANGUAGES --
-- the hook code replaces the occlusion function, so just adjust the stack and return
local langCode = "us" -- default
cpu.InsnReplace(0x8c163d8, 0x34040000, 0x27bd0080) -- addiu sp, sp, 0x80
--local languageList = {"Japanese","English","UK","Italian","German","Spanish","French","Korean","Chinese","ns","nf","Dutch","Portuguese","gr","Belgium"}
cpu.InsnReplace(0x8c163dc, 0xafa40048, 0x03e00008) -- jr ra
--local gameLanguageCode = {"jp","us","uk","it","de","sp","fr","kr","cn","ns","nf","nl","pt","gr","be"}
cpu.InsnReplace(0x8c163e0, 0x3c0408ee, 0x00000000) -- nop
local languageList = {"","English","","","","","","","","Spanish","French","","","",""}
</pre>
local gameLanguageCode = {"","us","","","","","","","","ns","nf","","","",""}
======Patapon 2'''======
<pre>
-- Lua 5.3
-- Title:  Patapon 2 PSP - UCUS-98732 (USA)


apiRequest(1.0) -- request version 1.0 API. Calling apiRequest() is mandatory.
-- US: english = 1, spanish = 9, french = 0xA (from Localize__Manager__setDefaultLangage)
-- EU: uk = 2, italian = 3, german = 4, spanish = 5, french = 6
-- JP: jp = 0
-- HP: ko = 7, ch = 8,
-- GLOBAL FUNCTIONS --


local gpr = require( "ax-gpr-alias" ) -- you can access Allegrex GPR by alias (gpr.a0 / gpr["a0"])
local GLOBAL = 0x8B7D088 -- reawakeDeathUnit - offset 0x88A95E8 in $v1
local emuObj = getEmuObject() -- emulator
local axObj = getAXObject() -- allegrex
local pad = require("pad")


-- Hook memcpy to catch framebuffer effects
function getGlobalAddr() -- gets Global to user data.
axFuncReplace(0x881D194, "patapon_memcpy")
-- address comes from: Labo::Bases::Camp::Controller::reawakeDeathUnit - offset 0x88A95E8 in $v1
-- add 0x20 to address to align it with the word "none"
local main = axObj.ReadMem32(GLOBAL) -- fixed Global address from: 0x88A95E8 -> 0x8c9fbc0
if main == 0xFFFFFFFF or main == 0 then
return 0xFFFFFFFF
end
local ptr = axObj.ReadMem32(main + 0x10c0) --> sets to: 0x8d07840
if ptr == 0xFFFFFFFF or ptr == 0 then
return 0xFFFFFFFF
end


-- Accelerate some functions
return ptr
axFuncReplace(0x8804670, "__ptmf_scall")
end
axFuncReplace(0x8892230, "Renderer__makeWorldMatrix__4psysFv")
 
axFuncReplace(0x88209A8, "patapon_strcmp")
-- MAIN FUNCTIONS --
axFuncReplace(0x8815130, "sceGupSetStatus")
 
axFuncReplace(0x8851D84, "FMtx44__setRow__3PydFv")
local H1 = function() -- Labo::Bases::Camp::Scene::updateTips
axFuncReplace(0x88437F0, "Script__Talk__Controller__setDeltaTime__3PydFv")
local v0 = axObj.GetGpr(gpr.v0)
axFuncReplace(0x8843B6C, "Script__Talk__Controller__setCmdId__3PydFv")
if v0 > 0 then
axFuncReplace(0x88441DC, "Script__Talk__Controller__getArgValuePtr__3PydFv_0")
emuObj.ThrottleMax()
axFuncReplace(0x89B25B0, "sceGmoCol4Multiply")
else
axFuncReplace(0x8910A60, "Gfx__CacheModel__getNodeMtx__6SystemFv")
emuObj.ThrottleNormal()
axFuncReplace(0x8911440, "Gfx__StaticGmoModel__getNodeIdx__6SystemFv")
end
axFuncReplace(0x89114C8, "Gfx__StaticGmoModel__getNodeMtx__6SystemFv")
end
axFuncReplace(0x891157C, "Gfx__StaticGmoModel__getNodeMtx__6SystemFv_0")
 
axFuncReplace(0x881462C, "sceGuEnable", 0x8B3C050) -- param = gupbase pointer
local H2 = function() -- GameSystem__SaveDataController__setStateMessage
axFuncReplace(0x8814684, "sceGuDisable", 0x8B3C050) -- param = gupbase pointer
local ptr = axObj.GetGpr(gpr.a2)
axFuncReplace(0x89B2D84, "sceGmoFCurveEval_fastpath", 0x89B2D88) -- param = function entry if not fast path
local str = axObj.ReadMemStr16(ptr)
--axFuncReplace(0x88D0788, "Game__Map__Weather__WindLocus__update__4LaboFv_loop", 0x88D0864) -- param = continue address
local newStr = "Now loading. Do not turn off the power."
axFuncReplace(0x890FCBC, "convertLowerString__6SystemFv")
-- english: Now loading./Do not remove the Memory Stick Duo™ /or turn off the system power.
axFuncReplace(0x8877104, "convertLowerString__6SystemFv") -- convertLowerString__21@unnamed@BNDFile_cpp@Fv, same functionality
-- spanish: Cargando./No extraigas el Memory Stick Duo™ /ni apagues el sistema.
axFuncReplace(0x897927C, "__extendsfdf2")
-- french: Chargement./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
axFuncReplace(0x8979AF8, "__muldf3")
-- italian: Caricamento in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
axFuncReplace(0x8979A8C, "__adddf3")
-- german: Lädt./Bitte den Memory Stick Duo™ nicht entfernen /und das System nicht ausschalten.
axFuncReplace(0x897A750, "__truncdfsf2")
-- japanese: システムデータをロード中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
axFuncReplace(0x88CBD64, "RemapPacket", 0x8ACC394) -- param comes from RemapPacketAddr24 & RemapPacketAddr16
-- chinese: 系統資料載入中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
axFuncReplace(0x890FEA0, "patapon_strcmp") -- strcmpFast__6SystemFv ('fast' strcmp)
-- korean: 시스템 데이터를 불러오는 중입니다./Memory Stick Duo™를 빼거나/전원을 끄지 마십시오.
 
-- Switch Select command to "Options" button.
if string.find(str, "Now loading") then
emuObj.PadSetButtonsMode(pad.BUTTONS_MODE_OPTION_IS_SELECT)
newStr = "Now loading." -- English: Now loading./Do not remove the Memory Stick Duo™ /or turn off the system power.
 
axObj.WriteMemStr16Z(ptr, newStr)
-- Remove "Transfer Patapon Saved Data" option from New Game option
elseif string.find(str, "Checking Memory Stick") then
--axInsnReplace(0x8A46660, 0x24070002, 0x24070001) -- li  a3,0x2  (change 2 menu options to 1)
newStr = "Please wait." -- English: Checking Memory Stick Duo™.
emuObj.RemapSavedata("UCUS98711", "CUSA06171", "504e802b04a1838c32b616abbe0b475fbea1c823825ef0df06cc2bad129ce2f7")
axObj.WriteMemStr16Z(ptr, newStr)
 
elseif string.find(str, "Now saving")then
-- Fix "Tree of Life" unaligned lines and shadows
newStr = "Now saving." -- English: Now saving./Do not remove the Memory Stick Duo™ /or turn off the system power.
axObj.AddHook(0x884600C, 0x8c850010, function() -- PSP::Gfx::PrimitiveContext::setVertex2f
axObj.WriteMemStr16Z(ptr, newStr)
local context = axObj.GetGpr(gpr.a0)
--
local cmdCount = axObj.ReadMem32(context + 0x14)
elseif string.find(str, "Cargando.") then
if (cmdCount & 1) == 1 then -- we have at least 2 commands
newStr = "Cargando..." -- Spanish: Cargando./No extraigas el Memory Stick Duo™ /ni apagues el sistema.
local cmdBuffer = axObj.ReadMem32(context + 0x10)
axObj.WriteMemStr16Z(ptr, newStr)
local cx = axObj.GetFpr(12)
elseif string.find(str, "Guardando...")then
local cy = axObj.GetFpr(13)
newStr = "Espera..." -- Spanish: Guardando.../No extraigas el Memory Stick Duo™ /ni apagues el sistema.
local ox = axObj.ReadMemFloat(cmdBuffer-12)
axObj.WriteMemStr16Z(ptr, newStr)
local oy = axObj.ReadMemFloat(cmdBuffer-8)
elseif string.find(str, "Comprobando el Memory Stick") then
newStr = "Guardando..." -- Spanish: Comprobando el Memory Stick Duo™.
if cx == ox then
axObj.WriteMemStr16Z(ptr, newStr)
axObj.SetFpr(12, cx + 0.5)
--
axObj.WriteMemFloat(cmdBuffer-12, ox + 0.5)
elseif string.find(str, "Chargement.") then
elseif cy == oy then
newStr = "Chargement." -- French: Chargement./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
axObj.SetFpr(13, cy + 0.5)
axObj.WriteMemStr16Z(ptr, newStr)
axObj.WriteMemFloat(cmdBuffer-8, oy + 0.5)
elseif string.find(str, "Vérification du Memory Stick")then
end
newStr = "Veuillez patienter." -- French: Vérification du Memory Stick Duo™.
end
axObj.WriteMemStr16Z(ptr, newStr)
end)
elseif string.find(str, "Sauvegarde.") then
 
newStr = "Sauvegarde en cours." -- French: Sauvegarde./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
-- LANGUAGES --
axObj.WriteMemStr16Z(ptr, newStr)
local langCode = "us" -- default
--
--local languageList = {"Japanese","English","UK","Italian","German","Spanish","French","Korean","Chinese","ns","nf","Dutch","Portuguese","gr","Belgium"}
elseif string.find(str, "Caricamento in corso") then
--local gameLanguageCode = {"jp","us","uk","it","de","sp","fr","kr","cn","ns","nf","nl","pt","gr","be"}
newStr = "Caricamento in corso." -- Italian: Caricamento in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
local languageList = {"","English","","","","","","","","Spanish","French","","","",""}
axObj.WriteMemStr16Z(ptr, newStr)
local gameLanguageCode = {"","us","","","","","","","","ns","nf","","","",""}
elseif string.find(str, "Controllo del Memory Stick")then
 
newStr = "Attendi." -- Italian: Controllo del Memory Stick Duo™.
-- US: english = 1, spanish = 9, french = 0xA (from Localize__Manager__setDefaultLangage)
axObj.WriteMemStr16Z(ptr, newStr)
-- EU: uk = 2, italian = 3, german = 4, spanish = 5, french = 6
elseif string.find(str, "Salvataggio in corso") then
-- JP: jp = 0
newStr = "Salvataggio in corso." -- Italian: Salvataggio in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
-- HP: ko = 7, ch = 8,
axObj.WriteMemStr16Z(ptr, newStr)
--
-- GLOBAL FUNCTIONS --
elseif string.find(str, "Lädt") then
 
newStr = "Lädt." -- German: Lädt./Bitte den Memory Stick Duo™ nicht entfernen /und das System nicht ausschalten.
local GLOBAL = 0x8B7D088 -- reawakeDeathUnit - offset 0x88A95E8 in $v1
axObj.WriteMemStr16Z(ptr, newStr)
 
elseif string.find(str, "Memory Stick Duo™ wird überprüft")then
function getGlobalAddr() -- gets Global to user data.
newStr = "Bitte warten." -- German: Memory Stick Duo™ wird überprüft.
-- address comes from: Labo::Bases::Camp::Controller::reawakeDeathUnit - offset 0x88A95E8 in $v1
axObj.WriteMemStr16Z(ptr, newStr)
-- add 0x20 to address to align it with the word "none"
elseif string.find(str, "Speichert.") then
newStr = "Speichert." -- German: Speichert./Bitte den Memory Stick Duo™ nicht entfernen und /das System nicht ausschalten.
local main = axObj.ReadMem32(GLOBAL) -- fixed Global address from: 0x88A95E8 -> 0x8c9fbc0
axObj.WriteMemStr16Z(ptr, newStr)
if main == 0xFFFFFFFF or main == 0 then
--
return 0xFFFFFFFF
elseif string.find(str, "システムデータをロード中です。") then
end
newStr = "ロード中。" -- Japanese: システムデータをロード中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
local ptr = axObj.ReadMem32(main + 0x10c0) --> sets to: 0x8d07840
axObj.WriteMemStr16Z(ptr, newStr)
if ptr == 0xFFFFFFFF or ptr == 0 then
elseif string.find(str, "Memory Stick Duo™のチェック中です。")then
return 0xFFFFFFFF
newStr = "お待ちください。" -- Japanese: Memory Stick Duo™のチェック中です。
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "システムデータをセーブ中です。") then
newStr = "セーブ中。" -- Japanese: システムデータをセーブ中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
axObj.WriteMemStr16Z(ptr, newStr)
--
elseif string.find(str, "系統資料載入中。") then
newStr = "載入中。" -- Chinese: 系統資料載入中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Memory Stick Duo™確認中。")then
newStr = "請稍候。" -- Chinese: Memory Stick Duo™確認中。
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "保存中。") then
newStr = "存檔中。" -- Chinese: 保存中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
axObj.WriteMemStr16Z(ptr, newStr)
--
elseif string.find(str, "시스템 데이터를 불러오는 중입니다") then
newStr = "불러오는 중입니다." -- Korean: 시스템 데이터를 불러오는 중입니다./Memory Stick Duo™를 빼거나/전원을 끄지 마십시오.
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Memory Stick Duo™ 체크 중입니다")then
newStr = "잠시 기다려 주십시오." -- Korean: Memory Stick Duo™ 체크 중입니다.
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "시스템 데이터를 저장 중입니다") then
newStr = "저장 중입니다." -- Korean: 시스템 데이터를 저장 중입니다./Memory Stick Duo™를 빼거나,/전원을 끄지 마십시오.
axObj.WriteMemStr16Z(ptr, newStr)
end
end
end


return ptr
local H3 = function() -- Localize__Manager__getLanguageName
local v0 = axObj.GetGpr(gpr.v0)
local langPtr = axObj.ReadMem32(v0)
langCode = axObj.ReadMemStr(langPtr)
end
end


-- MAIN FUNCTIONS --
local bundleFileName = ""
local H4 = function() -- System::Util__BNDFile__doNameCallback
local ptr = axObj.GetGpr(gpr.a0)
bundleFileName = axObj.ReadMemStr(ptr)
end


local H1 = function() -- Labo::Bases::Camp::Scene::updateTips
local H5 = function() -- Labo::GameSystem__callbackFunc_MemoryObject
local v0 = axObj.GetGpr(gpr.v0)
local ptr = axObj.GetGpr(gpr.s5)
if v0 > 0 then
local dataPtr = axObj.ReadMem32(ptr)
emuObj.ThrottleMax()
else
if bundleFileName == "colony_data.pac" then
emuObj.ThrottleNormal()
axObj.WriteMem16(dataPtr + 0x79ba, 4)
end
end
end
end


local H2 = function() -- GameSystem__SaveDataController__setStateMessage
-- Black Smith - Remove "KeyGuide" bug when hit anvil head while quenching --
local ptr = axObj.GetGpr(gpr.a2)
local blackSmithRunning = false
local str = axObj.ReadMemStr16(ptr)
local H6 = function() -- Sound__SubGame__Blacksmith__Command__start__4LaboFv
local newStr = "Now loading. Do not turn off the power."
blackSmithRunning = true
-- english: Now loading./Do not remove the Memory Stick Duo™ /or turn off the system power.
end
-- spanish: Cargando./No extraigas el Memory Stick Duo™ /ni apagues el sistema.
local H7 = function() -- Sound__BeatCommander__endSubGame__4LaboFv
-- french: Chargement./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
if blackSmithRunning == true then
-- italian: Caricamento in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
local a0 = axObj.GetGpr(gpr.a0)
-- german: Lädt./Bitte den Memory Stick Duo™ nicht entfernen /und das System nicht ausschalten.
axObj.WriteMem8(a0 + 0x19c, 1) -- set memory to 1 (instead of 0) otherwise brings up bad "KeyGuide"
-- japanese: システムデータをロード中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
end
-- chinese: 系統資料載入中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
-- korean: 시스템 데이터를 불러오는 중입니다./Memory Stick Duo™를 빼거나/전원을 끄지 마십시오.
if string.find(str, "Now loading") then
blackSmithRunning = false
newStr = "Now loading." -- English: Now loading./Do not remove the Memory Stick Duo™ /or turn off the system power.
end
axObj.WriteMemStr16Z(ptr, newStr)
 
elseif string.find(str, "Checking Memory Stick") then
-- TIPS System hacks --
newStr = "Please wait." -- English: Checking Memory Stick Duo™.
axInsnReplace(0x8A73A44, 0x3C0342A8, 0x3C0342A4) -- change required number of Tips from 84 to 82.
axObj.WriteMemStr16Z(ptr, newStr)
local H8 = function() -- GameSystem__Tips__Viewer__setup__4LaboFv
elseif string.find(str, "Now saving")then
local global = getGlobalAddr()
newStr = "Now saving." -- English: Now saving./Do not remove the Memory Stick Duo™ /or turn off the system power.
if global == 0xFFFFFFFF then
axObj.WriteMemStr16Z(ptr, newStr)
return
--
end
elseif string.find(str, "Cargando.") then
 
newStr = "Cargando..." -- Spanish: Cargando./No extraigas el Memory Stick Duo™ /ni apagues el sistema.
local unitTable = axObj.ReadMem32(global + 0x1068) --> sets to: 0x8d13580 (unit table)
axObj.WriteMemStr16Z(ptr, newStr)
local tipsPtr = unitTable + 0x1F5E4
elseif string.find(str, "Guardando...")then
newStr = "Espera..." -- Spanish: Guardando.../No extraigas el Memory Stick Duo™ /ni apagues el sistema.
local badTips = axObj.ReadMem32(tipsPtr + 8)
axObj.WriteMemStr16Z(ptr, newStr)
badTips = badTips & 0xFFBBFFFF -- remove tips 0x53 and 0x57 as they referred to Multiplayer
elseif string.find(str, "Comprobando el Memory Stick") then
axObj.WriteMem32(tipsPtr + 8, badTips)
newStr = "Guardando..." -- Spanish: Comprobando el Memory Stick Duo™.
end
axObj.WriteMemStr16Z(ptr, newStr)
 
--
-- Remove AutoSave menu from initial startup --
elseif string.find(str, "Chargement.") then
local H9 = function() -- GameSystem__SaveDataController__update__4LaboFv
newStr = "Chargement." -- French: Chargement./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
local s3 = axObj.GetGpr(gpr.s3)
axObj.WriteMemStr16Z(ptr, newStr)
local flg = axObj.ReadMem32(s3 + 0x7eed)
elseif string.find(str, "Vérification du Memory Stick")then
local val = axObj.ReadMem32(s3 + 0x7efc)
newStr = "Veuillez patienter." -- French: Vérification du Memory Stick Duo™.
axObj.WriteMemStr16Z(ptr, newStr)
if flg == 0 and val == 0x14 then
elseif string.find(str, "Sauvegarde.") then
axObj.WriteMem32(s3 + 0x7efc, 0x13)
newStr = "Sauvegarde en cours." -- French: Sauvegarde./Ne pas retirer le Memory Stick Duo™ /ou éteindre le système.
end
axObj.WriteMemStr16Z(ptr, newStr)
end
--
 
elseif string.find(str, "Caricamento in corso") then
-- Change game save name to "Patapon 2 Remastered" --
newStr = "Caricamento in corso." -- Italian: Caricamento in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
local H10 = function() -- Utility__SaveDataUtility__setDataParamsfoString
axObj.WriteMemStr16Z(ptr, newStr)
local ptr = axObj.GetGpr(gpr.s1)
elseif string.find(str, "Controllo del Memory Stick")then
local strPtr = axObj.ReadMem32(ptr)
newStr = "Attendi." -- Italian: Controllo del Memory Stick Duo™.
local newStr = "PATAPON™ 2 Remastered"
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Salvataggio in corso") then
axObj.WriteMemStrZ(strPtr, newStr)
newStr = "Salvataggio in corso." -- Italian: Salvataggio in corso.../Non rimuovere il Memory Stick Duo™ /e non spegnere il sistema.
end
axObj.WriteMemStr16Z(ptr, newStr)
 
--
-- Change description for the "Friendship" weapon to remove game sharing text --
elseif string.find(str, "Lädt") then
local itemsTable = {}
newStr = "Lädt." -- German: Lädt./Bitte den Memory Stick Duo™ nicht entfernen /und das System nicht ausschalten.
itemsTable[1] = "Proof of friendship establish" -- English
axObj.WriteMemStr16Z(ptr, newStr)
itemsTable[2] = "Prueba de la amistad establecida" -- Spanish
elseif string.find(str, "Memory Stick Duo™ wird überprüft")then
itemsTable[3] = "Preuve de l'amitié établie" -- French
newStr = "Bitte warten." -- German: Memory Stick Duo™ wird überprüft.
itemsTable[4] = "Preuve d'une amitié" -- French alt
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Speichert.") then
function changeStrings(strPtr) -- modify strings
newStr = "Speichert." -- German: Speichert./Bitte den Memory Stick Duo™ nicht entfernen und /das System nicht ausschalten.
local str = axObj.ReadMemStr16(strPtr) -- ptr to the string
axObj.WriteMemStr16Z(ptr, newStr)
local strFind = string.gsub(str, "/", " ") -- change any slash to space to strings can match.
--
strFind = string.gsub(strFind, " ", " ") -- change any double spaces due to above change to only 1 space.
elseif string.find(str, "システムデータをロード中です。") then
newStr = "ロード中。" -- Japanese: システムデータをロード中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
for i = 1, #itemsTable do
axObj.WriteMemStr16Z(ptr, newStr)
local startPos, endPos = string.find(strFind, itemsTable[i])
elseif string.find(str, "Memory Stick Duo™のチェック中です。")then
newStr = "お待ちください。" -- Japanese: Memory Stick Duo™のチェック中です。
if startPos ~= nil then
axObj.WriteMemStr16Z(ptr, newStr)
str = string.sub(str, 1, (startPos-1) )
elseif string.find(str, "システムデータをセーブ中です。") then
-- SPECIAL fixes --
newStr = "セーブ中。" -- Japanese: システムデータをセーブ中です。/Memory Stick Duo™を抜き挿ししたり、/電源を切ったりしないでください。
str = string.gsub(str, "Un oiseau avec de bons HP et /une grosse attaque.","Un oiseau qui augmente vos/HP.") -- French incorrect grammar (bird)
axObj.WriteMemStr16Z(ptr, newStr)
str = string.gsub(str, "aumente","augmente") -- French incorrect grammar.
--
 
elseif string.find(str, "系統資料載入中。") then
axObj.WriteMemStr16Z(strPtr, str)
newStr = "載入中。" -- Chinese: 系統資料載入中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
end
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Memory Stick Duo™確認中。")then
newStr = "請稍候。" -- Chinese: Memory Stick Duo™確認中。
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "保存中。") then
newStr = "存檔中。" -- Chinese: 保存中。/請勿插拔Memory Stick Duo™/或是關閉主機的電源。
axObj.WriteMemStr16Z(ptr, newStr)
--
elseif string.find(str, "시스템 데이터를 불러오는 중입니다") then
newStr = "불러오는 중입니다." -- Korean: 시스템 데이터를 불러오는 중입니다./Memory Stick Duo™를 빼거나/전원을 끄지 마십시오.
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "Memory Stick Duo™ 체크 중입니다")then
newStr = "잠시 기다려 주십시오." -- Korean: Memory Stick Duo™ 체크 중입니다.
axObj.WriteMemStr16Z(ptr, newStr)
elseif string.find(str, "시스템 데이터를 저장 중입니다") then
newStr = "저장 중입니다." -- Korean: 시스템 데이터를 저장 중입니다./Memory Stick Duo™를 빼거나,/전원을 끄지 마십시오.
axObj.WriteMemStr16Z(ptr, newStr)
end
end
end
end
 
local H3 = function() -- Localize__Manager__getLanguageName
local H11 = function() -- from Bases__Item__ExplanationWindow__setItemId
local v0 = axObj.GetGpr(gpr.v0)
local langPtr = axObj.ReadMem32(v0)
langCode = axObj.ReadMemStr(langPtr)
end
 
local bundleFileName = ""
local H4 = function() -- System::Util__BNDFile__doNameCallback
local ptr = axObj.GetGpr(gpr.a0)
local ptr = axObj.GetGpr(gpr.a0)
bundleFileName = axObj.ReadMemStr(ptr)
local a2 = axObj.GetGpr(gpr.a2)
end
local valPtr = axObj.ReadMem32(ptr)
local v1 = valPtr + 8
local v0 = a2 * 4
v0 = v0 + v1
local strPtr = axObj.ReadMem32(v0)
strPtr = strPtr + valPtr


local H5 = function() -- Labo::GameSystem__callbackFunc_MemoryObject
changeStrings(strPtr)
local ptr = axObj.GetGpr(gpr.s5)
local dataPtr = axObj.ReadMem32(ptr)
if bundleFileName == "colony_data.pac" then
axObj.WriteMem16(dataPtr + 0x79ba, 4)
end
end
end


-- Black Smith - Remove "KeyGuide" bug when hit anvil head while quenching --
-- Skip Memory message when selecting "Delete Save Data" on "Save the adventure" dialogue.
local blackSmithRunning = false
local menuSkip = false
local H6 = function() -- Sound__SubGame__Blacksmith__Command__start__4LaboFv
local H12 = function() -- Bases__Talk__CommandCamp__showDialog
blackSmithRunning = true
menuSkip = true
end
end
local H7 = function() -- Sound__BeatCommander__endSubGame__4LaboFv
local H13 = function() -- Bases__Talk__CommandCamp__showDialog
if blackSmithRunning == true then
if menuSkip == true then
local a0 = axObj.GetGpr(gpr.a0)
axObj.SetGpr(gpr.v1, 0)
axObj.WriteMem8(a0 + 0x19c, 1) -- set memory to 1 (instead of 0) otherwise brings up bad "KeyGuide"
menuSkip = false
end
end
blackSmithRunning = false
end
end
 
local H14 = function() -- Bases__Talk__CommandCamp__showDialog
-- TIPS System hacks --
if menuSkip == true then
axInsnReplace(0x8A73A44, 0x3C0342A8, 0x3C0342A4) -- change required number of Tips from 84 to 82.
axObj.SetPC(0x88D908C)
local H8 = function() -- GameSystem__Tips__Viewer__setup__4LaboFv
local global = getGlobalAddr()
if global == 0xFFFFFFFF then
return
end
end
end


local unitTable = axObj.ReadMem32(global + 0x1068) --> sets to: 0x8d13580 (unit table)
local tipsPtr = unitTable + 0x1F5E4
local badTips = axObj.ReadMem32(tipsPtr + 8)
badTips = badTips & 0xFFBBFFFF -- remove tips 0x53 and 0x57 as they referred to Multiplayer
axObj.WriteMem32(tipsPtr + 8, badTips)
end


-- Remove AutoSave menu from initial startup --
-- HOOKS --
local H9 = function() -- GameSystem__SaveDataController__update__4LaboFv
local hook1  = axObj.AddHook(0x88E9564, 0x0002102B, H1) -- Labo::Bases__Camp__Scene__updateTips
local s3 = axObj.GetGpr(gpr.s3)
local hook2  = axObj.AddHook(0x899E718, 0x00403021, H2) -- GameSystem__SaveDataController__setStateMessage
local flg = axObj.ReadMem32(s3 + 0x7eed)
local hook3  = axObj.AddHook(0x897771C, 0x00431021, H3) -- Localize__Manager__getLanguageName
local val = axObj.ReadMem32(s3 + 0x7efc)
local hook4  = axObj.AddHook(0x88774D0, 0x00402821, H4) -- System::Util__BNDFile__doNameCallback
local hook5  = axObj.AddHook(0x886889C, 0x02002021, H5) -- Labo::GameSystem__callbackFunc_MemoryObject
if flg == 0 and val == 0x14 then
local hook6  = axObj.AddHook(0x898BCDC, 0x27BDFFE0, H6) -- Sound__SubGame__Blacksmith__Command__start__4LaboFv
axObj.WriteMem32(s3 + 0x7efc, 0x13)
local hook7  = axObj.AddHook(0x89220F8, 0xAC80019C, H7) -- Sound__BeatCommander__endSubGame__4LaboFv
end
local hook8  = axObj.AddHook(0x8A734DC, 0x27BDFFC0, H8) -- GameSystem__Tips__Viewer__setup__4LaboFv
end
local hook9  = axObj.AddHook(0x899CF4C, 0x92637EED, H9) -- GameSystem__SaveDataController__update__4LaboFv
local hook10 = axObj.AddHook(0x88E7E48, 0x2490009C, H10) -- Utility__SaveDataUtility__setDataParamsfoString
local hook11 = axObj.AddHook(0x897CF90, 0x26041718, H11) -- Bases__Item__ExplanationWindow__setItemId
local hook12 = axObj.AddHook(0x88D9114, 0xAEA00014, H12) -- Bases__Talk__CommandCamp__showDialog
local hook13 = axObj.AddHook(0x88D90B4, 0x9063C550, H13) -- Bases__Talk__CommandCamp__showDialog
local hook14 = axObj.AddHook(0x88D907C, 0x8FA2003C, H14) -- Bases__Talk__CommandCamp__showDialog
local hook15 = axObj.AddHook(0x8A394B4, 0x26241718, H11) -- Bases__Organization__Managed__ItemSelectWindow__onSlotChange (note uses H11)
 


-- Change game save name to "Patapon 2 Remastered" --
-- US game bug fix.  "Paraget" -> "Patagate" --
local H10 = function() -- Utility__SaveDataUtility__setDataParamsfoString
axObj.AddHook(0x88DC5F4, 0x00409021, function() -- from Bases__Camp__Person__Behavior__Idle__update__4LaboFv
local ptr = axObj.GetGpr(gpr.s1)
local strPtr = axObj.GetGpr(gpr.v0) + 0xE -- 0xE skip over X/Y positions.
local strPtr = axObj.ReadMem32(ptr)
local str = axObj.ReadMemStr16(strPtr)
local newStr = "PATAPON™ 2 Remastered"
axObj.WriteMemStrZ(strPtr, newStr)
if string.find(str, "The Paraget will") then
end
-- org string: The Paraget will teleport you to/another world…
 
local newStr = "The Patagate can teleport you to/another world…"
-- Change description for the "Friendship" weapon to remove game sharing text --
axObj.WriteMemStr16Z(strPtr, newStr)
local itemsTable = {}
elseif string.find(str, "Paraget Shrine") then
itemsTable[1] = "Proof of friendship establish" -- English
-- org string: This is the Paraget Shrine./Only <N0> and <N1> can/enter.
itemsTable[2] = "Prueba de la amistad establecida" -- Spanish
local newStr = "This is the Patagate Shrine/Only <N0> and <N1> can/enter."
itemsTable[3] = "Preuve de l'amitié établie" -- French
axObj.WriteMemStr16Z(strPtr, newStr)
itemsTable[4] = "Preuve d'une amitié" -- French alt
end
end)
function changeStrings(strPtr) -- modify strings
local str = axObj.ReadMemStr16(strPtr) -- ptr to the string
local strFind = string.gsub(str, "/", " ") -- change any slash to space to strings can match.
strFind = string.gsub(strFind, "  ", " ") -- change any double spaces due to above change to only 1 space.
for i = 1, #itemsTable do
local startPos, endPos = string.find(strFind, itemsTable[i])
if startPos ~= nil then
str = string.sub(str, 1, (startPos-1) )
-- SPECIAL fixes --
str = string.gsub(str, "Un oiseau avec de bons HP et /une grosse attaque.","Un oiseau qui augmente vos/HP.") -- French incorrect grammar (bird)
str = string.gsub(str, "aumente","augmente") -- French incorrect grammar.


axObj.WriteMemStr16Z(strPtr, str)
--[[
end
axObj.AddHook(0x08982F48, 0x24070001, function()
end
if emuObj.NeoMode() then
end
axObj.SetGpr(gpr.a3, 0) -- turn on 60fps mode
end
local H11 = function() -- from Bases__Item__ExplanationWindow__setItemId
end)
local ptr = axObj.GetGpr(gpr.a0)
]]--
local a2 = axObj.GetGpr(gpr.a2)
local valPtr = axObj.ReadMem32(ptr)
local v1 = valPtr + 8
local v0 = a2 * 4
v0 = v0 + v1
local strPtr = axObj.ReadMem32(v0)
strPtr = strPtr + valPtr


changeStrings(strPtr)
--- MOVIE FIX ---
local movieLastTime = 0.0
local movieFix = function() -- Labo::GameSystem__MovieModule__render
local t = axObj.GetFpr(0)
if t == 0 and movieLastTime > 0 then
local s0 = axObj.GetGpr(gpr.s0)
axObj.WriteMemFloat(s0 + 0x44, movieLastTime)
elseif t > 0 then
movieLastTime = t
end
end
end


-- Skip Memory message when selecting "Delete Save Data" on "Save the adventure" dialogue.
axObj.AddHook(0x8A6A1DC, 0xe6000044, movieFix)
local menuSkip = false
local H12 = function() -- Bases__Talk__CommandCamp__showDialog
menuSkip = true
end
local H13 = function() -- Bases__Talk__CommandCamp__showDialog
if menuSkip == true then
axObj.SetGpr(gpr.v1, 0)
menuSkip = false
end
end
local H14 = function() -- Bases__Talk__CommandCamp__showDialog
if menuSkip == true then
axObj.SetPC(0x88D908C)
end
end




-- HOOKS --
--- PAT2-16 FIX ---
local hook1  = axObj.AddHook(0x88E9564, 0x0002102B, H1) -- Labo::Bases__Camp__Scene__updateTips
axObj.AddHook(0x890E9E0, 0x02002021, function() -- Labo::Game__Gimmick__WindowAttacher__update
local hook2  = axObj.AddHook(0x899E718, 0x00403021, H2) -- GameSystem__SaveDataController__setStateMessage
local ptr = axObj.GetGpr(gpr.sp) + 0x28
local hook3  = axObj.AddHook(0x897771C, 0x00431021, H3) -- Localize__Manager__getLanguageName
local posy = axObj.ReadMemFloat(ptr + 4)
local hook4  = axObj.AddHook(0x88774D0, 0x00402821, H4) -- System::Util__BNDFile__doNameCallback
local hook5  = axObj.AddHook(0x886889C, 0x02002021, H5) -- Labo::GameSystem__callbackFunc_MemoryObject
if posy < -30 then
local hook6  = axObj.AddHook(0x898BCDC, 0x27BDFFE0, H6) -- Sound__SubGame__Blacksmith__Command__start__4LaboFv
local obj = axObj.GetGpr(gpr.a0)
local hook7  = axObj.AddHook(0x89220F8, 0xAC80019C, H7) -- Sound__BeatCommander__endSubGame__4LaboFv
axObj.WriteMem8(obj + 0x2a8, 0)
local hook8  = axObj.AddHook(0x8A734DC, 0x27BDFFC0, H8) -- GameSystem__Tips__Viewer__setup__4LaboFv
end
local hook9  = axObj.AddHook(0x899CF4C, 0x92637EED, H9) -- GameSystem__SaveDataController__update__4LaboFv
end)
local hook10 = axObj.AddHook(0x88E7E48, 0x2490009C, H10) -- Utility__SaveDataUtility__setDataParamsfoString
</pre>
local hook11 = axObj.AddHook(0x897CF90, 0x26041718, H11) -- Bases__Item__ExplanationWindow__setItemId
local hook12 = axObj.AddHook(0x88D9114, 0xAEA00014, H12) -- Bases__Talk__CommandCamp__showDialog
local hook13 = axObj.AddHook(0x88D90B4, 0x9063C550, H13) -- Bases__Talk__CommandCamp__showDialog
local hook14 = axObj.AddHook(0x88D907C, 0x8FA2003C, H14) -- Bases__Talk__CommandCamp__showDialog
local hook15 = axObj.AddHook(0x8A394B4, 0x26241718, H11) -- Bases__Organization__Managed__ItemSelectWindow__onSlotChange (note uses H11)


== Emulators ==
<pre>Every emulator is programmed in a different way, sometimes choosing the right emulator is the only possible way to fix a game. Emulators are not provided pre-installed on the ps4, they have to be unpacked from a backup that's downloaded from the ps store from that specific game. this list includes The typical usage of some of The emulators.</pre>
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Emulator !! Usage !! API Version !! Similar emulators (Usage)
|-
| Echochrome || The default psp emulator for PSPFPKG tool at the time of writing and the best in terms of compatibility. || ? || ?
|-
| LocoRoco Midnight Carnival  || ? || ? || ?
|-
| LocoRoco 1  || ? || ? || ?
|-
| LocoRoco 2  || ? || ? || ?
|-
| Castlevania Requiem  || ? || ? || ?
|-
| Patapon 2 || ? ||  ? || ?
|-
| PaRappa the Rapper || An unofficial emulator developed by sony with very bad compatibility ||  ? || ?
|-
|}


-- US game bug fix.  "Paraget" -> "Patagate" --
==Memory mapping==
axObj.AddHook(0x88DC5F4, 0x00409021, function() -- from Bases__Camp__Person__Behavior__Idle__update__4LaboFv
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
local strPtr = axObj.GetGpr(gpr.v0) + 0xE -- 0xE skip over X/Y positions.
! Offset From !! Offset To !! Name
local str = axObj.ReadMemStr16(strPtr)
|-
| 0x1008000000 || 0x10887FFFFF  ||  Allegrex memory(?)
if string.find(str, "The Paraget will") then
|-
-- org string: The Paraget will teleport you to/another world…
|}
local newStr = "The Patagate can teleport you to/another world…"
==Register map==
axObj.WriteMemStr16Z(strPtr, newStr)
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
elseif string.find(str, "Paraget Shrine") then
! Register !! Offset
-- org string: This is the Paraget Shrine./Only <N0> and <N1> can/enter.
|-
local newStr = "This is the Patagate Shrine/Only <N0> and <N1> can/enter."
| PC?? || 0x20B89FAE8 
axObj.WriteMemStr16Z(strPtr, newStr)
|-
end
|}
end)
 
 
= Known issues =
--[[
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
axObj.AddHook(0x08982F48, 0x24070001, function()
! Issue !! Games affected !! Solution !! Description
if emuObj.NeoMode() then
|-
axObj.SetGpr(gpr.a3, 0) -- turn on 60fps mode
| - || || ||
end
|-
end)
|}
]]--


--- MOVIE FIX ---
=LUA include files=
local movieLastTime = 0.0
<br>Files that need to be placed in the '''/lua_include/''' folder
local movieFix = function() -- Labo::GameSystem__MovieModule__render
 
local t = axObj.GetFpr(0)
'''ax-gpr-alias.lua'''
if t == 0 and movieLastTime > 0 then
<pre>
local s0 = axObj.GetGpr(gpr.s0)
axObj.WriteMemFloat(s0 + 0x44, movieLastTime)
elseif t > 0 then
movieLastTime = t
end
end


axObj.AddHook(0x8A6A1DC, 0xe6000044, movieFix)
-- Recommended method to import this module:
--  local gpr = require("ax-gpr-alias")




--- PAT2-16 FIX ---
gpr = {}
axObj.AddHook(0x890E9E0, 0x02002021, function() -- Labo::Game__Gimmick__WindowAttacher__update
local ptr = axObj.GetGpr(gpr.sp) + 0x28
local posy = axObj.ReadMemFloat(ptr + 4)
if posy < -30 then
local obj = axObj.GetGpr(gpr.a0)
axObj.WriteMem8(obj + 0x2a8, 0)
end
end)
</pre>


== Emulators ==
gpr.zero = 0
<pre>Every emulator is programmed in a differently. Sometimes choosing the right emulator is the only possible way to fix a game. Emulators are not provided pre-installed on the ps4, they have to be unpacked from a backup that's downloaded from the ps store from that specific game. This list includes The typical usage of some of The emulators.</pre>
gpr.at  = 1
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
gpr.v0  = 2
! Emulator !! Usage !! API Version !! Similar emulators (compatibility)
gpr.v1  = 3
|-
gpr.a0  = 4
| Echochrome || The default psp emulator for PSPFPKG tool at the time of writing and the best in terms of compatibility. || ? || ?
gpr.a1  = 5
|-
gpr.a2  = 6
| LocoRoco Midnight Carnival  || ? || ? || ?
gpr.a3  = 7
|-
gpr.t0  = 8
| LocoRoco 1  || ? || ? || ?
gpr.t1  = 9
|-
gpr.t2  = 10
| LocoRoco 2  || ? || ? || ?
gpr.t3  = 11
|-
gpr.t4  = 12
| Castlevania Requiem  || ? || ? || ?
gpr.t5  = 13
|-
gpr.t6  = 14
| Patapon 2 || ? ||  ? || ?
gpr.t7  = 15
|-
gpr.s0  = 16
| PaRappa the Rapper || An unofficial emulator developed by sony with very bad compatibility ||  ? || ?
gpr.s1  = 17
|-
gpr.s2  = 18
| Syphon Filter: Dark Mirror || ? || ? || ?
gpr.s3  = 19
|-
gpr.s4  = 20
|}
gpr.s5  = 21
gpr.s6  = 22
gpr.s7  = 23
gpr.t8  = 24
gpr.t9  = 25
gpr.k0  = 26
gpr.k1  = 27
gpr.gp  = 28
gpr.sp  = 29
gpr.fp  = 30
gpr.ra  = 31


==Memory mapping==
return gpr
<br>'''Note''': The memory on PPSSPP is 0x4000 offsets ahead of the memory on the PS4
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Size !! Offset From -> Offset To !! Name
|-
| || 1008000000 -> 10887FFFFF ||  Allegrex memory(?)
|-
|640.00MB  || 228200000 -> 250200000 ||
|-
|64.00MB  ||  250200000 -> 254200000 ||
|-
|32.00MB  ||  254200000 -> 256200000 ||
|-
|2048.00MB ||  256200000 -> 2d6200000 ||
|-
|16.00MB  ||  2d6200000 -> 2d7200000 ||
|-
|16.00MB  ||  2d7200000 -> 2d8200000 ||
|-
|16.00MB  ||  2d8200000 -> 2d9200000 ||
|-
|16.00MB  ||  2d9200000 -> 2da200000 ||
|-
|}
 
===Registers map===
<br>Registers that are marked with '''(?)''' are untested but should be accurate.
<br>*'''Note''': The offsets' positions change as the CLI file's content increases, but the offsets should still be somewhere nearby the offsets listed below and the layout should be the same regardless. The PC pointer script can be used to locate another PC register properly in Echochrome's emulator
{| class=wikitable style="border: none; background: none;"
! scope=col | GPR
! scope=col | Offset
! scope=col | Notes
| rowspan=900 style="border: none; background: none;"|
! scope=col | FPU
! scope=col | Offset
|-
| zero || 0x200414CA8? || || f0 || 0x200414D4C?
|--style="background-color:#EEEFF2"
| at  || 0x200414CAC? || || f1 || 0x200414D50
|-
| v0 || 0x200414CB0  || || f2 || 0x200414D54?
|--style="background-color:#EEEFF2"
| v1 || 0x200414CB4  || || f3 || 0x200414D58?
|-
| a0 || 0x200414CB8  || || f4 || 0x200414D5C?
|--style="background-color:#EEEFF2"
| a1 || 0x200414CBC? || || f5 || 0x200414D60?
|-
| a2 || 0x200414CC0? || || f6 || 0x200414D64?
|--style="background-color:#EEEFF2"
| a3 ||  0x200414CC4? || || f7 || 0x200414D68?
|-
| t0 || 0x200414CC8? || ||f8|| 0x200414D6C?
|--style="background-color:#EEEFF2"
| t1 || 0x200414CCC? || ||f9 || 0x200414D70?
|-
| t2 ||  0x200414CD0? || || f10 || 0x200414D74?
|--style="background-color:#EEEFF2"
| t3 ||  0x200414CD4? || ||f11|| 0x200414D78?
|-
| t4 ||  0x200414CD8? || || f12 || 0x200414D7C?
|--style="background-color:#EEEFF2"
| t5 ||  0x200414CDC? || || f13 || 0x200414D80?
|-
| t6 || 0x200414CE0? || || f14 || 0x200414D84?
|--style="background-color:#EEEFF2"
| t7 || 0x200414CE4? || || f15 || 0x200414D88?
|-
| s0 ||  0x200414CE8? || || f16 || 0x200414D8C?
|--style="background-color:#EEEFF2"
| s1 || 0x200414CEC? || || f17 || 0x200414D90?
|-
| s2 ||  0x200414CF0? || || f18 || 0x200414D94?
|--style="background-color:#EEEFF2"
| s3 || 0x200414CF4? || || f19 || 0x200414D98?
|-
| s4 ||  0x200414CF8? || || f20|| 0x200414D9C?
|--style="background-color:#EEEFF2"
| s5 ||  0x200414CFC? || || f21 || 0x200414DA0?
|-
| s6 ||  0x200414D00? || || f22 || 0x200414DA4?
|--style="background-color:#EEEFF2"
| s7 ||  0x200414D04? || || f23|| 0x200414DA8?
|-
| t8 ||  0x200414D08? || || f24 || 0x200414DAC?
|--style="background-color:#EEEFF2"
| t9 ||  0x200414D0C? || || f25 || 0x200414DB0?
|-
| k0 ||  0x200414D10 || ||f26 || 0x200414DB4?
|--style="background-color:#EEEFF2"
| k1 ||  0x200414D14 || || f27 || 0x200414DB8?
|-
| gp ||  0x200414D18 || || f28|| 0x200414DBC?
|--style="background-color:#EEEFF2"
| sp || 0x200414D1C || || f29 || 0x200414DC0?
|-
| fp || 0x200414D20 ||  || f30 || 0x200414DC4?
|--style="background-color:#EEEFF2"
| {{cellcolors|#D7EF54|#000000}}ra || 0x200414D24 || || f31 || 0x200414DC8
|-
| ? || 0x20AD14D28 || ||  ||
|--style="background-color:#EEEFF2"
| last syscall? || 0x20AD14D2C || ||  ||
|-
| {{cellcolors|#7698FF|#000000}}pc || 0x200414D34 || Will show "0x0", "0x1", "0x5", if the Allegrex cpu is idle(?). || ||
|--style="background-color:#EEEFF2"
| hi || 0x200414D38 || ||  ||
|-
| lo || 0x200414D3C || ||  ||
|--style="background-color:#EEEFF2"
| Memory base? || 0x200414D48 || Shows "0x08800000", could be used as pointer or something?|| ||
|-
|}
====PC pointer====
<br>PS4CHEATER
<br>'''PSP.cht'''
<pre>
1.5|eboot.bin|ID:|VER:01.00|FM:505
simple pointer|pointer|4 bytes|@C6B8C8_2_6B8C8+210+108|data|4 bytes|143011412|0||
</pre>
'''VFPU'''
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Register !! Offset !! Register !! Offset !! Register !! Offset !! Register !! Offset
|-
| S000|| 0x200414DE0 || S001|| 0x200414DE4 || S002|| 0x200414DE8 || S003|| 0x200414DEC
|-
| S010|| 0x200414DF0 || S011|| 0x200414DF4 || S012|| 0x200414DF8  || S013|| 0x200414DFC
|-
| S020|| 0x200414E00 || S021|| 0x200414E04 || S022||  0x200414E08 || S023|| 0x200414E0C
|-
|S030|| 0x200414E10 || S031|| 0x200414E14 || S032|| 0x200414E18  || S033|| 0x200414E1C
|-
|S100|| 0x200414E20  || S101|| 0x200414E24  || S102||  0x200414E28  || S103|| 0x200414E2C
|-
| S110 || 0x200414E30  || S111|| 0x200414E34 || S112||  0x200414E38 || S113||0x200414E3C
|-
| S120|| 0x200414E40  || S121|| 0x200414E44 || S122|| 0x200414E48 || S123|| 0x200414E4C
|-
|S130|| 0x200414E50 || S131||0x200414E54  || S132|| 0x200414E58  || S133|| 0x200414E5C
|-
|S200|| 0x200414E60  || S201|| 0x200414E64 || S202||  0x200414E68 || S203||0x200414E6C
|-
|S210|| 0x200414E70  || S211|| 0x200414E74 || S212||  0x200414E78 || S213|| 0x200414E7C
|-
|S220|| 0x200414E80  || S221|| 0x200414E84 || S222|| 0x200414E88 || S223|| 0x200414E8C
|-
|S230|| 0x200414E90 || S231|| 0x200414E94 || S232||  0x200414E98 || S233|| 0x200414E9C
|-
|S300|| 0x200414EA0  || S301|| 0x200414EA4 || S302||  0x200414EA8 || S303|| 0x200414EAC
|-
|S310|| 0x200414EB0  || S311|| 0x200414EB4 || S312|| 0x200414EB8  || S313|| 0x200414EBC
|-
|S320|| 0x200414EC0  || S321|| 0x200414EC4 || S322|| 0x200414EC8 || S323||0x200414ECC
|-
|S330|| 0x200414ED0 || S331|| 0x200414ED4 || S332|| 0x200414ED8 || S333||0x200414EDC
|-
|S400|| 0x200414EE0  || S401||  0x200414EE4 || S402|| 0x200414EE8 || S403|| 0x200414EEC
|-
|S410|| 0x200414EF0  || S411||  0x200414EF4 || S412||  0x200414EF8 || S413|| 0x200414EFC
|-
|S420|| 0x200414F00 || S421|| 0x200414F04 || S422||  0x200414F08 || S423|| 0x200414F0C
|-
|S430|| 0x200414F10 || S431|| 0x200414F14 || S432||  0x200414F18 || S433|| 0x200414F1C
|-
|S500|| 0x200414F20 || S501|| 0x200414F24|| S502|| 0x200414F28 || S503|| 0x200414F2C
|-
|S510|| 0x200414F30  || S511|| 0x200414F34 || S512|| 0x200414F38 || S513|| 0x200414F3C
|-
|S520|| 0x200414F40 || S521|| 0x200414F44 || S522|| 0x200414F48 || S523||0x200414F4C
|-
|S530 || 0x200414F50|| S531|| 0x200414F54 || S532||  0x200414F58|| S533|| 0x200414F5C
|-
|S600|| 0x200414F60 || S601|| 0x200414F64 || S602|| 0x200414F68 || S603|| 0x200414F6C
|-
|S610|| 0x200414F70  || S611|| 0x200414F74 || S612||  0x200414F78 || S613||0x200414F7C
|-
|S620|| 0x200414F80  || S621|| 0x200414F84 || S622|| 0x200414F88 || S623|| 0x200414F8C
|-
|S630 || 0x200414F90 || S631|| 0x200414F94 || S632||  0x200414F98 || S633|| 0x200414F9C
|-
|S700|| 0x200414FA0 || S701 || 0x200414FA4 || S702|| 0x200414FA8  || S703|| 0x200414FAC
|-
|S710|| 0x200414FB0  || S711|| 0x200414FB4 || S712||  0x200414FB8 || S713|| 0x200414FBC
|-
|S720|| 0x200414FC0  || S721|| 0x200414FC4 || S722|| 0x200414FC8 || S723|| 0x200414FCC
|-
|S730 || 0x200414FD0|| S731|| 0x200414FD4 || S732||  0x200414FD8 || S733|| 0x200414FDC
|-
|}
 
= Known issues =
{| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;"
! Issue !! Games affected !! Solution !! Description
|-
| No gamdata installation functionality (?)|| || ||
|-
| Highly unoptimized graphics renderer || || || Low fps
|-
| No support for some syscalls || || ||
|-
|}
 
=LUA include files=
<br>Files that need to be placed in the '''/lua_include/''' folder
 
'''uv-clamping.lua'''
<pre>
print ("Loading uv-clamping.lua from global scripts")
 
UV_CLAMPING_ENABLE = true
UV_CLAMPING_DISABLE = false
 
UV_CLAMPING_USE_ZERO_EDGE_ALPHA = true
UV_CLAMPING_DONT_USE_ZERO_EDGE_ALPHA = false
 
emuObj = getEmuObject()
 
-- Turns off UV clamping for the given list of textures.
-- textureTable: A list of texture base addresses.
DisableUvClampingForTextures = function(textureTable)
if emuObj.OverrideUvClampingState then
for _, texAddr in ipairs(textureTable) do
emuObj.OverrideUvClampingState(texAddr, UV_CLAMPING_DISABLE, UV_CLAMPING_DONT_USE_ZERO_EDGE_ALPHA);
end
else
print ("This emulator does not support OverrideUvClampingState()")
end
end
 
</pre>
'''sce-locale.lua'''
<pre>
print ("Loading sce-locale.lua from global scripts")
 
-- Language codes
--
-- ja    Japanese
-- en    English (US)
-- fr    French (France)
-- es    Spanish (Spain)
-- de    German
-- it    Italian
-- nl    Dutch
-- pt    Portuguese (Portugal)
-- ru    Russian
-- ko    Korean
-- zh-TW  Chinese (traditional)
-- zh-CN  Chinese (simplified)
-- fi    Finnish
-- sv    Swedish
-- da    Danish
-- no    Norwegian
-- pl    Polish
-- pt-BR  Portuguese (Brazil)
-- en-GB  English (UK)
-- tr    Turkish
-- es-MX  Spanish (Latin America)
-- ar    Arabic
-- fr-CA  French (Canada)
-- cs    Czech
-- hu    Hungarian
-- el    Greek ("Ελληνικά" in the system language menu)
-- ro    Romanian
-- th    Thai
-- vi    Vietnamese
-- id    Indonesian
-- uk    Ukrainian
 
-- returns locale (en-US) and language only (us), useful for lookups with fallback.
GetLocaleLangPair = function()
local locale, lang
locale = AppHost_GetLocaleTag()
lang = locale:sub(1,2)    -- grab first two digits, eg. en-US -> en
 
print ("[BOOT] App Host Langauge =", lang)
 
if locale ~= nil then
print ("[BOOT] App Host Locale =", locale)
else
print ("[BOOT] Deprecated Native Language =", lang)
end
 
return locale, lang
end
 
FindLocaleTableKey = function(table, primary, fallback, default)
-- try for a specific Locale, and if that fails fallback on just a language (without region),
-- and if that fails fallback on default.
 
local keyres = primary
if keyres == nil or table[keyres] == nil then
keyres = fallback
end
 
if keyres == nil or table[keyres] == nil then
print ("WARNING: No table entry for locale", primary, "or language", fallback, ", using default", default);
keyres = default
else
print ("Found locale table entry", keyres);
end
 
return keyres
end
 
</pre>
'''disc-selection.lua'''
<pre>
print ("Loading disc-selection.lua from global scripts")
require "sce-locale"
 
-- Determines and sets the active SKU.
--
-- sku_map: Cannot be nil.  A table of the form
-- {
-- en = <sku dir name>,
-- fr = <sku dir name>,
-- de = <sku dir name>,
-- it = <sku dir name>,
-- es = <sku dir name>,
--  ...
-- }
--
RegisterSkus = function(sku_map, default_locale)
if default_locale == nil then
default_locale = "en"
end
local locale, lang = GetLocaleLangPair()
local key = FindLocaleTableKey(sku_map, locale, lang, default_locale)
local sku_name = sku_map[key]
 
if EM_SetActiveSku == nil then
print "EM_SetActiveSku is undefined, use the stable branch of the packager or use a new version of the emulator."
end
EM_SetActiveSku(sku_name)
 
end
 
</pre>
 
'''ax-gpr-alias.lua'''
<pre>
 
-- Recommended method to import this module:
--  local gpr = require("ax-gpr-alias")
 
 
gpr = {}
 
gpr.zero = 0
gpr.at  = 1
gpr.v0  = 2
gpr.v1  = 3
gpr.a0  = 4
gpr.a1  = 5
gpr.a2  = 6
gpr.a3  = 7
gpr.t0  = 8
gpr.t1  = 9
gpr.t2  = 10
gpr.t3  = 11
gpr.t4  = 12
gpr.t5  = 13
gpr.t6  = 14
gpr.t7  = 15
gpr.s0  = 16
gpr.s1  = 17
gpr.s2  = 18
gpr.s3  = 19
gpr.s4  = 20
gpr.s5  = 21
gpr.s6  = 22
gpr.s7  = 23
gpr.t8  = 24
gpr.t9  = 25
gpr.k0  = 26
gpr.k1  = 27
gpr.gp  = 28
gpr.sp  = 29
gpr.fp  = 30
gpr.ra  = 31
 
return gpr
 
</pre>
'''multiapp.lua'''
<pre>
-- Recommended method to import this module:
--  local mapp = require("mapp")
--
-- Multi-application support module
-- Wraps common hook calls to support multiple executables
--
 
local emuObj = getEmuObject() -- emulator
local axObj = getAXObject() -- allegrex
 
mapp = {}
mapp.curAppName = emuObj.GetAppName()
 
mapp.AddBootHook = function(app, func)
if mapp[app] == nil then
mapp[app] = {}
end
 
mapp[app].boot = func
end
 
mapp.AddHook = function(app, pc, verify, func)
if mapp[app] == nil then
mapp[app] = {}
end
if mapp[app].hooks == nil then
mapp[app].hooks = {}
mapp[app].hookids = 1
end
local localid = mapp[app].hookids
mapp[app].hookids = mapp[app].hookids + 1
local handler = { addr = pc, v = verify, f = func, id = 0 }
if mapp.curAppName == app then
handler.id = axObj.AddHook(pc, verify, func)
end
-- print(string.format("Added Hook for app: %s, pc=%08x, handler=%d", app, pc, localid))
mapp[app].hooks[localid] = handler
return localid
end
 
mapp.RemoveHook = function(app, hookid)
-- print(string.format("RemoveHook for app: %s, id=%d", app, hookid))
if mapp[app] ~= nil then
if mapp[app].hooks ~= nil then
if mapp[app].hooks[hookid] ~= nil then
local id = mapp[app].hooks[hookid].id
mapp[app].hooks[hookid] = nil -- WBD 7/6/2018
if mapp.curAppName == app and id > 0 then
axObj.RemoveHook(id)
end
end
end
end
end
 
mapp.GetHookPC = function(app, hookid)
if mapp[app] ~= nil then
if mapp[app].hooks ~= nil then
if mapp[app].hooks[hookid] ~= nil then
return mapp[app].hooks[hookid].addr
end
end
end
return 0
end
 
mapp.AddVSyncHook = function(app, func)
if mapp[app] == nil then
mapp[app] = {}
end
mapp[app].vsync = func
if mapp.curAppName == app then
emuObj.AddVsyncHook(func)
end
end
 
mapp.RemoveVSyncHook = function(app)
if mapp[app] == nil then
mapp[app] = {}
end
if mapp[app].vsync ~= nil then
table.remove(mapp[app].vsync)
end
if mapp.curAppName == app then
emuObj.RemoveVsyncHook(func)
end
end
 
-- Actual switch functionality
emuObj.AddBootHook(function()
local app = emuObj.GetAppName()
 
if app ~= mapp.curAppName then
-- switch out the old handlers
-- print(string.format("Switching out handlers for app: %s", mapp.curAppName))
if mapp[mapp.curAppName] ~= nil then
if mapp[mapp.curAppName].vsync ~= nil then
emuObj.RemoveVsyncHook()
end
if mapp[mapp.curAppName].hooks ~= nil then
local hooks = mapp[mapp.curAppName].hooks
-- print(string.format("hooks: %d", #hooks))
for k,v in pairs(hooks) do
if v.id > 0 then
axObj.RemoveHook(v.id)
v.id = 0
end
end
end
end
-- switch current app name
mapp.curAppName = app
-- install the new handlers
-- print(string.format("Switching in handlers for app: %s", mapp.curAppName))
if mapp[mapp.curAppName] ~= nil then
if mapp[mapp.curAppName].vsync ~= nil then
emuObj.AddVsyncHook(mapp[mapp.curAppName].vsync)
end
if mapp[mapp.curAppName].hooks ~= nil then
local hooks = mapp[mapp.curAppName].hooks
-- print(string.format("hooks: %d", #hooks))
for k,v in pairs(hooks) do
v.id = axObj.AddHook(v.addr, v.v, v.f)
end
end
end
end
if mapp[mapp.curAppName] ~= nil then
if mapp[mapp.curAppName].boot ~= nil then
mapp[mapp.curAppName].boot()
end
end
end)
 
return mapp


</pre>
</pre>
'''pad.lua'''
'''pad.lua'''
<pre>
<pre>
Line 1,592: Line 911:
├── lua_include
├── lua_include
│  ├── ax-gpr-alias.lua
│  ├── ax-gpr-alias.lua
│  ├── multiapp.lua
│  ├── sce-locale.lua
│  ├── uv-clamping.lua
│  ├── disc-selection.lua
│  └── pad.lua
│  └── pad.lua
├── scripts
├── scripts
Line 2,225: Line 1,540:
* https://forums.ppsspp.org/showthread.php?tid=11961
* https://forums.ppsspp.org/showthread.php?tid=11961
* https://github.com/LunaMoo/PPSSPP_workarounds/blob/master/cheat.db
* https://github.com/LunaMoo/PPSSPP_workarounds/blob/master/cheat.db
* https://www.psdevwiki.com/ps4/Talk:PSP_Emulator_Compatibility_List#Official_PSPemu_Configuration_Files
* https://www.psdevwiki.com/ps4/PSP_Emulator_Compatibility_List


===More Information:===
===More Information:===
Please note that all contributions to PS4 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS4 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)