109 lines
4.0 KiB
Python
Executable File
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()
|
|
|