2

Say I have a file and I'm interested in reading and storing hex values at certain addresses, like the snippet below:

22660 00 50 50 04 00 56 0F 50 25 98 8A 19 54 EF 76 00
22670 75 38 D8 B9 90 34 17 75 93 19 93 19 49 71 EF 81

I want to read the value at 0x2266D, and be able to replace it with another hex value, but I can't understand how to do it. I've tried using open('filename', 'rb'), however this reads it as the ASCII representation of the values, and I don't see how to pick and choose when addresses I want to change.

Thanks!


Edit: For an example, I have

rom = open("filename", 'rb')
for i in range(5):
     test = rom.next().split()
     print test
rom.close()

This outputs: ['NES\x1a', 'B\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x0f\x0f\x0f(\x0f!!', '!\x02\x0f\x0f', '!\x0f\x01\x08', '!:\x0f\x0f\x03!', '\x0f', '\x0f\x0f', '!', '\x0f\x0f!\x0f\x03\x0f\x12', '\x0f\x0f\x0f(\x02&%\x0f', '\x0f', '#', '!\x0f\x0f1', '!"#$\x14\x14\x14\x13\x13\x03\x04\x0f\x0f\x03\x13#!!\x00\x00\x00\x00\x00!!', '(', '\x0f"\x0f', '#\x14\x11\x12\x0f\x0f\x0f#', '\x10', "5'4\x0270&\x02\x02\x02\x02\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f126&\x13\x0f\x0f\x0f\x13&6222\x0f", '\x1c,', etc etc.

Much more than 5 bytes, and while some of it is in hex, some has been replaced with ASCII.

Aquova
  • 147
  • 3
  • 8
  • Possible duplicate of [Search and replace a line in a file in Python](http://stackoverflow.com/questions/39086/search-and-replace-a-line-in-a-file-in-python) – vallentin Apr 28 '17 at 03:03
  • 1
    Is the code block in your question literally the text of the file, or is it a hexdump of the (binary) file? – Cong Ma Apr 28 '17 at 03:07
  • @CongMa It's a hexdump of a binary file. To be specific, I'm looking at segments of an NES rom file. – Aquova Apr 28 '17 at 03:08
  • In that case what do you mean "this reads it as the ASCII representation of the values"? Can you show an example code snippet and output? Also you need to open the file as read-write. – Cong Ma Apr 28 '17 at 03:10

2 Answers2

0

There's no indication that some of the bytes were replaced by their ASCII representations. Some bytes happen to be printable.

With a binary file, you can simply seek to the location offset and write the bytes in. Working with the line-iterator in the case of binary file is problematic, as there's no meaningful "lines" in the binary blob.

You can do in-place editing like follows (in fake Python):

with open("filename", "rb+") as f:
    f.seek(0x2266D)
    the_byte = f.read(1)
    if len(the_byte) != 1:
        # something's wrong; bolt out ...
    else
        transformed_byte = your_function(the_byte)
        f.seek(-1, 1)  # back one byte relative to the current position
        f.write(transformed_byte)

But of course, you may want to do the edit on a copy, either in-memory (and commit later, as in the answer of @JosepValls), or on a file copy. The problem with gulping the whole file in memory is, of course, sometimes the system may choke ;) For that purpose you may want to mmap part of the file.

Cong Ma
  • 10,692
  • 3
  • 31
  • 47
-1

Given that is not a very big file (roms should fit fine in today's computer's memory), just do data = open('filename', 'rb').read(). Now you can do whatever you want to the data (if you print it, it will show ascii, but that is just data!). Unfortunately, string objects don't support item assignment, see this answer for more: Change one character in a string in Python?

In your case:

data = data[0:0x2266C] + str(0xFF) + data[0x2266D:]

Community
  • 1
  • 1
Josep Valls
  • 5,483
  • 2
  • 33
  • 67