#!/usr/bin/env python3 """ Pass 3 for Wild Gunman (JU): Add semantic names to data tables. Pass 3 names data tables and structures based on their usage patterns and the header documentation which identifies: - Inline dispatch tables ($C6AC-$C802) - Sound/music pattern data ($DEED-$F371) - Note/volume tables ($F3EF/$F48F) - Sprite/attribute tables ($F77C-$FFF3) """ import re from pathlib import Path # ============================================================================ # DATA TABLE NAME MAP # Address -> (name, description) # Only include regions that are pure data (not mixed code/data) # ============================================================================ DATA_TABLES = { 0xC6AC: ("SpriteAttributeTable", "Sprite attribute data: Y/tile/attr/X groups for object sprites"), 0xF3EF: ("NoteVolumeTable", "APU note period/volume lookup table (32 bytes)"), 0xF48F: ("VolumeEnvelopeTable", "APU volume envelope lookup table (96 bytes)"), 0xF77C: ("SpritePositionTable", "Sprite position/attribute table (2168 bytes)"), } def process_file(input_path, output_path): text = Path(input_path).read_text() lines = text.split('\n') # Build a map of PRG offset -> line index for data regions # Find where each data address appears in the file addr_to_line = {} for i, line in enumerate(lines): m = re.search(r'; CPU:\$([0-9A-F]{4}) PRG:([0-9A-F]{4})', line) if m: cpu_addr = int(m.group(1), 16) addr_to_line[cpu_addr] = i print(f"Found {len(addr_to_line)} address annotations") # Find insertion points for each data table insertions = [] # (line_index, label_text) for addr, (name, desc) in DATA_TABLES.items(): if addr in addr_to_line: line_idx = addr_to_line[addr] # Verify this line is a .byte or .word line (data, not code) if '.byte' in lines[line_idx] or '.word' in lines[line_idx]: insertions.append((line_idx, f"{name}:")) print(f" {name} at CPU:${addr:04X} -> line {line_idx+1}") else: print(f" SKIP {name} at CPU:${addr:04X} -> line {line_idx+1} is not a data line: {lines[line_idx][:60]}") else: print(f" WARNING: CPU:${addr:04X} not found in file") # Sort insertions by line index (descending) so we can insert without shifting insertions.sort(key=lambda x: x[0], reverse=True) # Apply insertions for line_idx, label_text in insertions: lines.insert(line_idx, label_text) new_text = '\n'.join(lines) Path(output_path).write_text(new_text) print(f"\nWritten to {output_path}") print(f"Added {len(insertions)} data table labels") if __name__ == '__main__': input_file = "NROM/Wild Gunman (U)/prg.s" output_file = "NROM/Wild Gunman (U)/prg.s" process_file(input_file, output_file)