Admin Panel

#!/usr/bin/env python2.7

import argparse
import array
import struct

parser = argparse.ArgumentParser(description="Patch the bsr.l to bsr.w instructions in an Amiga binary to make it 68000 compatible")
parser.add_argument('bin_file', help="AmigaOS binary")
parser.add_argument('off_file', help="Offset file to patch")
parser.add_argument('-a', '--add_offset', action='store', type=int, default=0, help="add global offset (i.e. hunk begin)")
parser.add_argument('-o', '--output', action='store', default=None, help="output file")
args = parser.parse_args()

# read bin_file
bin = open(args.bin_file, "rb")
bin_str = bin.read()
bin_data = array.array('B', bin_str)
bin.close()

add_offset = args.add_offset
nop = 0x4e71 # opcode NOP

# parse offset
off = open(args.off_file, "rb")
for line in off:
  # parse and get address
  parts = line.split()
  addr_str = parts[0]
  addr = int(addr_str, 16) + add_offset

  # read words
  words = struct.unpack_from(">HHh",bin_data,offset=addr)
  opcode = words[0]
  far = words[1]
  distance = words[2]
  # check opcode
  valid = opcode & 0xf0ff
  if valid == 0x60ff:
    # check distance
    if far == 0 or far == 0xffff:
      print "OK: %08x  distance: %d" % (addr, distance)
      # patch!
      opcode = opcode & 0xff00
      struct.pack_into(">HhH",bin_data,addr,opcode,distance,nop)
    else:
      print "INVALID(too far): %08x  %04x  %08x" % (addr,opcode,distance)
  else:
    print "INVALID(no branch): %08x  %04x  %08x" % (addr,opcode,distance)
  
off.close()

# write output
output = args.output
if output == None:
  output = args.bin_file + ".patched"

print "writing '%s'..." % output,
out = file(output, "wb")
bin_data.tofile(out)
out.close()
print "done"