mirror of
https://github.com/izzy2lost/Diddy-Kong-Racing.git
synced 2026-06-19 01:16:26 -07:00
136 lines
4.4 KiB
Python
136 lines
4.4 KiB
Python
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)
|