aboutsummaryrefslogtreecommitdiff
path: root/tools/buildrom.py
blob: beb51ac25367205d323e741c89a60467c8654ba1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env python
# Script to merge a rom32.bin file into a rom16.bin file.
#
# Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.

import sys
import struct

ROM16='out/rom16.bin'
ROM32='out/rom32.bin'
OFFSETS16='out/rom16.offset.auto.h'
OFFSETS32='out/rom32.offset.auto.h'
OUT='out/rom.bin'

def align(v, a):
    return (v + a - 1) // a * a

def scanconfig(file):
    f = open(file, 'rb')
    opts = {}
    for l in f.readlines():
        parts = l.split()
        if len(parts) != 3:
            continue
        if parts[0] != '#define':
            continue
        opts[parts[1]] = parts[2]
    return opts

def alteraddr(data, offset, ptr):
    rel = struct.pack("<i", ptr)
    return data[:offset] + rel + data[offset+4:]


def main():
    # Read in files
    f = open(ROM16, 'rb')
    data16 = f.read()
    f = open(ROM32, 'rb')
    data32 = f.read()

    if len(data16) != 65536:
        print "16bit code is not 65536 bytes long"
        sys.exit(1)

    # Get config options
    o16 = scanconfig(OFFSETS16)
    o32 = scanconfig(OFFSETS32)

    # Inject 32bit code
    spos = align(int(o16['OFFSET_bios16c_end'], 16), 16)
    epos = int(o16['OFFSET_post16'], 16)
    size32 = len(data32)
    freespace = epos - spos
    if size32 > freespace:
        print "32bit code too large (%d vs %d)" % (size32, freespace)
        sys.exit(1)
    outrom = data16[:spos] + data32 + data16[spos+size32:]

    # Fixup initial jump to 32 bit code
    jmppos = int(o16['OFFSET_set_entry32'], 16)
    start32 = int(o32['OFFSET__start'], 16)
    outrom = alteraddr(outrom, jmppos+2, start32)

    # Fixup resume from 16 jump to 32 bit code
    jmppos = int(o16['OFFSET_set_resume32'], 16)
    resume32 = int(o32['OFFSET_call16_resume'], 16)
    outrom = alteraddr(outrom, jmppos+2, resume32)

    # Write output rom
    f = open(OUT, 'wb')
    f.write(outrom)
    f.close()

if __name__ == '__main__':
    main()