initial commit
[retrocrawl] / tools / mk_adf.py
1 #!/usr/bin/python
2 # mk_adf.py <bootblock> <payload> <output_adf>
3 #
4 # Stuff a given bootblock and payload into an output ADF image.
5
6 # Written & released by Keir Fraser <keir.xen@gmail.com>
7
8 # This is free and unencumbered software released into the public domain.
9 # See the file COPYING for more details, or visit <http://unlicense.org>.
10
11 import struct, sys
12
13 # Amiga bootblock checksum
14 def checksum(bb, sum=0):
15     while len(bb):
16         x, bb = struct.unpack(">L",bb[:4]), bb[4:]
17         sum += x[0]
18         if sum >= (1<<32):
19             sum -= (1<<32)-1
20     return sum
21
22 def main(argv):
23     bb_f = open(argv[1], "rb")
24     pl_f = open(argv[2], "rb")
25     out_f = open(argv[3], "wb")
26     bb_dat = bb_f.read()
27     pl_dat = pl_f.read()
28
29     # Construct bootblock header. We will splice in the checksum later.
30     header = struct.pack(">ccccLLLL",
31                          'D', 'O', 'S', '\0',         # Bootblock signature
32                          0,                           # Checksum (placeholder)
33                          880,                         # Root block
34                          0x60060000,                  # BRA.B +6
35                          (len(pl_dat) + 511) & ~511)  # Payload length, padded
36                          
37     
38     # Compute checksum over header, bootblock, and first 512 bytes of payload.
39     sum = checksum(pl_dat[:512], checksum(bb_dat, checksum(header)))
40     sum ^= 0xFFFFFFFF
41     # Splice the computed checksum into the header
42     header = header[:4] + struct.pack(">L", sum) + header[8:]
43     # Write out the header and bootblock code
44     out_f.write(header)
45     out_f.write(bb_dat)
46     # Pad bootblock to 512 bytes
47     for x in xrange((512-len(bb_dat)-len(header))/4):
48         out_f.write(struct.pack(">L", 0))
49     # Write the payload from sector 1 onwards
50     out_f.write(pl_dat)
51     # Pad the ADF image to 880kB
52     for x in xrange((901120-len(pl_dat)-512)/4):
53         out_f.write(struct.pack(">L", 0))
54         
55 if __name__ == "__main__":
56     main(sys.argv)