tp/tools/libdol2asm/data/struct.py

96 lines
3.5 KiB
Python

from dataclasses import dataclass, field
from typing import List
from ..builder import AsyncBuilder
from .. import util
from ..types import *
from .base import *
from .identifier import *
@dataclass(eq=False)
class Structure(ArbitraryData):
members: List[Symbol] = field(default_factory=list)
def valid_reference(self, addr):
for field in self.members:
if field.addr == addr:
return True
return False
def cpp_reference(self, accessor, addr):
for field in self.members:
if field.addr == addr:
offset = field.addr - self.addr
return f"(((char*)&{self.identifier.label})+0x{offset:X}) /* {field.identifier.name} */"
raise Dol2ZelException(
f"invalid reference addr 0x{addr:08X} for {type(self).__name__}\n{self}")
def asm_reference(self, addr):
for field in self.members:
if field.addr == addr:
offset = field.addr - self.addr
return f"{self.identifier.label}+0x{offset:X}"
return None
def set_mlts(self, module: int, library: str, translation_unit: str, section: str):
super().set_mlts(module, library, translation_unit, section)
for member in self.members:
member.set_mlts(module, library, translation_unit, section)
async def export_declaration_head(self, exporter, builder: AsyncBuilder):
has_data = any([ not not x.data for x in self.members ])
if not has_data:
for field in self.members:
await builder.write(f"\t/* {field.addr:08X} {field.size:04X}+{field.padding:02X} {field.identifier.label} {field.identifier.name} */")
await super().export_declaration_head(exporter, builder)
async def export_declaration_body(self, exporter, builder: AsyncBuilder):
has_data = any([ not not x.data for x in self.members ])
if has_data:
await builder.write(f" = {{")
for field in self.members:
await builder.write(f"\t/* {field.addr:08X} {field.size:04X}+{field.padding:02X} {field.identifier.label} {field.identifier.name} */")
await self.export_u8_data(builder, field.data)
if field.padding_data:
assert field.padding == len(field.padding_data)
await builder.write("\t/* padding */")
await self.export_u8_data(builder, field.padding_data)
if self.padding_data:
assert self.padding == len(self.padding_data)
await builder.write("\t/* padding */")
await self.export_u8_data(builder, self.padding_data)
await builder.write("};")
else:
await builder.write(";")
@staticmethod
def create(section, group):
first = group[0]
last = group[-1]
start = first.start
end = last.end
members = []
for field in group:
members.append(field)
padding = last.padding
padding_data = last.padding_data
last.padding = 0
last.padding_data = bytes()
return Structure(Identifier("struct", start, None),
addr=start,
size=end - start,
padding=padding,
padding_data=padding_data,
data_type = U8,
members=members,
source=first.source)