Advertisement
Guest User

QB EBOOT Insert v1

a guest
Feb 5th, 2016
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.37 KB | None | 0 0
  1. import binascii
  2. import os
  3. import shutil
  4. import struct
  5.  
  6. def is_hex(n):
  7.     try:
  8.         int(n, 16)
  9.     except ValueError:
  10.         return False
  11.     return True
  12.  
  13. INPUT_COL = 2
  14. PTR_COL = 3
  15. s1 = " .,'!?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~-&>():;/%"
  16. s2 = " .,’!?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~‐&>():;/%"
  17. translate_table = str.maketrans(s1, s2)    #For converting between ASCII and fullwidth SHIFT-JIS characters
  18.  
  19. if os.path.isfile('EBOOT.orig'):    #This is to create a copy of the original (for running tool multiple times)
  20.     pass
  21. elif os.path.isfile('EBOOT.BIN'):
  22.     shutil.copy('EBOOT.BIN', 'EBOOT.orig')
  23. else:
  24.     print('Missing EBOOT.bin.')
  25.     quit()
  26.  
  27. with open('EBOOT.orig', 'rb') as f:
  28.     filedata = bytearray(f.read())
  29. def load_input(filename):
  30.     inputdata = []
  31.     with open(filename, 'r', encoding='utf-8') as f:
  32.         for line in f:
  33.             line = line.rstrip('\r\n').split('\t')
  34.             if line[0] != '':               #New entry
  35.                 ptrs = []
  36.                 for ptr in line[PTR_COL:]:  
  37.                     if is_hex(ptr):
  38.                         ptr = int(ptr, 16)
  39.                     else:                   #End of pointer list
  40.                         break
  41.                     ptrs.append(ptr)
  42.                 inputdata.append([int(line[0], 16), line[INPUT_COL], ptrs]) #addr, text, ptrs
  43.             else:                           #Additional line for same entry
  44.                 inputdata[-1][1] += '\x0a' + line[INPUT_COL]
  45.     return inputdata
  46.  
  47. #Insert SHIFT-JIS text (which is most of it)
  48. inputdata = load_input('SJIS.tsv')
  49. nextpos = 0x16CE00                          #Start of extra data (expanded EBOOT)
  50. for addr, text, ptrs in sorted(inputdata, key=lambda x: x[0], reverse=True):
  51. #Go backwards (reverse = True) // key is addr - we want to do later lines first
  52.     endpos = filedata.find(b'\x00', addr)   #Find end of string
  53.     while filedata[endpos] == 0:            #Find start of next string
  54.         endpos += 1
  55.     endpos -= 2                             #Need 2 nulls (at least) for SJIS terminator (I think)
  56.     avail_space = endpos - addr            
  57.     text = text.translate(translate_table).encode('cp932')
  58.     if len(text) > avail_space:                         #NOT enough space
  59.         filedata[addr:endpos] = b'\x00' * avail_space   #Blank out the line
  60.         text += b'\x00' * 2                             #Add terminator
  61.         while len(text) % 4 != 0:                       #Align to word boundary
  62.             text += b'\x00'
  63.         filedata[nextpos:nextpos+len(text)] = text      #Insert text
  64. #Compute virtual address (vaddr) - 0x89C4200 is the difference between file
  65. #image position and virtual address for text in the EBOOT extra data area
  66.         vaddr = nextpos + 0x89C4200
  67.         for ptr in ptrs:
  68.             if ptr > 0x08000000:                        #Virtual address specified in input
  69. #0x8803F8C is the difference between file image position and virtual address
  70. #for text in the original EBOOT area (not the extra data section)
  71.                 vaddr_orig = addr + 0x8803F8C          
  72.                 if (vaddr & 0xFFFF) > 0x8000:           #Accomodate addiu instructions (all of them are addiu)
  73.                     vaddr += 0x10000
  74.                 ptr = ptr - 0x8803F8C                   #Find file address of ptr
  75.                 filedata[ptr:ptr+2] = struct.pack('<H', vaddr >> 16)        #Write high bytes
  76.                 ptr = filedata.find(struct.pack('<H', vaddr_orig & 0xFFFF),
  77.                                     ptr)                                    #Search for original low bytes
  78.                 if ptr % 4 != 0:                                            #Error on search misses (was really for debugging)
  79.                     print('{} Error: ptr={}, searchedfor={}'.format( \
  80.                         hex(addr), hex(ptr),  binascii.hexlify(struct.pack('<H', vaddr_orig & 0xFFFF))))
  81.                 filedata[ptr:ptr+2] = struct.pack('<H', vaddr & 0xFFFF)     #Write low bytes
  82.             else:                                       #File address specified in input (this is a lot simpler)
  83.                 ptr += 0x20                             #Accomodate 0x20 added for new program header in EBOOT
  84.                 filedata[ptr:ptr+4] = struct.pack('<I', vaddr)              #Write the pointer
  85.         nextpos += len(text)                            #Update state (position next text should go)
  86.     else:                                               #THERE IS enough space
  87.         text += b'\x00' * (avail_space - len(text))     #Pad the text out to the right length
  88.         filedata[addr:endpos] = text                    #Replace the text
  89. #Insert UTF-8 text
  90. inputdata = load_input('UTF8.tsv')
  91. for addr, text, ptrs in inputdata:
  92.     endpos = filedata.find(b'\x00', addr)   #Find end of string
  93.     avail_space = endpos - addr
  94.     text = text.encode('UTF-8')
  95.     text = text.replace(b'{', b'\\n')
  96.     if len(text) > avail_space:
  97.         print('{} too long. Text len={}, avail space={}'.format(hex(addr), len(text), avail_space))
  98.     else:
  99.         text = text + b'\x00' * (avail_space - len(text))
  100.         filedata[addr:endpos] = text
  101. with open('EBOOT.BIN', 'wb') as f:
  102.     f.write(filedata)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement