Guest User

ZnK Dumper v3.1

a guest
Sep 1st, 2014
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.22 KB | None | 0 0
  1. import os
  2. import sys
  3. import struct
  4. import re
  5.  
  6. facedict = {}
  7. facedict['00'] = 'Lloyd'
  8. facedict['01'] = 'Elie'
  9. facedict['02'] = 'Tio'
  10. facedict['03'] = 'Randy'
  11. facedict['04'] = 'Lazy'
  12. facedict['05'] = 'Noel'
  13. facedict['06'] = 'Dudley'
  14. facedict['07'] = 'Yin'
  15. facedict['08'] = 'Estelle'
  16. facedict['09'] = 'Joshua'
  17. facedict['10'] = 'Sergei'
  18. facedict['11'] = 'KeA'
  19. facedict['12'] = 'Zeit'
  20. facedict['13'] = 'Cecil'
  21. facedict['14'] = 'Arios'
  22. facedict['15'] = 'Sizuku'
  23. facedict['16'] = 'Wald'
  24. facedict['17'] = 'Ilya'
  25. facedict['18'] = 'Rixia'
  26. facedict['19'] = 'Fran'
  27. facedict['20'] = 'Sonya'
  28. facedict['21'] = 'Grace'
  29. facedict['22'] = 'Ian'
  30. facedict['23'] = 'Jona'
  31. facedict['24'] = 'Joachim'
  32. facedict['25'] = 'McDowell'
  33. facedict['26'] = 'Earnest'
  34. facedict['27'] = 'Hartman'
  35. facedict['28'] = 'Dieter'
  36. facedict['29'] = 'Mariabell'
  37. facedict['30'] = 'Marconi'
  38. facedict['31'] = 'Garcia'
  39. facedict['32'] = 'Cao'
  40. facedict['33'] = 'Renne'
  41. facedict['34'] = 'Kirika'
  42. facedict['35'] = 'Lector'
  43. facedict['36'] = 'Harold'
  44. facedict['37'] = 'Sophia'
  45. facedict['38'] = 'Colin'
  46. facedict['39'] = 'Jorg'
  47. facedict['50'] = 'Lloyd (Fancy)'
  48. facedict['51'] = 'Lloyd (Fancy Glasses)'
  49. facedict['52'] = 'Lloyd (Casual)'
  50. facedict['53'] = 'Elie (Fancy)'
  51. facedict['54'] = 'Special'
  52. facedict['55'] = 'Tio (Casual)'
  53. facedict['56'] = 'Randy (Fancy)'
  54. facedict['57'] = 'Lazy (Fancy)'
  55. facedict['58'] = 'KeA (Fancy)'
  56. facedict['59'] = 'Cecil (Fancy)'
  57. facedict['60'] = 'Sizuku (Fancy)'
  58. facedict['61'] = 'Ilya (Dancer)'
  59. facedict['62'] = 'Rixia (Priestess)'
  60. facedict['63'] = 'Noel (Casual)'
  61. facedict['64'] = 'Fran (Casual)'
  62. facedict['65'] = 'McDowell (PJs)'
  63. facedict['66'] = 'Earnest (Suit)'
  64. facedict['67'] = 'Joachim (Blue Hair)'
  65. facedict['68'] = 'Joachim (White Hair)'
  66.  
  67. codedict = {}
  68. codedict['\x01'] = 'Lloyd'
  69. codedict['\x02'] = 'Elie'
  70. codedict['\x03'] = 'Tio'
  71. codedict['\x04'] = 'Randy'
  72. codedict['\x09'] = 'Noel'
  73. codedict['\x0a'] = 'Dudley'
  74. codedict['\x07'] = 'Estelle'
  75. codedict['\x08'] = 'Joshua'
  76. codedict['\x53'] = 'KeA'
  77. codedict['\x1c'] = 'Zeit'
  78.  
  79.  
  80. def replacestr(origstr,replacestr,startpos,replacelen):
  81. #Returns a string with a replaced sub-string
  82. #origstr - the original string, replacestr = the string to replace
  83. #startpos - where the replacement string should go
  84. #replacelen - how many characters of the original string to replace
  85.     return origstr[:startpos] + replacestr + origstr[startpos+replacelen:]
  86.  
  87. def is_jis_char(s):
  88.     try:
  89.         s.decode('cp932')
  90.     except UnicodeDecodeError:
  91.         return False
  92.     if len(s.decode('cp932')) == 1:
  93.         return True
  94.     return False
  95.  
  96. def is_number(s):
  97.     try:
  98.         float(s)
  99.         return True
  100.     except ValueError:
  101.         return False
  102.  
  103. def get_data(filename):
  104.     totalbytes = os.path.getsize(filename)
  105.     infile = open(filename, 'rb')
  106.     totalfiledata = infile.read(totalbytes)
  107.     return totalfiledata
  108.  
  109. def getpointers():
  110.     pointers = []
  111.  
  112.     strpos = 0
  113.     while strpos > -1:
  114.         strpos = filedata.find('\x5e\x00\x00\xff\xff',strpos+1)
  115.         if strpos > 0:
  116.             pointers.append(strpos)
  117.  
  118.     strpos = 0
  119.     while strpos > -1:
  120.         strpos = filedata.find('\x55\xff\x00',strpos+1)
  121.         if strpos > 0:
  122.             pointers.append(strpos)
  123.        
  124.     strpos = 0
  125.     while strpos > -1:
  126.         strpos = filedata.find('\x55\x01\x01',strpos+1)
  127.         if strpos > 0:
  128.             pointers.append(strpos)
  129.        
  130.     strpos = 0
  131.     while strpos > -1:
  132.         strpos = filedata.find('\x55\xe7\x03',strpos+1)
  133.         if strpos > 0:
  134.             pointers.append(strpos)
  135.        
  136.     strpos = 0
  137.     while strpos > -1:
  138.         strpos = filedata.find('\x61',strpos+1)
  139.         if strpos > 0 and is_jis_char(filedata[strpos+1:strpos+3]) and not is_jis_char(filedata[strpos-1:strpos+1]):
  140.             pointers.append(strpos)
  141.        
  142.     strpos = 0
  143.     while strpos > -1:
  144.         strpos = filedata.find('\x5c',strpos+1)
  145.         if strpos > 0:
  146.             if filedata[strpos+2] == '\x00' or filedata[strpos+2] == '\x01':
  147.                 if filedata[strpos+1:strpos+3] != '\x00\x00':
  148.                     if ord(filedata[strpos+3]) == 35 and filedata[strpos-4:strpos] != '\x00\x00\x00\x00' :
  149.                         pointers.append(strpos)
  150.                     elif ord(filedata[strpos+3]) > 127 and ord(filedata[strpos+3]) < 255 and ord(filedata[strpos+4]) > 39:
  151.                         if filedata[strpos-4:strpos] != '\x00\x00\x00\x00':
  152.                             pointers.append(strpos)
  153.  
  154.     strpos = 0
  155.     while strpos > -1:
  156.         strpos = filedata.find('\x5d',strpos+1)
  157.         if strpos > 0 and ord(filedata[strpos-1]) < 128:
  158.             if ord(filedata[strpos+3]) > 127 and ord(filedata[strpos+3]) < 255 and ord(filedata[strpos+4]) > 39:
  159.                 if ord(filedata[strpos+2]) == 0 or ord(filedata[strpos+2]) == 1:
  160.                     pointers.append(strpos)
  161.    
  162.     if pointers == []:
  163.         print "No dialogue in this file."
  164.         quit()
  165.        
  166.     return pointers
  167.  
  168. def findstrend(opcode, pointer):
  169.     if opcode == '5e':
  170.         strend = filedata.find('\x01\x00',pointer)
  171.     elif opcode in ('55','5c','5d'):
  172.         pos = pointer + 3
  173.         while True:
  174.             if filedata[pos:pos+2] == '\x02\x00':
  175.                 strend = pos
  176.                 break
  177.             elif filedata[pos] == '\x1F':
  178.                 pos += 5
  179.             elif is_jis_char(filedata[pos:pos+2]):
  180.                 pos += 2
  181.             else:
  182.                 pos += 1
  183.     elif opcode == '61':
  184.         strend = filedata.find('\x00',pointer)
  185.     else:
  186.         print 'Unknown opcode.'
  187.     return strend
  188.  
  189. def filterspecialcodes(text):
  190.     textpos = 0
  191.     newtext = ""
  192.     specialflag = False
  193.     while textpos < len(text):
  194.         if text[textpos] == '\x1F':
  195.             newtext += '{ '
  196.             for x in range(5):
  197.                 newtext+= text[textpos].encode('hex') + ' '
  198.                 textpos += 1
  199.             newtext += '}'
  200.         elif ord(text[textpos]) > 31 and ord(text[textpos]) < 128:
  201.             if specialflag == True:
  202.                 specialflag = False
  203.                 newtext += ' }'
  204.             newtext += text[textpos]
  205.             textpos += 1
  206.         elif is_jis_char(text[textpos:textpos+2]):
  207.             if specialflag == True:
  208.                 specialflag = False
  209.                 newtext += ' }'
  210.             newtext += text[textpos:textpos+2]
  211.             textpos += 2
  212.         else:
  213.             if specialflag == False:
  214.                 specialflag = True
  215.                 newtext += '{'
  216.             newtext += ' ' + text[textpos].encode('hex')
  217.             textpos += 1
  218.            
  219.     if specialflag == True: newtext += ' }'
  220.  
  221.     return newtext    
  222.  
  223. def processmatch(match):
  224.     if match is None:
  225.         return -1
  226.     return match.end()
  227.  
  228.    
  229.  
  230. def myprogram(filename):
  231.  
  232.     print filename
  233.     pointers = getpointers() #First grab the pointers. We'll need these later.
  234.  
  235.     namepointer = struct.unpack('<I',filedata[0x34:0x38])[0]
  236.     names = filedata[namepointer:].split('\x00')
  237.     output = filename + '\n'
  238.    
  239.     facere = re.compile('#\d{4}F')
  240.     asciire = re.compile('[#01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ]*')
  241.     asciistring = '#01234567890FSNKWP'
  242.     for pointer in sorted(pointers):
  243.         opcode = filedata[pointer].encode('hex')
  244.         strend = findstrend(opcode, pointer)
  245.         if opcode == '61':
  246.             name = filedata[pointer+1:strend]
  247.             text = ";;terminalcode\n"
  248.         elif opcode in ('55','5e'):
  249.             name = ""
  250.         elif opcode == '5c':
  251.             if filedata[pointer+2] == '\x00':
  252.                 if ord(filedata[pointer+1])-7 < len(names):
  253.                     name = names[ord(filedata[pointer+1])-7]
  254.                 else:
  255.                     name = ""
  256.             elif filedata[pointer+2] == '\x01':
  257.                 Fpos = processmatch(facere.search(filedata[pointer:strend])) - 1
  258.                 if Fpos == -1:
  259.                     name = 'None found'
  260.                 else:
  261.                     name = facedict.get(filedata[pointer+Fpos-4:pointer+Fpos-2],'Unknown')
  262.                     if name == 'Special':
  263.                         if int(filedata[pointer+Fpos-2:pointer+Fpos]) < 12:
  264.                             name = 'Tio (Fancy)'
  265.                         else:
  266.                             name = 'Zeit'
  267.                     if name == 'Unknown':
  268.                         name = codedict.get(filedata[pointer+1],'Unknown')    
  269.         elif opcode == '5d':
  270.             name = filedata[pointer+3:filedata.find('\x00',pointer+3)]
  271.  
  272.         if opcode == '5e':
  273.             text = filedata[pointer+8:strend]
  274.         elif opcode in ('55','5c'):
  275.             text = filedata[pointer+3:strend]
  276.         elif opcode == '5d':
  277.             strend1 = filedata.find('\x00',pointer+3)
  278.             text = filedata[strend1+1:strend]
  279.         if opcode in ('55','5c','5d','5e'):
  280.             text = filterspecialcodes(text)
  281.             text = text.replace('{ 01 }',';linebreak\n;;;;')
  282.             text = text.replace('{ 01',';linebreak\n;;;;{')
  283.             text = text.replace('{ 02 03 }',';pagebreak\n;;;;')
  284.             text = ';' + text
  285.             textpos = 0
  286.             newtext = ""
  287.             flag = False
  288.             while textpos < len(text):
  289.                 if text[textpos] == '#' and textpos + 1 != len(text):
  290.                     if text[textpos+1] in asciistring:
  291.                         flag = True
  292.                 if flag == True and text[textpos] not in asciistring:
  293.                     if text[textpos-1] in "FSNKWP":
  294.                         newtext = replacestr(newtext,"",newtext.rfind(';',0,-1),1)
  295.                         newtext += ";"
  296.                     flag = False
  297.                 newtext += text[textpos]
  298.                 textpos += 1
  299.             text = newtext
  300.                    
  301.         if opcode == '5e':
  302.             text += ';linebreak\n'
  303.         elif opcode in ('55','5c','5d'):
  304.             text += ';terminalcode\n'
  305.         output += hex(pointer) + ';' + opcode + ';' + name + ';' + text
  306.  
  307.     outfile = open(os.path.splitext(filename)[0] + '.data','wb')
  308.     outfile.write(output) #write the output
  309.     outfile.close
  310.        
  311. if __name__ == '__main__':
  312. ##
  313. ##    sys.argv.append('c0000')
  314.     filedata = get_data(sys.argv[1] + '.orig')
  315.     myprogram(sys.argv[1])
Add Comment
Please, Sign In to add comment