jvm/regs/sparse_struct_java.py
2025-01-20 19:53:23 -06:00

123 lines
4.3 KiB
Python

def render_fields(get_type, fields):
for field in fields:
if field.name.startswith("_res"):
continue
field_type = get_type(field.name)
if field.array_length == 1:
yield f"public {field_type} {field.name};"
else:
for i in range(field.array_length):
yield f"public {field_type} {field.name}{i};"
def render_constructor(get_type, declaration, store_queue_buffer):
initializer = f"public {declaration.name}("
padding = " " * len(initializer)
def start(i):
if i == 0:
return initializer
else:
return padding
constructor_fields = [f for f in declaration.fields
if (not f.name.startswith('_res')
and f.default is None
)]
for i, field in enumerate(constructor_fields):
s = start(i)
assert field.array_length <= 4, field
type = get_type(field.name) if field.array_length == 1 else "int"
comma = ',' if i + 1 < len(constructor_fields) else ''
yield s + f"{type} {field.name}" + comma
if constructor_fields:
yield padding + ') {'
else:
yield initializer + ') {'
yield "super();"
for i, field in enumerate(declaration.fields):
if field.name.startswith("_res"):
continue
value = field.name if not field.name.startswith('_res') else '0'
value = hex(field.default) if field.default is not None else value
s = ':' if i == 0 else ','
if field.array_length == 1:
yield f"this.{field.name} = {value};"
else:
max_shift = 8 * (field.array_length - 1)
for i in range(field.array_length):
shift = max_shift - (i * 8)
yield f"this.{field.name}{i} = ({field.name} >> {shift}) & 0xff;"
yield "}"
array_fields = [f for f in declaration.fields
if f.array_length > 1]
def render_get_byte(fields):
ix = 0
yield "public int getByte(int ix) {"
yield "switch (ix) {"
for field in fields:
if "_res" in field.name:
continue
if field.array_length == 1:
yield f"case {ix}: return {field.name};"
else:
for i in range(field.array_length):
yield f"case {ix + i}: return {field.name}{i};"
ix += field.array_length
yield "default: return 0;"
yield "}"
yield "}"
def render_submit(get_type, fields):
yield "public void submit() {"
for i, field in enumerate(fields):
index = i * 4
value = "0" if "_res" in field.name else field.name
field_type = get_type(field.name)
if field_type == "int":
yield f"putInt({index}, {value});"
elif field_type == "float":
yield f"putFloat({index}, {value});"
else:
assert False, field_type
yield "Memory.putU4(0xff000038, MemoryMap.ta_fifo_polygon_converter); // QACR0";
if len(fields) == 16:
yield "Memory.putU4(0xff00003c, MemoryMap.ta_fifo_polygon_converter); // QACR1";
if len(fields) == 8:
yield "SH4Intrinsic.pref1(MemoryMap.store_queue);"
else:
yield "SH4Intrinsic.pref2(MemoryMap.store_queue);"
yield "}"
def render_declaration(get_type, declaration, store_queue_buffer, get_byte):
yield f"public static class {declaration.name}"
if store_queue_buffer:
assert len(declaration.fields) in {8, 16}, len(declaration.fields)
yield " extends StoreQueueBuffer"
yield " implements GdromCommandPacketInterface {"
yield ""
yield from render_fields(get_type, declaration.fields)
yield from render_constructor(get_type, declaration, store_queue_buffer)
if get_byte:
yield from render_get_byte(declaration.fields)
if store_queue_buffer:
yield from render_submit(get_type, declaration.fields)
yield "}"
def render_declarations(get_type, package_name, class_name, declarations, *, store_queue_buffer, get_byte):
yield f"package sega.dreamcast.{package_name};"
yield ""
if store_queue_buffer:
yield "import sega.dreamcast.sh7091.StoreQueueBuffer32;"
yield ""
yield f"public class {class_name} {{"
for declaration in declarations:
yield from render_declaration(get_type, declaration, store_queue_buffer, get_byte)
yield "}"