PSXHAX

Staff Member
Moderator
Contributor
Verified
PS4 JAILBREAK PSP Injection Tutorial (PSPHD BASIC INJECTION TUTORIAL) by seanp2500

:note: Here's a Tutorial by strann0, and also another from KiiWii to quote: [WIP] PSP Injection

BASIC INJECTION TUTORIAL:

You will need:
  • orbis-pub-chk
  • orbis-pub-gen
  • parappa the rappa/patapon/loco roco 2 remasters fpkg
  • A compatible PSP iso (also currently very few work, examples: lumines, loco roco games, patapon games (stuck at "sign" screen)) or build your own homebrew iso (See Optional)
  • [plain]HXD[/plain]
  • notepad
  • gimp2
Start here:

Open the FPKG with pub-chk using all 0's as the key and extract ALL the content.

Copy all EXCEPT the playgo/psreserved/keystone files from the Sc0 folder

Locate Image0>sce_sys folder and paste the files in. (should look like this :))
Code:
/about
/trophy
icon0.dds
icon0.png
nptitle.dat
npbind.dat
param.sfo
pic0.dds
pic0.png
pic1.dds
pic1.png
pronunciation.sig
pronunciation.xml
save_data.png
shareparam.json
snd0.at9
Replacing the game:

Locate Image0 > data folder and delete the USER_L0.IMG

(Trivia: L0 refers to layer 0 and L1 refers to layer 1 for PSP umd creation, L0&L1 can be = 900mb max, combined 1.8gb max)

Copy your PSP ISO to this location and to make things easier name it game.iso

Simple!

OPTIONAL Making your own homebrew ISO:

You need to locate: UMDGEN 4.0 & EBOOT2ISO 1.1

Open EBOOT2ISO, and select your homebrew eboot.pbp, put the output path as the same folder you are currently in, and click CONVERT

Place any files that came with the homebrew eboot.pbp into PSP_GAME/Sysdir. (Rom folders go here too FYI)

Open UMDGEN, drag the PSP_GAME folder into UMDGen, click the UMD PROPERTIES tab and click GENERATE.

Click Save and select UNCOMPRESSED ISO.

Rename to game.iso and place in Image0 > data folder to test.

(Massive thanks to Ploggy for the mini tut!)

Editing the configuration:

Locate Image0 > config-emu-ps4.txt (make a back up somewhere else first just in case) open it in notepad:

Edit the "Game Image" part to this:
Code:
; Game Image
--image="data/game.iso"
Now go through config-emu-ps4.txt and ";" comment out EVERY uncommented command (you can actually leave SSAA4x if you want), for example:

Enabled:
Code:
; This enables bilinear filtering on replaced textures. (uncomment to enable)
--replacementfilter=true
Disabled (commented out):
Code:
; This enables bilinear filtering on replaced textures. (uncomment to enable)
;--replacementfilter=true
Save config-emu-ps4.txt and exit.

Editing icons and SFO:

To edit the SFO use HXD (make a back up somewhere else first just in case) you can edit (in three places) the line "PaRappa The Rapperâ„¢ Remastered" to almost any string you like, careful to maintain the length, for example mine is now set to: "PSPHD INJECTIONZ TEST REMASTERED"

You can also overwrite the CUSA ID/UCUS ID to individualize the game and allow more than one to be installed. For example: UP9000-CUSA05289_00-UCUS987020000001 is parappa original > EP9000-UCUS00304_00-UCUS003040000100 = Custom ID using Loco Roco's actual UCUS ID. (thanks Shopeg over at hax)

Dont forget the CUSA05289 line at the very bottom of the SFO too.

Save Param.SFO and exit.

Now go to Image0 > sce_sys and edit nptitle.dat with HXD to match the CUSA ID you used in the SFO.

To edit the icons and bg PNG's I suggest start new images in GIMP2 (or your preferred image editor):
  • 512x512 24bit PNG for Icon0.png
  • 1920x1080 24bit PNG for pic0.png and pic1.png
  • 228x128 24bit PNG for save_data.png
(if you have issues with PNG being 8bit or 32 bit, simply save png as jpg (which is 24 bit by default), then re-save that jpg as png, and you now have 24bit png)

Stripping out unneeded files:

You can remove pretty much anything that relates to texture/movie/sample swaps, languages, etc leaving a bare bones set of directories ready to customize your own in future. For this tutorial I have left pretty much everything up to you to make it simpler. Feel free to experiment with what files are and aren't needed (for example .dds files arent needed ;))

