Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #v2:Support {} IDs for ascii encode fields
- import binascii
- import os
- import shutil
- import struct
- INPUT_COL = 2
- PTR_COL = 3
- s1 = " .,'!?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~-&>():;/%"
- s2 = " .,’!?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~‐&>():;/%"
- translate_table = str.maketrans(s1, s2) #For converting between ASCII and fullwidth SHIFT-JIS characters
- def is_hex(n):
- try:
- int(n, 16)
- except ValueError:
- return False
- return True
- def text_decode(s, encoding='ascii', translate = True):
- out = b''
- while '"' in s:
- s = s.replace('"', '“', 1)
- s = s.replace('"', '”', 1)
- while '{' in s:
- if translate == True:
- out += s[:s.find('{')].translate(translate_table).encode(encoding)
- else:
- out += s[:s.find('{')].encode(encoding)
- code_pos = s.find('{')+1
- code_end = s.find('}')
- if code_end == -1:
- print('decode error')
- quit()
- out += s[code_pos:code_end].encode('ascii')
- s = s[code_end+1:]
- if translate == True:
- out += s.translate(translate_table).encode(encoding)
- else:
- out += s.encode(encoding)
- return out
- def load_input(filename):
- inputdata = []
- with open(filename, 'r', encoding='utf-8') as f:
- for line in f:
- line = line.rstrip('\r\n').split('\t')
- if line[0] != '': #New entry
- ptrs = []
- for ptr in line[PTR_COL:]:
- if is_hex(ptr):
- ptr = int(ptr, 16)
- else: #End of pointer list
- break
- ptrs.append(ptr)
- inputdata.append([int(line[0], 16), line[INPUT_COL], ptrs]) #addr, text, ptrs
- else: #Additional line for same entry
- inputdata[-1][1] += '\x0a' + line[INPUT_COL]
- return inputdata
- if os.path.isfile('EBOOT.orig'): #This is to create a copy of the original (for running tool multiple times)
- pass
- elif os.path.isfile('EBOOT.BIN'):
- shutil.copy('EBOOT.BIN', 'EBOOT.orig')
- else:
- print('Missing EBOOT.bin.')
- quit()
- with open('EBOOT.orig', 'rb') as f:
- filedata = bytearray(f.read())
- #Insert SHIFT-JIS text (which is most of it)
- inputdata = load_input('SJIS.tsv')
- nextpos = 0x16CE00 #Start of extra data (expanded EBOOT)
- for addr, text, ptrs in sorted(inputdata, key=lambda x: x[0], reverse=True):
- #Go backwards (reverse = True) // key is addr - we want to do later lines first
- endpos = filedata.find(b'\x00', addr) #Find end of string
- while filedata[endpos] == 0: #Find start of next string
- endpos += 1
- endpos -= 2 #Need 2 nulls (at least) for SJIS terminator (I think)
- avail_space = endpos - addr
- text = text_decode(text, encoding='cp932')
- if len(text) > avail_space: #NOT enough space
- filedata[addr:endpos] = b'\x00' * avail_space #Blank out the line
- text += b'\x00' * 2 #Add terminator
- while len(text) % 4 != 0: #Align to word boundary
- text += b'\x00'
- filedata[nextpos:nextpos+len(text)] = text #Insert text
- #Compute virtual address (vaddr) - 0x89C4200 is the difference between file
- #image position and virtual address for text in the EBOOT extra data area
- vaddr = nextpos + 0x89C4200
- for ptr in ptrs:
- if ptr > 0x08000000: #Virtual address specified in input
- #0x8803F8C is the difference between file image position and virtual address
- #for text in the original EBOOT area (not the extra data section)
- vaddr_orig = addr + 0x8803F8C
- if (vaddr & 0xFFFF) > 0x8000: #Accomodate addiu instructions (all of them are addiu)
- vaddr += 0x10000
- ptr = ptr - 0x8803F8C #Find file address of ptr
- filedata[ptr:ptr+2] = struct.pack('<H', vaddr >> 16) #Write high bytes
- ptr = filedata.find(struct.pack('<H', vaddr_orig & 0xFFFF),
- ptr) #Search for original low bytes
- if ptr % 4 != 0: #Error on search misses (was really for debugging)
- print('{} Error: ptr={}, searchedfor={}'.format( \
- hex(addr), hex(ptr), binascii.hexlify(struct.pack('<H', vaddr_orig & 0xFFFF))))
- filedata[ptr:ptr+2] = struct.pack('<H', vaddr & 0xFFFF) #Write low bytes
- else: #File address specified in input (this is a lot simpler)
- ptr += 0x20 #Accomodate 0x20 added for new program header in EBOOT
- filedata[ptr:ptr+4] = struct.pack('<I', vaddr) #Write the pointer
- nextpos += len(text) #Update state (position next text should go)
- else: #THERE IS enough space
- text += b'\x00' * (avail_space - len(text)) #Pad the text out to the right length
- filedata[addr:endpos] = text #Replace the text
- #Insert UTF-8 text
- inputdata = load_input('UTF8.tsv')
- for addr, text, ptrs in inputdata:
- endpos = filedata.find(b'\x00', addr) #Find end of string
- avail_space = endpos - addr
- text = text_decode(text, encoding='utf-8', translate=False)
- if len(text) > avail_space:
- print('{} too long. Text len={}, avail space={}'.format(hex(addr), len(text), avail_space))
- else:
- text = text + b'\x00' * (avail_space - len(text))
- filedata[addr:endpos] = text
- with open('EBOOT.BIN', 'wb') as f:
- f.write(filedata)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement