Guest User

Nayuta Script Insert v1.3

a guest
Mar 11th, 2015
495
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # v1.3 Inserts 0xC1 opcodes
  2. # v1.2 Specify insert files. Fix more jumps. Does all files in list.
  3. # Insert Nayuta no Kiseki script file / update data.lst
  4. # Usage is python script.py mp_0000
  5. # Where mp_0000.bin is the file you want to insert
  6. # Input file is from the dumper (*.data) with whichever strings you
  7. #   want to insert, in tab-separated format.
  8. # Also need *.orig (original data file) in same directory.
  9. # Also need data.lst from the ROM in same directory.
  10. import os
  11. import struct
  12. import sys
  13. import pdb
  14.  
  15. filelist = ['mp_0000', 'mp_0000c', 'mp_0000d',
  16.             'mp_0001', 'mp_0001c', 'mp_0001d',
  17.             'mp_0002', 'mp_0002c', 'mp_0002d',
  18.             'mp_0003', 'mp_0003c', 'mp_0003d',
  19.             'mp_0004', 'mp_0004c', 'mp_0004d', 'mp_0004n',
  20.             'mp_0005', 'mp_0005c',
  21.             'mp_0100', 'mp_0100a', 'mp_0100b',
  22.             'mp_0101', 'mp_0101a', 'mp_0101b', 'mp_0101c',
  23.             'mp_0102', 'mp_0104', 'mp_0105', 'mp_0106',
  24.             'mp_0110', 'mp_0111', 'mp_0112', 'mp_0113', 'mp_0114',
  25.             'mp_0115', 'mp_0115a', 'mp_0115b', 'mp_0115c', 'mp_0115d',
  26.             'mp_0116', 'mp_0117', 'mp_0118', 'mp_0119',
  27.             'mp_1000a', 'mp_1000b', 'mp_1000c', 'mp_1000d',
  28.             'mp_1001a', 'mp_1001b', 'mp_1001c', 'mp_1001d',
  29.             'mp_1002a', 'mp_1002b',
  30.             'mp_1010', 'mp_1011',
  31.             'mp_1099', 'mp_1100',
  32.             'mp_2000b', 'mp_2000c',
  33.             'mp_2001a', 'mp_2001b', 'mp_2001c', 'mp_2001d',
  34.             'mp_2002a', 'mp_2002b', 'mp_2002d',
  35.             'mp_2010', 'mp_2099', 'mp_2100',
  36.             'mp_3000b', 'mp_3000c', 'mp_3000d',
  37.             'mp_3001a', 'mp_3001b', 'mp_3001c', 'mp_3001d',
  38.             'mp_3002a', 'mp_3002c', 'mp_3002d',
  39.             'mp_3003c', 'mp_3003d',
  40.             'mp_3099', 'mp_3100',
  41.             'mp_4000a', 'mp_4000c', 'mp_4000d',
  42.             'mp_4001a', 'mp_4001b', 'mp_4001c', 'mp_4001d',
  43.             'mp_4002a', 'mp_4002b', 'mp_4002c', 'mp_4002d',
  44.             'mp_4011', 'mp_4099', 'mp_4100',
  45.             'mp_5000', 'mp_5098', 'mp_5099', 'mp_5100', 'mp_5101',
  46.             'mp_5200', 'mp_5300',
  47.             'mp_6000', 'mp_6001', 'mp_6002', 'mp_6003',
  48.             'mp_6100', 'mp_6100d', 'mp_6200',
  49.             'mp_6300', 'mp_6301', 'mp_6302', 'mp_6303',
  50.             'mp_7020', 'mp_7098',
  51.             'mp_7099', 'mp_7099a', 'mp_7099b', 'mp_7099c',
  52.             'mp_7100', 'mp_7200',
  53.             'mp_8098', 'mp_8099', 'mp_8100', 'mp_8100b',
  54.             'noi', 'system']
  55.  
  56. def get_data(filename):
  57.     totalbytes = os.path.getsize(filename)
  58.     infile = open(filename, 'rb')
  59.     totalfiledata = infile.read(totalbytes)
  60.     infile.close()
  61.     return totalfiledata
  62.  
  63. def replacestr(origstr,replacestr,startpos,replacelen):
  64. #Returns a string with a replaced sub-string
  65. #origstr - the original string, replacestr = the string to replace
  66. #startpos - where the replacement string should go
  67. #replacelen - how many characters of the original string to replace
  68.     return origstr[:startpos] + replacestr + origstr[startpos+replacelen:]
  69.  
  70. def twos_comp(val, bits):
  71.     """compute the 2's compliment of int value val"""
  72.     if( (val&(1<<(bits-1))) != 0 ):
  73.         val = val - (1<<bits)
  74.     return val
  75.  
  76. def myprogram(filename):
  77.  
  78.     opcodes = ((0x07,2),(0x40,2),(0x3f,2),(0x41,0x14),
  79.                (0x98,2),(0xc9,8),(0x36,8),(0xce,8),
  80.                (0xC1,'special'))
  81.  
  82.     # Load input
  83.     inputdata = []
  84.     with open(filename + '.data','rb') as f:
  85.         for line in f:
  86.             line = line.translate(None,'\r\n')
  87.             line = line.split('\t')
  88.             if len(line) < 3:
  89.                 continue
  90.             if line[1] != '':
  91.                 line[1] = int(line[1],16)
  92.             if line[0] != '' and line[1] == '':
  93.                 pass
  94.             elif line[0] != '': #Line has a new opcode
  95.                 if line[1] in [op[0] for op in opcodes]:  #It's one of our opcodes
  96.                     if line[4] == "" and line[3] != "":
  97.                         print '%s: Blank opcode %s at %s.' % (filename, hex(line[1]), line[0])
  98.                     line[0] = int(line[0],16)
  99.                     inputdata.append(line[:3])
  100.                     inputdata[-1].append([line[4]]) #append column 5 as set
  101.             else:
  102.                 inputdata[-1][-1].append(line[4])
  103.  
  104.     filedata = get_data(filename + '.orig')
  105.  
  106.     # Load pointers (file header)
  107.     pointers = []
  108.     pos = 0x3C
  109.     EOF = struct.unpack('<I',filedata[pos:pos+4])[0]
  110.     while pos < EOF:
  111.         pointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
  112.         pos += 0x28
  113.  
  114.     # Load more pointers (relative pointers in opcodes)
  115.     relpointers = []
  116.     pos = 0
  117.     for opcode in ('\x7b\x80\xe0\x82','\x7c\x80\xe0\x82','\x7d\x80\xdd\x82',
  118.                    '\x80\x80\xdd\x82','\x81\x80\xdd\x82','\x83\x80\xdd\x82'):
  119.         while True:
  120.             pos = filedata.find(opcode,pos+1)
  121.             if pos == -1:
  122.                 break
  123.             if opcode[0] in ('\x7b','\x7c'):
  124.                 pos += 4
  125.                 pos += struct.unpack('<I',filedata[pos:pos+4])[0] + 6 #Jump past 82E0 opcode
  126.                 relpointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
  127.             elif opcode[0] in ('\x7d','\x80','\x81'):
  128.                 pos += 4
  129.                 val = struct.unpack('<I',filedata[pos:pos+4])[0]
  130.                 if opcode[0] == '\x80':
  131.                     val = twos_comp(val,32)
  132.                 relpointers.append([pos,val])
  133.             elif opcode[0] == '\x83':
  134.                 pos += 10 #Jump past 82DD opcode
  135.                 relpointers.append([pos,struct.unpack('<I',filedata[pos:pos+4])[0]])
  136.  
  137.     # Replace strings
  138.     offset = 0
  139.     for (count,(addr,op,name,lines)) in enumerate(inputdata):
  140.         addr += offset
  141.         text = ""
  142.         # Build the 0x82DF opcodes (that have strings in them)
  143.         if op == 0x07:
  144.             for line in lines:
  145.                 text += line + '\\n'
  146.             text = text[:-2]
  147.             text = '\xDF\x82' + struct.pack('<I',len(text)) + text
  148.         else:
  149.             for line in lines:
  150.                 text += '\xDF\x82' + struct.pack('<I',len(line)) + line
  151.         name = '\xDF\x82' + struct.pack('<I',len(name)) + name
  152.         if op in (0x40,0x98):
  153.             text = name + text
  154.         # Go to the start of the first DF opcode
  155.         # Then look for the end of the string list
  156.         for opcode, jumplen in opcodes:
  157.             if op == opcode:
  158.                 break
  159.         else:
  160.             print "Failed opcode lookup!"
  161.             quit()
  162.         if op == 0xC1:
  163.             addr += 2
  164.             for x in range(3):
  165.                 addr += 2
  166.                 datalen = struct.unpack('<I',filedata[addr:addr+4])[0]
  167.                 addr += datalen + 4
  168.         else:
  169.             addr += jumplen
  170.         startpos = addr
  171.         if filedata[addr] != '\xDF':
  172.             pdb.set_trace()
  173.             print 'Fail'
  174.             quit()
  175.         else:
  176.             while filedata[addr] == '\xDF':
  177.                 addr += struct.unpack('<I',filedata[addr+2:addr+6])[0] + 6
  178.         endpos = addr
  179.         origlen = endpos - startpos
  180.         newlen = len(text)
  181.         # Replace the string
  182.         filedata = replacestr(filedata,text,startpos,endpos-startpos)
  183.         # Update pointers
  184.         for i,(pointerpos,pointertgt) in enumerate(pointers):
  185.             if pointertgt > startpos:
  186.                 pointers[i][1] = pointertgt + newlen - origlen
  187.         # Update relative pointers
  188.         for i,(pointerpos,pointertgt) in enumerate(relpointers):
  189.             if pointertgt < 0:
  190.                 if pointerpos + pointertgt > startpos:
  191.                     relpointers[i][0] += newlen - origlen
  192.                 elif pointerpos > startpos:
  193.                     relpointers[i][0] += newlen - origlen
  194.                     relpointers[i][1] += -newlen + origlen
  195.             else:
  196.                 if pointerpos > startpos:
  197.                     relpointers[i][0] += newlen - origlen
  198.                 elif pointerpos + pointertgt > startpos:
  199.                     relpointers[i][1] += newlen - origlen
  200.         # Update offset
  201.         offset += newlen - origlen
  202.  
  203.     # Write-back pointers
  204.     for pointerpos, pointertgt in pointers:
  205.         pointertgt = struct.pack('<I',pointertgt)
  206.         filedata = replacestr(filedata,pointertgt,pointerpos,4)
  207.  
  208.     # Write-back relative pointers
  209.     for pointerpos, pointertgt in relpointers:
  210.         if pointertgt > -1:
  211.             pointertgt = struct.pack('<I',pointertgt)
  212.         else:
  213.             pointertgt = int(hex(pointertgt & 0xFFFFFFFF)[2:-1],16)
  214.             pointertgt = struct.pack('<I',pointertgt)
  215.         filedata = replacestr(filedata,pointertgt,pointerpos,4)
  216.  
  217.     # Write the output
  218.     outfile = open(filename + '.bin','wb')
  219.     outfile.write(filedata)
  220.     outfile.close()
  221.  
  222.     # Update data.lst
  223.     datasize = struct.pack('<I',len(filedata))
  224.     filedata = get_data('data.lst')
  225.     pos = filedata.find(filename + (8-len(filename))*'\x00',0xCD00)
  226.     filedata = replacestr(filedata,datasize,pos+8,4)
  227.  
  228.     outfile = open('data.lst','wb')
  229.     outfile.write(filedata)
  230.     outfile.close()
  231.  
  232. if __name__ == '__main__':
  233. ##    for testing in IDLE
  234. ##    sys.argv.append('mp_0000')
  235.     for filename in filelist:
  236.         myprogram(filename)
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×