|
| 1 | +#!/usr/bin/python3 |
| 2 | + |
| 3 | +import os |
| 4 | + |
| 5 | +def linker_script(offset): |
| 6 | + out = """OUTPUT_ARCH(arm) |
| 7 | +MEMORY {{ |
| 8 | +
|
| 9 | + rom : ORIGIN = 0x{:08X}, LENGTH = 32M |
| 10 | + ewram : ORIGIN = 0x02000000, LENGTH = 4M - 4k |
| 11 | +}} |
| 12 | +
|
| 13 | +SECTIONS {{ |
| 14 | + .text : {{ |
| 15 | +
|
| 16 | + FILL (0xABCD) |
| 17 | +
|
| 18 | + __text_start = . ; |
| 19 | + *(.init) |
| 20 | + *(.text) |
| 21 | + *(.ctors) |
| 22 | + *(.dtors) |
| 23 | + *(.rodata) |
| 24 | + *(.fini) |
| 25 | + *(COMMON) |
| 26 | + __text_end = . ; |
| 27 | +
|
| 28 | + __bss_start__ = . ; |
| 29 | + *(.bss) |
| 30 | + __bss_end__ = . ; |
| 31 | + _end = __bss_end__ ; |
| 32 | + __end__ = __bss_end__ ; |
| 33 | + }} >rom = 0xff |
| 34 | +}} |
| 35 | + """.format(offset) |
| 36 | + |
| 37 | + return out |
| 38 | + |
| 39 | +def target(path): |
| 40 | + base, ext = os.path.splitext(path.strip()) |
| 41 | + |
| 42 | + # TODO: Ensure target name is unique |
| 43 | + target_name = base |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | + if ext in ['.s', '.asm']: |
| 48 | + target_name += '.o' |
| 49 | + output = '{}: {}\n\t'.format(target_name, path.strip()) |
| 50 | + output += '$(AS) $(AFLAGS) -c {} -o {}'.format(path.strip(), target_name) |
| 51 | + elif ext in ['.c']: |
| 52 | + target_name += '.o' |
| 53 | + output = '{}: {}\n\t'.format(target_name, path.strip()) |
| 54 | + output += '$(CC) $(CFLAGS) -c {}'.format(path) |
| 55 | + elif ext in ['.cc', '.cpp', '.cxx']: |
| 56 | + target_name += '.o' |
| 57 | + output = '{}: {}\n\t'.format(target_name, path.strip()) |
| 58 | + output += '$(CXX) $(CXXFLAGS) -c {}'.format(path) |
| 59 | + elif ext in ['.csv']: |
| 60 | + # String |
| 61 | + target_name += '.h' |
| 62 | + output = '{}: {}\n\t'.format(target_name, path.strip()) |
| 63 | + output += 'python3 poke2c.py {}'.format(path) |
| 64 | + else: |
| 65 | + raise ValueError(path, ext) |
| 66 | + |
| 67 | + output += '\n' |
| 68 | + |
| 69 | + return target_name, output |
| 70 | + |
| 71 | +def makefile(toolchain, rom_path, offset=0x800000): |
| 72 | + with open('targets') as file: |
| 73 | + lines = [line.strip() for line in file] |
| 74 | + targets = dict(target(line) for line in lines) |
| 75 | + order = [target(line)[0] for line in lines] |
| 76 | + |
| 77 | + with open('linker.lsc', 'w') as file: |
| 78 | + file.write(linker_script(0x8000000 + offset)) |
| 79 | + |
| 80 | + with open(rom_path, 'rb') as file: |
| 81 | + file.seek(0xAC) |
| 82 | + gamecode = file.read(4).decode() |
| 83 | + file.seek(0xBC) |
| 84 | + version = int(file.read(1)[0]) |
| 85 | + |
| 86 | + target_strings = ' '.join(item for item in order if os.path.splitext(item)[1] == '.o') |
| 87 | + target_strings_all = ' '.join(order) |
| 88 | + |
| 89 | + output = """ |
| 90 | +all: {targets_all} |
| 91 | +\t$(LD) $(LDFLAGS) -o a.o -T {linker_script} -T {symbols} {targets} |
| 92 | +\t$(OBJCOPY) -O binary a.o a.bin |
| 93 | +
|
| 94 | +""".format(targets=target_strings, targets_all=target_strings_all, linker_script='linker.lsc', symbols=gamecode + '.sym') |
| 95 | + |
| 96 | + defines = """CC={toolchain[cc]} |
| 97 | +CXX={toolchain[cxx]} |
| 98 | +AS={toolchain[as]} |
| 99 | +LD={toolchain[ld]} |
| 100 | +OBJCOPY={toolchain[objcopy]} |
| 101 | +OBJDUMP={toolchain[objdump]} |
| 102 | +XXD=xxd |
| 103 | +IMG=todo |
| 104 | +COMPRESS=toolchain/gbalzss |
| 105 | +PADBIN=toolchain/padbin |
| 106 | +
|
| 107 | +OPTS=-fauto-inc-dec -fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdse -fguess-branch-probability -fif-conversion2 -fif-conversion -fipa-pure-const -fipa-profile -fipa-reference -fmerge-constants -fsplit-wide-types -ftree-bit-ccp -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-sra -ftree-pta -ftree-ter -funit-at-a-time -fomit-frame-pointer -fthread-jumps -falign-functions -falign-jumps -falign-loops -falign-labels -fcaller-saves -fcrossjumping -fcse-follow-jumps -fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize -fexpensive-optimizations -fgcse -fgcse-lm -finline-small-functions -findirect-inlining -fipa-sra -foptimize-sibling-calls -fpartial-inlining -fpeephole2 -fregmove -freorder-blocks -freorder-functions -frerun-cse-after-loop -fsched-interblock -fsched-spec -fschedule-insns -fschedule-insns2 -fstrict-aliasing -fstrict-overflow -ftree-switch-conversion -ftree-tail-merge -ftree-pre -ftree-vrp -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-slp-vectorize -fvect-cost-model -fipa-cp-clone -ffast-math -fforward-propagate -finline-functions-called-once -fmerge-all-constants -fmodulo-sched -fmodulo-sched-allow-regmoves -fgcse-sm -fgcse-las -funsafe-loop-optimizations -fconserve-stack |
| 108 | +DEFINES=-D{gamecode} -DSOFTWARE_VERSION={version} |
| 109 | +CFLAGS=-mthumb -mthumb-interwork -mcpu=arm7tdmi $(OPTS) -mlong-calls -march=armv4t -Wall -O3 $(DEFINES) |
| 110 | +CXXFLAGS=-mthumb -mthumb-interwork -mcpu=arm7tdmi $(OPTS) -mlong-calls -march=armv4t -Wall -O3 $(DEFINES) |
| 111 | +ASFLAGS=-mthumb |
| 112 | +LDFLAGS= |
| 113 | +""".format(toolchain=toolchain, gamecode=gamecode, version=version) |
| 114 | + body = '\n'.join(targets.values()) |
| 115 | + |
| 116 | + clean = """ |
| 117 | +clean: |
| 118 | +\trm -rf {targets} a.o a.bin |
| 119 | +""".format(targets=target_strings_all) |
| 120 | + |
| 121 | + insert = """ |
| 122 | +insert: |
| 123 | +\tdd conv=notrunc of={rom} if={bin} bs=1 seek={offset} |
| 124 | +""".format(offset=offset, rom=rom_path, bin='a.bin') |
| 125 | + |
| 126 | + with open('makefile', 'w') as file: |
| 127 | + print(defines + output + body + clean + insert, file=file) |
| 128 | + |
| 129 | +toolchain = { |
| 130 | + 'cc': 'arm-linux-gnueabi-gcc-4.7', |
| 131 | + 'cxx': 'arm-linux-gnueabi-gcc-4.7', |
| 132 | + 'as': 'arm-linux-gnueabi-as', |
| 133 | + 'ld': 'arm-linux-gnueabi-ld', |
| 134 | + 'objcopy': 'arm-linux-gnueabi-objcopy', |
| 135 | + 'objdump': 'arm-linux-gnueabi-objcopy' |
| 136 | + } |
| 137 | +makefile(toolchain, 'test.gba') |
| 138 | + |
0 commit comments