makemessage.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from __future__ import with_statement
  4. import argparse
  5. import os
  6. import traceback
  7. import struct
  8. def main():
  9. #示例:lscript.py -i /home/user/PAL -e gb2312 -o dialog.txt
  10. parser = argparse.ArgumentParser(description='Output FFFF info of Script file.')
  11. parser.add_argument('-i','--input', dest='inpath', help='Game path')
  12. parser.add_argument('-o','--output', dest='outfile', help='Output file')
  13. parser.add_argument('-w','--width', dest='wordwidth', help='Word width in bytes')
  14. parser.add_argument('-e','--encoding', dest='encoding', help='Encoding name')
  15. options = parser.parse_args()
  16. if options.inpath == None or len(options.inpath) == 0:
  17. print 'Game path must be specified!'
  18. parser.print_help()
  19. return
  20. if options.encoding == None or len(options.encoding) == 0:
  21. print 'Encoding must be specified!'
  22. parser.print_help()
  23. return
  24. if options.outfile == None or len(options.outfile) == 0:
  25. print 'Output file must be specified!'
  26. parser.print_help()
  27. return
  28. if options.inpath[-1] != '/' and options.inpath[-1] != '\\':
  29. options.inpath += '/'
  30. if options.wordwidth == None:
  31. options.wordwidth = 10
  32. else:
  33. options.wordwidth = int(options.wordwidth)
  34. script_bytes = []
  35. index_bytes = []
  36. msg_bytes = []
  37. word_bytes = []
  38. is_msg_group = 0 #是否正在处理文字组的标示。
  39. msg_count = 0
  40. last_index = -1
  41. for file_ in os.listdir(options.inpath):
  42. if file_.lower() == 'sss.mkf':
  43. try:
  44. with open(options.inpath + file_, 'rb') as f:
  45. f.seek(12, os.SEEK_SET)
  46. offset_begin, script_begin, file_end = struct.unpack('<III', f.read(12))
  47. f.seek(offset_begin, os.SEEK_SET)
  48. index_bytes = f.read(script_begin - offset_begin)
  49. script_bytes = f.read(file_end - script_begin)
  50. except:
  51. traceback.print_exc()
  52. return
  53. elif file_.lower() == 'm.msg':
  54. try:
  55. with open(options.inpath + file_, 'rb') as f:
  56. msg_bytes = f.read()
  57. except:
  58. traceback.print_exc()
  59. return
  60. elif file_.lower() == 'word.dat':
  61. try:
  62. with open(options.inpath + file_, 'rb') as f:
  63. data_bytes=f.read()
  64. except:
  65. traceback.print_exc()
  66. return
  67. if len(data_bytes) % options.wordwidth != 0:
  68. data_bytes += [0x20 for i in range(0, options.wordwidth - len(data_bytes) % options.wordwidth)]
  69. output = "[BEGIN WORDS]\n"
  70. for i in range(0, len(data_bytes) / options.wordwidth):
  71. output += "%d=%s\n" % (i, data_bytes[i * options.wordwidth: (i + 1) * options.wordwidth].rstrip('\x20\x00').decode(options.encoding).encode('utf-8'))
  72. output += "[END WORDS]\n\n"
  73. print "Now Processing. Please wait..."
  74. for i in range(0, len(script_bytes) / 8):
  75. op, w1, w2, w3 = struct.unpack('<HHHH', script_bytes[i * 8 : (i + 1) * 8])
  76. if op == 0xFFFF:
  77. if is_msg_group == 0:
  78. is_msg_group = 1
  79. output += "%s %d\n" % ('[BEGIN MESSAGE]', w1)
  80. last_index = w1
  81. msg_count += 1
  82. msg_begin, msg_end = struct.unpack("<II",index_bytes[w1 * 4 : (w1 + 2) * 4])
  83. try:
  84. output += "%s\n" % (msg_bytes[msg_begin : msg_end].decode(options.encoding, 'replace').encode('utf-8'))
  85. except:
  86. traceback.print_exc()
  87. elif op == 0x008E:
  88. if is_msg_group == 1:
  89. output += "%s\n" % ('[CLEAR MESSAGE]')
  90. else:
  91. if is_msg_group == 1:
  92. is_msg_group = 0
  93. output += "%s %d\n\n" % ('[END MESSAGE]', last_index)
  94. try:
  95. with open(options.outfile, "wt") as f:
  96. f.write(output)
  97. except:
  98. traceback.print_exc()
  99. print "OK! Extraction finished!"
  100. print "Original Dialog script count: " + str(msg_count)
  101. if __name__ == '__main__':
  102. main()