mirror of
https://github.com/pmret/papermario.git
synced 2024-11-08 20:12:30 +01:00
126 lines
3.9 KiB
Python
126 lines
3.9 KiB
Python
|
from dataclasses import dataclass
|
||
|
from typing import Dict
|
||
|
|
||
|
import spimdisasm
|
||
|
import tqdm
|
||
|
from intervaltree import Interval, IntervalTree
|
||
|
|
||
|
from util import log, options, symbols
|
||
|
|
||
|
|
||
|
@dataclass
|
||
|
class Reloc:
|
||
|
rom_address: int
|
||
|
reloc_type: str
|
||
|
symbol_name: str
|
||
|
|
||
|
addend: int = 0
|
||
|
|
||
|
|
||
|
all_relocs: Dict[int, Reloc] = {}
|
||
|
|
||
|
|
||
|
def add_reloc(reloc: Reloc):
|
||
|
all_relocs[reloc.rom_address] = reloc
|
||
|
|
||
|
|
||
|
def initialize():
|
||
|
global all_relocs
|
||
|
|
||
|
all_relocs = {}
|
||
|
|
||
|
for path in options.opts.reloc_addrs_paths:
|
||
|
if not path.exists():
|
||
|
continue
|
||
|
|
||
|
with path.open() as f:
|
||
|
sym_addrs_lines = f.readlines()
|
||
|
for line_num, line in enumerate(
|
||
|
tqdm.tqdm(sym_addrs_lines, desc=f"Loading relocs ({path.stem})")
|
||
|
):
|
||
|
line = line.strip()
|
||
|
# Allow comments
|
||
|
line = line.split("//")[0]
|
||
|
line = line.strip()
|
||
|
|
||
|
if line == "":
|
||
|
continue
|
||
|
|
||
|
rom_addr = None
|
||
|
reloc_type = None
|
||
|
symbol_name = None
|
||
|
addend = None
|
||
|
|
||
|
for info in line.split(" "):
|
||
|
if ":" not in info:
|
||
|
continue
|
||
|
|
||
|
if info.count(":") > 1:
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.write(f"Too many ':'s in '{info}'")
|
||
|
log.error("")
|
||
|
|
||
|
attr_name, attr_val = info.split(":")
|
||
|
if attr_name == "":
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.write(
|
||
|
f"Missing attribute name in '{info}', is there extra whitespace?"
|
||
|
)
|
||
|
log.error("")
|
||
|
if attr_val == "":
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.write(
|
||
|
f"Missing attribute value in '{info}', is there extra whitespace?"
|
||
|
)
|
||
|
log.error("")
|
||
|
|
||
|
# Non-Boolean attributes
|
||
|
try:
|
||
|
if attr_name == "rom":
|
||
|
rom_addr = int(attr_val, 0)
|
||
|
continue
|
||
|
if attr_name == "reloc":
|
||
|
reloc_type = attr_val
|
||
|
continue
|
||
|
if attr_name == "symbol":
|
||
|
symbol_name = attr_val
|
||
|
continue
|
||
|
if attr_name == "addend":
|
||
|
addend = int(attr_val, 0)
|
||
|
continue
|
||
|
except:
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.write(f"value of attribute '{attr_name}' could not be read:")
|
||
|
log.write("")
|
||
|
raise
|
||
|
|
||
|
if rom_addr is None:
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.error(f"Missing required 'rom' attribute for reloc")
|
||
|
if reloc_type is None:
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.error(f"Missing required 'reloc' attribute for reloc")
|
||
|
if symbol_name is None:
|
||
|
log.parsing_error_preamble(path, line_num, line)
|
||
|
log.error(f"Missing required 'symbol' attribute for reloc")
|
||
|
|
||
|
reloc = Reloc(rom_addr, reloc_type, symbol_name)
|
||
|
if addend is not None:
|
||
|
reloc.addend = addend
|
||
|
|
||
|
add_reloc(reloc)
|
||
|
|
||
|
|
||
|
def initialize_spim_context():
|
||
|
for rom_address, reloc in all_relocs.items():
|
||
|
reloc_type = spimdisasm.common.RelocType.fromStr(reloc.reloc_type)
|
||
|
|
||
|
if reloc_type is None:
|
||
|
log.error(
|
||
|
f"Reloc type '{reloc.reloc_type}' is not valid. Rom address: 0x{rom_address:X}"
|
||
|
)
|
||
|
|
||
|
symbols.spim_context.addGlobalReloc(
|
||
|
rom_address, reloc_type, reloc.symbol_name, addend=reloc.addend
|
||
|
)
|