Advertisement
Guest User

Wander Wonder Script Dump v1.1

a guest
Apr 30th, 2015
528
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.69 KB | None | 0 0
  1. #1.1    Changed dump format- added delay into the flag box
  2. #1      Initial release
  3. import os
  4. import struct
  5. import sys
  6. asciichar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ()0123456789 :!'
  7.  
  8. #Gets data
  9. def get_data(filename):
  10.     totalbytes = os.path.getsize(filename)
  11.     infile = open(filename, 'rb')
  12.     totalfiledata = infile.read(totalbytes)
  13.     infile.close()
  14.     return totalfiledata
  15.  
  16. #Tells if the string s is a SHIFT-JIS character or not
  17. def is_jis_char(s):
  18.     if len(s) != 2: #If it's not a string of length 2, then...
  19.         return False
  20.     try:            #Python error handling
  21.         if len(s.decode('cp932')) != 1: #For example, 2 ascii characters will be length 2
  22.             return False                #Two bytes that decode to a SHIFT-JIS character will be length 1
  23.     except UnicodeDecodeError:  #The string couldn't be decoded
  24.         return False            #Not a SHIFT-JIS character
  25.     return True                 #It is a SHIFT-JIS character
  26.  
  27. def script_dump(filename):
  28.     filedata = get_data(filename + '.orig')  #Get data
  29.     ptr = 0                         #Initialize variables
  30.     end_of_ptr_table = struct.unpack('<I',filedata[0:4])[0]    
  31.     ptr_table = []
  32.     while ptr < end_of_ptr_table:   #Load pointers
  33.         ptr_table.append(struct.unpack('<I',filedata[ptr:ptr+4])[0])
  34.         ptr += 4
  35.     flag = True
  36.     chunks = []                     #Load chunks
  37.     for ptr in ptr_table:
  38.         if flag == True:
  39.             flag = False
  40.         else:
  41.             chunks.append([prev_ptr,filedata[prev_ptr:ptr]])
  42.         prev_ptr = ptr
  43.     chunks.append([ptr,filedata[ptr:]])
  44.  
  45.     #Find open dialog chunk and delay chunk by searching
  46.     for i, (ptr, chunk) in enumerate(chunks):
  47.         if chunk == '400B0000400600004001000040090100400C0000000000004002010040160000'.decode('hex'):
  48.             print 'Open dialog box chunk is 0x{:2x} at address {}.'.format(i,hex(ptr))
  49.             opendialog_chunk = i
  50.         elif chunk == '4002000040033C804002010040160000'.decode('hex'):
  51.             print 'Delay chunk is 0x{:2x} at address {}.'.format(i,hex(ptr))
  52.             delay_chunk = i
  53.  
  54.     script_chunks = []
  55.     name_chunks = []
  56.     for i, (ptr, chunk) in enumerate(chunks):   #Loop through chunks
  57.         #Finds open dialog and delay chunks
  58.         if chunk[:4] == '\x40\x14' + struct.pack('<H',opendialog_chunk):    
  59.             script_chunks.append(i)
  60.         elif chunk[:4] == '\x40\x02\x00\x00' and chunk.find('400500004002010040160000'.decode('hex')) > 0:
  61.             name_chunks.append(i)
  62.     print 'Script Chunks: {}'.format(', '.join([hex(x) for x in script_chunks]))
  63.     print 'Name Chunks: {}'.format(', '.join([hex(x) for x in name_chunks]))
  64.  
  65.     output = []                 #Initialize variables  
  66.     namelist = []
  67.     for j in name_chunks:       #Loop through name chunks
  68.         i, chunk = chunks[j]    #Assign chunk to local variable
  69.         pos = 4                 #Name starts at position 4 within chunk
  70.         while is_jis_char(chunk[pos:pos+2]):
  71.             pos += 2            #Find end of name
  72.         name = chunk[4:pos]
  73.         namelist.append([j, name])  #Add chunk number and name to name list
  74.         output.append(hex(j) + ';')         #Add name to output
  75.         output.append(name + ';;' + 'name' + '\r\n')
  76.  
  77.     firstpass = True
  78.     for chunk in script_chunks: #Loop through script chunks
  79.         if firstpass == True:
  80.             firstpass = False
  81.         else:
  82.             del output[-1]      #Delete ';' entry if 1st line in opcode
  83.         output.append(hex(chunk) + ';')     #Add chunk # to output
  84.         chunkaddr = chunks[chunk][0]        #Get chunk addr and text
  85.         chunk = chunks[chunk][1]
  86.         pos = 0                             #Init variable
  87.         while pos < len(chunk):            
  88.             if ord(chunk[pos]) == 0:        #For byte 0x00, advance to next byte
  89.                 pos += 1
  90.                 continue
  91.             elif ord(chunk[pos]) == 0x40:   #For byte 0x40, it's an opcode
  92.                 if ord(chunk[pos+1]) == 0x17:
  93.                     output.append('0x' + chunk[pos:pos+8].encode('hex') + ';' +
  94.                                   '0x' + chunk[pos:pos+8].encode('hex') + ';' + 'unknown' + '\r\n')
  95.                     output.append(';')
  96.                     pos += 8
  97.                     continue
  98.                 output.append('0x' + chunk[pos:pos+4].encode('hex') + ';' + '0x' +
  99.                               chunk[pos:pos+4].encode('hex') + ';')
  100.                 if ord(chunk[pos+1]) == 0x14:
  101.                     f_number = struct.unpack('<H',chunk[pos+2:pos+4])[0]
  102.                     if f_number == opendialog_chunk:
  103.                         output.append('open dialog')
  104.                     elif f_number == delay_chunk:
  105.                         output.append('delay')
  106.                     elif f_number in [x[0] for x in namelist]:
  107.                         for i, name in namelist:
  108.                             if f_number == i:
  109.                                 break
  110.                         output.append('name: {}'.format(name))
  111.                     else:
  112.                         output.append('function {}'.format(hex(f_number)))
  113.                 elif ord(chunk[pos+1]) == 0x00:
  114.                     output.append('end chunk')
  115.                 elif ord(chunk[pos+1]) == 0x02:
  116.                     output.append('unknown')
  117.                 elif ord(chunk[pos+1]) == 0x05:
  118.                     output.append('linebreak')
  119.                 elif ord(chunk[pos+1]) == 0x06:
  120.                     output.append('closebox')
  121.                 else:
  122.                     output.append('unknown opcode')
  123.                 pos += 4
  124.     ##            elif ord(chunk[pos]) == 0x80:
  125.     ##                output.append(chunk[pos:pos+4].encode('hex') + ';' + chunk[pos:pos+4].encode('hex') + ';')
  126.     ##                output.append('unknown opcode')
  127.     ##                pos += 4
  128.             elif is_jis_char(chunk[pos:pos+2]) or chunk[pos] in asciichar:  #It's text
  129.                 start = pos
  130.                 while is_jis_char(chunk[pos:pos+2]) or chunk[pos] in asciichar:
  131.                     if chunk[pos] in asciichar:         #If ascii, advance by 1
  132.                         pos += 1
  133.                     elif is_jis_char(chunk[pos:pos+2]): #If S-JIS, advance by 2
  134.                         pos += 2
  135.                 output.append(chunk[start:pos] + ';')   #Output text
  136.                 if chunk[pos:pos+2] == '\x40\x05':
  137.                     output.append(';linebreak')
  138.                     pos += 4
  139.                 elif chunk[pos:pos+4] == '\x00\x00\x40\x05':
  140.                     output.append(';linebreak')
  141.                     pos += 6
  142.                 if chunk[pos:pos+4] == '\x40\x14' + struct.pack('<H',delay_chunk):
  143.                     if 'linebreak' in output[-1]:
  144.                         output[-1] += '+delay'
  145.                     else:
  146.                         output.append(';delay')
  147.                     pos += 4
  148.             else:   #Not byte 0x00, byte 0x40, or text
  149.                 print 'Unknown character'
  150.                 print hex(chunkaddr)        #Start of chunk
  151.                 print hex(chunkaddr+pos)    #Postion of miss
  152.                 quit()
  153.             output.append('\r\n')           #Output linebreak and indent
  154.             output.append(';')              #for next opcode within chunk
  155.     with open(filename + '.csv','wb') as f: #Write output to file
  156.         f.write(''.join(output))
  157.  
  158. scripts = ['apend00','bird01','bird02','bird03','bird04','bird05','bird06','birddemo','boss01','boss02','boss2',
  159.            'boss03','boss3','catedral','church01','church02','church03','churdemo','cnt01','coloseum',
  160.            'eddemo01','eddemo02','eddemo03','exdemo01','extra01','extra02','extra03','fir01','fir02','fir03',
  161.            'grave01','grave02','grave03','house','ice01','ice02','ice03','inn01','inn02','inn03','ise01','ise02',
  162.            'ise03','knondemo','last01','last02_0','last02_1','last02_2','last02_3','last03','last04','lastdemo',
  163.            'mnt00','mnt01','mnt02','mnt03','mnt04','mnt05','museum','nxdemo01','nxdemo02','nxdemo03','opdemo00',
  164.            'opdemo01','opdemo02','opdemo03','plane01','plane02','plane03','random','sai01','sai02','sai03',
  165.            'sai04','sand01','sand02','shops','soldier','subgame','thu01','thu02','thu03','tiademo','tower00',
  166.            'tower01','tower02','tower03','tower04','tower05','tower06','tower07','tower08','tower09','town01',
  167.            'town02','town2','town03','tree00','tree01','tree02','tree03','tree04','tutori01','tutori02','tutori03',
  168.            'twdemo01','twdemo02','wind00','wind01','wind02','wood01','wood02','wpshop01','wpshop02','wpshop03']
  169. for script in scripts:                      #Dump each script
  170.     print 'Dumping: {}'.format(script)
  171.     script_dump(script)
  172.     print ''
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement