Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # v1.3 Inserts 0xC1 opcodes
- # v1.2 Specify insert files. Fix more jumps. Does all files in list.
- # Insert Nayuta no Kiseki script file / update data.lst
- # Usage is python script.py mp_0000
- # Where mp_0000.bin is the file you want to insert
- # Input file is from the dumper (*.data) with whichever strings you
- # want to insert, in tab-separated format.
- # Also need *.orig (original data file) in same directory.
- # Also need data.lst from the ROM in same directory.
- import os
- import struct
- import sys
- import pdb
- filelist = ['mp_0000', 'mp_0000c', 'mp_0000d',
- 'mp_0001', 'mp_0001c', 'mp_0001d',
- 'mp_0002', 'mp_0002c', 'mp_0002d',
- 'mp_0003', 'mp_0003c', 'mp_0003d',
- 'mp_0004', 'mp_0004c', 'mp_0004d', 'mp_0004n',
- 'mp_0005', 'mp_0005c',
- 'mp_0100', 'mp_0100a', 'mp_0100b',
- 'mp_0101', 'mp_0101a', 'mp_0101b', 'mp_0101c',
- 'mp_0102', 'mp_0104', 'mp_0105', 'mp_0106',
- 'mp_0110', 'mp_0111', 'mp_0112', 'mp_0113', 'mp_0114',
- 'mp_0115', 'mp_0115a', 'mp_0115b', 'mp_0115c', 'mp_0115d',
- 'mp_0116', 'mp_0117', 'mp_0118', 'mp_0119',
- 'mp_1000a', 'mp_1000b', 'mp_1000c', 'mp_1000d',
- 'mp_1001a', 'mp_1001b', 'mp_1001c', 'mp_1001d',
- 'mp_1002a', 'mp_1002b',
- 'mp_1010', 'mp_1011',
- 'mp_1099', 'mp_1100',
- 'mp_2000b', 'mp_2000c',
- 'mp_2001a', 'mp_2001b', 'mp_2001c', 'mp_2001d',
- 'mp_2002a', 'mp_2002b', 'mp_2002d',
- 'mp_2010', 'mp_2099', 'mp_2100',
- 'mp_3000b', 'mp_3000c', 'mp_3000d',
- 'mp_3001a', 'mp_3001b', 'mp_3001c', 'mp_3001d',
- 'mp_3002a', 'mp_3002c', 'mp_3002d',
- 'mp_3003c', 'mp_3003d',
- 'mp_3099', 'mp_3100',
- 'mp_4000a', 'mp_4000c', 'mp_4000d',
- 'mp_4001a', 'mp_4001b', 'mp_4001c', 'mp_4001d',
- 'mp_4002a', 'mp_4002b', 'mp_4002c', 'mp_4002d',
- 'mp_4011', 'mp_4099', 'mp_4100',
- 'mp_5000', 'mp_5098', 'mp_5099', 'mp_5100', 'mp_5101',
- 'mp_5200', 'mp_5300',
- 'mp_6000', 'mp_6001', 'mp_6002', 'mp_6003',
- 'mp_6100', 'mp_6100d', 'mp_6200',
- 'mp_6300', 'mp_6301', 'mp_6302', 'mp_6303',
- 'mp_7020', 'mp_7098',
- 'mp_7099', 'mp_7099a', 'mp_7099b', 'mp_7099c',
- 'mp_7100', 'mp_7200',
- 'mp_8098', 'mp_8099', 'mp_8100', 'mp_8100b',
- 'noi', 'system']
- def get_data(filename):
- totalbytes = os.path.getsize(filename)
- infile = open(filename, 'rb')
- totalfiledata = infile.read(totalbytes)
- infile.close()
- return totalfiledata
- def replacestr(origstr,replacestr,startpos,replacelen):
- #Returns a string with a replaced sub-string
- #origstr - the original string, replacestr = the string to replace
- #startpos - where the replacement string should go
- #replacelen - how many characters of the original string to replace
- return origstr[:startpos] + replacestr + origstr[startpos+replacelen:]
- def twos_comp(val, bits):
- """compute the 2's compliment of int value val"""
- if( (val&(1<<(bits-1))) != 0 ):
- val = val - (1<<bits)
- return val
- def myprogram(filename):
- opcodes = ((0x07,2),(0x40,2),(0x3f,2),(0x41,0x14),
- (0x98,2),(0xc9,8),(0x36,8),(0xce,8),
- (0xC1,'special'))
- # Load input
- inputdata = []
- with open(filename + '.data','rb') as f:
- for line in f:
- line = line.translate(None,'\r\n')
- line = line.split('\t')
- if len(line) < 3:
- continue
- if line[1] != '':
- line[1] = int(line[1],16)
- if line[0] != '' and line[1] == '':
- pass
- elif line[0] != '': #Line has a new opcode
- if line[1] in [op[0] for op in opcodes]: #It's one of our opcodes
- if line[4] == "" and line[3] != "":
- print '%s: Blank opcode %s at %s.' % (filename, hex(line[1]), line[0])
- line[0] = int(line[0],16)
- inputdata.append(line[:3])
- inputdata[-1].append([line[4]]) #append column 5 as set
- else:
- inputdata[-1][-1].append(line[4])
- filedata = get_data(filename + '.orig')
- # Load pointers (file header)
- pointers = []
- pos = 0x3C
- EOF = struct.unpack('<I',filedata[pos:pos+4])[0]
- while pos < EOF:
- pointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
- pos += 0x28
- # Load more pointers (relative pointers in opcodes)
- relpointers = []
- pos = 0
- for opcode in ('\x7b\x80\xe0\x82','\x7c\x80\xe0\x82','\x7d\x80\xdd\x82',
- '\x80\x80\xdd\x82','\x81\x80\xdd\x82','\x83\x80\xdd\x82'):
- while True:
- pos = filedata.find(opcode,pos+1)
- if pos == -1:
- break
- if opcode[0] in ('\x7b','\x7c'):
- pos += 4
- pos += struct.unpack('<I',filedata[pos:pos+4])[0] + 6 #Jump past 82E0 opcode
- relpointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
- elif opcode[0] in ('\x7d','\x80','\x81'):
- pos += 4
- val = struct.unpack('<I',filedata[pos:pos+4])[0]
- if opcode[0] == '\x80':
- val = twos_comp(val,32)
- relpointers.append([pos,val])
- elif opcode[0] == '\x83':
- pos += 10 #Jump past 82DD opcode
- relpointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
- # Replace strings
- offset = 0
- for (count,(addr,op,name,lines)) in enumerate(inputdata):
- addr += offset
- text = ""
- # Build the 0x82DF opcodes (that have strings in them)
- if op == 0x07:
- for line in lines:
- text += line + '\\n'
- text = text[:-2]
- text = '\xDF\x82' + struct.pack('<I',len(text)) + text
- else:
- for line in lines:
- text += '\xDF\x82' + struct.pack('<I',len(line)) + line
- name = '\xDF\x82' + struct.pack('<I',len(name)) + name
- if op in (0x40,0x98):
- text = name + text
- # Go to the start of the first DF opcode
- # Then look for the end of the string list
- for opcode, jumplen in opcodes:
- if op == opcode:
- break
- else:
- print "Failed opcode lookup!"
- quit()
- if op == 0xC1:
- addr += 2
- for x in range(3):
- addr += 2
- datalen = struct.unpack('<I',filedata[addr:addr+4])[0]
- addr += datalen + 4
- else:
- addr += jumplen
- startpos = addr
- if filedata[addr] != '\xDF':
- pdb.set_trace()
- print 'Fail'
- quit()
- else:
- while filedata[addr] == '\xDF':
- addr += struct.unpack('<I',filedata[addr+2:addr+6])[0] + 6
- endpos = addr
- origlen = endpos - startpos
- newlen = len(text)
- # Replace the string
- filedata = replacestr(filedata,text,startpos,endpos-startpos)
- # Update pointers
- for i,(pointerpos,pointertgt) in enumerate(pointers):
- if pointertgt > startpos:
- pointers[i][1] = pointertgt + newlen - origlen
- # Update relative pointers
- for i,(pointerpos,pointertgt) in enumerate(relpointers):
- if pointertgt < 0:
- if pointerpos + pointertgt > startpos:
- relpointers[i][0] += newlen - origlen
- elif pointerpos > startpos:
- relpointers[i][0] += newlen - origlen
- relpointers[i][1] += -newlen + origlen
- else:
- if pointerpos > startpos:
- relpointers[i][0] += newlen - origlen
- elif pointerpos + pointertgt > startpos:
- relpointers[i][1] += newlen - origlen
- # Update offset
- offset += newlen - origlen
- # Write-back pointers
- for pointerpos, pointertgt in pointers:
- pointertgt = struct.pack('<I',pointertgt)
- filedata = replacestr(filedata,pointertgt,pointerpos,4)
- # Write-back relative pointers
- for pointerpos, pointertgt in relpointers:
- if pointertgt > -1:
- pointertgt = struct.pack('<I',pointertgt)
- else:
- pointertgt = int(hex(pointertgt & 0xFFFFFFFF)[2:-1],16)
- pointertgt = struct.pack('<I',pointertgt)
- filedata = replacestr(filedata,pointertgt,pointerpos,4)
- # Write the output
- outfile = open(filename + '.bin','wb')
- outfile.write(filedata)
- outfile.close()
- # Update data.lst
- datasize = struct.pack('<I',len(filedata))
- filedata = get_data('data.lst')
- pos = filedata.find(filename + (8-len(filename))*'\x00',0xCD00)
- filedata = replacestr(filedata,datasize,pos+8,4)
- outfile = open('data.lst','wb')
- outfile.write(filedata)
- outfile.close()
- if __name__ == '__main__':
- ## for testing in IDLE
- ## sys.argv.append('mp_0000')
- for filename in filelist:
- myprogram(filename)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement