Files
Diddy-Kong-Racing/tools/python/generate_ld.py
T

136 lines
4.4 KiB
Python
Raw Normal View History

2020-05-27 19:14:56 -05:00
import re
from file_util import FileUtil
LD_NAME = 'dkr.ld'
ASM_DIR = './asm'
class LD:
def __init__(self, file):
print('Generating linker file...')
self.files = self.get_asm_files()
self.indentLevel = 0
self.file = file
self.gen_comment('linker script generated by generate_ld.py')
self.gen_newline()
self.gen_line('OUTPUT_ARCH (mips)')
self.gen_newline()
#self.gen_macros()
self.gen_sections()
print('New linker file created!')
def gen_macros(self):
self.gen_line('#define BEGIN_SEG(name, addr) \\')
self.increase_indent()
self.gen_line('_##name##SegmentStart = ADDR(.name); \\')
self.gen_line('_##name##SegmentRomStart = __romPos; \\')
self.gen_line('.name addr : AT(__romPos)')
self.decrease_indent()
self.gen_newline()
self.gen_line('#define END_SEG(name) \\')
self.increase_indent()
self.gen_line('_##name##SegmentEnd = ADDR(.name) + SIZEOF(.name); \\')
self.gen_line('_##name##SegmentRomEnd = __romPos + SIZEOF(.name); \\')
self.gen_line('__romPos += SIZEOF(.name);')
self.decrease_indent()
self.gen_newline()
def gen_sections(self):
self.gen_line('SECTIONS')
self.gen_open_block()
self.gen_line('romPos = 0x0;')
self.gen_boot_section()
self.gen_main_section()
self.gen_assets_section()
self.gen_discard()
self.gen_close_block()
def gen_boot_section(self):
self.gen_line('.boot 0 : AT(romPos)')
self.gen_open_block()
self.gen_line('build/asm/boot/rom_header.o(.text);')
self.gen_line('build/asm/boot/rom_boot.o(.text);')
self.gen_close_block()
self.gen_line('romPos += SIZEOF(.boot);')
self.gen_newline()
def gen_main_section(self):
self.gen_line('.main 0x80000400 : AT(romPos) SUBALIGN(16)')
self.gen_open_block()
self.files.sort(key = lambda x: x[2]) # Sort tuples by RAM address
for asmFile in self.files:
self.gen_line(asmFile[0] + '.o(.text);')
self.gen_close_block()
self.gen_line('romPos += SIZEOF(.main);')
self.gen_newline()
def gen_assets_section(self):
self.gen_line('.assets 0 : AT(romPos)')
self.gen_open_block()
self.gen_line('build/asm/assets/assets.o(.text);')
self.gen_close_block()
self.gen_line('romPos += SIZEOF(.assets);')
self.gen_newline()
def gen_discard(self):
self.gen_comment('Discard everything not specifically mentioned above.')
self.gen_line('/DISCARD/ :')
self.gen_open_block()
self.gen_line('*(*);')
self.gen_close_block()
def increase_indent(self):
self.indentLevel += 1
def decrease_indent(self):
self.indentLevel -= 1
def gen_open_block(self):
self.gen_line('{')
self.increase_indent()
def gen_close_block(self):
self.decrease_indent()
self.gen_line('}')
def gen_line(self, text):
spaces = 4 * self.indentLevel
while spaces > 0:
self.file.write(' ')
spaces -= 1
self.file.write(text)
self.gen_newline()
def gen_comment(self, text):
spaces = 4 * self.indentLevel
while spaces > 0:
self.file.write(' ')
spaces -= 1
self.file.write('/* ' + text + ' */')
self.gen_newline()
def gen_newline(self):
self.file.write('\n')
def get_asm_files(self):
asmFiles = []
asmFilenames = FileUtil.get_filenames_from_directory(ASM_DIR, ('.s',))
regex = r'[\/][*]\s*([0-9A-F]{6})\s*([0-9A-F]{8})\s*([0-9A-F]{8})\s*[*][\/]'
for filename in asmFilenames:
with open(ASM_DIR + '/' + filename, 'r') as asmFile:
notDone = True
line = asmFile.readline()
while line:
matches = re.match(regex, line)
if matches is None:
line = asmFile.readline()
continue
matchedGroups = matches.groups()
asmFiles.append(('build/asm/' + filename[:-2], matchedGroups[0], matchedGroups[1]))
break
return asmFiles
with open(LD_NAME, 'w') as ldFile:
LD(ldFile)