#!/usr/bin/env python3 """Analyze the exact binary structure of an action mapping""" def analyze_mapping_at_offset(filepath, offset, size=600): """Extract and analyze mapping at specific offset""" with open(filepath, 'rb') as f: f.seek(offset) data = f.read(size) print(f"Analyzing mapping at offset {offset} (0x{offset:X})") print("=" * 80) # Print hex dump with annotations print("\nHEX DUMP:") print("-" * 80) i = 0 while i < len(data): # Address addr = offset + i print(f"{addr:06X}: ", end="") # Hex bytes (16 per line) hex_bytes = [] ascii_chars = [] for j in range(16): if i + j < len(data): byte = data[i + j] hex_bytes.append(f"{byte:02X}") if 32 <= byte <= 126: ascii_chars.append(chr(byte)) else: ascii_chars.append(".") else: hex_bytes.append(" ") ascii_chars.append(" ") print(" ".join(hex_bytes[:8]) + " " + " ".join(hex_bytes[8:]), end="") print(" " + "".join(ascii_chars)) i += 16 # Parse structure print("\n\nSTRUCTURE ANALYSIS:") print("-" * 80) i = 0 # Check for marker if data[i:i+4] == b'ules': print(f"[{i:04d}] Marker: 'ules' (action mapping marker)") i += 4 elif i > 0 and data[i-1] == 0x05 and data[i:i+4] == b'ules': print(f"[{i-1:04d}] 0x05 - Marker type byte") print(f"[{i:04d}] Marker: 'ules' (action mapping marker)") i += 4 # Look for length byte if i < len(data): print(f"[{i:04d}] Length byte: 0x{data[i]:02X} ({data[i]} bytes)") marker_name_len = data[i] i += 1 # The "marker name" actually contains the entire mapping data print(f"[{i:04d}] Marker name/data section ({marker_name_len} bytes):") # Parse properties within the marker name props_start = i props_found = 0 j = 0 while j < min(marker_name_len, 200): # Property pattern: 01 <.name> if data[i+j] == 0x01 and j + 2 < marker_name_len: prop_name_len = data[i+j+1] if prop_name_len > 0 and prop_name_len < 50 and j + 2 + prop_name_len < marker_name_len: prop_name = data[i+j+2:i+j+2+prop_name_len].decode('utf-8', errors='ignore') if prop_name.startswith('.'): print(f" [{i+j:04d}] Property marker: 0x01") print(f" [{i+j+1:04d}] Name length: {prop_name_len}") print(f" [{i+j+2:04d}] Name: '{prop_name}'") # Check value type val_offset = i + j + 2 + prop_name_len if val_offset < len(data): val_marker = data[val_offset] if val_marker == 0x01: # Boolean val = data[val_offset+1] if val_offset+1 < len(data) else 0 print(f" [{val_offset:04d}] Value type: 0x01 (boolean)") print(f" [{val_offset+1:04d}] Value: {val} ({'True' if val else 'False'})") elif val_marker == 0x04: # Integer if val_offset + 4 < len(data): val = int.from_bytes(data[val_offset+1:val_offset+5], 'little') print(f" [{val_offset:04d}] Value type: 0x04 (integer)") print(f" [{val_offset+1:04d}] Value: {val}") elif val_marker == 0x00: # Null print(f" [{val_offset:04d}] Value type: 0x00 (null)") props_found += 1 j += 2 + prop_name_len + 2 # Skip property continue # Action pattern: 07 01 40 if data[i+j:i+j+3] == b'\x07\x01\x40' and j + 5 < marker_name_len: action_len = int.from_bytes(data[i+j+3:i+j+5], 'little') if action_len > 0 and action_len < 300 and j + 5 + action_len <= marker_name_len: action_str = data[i+j+5:i+j+5+action_len].decode('utf-8', errors='ignore') print(f" [{i+j:04d}] Action marker: 0x07 0x01 0x40") print(f" [{i+j+3:04d}] Action length: {action_len} (0x{action_len:04X})") print(f" [{i+j+5:04d}] Action string: '{action_str}'") j += 5 + action_len continue j += 1 print(f"\nFound {props_found} properties in marker data") print("\n" + "=" * 80) if __name__ == '__main__': # Analyze a new mapping from the modified file # Let's analyze mapping #37 at offset 267315 print("ANALYZING NEW MAPPING") print("Mapping #37 from TestMKS_added_mapping.set") print() analyze_mapping_at_offset('TestMKS_added_mapping.set', 267315, 600) # Also show the first mapping for comparison (has parameters) print("\n\n\n") print("ANALYZING FIRST MAPPING (WITH PARAMETERS)") print("Mapping #1 from TestMKS_added_mapping.set") print() analyze_mapping_at_offset('TestMKS_added_mapping.set', 252173, 600)