mirror of
https://github.com/weiju/amiga-stuff
synced 2026-09-14 04:30:55 +00:00
added hunk reading tool
This commit is contained in:
+1
-1
@@ -69,6 +69,6 @@ def process(input_file):
|
||||
if __name__ == '__main__':
|
||||
description = """fdtool - stub generator for FD files (c) 2013"""
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
parser.add_argument('--infile', required=True, help="FD input file")
|
||||
parser.add_argument('infile', help="FD input file")
|
||||
args = parser.parse_args()
|
||||
process(args.infile)
|
||||
|
||||
Executable
+168
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python3
|
||||
"""A tool like dalf.rexx that can be used to inspect the structure of
|
||||
an Amiga Hunk file.
|
||||
"""
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
HUNK_BLOCK_UNIT = b'\x00\x00\x03\xe7'
|
||||
HUNK_BLOCK_NAME = b'\x00\x00\x03\xe8'
|
||||
HUNK_BLOCK_CODE = b'\x00\x00\x03\xe9'
|
||||
HUNK_BLOCK_DATA = b'\x00\x00\x03\xea'
|
||||
HUNK_BLOCK_BSS = b'\x00\x00\x03\xeb'
|
||||
HUNK_BLOCK_RELOC32 = b'\x00\x00\x03\xec'
|
||||
HUNK_BLOCK_RELOC16 = b'\x00\x00\x03\xed'
|
||||
HUNK_BLOCK_RELOC8 = b'\x00\x00\x03\xee'
|
||||
HUNK_BLOCK_EXT = b'\x00\x00\x03\xef'
|
||||
HUNK_BLOCK_SYMBOL = b'\x00\x00\x03\xf0'
|
||||
HUNK_BLOCK_DEBUG = b'\x00\x00\x03\xf1'
|
||||
HUNK_BLOCK_END = b'\x00\x00\x03\xf2'
|
||||
HUNK_BLOCK_HEADER = b'\x00\x00\x03\xf3'
|
||||
HUNK_BLOCK_OVERLAY = b'\x00\x00\x03\xf5'
|
||||
HUNK_BLOCK_BREAK = b'\x00\x00\x03\xf6'
|
||||
HUNK_BLOCK_DRELOC32 = b'\x00\x00\x03\xf7'
|
||||
HUNK_BLOCK_DRELOC16 = b'\x00\x00\x03\xf8'
|
||||
HUNK_BLOCK_DRELOC8 = b'\x00\x00\x03\xf9'
|
||||
HUNK_BLOCK_RELOC32SHORT = b'\x00\x00\x03\xfc'
|
||||
|
||||
# new library file
|
||||
HUNK_BLOCK_LIB = b'\x00\x00\x03\xfb'
|
||||
HUNK_BLOCK_INDEX = b'\x00\x00\x03\xfc'
|
||||
|
||||
|
||||
def read_int32(infile):
|
||||
return struct.unpack('>i', infile.read(4))[0]
|
||||
|
||||
|
||||
def read_int16(infile):
|
||||
return struct.unpack('>h', infile.read(2))[0]
|
||||
|
||||
|
||||
def read_string_list(infile):
|
||||
result = []
|
||||
strlen = read_int32(infile)
|
||||
while strlen > 0:
|
||||
result.append(str(infile.read(strlen)))
|
||||
strlen = read_int32(infile)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def read_raw_bytes(infile):
|
||||
num_bytes = read_int32(infile) * 4
|
||||
data = infile.read(num_bytes)
|
||||
if len(data) < num_bytes:
|
||||
print("WARNING: tried to read %d bytes, but only %d bytes could be read" % (num_bytes,
|
||||
bytes_read))
|
||||
return data
|
||||
|
||||
def read_reloc32map(infile):
|
||||
num_offsets = read_int32(infile)
|
||||
result = {}
|
||||
while num_offsets > 0:
|
||||
hunknum = read_int32(infile)
|
||||
hunk_offsets = [read_int32(infile) for i in range(num_offsets)]
|
||||
result[hunknum] = hunk_offsets
|
||||
num_offsets = read_int32(infile)
|
||||
return result
|
||||
|
||||
|
||||
def read_reloc16map(infile):
|
||||
num_offsets = read_int16(infile)
|
||||
total_offsets = num_offsets
|
||||
|
||||
result = {}
|
||||
while num_offsets > 0:
|
||||
hunknum = read_int16(infile)
|
||||
hunk_offsets = [read_int16(infile) for i in range(num_offsets)]
|
||||
result[hunknum] = hunk_offsets
|
||||
num_offsets = read_int16(infile)
|
||||
total_offsets += num_offsets
|
||||
|
||||
if (total_offsets % 2) == 0:
|
||||
read_int16(infile)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def read_block(infile, is_loadfile):
|
||||
id = infile.read(4)
|
||||
if len(id) == 0: # end of input
|
||||
return None
|
||||
|
||||
if id == HUNK_BLOCK_CODE:
|
||||
return ('CODE', read_raw_bytes(infile))
|
||||
elif id == HUNK_BLOCK_RELOC32:
|
||||
return ('RELOC32', read_reloc32map(infile))
|
||||
elif id == HUNK_BLOCK_END:
|
||||
return ('END', None)
|
||||
elif id == HUNK_BLOCK_DRELOC32:
|
||||
if is_loadfile:
|
||||
return ('RELOC32SHORT', read_reloc16map(infile))
|
||||
else:
|
||||
return ('RELOC32', read_reloc32map(infile))
|
||||
elif id == HUNK_BLOCK_DATA:
|
||||
return ('DATA', read_raw_bytes(infile))
|
||||
elif id == HUNK_BLOCK_BSS:
|
||||
return ('BSS', read_int32(infile) * 4)
|
||||
elif id == HUNK_BLOCK_NAME:
|
||||
return ('NAME', str(infile.read(read_int32(infile) * 4)))
|
||||
else:
|
||||
raise Exception("unsupported id: %s" % id)
|
||||
|
||||
return None
|
||||
|
||||
def read_blocks(infile, is_loadfile):
|
||||
result = []
|
||||
block = read_block(infile, is_loadfile)
|
||||
while block is not None:
|
||||
result.append(block)
|
||||
block = read_block(infile, is_loadfile)
|
||||
return result
|
||||
|
||||
def parse_hunkfile(hunkfile):
|
||||
"""Top level parsing function"""
|
||||
with open(hunkfile, 'rb') as infile:
|
||||
id = infile.read(4)
|
||||
|
||||
# can be Header or Unit
|
||||
is_loadfile = True
|
||||
if id == HUNK_BLOCK_HEADER:
|
||||
library_names = read_string_list(infile)
|
||||
print("Libraries: ", library_names)
|
||||
hunk_table_size = read_int32(infile)
|
||||
print("size hunk table: %d" % hunk_table_size)
|
||||
first_slot = read_int32(infile)
|
||||
last_slot = read_int32(infile)
|
||||
num_hunk_sizes = last_slot - first_slot + 1
|
||||
print("first slot: %d, last slot: %d, # hunk sizes: %d" % (first_slot,
|
||||
last_slot,
|
||||
num_hunk_sizes))
|
||||
hunk_sizes = [read_int32(infile) for i in range(num_hunk_sizes)]
|
||||
print("hunk sizes: ", hunk_sizes)
|
||||
elif id == HUNK_BLOCK_UNIT:
|
||||
strlen = read_int32(infile) * 4
|
||||
print("# name: %d" % strlen)
|
||||
unit_name = str(infile.read(strlen))
|
||||
print("UNIT '%s'" % unit_name)
|
||||
else:
|
||||
is_loadfile = False
|
||||
raise Exception('Unsupported header type')
|
||||
|
||||
blocks = read_blocks(infile, is_loadfile)
|
||||
print("%d blocks read: " % len(blocks))
|
||||
for i, block in enumerate(blocks):
|
||||
if block[0] == 'NAME':
|
||||
print("%d: '%s' -> '%s'" % (i, block[0], block[1]))
|
||||
elif block[0] == 'BSS':
|
||||
print("%d: '%s' -> %d" % (i, block[0], block[1]))
|
||||
else:
|
||||
print("%d: '%s'" % (i, block[0]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
description = """hunk - hunk file reader (c) 2014 Wei-ju Wu"""
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
parser.add_argument('hunkfile', help="hunk format file")
|
||||
args = parser.parse_args()
|
||||
parse_hunkfile(args.hunkfile)
|
||||
Reference in New Issue
Block a user