Files
super6502/sw/script/o65dump.py
2023-10-29 21:38:04 -07:00

109 lines
4.0 KiB
Python
Executable File

#!/usr/bin/python
import sys
import io
class O65():
header: dict[str, int] = {}
options: list[(int, int, bytes)] = []
text: bytes
data: bytes
undef_ref_cnt: int
text_reloc: list[(int, int, int)] = []
data_reloc: list[(int, int, int)] = []
exports: list[(str, int, int)] = []
def __init__(self, filename: str) -> None:
with open(filename, "rb") as _file:
self.header["no_c64"] = int.from_bytes(_file.read(2))
self.header["magic"] = int.from_bytes(_file.read(3))
self.header["version"] = int.from_bytes(_file.read(1))
self.header["mode"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["tbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["tlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["dbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["dlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["bbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["blen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["zbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["zlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["stack"] = int.from_bytes(_file.read(2), byteorder="little")
olen = int.from_bytes(_file.read(1))
while olen != 0:
otype = int.from_bytes(_file.read(1))
obytes = _file.read(olen - 2)
self.options.append((olen, otype, obytes))
olen = int.from_bytes(_file.read(1))
text_offs = _file.tell()
print(f"Text offset: {text_offs}")
self.text = _file.read(self.header["tlen"])
self.data = _file.read(self.header["dlen"])
self.undef_ref_cnt = _file.read(2)
self.text_reloc = self._parse_reloc(_file)
self.data_reloc = self._parse_reloc(_file)
export_count = int.from_bytes(_file.read(2), byteorder="little")
for _ in range(export_count):
name: bytearray = bytearray()
data = 0
while True:
data = _file.read(1)
if data != b"\x00":
name.extend(data)
else:
break
segment = int.from_bytes(_file.read(1))
value = int.from_bytes(_file.read(2), byteorder="little")
self.exports.append((name.decode(), segment, value))
def _parse_reloc(self, fd: io.BufferedReader) -> list[(int, int, int)]:
reloc: list[(int, int, int)] = []
offset = fd.read(1)
while offset != b'\x00':
offset_val = 0
while offset == b'\xff':
offset = fd.read(1)
offset_val += int.from_bytes(offset) - 1
offset_val += int.from_bytes(offset)
typebyte = int.from_bytes(fd.read(1))
lobyte = None
if typebyte & 0x40:
lobyte = int.from_bytes(fd.read(1))
reloc.append((offset_val, typebyte, lobyte))
offset = fd.read(1)
return reloc
def main() -> None:
if len(sys.argv) < 2:
print("Please supply a filename")
return
filename = sys.argv[1]
print(filename)
o65 = O65(filename)
for item, value in o65.header.items():
print(f"{item}:\t{value:#x}")
total_olen = 0
for option in o65.options:
print(f"Length: {option[0]:#x} Type: {option[1]:#x}, Data: {option[2]}")
total_olen += option[0]
print(f"Total option length: {total_olen:#x}")
print(f"Text size: {len(o65.text)}")
print(f"Data size: {len(o65.data)}")
for item in o65.exports:
print(f"Name: {item[0]} Addr: {item[2]:#x}")
if __name__ == "__main__":
main()