Guest User

Untitled

a guest
Oct 19th, 2018
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.85 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. from binascii import unhexlify
  4. import md5
  5.  
  6. __author__ = "Devon Meunier"
  7. __email__ = "devon.meunier@utoronto.ca"
  8. __license__ = "MIT"
  9. __version__ = "0.3"
  10.  
  11.  
  12. def get_md5(source):
  13. """Return the MD5 hash of the file `source`."""
  14. m = md5.new()
  15. while True:
  16. d = source.read(8196)
  17. if not d:
  18. break
  19. m.update(d)
  20. return m.hexdigest()
  21.  
  22.  
  23. def hex_to_bstr(d):
  24. """Return the bytestring equivalent of a plain-text hex value."""
  25. if len(d) % 2:
  26. d = "0" + d
  27. return unhexlify(d)
  28.  
  29.  
  30. def load_line(s):
  31. """Tokenize a tab-delineated string and return as a list."""
  32. return s.strip().split('\t')
  33.  
  34.  
  35. def load_script():
  36. script = {}
  37. script["file"] = "ROM Expander Pro.txt"
  38. with open(script["file"]) as script_file:
  39. script_lines = script_file.readlines()
  40.  
  41. # Load the `NAME` line from script.
  42. l = load_line(script_lines.pop(0))
  43. assert 'NAME' == l.pop(0)
  44. script["source"], script["target"] = l
  45. assert script["target"] != script["source"]
  46.  
  47. # Load the `SIZE` and optional `MD5`
  48. l = load_line(script_lines.pop(0))
  49. script["old_size"] = eval("0x" + l[1])
  50. script["new_size"] = eval("0x" + l[2])
  51. if l.index(l[-1]) > 2:
  52. script["MD5"] = l[3].lower()
  53.  
  54. # Load the replacement `HEADER`.
  55. l = load_line(script_lines.pop(0))
  56. assert 'HEADER' == l.pop(0)
  57. script["header_size"] = eval("0x" + l.pop(0))
  58. assert script["header_size"] > len(l)
  59. # Sanitize and concatenate the header data.
  60. new_header = "".join(["0" * (2 - len(x)) + x for x in l])
  61. # Cast to character data and pad with 0x00 to header_size
  62. new_header = hex_to_bstr(new_header)
  63. script["header"] = new_header + "\x00" * (script["header_size"] - len(l))
  64.  
  65. # Check the source file MD5.
  66. if "MD5" in script:
  67. with open(script["source"], "rb") as s_file:
  68. # Don't digest the header.
  69. s_file.read(script["header_size"])
  70. assert script["MD5"] == get_md5(s_file)
  71.  
  72. script["ops"] = []
  73. while script_lines:
  74. script["ops"].append(load_line(script_lines.pop(0)))
  75.  
  76. script["patches"] = []
  77. for op in script["ops"]:
  78. if op[0] == "REPLACE":
  79. op.pop(0)
  80. script["patches"].append(op)
  81.  
  82. return script
  83.  
  84.  
  85. def expand_rom(script):
  86. print "Expanding..."
  87. with open(script["source"], "rb") as s, open(script["target"], "wb") as t:
  88. def copy(a, b):
  89. source_ptr = script["header_size"] + a
  90. write_ptr = script["header_size"] + b
  91. s.seek(source_ptr)
  92. t.seek(write_ptr)
  93. t.write(s.read(end_ptr - write_ptr))
  94. print "COPY"
  95.  
  96. def fill(destination, value):
  97. write_ptr = script["header_size"] + destination
  98. t.seek(write_ptr)
  99. t.write(value * (end_ptr - write_ptr))
  100. print "FILL"
  101.  
  102. # Write Header
  103. t.write(script["header"])
  104.  
  105. while script["ops"]:
  106. op = script["ops"].pop(0)
  107. cmd = op.pop(0)
  108.  
  109. if not script["ops"]:
  110. end_ptr = script["header_size"] + script["new_size"]
  111. else:
  112. end_ptr = eval("0x" + script["ops"][0][1]) + \
  113. script["header_size"]
  114.  
  115. if cmd == "COPY":
  116. copy(eval("0x" + op[1]), # Source
  117. eval("0x" + op[0])) # Target
  118.  
  119. elif cmd == "FILL":
  120. fill(eval("0x" + op[0]), # Destination
  121. hex_to_bstr(op[1])) # Value
  122. else:
  123. raise Exception
  124.  
  125. # REPLACE
  126. for patch in script["patches"]:
  127. offset = eval("0x" + patch.pop(0))
  128. data = "".join(["0" * (2 - len(x)) + x for x in patch])
  129. t.seek(offset)
  130. t.write(hex_to_bstr(data))
  131.  
  132.  
  133. def run():
  134. script = load_script()
  135. expand_rom(script)
  136.  
  137. if __name__ == "__main__":
  138. run()
Add Comment
Please, Sign In to add comment