Rebuilding the FPKG:
  • Open pub-gen, double click image0 in right pane, drag contents of your Image0 folder into that directory,
  • Click chunk panel on left, right click image0 on left and tick switch chunks, press C to close that pane.
  • Click command > project settings>package: give the pkg a name in the format "XXYY-XXXXYYYYY_00-ZZZZZZZZZZZZZZZZ" = use the ID you gave it while editing the SFO for easy way to remember it.
  • Give the FPKG a passcode (32 0's is HIGHLY recommended)
  • Click ok, hit build (far right) then set directory for output PKG, once selected then hit tab and hit enter to start the FPKG build.
Once done save the GP4 file (you can simply swap the iso over (cannot add or remove/rename files) and use this GP4 to quickly skip almost all steps in the rebuilding FPKG section: next time associate the GP4 file with gen-pub (in windows or your os), double click the GP4 and hit build.

You can rename the PKG anything you like, I name mine as <content vX>.pkg for example: Loco Roco v3.pkg (version denotes changes I have made in case of regressions)

Copy the FPKG to your exfat USB stick, and install to PS4 through [SETTINGS] > [DEBUG SETTINGS] > [GAME] > [PKG INSTALLER].

Enjoy and report back any specific PSP game success stories! (psdevwiki compatibility list)

Spoiler

Please feel free to contribute!

PS4HEN PSP PKGs for PS4
  • Age Of Zombies
  • Lumines
  • PaRappa the Rapper Remastered
  • Street Fighter Alpha 3 Max
:arrow: python fix_elf.py for PSP emulator via mysis, to quote:

So, the PSP Emulator on PS4 requires the BOOT.BIN to have certain section names that it is scanning. Most of the binaries actually do contain them AFTER decryption, but sometimes they are stripped. Luckily the string table is still there and sony left the offsets of the section header names intact. That means we can identify+restore them :D

Here is a script that can add those required (NPEZ00311, ULUS10567,..). If an empty entry is found, it will create a ".new" file. This will not magically make everything working, for that you still need to identify why the emulator is crashing, but you can read /dev/klog :)

I took partial elf reading code from flatz, so kudos to him: > python fix_elf.py <input_elf>
Code:
import struct
import sys

class ElfPHdr(object):
   FMT = '<8I'

   def __init__(self, idx):
       self.idx = idx
       self.type = None
       self.offset = None
       self.vaddr = None
       self.paddr = None
       self.filesz = None
       self.memsz = None
       self.flags = None
       self.align = None

   def load(self, f):
       self.type, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.flags, self.align = struct.unpack(ElfPHdr.FMT, f.read(struct.calcsize(ElfPHdr.FMT)))

class ElfSHdr(object):
   FMT = '<10I'

   def __init__(self, idx):
       self.idx = idx
       self.name = None
       self.name_end = None
       self.name_len = None
       self.type = None
       self.flags = None
       self.addr = None
       self.offset = None
       self.size = None
       self.link = None
       self.info = None
       self.align = None
       self.entsize = None

   def load(self, f):
       self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize = struct.unpack(ElfSHdr.FMT, f.read(struct.calcsize(ElfSHdr.FMT)))

class ElfEHdr(object):
   FMT = '<4s5B6xB'
   EX_FMT = '<2HI3II6H'

   def __init__(self):
       self.magic = None
       self.machine_class = None
       self.data_encoding = None
       self.version = None
       self.os_abi = None
       self.abi_version = None
       self.nident_size = None
       self.type = None
       self.machine = None
       self.version = None
       self.entry = None
       self.phoff = None
       self.shoff = None
       self.flags = None
       self.ehsize = None
       self.phentsize = None
       self.phnum = None
       self.shentsize = None
       self.shnum = None
       self.shstridx = None

   def load(self, f):
       self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size = struct.unpack(ElfEHdr.FMT, f.read(struct.calcsize(ElfEHdr.FMT)))
       self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx = struct.unpack(ElfEHdr.EX_FMT, f.read(struct.calcsize(ElfEHdr.EX_FMT)))

   def has_segments(self):
       return self.phentsize > 0 and self.phnum > 0

   def has_sections(self):
       return self.shentsize > 0 and self.shnum > 0

class ElfFile(object):
   def __init__(self):
       self.ehdr = None
       self.phdrs = None
       self.shdrs = None
       self.file_size = None
       self.segments = None
       self.sections = None
       self.shstrtab = None
       self.shstrtab_offset = None

   def load(self, f):
       start_offset = f.tell()
       data = f.read()
       self.file_size = len(data)
       f.seek(start_offset)

       self.ehdr = ElfEHdr()
       self.ehdr.load(f)

       self.phdrs = []
       self.segments = []
       if self.ehdr.has_segments():
           for i in xrange(self.ehdr.phnum):
               #print "[*] ElfPHdr Offset: %x" % (start_offset + self.ehdr.phoff + i * self.ehdr.phentsize)
               f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize)
               phdr = ElfPHdr(i)
               phdr.load(f)
               self.phdrs.append(phdr)
               if phdr.filesz > 0:
                   f.seek(start_offset + phdr.offset)
                   data = f.read(phdr.filesz)
               else:
                   data = ''
               self.segments.append(data)

       self.shdrs = []
       self.sections = []
       if self.ehdr.has_sections():
           for i in xrange(self.ehdr.shnum):
               #print "[*] ElfSHdr Offset: %x" % (start_offset + self.ehdr.shoff + i * self.ehdr.shentsize)
               f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize)
               shdr = ElfSHdr(i)
               shdr.load(f)
               self.shdrs.append(shdr)
           for i in xrange(self.ehdr.shnum):
               if self.shdrs[i].type == 3 and self.shdrs[i].size > 1:#self.shdrs[i].name_len == 9: # shstrtab
                   self.shstrtab_offset = self.shdrs[i].offset
                   print "[*] shstrtab found at: 0x%x" % self.shstrtab_offset
                   f.seek(self.shstrtab_offset)
                   self.shstrtab = f.read(self.shdrs[i].size)
                   #print self.shstrtab
           for i in xrange(self.ehdr.shnum):
               if i > 0:
                   self.shdrs[i-1].name_end = self.shdrs[i].name - 1
                   self.shdrs[i-1].name_len = self.shdrs[i-1].name_end - self.shdrs[i-1].name
                     #print "%d name_end - name - name_len: %x - %x = %x" % (i,self.shdrs[i-1].name_end, self.shdrs[i-1].name, self.shdrs[i-1].name_len)
               if i == self.ehdr.shnum-1:
                   self.shdrs[i].name_end = len(self.shstrtab) - 1
                   self.shdrs[i].name_len = self.shdrs[i].name_end - self.shdrs[i].name
                   #print "%d name_end - name - name_len: %x - %x = %x" % (i, self.shdrs[i].name_end, self.shdrs[i].name, self.shdrs[i].name_len)

