mirror of https://github.com/zeldaret/tp.git
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
import struct
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import List, Tuple
|
|
|
|
from ..builder import AsyncBuilder
|
|
from ..globals import *
|
|
from .. import util
|
|
from .base import *
|
|
from .identifier import *
|
|
from .literal import *
|
|
|
|
@dataclass(eq=False)
|
|
class ReferenceArray(ArbitraryData):
|
|
@property
|
|
def element_size(self):
|
|
return 4
|
|
|
|
def array_type(self):
|
|
size = self.size // self.element_size
|
|
padding = self.padding // self.element_size
|
|
|
|
if size == 1 and padding == 0:
|
|
return self.element_type()
|
|
else:
|
|
return PaddingArrayType.create(
|
|
self.element_type(),
|
|
self.size // self.element_size,
|
|
self.padding // self.element_size)
|
|
|
|
def valid_reference(self, addr):
|
|
return addr % 4 == 0
|
|
|
|
def values(self):
|
|
return Integer.u32_from(self.data)
|
|
|
|
def gather_references(self, context, valid_range):
|
|
self.references = [ addr for addr in self.values() if addr in valid_range ]
|
|
|
|
def export_reference_value(self, symbol_table, index, addr) -> str:
|
|
symbol = symbol_table[-1, addr]
|
|
if symbol:
|
|
return symbol.cpp_reference(self, addr)
|
|
elif addr == 0:
|
|
return "NULL"
|
|
else:
|
|
return f"0x{addr:08X}"
|
|
|
|
async def export_declaration_body(self, exporter, builder: AsyncBuilder):
|
|
values = self.values()
|
|
|
|
if self.total_element_count == 1:
|
|
await builder.write(f" = (void*){self.export_reference_value(exporter.gst, 0, values[0])};")
|
|
else:
|
|
await builder.write(f" = {{")
|
|
for index, addr in enumerate(values):
|
|
value = self.export_reference_value(exporter.gst, index, addr)
|
|
await builder.write(f"\t(void*){value},")
|
|
|
|
if self.padding > 0:
|
|
await builder.write("\t/* padding */")
|
|
for i in range(self.padding // self.element_size):
|
|
await builder.write("\tNULL,")
|
|
await builder.write("};")
|
|
|
|
|
|
@staticmethod
|
|
def create(identifier: Identifier, addr: int, data: bytearray, padding_data: bytearray, always_extern: bool = False) -> "ReferenceArray":
|
|
if sum(padding_data) != 0:
|
|
print(identifier)
|
|
|
|
assert sum(padding_data) == 0
|
|
assert len(data) % 4 == 0
|
|
assert len(padding_data) % 4 == 0
|
|
return ReferenceArray(
|
|
identifier=identifier,
|
|
data_type=PointerType(VOID),
|
|
addr=addr,
|
|
data = data,
|
|
size=len(data),
|
|
padding_data = padding_data,
|
|
padding = len(padding_data),
|
|
always_extern=always_extern,
|
|
) |