Editing PSP Emulation
Jump to navigation
Jump to search
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: | ||
=='''PSPHD'''== | |||
The new PS Plus PSP emulator 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 as the ps2 emulator due to the existence of an unofficial PPSSPP core in the unofficial Retroarch port for the PS4. As far as the compatibility and performance go, the Retroarch core is yet to be bested. This 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. | |||
== '''PSPHD''' == | |||
The PSP emulator | |||
== 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 commands === | === CLI commands === | ||
These commands can be added to any of these files: | These commands can be added to any of these files: | ||
Line 157: | Line 94: | ||
|- | |- | ||
|-style="background-color:#7698FF" | |-style="background-color:#7698FF" | ||
| || Speedhacks | | || Speedhacks || || | ||
|- | |- | ||
| --antialias || off || Turning Anti-Alias Off Improves Performance||--antialias=off | | --antialias || off || Turning Anti-Alias Off Improves Performance||--antialias=off | ||
Line 200: | Line 137: | ||
|- | |- | ||
| --active-sku || || || | | --active-sku || || || | ||
|- | |- | ||
|} | |} | ||
Line 248: | Line 161: | ||
===XXXXYYYYY_patches.lua=== | ===XXXXYYYYY_patches.lua=== | ||
The lua can be placed as: '''scripts\XXXXYYYYY_patches.lua''' | The lua can be placed as: '''scripts\XXXXYYYYY_patches.lua''' | ||
====Emulator commands==== | ====Emulator commands==== | ||
{| 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 !! Usage !! Notes - Example | ! Command !! Usage !! Notes - Example | ||
Line 485: | Line 396: | ||
|} | |} | ||
==== | ====Examples==== | ||
<br>''' | <br>'''''LUA example:''''' | ||
<br>"NPEZ00164" | <br> | ||
<br>Coconut Dodge "NPEZ00164" | |||
<pre> | <pre> | ||
local axObj = getAXObject() | local axObj = getAXObject() | ||
Line 494: | Line 406: | ||
local patcher = function() | local patcher = function() | ||
--Infinite lives | --Infinite lives | ||
axObj.WriteMem32(0x8ACA1A4, 0x3) --0x08ACE1A4 on PPSSPP | axObj.WriteMem32(0x8ACA1A4, 0x3) --0x08ACE1A4 on PPSSPP, PPSSPP addresses need to be reduced by 0x4000 in order to work on PS4 | ||
end | end | ||
emuObj.AddVsyncHook(patcher) | emuObj.AddVsyncHook(patcher) | ||
</pre> | </pre> | ||
[https://www.psdevwiki.com/ps4/Talk:PSP_Emulator_Compatibility_List#Official_PSPemu_Configuration_Files More patches can be found here] | [https://www.psdevwiki.com/ps4/Talk:PSP_Emulator_Compatibility_List#Official_PSPemu_Configuration_Files More patches can be found here] | ||
=====Patches.lua===== | |||
====Patches.lua==== | |||
======Syphon Filter: Dark Mirror====== | ======Syphon Filter: Dark Mirror====== | ||
Line 589: | Line 485: | ||
cpu.InsnReplace(0x8c163e0, 0x3c0408ee, 0x00000000) -- nop | cpu.InsnReplace(0x8c163e0, 0x3c0408ee, 0x00000000) -- nop | ||
</pre> | </pre> | ||
======Patapon 2'''====== | ======Patapon 2'''====== | ||
<pre> | <pre> | ||
-- Lua 5.3 | -- Lua 5.3 | ||
Line 997: | Line 891: | ||
== Emulators == | == 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;" | {| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;" | ||
! Emulator !! Usage !! API Version !! Similar emulators (compatibility) | ! Emulator !! Usage !! API Version !! Similar emulators (compatibility) | ||
|- | |- | ||
| Echochrome || The default | | Echochrome || The default psp emulator for PSPFPKG tool at the time of writing and the best in terms of compatibility. || ? || ? | ||
|- | |- | ||
| | | LocoRoco Midnight Carnival || ? || ? || ? | ||
|- | |- | ||
| LocoRoco | | LocoRoco 1 || ? || ? || ? | ||
|- | |- | ||
| LocoRoco | | LocoRoco 2 || ? || ? || ? | ||
|- | |- | ||
| | | Castlevania Requiem || ? || ? || ? | ||
|- | |- | ||
| Patapon 2 | | Patapon 2 || ? || ? || ? | ||
|- | |- | ||
| | | PaRappa the Rapper || An unofficial emulator developed by sony with very bad compatibility || ? || ? | ||
|- | |- | ||
| | | Syphon Filter: Dark Mirror || ? || ? || ? | ||
|- | |- | ||
|} | |} | ||
== Memory mapping == | ==Memory mapping== | ||
<br>'''Note''': The memory on PPSSPP is 0x4000 offsets ahead of the memory on the PS4 | <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;" | {| cellspacing="0" cellpadding="2" border="1" class="wikitable" style="text-align: center;" | ||
Line 1,219: | Line 1,107: | ||
! Issue !! Games affected !! Solution !! Description | ! Issue !! Games affected !! Solution !! Description | ||
|- | |- | ||
| | | Lack of ability to install gamedata (?)|| || || | ||
|- | |- | ||
| Highly unoptimized graphics renderer || || || Low fps | | Highly unoptimized graphics renderer || || || Low fps | ||
|- | |- | ||
| | | Lack of support for some syscalls || || || | ||
|- | |- | ||
|} | |} | ||
= | =LUA include files= | ||
<br>Files that need to be placed in the '''/lua_include/''' folder | <br>Files that need to be placed in the '''/lua_include/''' folder | ||
''' | '''ax-gpr-alias.lua''' | ||
<pre> | <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> | </pre> | ||
''' | '''multiapp.lua''' | ||
<pre> | <pre> | ||
-- Recommended method to import this module: | |||
-- local mapp = require("mapp") | |||
-- | |||
-- Multi-application support module | |||
-- Wraps common hook calls to support multiple executables | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | -- | ||
if | 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 | end | ||
mapp[app].boot = func | |||
end | 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 | |||
return | 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) | |||
mapp. | |||
if mapp[app] == nil then | if mapp[app] == nil then | ||
mapp[app] = {} | mapp[app] = {} | ||
end | end | ||
mapp[app]. | mapp[app].vsync = func | ||
if mapp.curAppName == app then | |||
emuObj.AddVsyncHook(func) | |||
end | |||
end | end | ||
mapp. | mapp.RemoveVSyncHook = function(app) | ||
if mapp[app] == nil then | if mapp[app] == nil then | ||
mapp[app] = {} | mapp[app] = {} | ||
end | end | ||
if mapp[app]. | if mapp[app].vsync ~= nil then | ||
table.remove(mapp[app].vsync) | |||
end | end | ||
if mapp.curAppName == app then | if mapp.curAppName == app then | ||
emuObj.RemoveVsyncHook(func) | |||
end | end | ||
end | end | ||
-- Actual switch functionality | |||
-- print(string.format(" | emuObj.AddBootHook(function() | ||
local app = emuObj.GetAppName() | |||
if app ~= mapp.curAppName then | |||
if mapp[ | -- switch out the old handlers | ||
local | -- print(string.format("Switching out handlers for app: %s", mapp.curAppName)) | ||
if mapp[mapp.curAppName] ~= nil then | |||
if | 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 | end | ||
end | end | ||
-- switch current app name | |||
mapp.curAppName = app | |||
mapp. | |||
-- install the new handlers | |||
-- print(string.format("Switching in handlers for app: %s", mapp.curAppName)) | |||
if mapp[ | 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 | end | ||
end | end | ||
if mapp[mapp.curAppName] ~= nil then | |||
if mapp[mapp.curAppName].boot ~= nil then | |||
mapp[mapp.curAppName].boot() | |||
mapp. | end | ||
end | end | ||
end) | |||
mapp | return mapp | ||
-- | </pre> | ||
'''pad.lua''' | |||
<pre> | |||
-- Recommended method to import this module: | |||
-- local pad = require("pad") | |||
-- | |||
-- Buttons marked PS4 are not used by the emulator, but can be read from Lua | |||
-- | |||
-- Read the Pad state with getEmuObject().PadRead() | |||
-- ie: | |||
-- local padstate = getEmuObject().PadRead() | |||
-- | |||
pad = {} | |||
pad.L3 = 0x00000002 -- L3 (PS4) | |||
pad.R3 = 0x00000004 -- R3 (PS4) | |||
-- | pad.OPTIONS = 0x00000008 -- Options (PS4) | ||
pad.UP = 0x00000010 -- Up | |||
pad.RIGHT = 0x00000020 -- Right | |||
pad.DOWN = 0x00000040 -- Down | |||
pad.LEFT = 0x00000080 -- Left | |||
pad.L2 = 0x00000100 -- L2 (PS4) | |||
pad.R2 = 0x00000200 -- R2 (PS4) | |||
pad.L1 = 0x00000400 -- L1 | |||
pad.R1 = 0x00000800 -- R1 | |||
-- | pad.TRIANGLE = 0x00001000 -- Triangle | ||
pad.CIRCLE = 0x00002000 -- Circle | |||
pad.CROSS = 0x00004000 -- Cross | |||
pad.SQUARE = 0x00008000 -- Square | |||
pad.SELECT = 0x00010000 -- Select | |||
pad.START = 0x00020000 -- Start | |||
-- | |||
-- | |||
-- Automap SELECT or START to the Options Button, leaving the full touchar for the opposite, with getEmuObject().PadSetButtonsMode(mode) | |||
-- ie: | |||
-- getEmuObject().PadSetButtonsMode(pad.BUTTONS_MODE_OPTION_IS_SELECT) | |||
pad.BUTTONS_MODE_NORMAL = 0 -- Touch bar is split in two for Start/Select. Option is unmapped (default behaviour) | |||
pad.BUTTONS_MODE_OPTION_IS_SELECT = 1 -- Touch bar is Start. Option is Select | |||
pad.BUTTONS_MODE_OPTION_IS_START = 2 -- Touch bar is Select. Option is Start | |||
return pad | |||
</pre> | |||
=Information= | |||
Note: Missing entries | |||
==Folder/File layout== | |||
<pre> | |||
pad. | ├── assets | ||
│ ├── common | |||
│ └── PSPHD | |||
├── app | |||
│ └── USER_L0.IMG | |||
├── lua_include | |||
│ ├── ax-gpr-alias.lua | |||
│ ├── multiapp.lua | |||
│ └── pad.lua | |||
├── scripts | |||
│ ├──XXXXYYYYY_patches.lua | |||
│ ├──XXXXYYYYY_features.lua | |||
│ ├──XXXXYYYYY_tooling.lua | |||
│ └──XXXXYYYYY_trophies.lua | |||
├── sce_module | |||
├── sce_sys | |||
├── vms | |||
├── trophy_data | |||
├── usermodule | |||
│ └──libfont.lib | |||
├── sce_discmap.plt | |||
├── eboot.bin | |||
├── revision.conf | |||
├── package-ps4.conf | |||
└── config-title.txt | |||
</pre> | |||
==Other== | |||
= | |||
<pre> | <pre> | ||
XXXXYYYYY_config.txt | |||
videos/ | |||
.mp4 | |||
videos/%08x.mp4 | |||
audio/%08x.ogg | |||
Paths: | |||
/app0/ | |||
/download0/ | |||
/savedata | |||
/host/ | |||
/hostapp/ | |||
/data/ | |||
</pre> | |||
==Sample== | |||
<pre>; PS4 configuration file for PSPHD | |||
<pre> | |||
; PS4 configuration file for PSPHD | |||
; Game Image | ; Game Image | ||
Line 1,746: | Line 1,465: | ||
--parappaalphahack=true | --parappaalphahack=true | ||
</pre> | </pre> | ||
==NIDs in HLE== | |||
== NIDs in HLE == | |||
<pre> | <pre> | ||
|HLEInterruptManager| | |HLEInterruptManager| | ||
Line 2,352: | Line 2,009: | ||
* 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/ | * https://www.psdevwiki.com/ps4/Talk:PSP_Emulator_Compatibility_List#Official_PSPemu_Configuration_Files | ||
* https://www.psdevwiki.com/ps4/PSP_Emulator_Compatibility_List | * https://www.psdevwiki.com/ps4/PSP_Emulator_Compatibility_List | ||