PS4 PSP on PS4 - New Information by mysis released

Discussion in 'PS4 News' started by STLcardsWS, Aug 15, 2018.

By STLcardsWS on Aug 15, 2018 at 7:04 PM
  1. 7,610
    6,486
    747
    STLcardsWS

    STLcardsWS Administrator

    Joined:
    Sep 18, 2014
    Messages:
    7,610
    Likes Received:
    6,486
    Trophy Points:
    747

    Today developer mysis has released new information regarding PSP emulation on the PS4, back in early May there was various discoveries found with PSP emulation (on PS4) by KiiWii as outlined in this article but overall the news while very positive left many unknowns as these sort of things don't come with instructions manuals. However, thanks to mysis's recent research we now know a bit more about this how emulator operates and can start logging those pages for the manual`and hopefully improve game comparability. Below you will find the discoveries that mysis has provided.


    17n6vwnj-900.jpg

    • Hi,

      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."


     
    Last edited: Aug 15, 2018
    Stayhye, pink1, Zazenora and 6 others like this.

Comments

Discussion in 'PS4 News' started by STLcardsWS, Aug 15, 2018.

    1. kozarovv
      kozarovv
      Zazenora and STLcardsWS like this.
    2. Zazenora
      Zazenora
      I'm excited to see some research progress for backwards compatible emulation on the PS4.
      It's inspiring to see the dedication you guys put into doing this.
      You are working towards making these consoles what they should have been from the very beginning.
    3. mysis
      mysis
      I dont think this was news worthy xD
      STLcardsWS likes this.
    4. kozarovv
      kozarovv
      I think it was, but.. If you have anything related to PSPtoPS4 that is more newsworthy, then you know.. We can write about it. ;)
      STLcardsWS and Zazenora like this.
    5. pinky
      pinky
      humble 'til the end. that's very meritorious. ;)
    6. sandungas
      sandungas
      Now you cant escape, the scene took you back into R&D
      Also, dont forget you are part of the emulator mafia, and there is only one way to get out of a mafia (girlfriends)
      Dont make us do what we dont want to do (to send you a waifu)
    7. STLcardsWS
      STLcardsWS
      You may be correct, but at the same time its progress and that is what the news was trying to convey. We get alot of questions about the progress on PSP on PS4, so this was a little update for those user's as well, As it shows there is still work to be done with the emu and that devs like yourself are looking and conducting / detailing great research (Thanks !!!! :) ). So for me i consider it news worthy, There is all different types of news and what is news worthy is always subjective, I try and keep things interesting and diverse, not that i always succeed, but that is the goal :) .
      Zazenora and pinky like this.
    8. pink1
      pink1

Share This Page