if len(sys.argv) < 2:
   print "python fix_elf.py <in_elf>"
   sys.exit(0)

print "[.] Opening file %s..." % sys.argv[1]
f = open(sys.argv[1], "rb")
#f = open("ULUS10491.BIN", "rb")
#f = open("NPEZ00311.BIN", "rb")
#f = open("ULUS10567.BIN", "rb")
#f = open("NPUG80248.BIN", "rb")
#f = open("ULES00193.BIN", "rb")

elf_file = ElfFile()
elf_file.load(f)
print "[*] magic: %s" % elf_file.ehdr.magic
print "[*] machine_class: %x" % elf_file.ehdr.machine_class
print "[*] data_encoding: %x" % elf_file.ehdr.data_encoding
print "[*] version: %x" % elf_file.ehdr.version
print "[*] os_abi: %x" % elf_file.ehdr.os_abi
print "[*] abi_version: %x" % elf_file.ehdr.abi_version
print "[*] nident_size: %x" % elf_file.ehdr.nident_size
print "[*] type: 0x%x" % elf_file.ehdr.type
print "[*] machine: %x" % elf_file.ehdr.machine
print "[*] version: %x" % elf_file.ehdr.version
print "[*] entry: 0x%x" % elf_file.ehdr.entry
print "[*] phoff: 0x%x" % elf_file.ehdr.phoff
print "[*] shoff: 0x%x" % elf_file.ehdr.shoff
print "[*] flags: 0x%x" % elf_file.ehdr.flags
print "[*] ehsize: 0x%x" % elf_file.ehdr.ehsize
print "[*] phentsize: 0x%x" % elf_file.ehdr.phentsize
print "[*] phnum: 0x%x" % elf_file.ehdr.phnum
print "[*] shentsize: 0x%x" % elf_file.ehdr.shentsize
print "[*] shnum: 0x%x" % elf_file.ehdr.shnum
print "[*] shstridx: %x" % elf_file.ehdr.shstridx
# Check first name if empty or not to determine fixing
if elf_file.shstrtab[elf_file.shdrs[1].name:elf_file.shdrs[1].name_end].replace('\x00',"") == "":
   print "[!] No Section header names found!"
   print "[.] attempting to identify required sections..."
   PF_WRITE = 0x1
   PF_READ = 0x2
   PF_EXEC = 0x4
   PF_READ_EXEC = PF_READ | PF_EXEC
   PF_READ_WRITE = PF_READ | PF_WRITE
   to_fix = 5
   for i in xrange(elf_file.ehdr.shnum):
       if (elf_file.shdrs[i].flags & PF_READ_EXEC) == PF_READ_EXEC and elf_file.shdrs[i].name_len == len(".text"):
           print "[!] found .text at section %d" % i
           elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".text" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
           to_fix -= 1
       if elf_file.shdrs[i].type == 8 and elf_file.shdrs[i].name_len == len(".bss"):
           print "[!] found .bss at section %d" % i
           elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".bss" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
           to_fix -= 1
       if elf_file.shdrs[i].type == 1 and elf_file.shdrs[i].flags == 3 and elf_file.shdrs[i].name_len == len(".data"):
           print "[!] found .data at section %d" % i
           elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".data" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
           to_fix -= 1
       if elf_file.shdrs[i].type == 1 and elf_file.shdrs[i].size == 0x34 and elf_file.shdrs[i].name_len == len(".rodata.sceModuleInfo"):
           print "[!] found .rodata.sceModuleInfo at section %d" % i
           elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".rodata.sceModuleInfo" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
           to_fix -= 1
       if elf_file.shdrs[i].type == 3 and elf_file.shdrs[i].size > 1 and elf_file.shdrs[i].name_len == len(".shstrtab"):
           print "[!] found .shstrtab at section %d" % i
           elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".shstrtab" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
           to_fix -= 1
   if to_fix == 0:
       print "[.] Writing new file..."
       f.seek(0)
       data = f.read()
       data = data[:elf_file.shstrtab_offset] + elf_file.shstrtab + data[elf_file.shstrtab_offset+len(elf_file.shstrtab):]
       open(sys.argv[1] + ".new", "wb").write(data)
   else:
       print "[!] Error. Could not identify required sections."
print "Section Headers:"
print "  [Nr] Name                Type            Addr       Off    Size  Flg Lk Inf Al"
for i in xrange(elf_file.ehdr.shnum):
   print "   %02d %-15.15s (%02x) %08x       %08x   %06x %06x %x" % (i, elf_file.shstrtab[elf_file.shdrs[i].name:elf_file.shdrs[i].name_end].replace('\x00',""),elf_file.shdrs[i].name_len, elf_file.shdrs[i].type,elf_file.shdrs[i].addr,elf_file.shdrs[i].offset,elf_file.shdrs[i].size,elf_file.shdrs[i].flags)

f.close()
print "[.] done."
PSPHD Demo
Download: PSP HD GUI V1.0.0.0 (Latest psphd.zip) / GIT

To quote from xXxTheDarkprogramerxXx (aka @TheDarkprograme): This is a release of my psp chd gui it will repack psp games for ps4 emulation

Currently there is alot more research needed on the current psp emulation on the ps4

But i believe something will come soon to make this emu even better

As Always Please install the .application file in the zip attached and auto updates for this will be done via click once

Please feel free to use the psp menu (layout) as i spent the most time on it and it just looks sexy

Enjoy
XDPx
 

Picalo

Senior Member
Contributor
Verified
Hello all, can someone please help me. I am trying to swap the iso in patapon remastered to another patapon (Chinese to english).

Can someone please guide me?
 
Recent Articles
Mednafen PlayStation 4 Emulator v0.3 Config Mod Update via Markus95
Following the Mednafen PS4 2-Players Config Mod and his recent N64 PS2 on PS4 Port Demo, developer @Markus95 (aka @Kus00095) shared via Twitter a PS4 Mednafen v0.3 configuration update featuring...
Final PlayStation State of Play for 2019 Next Week, No PS5 News Planned
Today Sony announced their final 2019 PlayStation State of Play Conference will take place next Tuesday, December 10th at 6:00am Pacific Time / 9:00am Eastern Time. ❄ Their previous PS State of...
PS4 CEX2Semi-DEX: CEX Console with DEX Debug Settings via LightningMods
Following his previous release, PlayStation 4 developer @LightningMods shared a screenshot on Twitter of what he calls PS4 CEX2Semi-DEX geared towards those with a retail jailbreakable PS4 5.05...
PS4 IOCTL Nabber IDA 7.0-7.2 Script for IOCTL Requests by SocraticBliss
Proceeding his PS4 Module Dumper Payload and PS4 Kernel Fixup Script, PlayStation 4 developer @SocraticBliss (Twitter) added a PS4 IOCTL Nabber to his Github repository for use with the IDA...
Top