{"version":3,"file":"index.mjs","names":["isNode","RebuildProcessor","snesAddressingModes","snesVectors","snesHeaders"],"sources":["../snes/addressingModes.json","../snes/vectors.json","../snes/headers.json","../src/rom/state.ts","../src/rom/extraction/processor.ts","../src/rom/extraction/reader.ts","../src/types/constants.ts","../src/types/addressing.ts","../src/types/members.ts","../src/types/processor.ts","../src/types/resources.ts","../src/types/transforms.ts","../src/database/opcode.ts","../src/types/assembly.ts","../src/types/bitstream.ts","../src/types/compression-registry.ts","../src/types/files.ts","../src/types/location.ts","../src/types/strings.ts","../src/types/tables.ts","../src/types/operands.ts","../src/rom/extraction/references.ts","../src/rom/extraction/stack.ts","../src/rom/extraction/cop.ts","../src/rom/extraction/addressing.ts","../src/rom/extraction/transforms.ts","../src/utils/file.ts","../src/utils/crc.ts","../src/utils/base64.ts","../src/utils/index.ts","../src/rom/extraction/strings.ts","../src/rom/extraction/parser.ts","../src/rom/extraction/asm.ts","../src/assembly/Stack.ts","../src/assembly/Registers.ts","../src/rom/extraction/blocks.ts","../src/rom/extraction/postprocessor.ts","../src/rom/extraction/writer.ts","../src/rom/rebuild/layout.ts","../src/rom/rebuild/writer.ts","../src/rom/rebuild/processor.ts","../src/rom/rebuild/string-processor.ts","../src/rom/rebuild/assembler-state.ts","../src/rom/rebuild/assembler.ts","../src/rom/rebuild/sorted-map.ts","../src/database/blocks.ts","../src/database/files.ts","../src/database/structs.ts","../src/database/addressingMode.ts","../src/database/strings.ts","../src/database/cop.ts","../src/database/parts.ts","../src/database/transforms.ts","../src/database/scenes.ts","../src/database/groups.ts","../src/compression/QuintetLZ.ts","../src/compression/index.ts","../src/database/header.ts","../src/database/root.ts","../src/database/overrides.ts","../src/database/paths.ts","../src/static/package-loader.ts","../src/rom/generator.ts","../src/sprites/SpriteFrame.ts","../src/sprites/SpritePart.ts","../src/sprites/SpriteGroup.ts","../src/sprites/SpriteMap.ts","../src/index.ts"],"sourcesContent":["","","","/**\n * Lightweight ROM state placeholder used during early development.\n * This stub will be expanded as the ROM extraction pipeline matures.\n */\nexport class RomState {\n  // Basic memory buffers\n  public readonly cgram = new Uint8Array(0x200); // Color palette RAM\n  public readonly vram = new Uint8Array(0x10000); // Video RAM\n\n  /**\n   * Create ROM state from scene metadata.\n   * Parameters are currently unused but kept for future implementation.\n   */\n  public static async fromScene(\n    _baseDir: string,\n    _root: unknown,\n    _metaFile: string,\n    _id: number\n  ): Promise<RomState> {\n    return new RomState();\n  }\n}\n\n/**\n * Utility helpers for working with RomState.\n */\nexport class RomStateUtils {\n  /** Create an empty ROM state */\n  public static createEmpty(): RomState {\n    return new RomState();\n  }\n\n  /** Clear all data in the given ROM state */\n  public static clear(state: RomState): void {\n    state.cgram.fill(0);\n    state.vram.fill(0);\n  }\n}\n","import { Registers } from '../../assembly';\n\nexport class MapExt<K, V> extends Map<K, V> {\n\n  constructor() {\n    super();\n  }\n\n  public tryAdd(key: K, value: V): boolean {\n    if (this.has(key)) {\n      return false;\n    }\n    this.set(key, value);\n    return true;\n  }\n\n  public setFlag(key: K, flag: number, value: boolean = true): void {\n    if (!value) this.clearFlag(key, flag);\n    else this.set(key, (((this.get(key) as number) ?? 0) | flag) as V);\n  }\n\n  public clearFlag(key: K, flag: number): void {\n    this.set(key, (((this.get(key) as number) ?? 0) & ~flag) as V);\n  }\n}\n\n/**\n * Manages CPU processor state during ROM analysis\n * Converted from GaiaLib/Rom/Extraction/ProcessorStateManager.cs\n */\nexport class ProcessorStateManager {\n  // public readonly accumulatorFlags = new MapExt<number, boolean | null>();\n  // public readonly indexFlags = new MapExt<number, boolean | null>();\n  // public readonly bankNotes = new MapExt<number, number | null>();\n  public readonly stackPositions = new MapExt<number, number>();\n\n  private readonly _buckets: Record<string, MapExt<number, number>> = {};\n\n  public get(key: string): MapExt<number, number> {\n    return this._buckets[key] ?? (this._buckets[key] = new MapExt<number, number>());\n  }\n\n  /**\n   * Hydrate processor registers with stored state\n   * Uses Registers from gaia-core/assembly for processor state management\n   */\n  public hydrateRegisters(position: number, reg: Registers): void {\n\n    for (const [key, value] of Object.entries(this._buckets)) {\n      const val = value.get(position);\n      if (val !== undefined) {\n        reg.value[key] = val;\n      }\n    }\n\n    // const acc = this.accumulatorFlags.get(position);\n    // if (acc !== undefined) {\n    //   reg.accumulatorFlag = acc ?? undefined;\n    // }\n\n    // const ind = this.indexFlags.get(position);\n    // if (ind !== undefined) {\n    //   reg.indexFlag = ind ?? undefined;\n    // }\n\n    // const bnk = this.bankNotes.get(position);\n    // if (bnk !== undefined) {\n    //   reg.dataBank = bnk ?? undefined;\n    // }\n\n    const stack = this.stackPositions.get(position);\n    if (stack !== undefined) {\n      reg.stack.location = stack;\n    }\n  }\n\n  // // Accumulator flag methods\n  // public getAccumulatorFlag(location: number): boolean | null | undefined {\n  //   return this.accumulatorFlags.get(location);\n  // }\n\n  // public setAccumulatorFlag(location: number, value: boolean | null): void {\n  //   this.accumulatorFlags.set(location, value);\n  // }\n\n  // public tryAddAccumulatorFlag(location: number, value: boolean | null): boolean {\n  //   if (this.accumulatorFlags.has(location)) {\n  //     return false;\n  //   }\n  //   this.accumulatorFlags.set(location, value);\n  //   return true;\n  // }\n\n  // // Index flag methods\n  // public getIndexFlag(location: number): boolean | null | undefined {\n  //   return this.indexFlags.get(location);\n  // }\n\n  // public setIndexFlag(location: number, value: boolean | null): void {\n  //   this.indexFlags.set(location, value);\n  // }\n\n  // public tryAddIndexFlag(location: number, value: boolean | null): boolean {\n  //   if (this.indexFlags.has(location)) {\n  //     return false;\n  //   }\n  //   this.indexFlags.set(location, value);\n  //   return true;\n  // }\n\n  // // Bank note methods\n  // public getBankNote(location: number): number | null | undefined {\n  //   return this.bankNotes.get(location);\n  // }\n\n  // public setBankNote(location: number, value: number | null): void {\n  //   this.bankNotes.set(location, value);\n  // }\n\n  // Stack position methods\n  public getStackPosition(location: number): number | undefined {\n    return this.stackPositions.get(location);\n  }\n\n  public setStackPosition(location: number, value: number): void {\n    this.stackPositions.set(location, value);\n  }\n\n  public tryAddStackPosition(location: number, value: number): boolean {\n    if (this.stackPositions.has(location)) {\n      return false;\n    }\n    this.stackPositions.set(location, value);\n    return true;\n  }\n} ","/**\r\n * Provides low-level ROM data reading functionality\r\n * Converted from GaiaLib/Rom/Extraction/RomDataReader.cs\r\n */\r\nexport class RomDataReader {\r\n  public romData: Uint8Array;\r\n  public position: number;\r\n  public offset?: number;\r\n\r\n  constructor(romData: Uint8Array, offset?: number) {\r\n    if (!romData) {\r\n      throw new Error('romData cannot be null');\r\n    }\r\n    this.romData = romData;\r\n    this.position = 0;\r\n    this.offset = offset;\r\n  }\r\n\r\n  public readByte(): number {\r\n    return this.romData[this.position++];\r\n  }\r\n\r\n  public readSByte(): number {\r\n    const value = this.readByte();\r\n    return value > 127 ? value - 256 : value;\r\n  }\r\n\r\n  public readUShort(): number {\r\n    return this.readByte() | (this.readByte() << 8);\r\n  }\r\n\r\n  public readShort(): number {\r\n    const value = this.readUShort();\r\n    return value > 32767 ? value - 65536 : value;\r\n  }\r\n\r\n  public readAddress(): number {\r\n    return this.readByte() | (this.readByte() << 8) | (this.readByte() << 16);\r\n  }\r\n\r\n  public readInt(): number {\r\n    return this.readByte() | (this.readByte() << 8) | (this.readByte() << 16) | (this.readByte() << 24);\r\n  }\r\n\r\n  public peekByte(): number {\r\n    return this.romData[this.position];\r\n  }\r\n\r\n  public peekShort(): number {\r\n    return this.romData[this.position] | (this.romData[this.position + 1] << 8);\r\n  }\r\n\r\n  public peekAddress(): number {\r\n    return this.romData[this.position]\r\n      | (this.romData[this.position + 1] << 8)\r\n      | (this.romData[this.position + 2] << 16);\r\n  }\r\n} ","/**\r\n * ROM processing constants\r\n * Converted from GaiaLib/Types/RomProcessingConstants.cs\r\n */\r\nexport class RomProcessingConstants {\r\n  // Core constants\r\n  public static readonly PAGE_SIZE = 0x8000;\r\n  public static readonly SNES_HEADER_SIZE = 0x50;\r\n\r\n  // Dictionary constants\r\n  public static readonly DICTIONARIES = [\"dictionary_01EBA8\", \"dictionary_01F54D\"];\r\n  public static readonly DICT_COMMANDS = [0xD6, 0xD7];\r\n  public static readonly END_CHARS = [0xC0, 0xCA, 0xD1];\r\n\r\n  // Character arrays for parsing\r\n  public static readonly WHITESPACE = [' ', '\\t'];\r\n  public static readonly OPERATORS = ['-', '+'];\r\n  public static readonly COMMA_SPACE = [',', ' ', '\\t'];\r\n  public static readonly ADDRESS_SPACE = ['@', '&', '^', '#', '$', '%', '*', '!'];\r\n  public static readonly SYMBOL_SPACE = [',', ' ', '\\t', '<', '>', '(', ')', ':', '[', ']', '{', '}', '`', '~', '|'];\r\n  public static readonly LABEL_SPACE = ['[', '{', '#', '`', '~', '|', ':', '&', '^', '*'];\r\n  public static readonly OBJECT_SPACE = ['<', '['];\r\n  public static readonly COP_SPLIT_CHARS = [' ', '\\t', ',', '(', ')', '[', ']', '$', '#'];\r\n  public static readonly OVERRIDE_CHARS = ['!', '+', '-'];\r\n\r\n  // Pre-compiled regular expressions for parsing\r\n  public static readonly WHITESPACE_REGEX = /[ \\t]/;\r\n  public static readonly COMMA_SPACE_REGEX = /[, \\t]/;\r\n  public static readonly SYMBOL_SPACE_REGEX = /[, \\t<>()\\:\\[\\]{}`~|]/;\r\n  public static readonly LABEL_SPACE_REGEX = /[\\[{#`~|:]/;\r\n  public static readonly OBJECT_SPACE_REGEX = /[<\\[]/;\r\n  public static readonly ADDRESS_SPACE_REGEX = /[@&^#$%*!]/;\r\n  public static readonly COP_SPLIT_REGEX = /[ \\t,()[\\]$#]/;\r\n  \r\n  // Trim patterns (for start/end of string)\r\n  public static readonly COMMA_SPACE_TRIM_REGEX = /^[, \\t]+|[, \\t]+$/g;\r\n\r\n  \r\n  // Platform detection that works in both Node.js and web environments\r\n  public static readonly IS_WINDOWS = (() => {\r\n    // Check if we're in Node.js environment\r\n    if (typeof process !== 'undefined' && process.platform) {\r\n      return process.platform === 'win32';\r\n    }\r\n    // In web environment, check user agent as fallback\r\n    // if (typeof navigator !== 'undefined' && navigator.userAgent) {\r\n    //   return navigator.userAgent.includes('Windows');\r\n    // }\r\n    // Default to Unix-style line endings if we can't determine\r\n    return false;\r\n  })();\r\n\r\n  public static readonly NEWLINE = RomProcessingConstants.IS_WINDOWS ? '\\r\\n' : '\\n';\r\n\r\n  public static stripMarkers(name: string): { raw: string, name: string, isSoft: boolean, isRaw: boolean } {\r\n    let isSoft = false;\r\n    let isRaw = false;\r\n    let stripped = name;\r\n\r\n    if(stripped[0] === '~') {\r\n      isSoft = true;\r\n      stripped = stripped.substring(1);\r\n    }\r\n    \r\n    if(stripped[stripped.length - 1] === '!') {\r\n      isRaw = true;\r\n      stripped = stripped.substring(0, stripped.length - 1);\r\n    }\r\n\r\n    return { raw: name, name: stripped, isSoft, isRaw };\r\n  }\r\n\r\n  /**\r\n   * Gets the size of an object for processing purposes\r\n   * @param obj The object to get the size for\r\n   * @returns Size in bytes\r\n   * @throws Error when unable to determine size\r\n   */\r\n  public static getSize(obj: unknown): number {\r\n    if(obj === undefined || obj === null) return 0;\r\n    switch(typeof obj) {\r\n      case 'object':\r\n        if(Array.isArray(obj)) {\r\n          return obj.reduce((acc, x) => acc + RomProcessingConstants.getSize(x), 0);\r\n        }\r\n        if ('size' in obj) return obj.size as number;\r\n        if ('length' in obj) return obj.length as number;\r\n        if ('_tag' in obj) {\r\n          switch ((obj as { _tag: string })._tag) {\r\n            case 'Byte':\r\n              return 1;\r\n            case 'Word':\r\n              return 2;\r\n          }\r\n        }\r\n        break;\r\n\r\n      case 'number':\r\n        // Determine size based on value range\r\n        if (obj <= 0xFF) return 1;\r\n        if (obj <= 0xFFFF) return 2;\r\n        if (obj <= 0xFFFFFF) return 3;\r\n        return 4;\r\n\r\n      case 'string':\r\n        let str = obj as string;\r\n        if(!str.length) return 0;\r\n\r\n        switch (str[0]) {\r\n          case '@':\r\n          case '%':\r\n          case '!':\r\n            return 3;\r\n          case '*':\r\n          case '&':\r\n            return 2;\r\n          case '^':\r\n            return 1;\r\n        }\r\n\r\n        switch (str.toLowerCase()) {\r\n          case \"byte\":\r\n            return 1;\r\n          case \"word\":\r\n          case \"offset\":\r\n            return 2;\r\n          case \"address\":\r\n          case \"long\":\r\n            return 3;\r\n        }\r\n        \r\n        return obj.length;\r\n    }\r\n\r\n    return 0;\r\n  }\r\n}\r\n\r\n/**\r\n * BlockReader specific constants\r\n */\r\nexport class BlockReaderConstants {\r\n  public static readonly REF_SEARCH_MAX_RANGE = 0x380;\r\n  public static readonly BANK_MASK_CHECK = 0x40;\r\n  public static readonly BYTE_DELIMITER_THRESHOLD = 0x100;\r\n  public static readonly BANK_HIGH_MEMORY_1 = 0x7E;\r\n  public static readonly BANK_HIGH_MEMORY_2 = 0x7F;\r\n  public static readonly POINTER_CHARACTERS = ['&', '@', '%', '!'];\r\n  public static readonly BINARY_TYPE = \"Binary\";\r\n  public static readonly CODE_TYPE = \"Code\";\r\n  \r\n  // Format strings\r\n  public static readonly MARKER_FORMAT = \"+M\";\r\n} ","import { RomProcessingConstants } from './constants';\r\n\r\n\r\n/**\r\n * Address type classifications\r\n * Converted from GaiaLib/Enum/AddressType.cs\r\n */\r\nexport enum AddressType {\r\n  Unknown = 'Unknown',\r\n  Bank = 'Bank',\r\n  Offset = 'Offset',\r\n  Address = 'Address',\r\n  WBank = 'WBank',\r\n  Relative = 'Relative',\r\n  WRelative = 'WRelative',\r\n  Location = 'Location',\r\n  OddLocation = 'OddLocation'\r\n}\r\n\r\n/**\r\n * Address space types\r\n * Converted from GaiaLib/Types/Address.cs\r\n */\r\nexport enum AddressSpace {\r\n  None = 'None',\r\n  ROM = 'ROM',\r\n  WRAM = 'WRAM',\r\n  SRAM = 'SRAM',\r\n  System = 'System'\r\n}\r\n\r\nexport enum MemoryMapMode {\r\n  Lo = 'Lo',\r\n  Hi = 'Hi',\r\n  ExHi = 'ExHi'\r\n}\r\n\r\nexport enum CpuMode {\r\n  Slow = 'Slow',\r\n  Fast = 'Fast'\r\n}\r\n\r\n/**\r\n * SNES address structure\r\n * Converted from GaiaLib/Types/Address.cs\r\n */\r\nexport class Address {\r\n  public offset: number;\r\n  public bank: number;\r\n  public mode: MemoryMapMode;\r\n  public isShort: boolean;\r\n  \r\n  public static readonly UPPER_BANK = 0x8000;\r\n  public static readonly DATA_BANK_FLAG = 0x40;\r\n  public static readonly FAST_BANK_FLAG = 0x80;\r\n\r\n  constructor(bank: number, offset: number, mode: MemoryMapMode, isShort: boolean = false) {\r\n    this.bank = bank & 0xFF;\r\n    this.offset = offset & 0xFFFF;\r\n    this.mode = mode;\r\n    this.isShort = isShort;\r\n  }\r\n\r\n  public get isROM(): boolean {\r\n    if(this.bank === 0x7E || this.bank === 0x7F) return false;\r\n    if(this.offset >= Address.UPPER_BANK) return true;\r\n    if(!this.isCodeBank) {\r\n      if(this.mode === MemoryMapMode.Lo && this.bank >= 0x70 && this.bank <= 0x7D) return false;\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  public get isWram(): boolean {\r\n    return this.bank === 0x7E || this.bank === 0x7F;\r\n  }\r\n\r\n  public get isCodeBank(): boolean {\r\n    return (this.bank & Address.DATA_BANK_FLAG) === 0;\r\n  }\r\n\r\n  // public get space(): AddressSpace {\r\n    \r\n  //   if (this.bank === 0x7E || this.bank === 0x7F) return AddressSpace.WRAM;\r\n  //   if (this.offset >= RomProcessingConstants.PAGE_SIZE) return AddressSpace.ROM;\r\n\r\n  //   // Check if bank is in lower half (bank & 0x40 == 0)\r\n  //   if (this.isCodeBank) {\r\n  //     // Memory map for lower banks\r\n  //     if (this.offset >= 0x6000 && (this.bank & 0x20) !== 0) {\r\n  //       return AddressSpace.SRAM;\r\n  //     }\r\n  //     if (this.offset < 0x2000) {\r\n  //       return AddressSpace.WRAM;\r\n  //     } else if (this.offset < 0x2100) {\r\n  //       return AddressSpace.None;\r\n  //     } else if (this.offset < 0x2200) {\r\n  //       return AddressSpace.System;\r\n  //     } else if (this.offset < 0x3000) {\r\n  //       return AddressSpace.None;\r\n  //     } else if (this.offset < 0x4100) {\r\n  //       return AddressSpace.System;\r\n  //     } else if (this.offset < 0x4200) {\r\n  //       return AddressSpace.None;\r\n  //     } else if (this.offset < 0x4500) {\r\n  //       return AddressSpace.System;\r\n  //     } else {\r\n  //       return AddressSpace.None;\r\n  //     }\r\n  //   }\r\n\r\n\r\n  //   return AddressSpace.ROM;\r\n  // }\r\n\r\n  public toLocation(): number {\r\n    if(this.mode === MemoryMapMode.Lo) return ((this.bank & 0x3F) << 15) | (this.offset & 0x7FFF);\r\n    if(this.mode === MemoryMapMode.Hi || (this.bank & Address.FAST_BANK_FLAG)) return ((this.bank & 0x3F) << 16) | (this.offset & 0xFFFF);\r\n    return (this.bank === 0x3E) ? (this.offset + 0x13D0000) : (this.bank === 0x3F) ? (this.offset + 0x13E0000) \r\n      : ((((this.bank & 0x3F) << 16) | (this.offset & 0xFFFF)) + 0x1000000);\r\n  }\r\n\r\n  public static fromLocation(value: number, mode: MemoryMapMode, cpuMode: CpuMode): Address {\r\n    let bankFlag = cpuMode === CpuMode.Fast ? Address.FAST_BANK_FLAG : 0;\r\n    if(mode === MemoryMapMode.Lo) {\r\n      return new Address((value >> 15) & 0x7F | bankFlag, (value & 0x7FFF) | 0x8000, mode);\r\n    }\r\n    if(mode === MemoryMapMode.Hi) {\r\n      if((value & RomProcessingConstants.PAGE_SIZE) === 0) bankFlag = 0xC0\r\n      return new Address((value >> 16) & 0x7F | bankFlag, value & 0xFFFF, mode);\r\n    }\r\n    ///TODO: Handle ExHi mode\r\n    if(value & Address.FAST_BANK_FLAG) return new Address((value >> 16) & 0xFF, value & 0xFFFF, mode);\r\n    if(value >= 0x13D0000 && value < 0x13E0000) return new Address(0x3E, value - 0x13D0000, mode);\r\n    if(value >= 0x13E0000 && value < 0x13F0000) return new Address(0x3F, value - 0x13E0000, mode);\r\n    return new Address((value >> 16) & 0x7F, value & 0xFFFF, mode);\r\n  }\r\n\r\n  public static resolveBank(value: number, mode: MemoryMapMode): number {\r\n    if(mode === MemoryMapMode.Lo) return (value >> 15) & 0xFF;\r\n    if(mode === MemoryMapMode.Hi || (value & Address.FAST_BANK_FLAG)) return (value >> 16) & 0xFF;\r\n    if(value >= 0x13D0000 && value < 0x13E0000) return 0x3E;\r\n    if(value >= 0x13E0000 && value < 0x13F0000) return 0x3F;\r\n    return (value >> 16) & 0x7F;  \r\n  }\r\n\r\n  public toInt(): number {\r\n    return (this.bank << 16) | this.offset;\r\n  }\r\n\r\n  public toOffsetString(): string {\r\n    return this.offset.toString(16).toUpperCase().padStart(4, '0');\r\n  }\r\n\r\n  public toString(): string {\r\n    return this.toInt().toString(16).toUpperCase().padStart(6, '0');\r\n  }\r\n\r\n  public static typeFromCode(code: string): AddressType {\r\n    switch (code) {\r\n      case '^':\r\n        return AddressType.Bank;\r\n      case '&':\r\n        return AddressType.Offset;\r\n      case '@':\r\n        return AddressType.Address;\r\n      case '*':\r\n        return AddressType.WBank;\r\n      case '%':\r\n        return AddressType.Location;\r\n      case '!':\r\n        return AddressType.OddLocation;\r\n      default:\r\n        return AddressType.Unknown;\r\n    }\r\n  }\r\n\r\n  public static codeFromType(type: AddressType): string | null {\r\n    switch (type) {\r\n      case AddressType.Bank:\r\n        return '^';\r\n      case AddressType.Offset:\r\n        return '&';\r\n      case AddressType.Address:\r\n        return '@';\r\n      case AddressType.WBank:\r\n        return '*';\r\n      case AddressType.Location:\r\n        return '%';\r\n      case AddressType.OddLocation:\r\n        return '!';\r\n      default:\r\n        return null;\r\n    }\r\n  }\r\n} ","/**\r\n * Member type definitions for data structures\r\n * Converted from GaiaLib/Enum/MemberType.cs\r\n */\r\nexport enum MemberType {\r\n  Byte = 'Byte',\r\n  Word = 'Word',\r\n  Offset = 'Offset',\r\n  Address = 'Address',\r\n  Binary = 'Binary',\r\n  Code = 'Code',\r\n  Branch = 'Branch',\r\n  Location = 'Location',\r\n  OddLocation = 'OddLocation'\r\n} ","/**\r\n * Processor register type definitions\r\n * Converted from GaiaLib/Enum/RegisterType.cs\r\n */\r\nexport enum RegisterType {\r\n  M = 'M',\r\n  X = 'X',\r\n  B = 'B'\r\n}\r\n\r\n/**\r\n * Status flags for 65816 processor\r\n * Converted from GaiaLib/Enum/StatusFlags.cs\r\n * \r\n * Bit pattern: [ n v m x d i z c ]\r\n * n = Negative\r\n * v = Overflow\r\n * m = Accumulator Mode\r\n * x = Index Mode\r\n * d = Decimal Mode\r\n * i = IRQ Disable\r\n * z = Zero\r\n * c = Carry\r\n */\r\nexport enum StatusFlags {\r\n  /**\r\n   * Clear before starting addition or subtraction.\r\n   * Arithmetic overflow:\r\n   * [addition - carry out of high bit:]\r\n   * 0 = no carry\r\n   * 1 = carry\r\n   * [subtraction - borrow required to subtract:]\r\n   * 0 = borrow required\r\n   * 1 = no borrow required\r\n   * [Logic:]\r\n   * receives bit shifted or rotated out;\r\n   * source of bit rotated in\r\n   */\r\n  Carry = 0x01,\r\n  /**\r\n   * Indicates zero or non-zero result:\r\n   * 0 = non-zero result\r\n   * 1 = zero result\r\n   */\r\n  Zero = 0x02,\r\n  /**\r\n   * Enables or disables processor's IRQ interrupt line:\r\n   * Set to disable interrupts by masking the IRQ line\r\n   * Clear to enable IRQ interrupts\r\n   */\r\n  IrqDisable = 0x04,\r\n  /**\r\n   * Determines mode for add/subtract (not increment/decrement, though):\r\n   * Set to force decimal operation (BCD)\r\n   * Clear to return to binary operation\r\n   */\r\n  DecimalMode = 0x08,\r\n  IndexMode = 0x10,\r\n  AccumulatorMode = 0x20,\r\n  /**\r\n   * Clear to reverse \"set-overflow\" hardware input.\r\n   * Indicates invalid carry into high bit of arithmetic\r\n   * result (two's-complement overflow):\r\n   * 0 = two's-complement result ok\r\n   * 1 = error if two's-complement arithmetic\r\n   */\r\n  Overflow = 0x40,\r\n  /**\r\n   * Reflects most significant bit of result\r\n   * (the sign of a two's-complement binary number):\r\n   * 0 = high bit clear (positive result)\r\n   * 1 = high bit set (negative result)\r\n   */\r\n  Negative = 0x80\r\n} ","/**\r\n * Binary resource type definitions\r\n * Converted from GaiaLib/Enum/BinType.cs\r\n */\r\nexport enum BinType {\r\n  Bitmap = 'Bitmap',\r\n  Tilemap = 'Tilemap',\r\n  Tileset = 'Tileset',\r\n  Palette = 'Palette',\r\n  Sound = 'Sound',\r\n  Music = 'Music',\r\n  //Unknown = 'Unknown',\r\n  Meta17 = 'Meta17',\r\n  Spritemap = 'Spritemap',\r\n  Assembly = 'Assembly',\r\n  Patch = 'Patch',\r\n  Transform = 'Transform',\r\n  Binary = 'Binary'\r\n} ","/**\r\n * Transform type definitions\r\n * Converted from GaiaLib/Enum/XformType.cs\r\n */\r\nexport enum XformType {\r\n  Lookup = 'Lookup',\r\n  Replace = 'Replace'\r\n}\r\n\r\n/**\r\n * Transform definition\r\n * Converted from GaiaLib/Types/XformDef.cs\r\n */\r\nexport interface XformDef {\r\n  type: XformType;\r\n  key?: string;\r\n  value?: string;\r\n  keyIx?: number;\r\n  valueIx?: number;\r\n} ","\r\nexport class OpCode {\r\n    public code: number;\r\n    public mnem: string;\r\n    public mode: string;\r\n\r\n    constructor(code: number, mnem: string, mode: string) {\r\n        this.code = code;\r\n        this.mnem = mnem;\r\n        this.mode = mode;\r\n    }\r\n}\r\n","import { ChunkFile } from \"./files\";\r\nimport { CopDef } from \"../database/cop\";\r\nimport { OpCode } from \"../database/opcode\";\r\n\r\n\r\n/**\r\n * Represents a single assembly operation/instruction\r\n */\r\nexport class Op extends OpCode {\r\n  public location: number;\r\n  public operands: unknown[];\r\n  public size: number;\r\n  public copDef?: CopDef;\r\n\r\n  constructor(\r\n    code: OpCode,\r\n    location: number = 0,\r\n    operands: unknown[] = [],\r\n    size: number = 1\r\n  ) {\r\n    super(code.code, code.mnem, code.mode);\r\n    this.code = code.code;\r\n    this.location = location;\r\n    this.operands = operands;\r\n    this.size = size;\r\n  }\r\n}\r\n\r\n/**\r\n * Represents a block of assembly code or data\r\n */\r\nexport class AsmBlock {\r\n  public label?: string;\r\n  public location: number;\r\n  public size: number;\r\n  //public isString: boolean;\r\n  public objList: any[];\r\n  public structName?: string;\r\n  public includes?: Set<{block: ChunkFile, part: AsmBlock}>;\r\n  public file: ChunkFile;\r\n\r\n  constructor(\r\n    file: ChunkFile,\r\n    location: number = 0,\r\n    size: number = 0,\r\n    label?: string,\r\n    structName?: string,\r\n    //isString: boolean = false,\r\n    //bank?: number\r\n  ) {\r\n    this.file = file;\r\n    this.label = label;\r\n    this.location = location;\r\n    this.size = size;\r\n    //this.isString = isString;\r\n    this.objList = [];\r\n    this.structName = structName;\r\n    this.includes = new Set();\r\n  }\r\n} \r\n\r\n/**\r\n * Database part utilities\r\n */\r\nexport class AsmBlockUtils {\r\n  /**\r\n   * Check if a location is inside this part\r\n   */\r\n  static isInside(part: AsmBlock, location: number): boolean {\r\n    return location >= part.location && location < (part.location + part.size);\r\n  }\r\n\r\n  /**\r\n   * Check if a location is outside this part\r\n   */\r\n  static isOutside(part: AsmBlock, location: number): boolean {\r\n    return location < part.location || location >= (part.location + part.size);\r\n  }\r\n} ","/**\n * Bit stream for reading/writing binary data at bit level\n * Converted from GaiaLib/Types/BitStream.cs\n */\nexport class BitStream {\n  private static readonly NIBBLE_MASK = 0xF;\n  private static readonly NIBBLE_PERFECT_POSITION = 0x08;\n\n  private data: Uint8Array;\n  private position: number;\n  private bitFlag: number = 0x80;\n  private writeSample: number = 0;\n\n  constructor(data: Uint8Array, position: number = 0) {\n    this.data = data;\n    this.position = position;\n  }\n\n  public get dataArray(): Uint8Array {\n    return this.data;\n  }\n\n  public get currentPosition(): number {\n    return this.position;\n  }\n\n  public set currentPosition(value: number) {\n    this.position = value;\n  }\n\n  /**\n   * Read a byte from the stream\n   * @returns The byte read, or -1 if the end of the data has been reached\n   */\n  public readByte(): number {\n    // If we've reached the end of the data, return -1\n    if (this.position >= this.data.length) {\n      return -1;\n    }\n\n    // Read the current byte, and advance the position\n    let sample = this.data[this.position++];\n\n    // If the bit flag is not the most significant bit, we need to include the next byte\n    if (this.bitFlag !== 0x80) {\n      // Include the next byte in the sample\n      sample = (sample << 8) | this.data[this.position];\n\n      // Shift the (temporary) bit flag to the right until it is 0\n      for (let x = this.bitFlag; x > 0; x >>= 1) {\n        // Shift sample for each iteration so it will line up with the byte boundary\n        sample >>= 1;\n      }\n    }\n\n    // Return the sample\n    return sample & 0xFF;\n  }\n\n  /**\n   * Read a ushort from the stream (ignores the current bit flag)\n   * @returns The short read, or -1 if the end of the data has been reached\n   */\n  public readShort(): number {\n    // If end of stream (position would overlap data.length), return -1\n    if (this.position + 1 >= this.data.length) {\n      return -1;\n    }\n\n    // Read sample using two bytes to form a ushort. Advance position by 2\n    const value = this.data[this.position++] | (this.data[this.position++] << 8);\n\n    // Return the value\n    return value;\n  }\n\n  /**\n   * Read a bit from the stream\n   * @returns True if the current bit at bitFlag is set, false otherwise\n   */\n  public readBit(): boolean {\n    // If we've reached the end of the data, return false\n    if (this.position >= this.data.length) {\n      return false;\n    }\n\n    // Read the current bit and test it against current bit flag\n    const sample = this.data[this.position] & this.bitFlag;\n\n    // Shift the bit flag to the right\n    this.bitFlag >>= 1;\n\n    // If the bit flag is 0, we need to move to the next byte\n    if (this.bitFlag === 0) {\n      // Reset the bit flag to the most significant bit\n      this.bitFlag = 0x80;\n      // Advance the position to the next byte\n      this.position++;\n    }\n\n    // Return true if the bit is set, false otherwise\n    return sample !== 0;\n  }\n\n  /**\n   * Read a nibble from the stream\n   * @returns The nibble read, or -1 if the end of the data has been reached\n   */\n  public readNibble(): number {\n    // If we've reached the end of the data, return -1\n    if (this.position >= this.data.length) {\n      return -1;\n    }\n\n    // Read the current (unshifted) byte sample\n    let sample = this.data[this.position];\n\n    if (this.bitFlag === BitStream.NIBBLE_PERFECT_POSITION) {\n      // Reset the bit flag to the most significant bit\n      this.bitFlag = 0x80;\n      // Advance the position to the next byte\n      this.position++;\n    } else {\n      // Initialize the bit position to -4 (will be incremented as we shift the bit flag to the right)\n      let bitPos = -4;\n\n      // Shift the bit flag to the right until it is 0\n      while (this.bitFlag !== 0) {\n        // Shift the bit flag to the right\n        this.bitFlag >>= 1;\n        // Increment the bit position\n        bitPos++;\n      }\n\n      // If the bit position is less than 0, we need to include the next byte\n      if (bitPos < 0) {\n        // Include the next byte in the sample, and advance the position\n        sample = (sample << 8) | this.data[++this.position];\n\n        // Advance the bit position by 8 (will no longer be less than 0)\n        bitPos += 8;\n      }\n\n      // Shift the sample to the right by the bit position\n      sample >>= bitPos;\n\n      // Set the bit flag to the new bit position\n      this.bitFlag = 1 << (bitPos - 1);\n    }\n\n    // Return the nibble\n    return sample & BitStream.NIBBLE_MASK;\n  }\n\n  /**\n   * Write a bit to the stream\n   * @param set True if the current bit should be set, false otherwise\n   */\n  public writeBit(set: boolean): void {\n    // If the bit should be set, set the bit in the write sample\n    if (set) {\n      this.writeSample |= this.bitFlag;\n    }\n\n    // Shift the bit flag to the right\n    this.bitFlag >>= 1;\n\n    // If the bit flag is 0, we need to move to the next byte\n    if (this.bitFlag === 0) {\n      // Reset the bit flag to the most significant bit\n      this.bitFlag = 0x80;\n      // Write the sample to the data stream\n      this.data[this.position++] = this.writeSample;\n      // Reset the write sample\n      this.writeSample = 0;\n    }\n  }\n\n  /**\n   * Write a byte to the stream\n   * @param value The byte to write\n   */\n  public writeByte(value: number): void {\n    // If the bit flag is the most significant bit, we can write the byte directly\n    if (this.bitFlag === 0x80) {\n      this.data[this.position++] = value;\n    } else {\n      // Shift the value to the left until it is aligned with the bit flag\n      for (let x = 1; x <= this.bitFlag; x <<= 1) {\n        value <<= 1;\n      }\n\n      // Write the value to the data stream\n      this.data[this.position++] = (this.writeSample | (value >> 8)) & 0xFF;\n\n      // Update the write sample\n      this.writeSample = value & 0xFF;\n    }\n  }\n\n  /**\n   * Write a nibble to the stream\n   * @param value The nibble to write\n   */\n  public writeNibble(value: number): void {\n    value &= BitStream.NIBBLE_MASK;\n\n    if (this.bitFlag >= 0x10) {\n      let shift = 0;\n      switch (this.bitFlag) {\n        case 0x80: shift = 4; break;\n        case 0x40: shift = 3; break;\n        case 0x20: shift = 2; break;\n        case 0x10: shift = 1; break;\n      }\n      this.writeSample |= (value << shift);\n      this.bitFlag >>= 4;\n    } else {\n      let shift = 0;\n      switch (this.bitFlag) {\n        case 0x8: shift = 0; break;\n        case 0x4: shift = 1; break;\n        case 0x2: shift = 2; break;\n        case 0x1: shift = 3; break;\n      }\n      this.data[this.position++] = (this.writeSample | (value >> shift));\n      this.writeSample = (value << (8 - shift));\n      this.bitFlag <<= 4;\n    }\n  }\n\n  public flush(): void {\n    if (this.bitFlag !== 0x80) {\n      this.data[this.position++] = this.writeSample;\n    }\n  }\n} ","import type { ICompressionProvider } from './compression';\r\n\r\n/**\r\n * Registry for compression providers\r\n * Allows registration of compression implementations by string ID\r\n */\r\nexport class CompressionRegistry {\r\n  private static providers = new Map<string, () => ICompressionProvider>();\r\n\r\n  /**\r\n   * Register a compression provider\r\n   * @param id String identifier for the compression type\r\n   * @param factory Factory function that creates the compression provider\r\n   */\r\n  public static register(id: string, factory: () => ICompressionProvider): void {\r\n    this.providers.set(id, factory);\r\n  }\r\n\r\n  /**\r\n   * Get a compression provider by ID\r\n   * @param id String identifier for the compression type\r\n   * @returns Compression provider instance\r\n   */\r\n  public static get(id: string): ICompressionProvider {\r\n    const factory = this.providers.get(id);\r\n    if (!factory) {\r\n      throw new Error(`No compression provider registered for type: ${id}`);\r\n    }\r\n    return factory();\r\n  }\r\n\r\n  /**\r\n   * Check if a compression provider is registered\r\n   * @param id String identifier for the compression type\r\n   * @returns True if provider is registered\r\n   */\r\n  public static has(id: string): boolean {\r\n    return this.providers.has(id);\r\n  }\r\n\r\n  /**\r\n   * Get list of registered provider IDs\r\n   * @returns Array of registered provider IDs\r\n   */\r\n  public static getRegisteredIds(): string[] {\r\n    return Array.from(this.providers.keys());\r\n  }\r\n\r\n  /**\r\n   * Clear all registered providers (mainly for testing)\r\n   */\r\n  public static clear(): void {\r\n    this.providers.clear();\r\n  }\r\n}\r\n","import { BinType } from './resources';\r\nimport { AsmBlock, AsmBlockUtils } from './assembly';\r\nimport { DbFile, DbFileType } from '../database/files';\r\nimport { DbBlock } from '../database/blocks';\r\nimport { ICompressionProvider } from './compression';\r\nimport { MemoryMapMode } from './addressing';\r\nimport { ReferenceManager } from '../rom/extraction/references';\r\n\r\n/**\r\n * Chunk file for ROM processing\r\n * Converted from GaiaLib/Types/ChunkFile.cs\r\n */\r\nexport class ChunkFile {\r\n  //id?: string;\r\n  name: string;\r\n  size: number;\r\n  location: number;\r\n  type: DbFileType;\r\n  parts?: AsmBlock[];\r\n  includes?: Set<string>;\r\n  includeLookup?: Record<string, AsmBlock>;\r\n  bank?: number;\r\n  compressed?: boolean;\r\n  upper?: boolean;\r\n  rawData?: Uint8Array | null;\r\n  textData?: string;\r\n  transforms?: { key: string; value: string }[];\r\n  postProcess?: string;\r\n  mnemonics: Record<string, string>;\r\n  group?: string;\r\n  scene?: string;\r\n  base?: number;\r\n  referenceManager?: ReferenceManager;\r\n  isFile: boolean;\r\n  struct?: string;\r\n  sizeHeader?: number;\r\n\r\n  constructor(type: DbFileType, name: string, size: number = 0, location: number = 0) {\r\n    this.type = type;\r\n    this.name = name;\r\n    this.size = size;\r\n    this.location = location;\r\n    this.mnemonics = {};\r\n    this.compressed = type.compressed;\r\n    this.isFile = !type.isBlock;\r\n    this.struct = type.struct ?? undefined;\r\n    this.base = type.base ?? undefined;\r\n    this.upper = type.upper ?? undefined;\r\n  }\r\n  \r\n  public enrichWithRawDataFromDbFile(file: DbFile, rom: Uint8Array, compression: ICompressionProvider | undefined): void {\r\n    this.upper = file.upper ?? this.type.upper ?? this.upper;\r\n    this.size = file.end - file.start;\r\n    this.location = file.start;\r\n    this.base = file.base ?? this.type.base ?? this.base;\r\n    this.group = file.group ?? this.group;\r\n    this.scene = file.scene ?? this.scene;\r\n    this.compressed = file.compressed ?? this.type.compressed ?? this.compressed;\r\n    this.struct = file.struct ?? this.type.struct ?? this.struct;\r\n    this.isFile = true;\r\n\r\n    let start = this.location;\r\n    let header: Uint8Array | null = null;\r\n    const fileType = this.type;\r\n\r\n    if(this.struct && !this.compressed) {\r\n      const newPart = new AsmBlock(this, this.location, this.size, this.name, this.struct);\r\n      this.parts = [newPart];\r\n      return;\r\n    }\r\n\r\n    if(fileType.header) {\r\n      header = new Uint8Array(rom.slice(start, start + fileType.header));\r\n      start += fileType.header;\r\n    }\r\n    let length = this.size;\r\n    let fileData: Uint8Array;\r\n    if (this.compressed === true && compression) {\r\n      const expanded = compression.expand(rom, start, length);\r\n      fileData = combineHeader(expanded, 0, expanded.length, header, fileType.type as BinType);\r\n    } else {\r\n      if (this.compressed !== undefined) {\r\n        start += 2; length -= 2; // skip zero-compression header\r\n      }\r\n      fileData = combineHeader(rom, start, length, header, fileType.type as BinType);\r\n    }\r\n    \r\n    this.rawData = fileData;\r\n    this.size = fileData.length;\r\n  }\r\n  \r\n  public enrichWithAsmBlocksFromDbBlock(block: DbBlock, memoryMode: MemoryMapMode): void {\r\n    // Create assembly ChunkFile\r\n    //const chunkFile = new ChunkFile(fileType, undefined, block.name);\r\n    //chunkFile.id = block.id;\r\n    this.group = block.group;\r\n    this.scene = block.scene;\r\n    this.base = block.base;\r\n    this.isFile = false;\r\n    \r\n    // Enrich with AsmBlock parts\r\n    this.parts = [];\r\n    this.size = 0;\r\n    if(!block.parts?.length) {\r\n      throw new Error(`Block ${block.name} has no parts`);\r\n    }\r\n    this.location = block.parts[0].start;\r\n    this.upper = (this.location & 0x8000) !== 0;\r\n    this.bank = block.movable ? undefined : (memoryMode === MemoryMapMode.Lo ? this.location >> 15 : this.location >> 16);\r\n    this.transforms = block.transforms;\r\n    this.postProcess = block.postProcess;\r\n    \r\n    for (const part of block.parts) {\r\n      const asmBlock = new AsmBlock(\r\n        this,\r\n        part.start,\r\n        part.end - part.start,\r\n        part.name,\r\n        part.type\r\n        //false // isString will be determined during processing\r\n        //part.bank\r\n      );\r\n      this.size += asmBlock.size;\r\n      this.parts.push(asmBlock);\r\n    }\r\n  }\r\n\r\n}\r\n\r\n\r\n\r\nexport function combineHeader(\r\n  data: Uint8Array,\r\n  position: number,\r\n  length: number,\r\n  header: Uint8Array | null,\r\n  type: BinType\r\n): Uint8Array {\r\n  let totalLength = length + (header ? header.length : 0);\r\n  if (type === BinType.Palette && length < 0x200) {\r\n    totalLength += (0x200 - length);\r\n  }\r\n  const result = new Uint8Array(totalLength);\r\n  let offset = 0;\r\n  if (header) { result.set(header, offset); offset += header.length; }\r\n  result.set(data.slice(position, position + length), offset);\r\n  offset += length;\r\n  if (type === BinType.Palette && length < 0x200) {\r\n    result.fill(0, offset, offset + (0x200 - length));\r\n  }\r\n  return result;\r\n}\r\n\r\n\r\n\r\n/**\r\n * Chunk file utilities\r\n */\r\nexport class ChunkFileUtils {\r\n  /**\r\n   * Rebase blocks to a new location\r\n   */\r\n  static rebase(chunkFile: ChunkFile, newLocation?: number): void {\r\n    if (newLocation !== undefined) {\r\n      chunkFile.location = newLocation;\r\n    }\r\n\r\n    if (!chunkFile.parts) {\r\n      return;\r\n    }\r\n\r\n    let loc = chunkFile.location;\r\n    for (let x = 0; x < chunkFile.parts.length; x++) {\r\n      const block = chunkFile.parts[x];\r\n      if (x > 0 && !block.label) {\r\n        break;\r\n      }\r\n      block.location = loc;\r\n      loc += block.size || 0;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Calculate the total size of all blocks\r\n   */\r\n  static calculateSize(chunkFile: ChunkFile): number {\r\n    let size = 0;\r\n    if (chunkFile.rawData) {\r\n      size = chunkFile.rawData.length;\r\n      if (chunkFile.type.header === -2 || chunkFile.compressed === false) size += 2;\r\n    } else if(chunkFile.parts) {\r\n      for (let x = 0; x < chunkFile.parts.length; x++) {\r\n        const block = chunkFile.parts[x];\r\n        if (x > 0 && !block.label) break;\r\n        size += block.size || 0;\r\n      }\r\n    }\r\n    \r\n    chunkFile.size = size;\r\n    return size;\r\n  }\r\n\r\n    /**\r\n   * Check if a location is outside this block and return the part (matches C# IsOutside)\r\n   * Returns [isOutside, part] where part is the part containing the location\r\n   */\r\n  static isOutsideWithPart(root: ChunkFile[], block: ChunkFile, location: number): [boolean, ChunkFile | null, AsmBlock | null] {\r\n    const [isInside, part] = this.isInsideWithPart(block, location);\r\n    if (isInside) {\r\n      return [false, block, part];\r\n    }\r\n\r\n    // Find chunk this reference belongs to\r\n    for (const otherBlock of root) {\r\n      if (otherBlock !== block && !otherBlock.struct) {\r\n        const [otherIsInside, otherPart] = this.isInsideWithPart(otherBlock, location);\r\n        if (otherIsInside) {\r\n          return [true, otherBlock, otherPart];\r\n        }\r\n      }\r\n    }\r\n\r\n    return [true, null, null];\r\n  }\r\n\r\n  /**\r\n   * Check if a location is inside this block and return the part (matches C# IsInside)\r\n   * Returns [isInside, part] where part is the part containing the location\r\n   */\r\n  static isInsideWithPart(block: ChunkFile, location: number): [boolean, AsmBlock | null] {\r\n    for (const part of block?.parts || []) {\r\n      if (AsmBlockUtils.isInside(part, location)) {\r\n        return [true, part];\r\n      }\r\n    }\r\n    return [false, null];\r\n  }\r\n\r\n  /**\r\n   * Check if a location is outside this block (shorthand version)\r\n   */\r\n  static isOutside(block: ChunkFile, location: number): boolean {\r\n    return !this.isInside(block, location);\r\n  }\r\n\r\n  /**\r\n   * Check if a location is inside this block (shorthand version)\r\n   */\r\n  static isInside(block: ChunkFile, location: number): boolean {\r\n    for (const part of block?.parts || []) {\r\n      if (AsmBlockUtils.isInside(part, location)) {\r\n        return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Get all included blocks\r\n   */\r\n  static getIncludes(chunkFile: ChunkFile): ChunkFile[] {\r\n    if(!chunkFile.parts) return [];\r\n    const includes: ChunkFile[] = [];\r\n    const seen = new Set<ChunkFile>();\r\n\r\n    for (const part of chunkFile.parts) {\r\n      if (part?.includes) {\r\n        for (const includedPart of part.includes) {\r\n          if (!seen.has(includedPart.block)) {\r\n            includes.push(includedPart.block);\r\n            seen.add(includedPart.block);\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    return includes;\r\n  }\r\n} ","import { AddressType } from './addressing';\r\n\r\n/**\r\n * Location wrapper for additional metadata\r\n * Converted from GaiaLib/Types/LocationWrapper.cs\r\n */\r\nexport class LocationWrapper {\r\n  public location: number;\r\n  public type: AddressType;\r\n\r\n  constructor(location: number, type: AddressType) {\r\n    this.location = location;\r\n    this.type = type;\r\n  }\r\n} ","import type { DbStringType } from '../database/strings';\r\nimport { AsmBlock } from './assembly';\r\n\r\n/**\r\n * String marker for positioning\r\n * Converted from GaiaLib/Types/StringMarker.cs\r\n */\r\nexport interface StringMarker {\r\n  offset: number;\r\n}\r\n\r\n/**\r\n * String wrapper with type and location information\r\n * Converted from GaiaLib/Types/StringWrapper.cs\r\n */\r\nexport interface StringWrapper {\r\n  string: string;\r\n  type: DbStringType;\r\n  marker: number;\r\n  location: number;\r\n  fixedSize: number;\r\n  isRaw: boolean;\r\n}\r\n\r\n/**\r\n * String entry (commented out in original C# code)\r\n * Converted from GaiaLib/Types/StringEntry.cs\r\n */\r\nexport interface StringEntry {\r\n  block: AsmBlock;\r\n  index: number;\r\n  size: number;\r\n  data: Uint8Array;\r\n}\r\n\r\n/**\r\n * String size comparer utility\r\n * Converted from GaiaLib/Types/StringSizeComparer.cs\r\n */\r\nexport class StringSizeComparer {\r\n  /**\r\n   * Compare two strings by length\r\n   */\r\n  static compare(a: string, b: string): number {\r\n    if (a.length < b.length) return -1;\r\n    if (a.length > b.length) return 1;\r\n    return a.localeCompare(b);\r\n  }\r\n  \r\n  /**\r\n   * Compare two StringWrapper objects by string length\r\n   */\r\n  static compareWrappers(a: StringWrapper, b: StringWrapper): number {\r\n    return this.compare(a.string, b.string);\r\n  }\r\n} ","\r\nexport class TableEntry {\r\n  location: number;\r\n  object: unknown;\r\n  name?: string;\r\n\r\n  constructor(location: number, object?: unknown, name?: string) {\r\n    if(typeof location !== 'number') throw new Error('Location is required');\r\n    this.location = location;\r\n    this.object = object;\r\n    this.name = name;\r\n  }\r\n}\r\n","export class TypedNumber {\r\n  value: number;\r\n  size: number;\r\n  isDelimiter?: boolean;\r\n\r\n  constructor(value: number, size: number, isDelimiter?: boolean) {\r\n    this.value = value;\r\n    this.size = size;\r\n    this.isDelimiter = isDelimiter;\r\n  }\r\n}\r\n\r\nexport class Byte extends TypedNumber {\r\n  constructor(value: number, isDelimiter?: boolean) {\r\n    super(value & 0xFF, 1, isDelimiter);\r\n  }\r\n}\r\n\r\nexport class Word extends TypedNumber {\r\n  constructor(value: number, isDelimiter?: boolean) {\r\n    super(value & 0xFFFF, 2, isDelimiter);\r\n  }\r\n}\r\n\r\nexport class Long extends TypedNumber {\r\n  constructor(value: number) {\r\n    super(value & 0xFFFFFF, 3);\r\n  }\r\n}","import { AddressType, Address } from '../../types';\r\nimport { BlockReaderConstants, RomProcessingConstants } from '../../types/constants';\r\nimport type { DbRoot } from '../../database';\r\nimport { ChunkFileUtils } from '../../types/files';\r\nimport type { ChunkFile } from '../../types/files';\r\n\r\n/**\r\n * Manages references, chunks, and markers during ROM analysis\r\n * Converted from GaiaLib/Rom/Extraction/ReferenceManager.cs\r\n */\r\nexport class ReferenceManager {\r\n  public readonly structTable = new Map<number, string>();\r\n  public readonly markerTable = new Map<number, number>();\r\n  public readonly nameTable = new Map<number, string>();\r\n  public readonly fileTable = new Map<number, string>();\r\n  private readonly root: DbRoot;\r\n\r\n  constructor(root: DbRoot) {\r\n    if (!root) {\r\n      throw new Error('root cannot be null');\r\n    }\r\n    this.root = root;\r\n  }\r\n\r\n  // Struct management\r\n  public tryGetStruct(location: number): { found: boolean; chunkType?: string, rawType?: string, isSoft?: boolean, isRaw?: boolean } {\r\n    let chunkType = this.structTable.get(location);\r\n    if(!chunkType) return { found: false };\r\n    const { name, isSoft, isRaw } = RomProcessingConstants.stripMarkers(chunkType);\r\n    return { found: true, chunkType: name, rawType: chunkType, isSoft, isRaw };\r\n  }\r\n\r\n  public tryAddStruct(location: number, chunkType: string): boolean {\r\n    const existingStruct = this.tryGetStruct(location);\r\n    const isSoft = chunkType[0] === '~';\r\n    if (existingStruct.isSoft === false || (existingStruct.found && isSoft)) {\r\n      return false;\r\n    }\r\n\r\n    this.structTable.set(location, chunkType);\r\n    return true;\r\n  }\r\n\r\n  public containsStruct(location: number): boolean {\r\n    return this.structTable.has(location);\r\n  }\r\n\r\n  // Name management\r\n  public tryGetName(location: number): { found: boolean; referenceName?: string; isSoft?: boolean } {\r\n    let referenceName = this.nameTable.get(location);\r\n    const found = referenceName !== undefined;\r\n    let isSoft : boolean | undefined;\r\n    if(referenceName) {\r\n      if(referenceName[0] === '~') {\r\n        isSoft = true;\r\n        referenceName = referenceName.substring(1);\r\n      }\r\n      else isSoft = false;\r\n    }\r\n    return { found, referenceName, isSoft };\r\n  }\r\n\r\n  public tryAddName(location: number, referenceName: string): boolean {\r\n    const existingName = this.tryGetName(location);\r\n    const isSoft = referenceName[0] === '~';\r\n    if (existingName.isSoft === false || (existingName.found && isSoft)) {\r\n      return false;\r\n    }\r\n    this.nameTable.set(location, referenceName);\r\n    return true;\r\n  }\r\n\r\n  // Marker management\r\n  public tryGetMarker(location: number): { found: boolean; offset?: number } {\r\n    const offset = this.markerTable.get(location);\r\n    return { found: offset !== undefined, offset };\r\n  }\r\n\r\n  public setMarker(location: number, offset: number): void {\r\n    this.markerTable.set(location, offset);\r\n  }\r\n\r\n  // Label creation\r\n  public createBranchLabel(location: number): string {\r\n    // const adrs = Address.fromInt(location, this.root.config.memoryMode);\r\n    // const name = `loc_${adrs.toString()}`;\r\n    const name = `loc_${location.toString(16).toUpperCase().padStart(6, '0')}`;\r\n    this.nameTable.set(location, name);\r\n    return name;\r\n  }\r\n\r\n  public createTypeName(type: string, location: number): string {\r\n    let name = type.replaceAll('-', '_').replaceAll(' ', '_').toLowerCase();\r\n    const isSoft = name[0] === '~';\r\n    if(isSoft) name = name.substring(1);\r\n    const isRaw = name[name.length - 1] === '!';\r\n    if(isRaw) name = name.substring(0, name.length - 1);\r\n\r\n    if (name === \"branch\") name = 'loc';\r\n    \r\n    // Handle pointer characters\r\n    while (name.length > 0 && BlockReaderConstants.POINTER_CHARACTERS.includes(name[0])) {\r\n      name = name.substring(1) + '_list';\r\n    }\r\n\r\n    //const adrs = Address.fromInt(location, this.root.config.memoryMode);\r\n    //return `${name}_${adrs.toString()}`;\r\n    return `${name}_${location.toString(16).toUpperCase().padStart(6, '0')}`;\r\n  }\r\n\r\n  public createFallbackName(location: number): string {\r\n    const fileMatch = this.root.files.find(x =>\r\n      x.start <= location && x.end > location\r\n    );\r\n\r\n    if (fileMatch) {\r\n      const offset = location - fileMatch.start;\r\n      return fileMatch.name + (offset !== 0 ? `+${offset.toString(16).toUpperCase()}` : '');\r\n    }\r\n\r\n    // const adrs = Address.fromInt(location, this.root.config.memoryMode);\r\n    // return adrs.toString(); \r\n    return location.toString(16).toUpperCase().padStart(6, '0');\r\n  }\r\n\r\n  /**\r\n   * Finds a reference location by its assigned name.\r\n   */\r\n  public findLocationByName(name: string): number | undefined {\r\n    for (const [loc, refName] of this.nameTable) {\r\n      if (refName === name) {\r\n        return loc;\r\n      }\r\n    }\r\n    return undefined;\r\n  }\r\n\r\n  public resolveName(location: number, type: AddressType, isBranch: boolean, block?: ChunkFile): string {\r\n    const prefix = Address.codeFromType(type);\r\n    let name: string | undefined;\r\n    let label: string | undefined;\r\n\r\n    // Handle rewrites first\r\n    const rewrite = !block?.compressed ? this.root.rewrites[location] : undefined;\r\n    if (rewrite !== undefined) {\r\n      name = this.tryGetName(rewrite).referenceName;\r\n      if (!name) throw new Error(`Rewrite reference not found for location ${location.toString(16).toUpperCase().padStart(6, '0')}`);\r\n      label = this.processClosestMatch(location, rewrite);\r\n      location = rewrite;\r\n    }\r\n\r\n    //name = ChunkFileUtils.isOutside(block, resolvedLocation) && this.fileTable.get(resolvedLocation) || null;\r\n    // if(block) {\r\n    //   name = this.fileTable.get(block.location);\r\n    //   if(name && block.includes?.has(name)) name = undefined;\r\n    // }\r\n    \r\n    const partMatch = block?.parts?.find(y => location >= y.location && location < y.location + y.size);\r\n    const targetBlock = partMatch ? undefined : this.root.blocks.find(x => x.parts.find(y => y.start <= location && y.end > location));\r\n\r\n    // Try to get existing reference\r\n    if (!name) name = (partMatch?.location === location ? partMatch.label : undefined) ?? this.tryGetName(location).referenceName;\r\n\r\n    if (!name) {\r\n      if (isBranch) name = this.createBranchLabel(location);\r\n      else {\r\n        const closestReference = this.findClosestReference(location);\r\n        if (closestReference) { name = closestReference.name; label = closestReference.label; location = closestReference.location; }\r\n        else name = this.createFallbackName(location);\r\n      }\r\n    }\r\n\r\n    if (name[0] === '~') name = name.substring(1);\r\n\r\n    const blockName = targetBlock && targetBlock.name !== block?.name && (targetBlock.location !== location || targetBlock.name !== name) ? targetBlock.name + '.' : '';\r\n    \r\n    return `${prefix || ''}${blockName}${name}${label || ''}`;\r\n  }\r\n\r\n  public findClosestReference(location: number): { name: string; label: string; location: number } | undefined {\r\n    let closestDistance = BlockReaderConstants.REF_SEARCH_MAX_RANGE;\r\n    let name: string | undefined;\r\n    let closestLocation: number | undefined;\r\n\r\n    for (const [entryKey, entryValue] of this.nameTable) {\r\n      if (entryKey > location) continue;\r\n\r\n      const distance = location - entryKey;\r\n      if (distance >= closestDistance) continue;\r\n\r\n      closestDistance = distance;\r\n      name = entryValue;\r\n      closestLocation = entryKey;\r\n\r\n      if (closestDistance === 1) break;\r\n    }\r\n\r\n    return name ? { name, label: this.processClosestMatch(location, closestLocation!), location: closestLocation! } : undefined;\r\n  }\r\n\r\n  // private processRewrite(location: number, rewrite: number): { location: number; label?: string } {\r\n  //   const offset = location - rewrite;\r\n  //   const cmd = offset < 0 ? '-' : '+';\r\n  //   const absOffset = Math.abs(offset);\r\n\r\n  //   let label: string | undefined;\r\n  //   const structType = this.tryGetStruct(rewrite);\r\n  //   const isString = structType.found && this.root.stringTypes[structType.chunkType!];\r\n    \r\n  //   if (isString) {\r\n  //     this.markerTable.set(rewrite, absOffset);\r\n  //     this.markerTable.set(location, absOffset);\r\n  //     label = cmd === '-' ? BlockReaderConstants.NEGATIVE_MARKER_FORMAT : BlockReaderConstants.MARKER_FORMAT;\r\n  //   } else {\r\n  //     const formatString = cmd === '-' ? BlockReaderConstants.NEGATIVE_OFFSET_FORMAT : BlockReaderConstants.OFFSET_FORMAT;\r\n  //     label = formatString.replace('{0:X}', absOffset.toString(16).toUpperCase());\r\n  //   }\r\n\r\n  //   return { location: rewrite, label };\r\n  // }\r\n\r\n  public processClosestMatch( location: number, closestLocation: number ) : string {\r\n    const offset = location - closestLocation;\r\n    if(!offset) return '';\r\n\r\n    let structType = this.tryGetStruct(closestLocation);\r\n\r\n    if(!structType.found) {\r\n      let structDistance = BlockReaderConstants.REF_SEARCH_MAX_RANGE;\r\n      let structName: string | undefined;\r\n      let structLocation: number | undefined;\r\n\r\n      for (const [entryKey, entryValue] of this.structTable) {\r\n        if (entryKey > closestLocation) continue;\r\n\r\n        const distance = closestLocation - entryKey;\r\n        if (distance >= structDistance) continue;\r\n\r\n        structDistance = distance;\r\n        structName = entryValue;\r\n        structLocation = entryKey;\r\n\r\n        if (structDistance === 1) break;\r\n      }\r\n\r\n      if (structName) {\r\n        const { name, isSoft, isRaw } = RomProcessingConstants.stripMarkers(structName);\r\n        structType = { found: true, chunkType: name, isSoft, isRaw };\r\n      }\r\n    }\r\n\r\n    const isString = structType.found && this.root.stringTypes[structType.chunkType!];\r\n\r\n    if (isString) {\r\n      if(offset < 0) throw new Error('String offset is negative, unable to mark');\r\n      this.markerTable.set(closestLocation, offset);\r\n      this.markerTable.set(location, offset);\r\n      return BlockReaderConstants.MARKER_FORMAT;\r\n    } else {\r\n      return `${offset < 0 ? '-' : '+'}${Math.abs(offset).toString(16).toUpperCase()}`;\r\n    }\r\n  }\r\n} ","import { Registers } from '../../assembly';\r\nimport { StatusFlags } from '../../types';\r\nimport type { BlockReader } from './blocks';\r\n\r\n/**\r\n * Handles stack operations for various stack-related instructions\r\n * Converted from GaiaLib/Rom/Extraction/StackOperations.cs\r\n */\r\nexport class StackOperations {\r\n  private readonly _registers: Registers;\r\n  private readonly _blockReader: BlockReader;\r\n\r\n  constructor(registers: Registers, blockReader: BlockReader) {\r\n    this._registers = registers;\r\n    this._blockReader = blockReader;\r\n  }\r\n\r\n  public handleStackOperation(mnemonic: string): void {\r\n    switch (mnemonic) {\r\n      case 'PHD':\r\n        this._registers.stack.push(this._registers.value['direct'] ?? 0);\r\n        break;\r\n        \r\n      case 'PLD':\r\n        this._registers.value['direct'] = this._registers.stack.popUInt16();\r\n        break;\r\n        \r\n      case 'PHK':\r\n        this._registers.stack.push((this._blockReader._romDataReader.position >> 16) | 0x80);\r\n        break;\r\n        \r\n      case 'PHB':\r\n        this._registers.stack.push(this._registers.value['dataBank'] ?? 0x81);\r\n        break;\r\n        \r\n      case 'PLB':\r\n        let bank = this._registers.stack.popByte();\r\n        if (bank === 0) bank = 0x81;\r\n        this._registers.value['dataBank'] = bank;\r\n        break;\r\n        \r\n      case 'PHP':\r\n        this._registers.stack.push(this._registers.value['statusFlags'] ?? 0);\r\n        break;\r\n        \r\n      case 'PLP':\r\n        this._registers.value['statusFlags'] = this._registers.stack.popByte();\r\n        break;\r\n\r\n      case 'PHA':\r\n        this.handleAccumulatorPush();\r\n        break;\r\n\r\n      case 'PLA':\r\n        this.handleAccumulatorPull();\r\n        break;\r\n\r\n      case 'PHX':\r\n        this.handleXIndexPush();\r\n        break;\r\n\r\n      case 'PLX':\r\n        this.handleXIndexPull();\r\n        break;\r\n\r\n      case 'PHY':\r\n        this.handleYIndexPush();\r\n        break;\r\n\r\n      case 'PLY':\r\n        this.handleYIndexPull();\r\n        break;\r\n\r\n      case 'XBA':\r\n        this.handleExchangeBytes();\r\n        break;\r\n\r\n      case 'RTL':\r\n      case 'RTS':\r\n        this._blockReader._referenceManager.tryAddStruct(this._blockReader._romDataReader.position, '~Code');\r\n        break;\r\n    }\r\n  }\r\n\r\n  private handleAccumulatorPush(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.AccumulatorMode) {\r\n      this._registers.stack.push(this._registers.value['accumulator'] ?? 0);\r\n    } else {\r\n      this._registers.stack.pushUInt16(this._registers.value['accumulator'] ?? 0);\r\n    }\r\n  }\r\n\r\n  private handleAccumulatorPull(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.AccumulatorMode) {\r\n      this._registers.value['accumulator'] = ((this._registers.value['accumulator'] ?? 0) & 0xFF00) | this._registers.stack.popByte();\r\n    } else {\r\n      this._registers.value['accumulator'] = this._registers.stack.popUInt16();\r\n    }\r\n  }\r\n\r\n  private handleXIndexPush(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.IndexMode) {\r\n      this._registers.stack.push((this._registers.value['xIndex'] ?? 0) & 0xFF);\r\n    } else {\r\n      this._registers.stack.pushUInt16(this._registers.value['xIndex'] ?? 0);\r\n    }\r\n  }\r\n\r\n  private handleXIndexPull(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.IndexMode) {\r\n      this._registers.value['xIndex'] = ((this._registers.value['xIndex'] ?? 0) & 0xFF00) | this._registers.stack.popByte();\r\n    } else {\r\n      this._registers.value['xIndex'] = this._registers.stack.popUInt16();\r\n    }\r\n  }\r\n\r\n  private handleYIndexPush(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.IndexMode) {\r\n      this._registers.stack.push((this._registers.value['yIndex'] ?? 0) & 0xFF);\r\n    } else {\r\n      this._registers.stack.pushUInt16(this._registers.value['yIndex'] ?? 0);\r\n    }\r\n  }\r\n\r\n  private handleYIndexPull(): void {\r\n    if (this._registers.value['statusFlags'] & StatusFlags.IndexMode) {\r\n      this._registers.value['yIndex'] = ((this._registers.value['yIndex'] ?? 0) & 0xFF00) | this._registers.stack.popByte();\r\n    } else {\r\n      this._registers.value['yIndex'] = this._registers.stack.popUInt16();\r\n    }\r\n  }\r\n\r\n  private handleExchangeBytes(): void {\r\n    const acc = this._registers.value['accumulator'] ?? 0;\r\n    this._registers.value['accumulator'] = ((acc >> 8) | (acc << 8)) & 0xFFFF;\r\n  }\r\n} ","import { RomDataReader } from './reader';\r\nimport {\r\n  Address,\r\n  AddressType,\r\n  AddressSpace,\r\n  LocationWrapper,\r\n  MemberType,\r\n  Byte,\r\n  Word,\r\n} from '../../types';\r\nimport type { CopDef } from '../../database';\r\nimport type { BlockReader } from './blocks';\r\nimport { TransformProcessor } from './transforms';\r\nimport { Registers } from '../../assembly';\r\n\r\n/**\r\n * Handles COP (Coprocessor) command processing\r\n * Converted from GaiaLib/Rom/Extraction/CopCommandProcessor.cs\r\n */\r\nexport class CopCommandProcessor {\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _romDataReader: RomDataReader;\r\n  private readonly _transformProcessor: TransformProcessor;\r\n\r\n  constructor(blockReader: BlockReader, transformProcessor: TransformProcessor) {\r\n    this._blockReader = blockReader;\r\n    this._romDataReader = blockReader._romDataReader;\r\n    this._transformProcessor = transformProcessor;\r\n  }\r\n\r\n  /**\r\n   * Parses a COP command based on its definition\r\n   */\r\n  public parseCopCommand(copDef: CopDef, operands: unknown[], reg: Registers): void {\r\n\r\n    let parts = copDef.parts;\r\n\r\n    if(copDef.conditions) {\r\n      for(const condition of copDef.conditions) {\r\n        let value = this._romDataReader.romData[this._romDataReader.position + condition.offset];\r\n        if(condition.value >= 256) {\r\n          value |= this._romDataReader.romData[this._romDataReader.position + condition.offset + 1] << 8;\r\n        }\r\n        if(condition.logic === '&') {\r\n          if(value & condition.value) {\r\n            parts = condition.parts;\r\n            break;\r\n          }\r\n        } else if(value === condition.value) {\r\n          parts = condition.parts;\r\n          break;\r\n        }\r\n      }\r\n    }\r\n\r\n    for (let partStr of parts) {\r\n      let bank : number | null = null;\r\n\r\n      //Trim the end for bank hints\r\n      const bankHintIx = partStr.indexOf('$')\r\n      if(bankHintIx > 0) {\r\n        if(partStr[bankHintIx + 1] === '$') bank = reg.value['dataBank'] ?? this._blockReader._root.config.defaultBank ?? 0x81;\r\n        else bank = parseInt(partStr.substring(bankHintIx + 1), 16);\r\n        partStr = partStr.substring(0, bankHintIx);\r\n      }\r\n\r\n      // Use the first character to determine the address type (for pointers)\r\n      const addrType = Address.typeFromCode(partStr[0]);\r\n      const isPtr = addrType !== AddressType.Unknown;\r\n      \r\n      // Reference type is the target of a pointer from partStr, or the struct type if not a pointer\r\n      const referenceType = isPtr ? partStr.substring(1) : this._blockReader._currentAsmBlock!.structName ?? 'Binary';\r\n      \r\n      // Member type resolves to the underlying pointer type, or partStr\r\n      const memberTypeName = isPtr ? addrType.toString() : partStr;\r\n\r\n      // Resolve member type name to a MemberType enum\r\n      const memberType = this.tryParseMemberType(memberTypeName);\r\n      if (memberType === null) {\r\n        throw new Error('Cannot use structs in cop def'); // Only basic types are allowed in COP definitions\r\n      }\r\n      \r\n      const xform = this._transformProcessor.getTransform();\r\n      const op = this.readMemberTypeValue(memberType, partStr, isPtr, referenceType, addrType, bank);\r\n      operands.push(this._transformProcessor.applyTransform(xform, op));\r\n\r\n      // If there is a label, ignore reading and use the label instead\r\n      // const label = this._blockReader._root.labels[this._romDataReader.position];\r\n      // if (label) {\r\n      //   this._romDataReader.position += this.getMemberTypeSize(memberType);\r\n      //   operands.push(label);\r\n      // } else {\r\n      //   operands.push(this.readMemberTypeValue(memberType, partStr, isPtr, referenceType, addrType, bank));\r\n      // }\r\n\r\n    }\r\n\r\n    if(copDef.halt) {\r\n      this._blockReader.noteType(this._romDataReader.position, \"~Branch\", true, reg);\r\n    }\r\n  }\r\n\r\n  private tryParseMemberType(memberTypeName: string): MemberType | null {\r\n    // Check if the string matches any MemberType enum value (case-insensitive)\r\n    const upperName = memberTypeName.toUpperCase();\r\n    for (const [key, value] of Object.entries(MemberType)) {\r\n      if (key.toUpperCase() === upperName) {\r\n        return value;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private getMemberTypeSize(memberType: MemberType): number {\r\n    switch (memberType) {\r\n      case MemberType.Byte:\r\n        return 1;\r\n      case MemberType.Word:\r\n      case MemberType.Offset:\r\n        return 2;\r\n      case MemberType.Address:\r\n        return 3;\r\n      default:\r\n        throw new Error('Unsupported COP member type');\r\n    }\r\n  }\r\n\r\n  private readMemberTypeValue(\r\n    memberType: MemberType,\r\n    partStr: string,\r\n    isPtr: boolean,\r\n    referenceType: string,\r\n    addrType: AddressType,\r\n    bank: number | null\r\n  ): unknown {\r\n    switch (memberType) {\r\n      case MemberType.Byte:\r\n        return new Byte(this._romDataReader.readByte());\r\n      case MemberType.Word:\r\n        return new Word(this._romDataReader.readUShort());\r\n      case MemberType.Offset:\r\n        return this.createCopLocation(this._romDataReader.readUShort(), bank, partStr, isPtr, referenceType, addrType);\r\n      case MemberType.Address:\r\n        return this.createCopLocation(this._romDataReader.readUShort(), this._romDataReader.readByte(), partStr, isPtr, referenceType, addrType);\r\n      default:\r\n        throw new Error('Unsupported COP member type');\r\n    }\r\n  }\r\n\r\n  private createCopLocation(\r\n    offset: number, \r\n    bank: number | null, \r\n    partStr: string, \r\n    isPtr: boolean, \r\n    otherStr: string, \r\n    type: AddressType\r\n  ): unknown {\r\n    if (bank === null && offset === 0) {\r\n      return new Word(offset);\r\n    }\r\n\r\n    const resolvedBank = bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode);\r\n\r\n    const addr = new Address(resolvedBank, offset, this._blockReader._root.config.memoryMode, type === AddressType.Offset);\r\n    if (addr.isROM) {\r\n      const location = addr.toLocation();\r\n      if (partStr !== 'Address' && isPtr && !this._blockReader._root.rewrites[location]) {\r\n        this._blockReader.noteType(location, otherStr, true);\r\n      }\r\n\r\n      // When address is unknown, try to use the part string (for Offset or Address)\r\n      if (type === AddressType.Unknown) {\r\n        type = this.tryParseAddressType(partStr) ?? AddressType.Unknown;\r\n      }\r\n\r\n      return new LocationWrapper(location, type);\r\n    }\r\n    return addr;\r\n  }\r\n\r\n  private tryParseAddressType(addressTypeName: string): AddressType | null {\r\n    // Check if the string matches any AddressType enum value (case-insensitive)\r\n    const upperName = addressTypeName.toUpperCase();\r\n    for (const [key, value] of Object.entries(AddressType)) {\r\n      if (key.toUpperCase() === upperName) {\r\n        return value;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n} ","import { Registers } from '../../assembly';\r\nimport {\r\n  AddressType,\r\n  AddressSpace,\r\n  Address,\r\n  LocationWrapper,\r\n  StatusFlags,\r\n  Byte,\r\n  Word,\r\n} from '../../types';\r\nimport { RomDataReader } from './reader';\r\nimport { StackOperations } from './stack';\r\nimport { TransformProcessor } from './transforms';\r\nimport { CopCommandProcessor } from './cop';\r\nimport type { DbRoot, CopDef, OpCode } from '../../database';\r\nimport type { BlockReader } from './blocks';\r\n\r\n/**\r\n * Context information for an operation being processed\r\n * Converted from GaiaLib/Rom/Extraction/AsmReader.cs OperationContext\r\n */\r\nexport class OperationContext {\r\n  public size: number = 0;\r\n  public nextAddress: number = 0;\r\n  public xForm1: string | undefined = undefined;\r\n  public xForm2: string | undefined = undefined;\r\n  public copDef: CopDef | null = null;\r\n}\r\n\r\n/**\r\n * Handles different addressing modes for assembly instructions\r\n * Converted from GaiaLib/Rom/Extraction/AddressingModeHandler.cs\r\n */\r\nexport class AddressingModeHandler {\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _transformProcessor: TransformProcessor;\r\n  private readonly _copProcessor: CopCommandProcessor;\r\n  private readonly _dataReader: RomDataReader;\r\n\r\n  constructor(blockReader: BlockReader, transformProcessor: TransformProcessor) {\r\n    this._blockReader = blockReader;\r\n    this._transformProcessor = transformProcessor;\r\n    this._copProcessor = new CopCommandProcessor(blockReader, transformProcessor);\r\n    this._dataReader = blockReader._romDataReader;\r\n  }\r\n\r\n  public processAddressingMode(code: OpCode, context: OperationContext, reg: Registers): unknown[] {\r\n    const operands: unknown[] = [];\r\n\r\n    switch (code.mode) {\r\n      case 'Stack':\r\n      case 'Implied':\r\n      case 'Accumulator':\r\n        this.handleStackOrImpliedMode(code.mnem, reg);\r\n        break;\r\n\r\n      case 'Immediate':\r\n        this.handleImmediateMode(code.mnem, context.size, operands, reg);\r\n        break;\r\n\r\n      case 'AbsoluteIndexedIndirect':\r\n        this.handleAbsoluteMode(code.mnem, undefined, context.nextAddress, reg.value['dataBank'], operands, reg, true);\r\n        break;\r\n\r\n      case 'AbsoluteIndirect':\r\n      case 'AbsoluteIndirectLong':\r\n      case 'Absolute':\r\n      case 'AbsoluteIndexedX':\r\n      case 'AbsoluteIndexedY':\r\n        this.handleAbsoluteMode(code.mnem, undefined, context.nextAddress, reg.value['dataBank'], operands, reg);\r\n        break;\r\n\r\n      case 'AbsoluteLong':\r\n      case 'AbsoluteLongIndexedX':\r\n        this.handleAbsoluteLongMode(code.mnem, operands, reg);\r\n        break;\r\n\r\n      case 'BlockMove':\r\n        this.handleBlockMoveMode(operands, context);\r\n        break;\r\n\r\n      case 'DirectPage':\r\n      case 'DirectPageIndexedIndirectX':\r\n      case 'DirectPageIndexedX':\r\n      case 'DirectPageIndexedY':\r\n      case 'DirectPageIndirect':\r\n      case 'DirectPageIndirectIndexedY':\r\n      case 'DirectPageIndirectLong':\r\n      case 'DirectPageIndirectLongIndexedY':\r\n        this.handleDirectPageMode(operands);\r\n        break;\r\n\r\n      case 'PCRelative':\r\n        this.handlePCRelativeMode(code.mnem, operands, context.nextAddress, reg, false);\r\n        break;\r\n\r\n      case 'PCRelativeLong':\r\n        this.handlePCRelativeMode(code.mnem, operands, context.nextAddress, reg, true);\r\n        break;\r\n\r\n      case 'StackRelative':\r\n      case 'StackRelativeIndirectIndexedY':\r\n        this.handleStackRelativeMode(operands);\r\n        break;\r\n\r\n      case 'StackInterrupt':\r\n        this.handleStackInterruptMode(code.mnem, operands, context, reg);\r\n        break;\r\n\r\n      default:\r\n        throw new Error(`Unknown addressing mode: ${code}`);\r\n    }\r\n\r\n    return operands;\r\n  }\r\n\r\n  private handleImmediateMode(mnemonic: string, size: number, operands: unknown[], reg: Registers): void {\r\n    const operand = this.readImmediateOperand(size);\r\n    operands.push(operand);\r\n    this.updateRegisterForImmediateInstruction(mnemonic, operand, reg);\r\n  }\r\n\r\n  private readImmediateOperand(size: number) {\r\n    return size === 3\r\n      ? new Word(this._dataReader.readUShort())\r\n      : new Byte(this._dataReader.readByte());\r\n  }\r\n\r\n  private updateRegisterForImmediateInstruction(\r\n    mnemonic: string,\r\n    operand: number | { value: number },\r\n    reg: Registers\r\n  ): void {\r\n    const value = typeof operand === 'number' ? operand : operand.value;\r\n    switch (mnemonic) {\r\n      case 'LDA':\r\n        reg.value['accumulator'] = this.calculateRegisterValue(reg.value['accumulator'], (reg.value['statusFlags'] & StatusFlags.AccumulatorMode) === StatusFlags.AccumulatorMode, value);\r\n        break;\r\n\r\n      case 'LDX':\r\n        reg.value['xIndex'] = this.calculateRegisterValue(reg.value['xIndex'], (reg.value['statusFlags'] & StatusFlags.IndexMode) === StatusFlags.IndexMode, value);\r\n        break;\r\n\r\n      case 'LDY':\r\n        reg.value['yIndex'] = this.calculateRegisterValue(reg.value['yIndex'], (reg.value['statusFlags'] & StatusFlags.IndexMode) === StatusFlags.IndexMode, value);\r\n        break;\r\n\r\n      case 'SEP':\r\n      case 'REP':\r\n        let statusFlags = reg.value['statusFlags'] ?? 0;\r\n        if (mnemonic === 'SEP') {\r\n          statusFlags |= value;\r\n        } else {\r\n          statusFlags &= ~value;\r\n        }\r\n        reg.value['statusFlags'] = statusFlags;\r\n        break;\r\n    }\r\n  }\r\n\r\n  private calculateRegisterValue(currentValue: number | undefined, flag: boolean, operand: number): number {\r\n    if (flag) {\r\n      // 16-bit mode: use full operand value\r\n      return operand;\r\n    } else {\r\n      // 8-bit mode: preserve high byte\r\n      return ((currentValue ?? 0) & 0xFF00) | (operand & 0xFF);\r\n    }\r\n  }\r\n\r\n  private handleAbsoluteLongMode(mnemonic: string, operands: unknown[], reg: Registers): void {\r\n    const refLoc = this._dataReader.readUShort();\r\n    const bank = this._dataReader.readByte();\r\n    const address = new Address(bank, refLoc, reg.mode);\r\n\r\n    if (address.isROM) {\r\n      const wrapper = new LocationWrapper(address.toLocation(), AddressType.Address);\r\n      if (this.isJumpInstruction(mnemonic)) {\r\n        this._blockReader.noteType(wrapper.location, 'Code', false, reg);\r\n      }\r\n      if(mnemonic === 'JML') this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, 'Code');\r\n      operands.push(wrapper);\r\n    } else {\r\n      operands.push(address);\r\n    }\r\n  }\r\n\r\n  private handleBlockMoveMode(operands: unknown[], context: OperationContext): void {\r\n    operands.push(new Byte(this._dataReader.readByte()));\r\n    context.xForm2 = this._transformProcessor.getTransform();\r\n    operands.push(new Byte(this._dataReader.readByte()));\r\n  }\r\n\r\n  private handleDirectPageMode(operands: unknown[]): void {\r\n    operands.push(new Byte(this._dataReader.readByte()));\r\n  }\r\n\r\n  private handlePCRelativeMode(mnemonic: string, operands: unknown[], nextAddress: number, reg: Registers, isLong: boolean): void {\r\n    const relative = isLong\r\n      ? nextAddress + this._dataReader.readShort()\r\n      : nextAddress + this._dataReader.readSByte();\r\n\r\n    //this._blockReader.noteType(relative, 'Code', false, reg);\r\n    this._blockReader._referenceManager.tryAddStruct(relative, \"~Branch\");\r\n    this._blockReader.updateRegisterState(relative, reg);\r\n\r\n    //Add branch suggestion to immediately following instruction\r\n    if(mnemonic === 'BRA' || mnemonic === 'BRL') this._blockReader.noteType(nextAddress, \"~Branch\", true, reg);\r\n\r\n    operands.push(new LocationWrapper(relative, isLong ? AddressType.WRelative : AddressType.Relative));\r\n  }\r\n\r\n  private handleStackRelativeMode(operands: unknown[]): void {\r\n    operands.push(new Byte(this._dataReader.readByte()));\r\n  }\r\n\r\n  private handleStackInterruptMode(mnemonic: string, operands: unknown[], context: OperationContext, reg: Registers): void {\r\n    const cmd = this._dataReader.readByte();\r\n    operands.push(new Byte(cmd));\r\n\r\n    if (mnemonic === 'COP') {\r\n      const copDef = this._blockReader._root.copDef[cmd];\r\n      if (!copDef) {\r\n        //throw new Error('Unknown COP command');\r\n        return;\r\n      }\r\n\r\n      context.copDef = copDef;\r\n      this._copProcessor.parseCopCommand(copDef, operands, reg);\r\n    }\r\n  }\r\n\r\n  private handleStackOrImpliedMode(mnemonic: string, reg: Registers): void {\r\n    const stackOperations = new StackOperations(reg, this._blockReader);\r\n    stackOperations.handleStackOperation(mnemonic);\r\n  }\r\n\r\n  private handleAbsoluteMode(\r\n    mnemonic: string,\r\n    xBank1: number | undefined,\r\n    next: number,\r\n    dataBank: number | undefined,\r\n    operands: unknown[],\r\n    registers: Registers,\r\n    isIndexedIndirect: boolean = false\r\n  ): void {\r\n    let refLoc = this._dataReader.readUShort();\r\n\r\n    const isPush = this.isPushInstruction(mnemonic);\r\n    if (isPush) {\r\n      refLoc++;\r\n    }\r\n\r\n    const isJump = isPush || isIndexedIndirect || this.isJumpInstruction(mnemonic);\r\n    const resolvedBank = xBank1 \r\n      ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) \r\n      ?? this._blockReader._root.config.defaultBank\r\n      ?? 0x81;\r\n\r\n    const addr = new Address(resolvedBank, refLoc, registers.mode, true);\r\n    if (addr.isROM) {\r\n      const wrapper = new LocationWrapper(addr.toLocation(), AddressType.Offset);\r\n      if (isJump) {\r\n        const type = isIndexedIndirect ? '&Code' : 'Code';\r\n        const name = this._blockReader.noteType(wrapper.location, type, isPush, registers);\r\n        if(mnemonic === 'JMP') this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, '~Code');\r\n\r\n        if (isPush) {\r\n          operands.push(`&${name}-1`);\r\n          return;\r\n        }\r\n      }\r\n      operands.push(wrapper);\r\n    } else {\r\n      operands.push(addr);\r\n    }\r\n  }\r\n\r\n  private isJumpInstruction(mnemonic: string): boolean {\r\n    return mnemonic[0] === 'J';\r\n  }\r\n\r\n  private isPushInstruction(mnemonic: string): boolean {\r\n    return mnemonic[0] === 'P';\r\n  }\r\n} ","import { RomDataReader } from './reader';\r\nimport { ReferenceManager } from './references';\r\nimport { RomProcessingConstants } from '../../types/constants';\r\nimport type { BlockReader } from './blocks';\r\nimport { Address, AddressType } from '../../types/addressing';\r\nimport { indexOfAny, LocationWrapper } from '../..';\r\n\r\n/**\r\n * Handles transform processing for assembly instructions\r\n * Converted from GaiaLib/Rom/Extraction/TransformProcessor.cs\r\n */\r\nexport class TransformProcessor {\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _romDataReader: RomDataReader;\r\n  private readonly _referenceManager: ReferenceManager;\r\n  private readonly _labelLookup: Record<number, string>;\r\n\r\n  // Location regex pattern: _([A-Fa-f0-9]{6})\r\n  private static readonly LOCATION_REGEX = /_([A-Fa-f0-9]{6})/;\r\n\r\n  constructor(romReader: BlockReader) {\r\n    this._blockReader = romReader;\r\n    this._romDataReader = romReader._romDataReader;\r\n    this._referenceManager = romReader._referenceManager;\r\n    this._labelLookup = romReader._root.labels;\r\n  }\r\n\r\n  /**\r\n   * Retrieves transform information for the current ROM position\r\n   */\r\n  public getTransform(): string | undefined {\r\n    const transform = this._labelLookup[this._romDataReader.position];\r\n    if (transform === '') {\r\n      return transform;\r\n    } else if (!transform) {\r\n      return undefined;\r\n    }\r\n\r\n    const transformName = this.cleanTransformName(transform);\r\n    const referenceLocation = this.resolveTransformReference(transformName);\r\n    \r\n    if (referenceLocation !== null) {\r\n      this._blockReader.resolveInclude(referenceLocation, false);\r\n    }\r\n\r\n    return transform;\r\n  }\r\n\r\n  /**\r\n   * Applies transforms to operands\r\n   */\r\n  public applyTransforms(op1Label: string | undefined, op2Label: string | undefined, operands: any[]): void {\r\n    if(operands.length > 0) operands[0] = this.applyTransform(op1Label, operands[0]);\r\n    if(operands.length > 1) operands[1] = this.applyTransform(op2Label, operands[1]);\r\n  }\r\n\r\n  public applyTransform(transform: string | undefined, operand: any | undefined): any {\r\n    if (transform === undefined || operand === undefined) {\r\n      return operand;\r\n    }\r\n\r\n    let type = AddressType.Offset;\r\n    let loc : number | undefined;\r\n\r\n    if (transform === '' || transform[0] === '$') {\r\n      const offset = operand && 'value' in operand ? operand['value'] : operand as number;\r\n      const bank = transform[0] === '$' \r\n        ? parseInt(transform.substring(1), 16) \r\n        : Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode);\r\n        const adrs = new Address(bank, offset, this._blockReader._root.config.memoryMode, true);\r\n        loc = adrs.toLocation();\r\n    } else if(transform.match(/^[*^][A-Fa-f0-9]{6}$/)) {\r\n      loc = parseInt(transform.substring(1), 16);\r\n      type = Address.typeFromCode(transform[0]);\r\n    }\r\n\r\n    return loc !== undefined ? new LocationWrapper(loc, type) : transform;\r\n  }\r\n\r\n  private cleanTransformName(transform: string): string {\r\n    let name = transform;\r\n    \r\n    // Remove address space characters from the start\r\n    while (name.length > 0 && RomProcessingConstants.ADDRESS_SPACE.includes(name[0])) {\r\n      name = name.substring(1);\r\n    }\r\n    \r\n    // Find math operators and truncate at that point\r\n    let mathIndex = -1;\r\n    for (let i = 0; i < name.length; i++) {\r\n      if (RomProcessingConstants.OPERATORS.includes(name[i])) {\r\n        mathIndex = i;\r\n        break;\r\n      }\r\n    }\r\n    \r\n    if (mathIndex > 0) {\r\n      name = name.substring(0, mathIndex);\r\n    }\r\n    \r\n    return name;\r\n  }\r\n\r\n  private resolveTransformReference(transformName: string): number | null {\r\n    // Directly resolve by name in the reference table\r\n    const location = this._referenceManager.findLocationByName(transformName);\r\n    if (location !== undefined) {\r\n      return location;\r\n    }\r\n\r\n    // Fallback to parsing the location pattern\r\n    const match = TransformProcessor.LOCATION_REGEX.exec(transformName);\r\n    return match ? parseInt(match[1], 16) : null;\r\n  }\r\n}","/**\r\n * Universal file reading utilities\r\n * Works in both Node.js and browser environments\r\n */\r\n\r\n// Platform detection\r\nconst isNode = typeof process !== 'undefined' && process.versions?.node;\r\n// const isBrowser = typeof globalThis !== 'undefined' && 'window' in globalThis;\r\n\r\nexport interface FileReadOptions {\r\n  encoding?: 'utf8' | 'binary';\r\n}\r\n\r\n/**\r\n * Read a file as text\r\n * @param path File path or URL\r\n * @param options Read options\r\n * @returns Promise<string>\r\n */\r\nexport async function readFileAsText(path: string, options: FileReadOptions = {}): Promise<string> {\r\n  const { encoding = 'utf8' } = options;\r\n  \r\n  if (isNode) {\r\n    // Node.js environment\r\n    const { readFile } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n    \r\n    const fullPath = pathModule.resolve(path);\r\n    \r\n    try {\r\n      let text = await readFile(fullPath, { encoding });\r\n      \r\n      // Strip UTF-8 BOM if present\r\n      if (text.charCodeAt(0) === 0xFEFF) {\r\n        text = text.slice(1);\r\n      }\r\n      \r\n      return text;\r\n    } catch (error: any) {\r\n      if (error.code === 'ENOENT') {\r\n        throw new Error(`File not found: ${fullPath}`);\r\n      }\r\n      throw error;\r\n    }\r\n  } else {\r\n    // Browser environment\r\n    const response = await fetch(path);\r\n    if (!response.ok) {\r\n      throw new Error(`Failed to fetch file: ${path} (${response.status})`);\r\n    }\r\n    \r\n    let text = await response.text();\r\n    \r\n    // Strip UTF-8 BOM if present\r\n    if (text.charCodeAt(0) === 0xFEFF) {\r\n      text = text.slice(1);\r\n    }\r\n    \r\n    return text;\r\n  }\r\n}\r\n\r\n/**\r\n * Read a file as binary data (Uint8Array)\r\n * @param path File path or URL\r\n * @returns Promise<Uint8Array>\r\n */\r\nexport async function readFileAsBinary(path: string): Promise<Uint8Array> {\r\n  if (isNode) {\r\n    // Node.js environment\r\n    const { readFile } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n    \r\n    const fullPath = pathModule.resolve(path);\r\n\r\n    try {\r\n      const buffer = await readFile(fullPath);\r\n      return new Uint8Array(buffer);\r\n    } catch (error: any) {\r\n      if (error.code === 'ENOENT') {\r\n        throw new Error(`File not found: ${fullPath}`);\r\n      }\r\n      throw error;\r\n    }\r\n  } else {\r\n    // Browser environment\r\n    const response = await fetch(path);\r\n    if (!response.ok) {\r\n      throw new Error(`Failed to fetch file: ${path} (${response.status})`);\r\n    }\r\n    \r\n    const arrayBuffer = await response.arrayBuffer();\r\n    return new Uint8Array(arrayBuffer);\r\n  }\r\n}\r\n\r\n/**\r\n * Read a JSON file and parse it\r\n * @param path File path or URL\r\n * @returns Promise<any>\r\n */\r\nexport async function readJsonFile<T = any>(path: string): Promise<T> {\r\n  const text = await readFileAsText(path);\r\n  return JSON.parse(text) as T;\r\n}\r\n\r\n/**\r\n * Check if a file exists\r\n * @param path File path\r\n * @returns Promise<boolean>\r\n */\r\nexport async function fileExists(path: string): Promise<boolean> {\r\n  if (isNode) {\r\n    // Node.js environment\r\n    const { access } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n    \r\n    const fullPath = pathModule.resolve(path);\r\n    try {\r\n      await access(fullPath);\r\n      return true;\r\n    } catch {\r\n      return false;\r\n    }\r\n  } else {\r\n    // Browser environment - try to fetch and check if successful\r\n    try {\r\n      const response = await fetch(path, { method: 'HEAD' });\r\n      return response.ok;\r\n    } catch {\r\n      return false;\r\n    }\r\n  }\r\n}\r\n\r\n/**\r\n * Get the directory path containing a file\r\n * @param filePath File path\r\n * @returns string\r\n */\r\nexport async function getDirectory(filePath: string): Promise<string> {\r\n  if (isNode) {\r\n    // Node.js environment\r\n    const path = await import('path');\r\n    return path.dirname(path.resolve(filePath));\r\n  } else {\r\n    // Browser environment\r\n    const url = new URL(filePath, (globalThis as any).location.href);\r\n    return url.pathname.split('/').slice(0, -1).join('/') || './';\r\n  }\r\n}\r\n\r\n/**\r\n * Create a temporary directory.\r\n * This is a Node.js-specific operation.\r\n * @param prefix Prefix for the temporary directory name.\r\n * @returns Promise<string> Path to the created temporary directory.\r\n */\r\nexport async function createTempDirectory(prefix: string): Promise<string> {\r\n  if (isNode) {\r\n    const { mkdtemp } = await import('fs/promises');\r\n    const { tmpdir } = await import('os');\r\n    const { join } = await import('path');\r\n    return mkdtemp(join(tmpdir(), prefix));\r\n  } else {\r\n    throw new Error('createTempDirectory is not supported in the browser environment.');\r\n  }\r\n}\r\n\r\n/**\r\n * Remove a directory recursively.\r\n * This is a Node.js-specific operation.\r\n * @param dirPath Path to the directory to remove.\r\n * @returns Promise<void>\r\n */\r\nexport async function removeDirectory(dirPath: string): Promise<void> {\r\n  if (isNode) {\r\n    const { rm } = await import('fs/promises');\r\n    return rm(dirPath, { recursive: true, force: true });\r\n  } else {\r\n    throw new Error('removeDirectory is not supported in the browser environment.');\r\n  }\r\n}\r\n\r\nexport interface DirectoryEntry {\r\n  name: string;\r\n  path: string;\r\n  extension: string | null;\r\n  isDirectory: boolean;\r\n  isFile: boolean;\r\n}\r\n\r\n/**\r\n * List directory contents\r\n * This is a Node.js-specific operation.\r\n * @param dirPath Path to the directory to list\r\n * @param options Options for filtering and recursion\r\n * @returns Promise<DirectoryEntry[]>\r\n */\r\nexport async function listDirectory(\r\n  dirPath: string,\r\n  options: {\r\n    recursive?: boolean;\r\n    filter?: (entry: DirectoryEntry) => boolean;\r\n    extension?: string;\r\n  } = {}\r\n): Promise<DirectoryEntry[]> {\r\n  if (isNode) {\r\n    const { readdir, stat } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n\r\n    const { recursive = false, filter, extension } = options;\r\n    const fullPath = pathModule.resolve(dirPath);\r\n\r\n    try {\r\n      const entries: DirectoryEntry[] = [];\r\n      const items = await readdir(fullPath);\r\n\r\n      for (const item of items) {\r\n        const itemPath = pathModule.join(fullPath, item);\r\n        const stats = await stat(itemPath);\r\n        const isFile = stats.isFile();\r\n        const extIx = isFile ? item.indexOf('.') : -1;\r\n        const ext = extIx > 0 ? item.substring(extIx + 1) : null;\r\n        const name = extIx > 0 ? item.substring(0, extIx) : item;\r\n\r\n        const entry: DirectoryEntry = {\r\n          name: name,\r\n          path: itemPath,\r\n          extension: ext,\r\n          isFile: isFile,\r\n          isDirectory: stats.isDirectory()\r\n        };\r\n\r\n        // Apply extension filter\r\n        if (extension && ext !== extension) {\r\n          continue;\r\n        }\r\n\r\n        // Apply custom filter\r\n        if (filter && !filter(entry)) {\r\n          continue;\r\n        }\r\n\r\n        entries.push(entry);\r\n\r\n        // Recurse into subdirectories if requested\r\n        if (recursive && entry.isDirectory) {\r\n          const subEntries = await listDirectory(itemPath, options);\r\n          entries.push(...subEntries);\r\n        }\r\n      }\r\n\r\n      return entries;\r\n    } catch (error: any) {\r\n      if (error.code === 'ENOENT') {\r\n        throw new Error(`Directory not found: ${fullPath}`);\r\n      }\r\n      throw error;\r\n    }\r\n  } else {\r\n    throw new Error('listDirectory is not supported in the browser environment.');\r\n  }\r\n}\r\n\r\n/**\r\n * Save text content to a file\r\n * This is a Node.js-specific operation.\r\n * @param path File path where to save the content\r\n * @param text Text content to save\r\n * @returns Promise<void>\r\n */\r\nexport async function saveFileAsText(path: string, text: string): Promise<void> {\r\n  if (isNode) {\r\n    const { writeFile, mkdir } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n\r\n    const fullPath = pathModule.resolve(path);\r\n    const dirPath = pathModule.dirname(fullPath);\r\n\r\n    try {\r\n      // Ensure parent directories exist\r\n      await mkdir(dirPath, { recursive: true });\r\n\r\n      // Write the file with UTF-8 encoding\r\n      await writeFile(fullPath, text, { encoding: 'utf8' });\r\n    } catch (error: any) {\r\n      throw new Error(`Failed to save file: ${fullPath} - ${error.message}`);\r\n    }\r\n  } else {\r\n    throw new Error('saveFileAsText is not supported in the browser environment.');\r\n  }\r\n}\r\n\r\n/**\r\n * Save binary data to a file\r\n * This is a Node.js-specific operation.\r\n * @param path File path where to save the data\r\n * @param data Binary data as Uint8Array to save\r\n * @returns Promise<void>\r\n */\r\nexport async function saveFileAsBinary(path: string, data: Uint8Array): Promise<void> {\r\n  if (isNode) {\r\n    const { writeFile, mkdir } = await import('fs/promises');\r\n    const pathModule = await import('path');\r\n\r\n    const fullPath = pathModule.resolve(path);\r\n    const dirPath = pathModule.dirname(fullPath);\r\n\r\n    try {\r\n      // Ensure parent directories exist\r\n      await mkdir(dirPath, { recursive: true });\r\n\r\n      // Write the binary data directly\r\n      await writeFile(fullPath, data);\r\n    } catch (error: any) {\r\n      throw new Error(`Failed to save file: ${fullPath} - ${error.message}`);\r\n    }\r\n  } else {\r\n    throw new Error('saveFileAsBinary is not supported in the browser environment.');\r\n  }\r\n}","\r\nconst polynomial = 0x04C11DB7;\r\n\r\nfunction crc32_reverse(polynomial: number) {\r\n    var reversedPolynomial = 0\r\n\r\n    for (let i = 0; i < 32; i++) {\r\n        reversedPolynomial = reversedPolynomial << 1\r\n        reversedPolynomial = reversedPolynomial | ((polynomial >>> i) & 1)\r\n    }\r\n\r\n    return reversedPolynomial\r\n}\r\n\r\nconst reversedPolynomial = crc32_reverse(polynomial);\r\n\r\nfunction crc32_generate() {\r\n    var table = new Array()\r\n    var i, j, n\r\n\r\n    for (i = 0; i < 256; i++) {\r\n        n = i\r\n        for (j = 8; j > 0; j--) {\r\n            if ((n & 1) == 1) {\r\n                n = (n >>> 1) ^ reversedPolynomial\r\n            } else {\r\n                n = n >>> 1\r\n            }\r\n        }\r\n        table[i] = n\r\n    }\r\n\r\n    return table\r\n}\r\n\r\nfunction crc32_initial() {\r\n    return 0xFFFFFFFF\r\n}\r\n\r\nfunction crc32_add_byte(table: number[], crc: number, byte: number) {\r\n    crc = (crc >>> 8) ^ table[(byte) ^ (crc & 0x000000FF)]\r\n    return crc\r\n}\r\n\r\nfunction crc32_final(crc: number) {\r\n    crc = ~crc\r\n    crc = (crc < 0) ? (0xFFFFFFFF + crc + 1) : crc\r\n    return crc & 0xFFFFFFFF;\r\n}\r\n\r\n// Deprecated\r\n// export function crc32_string(str: string) {\r\n//     var table = crc32_generate()\r\n//     var crc =  crc32_initial()\r\n\r\n//     for (let i = 0; i < str.length; i++)\r\n//         crc = crc32_add_byte(table, crc, str.charCodeAt(i))\r\n\r\n//     crc = crc32_final(crc)\r\n//     return crc\r\n// }\r\n\r\nexport function crc32_buffer(data: Uint8Array) {\r\n    var table = crc32_generate()\r\n    var crc = crc32_initial()\r\n\r\n    for (let i = 0; i < data.length; i++)\r\n        crc = crc32_add_byte(table, crc, data[i])\r\n\r\n    crc = crc32_final(crc)\r\n    return crc\r\n}\r\n\r\nexport function crc32_text_utf8(text: string): number {\r\n    const utf8Bytes = new TextEncoder().encode(text);\r\n    return crc32_buffer(utf8Bytes);\r\n}\r\n\r\nexport function crc32_text_utf16(text: string): number {\r\n    const utf16Bytes = new Uint8Array(text.length * 2);\r\n    for (let i = 0; i < text.length; i++) {\r\n        const code = text.charCodeAt(i);\r\n        utf16Bytes[i * 2] = code & 0xFF;\r\n        utf16Bytes[i * 2 + 1] = (code >> 8) & 0xFF;\r\n    }\r\n    return crc32_buffer(utf16Bytes);\r\n}\r\n","/**\n * Base64 encoding and decoding utilities for Uint8Arrays\n * Works in both Node.js and browser environments\n */\n\n// Platform detection\nconst isNode = typeof process !== 'undefined' && process.versions?.node;\n\n// Base64 character set\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Create lookup table for decoding\nconst BASE64_LOOKUP: { [key: string]: number } = {};\nfor (let i = 0; i < BASE64_CHARS.length; i++) {\n  BASE64_LOOKUP[BASE64_CHARS[i]] = i;\n}\n\n/**\n * Custom base64 encoding implementation that handles large data without call stack overflow\n * @param data The binary data to encode\n * @returns Base64 encoded string\n */\nfunction customBase64Encode(data: Uint8Array): string {\n  let result = '';\n  let i = 0;\n\n  // Process 3 bytes at a time\n  while (i < data.length) {\n    const byte1 = data[i++];\n    const byte2 = i < data.length ? data[i++] : 0;\n    const byte3 = i < data.length ? data[i++] : 0;\n\n    // Convert 3 bytes to 4 base64 characters\n    const bitmap = (byte1 << 16) | (byte2 << 8) | byte3;\n\n    result += BASE64_CHARS[(bitmap >> 18) & 63];\n    result += BASE64_CHARS[(bitmap >> 12) & 63];\n    result += BASE64_CHARS[(bitmap >> 6) & 63];\n    result += BASE64_CHARS[bitmap & 63];\n  }\n\n  // Add padding if necessary\n  const padding = data.length % 3;\n  if (padding === 1) {\n    result = result.slice(0, -2) + '==';\n  } else if (padding === 2) {\n    result = result.slice(0, -1) + '=';\n  }\n\n  return result;\n}\n\n/**\n * Custom base64 decoding implementation that handles large data without call stack overflow\n * @param base64String The base64 string to decode\n * @returns Decoded binary data as Uint8Array\n * @throws {Error} If the input contains invalid base64 characters\n */\nfunction customBase64Decode(base64String: string): Uint8Array {\n  // Remove padding for calculation\n  const cleanString = base64String.replace(/=/g, '');\n  const outputLength = Math.floor((cleanString.length * 3) / 4);\n  const result = new Uint8Array(outputLength);\n\n  let resultIndex = 0;\n  let i = 0;\n\n  // Process 4 characters at a time\n  while (i < cleanString.length) {\n    const char1 = cleanString[i++];\n    const char2 = i < cleanString.length ? cleanString[i++] : 'A';\n    const char3 = i < cleanString.length ? cleanString[i++] : 'A';\n    const char4 = i < cleanString.length ? cleanString[i++] : 'A';\n\n    // Validate characters\n    if (!(char1 in BASE64_LOOKUP) || !(char2 in BASE64_LOOKUP) ||\n        !(char3 in BASE64_LOOKUP) || !(char4 in BASE64_LOOKUP)) {\n      throw new Error('Invalid base64 character encountered');\n    }\n\n    // Convert 4 base64 characters to 3 bytes\n    const bitmap = (BASE64_LOOKUP[char1] << 18) |\n                   (BASE64_LOOKUP[char2] << 12) |\n                   (BASE64_LOOKUP[char3] << 6) |\n                   BASE64_LOOKUP[char4];\n\n    if (resultIndex < result.length) {\n      result[resultIndex++] = (bitmap >> 16) & 255;\n    }\n    if (resultIndex < result.length) {\n      result[resultIndex++] = (bitmap >> 8) & 255;\n    }\n    if (resultIndex < result.length) {\n      result[resultIndex++] = bitmap & 255;\n    }\n  }\n\n  return result;\n}\n\n/**\n * Encode a Uint8Array to a base64 string\n * @param data The binary data to encode\n * @returns Base64 encoded string\n */\nexport function encodeBase64(data: Uint8Array): string {\n  if (!data || data.length === 0) {\n    return '';\n  }\n\n  if (isNode) {\n    // Node.js environment - use Buffer\n    return Buffer.from(data).toString('base64');\n  } else {\n    // Browser environment - custom base64 encoding implementation\n    return customBase64Encode(data);\n  }\n}\n\n/**\n * Decode a base64 string to a Uint8Array\n * @param base64String The base64 string to decode\n * @returns Decoded binary data as Uint8Array\n * @throws {Error} If the input is not a valid base64 string\n */\nexport function decodeBase64(base64String: string): Uint8Array {\n  if (!base64String || base64String.length === 0) {\n    return new Uint8Array(0);\n  }\n\n  // Validate base64 format\n  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(base64String)) {\n    throw new Error('Invalid base64 string format');\n  }\n\n  if (isNode) {\n    // Node.js environment - use Buffer\n    try {\n      const buffer = Buffer.from(base64String, 'base64');\n      return new Uint8Array(buffer);\n    } catch (error) {\n      throw new Error(`Failed to decode base64 string: ${error instanceof Error ? error.message : 'Unknown error'}`);\n    }\n  } else {\n    // Browser environment - custom base64 decoding implementation\n    try {\n      return customBase64Decode(base64String);\n    } catch (error) {\n      throw new Error(`Failed to decode base64 string: ${error instanceof Error ? error.message : 'Unknown error'}`);\n    }\n  }\n}\n\n/**\n * Check if a string is valid base64\n * @param str The string to validate\n * @returns True if the string is valid base64, false otherwise\n */\nexport function isValidBase64(str: string): boolean {\n  if (typeof str !== 'string') {\n    return false;\n  }\n\n  // Empty string is valid base64\n  if (str === '') {\n    return true;\n  }\n\n  // Check format with regex\n  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(str)) {\n    return false;\n  }\n\n  // Check length (must be multiple of 4)\n  if (str.length % 4 !== 0) {\n    return false;\n  }\n\n  try {\n    // Try to decode to verify it's actually valid\n    decodeBase64(str);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Encode a string to base64 (convenience function)\n * @param text The text string to encode\n * @returns Base64 encoded string\n */\nexport function encodeBase64String(text: string): string {\n  const encoder = new TextEncoder();\n  const data = encoder.encode(text);\n  return encodeBase64(data);\n}\n\n/**\n * Decode a base64 string to text (convenience function)\n * @param base64String The base64 string to decode\n * @returns Decoded text string\n * @throws {Error} If the input is not a valid base64 string or doesn't contain valid UTF-8\n */\nexport function decodeBase64String(base64String: string): string {\n  const data = decodeBase64(base64String);\n  const decoder = new TextDecoder('utf-8', { fatal: true });\n  \n  try {\n    return decoder.decode(data);\n  } catch (error) {\n    throw new Error(`Failed to decode base64 string as UTF-8 text: ${error instanceof Error ? error.message : 'Unknown error'}`);\n  }\n}\n","// Utility functions and helpers\r\n\r\n// File utilities\r\nexport * from './file';\r\nexport * from './crc';\r\nexport * from './base64';\r\n\r\n/**\r\n * Convert bytes to hex string\r\n */\r\nexport function bytesToHex(bytes: Uint8Array): string {\r\n  return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');\r\n}\r\n\r\n/**\r\n * Convert hex string to bytes\r\n */\r\nexport function hexToBytes(hex: string): Uint8Array {\r\n  const bytes = new Uint8Array(hex.length / 2);\r\n  for (let i = 0; i < hex.length; i += 2) {\r\n    bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\r\n  }\r\n  return bytes;\r\n}\r\n\r\n/**\r\n * Clamp a value between min and max\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n  return Math.min(Math.max(value, min), max);\r\n}\r\n\r\n/**\r\n * Convert binary data (Uint8Array) to UTF-8 string representation\r\n *\r\n * This function properly decodes UTF-8 encoded binary data to avoid corruption\r\n * of special characters and multi-byte sequences.\r\n *\r\n * @param binaryData - The binary data as Uint8Array containing UTF-8 encoded text\r\n * @returns The decoded UTF-8 string\r\n * @throws {Error} If the binary data contains invalid UTF-8 sequences\r\n *\r\n * @example\r\n * ```typescript\r\n * const binaryData = new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);\r\n * const text = binaryToUtf8String(binaryData);\r\n * console.log(text); // \"Hello World\"\r\n *\r\n * // Handle UTF-8 multi-byte characters\r\n * const utf8Data = new Uint8Array([240, 159, 152, 128]); // 😀 emoji\r\n * const emoji = binaryToUtf8String(utf8Data);\r\n * console.log(emoji); // \"😀\"\r\n * ```\r\n */\r\nexport function binaryToUtf8String(binaryData: Uint8Array): string {\r\n  if (!binaryData || binaryData.length === 0) {\r\n    return '';\r\n  }\r\n\r\n  try {\r\n    // Use TextDecoder for proper UTF-8 decoding with error handling\r\n    if (typeof TextDecoder !== 'undefined') {\r\n      const decoder = new TextDecoder('utf-8', { fatal: true });\r\n      return decoder.decode(binaryData);\r\n    }\r\n\r\n    // Node.js fallback using Buffer\r\n    if (typeof Buffer !== 'undefined') {\r\n      return Buffer.from(binaryData).toString('utf8');\r\n    }\r\n\r\n    // Manual UTF-8 decoding fallback (less robust but works in all environments)\r\n    let result = '';\r\n    let i = 0;\r\n\r\n    while (i < binaryData.length) {\r\n      let byte1 = binaryData[i++];\r\n\r\n      // Single-byte character (ASCII)\r\n      if (byte1 < 0x80) {\r\n        result += String.fromCharCode(byte1);\r\n      }\r\n      // Two-byte character\r\n      else if ((byte1 & 0xE0) === 0xC0) {\r\n        if (i >= binaryData.length) {\r\n          throw new Error(`Invalid UTF-8 sequence: incomplete two-byte character at position ${i - 1}`);\r\n        }\r\n        const byte2 = binaryData[i++];\r\n        if ((byte2 & 0xC0) !== 0x80) {\r\n          throw new Error(`Invalid UTF-8 sequence: invalid continuation byte at position ${i - 1}`);\r\n        }\r\n        const codePoint = ((byte1 & 0x1F) << 6) | (byte2 & 0x3F);\r\n        result += String.fromCharCode(codePoint);\r\n      }\r\n      // Three-byte character\r\n      else if ((byte1 & 0xF0) === 0xE0) {\r\n        if (i + 1 >= binaryData.length) {\r\n          throw new Error(`Invalid UTF-8 sequence: incomplete three-byte character at position ${i - 1}`);\r\n        }\r\n        const byte2 = binaryData[i++];\r\n        const byte3 = binaryData[i++];\r\n        if ((byte2 & 0xC0) !== 0x80 || (byte3 & 0xC0) !== 0x80) {\r\n          throw new Error(`Invalid UTF-8 sequence: invalid continuation bytes at position ${i - 2}`);\r\n        }\r\n        const codePoint = ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F);\r\n        result += String.fromCharCode(codePoint);\r\n      }\r\n      // Four-byte character\r\n      else if ((byte1 & 0xF8) === 0xF0) {\r\n        if (i + 2 >= binaryData.length) {\r\n          throw new Error(`Invalid UTF-8 sequence: incomplete four-byte character at position ${i - 1}`);\r\n        }\r\n        const byte2 = binaryData[i++];\r\n        const byte3 = binaryData[i++];\r\n        const byte4 = binaryData[i++];\r\n        if ((byte2 & 0xC0) !== 0x80 || (byte3 & 0xC0) !== 0x80 || (byte4 & 0xC0) !== 0x80) {\r\n          throw new Error(`Invalid UTF-8 sequence: invalid continuation bytes at position ${i - 3}`);\r\n        }\r\n        const codePoint = ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) << 6) | (byte4 & 0x3F);\r\n        // Use surrogate pairs for code points > 0xFFFF\r\n        if (codePoint > 0xFFFF) {\r\n          const surrogate1 = 0xD800 + ((codePoint - 0x10000) >> 10);\r\n          const surrogate2 = 0xDC00 + ((codePoint - 0x10000) & 0x3FF);\r\n          result += String.fromCharCode(surrogate1, surrogate2);\r\n        } else {\r\n          result += String.fromCharCode(codePoint);\r\n        }\r\n      }\r\n      // Invalid UTF-8 start byte\r\n      else {\r\n        throw new Error(`Invalid UTF-8 sequence: invalid start byte 0x${byte1.toString(16)} at position ${i - 1}`);\r\n      }\r\n    }\r\n\r\n    return result;\r\n  } catch (error) {\r\n    throw new Error(`Failed to decode UTF-8 binary data: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n  }\r\n}\r\n\r\n/**\r\n * Safely get nested object property\r\n */\r\nexport function getNestedProperty(obj: any, path: string): any {\r\n  return path.split('.').reduce((current, key) => current?.[key], obj);\r\n}\r\n\r\n\r\nexport function indexOfAny(str: string, chars: string[], startIndex = 0): number {\r\n  for (let i = startIndex; i < str.length; i++) {\r\n    if (chars.includes(str[i])) {\r\n      return i;\r\n    }\r\n  }\r\n  return -1;\r\n}\r\n\r\n","import { RomDataReader } from './reader';\r\nimport { \r\n  Address, \r\n  AddressSpace, \r\n  AddressType, \r\n  MemberType, \r\n  RomProcessingConstants,\r\n  ChunkFileUtils, \r\n  TableEntry \r\n} from '../../types';\r\nimport type { DbStringType, DbStringCommand, DbStringLayer } from '../../database';\r\nimport type { StringWrapper } from '../../types';\r\nimport type { BlockReader } from './blocks';\r\nimport { indexOfAny } from '../../utils';\r\n\r\n/**\r\n * Reads and processes strings from ROM data\r\n * Converted from GaiaLib/Rom/Extraction/StringReader.cs\r\n */\r\nexport class StringReader {\r\n  public static readonly STRING_REFERENCE_CHARACTERS = ['~', '^'];\r\n\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _romDataReader: RomDataReader;\r\n\r\n  constructor(blockReader: BlockReader) {\r\n    this._blockReader = blockReader;\r\n    this._romDataReader = blockReader._romDataReader;\r\n  }\r\n\r\n  private resolveCommand(cmd: DbStringCommand, builder: string[]): void {\r\n\r\n    builder.push(cmd.dictionary ? \"{\" : \"[\");\r\n    builder.push(cmd.name);\r\n\r\n    let first = true;\r\n    for (const t of cmd.types ?? []) {\r\n      builder.push(first ? \":\" : \",\");\r\n      first = false;\r\n\r\n      switch (t) {\r\n        case MemberType.Byte:\r\n          builder.push(this._romDataReader.readByte().toString(16).toUpperCase());\r\n          break;\r\n        case MemberType.Word:\r\n          builder.push(this._romDataReader.readUShort().toString(16).toUpperCase());\r\n          break;\r\n        case MemberType.Offset:\r\n          const loc = this._romDataReader.readUShort() | \r\n            (Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode) << 16);\r\n          builder.push(`^${loc.toString(16).toUpperCase().padStart(6, '0')}`);\r\n          break;\r\n        case MemberType.Address:\r\n          builder.push(`~${this._romDataReader.readAddress().toString(16).toUpperCase().padStart(6, '0')}`);\r\n          break;\r\n        case MemberType.Binary:\r\n          let sfirst = true;\r\n          do {\r\n            const r = this._romDataReader.readByte();\r\n            if (cmd.delimiter !== undefined && r === cmd.delimiter) {\r\n              break;\r\n            }\r\n            if (sfirst) {\r\n              sfirst = false;\r\n            } else {\r\n              builder.push(',');\r\n            }\r\n            builder.push(r.toString(16).toUpperCase());\r\n          } while (this._blockReader.partCanContinue());\r\n          break;\r\n        default:\r\n          throw new Error('Unsupported member type');\r\n      }\r\n    }\r\n      \r\n    builder.push(cmd.dictionary ? \"}\" : \"]\");\r\n    if(cmd.newline) builder.push(`\\\\${RomProcessingConstants.NEWLINE}`);\r\n  }\r\n\r\n  public parseString(stringType: DbStringType, fixedSize: number, isRaw: boolean): StringWrapper {\r\n    const commands = stringType.commandLookup;\r\n    const dictionaries = stringType.dictionaries;\r\n    const builder: string[] = [];\r\n    const strLoc = this._romDataReader.position;\r\n    const terminator = stringType.terminator;\r\n    const modifiers = stringType.modifiers;\r\n    let currentLayer = stringType.layers[0];\r\n\r\n    do {\r\n      const c = this._romDataReader.readByte();\r\n      if (c === terminator) {\r\n        if (stringType.greedyTerminator) {\r\n          while (this._romDataReader.peekByte() === terminator && this._blockReader.partCanContinue()) {\r\n            this._romDataReader.position++;\r\n          }\r\n        }\r\n        break;\r\n      }\r\n\r\n      let cmd: DbStringCommand | undefined = undefined;\r\n\r\n      const mod = modifiers ? modifiers[c] : undefined;\r\n      if(mod) {\r\n        const prev = builder[builder.length - 1];\r\n        const next = mod[prev]\r\n        if(next) builder[builder.length - 1] = next;\r\n        else builder.push(currentLayer.map[c - (currentLayer.base ?? 0)]);\r\n      } else if ((cmd = commands[c])) {\r\n        this.resolveCommand(cmd, builder);\r\n        if (cmd.halt) {\r\n          break;\r\n        }\r\n      } else {\r\n        let found = false;\r\n\r\n        for(const dictionary of Object.values(dictionaries)) {\r\n          if(dictionary.command === undefined && dictionary.base !== undefined \r\n            && c >= dictionary.base && c < dictionary.base + dictionary.entries.length) {\r\n            builder.push(`{${c.toString(16).padStart(2, '0').toUpperCase()}}`);\r\n            found = true;\r\n            break;\r\n          }\r\n        }\r\n\r\n        if(!found) {\r\n          for(const layer of stringType.layers) {\r\n            if(layer.on !== undefined) {\r\n              if(c === layer.on) {\r\n                currentLayer = layer;\r\n                builder.push(\"[--]\");\r\n                found = true;\r\n                break;\r\n              }\r\n            } else if(layer.base && c >= layer.base && c < layer.base + layer.map.length){\r\n              builder.push(layer.map[c - layer.base]);\r\n              found = true;\r\n              break;\r\n            }\r\n          }\r\n        }\r\n        \r\n        if(!found) {\r\n          let index = c - (currentLayer.base ?? 0);\r\n          if(typeof currentLayer.shiftBit === 'number') {\r\n            const shiftBit = 1 << currentLayer.shiftBit;\r\n            const lowerFlag = shiftBit - 1;\r\n            const upperFlag = ~shiftBit & ~lowerFlag;\r\n            index = ((index & upperFlag) >> 1) | (index & lowerFlag);\r\n          }\r\n          //const index = currentLayer.shift ? DbStringTypeUtils.getShiftDown(currentLayer.shift)(c) : c - (currentLayer.base ?? 0);\r\n          if (index >= 0 && index < currentLayer.map.length) {\r\n            builder.push(currentLayer.map[index]);\r\n          } else {\r\n            // Fallback for unknown characters\r\n            builder.push(`[${c.toString(16).toUpperCase()}]`);\r\n          }\r\n        }\r\n      }\r\n\r\n      if(fixedSize && this._romDataReader.position >= strLoc + fixedSize) break;\r\n      \r\n    } while (this._blockReader.partCanContinue());\r\n\r\n    if(fixedSize && this._romDataReader.position < strLoc + fixedSize) this._romDataReader.position = strLoc + fixedSize;\r\n\r\n    return {\r\n      string: builder.join(''),\r\n      type: stringType,\r\n      marker: 0,\r\n      location: strLoc,\r\n      fixedSize,\r\n      isRaw\r\n    };\r\n  }\r\n\r\n  public resolveString(sw: StringWrapper, isBranch: boolean): void {\r\n    let str = sw.string;\r\n    let ix = indexOfAny(str, StringReader.STRING_REFERENCE_CHARACTERS);\r\n\r\n    while(ix >= 0) {\r\n      if(ix + 6 >= str.length) break;\r\n    \r\n      const hexStr = str.substring(ix + 1, ix + 7);\r\n      let sloc = parseInt(hexStr, 16);\r\n\r\n      if(isNaN(sloc)) break;\r\n    \r\n      const addrs = new Address((sloc >> 16) & 0xFF, sloc & 0xFFFF, this._blockReader._root.config.memoryMode);\r\n      if (addrs.isROM) {\r\n        sloc = addrs.toLocation();\r\n        this._blockReader.resolveInclude(sloc, false);\r\n        const name = this._blockReader._referenceManager.resolveName(sloc, AddressType.Unknown, false, this._blockReader._currentChunk!);\r\n        const opix = indexOfAny(name, RomProcessingConstants.OPERATORS);\r\n        \r\n        if (opix > 0) {\r\n          const offsetStr = name.substring(opix + 1);\r\n          let offset: number;\r\n          \r\n          if (offsetStr === 'M') {\r\n            offset = this._blockReader._referenceManager.markerTable.get(sloc) || 0;\r\n          } else {\r\n            offset = parseInt(offsetStr, 16) || 0;\r\n          }\r\n\r\n          if (name[opix] === '-') {\r\n            offset = -offset;\r\n          }\r\n\r\n          const targetName = name.substring(0, opix);\r\n          const target = sloc - offset;\r\n          \r\n          // Try to find the target using IsOutside pattern\r\n          const [isOutside, block, part] = ChunkFileUtils.isOutsideWithPart(this._blockReader._enrichedChunks, this._blockReader._currentChunk!, sloc);\r\n          if (part != null) {\r\n            const entry = part.objList?.find((x): x is TableEntry => \r\n              typeof x === 'object' && x !== null && 'location' in x && 'object' in x && (x as TableEntry).location === target) as TableEntry | undefined;\r\n            if (entry && entry.object) {\r\n              (entry.object as StringWrapper).marker = offset;\r\n            }\r\n          }\r\n        }\r\n      }\r\n      \r\n      ix = indexOfAny(str, StringReader.STRING_REFERENCE_CHARACTERS, ix + 7);\r\n    }\r\n  }\r\n\r\n}","import { Op } from '../../types/assembly';\r\nimport { Registers } from '../../assembly';\r\nimport { RomDataReader } from './reader';\r\nimport { StringReader } from './strings';\r\nimport { ReferenceManager } from './references';\r\nimport {\r\n  Address,\r\n  AddressSpace,\r\n  AddressType,\r\n  ChunkFileUtils,\r\n  LocationWrapper,\r\n  MemberType,\r\n  StructDef,\r\n  Byte,\r\n  Word, \r\n  CpuMode,\r\n} from '../../types';\r\nimport type { DbStringType } from '../../database';\r\nimport type { BlockReader } from './blocks';\r\n\r\n/**\r\n * Handles parsing of different data types from ROM\r\n * Converted from GaiaLib/Rom/Extraction/TypeParser.cs\r\n */\r\nexport class TypeParser {\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _romDataReader: RomDataReader;\r\n  private readonly _stringReader: StringReader;\r\n  private readonly _stringTypes: Record<string, DbStringType>;\r\n  private readonly _referenceManager: ReferenceManager;\r\n\r\n  constructor(blockReader: BlockReader) {\r\n    this._blockReader = blockReader;\r\n    this._referenceManager = blockReader._referenceManager;\r\n    this._romDataReader = blockReader._romDataReader;\r\n    this._stringReader = blockReader._stringReader;\r\n    this._stringTypes = blockReader._root.stringTypes;\r\n  }\r\n\r\n  public parseType(typeName: string, reg: Registers | null, depth: number, bank?: number, single?: boolean): unknown {\r\n    \r\n    const objects: unknown[] = [];\r\n    const arrayIx = typeName.indexOf('[');\r\n    const arrayCount = arrayIx !== -1 ? parseInt(typeName.substring(arrayIx + 1, typeName.length - 1), 16) : 0;\r\n    const arrayTypeName = arrayIx !== -1 ? typeName.substring(0, arrayIx) : typeName;\r\n    \r\n    if(arrayCount > 0) {\r\n      for(let i = 0; i < arrayCount; i++) {\r\n        objects.push(this.parseType(arrayTypeName, reg, depth + 1, bank, true));\r\n      }\r\n      return objects;\r\n    }\r\n    \r\n    const isSoft = arrayTypeName[0] === '~';\r\n    let realTypeName = isSoft ? arrayTypeName.substring(1) : arrayTypeName;\r\n    \r\n    const isRaw = realTypeName[realTypeName.length - 1] === '!';\r\n    if(isRaw) realTypeName = realTypeName.substring(0, realTypeName.length - 1);\r\n\r\n    const fixedIx = realTypeName.indexOf('(');\r\n    const fixedSize = fixedIx !== -1 ? parseInt(realTypeName.substring(fixedIx + 1, realTypeName.length - 1), 16) : 0;\r\n    let fixedTypeName = fixedIx !== -1 ? realTypeName.substring(0, fixedIx) : realTypeName;\r\n\r\n    const stringType = this._stringTypes[fixedTypeName];\r\n    \r\n    if (stringType) return this._stringReader.parseString(stringType, fixedSize, isRaw);\r\n\r\n    const addrType = Address.typeFromCode(fixedTypeName[0]);\r\n    const isPtr = addrType !== AddressType.Unknown;\r\n\r\n    // Parse raw values\r\n    let mType = isPtr ? addrType : TypeParser.tryParseMemberType(fixedTypeName);\r\n    if (mType !== null) {\r\n      fixedTypeName = isPtr ? fixedTypeName.substring(1) : '';\r\n      const transform = this._blockReader._transformProcessor.getTransform();\r\n      let result: any;\r\n      if (mType === MemberType.Offset && transform !== undefined) mType = MemberType.Word;\r\n\r\n      switch (mType) {\r\n        case MemberType.Byte: result = new Byte(this._romDataReader.readByte()); break;\r\n        case MemberType.Word: result = new Word(this.parseWordSafe()); break;\r\n        case MemberType.Offset:\r\n          const bankIx = fixedTypeName.indexOf('$');\r\n          if(bankIx !== -1) {\r\n            if(fixedTypeName[bankIx + 1] === '$') bank = reg?.value['dataBank'];\r\n            else bank = parseInt(fixedTypeName.substring(bankIx + 1, fixedTypeName.length), 16);\r\n            fixedTypeName = fixedTypeName.substring(0, bankIx);\r\n          }\r\n          return this.parseLocation(this._romDataReader.readUShort(), bank, AddressType.Offset, fixedTypeName, isSoft);\r\n        case MemberType.Address:\r\n        case MemberType.Location:\r\n        case MemberType.OddLocation:\r\n          return this.parseLocation(this._romDataReader.readUShort(), this._romDataReader.readByte(), mType as unknown as AddressType, fixedTypeName, isSoft);\r\n        case MemberType.Binary:\r\n          return this.parseBinary(fixedSize);\r\n        case MemberType.Code:\r\n        case MemberType.Branch:\r\n          return this.parseCode(reg!);\r\n        default:\r\n          throw new Error('Invalid member type');\r\n      }\r\n      return this._blockReader._transformProcessor.applyTransform(transform, result);\r\n    }\r\n\r\n    const parentType = this._blockReader._root.structs[fixedTypeName.replaceAll('-', '_').replaceAll(' ', '_').toLowerCase()];\r\n    if (!parentType) {\r\n      throw new Error(`Unknown type: ${fixedTypeName}`);\r\n    }\r\n\r\n    const delimiter = parentType.delimiter;\r\n    const discOffset = parentType.discriminator;\r\n    const discLogic = parentType.discriminatorLogic ?? '=';\r\n    const discSize = parentType.discriminatorSize ?? 1;\r\n    const nullValue = parentType.null;\r\n\r\n    if(delimiter === undefined && this._blockReader.delimiterReached(nullValue)) {\r\n      objects.push({ name: parentType.name, parts: [ \"null\" ]})\r\n      return objects;\r\n    }\r\n\r\n    // Continue to iterate until end or delimiter is reached\r\n    let delReached: boolean;\r\n    while (!(delReached = this._blockReader.delimiterReached(delimiter))) {\r\n      const startPosition = this._romDataReader.position;\r\n      let targetType = parentType;\r\n\r\n      if(this._blockReader.delimiterReached(nullValue)) {\r\n        objects.push({ name: parentType.name, parts: [ \"null\" ]})\r\n      } else {        \r\n        // If a discriminator offset is present, use it to identify the type\r\n        if (discOffset !== undefined) {\r\n          // Get discriminator position in ROM\r\n          const discPosition = this._romDataReader.position + discOffset;\r\n\r\n          // Get discriminator value\r\n          const disc = this._romDataReader.romData[discPosition];\r\n          const disc16 = this._romDataReader.romData[discPosition + 1] << 8 | disc;\r\n\r\n          // Match discriminator to type\r\n          const matchedStruct = Object.values(this._blockReader._root.structs).find(x => {\r\n            if (x.parent !== fixedTypeName || x.discriminator === undefined) return false;\r\n            const size = x.discriminatorSize ?? discSize;\r\n            const value = size > 1 || x.discriminator > 255 ? disc16 : disc;\r\n            const logic = x.discriminatorLogic ?? discLogic;\r\n            if(logic === '&') return (x.discriminator & value) !== 0;\r\n            return x.discriminator === value;\r\n          });\r\n          targetType = matchedStruct || parentType; // Default to parent if no match is found\r\n          \r\n          const logic = targetType.discriminatorLogic ?? discLogic;\r\n\r\n          // Advance position (hide value) if discriminator is first\r\n          if (discOffset === 0 && parentType != targetType && logic === '=') {\r\n            this._romDataReader.position++;\r\n            if((targetType.discriminatorSize ?? discSize) > 1 || targetType.discriminator! >= 256) this._romDataReader.position++;\r\n          }\r\n        }\r\n\r\n        const types = targetType.types;\r\n        if (types) {\r\n          const memberCount = types.length;\r\n          const prevPosition = this._romDataReader.position;\r\n          const parts = new Array(memberCount); // Create new member collection\r\n          const def: StructDef = { name: targetType.name, parts, location: prevPosition };\r\n\r\n          let partLocation = prevPosition;\r\n\r\n          // Parse each member of the struct\r\n          for (let i = 0; i < memberCount; i++) {\r\n            //const transform = this._blockReader._transformProcessor.getTransform();\r\n            //if(transform !== null) debugger;\r\n            parts[i] = this.parseType(types[i], reg, depth + 1, bank, false);\r\n            //this._blockReader._transformProcessor.applyTransform(transform, i, parts);\r\n          }\r\n\r\n          // Advance (hide) discriminator if it is the last member\r\n          if (discOffset !== undefined \r\n            && discOffset === this._romDataReader.position - prevPosition\r\n            && targetType.discriminator !== undefined\r\n            && discLogic === '='\r\n            && types?.length > 0) {\r\n            this._romDataReader.position++;\r\n            if((targetType.discriminatorSize ?? discSize) > 1 || targetType.discriminator >= 256) this._romDataReader.position++;\r\n          }\r\n\r\n          if(targetType.tail !== undefined) {\r\n            this._romDataReader.position += targetType.tail;\r\n          }\r\n\r\n          objects.push(def);\r\n        } else {\r\n          this._romDataReader.position++;\r\n        }\r\n      }\r\n      \r\n      // Roll back work if struct overflows a chunk boundary\r\n      // SHOULD only happen for the inventory sprite map\r\n      let checkPosition = startPosition;\r\n      while (++checkPosition < this._romDataReader.position) {\r\n        const struct = this._referenceManager.tryGetStruct(checkPosition)\r\n        if (struct.found && struct.chunkType !== \"Code\" && struct.chunkType !== \"Branch\") {\r\n          this._romDataReader.position = checkPosition;\r\n          break;\r\n        }\r\n      }\r\n\r\n      // Stop if the reader should not continue\r\n      if (!this._blockReader.partCanContinue()) break;\r\n      if (nullValue !== undefined) break;\r\n      if(single) break;\r\n    }\r\n\r\n    // If we have reached delimiter and at depth 0, note the struct\r\n    if (delReached && depth === 0) {\r\n      this._referenceManager.tryAddStruct(this._romDataReader.position, typeName);\r\n    }\r\n\r\n    if(single) return objects[0];\r\n    else return objects;\r\n  }\r\n\r\n  public static tryParseMemberType(memberTypeName: string): MemberType | null {\r\n    // Check if the string matches any MemberType enum value (case-insensitive)\r\n    const upperName = memberTypeName.toUpperCase();\r\n    for (const [key, value] of Object.entries(MemberType)) {\r\n      if (key.toUpperCase() === upperName) {\r\n        return value;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private parseWordSafe(): number {\r\n    return this._referenceManager.containsStruct(this._romDataReader.position + 1)\r\n      ? this._romDataReader.readByte()\r\n      : this._romDataReader.readUShort();\r\n  }\r\n\r\n  private parseBinary(size: number): Uint8Array {\r\n    // Store old position for length calculation\r\n    const startPosition = this._romDataReader.position;\r\n\r\n    //Calculate length if it is not provided\r\n    let len = 0;\r\n\r\n    // Advance the reader until we reach the end of the section\r\n    do {\r\n      this._romDataReader.position++;\r\n      len++;\r\n    } while (len !== size && this._blockReader.partCanContinue());\r\n\r\n    // Create buffer for the raw bytes\r\n    const outBuffer = new Uint8Array(len);\r\n\r\n    // Copy raw bytes from ROM to buffer\r\n    for (let i = 0; i < len; i++) {\r\n      outBuffer[i] = this._romDataReader.romData[startPosition + i];\r\n    }\r\n\r\n    return outBuffer;\r\n  }\r\n\r\n  private parseLocation(offset: number, bank: number | undefined, addrType: AddressType, typeName?: string, isSoft?: boolean): unknown {\r\n    // If bank is not provided and offset is 0, it should resolve to #$0000\r\n    if ((bank === undefined || bank === null) && (offset === 0 || offset === 0xFFFF)) {\r\n      return new Word(offset);\r\n    }\r\n\r\n    const hasOffset = this._romDataReader.offset !== undefined;\r\n\r\n    if(hasOffset) offset -= this._romDataReader.offset!;\r\n\r\n    let adrs: Address;\r\n    let loc: number;\r\n    if(addrType === AddressType.Location || hasOffset) {\r\n      loc = offset | (bank! << 16);\r\n      if(hasOffset && !this._blockReader._currentChunk!.compressed) loc += this._blockReader._currentChunk!.location;\r\n      //adrs = Address.fromInt(loc, this._blockReader._root.config.memoryMode);\r\n    } else {\r\n      if(addrType === AddressType.OddLocation) {\r\n        const bankFlag = this._blockReader._root.config.cpuMode === CpuMode.Fast ? Address.FAST_BANK_FLAG : 0;\r\n        const bankReal = this._romDataReader.position >> 16;\r\n        const isVeryOdd = bankReal !== this._blockReader._root.config.oddLocationBase;\r\n        const bankSpan = this._blockReader._root.config.oddLocationSpan ?? (this._romDataReader.romData.length >> 16);\r\n\r\n        let oddBank = bank! << 1 | (offset & 0x8000 ? 1 : 0);\r\n        offset &= 0x7FFF;\r\n\r\n        oddBank += bankReal;\r\n\r\n        if(oddBank >= bankSpan) {\r\n          oddBank += Address.DATA_BANK_FLAG - bankSpan; \r\n        } else if(isVeryOdd) {\r\n          oddBank |= Address.DATA_BANK_FLAG;\r\n        } else {\r\n          offset |= 0x8000;\r\n        }\r\n\r\n        bank = oddBank & 0x7F | bankFlag;\r\n      }\r\n      // Bank cannot be null, instead use bank from current position\r\n      const resolvedBank = bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode);\r\n  \r\n      // Create the address with resolved bank\r\n      adrs = new Address(resolvedBank, offset, this._blockReader._root.config.memoryMode, addrType === AddressType.Offset);\r\n  \r\n      // If we have a system address, keep it as is\r\n      if (!adrs.isROM) return adrs;\r\n  \r\n      // Convert address to ROM location\r\n      loc = adrs.toLocation();\r\n    }\r\n\r\n\r\n    // If the location is inside the current block and there is no rewrite for it...\r\n    if (\r\n      //this._blockReader._currentChunk &&\r\n      //ChunkFileUtils.isInside(this._blockReader._currentChunk, loc) &&\r\n      typeName && \r\n      (hasOffset || !this._blockReader._root.rewrites[loc])\r\n    ) {\r\n      // Normalize the type name to default to current part definition\r\n      //const resolvedTypeName = typeName ?? this._blockReader._currentAsmBlock!.structName ?? 'Binary';\r\n\r\n      // Add the struct type to our chunk table if it is not already present\r\n      this._referenceManager.tryAddStruct(loc, isSoft ? \"~\" + typeName : typeName);\r\n      //if(!oldStruct || oldStruct === 'Branch') this._referenceManager.structTable.set(loc, typeName);\r\n\r\n      //const resolvedTypeName = typeName[0] === '~' ? typeName.substring(1) : typeName;\r\n      // If the location is not already in the reference table, add it\r\n      //const referenceName = `${resolvedTypeName.toLowerCase()}_${adrs.toString()}`;\r\n      const referenceName = `${typeName.replaceAll('-', '_').toLowerCase()}_${loc.toString(16).toUpperCase().padStart(6, '0')}`;\r\n      this._referenceManager.tryAddName(loc, isSoft ? \"~\" + referenceName : referenceName);\r\n    }\r\n\r\n    return new LocationWrapper(loc, addrType);\r\n  }\r\n\r\n  private parseCode(reg: Registers): Op[] {\r\n    // Output list\r\n    const opList: Op[] = [];\r\n\r\n    let first = true;\r\n    while (this._romDataReader.position < this._blockReader._partEnd) {\r\n      // Check the chunk table for a new type block, but not on the first iteration\r\n      if (first) {\r\n        first = false;\r\n      } else {\r\n        const struct = this._referenceManager.tryGetStruct(this._romDataReader.position);\r\n        if (struct.found && struct.chunkType !== \"Branch\") break;\r\n      }\r\n\r\n      // Process register adjustments before parse\r\n      if (reg) {\r\n        this._blockReader.hydrateRegisters(reg);\r\n      }\r\n\r\n      // Parse instruction\r\n      const op = this._blockReader._asmReader.parseAsm(reg);\r\n\r\n      // Add instruction to list\r\n      opList.push(op);\r\n    }\r\n\r\n    return opList;\r\n  }\r\n} ","import { OpCode } from '../../database';\r\nimport { Op } from '../../types/assembly';\r\n\r\nimport { Registers } from '../../assembly';\r\nimport { RomDataReader } from './reader';\r\nimport { TransformProcessor } from './transforms';\r\nimport { AddressingModeHandler, OperationContext } from './addressing';\r\nimport type { BlockReader } from './blocks';\r\nimport { StatusFlags } from '../../types/processor';\r\n\r\n/**\r\n * Parses assembly instructions from ROM data, handling different addressing modes\r\n * and maintaining CPU register state during analysis.\r\n * Converted from GaiaLib/Rom/Extraction/AsmReader.cs\r\n */\r\nexport class AsmReader {\r\n  // Constants\r\n  private static readonly STATUS_OP_MASK = 0xDF;\r\n  private static readonly STATUS_OP_VALUE = 0xC2;\r\n  private static readonly ACCUMULATOR_OP_MASK = 0xF;\r\n  private static readonly ACCUMULATOR_OP_VALUE = 0x9;\r\n  public static readonly VARIABLE_SIZE_INDICATOR = -2;\r\n  // private static readonly TWO_BYTES_SIZE = 2;\r\n  // private static readonly THREE_BYTES_SIZE = 3;\r\n\r\n  private readonly _blockReader: BlockReader;\r\n  private readonly _transformProcessor: TransformProcessor;\r\n  private readonly _addressingModeHandler: AddressingModeHandler;\r\n  private readonly _romDataReader: RomDataReader;\r\n\r\n  constructor(blockReader: BlockReader) {\r\n    this._blockReader = blockReader;\r\n    this._transformProcessor = blockReader._transformProcessor;\r\n    this._addressingModeHandler = new AddressingModeHandler(blockReader, this._transformProcessor);\r\n    this._romDataReader = blockReader._romDataReader;\r\n  }\r\n\r\n  public parseAsm(reg: Registers): Op {\r\n    const opStart = this._romDataReader.position;\r\n    const opCode = this._romDataReader.readByte();\r\n\r\n    // Find matching OpCode in the database\r\n    const code = this._blockReader._root.opCodes[opCode];\r\n    if (!code) {\r\n      throw new Error('Unknown OpCode');\r\n    }\r\n\r\n    // Initialize operation context\r\n    const operationContext = this.initializeOperation(code, reg, opStart);\r\n\r\n    // Process operands based on the addressing mode\r\n    const operands = this._addressingModeHandler.processAddressingMode(code, operationContext, reg);\r\n    \r\n    // Apply label transforms to operands after processing. This ensures that the ROM state is processed and valid.\r\n    this._transformProcessor.applyTransforms(operationContext.xForm1, operationContext.xForm2, operands);\r\n\r\n    const op = new Op(\r\n      code,\r\n      opStart,\r\n      operands,\r\n      this._romDataReader.position - opStart\r\n    );\r\n\r\n    if (operationContext.copDef) {\r\n      op.copDef = operationContext.copDef;\r\n    }\r\n\r\n    return op;\r\n  }\r\n\r\n  public clearDestinationRegister(code: OpCode, reg: Registers): void {\r\n    switch (code.mnem) {\r\n      case 'LDA':\r\n        delete reg.value['accumulator'];\r\n        break;\r\n      case 'LDX':\r\n        delete reg.value['xIndex'];\r\n        break;\r\n      case 'LDY':\r\n        delete reg.value['yIndex'];\r\n        break;\r\n    }\r\n  }\r\n\r\n  private initializeOperation(code: OpCode, reg: Registers, loc: number): OperationContext {\r\n    // Calculate instruction size (some are variable)\r\n    const size = this.calculateInstructionSize(code, reg);\r\n\r\n    // Calculate next address (for branching)\r\n    const next = loc + size;\r\n\r\n    // Clear destination register for load operations. This resets the register state\r\n    this.clearDestinationRegister(code, reg);\r\n\r\n    const context = new OperationContext();\r\n    context.size = size;\r\n    context.nextAddress = next;\r\n    context.xForm1 = this._transformProcessor.getTransform();\r\n    //context.xForm2 = null;\r\n    context.copDef = null;\r\n\r\n    return context;\r\n  }\r\n\r\n  private calculateInstructionSize(code: OpCode, reg: Registers): number {\r\n    const addrMode = this._blockReader._root.addrLookup[code.mode];\r\n    let size = addrMode.size;\r\n    \r\n    if (size === AsmReader.VARIABLE_SIZE_INDICATOR || code.mode === 'Immediate') {\r\n      if((code.code & AsmReader.STATUS_OP_MASK) === AsmReader.STATUS_OP_VALUE){\r\n        size = 2; //SEP REP are 2 bytes\r\n      } else if ((code.code & AsmReader.ACCUMULATOR_OP_MASK) === AsmReader.ACCUMULATOR_OP_VALUE) {\r\n        size = ((reg.value['statusFlags'] & StatusFlags.AccumulatorMode) === StatusFlags.AccumulatorMode) ? 2 : 3;\r\n      } else {\r\n        size = ((reg.value['statusFlags'] & StatusFlags.IndexMode) === StatusFlags.IndexMode) ? 2 : 3;\r\n      }\r\n    }\r\n    \r\n    return size;\r\n  }\r\n} ","/**\r\n * Represents the stack for the 65816 processor\r\n */\r\nexport class Stack {\r\n  public bytes: Uint8Array;\r\n  public location: number;\r\n\r\n  constructor() {\r\n    this.bytes = new Uint8Array(70);\r\n    this.location = 10;\r\n  }\r\n\r\n  /**\r\n   * Push a byte onto the stack\r\n   */\r\n  public push(value: number): void {\r\n    this.bytes[this.location++] = value & 0xFF;\r\n  }\r\n\r\n  /**\r\n   * Push a 16-bit value onto the stack (little-endian)\r\n   */\r\n  public pushUInt16(value: number): void {\r\n    this.bytes[this.location++] = value & 0xFF;\r\n    this.bytes[this.location++] = (value >> 8) & 0xFF;\r\n  }\r\n\r\n  /**\r\n   * Pop a byte from the stack\r\n   */\r\n  public popByte(): number {\r\n    return this.bytes[--this.location];\r\n  }\r\n\r\n  /**\r\n   * Pop a 16-bit value from the stack (little-endian)\r\n   */\r\n  public popUInt16(): number {\r\n    const high = this.bytes[--this.location];\r\n    const low = this.bytes[--this.location];\r\n    return (high << 8) | low;\r\n  }\r\n\r\n  /**\r\n   * Reset the stack to initial state\r\n   */\r\n  public reset(): void {\r\n    this.bytes.fill(0);\r\n    this.location = 10;\r\n  }\r\n} ","import { StatusFlags } from '../types';\r\nimport { Stack } from './Stack';\r\nimport { MemoryMapMode } from '../types';\r\n\r\n/**\r\n * Manages the 65816 processor registers and status flags\r\n */\r\nexport class Registers {\r\n  // public accumulatorFlag?: boolean;\r\n  // public indexFlag?: boolean;\r\n  // public direct?: number;\r\n  // public dataBank?: number;\r\n  // public accumulator?: number;\r\n  // public xIndex?: number;\r\n  // public yIndex?: number;\r\n  public value: Record<string, number>;\r\n  public stack: Stack;\r\n  public mode: MemoryMapMode;\r\n\r\n  constructor(mode: MemoryMapMode) {\r\n    this.value = {};\r\n    this.stack = new Stack();\r\n    this.mode = mode;\r\n  }\r\n\r\n  /**\r\n   * Get the current status flags\r\n   */\r\n  // public get statusFlags(): StatusFlags {\r\n  //   let flags = 0;\r\n  //   if (this.accumulatorFlag ?? false) {\r\n  //     flags |= StatusFlags.AccumulatorMode;\r\n  //   }\r\n  //   if (this.indexFlag ?? false) {\r\n  //     flags |= StatusFlags.IndexMode;\r\n  //   }\r\n  //   return flags;\r\n  // }\r\n\r\n  // /**\r\n  //  * Set the status flags\r\n  //  */\r\n  // public set statusFlags(value: StatusFlags) {\r\n  //   this.accumulatorFlag = (value & StatusFlags.AccumulatorMode) !== 0;\r\n  //   this.indexFlag = (value & StatusFlags.IndexMode) !== 0;\r\n  // }\r\n\r\n  /**\r\n   * Reset all registers to initial state\r\n   */\r\n  // public reset(): void {\r\n  //   this.accumulatorFlag = undefined;\r\n  //   this.indexFlag = undefined;\r\n  //   this.direct = undefined;\r\n  //   this.dataBank = undefined;\r\n  //   this.accumulator = undefined;\r\n  //   this.xIndex = undefined;\r\n  //   this.yIndex = undefined;\r\n  //   this.stack.reset();\r\n  // }\r\n} ","import { Registers } from '../../assembly';\r\nimport { Op } from '../../types/assembly';\r\nimport { RomDataReader } from './reader';\r\nimport { ProcessorStateManager } from './processor';\r\nimport { ReferenceManager } from './references';\r\nimport { StringReader } from './strings';\r\nimport { AsmReader } from './asm';\r\nimport { TypeParser } from './parser';\r\nimport { \r\n  Address, \r\n  LocationWrapper, \r\n  StructDef, \r\n  BlockReaderConstants,\r\n  RomProcessingConstants,\r\n  TableEntry,\r\n  BinType,\r\n  AsmBlock,\r\n  StatusFlags,\r\n} from '../../types';\r\nimport type { StringWrapper } from '../../types';\r\nimport type { DbRoot } from '../../database';\r\nimport { ChunkFile, ChunkFileUtils } from '../../types/files';\r\nimport { indexOfAny } from '../../utils';\r\nimport { TransformProcessor } from './transforms';\r\n\r\n/**\r\n * Central class for reading and analyzing ROM blocks\r\n * Converted from GaiaLib/Rom/Extraction/BlockReader.cs\r\n */\r\nexport class BlockReader {\r\n  // Constants\r\n  private static readonly REF_SEARCH_MAX_RANGE = 0x1A0;\r\n  private static readonly BANK_MASK_CHECK = 0x40;\r\n  private static readonly BYTE_DELIMITER_THRESHOLD = 0x100;\r\n  private static readonly BANK_HIGH_MEMORY_1 = 0x7E;\r\n  private static readonly BANK_HIGH_MEMORY_2 = 0x7F;\r\n  private static readonly POINTER_CHARACTERS = ['&', '@'];\r\n\r\n  // Location regex pattern: _([A-Fa-f0-9]{6})\r\n  private static readonly LOCATION_REGEX = /_([A-Fa-f0-9]{6})/;\r\n\r\n  // Core Dependencies\r\n  public readonly _root: DbRoot;\r\n  public readonly _stringReader: StringReader;\r\n  public readonly _asmReader: AsmReader;\r\n  public _typeParser: TypeParser;\r\n  public _romDataReader: RomDataReader;\r\n  public readonly _stateManager: ProcessorStateManager;\r\n  public _referenceManager: ReferenceManager;\r\n  public _transformProcessor: TransformProcessor;\r\n\r\n  // Current Processing State (Database)\r\n  //public _currentBlock!: DbBlock;\r\n  //public _currentPart: DbPart | null = null;\r\n  public _partEnd: number = 0;\r\n  \r\n  // ChunkFile Processing State\r\n  public _currentChunk: ChunkFile | null = null;\r\n  public _currentAsmBlock: AsmBlock | null = null;\r\n  public _enrichedChunks: ChunkFile[] = [];\r\n\r\n  constructor(romData: Uint8Array, root: DbRoot) {\r\n    this._root = root;\r\n    this._romDataReader = new RomDataReader(romData);\r\n    this._stateManager = new ProcessorStateManager();\r\n    this._referenceManager = new ReferenceManager(root);\r\n    this._transformProcessor = new TransformProcessor(this);\r\n\r\n    this._stringReader = new StringReader(this as any);\r\n    this._asmReader = new AsmReader(this as any);\r\n    this._typeParser = new TypeParser(this as any);\r\n  }\r\n\r\n  /**\r\n   * Processes predefined overrides for registers and bank notes\r\n   */\r\n  private initializeOverrides(): void {\r\n    for (const [location, overrides] of Object.entries(this._root.overrides)) {\r\n      for (const [register, value] of Object.entries(overrides)) {\r\n        switch (register) {\r\n          case 'M':\r\n            this._stateManager.get('statusFlags').setFlag(parseInt(location), StatusFlags.AccumulatorMode, value === 1);\r\n            break;\r\n          case 'X':\r\n            this._stateManager.get('statusFlags').setFlag(parseInt(location), StatusFlags.IndexMode, value === 1);\r\n            break;\r\n          case 'B':\r\n            this._stateManager.get('dataBank').set(parseInt(location), value);\r\n            break;\r\n          case 'type':\r\n            this._referenceManager.tryAddStruct(parseInt(location), value);\r\n            break;\r\n          case 'name':\r\n            this._referenceManager.tryAddName(parseInt(location), value);\r\n            break;\r\n        }\r\n      }\r\n    }\r\n    for (const [location, value] of Object.entries(this._root.names)) {\r\n      this._referenceManager.tryAddName(parseInt(location), value);\r\n    }\r\n    for (const [location, value] of Object.entries(this._root.types)) {\r\n      this._referenceManager.tryAddStruct(parseInt(location), value);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Processes predefined file references\r\n   */\r\n  // private initializeFileReferences(): void {\r\n  //   for (const file of this._root.files) {\r\n  //     this._referenceManager.tryAddName(file.start, file.name);\r\n  //   }\r\n  // }\r\n\r\n  /**\r\n   * Resolves mnemonic for a given address\r\n   */\r\n  public resolveMnemonic(addr: Address, emitAll: boolean): void {\r\n    let offset = 0;\r\n    const isWram = addr.bank === 0x7E || addr.bank === 0x7F;\r\n\r\n    if (isWram) {\r\n      if (!addr.isShort && !emitAll) return;\r\n      offset = addr.toInt();\r\n    }\r\n    else if (!addr.isCodeBank || addr.offset >= 0x8000) return;\r\n    else if (addr.isShort && !emitAll) return;\r\n    else offset = addr.offset;\r\n    \r\n    let label = this._root.mnemonics[offset];\r\n    if (!label) return;\r\n\r\n    const ix = indexOfAny(label, RomProcessingConstants.OPERATORS);\r\n    if (ix >= 0) {\r\n      let opnd = parseInt(label.substring(ix + 1), 16);\r\n      if(label[ix] === '-')\r\n        opnd = -opnd;\r\n      \r\n      offset -= opnd;\r\n\r\n      label = label.substring(0, ix);\r\n    }\r\n\r\n    if (isWram && addr.isShort) {\r\n      this._currentChunk!.mnemonics[`S_${label}`] = (offset & 0xFFFF).toString(16).toUpperCase().padStart(4, '0');\r\n      return;\r\n    }\r\n\r\n    if (!isWram && !addr.isShort) {\r\n      this._currentChunk!.mnemonics[`L_${label}`] = (addr.bank << 16 | offset).toString(16).toUpperCase().padStart(6, '0');\r\n      return;\r\n    }\r\n\r\n    this._currentChunk!.mnemonics[label] = offset.toString(16).toUpperCase().padStart(offset <= 0xFF ? 2 : offset <= 0xFFFF ? 4 : 6, '0');\r\n  }\r\n\r\n  /**\r\n   * Resolves name for a location (delegated to ReferenceManager)\r\n   */\r\n  // public resolveName(location: number, type: AddressType, isBranch: boolean): string {\r\n  //   return this._referenceManager.resolveName(location, type, isBranch);\r\n  // }\r\n\r\n  /**\r\n   * Resolves include for a location\r\n   */\r\n  public resolveInclude(loc: number, isBranch: boolean): void {\r\n    const rewrite = this._currentChunk?.compressed ? undefined : this._root.rewrites[loc];\r\n    const adjLoc = rewrite ?? loc;\r\n\r\n    const [outside, foundBlock, foundPart] = ChunkFileUtils.isOutsideWithPart(this._enrichedChunks, this._currentChunk!, adjLoc);\r\n    \r\n    if (foundPart && rewrite) {\r\n      const name = BlockReaderConstants.POINTER_CHARACTERS.includes(foundPart.structName![0]) ? foundPart.structName!.substring(1) : foundPart.structName!;\r\n      if (this._root.stringTypes[name]) {\r\n        this._referenceManager.markerTable.set(loc, loc - rewrite);\r\n        this._referenceManager.markerTable.set(rewrite, loc - rewrite);\r\n      }\r\n    }\r\n\r\n    if (outside && foundBlock && foundPart) {\r\n      //if(foundBlock.location === loc) return; //Defer to direct file references\r\n      //if(foundBlock.parts?.length === 1 && foundBlock.location === loc) return;\r\n      this._currentAsmBlock!.includes!.add({block: foundBlock, part: foundPart});\r\n    } else if (isBranch && !this._referenceManager.tryGetName(adjLoc).found) {\r\n      // const adrs = Address.fromInt(loc, this._root.config.memoryMode);\r\n      // const name = `loc_${adrs.toString()}`;\r\n      const name = `loc_${adjLoc.toString(16).toUpperCase().padStart(6, '0')}`;\r\n      this._referenceManager.tryAddName(adjLoc, name);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Notes a type at a location and manages chunk references\r\n   */\r\n  public noteType(loc: number, type: string, silent: boolean = false, reg?: Registers): string {\r\n    const typeName = RomProcessingConstants.stripMarkers(type);\r\n    //const isSoft = type[0] === '~';\r\n    //const isRaw = type[type.length - 1] === '!';\r\n    if(!this._referenceManager.tryAddStruct(loc, type) && typeName.name === 'Branch') return this._referenceManager.tryGetName(loc).referenceName ?? '';\r\n    //if(!oldStruct || oldStruct === 'Branch') this._referenceManager.structTable.set(loc, type);\r\n\r\n    const nameResult = this._referenceManager.tryGetName(loc);\r\n    let name: string;\r\n    \r\n    if (!nameResult.found || nameResult.isSoft) {\r\n      name = this._referenceManager.createTypeName(type, loc);\r\n      this._referenceManager.tryAddName(loc, `${typeName.isSoft ? \"~\" : \"\"}${name}`);\r\n    } else {\r\n      name = nameResult.referenceName!;\r\n    }\r\n\r\n    if (!silent && type === BlockReaderConstants.CODE_TYPE && reg) {\r\n      this.updateRegisterState(loc, reg);\r\n    }\r\n\r\n    return name;\r\n  }\r\n\r\n  public updateRegisterState(loc: number, reg: Registers): void {\r\n    for (const [key, value] of Object.entries(reg.value)) {\r\n      if (value === undefined || value === null) continue;\r\n      this._stateManager.get(key).tryAdd(loc, value);\r\n    }\r\n    // if (reg.accumulatorFlag !== undefined) {\r\n    //   this._stateManager.tryAddAccumulatorFlag(loc, reg.accumulatorFlag);\r\n    // }\r\n    // if (reg.indexFlag !== undefined) {\r\n    //   this._stateManager.tryAddIndexFlag(loc, reg.indexFlag);\r\n    // }\r\n    if (reg.stack.location > 0) {\r\n      this._stateManager.tryAddStackPosition(loc, reg.stack.location);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Checks if a delimiter has been reached\r\n   */\r\n  public delimiterReached(delimiter?: number): boolean {\r\n    if (delimiter === undefined) {\r\n      return false;\r\n    }\r\n\r\n    if (delimiter >= BlockReaderConstants.BYTE_DELIMITER_THRESHOLD) {\r\n      if (this._romDataReader.peekShort() === delimiter) {\r\n        this._romDataReader.position += 2;\r\n        return true;\r\n      }\r\n    } else if (this._romDataReader.peekByte() === delimiter) {\r\n      this._romDataReader.position++;\r\n      return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Checks if processing of the current part can continue\r\n   */\r\n  public partCanContinue(): boolean {\r\n    return this._romDataReader.position < this._partEnd && \r\n           !this._referenceManager.containsStruct(this._romDataReader.position);\r\n  }\r\n\r\n  public analyzeAndResolve(): ChunkFile[] {\r\n    console.log('analyzeAndResolve started');\r\n    this.initializeOverrides();\r\n    //this.initializeFileReferences();\r\n    this.createChunkFilesFromDatabase();\r\n    this.initializeBlocksAndParts();\r\n    this.analyzeChunkFiles();\r\n    this.resolveReferences();\r\n    console.log('analyzeAndResolve complete');\r\n    \r\n    return this._enrichedChunks;\r\n  }\r\n\r\n  /**\r\n   * Analyzes all blocks in the ROM\r\n   */\r\n  // private analyzeBlocks(): void {\r\n  //   this.initializeBlocksAndParts();\r\n\r\n  //   for (const chunk of this._enrichedChunks) {\r\n  //     this._currentChunk = chunk;\r\n  //     for (const part of chunk.parts || []) {\r\n  //       this.processPart(part);\r\n  //     }\r\n  //   }\r\n  // }\r\n\r\n  /**\r\n   * Initializes blocks and parts with base references\r\n   */\r\n  private initializeBlocksAndParts(): void {\r\n    console.log('initializeBlocksAndParts');\r\n    for (const block of this._enrichedChunks) {\r\n      this._referenceManager.fileTable.set(block.location, block.name);\r\n      for (const part of block.parts || []) {\r\n        if(part.structName) {\r\n          this._referenceManager.tryAddStruct(part.location, part.structName);\r\n        }\r\n        if(part.label) {\r\n          this._referenceManager.tryAddName(part.location, part.label);\r\n        }\r\n      }\r\n      this._referenceManager.tryAddName(block.location, block.name);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Processes a single part\r\n   */\r\n  public processPart(part: AsmBlock): void {\r\n    this._currentAsmBlock = part;\r\n    this._romDataReader.position = part.location;\r\n    this._partEnd = part.location + part.size;\r\n\r\n    let currentStruct = RomProcessingConstants.stripMarkers(part.structName || BlockReaderConstants.CODE_TYPE);\r\n\r\n    const chunks: TableEntry[] = [];\r\n    const reg = new Registers(this._root.config.memoryMode); //platform.createRegisters()\r\n    const bank : number | undefined = undefined;\r\n    let last: TableEntry | null = null;\r\n\r\n    while (this._romDataReader.position < this._partEnd) {\r\n      this.hydrateRegisters(reg);\r\n  \r\n      const structResult = this._referenceManager.tryGetStruct(this._romDataReader.position);\r\n      if (structResult.found) {\r\n        currentStruct = { raw: structResult.rawType!, name: structResult.chunkType!, isSoft: structResult.isSoft!, isRaw: structResult.isRaw! };\r\n        //current = structResult.isSoft ? \"~\" + structResult.chunkType! : structResult.chunkType!;\r\n      } else if (last !== null && !this._root.stringTypes[currentStruct.name]) {\r\n        this.processContinuousEntry(currentStruct.raw, reg, bank, last);\r\n        continue;\r\n      }\r\n\r\n      if(!this._referenceManager.nameTable.has(this._romDataReader.position)) {\r\n        const name = this._referenceManager.createTypeName(currentStruct.name, this._romDataReader.position);\r\n        this._referenceManager.nameTable.set(this._romDataReader.position, name);\r\n      }\r\n      last = new TableEntry(this._romDataReader.position);\r\n      chunks.push(last);\r\n      this.processNewEntry(currentStruct.raw, reg, bank, last);\r\n    }\r\n\r\n    part.objList = chunks;\r\n  }\r\n\r\n  /**\r\n   * Processes a continuous entry (same type as previous)\r\n   */\r\n  private processContinuousEntry(current: string, reg: Registers, bank: number | undefined, last: TableEntry): void {\r\n    let obj = this._typeParser.parseType(current, reg, 0, bank, false);\r\n    if (!Array.isArray(last.object)) last.object = [last.object];\r\n    (last.object as unknown[]).push(obj);\r\n  }\r\n\r\n  /**\r\n   * Processes a new entry\r\n   */\r\n  private processNewEntry(current: string, reg: Registers, bank: number | undefined, last: TableEntry): void {\r\n    let res = this._typeParser.parseType(current, reg, 0, bank);\r\n    if (current.indexOf(\"[\") !== -1 || (\r\n      BlockReaderConstants.POINTER_CHARACTERS.includes(current[0]) \r\n      && !Array.isArray(res))\r\n     ) res = [res];\r\n    last.object = res;\r\n  }\r\n\r\n  /**\r\n   * Creates ChunkFile objects from database structure\r\n   */\r\n  private createChunkFilesFromDatabase(): void {\r\n    console.log('createChunkFilesFromDatabase');\r\n    // Clear any previous results\r\n    this._enrichedChunks = [];\r\n    this.createChunkFilesFromSfx();\r\n    // Convert DbFiles to binary ChunkFiles with rawData\r\n    this.createChunkFilesFromDbFiles();\r\n    // Convert DbBlocks to assembly ChunkFiles with parts\r\n    this.createChunkFilesFromDbBlocks();\r\n  }\r\n\r\n  /**\r\n   * Creates binary ChunkFiles from DbFiles (enriched with rawData)\r\n   */\r\n  private createChunkFilesFromSfx(): void {\r\n    let pos = this._root.config.sfxLocation;\r\n    let offset = 0;\r\n    const count = this._root.config.sfxCount;\r\n    const romData = this._romDataReader.romData;\r\n    const fileType = Object.values(this._root.fileTypes).find(x => x.type === BinType.Sound)!;\r\n\r\n    const getByte = this._root.config.sfxType === 'Striped' ? () => {\r\n      const byte = romData[pos + offset++];\r\n      if(offset & RomProcessingConstants.PAGE_SIZE) offset += RomProcessingConstants.PAGE_SIZE;\r\n      return byte;\r\n    } : () => romData[pos + offset++];\r\n\r\n    const getSize = () => getByte() | (getByte() << 8);\r\n\r\n    const getBytes = this._root.config.sfxType === 'Striped' ? (size: number) => {\r\n      let end = offset + size;\r\n      let data: Uint8Array;\r\n      if (end & RomProcessingConstants.PAGE_SIZE) {\r\n        const endLen = end & 0x7FFF;\r\n        size -= endLen;\r\n        data = romData.slice(pos + offset, pos + offset + size);\r\n        offset += size + RomProcessingConstants.PAGE_SIZE;\r\n        end = offset + endLen;\r\n        const data2 = romData.slice(pos + offset, pos + end);\r\n        data = new Uint8Array([...data, ...data2]);\r\n      } else {\r\n        data = romData.slice(pos + offset, pos + end);\r\n      }\r\n      offset = end;\r\n      return data;\r\n    } : (size: number) => {\r\n      const end = offset + size;\r\n      const data = romData.slice(pos + offset, pos + end);\r\n      offset = end;\r\n      return data;\r\n    }\r\n\r\n    for (let i = 0; i < count; i++) {\r\n      const size = getSize();\r\n      const startPos = pos + offset;\r\n      const data = getBytes(size);\r\n\r\n      const chunk = new ChunkFile(fileType, `sfx${i.toString(16).toUpperCase().padStart(2, '0')}`, size, startPos);\r\n      chunk.rawData = data;\r\n      chunk.group = 'sfx';\r\n      this._enrichedChunks.push(chunk);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creates binary ChunkFiles from DbFiles (enriched with rawData)\r\n   */\r\n  private createChunkFilesFromDbFiles(): void {\r\n    for (const dbFile of this._root.files) {\r\n      const fileType = this._root.fileTypes[dbFile.type];\r\n      const chunkFile = new ChunkFile(fileType, dbFile.name);\r\n      chunkFile.enrichWithRawDataFromDbFile(dbFile, this._romDataReader.romData, this._root.compression);\r\n      this._enrichedChunks.push(chunkFile);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creates assembly ChunkFiles from DbBlocks (enriched with parts)\r\n   */\r\n  private createChunkFilesFromDbBlocks(): void {\r\n    const fileType = Object.values(this._root.fileTypes).find(x => x.isBlock)!;\r\n    for (const block of this._root.blocks) {\r\n      const chunkFile = new ChunkFile(fileType, block.name);\r\n      chunkFile.enrichWithAsmBlocksFromDbBlock(block, this._root.config.memoryMode);\r\n      this._enrichedChunks.push(chunkFile);\r\n    }\r\n  }\r\n  /**\r\n   * Analyzes only assembly ChunkFiles (those with parts from DbBlocks)\r\n   */\r\n  private analyzeChunkFiles(): void {\r\n    console.log('analyzeChunkFiles');\r\n    \r\n    for (const chunkFile of this._enrichedChunks) {\r\n      if(!chunkFile.parts?.length) continue;\r\n      chunkFile.referenceManager = this._referenceManager;\r\n      this._currentChunk = chunkFile;\r\n      this._romDataReader.offset = chunkFile.base;\r\n      for (const asmBlock of chunkFile.parts) {\r\n        this._currentAsmBlock = asmBlock;\r\n        this.processPart(asmBlock);\r\n      }\r\n    }\r\n\r\n    const oldState = this._referenceManager;\r\n    const oldReader = this._romDataReader;\r\n    const oldTypeParser = this._typeParser;\r\n    \r\n    for (const chunkFile of this._enrichedChunks) {\r\n      if(!chunkFile.struct || !chunkFile.compressed) continue;\r\n      this._currentChunk = chunkFile;\r\n\r\n      const asmBlock = new AsmBlock(chunkFile, 0, chunkFile.size, chunkFile.name, chunkFile.struct);\r\n      chunkFile.parts = [asmBlock];\r\n      this._currentAsmBlock = asmBlock;\r\n      this._referenceManager = chunkFile.referenceManager = new ReferenceManager(this._root);\r\n      this._romDataReader = new RomDataReader(chunkFile.rawData!, chunkFile.base);\r\n      this._typeParser = new TypeParser(this);\r\n      this.processPart(asmBlock);\r\n    }\r\n\r\n    this._referenceManager = oldState;\r\n    this._romDataReader = oldReader;\r\n    this._typeParser = oldTypeParser;\r\n  }\r\n\r\n  /**\r\n   * Resolves references in assembly ChunkFiles only\r\n   */\r\n  private resolveReferences(): void {\r\n    console.log('resolveReferences');\r\n    for (const chunkFile of this._enrichedChunks) {\r\n      if(!chunkFile.parts?.length) continue;\r\n      this._currentChunk = chunkFile;\r\n      for (const asmBlock of chunkFile.parts) {\r\n        this._currentAsmBlock = asmBlock;\r\n        this.resolveObject(asmBlock.objList, false);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Resolves a single object and its references\r\n   */\r\n  private resolveObject(obj: unknown, isBranch: boolean): void {\r\n    if(obj === undefined || obj === null) return;\r\n\r\n    if (typeof obj === 'string') {\r\n      // String objects don't need resolution\r\n      return;\r\n    }\r\n\r\n    if (Array.isArray(obj)) {\r\n      for (const o of obj) {\r\n        this.resolveObject(o, isBranch);\r\n      }\r\n      return;\r\n    }\r\n\r\n    if (obj instanceof Address) {\r\n      this.resolveMnemonic(obj, true);\r\n      return;\r\n    }\r\n\r\n    if (typeof obj === 'number') {\r\n      this.resolveInclude(obj, isBranch);\r\n      return;\r\n    }\r\n\r\n    if (obj instanceof LocationWrapper) {\r\n      this.resolveInclude(obj.location, isBranch);\r\n      return;\r\n    }\r\n\r\n    if (obj instanceof TableEntry) {\r\n      this.resolveObject(obj.object, isBranch);\r\n      return;\r\n    }\r\n\r\n    if (obj instanceof Op) {\r\n      this.resolveOperationObject(obj);\r\n      return;\r\n    }\r\n\r\n    if (typeof obj === 'object') {\r\n      if ('string' in obj && 'type' in obj) {\r\n        // StringWrapper\r\n        this._stringReader.resolveString(obj as StringWrapper, isBranch);\r\n        return;\r\n      }\r\n\r\n      if ('name' in obj && 'parts' in obj) {\r\n        // StructDef\r\n        this.resolveObject((obj as StructDef).parts, isBranch);\r\n        return;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Resolves references in an operation object\r\n   */\r\n  private resolveOperationObject(op: Op): void {\r\n    const branch = this.isBranchOperation(op);\r\n    for (const opnd of op.operands) {\r\n      this.resolveObject(opnd, branch);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Checks if an operation is a branch operation\r\n   */\r\n  private isBranchOperation(op: Op): boolean {\r\n    return op.mode === 'PCRelative' ||\r\n           op.mode === 'PCRelativeLong' ||\r\n           op.mnem[0] === 'J';\r\n  }\r\n\r\n  /**\r\n   * Hydrates registers with stored state\r\n   */\r\n  public hydrateRegisters(reg: Registers): void {\r\n    this._stateManager.hydrateRegisters(this._romDataReader.position, reg);\r\n  }\r\n\r\n}","import { ChunkFile } from '../../types/files';\r\nimport { TableEntry } from '../../types';\r\nimport { StructDef, Word, LocationWrapper, AddressType } from '../../types';\r\nimport { BlockReader } from './blocks';\r\nimport { ReferenceManager } from './references';\r\nimport { AsmBlock } from '../../types/assembly';\r\n\r\n/**\r\n * Handles post processing of extracted blocks.\r\n * Mirrors functionality of GaiaLib.Rom.Extraction.PostProcessor.\r\n */\r\nexport class PostProcessor {\r\n  private readonly _referenceManager: ReferenceManager;\r\n\r\n  constructor(reader: BlockReader) {\r\n    this._referenceManager = reader._referenceManager;\r\n  }\r\n\r\n  /**\r\n   * Execute post process directive on a block if present.\r\n   */\r\n  public process(block: ChunkFile): void {\r\n    if (!block.postProcess || block.postProcess.trim() === '') {\r\n      return;\r\n    }\r\n\r\n    const steps = block.postProcess.split('&&').map(step => step.trim());\r\n\r\n    for (const step of steps) {\r\n      let signature = step;\r\n      const parts: string[] = [];\r\n\r\n      const index = signature.indexOf('(');\r\n      if (index > 0) {\r\n        const endIx = signature.indexOf(')', index);\r\n        const params = signature.substring(\r\n          index + 1,\r\n          endIx >= 0 ? endIx : signature.length\r\n        );\r\n        if (params.length > 0) {\r\n          for (const p of params.split(',')) {\r\n            parts.push(p.trim());\r\n          }\r\n        }\r\n        signature = signature.substring(0, index);\r\n      }\r\n\r\n      const fn = (this as any)[signature];\r\n      if (typeof fn !== 'function') {\r\n        throw new Error(`Unable to locate postprocess function ${signature}`);\r\n      }\r\n      fn.apply(this, [block, ...parts]);\r\n    }\r\n    \r\n  }\r\n\r\n  /**\r\n   * Builds a lookup table from struct entries.\r\n   * Equivalent to PostProcessor.Lookup in C# implementation.\r\n   */\r\n  public Lookup(block: ChunkFile, keyIx: string, valueIx: string, maxId: string): void {\r\n    const keyIndex = parseInt(keyIx);\r\n    const valueIndex = parseInt(valueIx);\r\n    const maxKey = maxId ? parseInt(maxId) : undefined;\r\n\r\n    if(!block.parts?.length) throw new Error('Invalid block structure for Lookup post process');\r\n\r\n    const newParts: TableEntry[] = [];\r\n    const lookupList: any[] = [];\r\n    \r\n    // Add the master lookup (use location - 1 to avoid overwriting the first entry)\r\n    newParts.push({ location: block.location - 1, object: lookupList });\r\n\r\n    const newBlockName = `${block.parts[0].objList[0].object[0].name}_list`;\r\n\r\n    //Add mater lookup name\r\n    this._referenceManager.nameTable.set(block.location - 1, newBlockName);\r\n\r\n    const entryLookup: Record<number, TableEntry> = {};\r\n    let endKey = -1;\r\n\r\n    for (const part of block.parts) {\r\n      \r\n      const entries = (part.objList[0] as TableEntry).object as StructDef[];\r\n      for (const entry of entries) {\r\n        \r\n        let key: number | undefined;\r\n        let value: any | undefined;\r\n        \r\n        for(let i = 0; i < entry.parts.length; i++) {\r\n          if (i === keyIndex) {\r\n            const obj = entry.parts[i];\r\n            if (typeof obj === 'number') key = obj;\r\n            else if (obj && typeof obj === 'object' && 'value' in obj) key = obj.value as number;\r\n          } \r\n          else if (i === valueIndex) value = entry.parts[i];\r\n        }\r\n\r\n        if (key === undefined || value === undefined) continue;\r\n        if (maxKey && key > maxKey) continue;\r\n\r\n        //Adjust highest key found\r\n        if (key > endKey) endKey = key;\r\n\r\n        const name = `${entry.name.replaceAll('-', '_').replaceAll(' ', '_').toLowerCase()}_${key.toString(16).toUpperCase().padStart(4, '0')}`;\r\n        \r\n        const tableEntry = new TableEntry(entry.location, value, name);\r\n\r\n        //Add key to entry lookup table\r\n        entryLookup[key] = tableEntry;\r\n        \r\n        //Add entry name to name table\r\n        this._referenceManager.nameTable.set(entry.location, name);\r\n        \r\n        //Add entry to new parts\r\n        //newParts.push({ location: entry.location, object: value, name: name });\r\n      }\r\n    }\r\n    \r\n    //Generate lookup list\r\n    for (let i = 0; i <= endKey; i++) {\r\n      const entry = entryLookup[i];\r\n      if(entry) newParts.push(entry);\r\n      lookupList.push(entry ? `&${entry.name}` : new Word(0));\r\n    }\r\n\r\n    const newBlock = new AsmBlock(block, block.location - 1, 0, newBlockName, 'Offset');\r\n    newBlock.objList = newParts;\r\n\r\n    block.parts = [ newBlock ];\r\n  }\r\n\r\n  public Label( block: ChunkFile, structType: string, listName?: string) {\r\n    \r\n    if(!block.parts?.length) throw new Error('Invalid block structure for Label post process');\r\n\r\n    const keyLookup: Record<number, string> = {};\r\n    let endKey = -1;\r\n\r\n    listName ??= structType;\r\n\r\n    for (const part of block.parts) {\r\n\r\n      for(const obj of part.objList) {\r\n        if(!obj || typeof obj !== 'object' || !('object' in obj)) continue;\r\n\r\n        for(let i = 0; i < obj.object.length; i++) {\r\n          const entry = obj.object[i];\r\n          if(!entry || typeof entry !== 'object' || !('name' in entry) || !('parts' in entry) || entry.name !== structType) continue;\r\n          const part = entry.parts[0];\r\n\r\n          const key = typeof part === 'number' ? part : part.value as number;\r\n          const name = `${listName}_${key.toString(16).toUpperCase().padStart(2, '0')}`;\r\n          obj.object[i] = `${name}:`;\r\n          keyLookup[key] = name;\r\n          if (key > endKey) endKey = key;\r\n        }\r\n      }\r\n\r\n    }\r\n\r\n    const keyList: any[] = [];\r\n    for (let i = 0; i <= endKey; i++) {\r\n      const name = keyLookup[i];\r\n      keyList.push(name ? `&${name}` : new Word(0));\r\n    }\r\n\r\n    const newName = `${listName}_list`;\r\n    const newBlock = new AsmBlock(block, block.location + block.size - 2, 0, newName, `&${structType}`);\r\n    newBlock.objList = [ { location: newBlock.location, object: keyList } ];\r\n\r\n    this._referenceManager.nameTable.set(newBlock.location, newName);\r\n\r\n    block.parts.push(newBlock);\r\n  }\r\n\r\n  public Extract( block: ChunkFile, valueIndexString: string) {\r\n    if(!block.parts?.length) throw new Error('Invalid block structure for Extract post process');\r\n    \r\n    //const offset = offsetString ? parseInt(offsetString) ?? 0 : 0;\r\n    const valueIndex = valueIndexString ? parseInt(valueIndexString) ?? 0 : 0;\r\n\r\n    for (const part of block.parts) {\r\n      const tableList = part.objList as TableEntry[];\r\n      const locationList = tableList[0].object as LocationWrapper[];\r\n      const objLookup : Record<number, any> = {};\r\n      let objLocation = tableList[0].location;\r\n      let valueLocation = tableList.length + objLocation++;\r\n\r\n      const extractName = part.label || this._referenceManager.tryGetName(part.location)?.referenceName;\r\n\r\n      const newLocationList: LocationWrapper[] = [];\r\n      const newLocationTable: TableEntry = { location: valueLocation++, object: newLocationList, name: `${extractName}_extract_table` };\r\n      \r\n      const newTableList: TableEntry[] = [ newLocationTable ];\r\n\r\n      for(let i = 1; i < tableList.length; i++) {\r\n        const tableEntry = tableList[i];\r\n        const oldLocation = tableEntry.location;\r\n\r\n        const name = this._referenceManager.nameTable.get(oldLocation);\r\n        if(!name) throw new Error(`Object name not found for location ${oldLocation}`);\r\n\r\n        //Get entry object and value\r\n        const entryObject = (tableEntry.object as any[])[0] as StructDef;\r\n        const entryValue = entryObject.parts[valueIndex];\r\n        \r\n        //Remove value from entry object\r\n        entryObject.parts.splice(valueIndex, 1);\r\n\r\n        if(entryObject.parts.length === 1) tableEntry.object = entryObject.parts[0]!;\r\n\r\n        //Generate value name\r\n        const valueName = `${name}_value`;\r\n\r\n        //Generate new value entry\r\n        const valueTableEntry: TableEntry = { location: valueLocation, object: entryValue, name: valueName };\r\n\r\n        //Cretae obj lookup entry\r\n        objLookup[oldLocation] = { name, objLocation, valueLocation, object: tableEntry, value: valueTableEntry };\r\n\r\n        //Add new value entry to new table\r\n        newTableList.push(valueTableEntry);\r\n\r\n        objLocation++;\r\n        valueLocation++;\r\n      }\r\n\r\n      //Rewrite original table/name locations\r\n      for(let i = 1; i < tableList.length; i++) {\r\n        const tableEntry = tableList[i];\r\n        const lookupObj = objLookup[tableEntry.location];\r\n        tableEntry.location = lookupObj.objLocation;\r\n        this._referenceManager.nameTable.set(lookupObj.objLocation, lookupObj.name);\r\n      }\r\n\r\n      //Rewrite original lookup table locations\r\n      for(const wrapper of locationList) {\r\n        const lookupObj = objLookup[wrapper.location];\r\n        wrapper.location = lookupObj.objLocation;\r\n        newLocationList.push(new LocationWrapper(lookupObj.valueLocation, AddressType.Offset));\r\n      }\r\n\r\n      //Write new table names to name table\r\n      for(const table of newTableList) this._referenceManager.nameTable.set(table.location, table.name!);\r\n\r\n      //Concatenate new table list to original table list\r\n      tableList.push(...newTableList);\r\n    }\r\n  }\r\n\r\n}\r\n\r\nexport default PostProcessor;\r\n\r\n","import { Op } from '../../types/assembly';\r\nimport { AsmBlock, ChunkFile, ChunkFileUtils, RomProcessingConstants, TypedNumber } from '../../types';\r\nimport { \r\n  AddressType, \r\n  MemberType,\r\n  AddressSpace,\r\n  TableEntry,\r\n  StructDef,\r\n  StringWrapper,\r\n  LocationWrapper,\r\n  Address\r\n} from '../../types';\r\nimport { DbRoot } from '../../database';\r\nimport { BlockReader } from './blocks';\r\nimport { ReferenceManager } from './references';\r\nimport { PostProcessor } from './postprocessor';\r\n\r\n// Type tags for better object identification\r\nexport enum ObjectType {\r\n  TableEntryArray = 'TableEntryArray',\r\n  StructDef = 'StructDef',\r\n  OpArray = 'OpArray',\r\n  LocationWrapper = 'LocationWrapper',\r\n  Address = 'Address',\r\n  StringWrapper = 'StringWrapper',\r\n  ByteArray = 'ByteArray',\r\n  Array = 'Array',\r\n  String = 'String',\r\n  Number = 'Number',\r\n  TypedNumber = 'TypedNumber'\r\n}\r\n\r\nexport class BlockWriter {\r\n  private _root: DbRoot;\r\n  private _blockReader: BlockReader;\r\n  private _referenceManager: ReferenceManager;\r\n  private _postProcessor: PostProcessor;\r\n  private _isInline: boolean = false;\r\n  private _currentPart: AsmBlock | null = null;\r\n  private _currentBlock: ChunkFile | undefined = undefined;\r\n\r\n  constructor(reader: BlockReader) {\r\n    this._blockReader = reader;\r\n    this._root = reader._root;\r\n    this._referenceManager = reader._referenceManager;\r\n    this._postProcessor = new PostProcessor(reader);\r\n  }\r\n\r\n  // async writeBlocks(outPath: string): Promise<void> {\r\n  //   const res = DbRootUtils.getPath(this._root, BinType.Assembly);\r\n\r\n  //   const folderPath = join(outPath, res.folder);\r\n\r\n  //   for (const block of this._root.blocks) {\r\n  //     const groupedFolderPath = block.group \r\n  //       ? join(folderPath, block.group)\r\n  //       : folderPath;\r\n      \r\n  //     await fs.mkdir(groupedFolderPath, { recursive: true });\r\n\r\n  //     const outFile = join(groupedFolderPath, `${block.name}.${res.extension}`);\r\n      \r\n  //     // Check if file exists, skip if it does\r\n  //     try {\r\n  //       await fs.access(outFile);\r\n  //       continue;\r\n  //     } catch {\r\n  //       // File doesn't exist, continue with creation\r\n  //     }\r\n\r\n  //     const content = this.generateAsm(block);\r\n      \r\n  //     await fs.writeFile(outFile, content);\r\n  //   }\r\n  // }\r\n\r\n  generateAllAsm(chunkFiles: ChunkFile[]): any[] {\r\n    const lines: any[] = [];\r\n    for (const block of chunkFiles) {\r\n      lines.push({\r\n        name: block.name,\r\n        group: block.group,\r\n        text: this.generateAsm(block)\r\n      });\r\n    }\r\n    return lines;\r\n  }\r\n\r\n  generateAsm(block: ChunkFile): string{\r\n    if(!block.parts) {\r\n      throw new Error('Invalid block structure for generateAsm');\r\n    }\r\n\r\n    const lines: string[] = [];\r\n    this._referenceManager = block.referenceManager!;\r\n    this._currentBlock = block;\r\n\r\n    const notes = this._root.blockNotes[block.name];\r\n    if (notes?.length > 0) {\r\n      lines.push(...notes.split(/\\r?\\n/).map(line => `; ${line}`));\r\n      lines.push('---------------------------------------------');\r\n      lines.push('');\r\n    }\r\n\r\n    // Write bank information if not movable\r\n    if (block.bank !== undefined) {\r\n      lines.push(`?BANK ${block.bank.toString(16).toUpperCase().padStart(2, '0')}`);\r\n      lines.push('');\r\n    }\r\n\r\n    // Write includes - these should be from the block's include list\r\n    const includes = ChunkFileUtils.getIncludes(block);\r\n    if (includes?.length > 0) {\r\n      for (const inc of includes.sort((a, b) => a.name.localeCompare(b.name))) {\r\n        lines.push(`?INCLUDE '${inc.name}'`);\r\n      }\r\n      lines.push('');\r\n    }\r\n\r\n    // Write mnemonics - these should be from the root mnemonics that are referenced in this block\r\n    const mnemonics = this.getMnemonicsForBlock(block);\r\n    if (mnemonics?.length > 0) {\r\n      for (const [name, address] of mnemonics) {\r\n        const paddedName = name.padEnd(30, ' ');\r\n        lines.push(`!${paddedName} ${address}`); // ${address.toString(16).toUpperCase().padStart(4, '0')}`);\r\n      }\r\n      lines.push('');\r\n    }\r\n\r\n    // Apply any post processing defined for the block\r\n    this._postProcessor.process(block);\r\n\r\n    // Process each part\r\n    for (const part of block.parts || []) {\r\n      this._currentPart = part;\r\n      this._isInline = true;\r\n\r\n      lines.push('---------------------------------------------');\r\n\r\n      try {\r\n        const objectLines = this.writeObject(part.objList, -1);\r\n        lines.push(...objectLines);\r\n      } catch (error) {\r\n        throw new Error(`Error writing object for part ${part.label}: ${error}`);\r\n      }\r\n    }\r\n\r\n    let content = lines.join(RomProcessingConstants.NEWLINE);\r\n\r\n    // Apply replace transforms\r\n    if (block.transforms) {\r\n      for (const x of block.transforms) {\r\n        if (x.key && x.value !== undefined) {\r\n          const regex = new RegExp(x.key, 'g');\r\n          content = content.replace(regex, x.value);\r\n        }\r\n      }\r\n    }\r\n\r\n    if(!RomProcessingConstants.IS_WINDOWS){\r\n      content = content.replace(/\\r/g, '');\r\n    }\r\n\r\n    return content;\r\n  };\r\n\r\n  private getMnemonicsForBlock(block: ChunkFile): [string, string][] {\r\n    if (!block.mnemonics) {\r\n      return [];\r\n    }\r\n\r\n    return Object.entries(block.mnemonics)\r\n      //.map(([k, v]) => [v, parseInt(k, 10)] as [string, number])\r\n      .sort((a, b) => a[1].localeCompare(b[1]));\r\n  }\r\n\r\n  private resolveOperand(op: Op, obj: any, isBranch: boolean = false): any {\r\n\r\n    if(obj instanceof TypedNumber) {\r\n      const len = obj.size * 2;\r\n      return obj.value.toString(16).toUpperCase().padStart(len, '0');\r\n    }\r\n\r\n    if (typeof obj === 'number') {\r\n      if (op.mode === 'Immediate') {\r\n        return obj;\r\n      }\r\n      return this._referenceManager.resolveName(obj, AddressType.Address, isBranch, this._currentBlock);\r\n    }\r\n    \r\n    if (this.getObjectType(obj) === ObjectType.LocationWrapper) {\r\n      const lw = obj as LocationWrapper;\r\n      return this._referenceManager.resolveName(lw.location, lw.type, isBranch, this._currentBlock);\r\n    }\r\n    if (this.getObjectType(obj) === ObjectType.Address) {\r\n      const addr = obj as Address;\r\n      const isWram = addr.isWram;\r\n\r\n      if (isWram || (addr.isCodeBank && addr.offset < Address.UPPER_BANK)) {\r\n        const offset = isWram ? addr.toInt() : addr.offset;\r\n        const label = this._root.mnemonics[offset];\r\n        if (label) return (isWram && addr.isShort) ? `S_${label}` : (!isWram && !addr.isShort) ? `L_${label}` : label;\r\n      }\r\n      \r\n      return addr.isShort ? addr.offset : addr.toString();\r\n    }\r\n\r\n    // Preserve tag information on typed numbers without resolving names\r\n    if (obj && obj instanceof TypedNumber) {\r\n      // const typed = obj as { _tag: string; value: any };\r\n\r\n      // // Byte/Word objects should remain untouched\r\n      // if (typed._tag === 'Byte' || typed._tag === 'Word' || typed._tag === 'TypedNumber') {\r\n      //   return obj;\r\n      // }\r\n\r\n      // if (typeof typed.value === 'number' && op.mode !== 'Immediate') {\r\n      //   const resolved = this._blockReader.resolveName(typed.value, AddressType.Address, isBranch);\r\n      //   return { ...typed, value: resolved };\r\n      // }\r\n      return obj;\r\n    }\r\n    return obj;\r\n  }\r\n\r\n  private getObjectType(obj: any): ObjectType {\r\n    if (obj === null || obj === undefined) {\r\n      return ObjectType.String;\r\n    }\r\n\r\n    // Check for explicit type tags first\r\n    if (obj._tag) {\r\n      return obj._tag as ObjectType;\r\n    }\r\n\r\n    if (obj instanceof TypedNumber) {\r\n      return ObjectType.TypedNumber;\r\n    }\r\n\r\n    // Duck typing fallbacks\r\n    if (Array.isArray(obj)) {\r\n      if (obj.length > 0) {\r\n        if (obj[0] && typeof obj[0] === 'object' && 'location' in obj[0] && 'object' in obj[0]) {\r\n          return ObjectType.TableEntryArray;\r\n        }\r\n        if (obj[0] instanceof Op) {\r\n          return ObjectType.OpArray;\r\n        }\r\n      }\r\n      return ObjectType.Array;\r\n    }\r\n\r\n    if (obj instanceof Op) {\r\n      return ObjectType.OpArray;\r\n    }\r\n\r\n    if (obj instanceof LocationWrapper) {\r\n      return ObjectType.LocationWrapper;\r\n    }\r\n\r\n    if (obj instanceof Address) {\r\n      return ObjectType.Address;\r\n    }\r\n\r\n    if (obj instanceof Uint8Array) {\r\n      return ObjectType.ByteArray;\r\n    }\r\n\r\n    if (obj && typeof obj === 'object') {\r\n      if ('string' in obj && 'type' in obj && 'marker' in obj && 'location' in obj) {\r\n        return ObjectType.StringWrapper;\r\n      }\r\n      if ('name' in obj && 'parts' in obj) {\r\n        return ObjectType.StructDef;\r\n      }\r\n    }\r\n\r\n    if (typeof obj === 'string') {\r\n      return ObjectType.String;\r\n    }\r\n\r\n    if (typeof obj === 'number') {\r\n      return ObjectType.Number;\r\n    }\r\n\r\n    return ObjectType.String;\r\n  }\r\n\r\n  private writeObject(obj: any, depth: number, isBranch: boolean = false, isArray: boolean = false): string[] {\r\n    const lines: string[] = [];\r\n\r\n    const objType = this.getObjectType(obj);\r\n    let objLines: string[];\r\n\r\n    switch (objType) {\r\n      case ObjectType.TableEntryArray:\r\n        objLines = this.writeTableEntryArray(obj as TableEntry[], depth);\r\n        break;\r\n\r\n      case ObjectType.StructDef:\r\n        objLines = this.writeStructDef(obj as StructDef, depth);\r\n        break;\r\n\r\n      case ObjectType.OpArray:\r\n        objLines = this.writeOpArray(obj as Op[], depth);\r\n        break;\r\n\r\n      case ObjectType.LocationWrapper:\r\n        const lw = obj as LocationWrapper;\r\n        objLines = [this._referenceManager.resolveName(lw.location, lw.type, isBranch, this._currentBlock)];\r\n        break;\r\n\r\n      case ObjectType.Address:\r\n        const addr = obj as Address;\r\n        objLines = [`$${isArray ? '#' : ''}${addr.isShort ? addr.toOffsetString() : addr.toString()}`];\r\n        break;\r\n\r\n      case ObjectType.ByteArray:\r\n        objLines = [\r\n          `#${Array.from(obj as Uint8Array)\r\n            .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\r\n            .join('')}`,\r\n        ];\r\n        break;\r\n\r\n      case ObjectType.StringWrapper:\r\n        objLines = this.writeStringWrapper(obj as StringWrapper);\r\n        break;\r\n\r\n      case ObjectType.Array:\r\n        objLines = this.writeArray(obj as any[], depth);\r\n        break;\r\n\r\n      case ObjectType.Number:\r\n        objLines = this.writeNumber(obj as number);\r\n        break;\r\n\r\n      case ObjectType.TypedNumber:\r\n        objLines = this.writeTypedNumber(obj as any);\r\n        break;\r\n\r\n      case ObjectType.String:\r\n        objLines = [String(obj)];\r\n        break;\r\n\r\n      default:\r\n        objLines = [String(obj)];\r\n        break;\r\n    }\r\n\r\n    lines.push(...objLines);\r\n\r\n    return lines;\r\n  }\r\n\r\n  private writeTableEntryArray(tGroup: TableEntry[], depth: number): string[] {\r\n    const lines: string[] = [];\r\n    const isInline = this._isInline;\r\n    //this._isInline = true;\r\n\r\n    let first = true;\r\n    for (const t of tGroup) {\r\n      let name : string | undefined;\r\n\r\n      if (t.location === this._currentPart?.location) name = this._currentPart.label;\r\n      if (!name) name = this._referenceManager.tryGetName(t.location).referenceName;\r\n      if (!name) name = `loc_${t.location.toString(16).toUpperCase().padStart(6, '0')}`;\r\n      \r\n      const objectLines = this.writeObject(t.object, depth + 1);\r\n\r\n      const notes = this._root.partNotes[name];\r\n      if (notes?.length > 0) {\r\n        lines.push('');\r\n        if (!first) lines.push('---------------------------------------------');\r\n        lines.push(...notes.split(/\\r?\\n/).map(line => `; ${line}`));\r\n      }\r\n\r\n      lines.push('');\r\n      lines.push(`${name} ${objectLines[0]}`);\r\n      if(objectLines.length > 1) lines.push(...objectLines.slice(1)); \r\n      first = false;\r\n    }\r\n    \r\n    this._isInline = isInline;\r\n    return lines;\r\n  }\r\n\r\n  private writeStructDef(structObj: StructDef, depth: number): string[] {\r\n    const parts: string[] = [];\r\n    const isInline = this._isInline;\r\n    this._isInline = true;\r\n    for (const part of structObj.parts) {\r\n      const partLines = this.writeObject(part, depth);\r\n      parts.push(partLines.join(RomProcessingConstants.NEWLINE));\r\n    }\r\n    const line = `${structObj.name} < ${parts.join(', ')} >`;\r\n    this._isInline = isInline; // match C# spacing behaviour\r\n    return [line];\r\n  }\r\n\r\n  private writeOpArray(opList: Op[], depth: number): string[] {\r\n    const lines: string[] = [];\r\n    lines.push('{');\r\n    const isInline = this._isInline;\r\n    this._isInline = true; // instructions follow immediately\r\n\r\n    let first = true;\r\n    for (const op of opList) {\r\n      if (!first || depth > 0) {\r\n        // Check for labels on subsequent instructions\r\n        let label = this._referenceManager.tryGetName(op.location)?.referenceName;\r\n        if (!label && first && depth > 0) label = `code_${op.location.toString(16).toUpperCase().padStart(6, '0')}`;\r\n        if(label) {\r\n\r\n          const notes = this._root.partNotes[label];\r\n          if (notes?.length > 0) {\r\n            lines.push('');\r\n            lines.push(...notes.split(/\\r?\\n/).map(line => `; ${line}`));\r\n          }\r\n\r\n          lines.push('');\r\n          lines.push(`  ${label}:`);\r\n        }\r\n      }\r\n\r\n      first = false;\r\n\r\n      let opLine = `    ${op.mnem} `;\r\n\r\n      if (op.copDef) {\r\n        // Handle COP instructions specially\r\n        opLine += `[${op.copDef.name}]`;\r\n        if (op.operands && op.operands.length > 1) {\r\n          const operandStrings: string[] = [];\r\n          for (let i = 1; i < op.operands.length; i++) {\r\n            const operandLines = this.writeObject(op.operands[i], depth + 1, false);\r\n            operandStrings.push(operandLines[0]);\r\n          }\r\n          opLine += ` ( ${operandStrings.join(', ')} )`;\r\n        }\r\n      } else if (op.operands && op.operands.length > 0) {\r\n        const isBr = op.mnem[0] === 'J' || \r\n                    op.mode === 'PCRelative' ||\r\n                    op.mode === 'PCRelativeLong';\r\n\r\n        // Regular instruction formatting\r\n        const resolvedOperand = this.resolveOperand(op, op.operands[0], isBr);\r\n        const format = this._root.addrLookup[op.mode]?.formatString; // || this._root.config.asmFormats?.[op.code.mode];\r\n        \r\n        if (format) {\r\n          let actualFormat = format;\r\n          if (op.mode === 'Immediate' && op.size === 3) {\r\n            actualFormat = format.replace('X2', 'X4');\r\n          }\r\n          const resolvedSecondOperand = op.operands.length > 1 ? this.resolveOperand(op, op.operands[1], isBr) : undefined;\r\n          opLine += this.formatOperand(actualFormat, [resolvedOperand, resolvedSecondOperand]);\r\n        } else {\r\n          // Default formatting based on operand type\r\n          opLine += this.formatDefaultOperand(resolvedOperand, op.size);\r\n        }\r\n      }\r\n\r\n      const comment = this._root.comments[op.location];\r\n      if (comment) opLine = opLine.padEnd(25, ' ') + ` ; ${comment}`;\r\n      else if (this._root.config.emitLineTracking) opLine += ` ; {${op.location}}`;\r\n      \r\n      lines.push(opLine);\r\n    }\r\n    \r\n    lines.push('}');\r\n    this._isInline = isInline; // ensure following object is separated by blank line\r\n    return lines;\r\n  }\r\n\r\n  private formatDefaultOperand(operand: any, size: number): string {\r\n    if (typeof operand === 'string') {\r\n      return operand; // Already formatted\r\n    }\r\n\r\n    if (operand && operand instanceof TypedNumber) {\r\n      return this.formatTypedNumber(operand);\r\n    }\r\n\r\n    if (typeof operand === 'number') {\r\n      const hexSize = (size - 1) * 2;\r\n      const hex = operand.toString(16).toUpperCase().padStart(hexSize, '0');\r\n      return `$${hex}`;\r\n    }\r\n    \r\n    return String(operand);\r\n  }\r\n\r\n  private writeStringWrapper(stringObj: StringWrapper): string[] {\r\n    let str = stringObj.string;\r\n    \r\n    // Process string references\r\n    const stringReferenceChars = ['~', '^'];\r\n    for (const char of stringReferenceChars) {\r\n      let ix = str.indexOf(char);\r\n      while (ix >= 0) {\r\n        const hexStr = str.substring(ix + 1, ix + 7);\r\n        const rawAddr = parseInt(hexStr, 16);\r\n        const adrs = new Address((rawAddr >> 16) & 0xFF, rawAddr & 0xFFFF, this._blockReader._root.config.memoryMode);\r\n        const addressType = char === '^' ? AddressType.Offset : AddressType.Address;\r\n        let name = '';\r\n        \r\n        if (adrs.isROM) {\r\n          name = this._referenceManager.resolveName(adrs.toLocation(), addressType, false, this._currentBlock);\r\n        } else if(addressType === AddressType.Offset) {\r\n          name = adrs.offset.toString(16).toUpperCase().padStart(4, '0');\r\n        } else {\r\n          name = adrs.toString();\r\n        }\r\n        \r\n        str = str.replace(str.substring(ix, ix + 7), name);\r\n        ix = str.indexOf(char);\r\n      }\r\n    }\r\n\r\n    const refChar = stringObj.type.delimiter;\r\n    let marker = stringObj.marker;\r\n    \r\n    if (marker <= 0) marker = this._referenceManager.markerTable.get(stringObj.location) ?? 0;\r\n\r\n    if (marker > 0) {\r\n      let six = 0;\r\n      let mix = 0;\r\n      \r\n      while (mix < marker) {\r\n        if (str[six] === '[' || str[six] === '{') {\r\n          const eix = str.indexOf(str[six] === '[' ? ']' : '}', six);\r\n          const parts = str.substring(six + 1, eix).split(/[,: ]/);\r\n          const cmd = stringObj.type.commands[parts[0]];\r\n          if(cmd) {\r\n            for (const t of cmd.types) {\r\n              switch (t) {\r\n                case MemberType.Byte:\r\n                  mix += 1;\r\n                  break;\r\n                case MemberType.Word:\r\n                case MemberType.Offset:\r\n                  mix += 2;\r\n                  break;\r\n                case MemberType.Address:\r\n                case MemberType.Location:\r\n                  mix += 3;\r\n                  break;\r\n                case MemberType.Binary:\r\n                  mix += parts.length - 1;\r\n                  break;\r\n                default:\r\n                  throw new Error('Unsupported member type');\r\n              }\r\n            }\r\n          } else {\r\n            mix += parts.length - 1;\r\n          }\r\n          six = eix + 1;\r\n          mix++;\r\n        } else if(str[six] === '\\\\') {\r\n          six += RomProcessingConstants.NEWLINE.length + 1;\r\n        } else {\r\n          six++;\r\n          mix++;\r\n        }\r\n      }\r\n      \r\n      str = str.substring(0, six) + '[::]' + str.substring(six);\r\n    }\r\n\r\n    //Expand dictionaries\r\n    let dix = -1;\r\n    while((dix = str.indexOf('{')) >= 0) {\r\n      const eix = str.indexOf('}', dix);\r\n      const parts = str.substring(dix + 1, eix).split(/[,: ]/);\r\n      const cmd = stringObj.type.commands[parts[0]];\r\n      let entryText : string | undefined;\r\n\r\n      if(cmd?.dictionary && parts.length > 1) {\r\n        entryText = cmd.dictionary.entries[parseInt(parts[1], 16)];\r\n      } else {\r\n        const entryIx = parseInt(parts[0], 16);\r\n        const dictionary = isNaN(entryIx) ? undefined \r\n          : Object.values(stringObj.type.dictionaries).find(d => \r\n            d.command === undefined && d.base !== undefined && entryIx >= d.base && entryIx < d.base + d.entries.length);\r\n        if(dictionary) entryText = dictionary.entries[entryIx - dictionary.base!];\r\n      }\r\n\r\n      str = str.substring(0, dix) + (entryText ?? '') + str.substring(eix + 1);\r\n    }\r\n\r\n    //Remove marker bytes\r\n    str = str.replace(/\\[--\\]/g, '');\r\n\r\n    const sizeParam = stringObj.fixedSize ? `(${stringObj.fixedSize})` : '';\r\n\r\n    return [`${refChar}${str}${refChar}${sizeParam}${stringObj.isRaw ? '!' : ''}`];\r\n  }\r\n\r\n  private writeArray(arr: any[], depth: number): string[] {\r\n    const lines: string[] = [];\r\n    const indent = '  '.repeat(Math.max(0, depth));\r\n    const isInline = this._isInline;\r\n    lines.push('[');\r\n    this._isInline = false; // start elements on their own lines\r\n    const showIndex = arr.length > 1;\r\n\r\n    for (let i = 0; i < arr.length; i++) {\r\n      const objLines = this.writeObject(arr[i], depth + 1, false, true);\r\n      for (const line of objLines) lines.push(indent + '  ' + line);\r\n      if (showIndex) lines[lines.length - 1] += `   ;${i.toString(16).toUpperCase().padStart(2, '0')}`;\r\n    }\r\n\r\n    lines.push(indent + ']');\r\n    this._isInline = isInline;\r\n    return lines;\r\n  }\r\n\r\n  private writeNumber(num: number): string[] {\r\n    // Format numbers based on value and size\r\n    if (num <= 0xff) {\r\n      // Mirror C# BlockWriter: bytes omit the '$' prefix\r\n      return [`#${num.toString(16).toUpperCase().padStart(2, '0')}`];\r\n    }\r\n\r\n    if (num <= 0xffff) {\r\n      return [`#$${num.toString(16).toUpperCase().padStart(4, '0')}`];\r\n    }\r\n\r\n    return [`#$${num.toString(16).toUpperCase().padStart(6, '0')}`];\r\n  }\r\n\r\n  private formatTypedNumber(num: TypedNumber): string {\r\n    if (typeof num.value === 'number') {\r\n      const width = num.size * 2;\r\n      const hex = num.value.toString(16).toUpperCase().padStart(width, '0');\r\n      return num.size === 1 ? `#${hex}` : `#$${hex}`;\r\n    }\r\n\r\n    return `#${num.value}`;\r\n  }\r\n\r\n  private writeTypedNumber(num: TypedNumber): string[] {\r\n    return [this.formatTypedNumber(num)];\r\n  }\r\n\r\n  private formatOperand(format: string, operands: any[]): string {\r\n    return format.replace(/\\{(\\d+)(?::([^}]+))?\\}/g, (match, index, formatSpec) => {\r\n      const operand = operands[parseInt(index)];\r\n      if (operand && typeof operand === 'object' && operand._tag && 'value' in operand) {\r\n        const value = operand.value;\r\n        if (formatSpec && typeof value === 'number' && formatSpec.startsWith('X')) {\r\n          const width = parseInt(formatSpec.substring(1)) || 2;\r\n          return value.toString(16).toUpperCase().padStart(width, '0');\r\n        }\r\n        return String(value);\r\n      }\r\n\r\n      if (formatSpec && typeof operand === 'number') {\r\n        if (formatSpec.startsWith('X')) {\r\n          const width = parseInt(formatSpec.substring(1)) || 2;\r\n          return operand.toString(16).toUpperCase().padStart(width, '0');\r\n        }\r\n      }\r\n      return String(operand);\r\n    });\r\n  }\r\n} ","import { RomProcessingConstants } from '../../types/constants';\r\nimport { ChunkFile } from '../../types/files';\r\nimport { MemoryMapMode } from '../../types/addressing';\r\nimport type { DbConfig } from '../../database/config';\r\nimport type { DbRoot } from '../../database/root';\r\nimport { BinType } from '../../types/resources';\r\n\r\n/**\r\n * ROM layout planner\r\n * Converted from ext/GaiaLib/Rom/Rebuild/RomLayout.cs\r\n */\r\nexport class RomLayout {\r\n  private static readonly MIN_ACCEPTED_REMAINING = 0x20;\r\n\r\n  public readonly unmatchedFiles: ChunkFile[];\r\n  private readonly bestResult: number[] = new Array(0x200).fill(0);\r\n  private readonly bestSample: number[] = new Array(0x200).fill(0);\r\n\r\n  private currentBank = 0;\r\n  private currentUpper = false;\r\n  private bestDepth = 0;\r\n  private bestOffset = 0;\r\n  private bestRemain = 0;\r\n  private root: DbRoot;\r\n  private config: DbConfig;\r\n  private sfxPackType: string;\r\n  public readonly srcFiles: ChunkFile[] = [];\r\n  public readonly sfxFiles: ChunkFile[] = [];\r\n\r\n  constructor(files: ChunkFile[], root: DbRoot) {\r\n    this.root = root;\r\n    this.config = root.config;\r\n    this.sfxPackType = root.config.sfxPack ?? root.config.sfxType;\r\n    this.srcFiles = files;\r\n    this.sfxFiles = this.sfxPackType !== 'Individual' ? files.filter(x => x.type.type === 'Sound')\r\n      .sort((a, b) => {\r\n        const aId = parseInt(a.name.substring(a.name.length - 2, a.name.length), 16);\r\n        const bId = parseInt(b.name.substring(b.name.length - 2, b.name.length), 16);\r\n        return aId - bId;\r\n      }) : [];\r\n      \r\n    // Filter out zero-size files and order: assembly first, then by size desc\r\n    this.unmatchedFiles = files.filter(x => (x.size || 0) > 0)\r\n      .filter(x => this.sfxPackType === 'Individual' || x.type.type !== 'Sound')\r\n      .sort((a, b) => {\r\n        const aAsm = a.rawData ? 1 : 0;\r\n        const bAsm = b.rawData ? 1 : 0;\r\n        if (aAsm !== bAsm) return aAsm - bAsm;\r\n        if (b.size !== a.size) return b.size - a.size;\r\n        if (a.location !== b.location) return a.location - b.location;\r\n        return a.name.localeCompare(b.name);\r\n      });\r\n  }\r\n\r\n  public organize(): number {\r\n    let stripeSfx = false;\r\n    let page: number;\r\n    const maxPages = this.config.memoryMode === MemoryMapMode.Hi ? 0x80 \r\n      : this.config.memoryMode === MemoryMapMode.ExHi ? 0x100\r\n      : 0x40;\r\n    for (page = 0; page < maxPages; page++) {\r\n      if (this.unmatchedFiles.length === 0) break;\r\n      let start = page << 15; // 0x8000 per page\r\n      let remain = RomProcessingConstants.PAGE_SIZE;\r\n      \r\n      if(start <= this.config.sfxLocation && start + remain > this.config.sfxLocation) {\r\n        const gap = this.config.sfxLocation - start;\r\n        //if(gap) do something\r\n\r\n        if(this.sfxPackType === 'Sequential') {\r\n          let offset = 0;\r\n          for(const file of this.sfxFiles) {\r\n            file.location = start + offset;\r\n            console.log(`  ${file.location.toString(16).toUpperCase().padStart(6, '0')}: ${file.name}`);\r\n            offset += file.size;\r\n            if(offset & RomProcessingConstants.PAGE_SIZE) {\r\n              offset &= 0x7FFF;\r\n              console.log(`Page ${start.toString(16).toUpperCase().padStart(6, '0')} matched with SFX files 0 remaining`);\r\n              start += RomProcessingConstants.PAGE_SIZE;\r\n              page++;\r\n            }\r\n          }\r\n          console.log(`Page ${start.toString(16).toUpperCase().padStart(6, '0')} matched with SFX files ${remain} remaining`);\r\n          start += offset;\r\n          remain = RomProcessingConstants.PAGE_SIZE - offset;\r\n        } else if(this.sfxPackType === 'Striped') {\r\n          stripeSfx = true;\r\n        }\r\n      }\r\n\r\n      if ((page === 0 && this.config.memoryMode === MemoryMapMode.Lo) ||\r\n          (page === 1 && this.config.memoryMode === MemoryMapMode.Hi)) {\r\n        remain -= RomProcessingConstants.SNES_HEADER_SIZE;\r\n      }\r\n\r\n      if(stripeSfx) {\r\n        let offset = 0;\r\n        while(remain > 0 && this.sfxFiles.length) {\r\n          const file = this.sfxFiles.shift();\r\n          if(!file) continue;\r\n          file.location = start + offset;\r\n          console.log(`  ${file.location.toString(16).toUpperCase().padStart(6, '0')}: ${file.name}`);\r\n          offset += file.size;\r\n          if(offset & RomProcessingConstants.PAGE_SIZE) {\r\n            offset &= 0x7FFF;\r\n            console.log(`Page ${start.toString(16).toUpperCase().padStart(6, '0')} matched with SFX files 0 remaining`);\r\n            start += RomProcessingConstants.PAGE_SIZE;\r\n            page++;\r\n\r\n            if(offset) {\r\n              const newFile = new ChunkFile(Object.values(this.root.fileTypes).find(x => x.type === BinType.Binary)!, file.name + \"_2\", 0, 0);\r\n              const end = file.rawData!.length - offset;\r\n              newFile.rawData = file.rawData!.slice(end);\r\n              newFile.size = newFile.rawData.length;\r\n              this.sfxFiles.unshift(newFile);\r\n              this.srcFiles.push(newFile);\r\n              file.sizeHeader = file.rawData!.length;\r\n              file.rawData = file.rawData!.slice(0, end);\r\n              file.size -= offset;\r\n              offset = 0;\r\n            }\r\n            remain = RomProcessingConstants.PAGE_SIZE;\r\n            break;\r\n          } else {\r\n            remain -= file.size;\r\n          }\r\n        }\r\n        start += offset;\r\n        if(!this.sfxFiles.length) {\r\n          stripeSfx = false;\r\n        }\r\n\r\n      }\r\n      \r\n      this.currentUpper = this.config.memoryMode === MemoryMapMode.Lo || (page & 1) !== 0;\r\n      this.currentBank = this.config.memoryMode === MemoryMapMode.Lo ? page : (page >> 1);\r\n      this.bestDepth = 0;\r\n      this.bestRemain = remain;\r\n      this.bestOffset = 0;\r\n\r\n      // Pass 1: assembly preferred in upper banks\r\n      this.testDepth(0, this.bestDepth, this.bestRemain, true);\r\n\r\n      // Pass 2: if upper, also try binary-only fill\r\n      //if (this.currentUpper) {\r\n      this.bestOffset = this.bestDepth;\r\n      this.testDepth(0, this.bestDepth, this.bestRemain, false);\r\n      //}\r\n\r\n      // Assign positions for best selection\r\n      let position = start;\r\n      for (let i = 0; i < this.bestDepth;) {\r\n        const file = this.unmatchedFiles[this.bestResult[i++]];\r\n        file.location = position;\r\n        console.log(`  ${position.toString(16).toUpperCase().padStart(6, '0')}: ${file.name}`);\r\n        position += file.size;\r\n      }\r\n\r\n      console.log(`Page ${start.toString(16).toUpperCase().padStart(6, '0')} matched with ${this.bestDepth} files ${this.bestRemain} remaining`);\r\n      // Commit: remove placed files from queue\r\n      this.commitPage();\r\n    }\r\n\r\n    if (this.unmatchedFiles.length > 0) {\r\n      const names = this.unmatchedFiles.map(x => x.name).join('\\r\\n');\r\n      throw new Error(`Unable to match ${this.unmatchedFiles.length} files\\r\\n${names}`);\r\n    }\r\n\r\n    return page;\r\n  }\r\n\r\n  private testDepth(startIndex: number, depth: number, remain: number, asmMode: boolean): boolean {\r\n    for (let fileIndex = startIndex; fileIndex < this.unmatchedFiles.length; fileIndex++) {\r\n      const file = this.unmatchedFiles[fileIndex];\r\n\r\n      const fileSize = file.size || 0;\r\n      if (fileSize > remain) continue;\r\n\r\n      const isUpper = file.upper ?? (file.type.isPatch || file.type.isBlock ? true : this.currentUpper);\r\n\r\n      if(isUpper !== this.currentUpper) continue;\r\n\r\n      // Assembly preference and constraints\r\n      if (file.parts) {\r\n        if (!asmMode) {\r\n          if (file.bank !== undefined) continue;\r\n        } else if (file.bank !== this.currentBank) {\r\n          continue;\r\n        }\r\n      } else if (asmMode) {\r\n        continue;\r\n      }\r\n\r\n      // Skip if already selected in first pass window\r\n      let inList = false;\r\n      for (let y = this.bestOffset; --y >= 0;) {\r\n        if (this.bestResult[y] === fileIndex) {\r\n          inList = true;\r\n          break;\r\n        }\r\n      }\r\n      if (inList) continue;\r\n\r\n      // Try this file at current depth\r\n      this.bestSample[depth] = fileIndex;\r\n      const newRemain = remain - fileSize;\r\n\r\n      if (newRemain < this.bestRemain) {\r\n        this.bestRemain = newRemain;\r\n        this.bestDepth = depth + 1;\r\n        for (let i = this.bestOffset; i < this.bestDepth; i++) {\r\n          this.bestResult[i] = this.bestSample[i];\r\n        }\r\n      }\r\n\r\n      if (newRemain < RomLayout.MIN_ACCEPTED_REMAINING) return true;\r\n\r\n      if (this.testDepth(fileIndex + 1, depth + 1, newRemain, asmMode)) return true;\r\n    }\r\n    return true;\r\n  }\r\n\r\n  private commitPage(): void {\r\n    if (this.bestOffset > 0) {\r\n      for (let i = this.bestDepth; --i >= 0;) {\r\n        let lastY = 0;\r\n        let lastX = 0;\r\n        let y = 0;\r\n        for (let x = this.bestDepth; --x >= 0;) {\r\n          y = this.bestResult[x];\r\n          if (y > lastY) {\r\n            lastY = y;\r\n            lastX = x;\r\n          }\r\n        }\r\n        this.bestResult[lastX] = 0;\r\n        this.unmatchedFiles.splice(lastY, 1);\r\n      }\r\n    } else {\r\n      for (let i = this.bestDepth; --i >= 0;) {\r\n        this.unmatchedFiles.splice(this.bestResult[i], 1);\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n\r\n\r\n","import { \r\n  BinType, \r\n  AddressType, \r\n  Address, \r\n  RomProcessingConstants,\r\n  ChunkFile, \r\n  AsmBlock, \r\n  StringMarker,\r\n  TableEntry,\r\n  Byte,\r\n  Word,\r\n  Long,\r\n  TypedNumber\r\n} from '../../types';\r\nimport { DbEntryPoint, DbHeader, DbRoot } from '../../database';\r\nimport { RomProcessor as RebuildProcessor } from './processor';\r\nimport { Op } from '../../types/assembly';\r\nimport { CpuMode, MemoryMapMode } from '../../types/addressing';\r\n//import { ConditionBlock } from './assembler';\r\n/**\r\n * ROM writer (binary)\r\n * Converted from ext/GaiaLib/Rom/Rebuild/RomWriter.cs (subset: binary write only)\r\n */\r\nexport class RomWriter {\r\n  public bpsPath?: string;\r\n  public outBuffer?: Uint8Array;\r\n  private romSize? : number;\r\n  public readonly root: DbRoot;\r\n\r\n  constructor(root: DbRoot) {\r\n    this.root = root;\r\n  }\r\n\r\n  public async repack(files: ChunkFile[], modules?: string[])\r\n  : Promise<{ masterLookup: Record<string, AsmBlock>, files: ChunkFile[], header: any, romData: Uint8Array }> {\r\n    const processor = new RebuildProcessor(this);\r\n    const masterLookup = await processor.repack(files, modules);\r\n\r\n    const header = this.writeHeaders(masterLookup);\r\n\r\n    //await this.generatePatch();\r\n    return { masterLookup, files, header, romData: this.outBuffer! };\r\n  }\r\n\r\n  public allocate(pages: number): void {\r\n    if(this.root.config.memoryMode !== MemoryMapMode.Lo && (pages & 1) !== 0) pages++;\r\n    const size = pages * RomProcessingConstants.PAGE_SIZE;\r\n    let bits = 0;\r\n    let target = 1 << 10; // 1KB\r\n\r\n    while(target < size) {\r\n      target <<= 1;\r\n      bits++;\r\n    }\r\n\r\n    this.romSize = bits;\r\n    this.outBuffer = new Uint8Array(size);\r\n  }\r\n\r\n  public writeHeaders(masterLookup: Record<string, AsmBlock>): any {\r\n    const values = this.prepareHeaderValues();\r\n    for (const header of this.root.headers) {\r\n      if(header.condition && !eval(header.condition)) continue;\r\n      this.writeHeader(header, values, masterLookup);\r\n    }\r\n    this.writeChecksum(values);\r\n    return values;\r\n  }\r\n\r\n  public prepareHeaderValues(): any {\r\n    const values = { ...this.root.config } as any;\r\n    values.romSize = this.romSize;\r\n    values.checksum = 0;\r\n    values.compliment = 0xFFFF;\r\n    values.mapMode = 0x20 \r\n    | (values.cpuMode === CpuMode.Fast ? 0x10 : 0x00)\r\n    | (values.memoryMode === MemoryMapMode.Hi ? 1 : values.memoryMode === MemoryMapMode.ExHi ? 5 : 0);\r\n    return values;\r\n  }\r\n\r\n\r\n  public writeHeader(header: DbHeader, values: any, masterLookup: Record<string, AsmBlock>): void {\r\n    const buf = this.outBuffer!;\r\n    \r\n    let pos = new Address(header.bank, header.address, this.root.config.memoryMode).toLocation();\r\n\r\n    for (const part of header.parts) {\r\n      let type = part.type;\r\n      let value = part.value ?? values[part.name] ?? (type === 'string' ? '' : 0);\r\n      let size = part.size;\r\n\r\n      if(!size) {\r\n        if(!type) {\r\n          //Try to infer the type/size from the value\r\n          if(typeof value === 'string') throw new Error(`String size for ${part.name} is not specified`);\r\n          if(typeof value === 'number') {\r\n            if(value <= 0xFF) {\r\n              size = 1;\r\n              type = 'byte';\r\n            }\r\n            else {\r\n              size = 2;\r\n              type = 'word';\r\n            }\r\n          }\r\n        } else {\r\n          switch(type) {\r\n            case 'byte': size = 1; break;\r\n            case 'word': case 'entry': size = 2; break;\r\n            case 'string': throw new Error(`String size for ${part.name} is not specified`); break;\r\n            default: throw new Error(`Invalid type ${type} for ${part.name}`);\r\n          }\r\n        }\r\n      }\r\n\r\n      switch(part.type) {\r\n        case 'string':\r\n          value = value.toString();\r\n          value = value.length > size ? value.substring(0, size) : value.padEnd(size, ' ');\r\n          this.writeAscii(value, pos);\r\n          break;\r\n\r\n        case 'byte':\r\n          buf[pos] = value & 0xFF;\r\n          break;\r\n\r\n        case 'entry':\r\n          let location = 0;\r\n          if(typeof value === 'string') {\r\n            location = value === '' ? 0 : masterLookup[value.toUpperCase()]?.location ?? 0;\r\n          } else if(typeof value === 'number') {\r\n            location = value;\r\n          }\r\n          value = location;\r\n\r\n        case 'word':\r\n          buf[pos] = value & 0xFF;\r\n          buf[pos + 1] = (value >> 8) & 0xFF;\r\n          break;\r\n\r\n      }\r\n\r\n      part.value = value;\r\n      part.size = size;\r\n      part.type = type;\r\n\r\n      pos += size;\r\n    }\r\n\r\n    // //let pos = this.root.config.memoryMode === MemoryMapMode.Lo ? 0x7FB0 : 0xFFB0;\r\n    // this.writeAscii(this.makerCode.padEnd(6, ' '), pos); \r\n    // pos += 6;\r\n    // for (let i = 0; i < 10; i++) buf[pos++] = 0;\r\n    // this.writeAscii(this.cartName.toUpperCase().padEnd(21, ' '), pos); \r\n    // pos += 21;\r\n    // buf[pos++] = 0x20  // map mode\r\n    //   | (this.root.config.cpuMode === CpuMode.Fast ? 0x10 : 0x00)\r\n    //   | (this.root.config.memoryMode === MemoryMapMode.Hi ? 1 : this.root.config.memoryMode === MemoryMapMode.ExHi ? 5 : 0);\r\n    // buf[pos++] = this.root.config.chipset; // chipset\r\n    // buf[pos++] = this.romSize!; // ROM size\r\n    // buf[pos++] = this.root.config.ramSize; // RAM size\r\n    // buf[pos++] = 0x01; // country\r\n    // buf[pos++] = 0x33; // dev id\r\n    // buf[pos++] = 0x00; // version\r\n  }\r\n\r\n  public writeChecksum(values: any): void {\r\n    const buf = this.outBuffer!;\r\n\r\n    let sum = 0;\r\n    for (let i = 0; i < buf.length; i++) sum += buf[i];\r\n\r\n    const comp = ~sum;\r\n\r\n    for(const header of this.root.headers) {\r\n      if(header.condition && !eval(header.condition)) continue;\r\n      let pos = new Address(header.bank, header.address, this.root.config.memoryMode).toLocation();\r\n      for(const part of header.parts) {\r\n        if(part.name === 'checksum') {\r\n          buf[pos] = sum & 0xFF;\r\n          buf[pos + 1] = (sum >> 8) & 0xFF;\r\n        } else if(part.name === 'compliment') {\r\n          buf[pos] = comp & 0xFF;\r\n          buf[pos + 1] = (comp >> 8) & 0xFF;\r\n        }\r\n        pos += part.size;\r\n      }\r\n    }\r\n  \r\n    values.checksum = sum;\r\n    values.compliment = comp;\r\n  }\r\n\r\n  // private async generatePatch(): Promise<void> {\r\n  //   const flips = this._projectRoot.flipsPath;\r\n  //   if (!flips) return;\r\n  //   if (typeof process === 'undefined' || !process.versions?.node) return;\r\n  //   const { spawn } = await import('child_process');\r\n  //   const { resolve } = await import('path');\r\n  //   this.bpsPath = `${this._projectRoot.baseDir}/${this._projectRoot.name}.bps`;\r\n  //   await new Promise<void>((resolvePromise) => {\r\n  //     const p = spawn(flips, ['--create', '--bps', `${this._projectRoot.romPath}`, `${this.romPath}`, `${this.bpsPath}`], {\r\n  //       stdio: ['ignore', 'pipe', 'pipe']\r\n  //     });\r\n  //     p.on('close', () => resolvePromise());\r\n  //   });\r\n  // }\r\n\r\n  public writeEntryPoints(asmFiles: ChunkFile[]): void {\r\n    const buf = this.outBuffer!;\r\n    \r\n    // Entry point fixups\r\n    const entryBlocks = (asmFiles\r\n      .filter(x => (x.bank ?? -1) === 0)\r\n      .flatMap(x => x.parts || [])\r\n      .filter(b => !!b.label)) as { label?: string; location: number }[];\r\n\r\n    for (const ep of this.root.config.entryPoints) {\r\n      const match = entryBlocks.find(b => b.label === ep.name);\r\n      if (match) {\r\n        let location = match.location;\r\n        if(this.root.config.memoryMode === MemoryMapMode.Lo) location += RomProcessingConstants.PAGE_SIZE;\r\n        buf[ep.location] = location & 0xFF;\r\n        buf[ep.location + 1] = (location >> 8) & 0xFF;\r\n      }\r\n    }\r\n  }\r\n\r\n  // public writeTransform(location: number, value: number, size?: number): void {\r\n  //   const buf = this.outBuffer!;\r\n\r\n  //   // Determine size based on value range if not explicitly provided\r\n  //   if (size === undefined) {\r\n  //     if (value <= 0xFF) {\r\n  //       size = 1; // byte\r\n  //     } else if (value <= 0xFFFF) {\r\n  //       size = 2; // ushort \r\n  //     } else if (value <= 0xFFFFFF) {\r\n  //       size = 3; // uint (3 bytes)\r\n  //     } else {\r\n  //       size = 4; // full uint (4 bytes, though C# version only uses 3)\r\n  //     }\r\n  //   }\r\n\r\n  //   // Write bytes based on size\r\n  //   switch (size) {\r\n  //     case 1: // byte\r\n  //       buf[location] = value & 0xFF;\r\n  //       break;\r\n  //     case 2: // ushort\r\n  //       buf[location] = value & 0xFF;\r\n  //       buf[location + 1] = (value >> 8) & 0xFF;\r\n  //       break;\r\n  //     case 3: // uint (3 bytes as per C# version)\r\n  //       buf[location] = value & 0xFF;\r\n  //       buf[location + 1] = (value >> 8) & 0xFF;\r\n  //       buf[location + 2] = (value >> 16) & 0xFF;\r\n  //       break;\r\n  //     case 4: // full uint\r\n  //       buf[location] = value & 0xFF;\r\n  //       buf[location + 1] = (value >> 8) & 0xFF;\r\n  //       buf[location + 2] = (value >> 16) & 0xFF;\r\n  //       buf[location + 3] = (value >> 24) & 0xFF;\r\n  //       break;\r\n  //     default:\r\n  //       throw new Error(`Invalid size ${size} for writeTransform`);\r\n  //   }\r\n  // }\r\n\r\n  public async writeFile(file: ChunkFile, fileLookup: Record<string, number>): Promise<number> {\r\n    const start = file.location;\r\n    let pos = start;\r\n    const buf = this.outBuffer!;\r\n\r\n    if (file.rawData) {\r\n      // Write type-specific headers\r\n      const data = file.rawData;\r\n      let remain = file.size;\r\n      let srcPos = 0;\r\n\r\n      if (file.compressed !== true) {\r\n        if (file.type.header === -2) {\r\n          remain -= 2;\r\n          if(file.sizeHeader !== undefined) {\r\n            buf[pos++] = file.sizeHeader & 0xFF;\r\n            buf[pos++] = (file.sizeHeader >> 8) & 0xFF;\r\n          } else {\r\n            buf[pos++] = remain & 0xFF;\r\n            buf[pos++] = (remain >> 8) & 0xFF;\r\n          }\r\n        } else if (file.type.header > 0) {\r\n          remain -= file.type.header;\r\n          for (let i = 0; i < file.type.header; i++) buf[pos++] = data[srcPos++];\r\n        }\r\n      }\r\n\r\n      //Write null compression header\r\n      if (file.compressed === false) {\r\n        remain -= 2;\r\n        const size = (0 - remain) & 0xFFFF;\r\n        buf[pos++] = size & 0xFF;\r\n        buf[pos++] = (size >> 8) & 0xFF;\r\n      }\r\n\r\n      // Copy the rest\r\n      while (remain > 0) {\r\n        buf[pos++] = data[srcPos++];\r\n        remain--;\r\n      }\r\n    } else {\r\n      // Handle assembly parts\r\n      if (file.parts && file.parts.length > 0) {\r\n        // For safety, ensure first block location matches file location when present\r\n        if (file.parts[0].location !== file.location && (file.location || 0) !== 0) {\r\n          throw new Error('Assembly was not based properly');\r\n        }\r\n        \r\n        // Parse assembly parts\r\n        RomWriter.parseAssembly(this.root, file.parts, fileLookup, file.includeLookup!, this.outBuffer!, file.base);\r\n      }\r\n    }\r\n\r\n    return pos - start;\r\n  }\r\n\r\n  // No address mapping required: layout assigns absolute file offsets\r\n\r\n  private writeAscii(text: string, pos: number): void {\r\n    const buf = this.outBuffer!;\r\n    for (let i = 0; i < text.length; i++) buf[pos + i] = text.charCodeAt(i) & 0xFF;\r\n  }\r\n\r\n  /**\r\n   * Parse assembly blocks and write binary data to output buffer\r\n   * Converted from ext/GaiaLib/Rom/Rebuild/RomWriter.cs ParseAssembly method\r\n   */\r\n  public static parseAssembly(root: DbRoot, blocks: AsmBlock[], fileLookup: Record<string, number>, includeLookup: Record<string, AsmBlock>, outBuffer: Uint8Array, addrOffset?: number): void {\r\n    if (!blocks) {\r\n      throw new Error('Assembly has not been parsed');\r\n    }\r\n\r\n    let bix = 0;\r\n    const rootLoc = blocks[0].location;\r\n\r\n    for (const block of blocks) {\r\n      let position = block.location; // Always start at block's absolute location\r\n\r\n      const objList = block.objList;\r\n      let oix = 0;\r\n      let opos = 0;\r\n\r\n      // Process each object in the block's object list\r\n      const processObject = (obj: unknown, parentOp?: Op): void => {\r\n        let currentObj = obj;\r\n\r\n        while (true) { // Top: label equivalent\r\n          if (Array.isArray(currentObj)) {\r\n            for (const obj of currentObj) {\r\n              processObject(obj, parentOp);\r\n            }\r\n            break;\r\n          } else if (currentObj instanceof TableEntry) {\r\n            currentObj = currentObj.object;\r\n            continue;\r\n          } else if (currentObj instanceof Op) {\r\n            const op = currentObj as Op;\r\n            outBuffer[position++] = op.code & 0xFF;\r\n            opos += op.size;\r\n\r\n            for (const operand of op.operands) {\r\n              processObject(operand, op);\r\n            }\r\n            break;\r\n          } else if (currentObj instanceof Uint8Array) {\r\n            const arr = currentObj as Uint8Array;\r\n            for (let i = 0; i < arr.length; i++) {\r\n              outBuffer[position + i] = arr[i];\r\n            }\r\n            position += arr.length;\r\n            opos += arr.length;\r\n            break;\r\n          } else if (typeof currentObj === 'string') {\r\n            const str = currentObj as string;\r\n            let label = str;\r\n\r\n            let ix = 0;\r\n            while (ix < label.length && RomProcessingConstants.ADDRESS_SPACE.includes(label[ix])) {\r\n              ix++;\r\n            }\r\n\r\n            if (ix > 0) {\r\n              label = label.substring(ix);\r\n            }\r\n\r\n            let loc: number;\r\n            const isRelative = parentOp && \r\n              (parentOp.mode === 'PCRelative' || \r\n               parentOp.mode === 'PCRelativeLong');\r\n\r\n            const operatorIdx = RomWriter.indexOfAny(label, RomProcessingConstants.OPERATORS);\r\n            let offset: number | null = null;\r\n            let useMarker = false;\r\n\r\n            if (operatorIdx > 0) {\r\n              if (label[operatorIdx + 1] === 'M') {\r\n                useMarker = true;\r\n              } else {\r\n                offset = parseInt(label.substring(operatorIdx + 1), 16);\r\n                if (label[operatorIdx] === '-') {\r\n                  offset = -offset;\r\n                }\r\n              }\r\n              label = label.substring(0, operatorIdx);\r\n            }\r\n\r\n            const dotIx = label.indexOf('.');\r\n            if(dotIx > 0) label = label.substring(dotIx + 1);\r\n\r\n            // Search local labels first\r\n            const labelUpper = label.toUpperCase();\r\n            const target = includeLookup[labelUpper];\r\n\r\n            if (target) loc = target.location;\r\n            else if ((loc = fileLookup[labelUpper] ?? -1) < 0) {\r\n              // Handle direct hex values\r\n              if (label.startsWith('#')) {\r\n                label = label.substring(1);\r\n              }\r\n              if (label.startsWith('$')) {\r\n                label = label.substring(1);\r\n              }\r\n\r\n              if (isRelative && label.length > 4) {\r\n                throw new Error(`Invalid relative operand '${label}'`);\r\n                //const off = parseInt(label, 16) - (block.location + opos);\r\n                //currentObj = parentOp?.size === 2 ? (off & 0xFF) : (off & 0xFFFF);\r\n                //continue; // goto Top\r\n              } else {\r\n                let num: number;\r\n                switch (label.length) {\r\n                  case 1:\r\n                  case 2:\r\n                    currentObj = new Byte(parseInt(label, 16));\r\n                    continue;\r\n                  case 3:\r\n                  case 4:\r\n                    currentObj = new Word(parseInt(label, 16));\r\n                    continue;\r\n                  case 5:\r\n                  case 6:\r\n                    currentObj = new Long(parseInt(label, 16));\r\n                    continue;\r\n                  default:\r\n                    throw new Error(\r\n                      `Invalid operand '${label}'` +\r\n                      (parentOp ? ` (${parentOp.mnem} ${parentOp.mode})` : '')\r\n                    );\r\n                }\r\n              }\r\n            }\r\n\r\n            let type = isRelative ? (parentOp?.size === 3 ? AddressType.WRelative : AddressType.Relative) : Address.typeFromCode(str[0]);\r\n            if (type === AddressType.Unknown) {\r\n              type = parentOp?.size === 4 ? AddressType.Address\r\n                : parentOp?.size === 2 ? AddressType.Unknown : AddressType.Offset;\r\n            }\r\n\r\n            if (isRelative) {\r\n              loc -= block.location + opos;\r\n              if(type === AddressType.WRelative && Math.abs(loc) > 0x7FFF || type === AddressType.Relative && (loc < -0x80 || loc > 0x7F)) {\r\n                throw new Error(`Relative out of range in ${block.label}: ${parentOp?.mnem} '${label}' (${loc})`);\r\n              }\r\n              // if (type === AddressType.Unknown && !(loc < 0x80 || loc >= 0x3FFF80)) {\r\n              //   throw new Error('Relative out of range');\r\n              // }\r\n            }\r\n\r\n            if (offset !== null) {\r\n              loc += offset;\r\n            } else if (useMarker && target instanceof AsmBlock) {\r\n              let markerOffset = 0;\r\n              for (const part of target.objList) {\r\n                if (RomWriter.isStringMarker(part)) {\r\n                  loc += markerOffset;\r\n                  break;\r\n                } else {\r\n                  markerOffset += RomProcessingConstants.getSize(part);\r\n                }\r\n              }\r\n            }\r\n\r\n            if(addrOffset !== undefined) {\r\n              loc += addrOffset;\r\n              if(fileLookup?.size) loc -= rootLoc;\r\n            // } else if (type === AddressType.OddLocation) {\r\n            //   const bankFlag = root.config.cpuMode === CpuMode.Fast ? Address.FAST_BANK_FLAG : 0;\r\n            //   const bankReal = position >> 16;\r\n            //   const isVeryOdd = bankReal !== root.config.oddLocationBase;\r\n            //   //const bankBase = ((isVeryOdd ? Address.DATA_BANK_FLAG : 0) + bankReal) | bankFlag;\r\n            //   const bankMax = root.config.oddLocationSpan ?? (outBuffer.length >> 16);\r\n            //   //const bankSpan = (Address.DATA_BANK_FLAG - bankMax);\r\n \r\n            //   let oddBank = (loc >> 16);\r\n            //   if(loc & 0x8000) {\r\n            //     oddBank -= bankReal;\r\n            //   } else {\r\n            //     oddBank += bankMax - bankReal;\r\n            //   }\r\n\r\n            //   oddBank &= 0xFF;\r\n\r\n            //   currentObj = new Long((oddBank << 15) | (loc & 0x7FFF));\r\n            //   continue;\r\n            } else if(!isRelative && type !== AddressType.Location) {\r\n              const address = Address.fromLocation(loc, root.config.memoryMode, root.config.cpuMode);\r\n              loc = address.toInt();\r\n            }\r\n\r\n            switch (type) {\r\n              case AddressType.Offset:\r\n\r\n                if ((parentOp?.mnem === 'JSR' || parentOp?.mnem === 'JMP' || parentOp?.mnem === 'COP') && (block.location & 0x3F0000) !== (loc & 0x3F0000)) {\r\n                  console.log(`Cross bank call detected in ${block.label}: '${parentOp?.mnem} ${label}' (${loc.toString(16).toUpperCase()})`);\r\n                }\r\n\r\n              case AddressType.WRelative:\r\n                currentObj = new Word(loc);\r\n                continue;\r\n              case AddressType.Bank:\r\n                currentObj = new Byte(loc >> 16);\r\n                continue;\r\n              case AddressType.WBank:\r\n                currentObj = new Word(loc >> 16);\r\n                continue;\r\n              case AddressType.Address:\r\n              case AddressType.Location:\r\n              case AddressType.OddLocation:\r\n                currentObj = new Long(loc);\r\n                continue;\r\n              case AddressType.Unknown:\r\n              case AddressType.Relative:\r\n              default:\r\n                currentObj = new Byte(loc);\r\n                continue;\r\n            }\r\n            \r\n          } else if (currentObj instanceof TypedNumber) {\r\n            let value = currentObj.value;\r\n            for (let i = 0; i < currentObj.size; i++) {\r\n              outBuffer[position++] = value & 0xFF;\r\n              value >>= 8;\r\n              if(!parentOp) opos++;\r\n            }\r\n            break;\r\n          } else if (typeof currentObj === 'number') {\r\n            const num = currentObj as number;\r\n            const size = parentOp?.size ?? 0;\r\n            \r\n            if (num <= 0xFF && size <= 2) {\r\n              // byte\r\n              outBuffer[position] = num & 0xFF;\r\n              position++;\r\n              if(!parentOp) opos++;\r\n            } else if (num <= 0xFFFF && size <= 3) {\r\n              // ushort\r\n              outBuffer[position] = num & 0xFF;\r\n              outBuffer[position + 1] = (num >> 8) & 0xFF;\r\n              position += 2;\r\n              if(!parentOp) opos += 2;\r\n            } else if (num <= 0xFFFFFF && size <= 4) {\r\n              // 3-byte\r\n              outBuffer[position] = num & 0xFF;\r\n              outBuffer[position + 1] = (num >> 8) & 0xFF;\r\n              outBuffer[position + 2] = (num >> 16) & 0xFF;\r\n              position += 3;\r\n              if(!parentOp) opos += 3;\r\n            } else {\r\n              // 4-byte\r\n              outBuffer[position] = num & 0xFF;\r\n              outBuffer[position + 1] = (num >> 8) & 0xFF;\r\n              outBuffer[position + 2] = (num >> 16) & 0xFF;\r\n              outBuffer[position + 3] = (num >> 24) & 0xFF;\r\n              position += 4;\r\n              if(!parentOp) opos += 4;\r\n            }\r\n            break;\r\n          } else if (RomWriter.isStringMarker(currentObj)) {\r\n            // StringMarker - no operation needed\r\n            break;\r\n          } else {\r\n            throw new Error(`Unable to process '${currentObj}'`);\r\n          }\r\n        }\r\n      };\r\n\r\n      for (const obj of objList) {\r\n        oix++;\r\n        processObject(obj);\r\n      }\r\n\r\n      // Position management no longer needed since we use absolute locations\r\n\r\n      bix++;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Helper method to find index of any character from an array in a string\r\n   */\r\n  public static indexOfAny(str: string, chars: string[]): number {\r\n    for (let i = 0; i < str.length; i++) {\r\n      if (chars.includes(str[i])) {\r\n        return i;\r\n      }\r\n    }\r\n    return -1;\r\n  }\r\n\r\n  /**\r\n   * Helper method to check if an object is a StringMarker\r\n   */\r\n  public static isStringMarker(obj: unknown): obj is StringMarker {\r\n    return typeof obj === 'object' && obj !== null && 'offset' in obj;\r\n  }\r\n\r\n  public static isTableEntry(obj: unknown): obj is TableEntry {\r\n    return typeof obj === 'object' && obj !== null && 'location' in obj && 'object' in obj;\r\n  }\r\n}\r\n\r\n\r\n","import { BinType } from '../../types/resources';\r\nimport { ChunkFileUtils, type ChunkFile } from '../../types/files';\r\nimport { RomLayout } from './layout';\r\nimport { RomWriter } from './writer';\r\nimport { Assembler, RomProcessingConstants } from '../..';\r\nimport { DbRoot } from '../../database';\r\nimport { AsmBlock } from '../../types/assembly';\r\n\r\n/**\r\n * ROM rebuild processor\r\n * Converted from ext/GaiaLib/Rom/Rebuild/RomProcessor.cs\r\n */\r\nexport class RomProcessor {\r\n  private readonly writer: RomWriter;\r\n\r\n  constructor(writer: RomWriter) {\r\n    this.writer = writer;\r\n  }\r\n\r\n  public async repack(allFiles: ChunkFile[], modules?: string[]): Promise<Record<string, AsmBlock>> {\r\n    // Discover files\r\n    //const allFiles = await this.discoverFiles(this.writer._projectRoot.baseDir);\r\n\r\n    const patches : ChunkFile[] = [];\r\n    const asmFiles : ChunkFile[] = [];\r\n    const compression = this.writer.root.compression;\r\n    const canCompress = !!compression;\r\n    const conditionFiles : string[] = [];\r\n\r\n    if(modules) conditionFiles.push(...modules);\r\n    \r\n    const dummyMap: Record<string, number> = {};\r\n    for (const file of allFiles) {\r\n      conditionFiles.push(file.name);\r\n\r\n      if (file.type.isPatch) { patches.push(file); asmFiles.push(file);} \r\n      else if (file.type.isBlock) asmFiles.push(file);\r\n      else if (!file.struct) continue;\r\n      \r\n      const assembler = new Assembler(this.writer.root, file, conditionFiles);\r\n      const { blocks, includes, reqBank } = assembler.parseAssembly();\r\n      file.parts = blocks;\r\n      file.includes = includes;\r\n      file.bank = reqBank ?? void 0;\r\n\r\n      if(file.struct) {\r\n        file.includeLookup = {};\r\n        for (const b of file.parts) {\r\n          if(b.label) file.includeLookup[b.label.toUpperCase()] = b;\r\n        }\r\n        file.rawData = undefined;\r\n        file.rawData = new Uint8Array(ChunkFileUtils.calculateSize(file));\r\n        RomWriter.parseAssembly(this.writer.root, file.parts, dummyMap, file.includeLookup!, file.rawData!, file.base);\r\n      }\r\n    }\r\n\r\n    for(const file of allFiles) {\r\n      if(file.compressed === true && canCompress) {\r\n        if(this.writer.root.config.uncompress){\r\n          file.compressed = false;\r\n        } else {\r\n          let newData = compression!.compact(file.rawData!, file.type.header);\r\n          if(file.type.header) newData = new Uint8Array([...file.rawData!.slice(0, file.type.header), ...newData]);\r\n          file.rawData = newData;\r\n          file.size = newData.length;\r\n        }\r\n      }\r\n    }\r\n\r\n    // const patches = allFiles.filter(x => x.type.type === 'Patch');\r\n    // const asmFiles = allFiles.filter(x => !!x.parts);\r\n\r\n    // //Assemble code that hasn't been assembled yet\r\n    // for(const asm of asmFiles) {\r\n    //   if(!asm.parts) {\r\n    //     const assembler = new Assembler(this.writer.root, asm.textData!);\r\n    //     const { blocks, includes, reqBank } = assembler.parseAssembly();\r\n    //     asm.parts = blocks;\r\n    //     asm.includes = includes;\r\n    //     asm.bank = reqBank ?? undefined;\r\n    //   }\r\n    // }\r\n\r\n    // Assembly processing now happens in project.ts via ChunkBlockReader.analyzeAndResolveChunks()\r\n    // This provides comprehensive cross-referencing and object graph generation\r\n\r\n    const masterLookup: Record<string, AsmBlock> = {};\r\n\r\n    // Build include lookup map per asm file\r\n    for (const f of asmFiles) {\r\n      f.includeLookup = masterLookup;\r\n\r\n      //Add labels from current file\r\n      for (const b of f.parts!) {\r\n        let label = b.label;\r\n        if (label) {\r\n          const isOverride = f.type.isPatch && RomProcessingConstants.OVERRIDE_CHARS.includes(label[label.length - 1]);\r\n          if(isOverride) label = label.slice(0, -1);\r\n\r\n          label = label.toUpperCase();\r\n          if (masterLookup[label]) {\r\n            if (!isOverride) throw new Error(`Duplicate label in ${f.name}: ${label}`);\r\n          } else if (isOverride) {\r\n            //This will be handled by the patch processor\r\n            //throw new Error(`Label not found to override in ${f.name}: ${label}`);\r\n          } else {\r\n            masterLookup[label] = b;\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    // Apply patches to asm blocks\r\n    RomProcessor.applyPatches(asmFiles, patches, masterLookup);\r\n\r\n    // Calculate ASM sizes\r\n    for (const file of allFiles) ChunkFileUtils.calculateSize(file);\r\n\r\n    // Assign locations\r\n    const layout = new RomLayout(allFiles, this.writer.root);\r\n    const pages = layout.organize();\r\n\r\n    // Rebase assemblies\r\n    for (const file of asmFiles) ChunkFileUtils.rebase(file);\r\n\r\n    // Create block lookup for resolving labels to locations\r\n    const fileLookup: Record<string, number> = {};\r\n    for (const f of allFiles) fileLookup[f.name.toUpperCase()] = f.location;\r\n    \r\n    //Allocate memory for the ROM\r\n    this.writer.allocate(pages);\r\n\r\n    // Write all files\r\n    for (const file of allFiles) await this.writer.writeFile(file, fileLookup);\r\n\r\n    return masterLookup;\r\n  }\r\n\r\n  public static applyPatches(asmFiles: ChunkFile[], patches: ChunkFile[], masterLookup: Record<string, AsmBlock>): void {\r\n    for (const patch of patches) {\r\n      if(!patch.parts) continue;\r\n\r\n\r\n      //Separate top level code from the rest of the patch\r\n      let topIx = 0;\r\n      while (topIx < patch.parts.length) {\r\n        const label = patch.parts[topIx].label;\r\n        if(label && RomProcessingConstants.OVERRIDE_CHARS.includes(label[label.length - 1])) break;\r\n        topIx++;\r\n      }\r\n\r\n      const rewriteParts = patch.parts.slice(topIx);\r\n      patch.parts = patch.parts.slice(0, topIx);\r\n      \r\n      let file = patch;\r\n      let dstIx = -1;\r\n\r\n      //Process rewrite parts in their own list/loop\r\n      for (const newPart of rewriteParts) {\r\n        let label = newPart.label!;\r\n        const lastChar = label[label.length - 1];\r\n\r\n        //Handle rewrite commands\r\n        if (RomProcessingConstants.OVERRIDE_CHARS.includes(lastChar)) {\r\n          label = label.slice(0, -1).toUpperCase();\r\n          const match = masterLookup[label];\r\n          if(!match) throw new Error(`Patch ${patch.name} contains a rewrite that does not exist: ${label}`);\r\n\r\n          file = match.file!;\r\n          dstIx = file.parts!.indexOf(match);\r\n\r\n          switch (lastChar) {\r\n            case '!':\r\n              masterLookup[label] = newPart;\r\n              file.parts![dstIx++] = newPart;\r\n              newPart.file = file;\r\n              continue;\r\n            case '+': dstIx++;\r\n            case '-': \r\n              if (match.objList[match.objList.length - 1].isDelimiter) {\r\n                if (lastChar === '+') {\r\n                  const delimiter = match.objList.pop();\r\n                  match.objList.push(...newPart.objList);\r\n                  match.size += newPart.size;\r\n                  if (!match.objList[match.objList.length - 1].isDelimiter) match.objList.push(delimiter);\r\n                  else match.size--;\r\n                }\r\n                else { \r\n                  if (newPart.objList[newPart.objList.length - 1].isDelimiter) {\r\n                    newPart.objList.pop();\r\n                    newPart.size--;\r\n                  }\r\n                  match.objList.unshift(...newPart.objList);\r\n                  match.size += newPart.size;\r\n                }\r\n                newPart.file = file;\r\n                continue;\r\n              }\r\n              break;\r\n          }\r\n        }\r\n\r\n        file.parts!.splice(dstIx++, 0, newPart);\r\n        newPart.file = file;\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n\r\n","import { DbRoot, DbStringCommand, DbStringLayer, DbStringType } from '../../database';\r\nimport { MemberType, StringMarker } from '../../types';\r\nimport type { Assembler } from './assembler';\r\n\r\n/**\r\n * String processor for assembly parsing\r\n * Converted from GaiaLib/Rom/Rebuild/StringProcessor.cs\r\n */\r\nexport class StringProcessor {\r\n  private memBuffer: number[] = [];\r\n  private totalSize: number = 0;\r\n  private fixedStr: number = 0;\r\n  private readonly context: Assembler;\r\n  private readonly root: DbRoot;\r\n  private readonly stringCharLookup: Record<string, DbStringType>;\r\n  private readonly testRegex: RegExp;\r\n  private inShift: boolean = false;\r\n\r\n  constructor(context: Assembler) {\r\n    this.context = context;\r\n    this.root = context.root;\r\n    this.stringCharLookup = context.root.stringDelimiterLookup;\r\n    this.testRegex = new RegExp(/^[0-9A-F]+$/i);\r\n  }\r\n\r\n  public consumeString(typeChar: string): void {\r\n    let str: string | null = null;\r\n    let fixedStr: number = 0;\r\n    let isRaw = false;\r\n\r\n    // Get character code of string type\r\n    //const typeChar = this.context.lineBuffer[0];\r\n\r\n    // Find last index of character code\r\n    const endIx = this.context.lineBuffer.indexOf(typeChar, 1);\r\n    if (endIx >= 0) {\r\n      // Take the line up until the type code\r\n      str = this.context.lineBuffer.substring(1, endIx);\r\n      // Line takes content after and code\r\n      this.context.lineBuffer = this.context.lineBuffer.substring(endIx + 1).replace(/^[\\s,\\t]+/, '');\r\n      \r\n      if(this.context.lineBuffer[0] === '(') {\r\n        const endIx = this.context.lineBuffer.indexOf(')');\r\n        if(endIx >= 0) {\r\n          fixedStr = parseInt(this.context.lineBuffer.substring(1, endIx), 10);\r\n          this.context.lineBuffer = this.context.lineBuffer.substring(endIx + 1).replace(/^[\\s,\\t]+/, '');\r\n        }\r\n      }\r\n      \r\n      isRaw = this.context.lineBuffer[0] === '!';\r\n      if(isRaw) this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n\r\n    } else {\r\n      // Take the remaining line\r\n      str = this.context.lineBuffer.substring(1);\r\n      this.context.lineBuffer = '';\r\n    }\r\n\r\n    // Reset memory buffer for new string\r\n    this.memBuffer.length = 0;\r\n    this.totalSize = 0;\r\n    this.fixedStr = fixedStr;\r\n\r\n    this.processString(str!, typeChar, isRaw);\r\n  }\r\n\r\n  private flushBuffer(stringType: DbStringType, wrap: boolean = false): void {\r\n    const size = this.memBuffer.length;\r\n    if (size > 0) {\r\n      const newSize = this.totalSize + size;\r\n      if(this.fixedStr && newSize > this.fixedStr) {\r\n        const buffer = new Uint8Array(this.memBuffer.slice(0, this.fixedStr - this.totalSize));\r\n        this.context.currentBlock!.objList.push(buffer);\r\n        this.context.currentBlock!.size += buffer.length;\r\n        this.totalSize = this.fixedStr;\r\n      } else {\r\n        const buffer = new Uint8Array(this.memBuffer);\r\n        this.context.currentBlock!.objList.push(buffer);\r\n        this.context.currentBlock!.size += size;\r\n        this.totalSize += size;\r\n      }\r\n      this.memBuffer.length = 0;\r\n    }\r\n  }\r\n\r\n  private processString(str: string, typeChar: string, isRaw: boolean): void {\r\n    const stringType = this.stringCharLookup[typeChar];\r\n    const dictionaries = stringType.dictionaryLookup;\r\n    const cmdLookup = stringType.commands;\r\n    let currentLayer = stringType.layers[0];\r\n\r\n    //const charMap = stringType.characterMap;\r\n    //const shift = this.getShiftUp(stringType.shiftType);\r\n    let lastCmd: DbStringCommand | null = null;\r\n\r\n    let fullMatch = false;\r\n    if (!isRaw) {\r\n      for(const dictionary of dictionaries) {\r\n        let index : number;\r\n        while((index = str.indexOf(dictionary.text)) >= 0) {\r\n          if(index === 0 && str.length === dictionary.text.length) {\r\n            fullMatch = true;\r\n            break;\r\n          }\r\n          str = str.substring(0, index) + `[${(dictionary.id).toString(16).toUpperCase()}]` + str.substring(index + dictionary.text.length);\r\n        }\r\n        if(fullMatch) break;\r\n      }\r\n    }\r\n\r\n\r\n    for (let x = 0; x < str.length; x++) {\r\n      const c = str[x];\r\n      if (c === '[') {\r\n        const endIx = str.indexOf(']', x + 1);\r\n        const splitChars = [':', ',', ' '];\r\n\r\n        const parts = str.substring(x + 1, endIx)\r\n          .split(new RegExp(`[${splitChars.join('')}]`))\r\n          .filter(p => p.length > 0);\r\n\r\n        x = endIx;\r\n\r\n        // Marker\r\n        if (parts.length === 0) {\r\n          this.flushBuffer(stringType, true);\r\n          this.context.currentBlock!.objList.push({\r\n            offset: this.context.currentBlock!.size\r\n          } as StringMarker);\r\n          continue;\r\n        }\r\n\r\n        const cmd = cmdLookup[parts[0]];\r\n        if (cmd) {\r\n          lastCmd = cmd;\r\n          this.memBuffer.push(cmd.id);\r\n          this.processStringCommand(cmd, stringType, parts);\r\n          continue;\r\n        }\r\n\r\n        //Direct values for dictionary commands etc\r\n        if(parts.length === 1 && this.testRegex.test(parts[0])) {\r\n          const value = parseInt(parts[0], 16);\r\n          if(value < 0x100) this.memBuffer.push(value);\r\n          else this.memBuffer.push((value >> 8) & 0xFF, value & 0xFF);\r\n          continue;\r\n        }\r\n      }\r\n\r\n      lastCmd = null;\r\n\r\n      // Process string layers\r\n      let found = false;\r\n      for (const layer of stringType.layers) {\r\n        for (let i = 0, len = layer.map.length; i < len; i++) {\r\n          const v = layer.map[i];\r\n          if (c === v) {\r\n            //Toggle layers if they are not active\r\n            if(layer.on !== undefined && currentLayer !== layer) {\r\n              this.memBuffer.push(layer.on);\r\n              currentLayer = layer;\r\n            }\r\n\r\n            let value = i + (layer.base ?? 0);\r\n            if(typeof layer.shiftBit === 'number') {\r\n              const shiftBit = 1 << layer.shiftBit;\r\n              const lowerFlag = shiftBit - 1;\r\n              const upperFlag = ~lowerFlag;\r\n              value = ((value & upperFlag) << 1) | (value & lowerFlag);\r\n            }\r\n            this.memBuffer.push(value);\r\n            found = true; \r\n            break;\r\n          }\r\n        }\r\n        if(found) break;\r\n      }\r\n    }\r\n\r\n    if(this.fixedStr) {\r\n      let count = this.fixedStr - this.totalSize;\r\n      while(count--) this.memBuffer.push(stringType.terminator);\r\n    } else if (lastCmd === null || !lastCmd.halt) {\r\n      this.memBuffer.push(stringType.terminator);\r\n    }\r\n\r\n    this.flushBuffer(stringType, true);\r\n  }\r\n\r\n  private processStringCommand(cmd: DbStringCommand, stringType: DbStringType, parts: string[]): void {\r\n    const hasPointer = cmd.types.includes(MemberType.Address) || cmd.types.includes(MemberType.Offset);\r\n    // if (hasPointer) {\r\n    //   this.flushBuffer(stringType, true);\r\n    // }\r\n\r\n    for (let y = 0, pix = 1; y < cmd.types.length; y++, pix++) {\r\n      switch (cmd.types[y]) {\r\n        case MemberType.Byte:\r\n          this.memBuffer.push(parseInt(parts[pix], 16));\r\n          break;\r\n\r\n        case MemberType.Word:\r\n          const us = parseInt(parts[pix], 16);\r\n          this.memBuffer.push(us & 0xFF);\r\n          this.memBuffer.push((us >> 8) & 0xFF);\r\n          break;\r\n\r\n        case MemberType.Binary:\r\n          while (pix < parts.length) {\r\n            const ch = parseInt(parts[pix], 16);\r\n            this.memBuffer.push(ch);\r\n            pix++;\r\n          }\r\n          if (cmd.delimiter !== undefined) {\r\n            this.memBuffer.push(cmd.delimiter);\r\n          }\r\n          break;\r\n\r\n        case MemberType.Offset:\r\n        case MemberType.Address:\r\n          this.flushBuffer(stringType, true);\r\n          // Have to keep these for later since we don't have lookups yet\r\n          //this.flushBuffer(stringType, false);\r\n          this.context.currentBlock!.objList.push(parts[pix]);\r\n          this.context.currentBlock!.size += cmd.types[y] === MemberType.Offset ? 2 : 3;\r\n          break;\r\n      }\r\n    }\r\n\r\n    // if (hasPointer) {\r\n    //   this.flushBuffer(stringType, false);\r\n    // }\r\n  }\r\n}\r\n","import { Byte, RomProcessingConstants, AsmBlock, Op, Word, Long, MemberType } from '../../types';\r\nimport { DbRoot, DbStruct, OpCode } from '../../database';\r\nimport type { Assembler } from './assembler';\r\nimport { AsmReader } from '../extraction/asm';\r\nimport { TypeParser } from '../extraction';\r\n\r\n/**\r\n * Assembler state machine for processing assembly text\r\n * Converted from GaiaLib/Rom/Rebuild/AssemblerState.cs\r\n */\r\nexport class AssemblerState {\r\n  private readonly dbStruct?: DbStruct;\r\n  private readonly parentStruct?: DbStruct;\r\n  private readonly root: DbRoot;\r\n  private readonly discriminator?: number;\r\n  private readonly discriminatorLogic?: string;\r\n  private readonly discriminatorSize: number | undefined;\r\n  private delimiter?: number;\r\n  private memberOffset: number;\r\n  private dataOffset: number;\r\n  private readonly memberTypes?: string[];\r\n  private currentType?: string;\r\n  private readonly context: Assembler;\r\n  private readonly openTag?: string;\r\n\r\n  constructor(context: Assembler, structType?: string, openTag?: string, saveDelimiter: boolean = false) {\r\n    this.context = context;\r\n    this.root = context.root;\r\n    this.openTag = openTag;\r\n\r\n    if (structType) {\r\n      const cleanedType = structType.replaceAll('-', '_').replaceAll(' ', '_').toLowerCase();\r\n      this.dbStruct = this.root.structs[cleanedType];\r\n      if (!this.dbStruct) {\r\n        if (openTag === '<' || !TypeParser.tryParseMemberType(structType)) {\r\n          throw new Error(`Unknown struct type: ${structType}`);\r\n        }\r\n      } else {\r\n        const parentName = this.dbStruct.parent?.replaceAll('-', '_').replaceAll(' ', '_').toLowerCase();\r\n        this.parentStruct = this.root.structs[parentName ?? ''];\r\n        if (parentName && !this.parentStruct) throw new Error(`Unknown parent struct type: ${parentName}`);\r\n      }\r\n    } else if (openTag === '<') {\r\n      throw new Error(`Struct type required for < tag.`);\r\n    }\r\n\r\n    this.discriminator = this.parentStruct?.discriminator;\r\n    this.discriminatorLogic = this.dbStruct?.discriminatorLogic ?? this.parentStruct?.discriminatorLogic ?? \"=\";\r\n    this.discriminatorSize = this.parentStruct?.discriminatorSize ?? 1;\r\n    this.delimiter = this.dbStruct?.delimiter;\r\n    this.memberOffset = 0;\r\n    this.dataOffset = 0;\r\n    this.memberTypes = this.dbStruct?.types;\r\n    this.currentType = this.memberTypes?.[this.memberOffset];\r\n\r\n    if (saveDelimiter) {\r\n      this.context.lastDelimiter = this.dbStruct?.delimiter ?? this.parentStruct?.delimiter;\r\n    }\r\n  }\r\n\r\n  private checkDisc(): void {\r\n    if (this.discriminator === this.dataOffset && this.discriminatorLogic === \"=\") {\r\n      const discriminator = this.dbStruct!.discriminator!;\r\n      const size = this.dbStruct!.discriminatorSize ?? this.discriminatorSize ?? 1;\r\n      if(discriminator > 255 || size > 1) {\r\n        this.context.currentBlock!.objList.push(new Word(discriminator));\r\n        this.context.currentBlock!.size += 2;\r\n        this.dataOffset += 2;\r\n      } else {\r\n        this.context.currentBlock!.objList.push(new Byte(discriminator));\r\n        this.context.currentBlock!.size += 1;\r\n        this.dataOffset += 1;\r\n      }\r\n    }\r\n  }\r\n\r\n  private advancePart(): void {\r\n    if (this.currentType != null && this.discriminator != null) {\r\n      this.dataOffset += RomProcessingConstants.getSize(this.currentType);\r\n    }\r\n\r\n    if (this.memberTypes != null && this.memberOffset + 1 < this.memberTypes.length) {\r\n      this.currentType = this.memberTypes[++this.memberOffset];\r\n    }\r\n  }\r\n\r\n  // private processOrigin(): void {\r\n  //   this.context.lineBuffer = this.context.lineBuffer.substring(3).replace(/^[\\s,\\t]+/, '');\r\n  //   if (this.context.lineBuffer.startsWith('$')) {\r\n  //     this.context.lineBuffer = this.context.lineBuffer.substring(1);\r\n  //   }\r\n\r\n  //   let hex: string;\r\n  //   const endIx = this.context.lineBuffer.search(/[\\s,\\t]/);\r\n  //   if (endIx >= 0) {\r\n  //     hex = this.context.lineBuffer.substring(0, endIx);\r\n  //     this.context.lineBuffer = this.context.lineBuffer.substring(endIx + 1).replace(/^[\\s,\\t]+/, '');\r\n  //   } else {\r\n  //     hex = this.context.lineBuffer;\r\n  //     this.context.lineBuffer = '';\r\n  //   }\r\n\r\n  //   const location = parseInt(hex, 16);\r\n\r\n  //   this.context.blocks.push(this.context.currentBlock = new AsmBlock(this.context.file, location));\r\n  //   //this.context.blockIndex++;\r\n  // }\r\n\r\n  private static doMath(operand: string): string {\r\n    const ix = operand.search(/[-+]/);\r\n    if (ix >= 0) {\r\n      const op = operand[ix];\r\n\r\n      const vix = operand.lastIndexOf('$', ix) + 1;\r\n\r\n      const valueStr = operand.substring(vix, ix);\r\n      if (valueStr.match(/^[a-fA-F0-9]+$/)) {\r\n        const value = parseInt(valueStr, 16);\r\n        \r\n        let endIx = operand.substring(ix + 1).search(RomProcessingConstants.SYMBOL_SPACE_REGEX);\r\n        endIx = endIx < 0 ? operand.length : (endIx + ix + 1);\r\n\r\n        const number = parseInt(operand.substring(ix + 1, endIx), 16);\r\n        const result = value + ((op === '-') ? -number : number);\r\n\r\n        const len = (ix - vix) <= 2 ? 2 : (ix - vix) <= 4 ? 4 : 6;\r\n\r\n        operand = operand.substring(0, vix) + result.toString(16).toUpperCase().padStart(len, '0') + operand.substring(endIx);\r\n      }\r\n    }\r\n    return operand;\r\n  }\r\n\r\n  private tryCreateLabel(mnemonic: string, operand?: string): boolean {\r\n    // Check that the operand has content\r\n    if (!operand || operand.length === 0) {\r\n      return false;\r\n    }\r\n\r\n    const labelChar = operand[0];\r\n\r\n    // If our operand starts with a label space character, create a label\r\n    if (!RomProcessingConstants.LABEL_SPACE.includes(labelChar)) {\r\n      return false;\r\n    }\r\n\r\n    // Create new block for this label\r\n    const newBlock = new AsmBlock(\r\n      this.context.file,\r\n      this.context.currentBlock!.location + this.context.currentBlock!.size,\r\n      0,\r\n      mnemonic,\r\n      //undefined,\r\n      //this.root.stringDelimiters.includes(operand[0])\r\n    );\r\n    // const conditionBlock = this.context.conditionBlock;\r\n    // if(conditionBlock) {\r\n    //   conditionBlock.objList.push(newBlock);\r\n    // } else {\r\n    this.context.blocks.push(newBlock);\r\n    //}\r\n\r\n    // Set as current\r\n    this.context.currentBlock = newBlock;\r\n\r\n    // Increment current block index\r\n    //this.context.blockIndex++;\r\n\r\n    // Remove label marker\r\n    if (labelChar === ':') this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n    // } else if (labelChar === '[' || labelChar === '{') {\r\n    //   this.context.lineBuffer = operand.substring(1).replace(/^[\\s,\\t]+/, '');\r\n\r\n    //   // Process the next \r\n    //   const state = new AssemblerState(this.context, this.currentType);\r\n    //   state.processText(labelChar);\r\n\r\n    //   // Advance to next part\r\n    //   this.advancePart();\r\n    // }\r\n\r\n    return true;\r\n  }\r\n\r\n  public processText(): void {\r\n    this.checkDisc();\r\n\r\n    while (!this.context.eof) {\r\n      if (!this.context.getLine()) {\r\n        return;\r\n      }\r\n\r\n      // if (this.context.lineBuffer.startsWith('DB')) {\r\n      //   const hex = this.context.lineBuffer.substring(2).replace(HEX_REGEX, '');\r\n      //   const data = this.hexStringToBytes(hex);\r\n      //   this.context.currentBlock!.objList.push(data);\r\n      //   this.context.currentBlock!.size += data.length;\r\n      //   this.context.lineBuffer = '';\r\n      //   continue;\r\n      // }\r\n\r\n      let mnemonic: string | null = null;\r\n      let operand: string | null = null;\r\n      let operand2: string | null = null;\r\n\r\n      while (this.context.lineBuffer.length > 0) {\r\n        const lineSymbol = this.context.lineBuffer[0];\r\n\r\n        // Process strings\r\n        if (this.root.stringDelimiters.includes(lineSymbol)) {\r\n          this.context.stringProcessor.consumeString(lineSymbol);\r\n          this.advancePart();\r\n          continue;\r\n        }\r\n\r\n        // Process raw data\r\n        if (RomProcessingConstants.ADDRESS_SPACE.includes(lineSymbol)) {\r\n          this.context.processRawData();\r\n\r\n          if (this.openTag === '[') {\r\n            this.context.lastDelimiter = undefined;\r\n          }\r\n\r\n          this.advancePart();\r\n          continue;\r\n        }\r\n\r\n        if (lineSymbol === '>') {\r\n          if (this.openTag === '<') {\r\n            this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n            this.checkDisc();\r\n            if(this.dbStruct?.tail !== undefined) {\r\n              this.context.currentBlock!.objList.push(new Uint8Array(this.dbStruct.tail));\r\n              this.context.currentBlock!.size += this.dbStruct.tail;\r\n            }\r\n          }\r\n          return;\r\n        }\r\n\r\n        // Array Close\r\n        if (lineSymbol === ']') {\r\n          this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n\r\n          this.delimiter = this.delimiter ?? this.context.lastDelimiter;\r\n\r\n          // Apply delimiter if set\r\n          if (this.delimiter != null) {\r\n            if (this.delimiter >= 0x100) {\r\n              // When over the word boundary use two bytes\r\n              this.context.currentBlock!.objList.push(new Word(this.delimiter, true));\r\n              this.context.currentBlock!.size += 2;\r\n            } else {\r\n              // Otherwise default to single byte\r\n              this.context.currentBlock!.objList.push(new Byte(this.delimiter, true));\r\n              this.context.currentBlock!.size += 1;\r\n            }\r\n          }\r\n\r\n          return;\r\n        }\r\n\r\n        if(lineSymbol === '{') {\r\n          this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n          const state = new AssemblerState(this.context, this.currentType, '{');\r\n          state.processText();\r\n          this.advancePart();\r\n          continue;\r\n        }\r\n\r\n        // Block close\r\n        if (lineSymbol === '}') {\r\n          if (this.openTag === '{') {\r\n            this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n          }\r\n          return;\r\n        }\r\n\r\n        // Array Open\r\n        if (lineSymbol === '[') {\r\n          this.context.lineBuffer = this.context.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n          const state = new AssemblerState(this.context, this.currentType, '[');\r\n          state.processText();\r\n          this.advancePart();\r\n          continue;\r\n        }\r\n\r\n        // // Process origin tags\r\n        // if (this.context.lineBuffer.startsWith('ORG')) {\r\n        //   this.processOrigin();\r\n        //   continue;\r\n        // }\r\n\r\n        // Separate instructions into mnemonic and operand parts\r\n        const symbolIndex = this.context.lineBuffer.search(RomProcessingConstants.SYMBOL_SPACE_REGEX);\r\n        if (symbolIndex > 0) {\r\n          mnemonic = this.context.lineBuffer.substring(0, symbolIndex);\r\n          operand = this.context.lineBuffer.substring(symbolIndex).replace(/^[, \\t]+/, '');\r\n\r\n          // Process object tags\r\n          if (operand && operand.startsWith('<')) {\r\n            this.context.lineBuffer = operand.substring(1).replace(/^[, \\t]+/, '');\r\n            const state = new AssemblerState(this.context, mnemonic, '<', this.openTag === '[' && this.currentType == null);\r\n            state.processText();\r\n            mnemonic = null;\r\n            continue;\r\n          }\r\n          \r\n          this.context.lineBuffer = operand;\r\n        } else {\r\n          mnemonic = this.context.lineBuffer;\r\n          this.context.lineBuffer = '';\r\n        }\r\n\r\n        break;\r\n      }\r\n\r\n      if (mnemonic && mnemonic.length > 0) {\r\n\r\n        if(mnemonic == 'null' && this.dbStruct?.null !== undefined) {\r\n          if(this.dbStruct.null > 255) {\r\n            this.context.currentBlock!.objList.push(new Word(this.dbStruct.null));\r\n            this.context.currentBlock!.size += 2;\r\n          } else {\r\n            this.context.currentBlock!.objList.push(new Byte(this.dbStruct.null));\r\n            this.context.currentBlock!.size += 1;\r\n          }\r\n          continue;\r\n        }\r\n\r\n        // Get list of opcodes from mnemonic\r\n        const codes = this.root.opLookup[mnemonic.toUpperCase()];\r\n\r\n        // If no codes were found, try to create a label\r\n        if (!codes || codes.length === 0) {\r\n          if (this.tryCreateLabel(mnemonic, operand || undefined)) {\r\n            continue;\r\n          }\r\n\r\n          // If label creation fails, throw exception\r\n          throw new Error(`Unknown instruction line ${this.context.lineCount}: '${mnemonic}'`);\r\n        }\r\n\r\n        // Reset current assembler line\r\n        this.context.lineBuffer = '';\r\n\r\n        // No operand instructions\r\n        if (!operand) {\r\n          const opCode = codes.find(x => this.root.addrLookup[x.mode].size === 1);\r\n          if (!opCode) throw new Error(`Unknown instruction line ${this.context.lineCount}: '${mnemonic}'`);\r\n          this.context.currentBlock!.objList.push(new Op (opCode, 0, [], 1));\r\n          this.context.currentBlock!.size++;\r\n          continue;\r\n        }\r\n        \r\n        const operandParts = operand.split(/[\\s\\t,()[\\]#$&+-]/).filter(p => p.length > 0);\r\n\r\n        for(let i = 0; i < operandParts.length; i++) {\r\n          const part = operandParts[i];\r\n          let mnemonicStr = this.context.tags[part] ?? this.root.mnemonicsLookup[part];\r\n          if (mnemonicStr) operand = operand.replace(part, mnemonicStr);\r\n        }\r\n\r\n        // COP processing\r\n        let opCode: OpCode | null = codes[0];\r\n        if (opCode?.mnem === 'COP') {\r\n          const parts = operand.split(/[\\s\\t,()[\\]$#]/).filter(p => p.length > 0);\r\n          const cmd = parts[0];\r\n\r\n          let cop = this.root.copLookup[cmd];\r\n          if (!cop && cmd.match(/^[a-fA-F0-9]{2}$/)) cop = this.root.copDef[parseInt(cmd, 16)];\r\n\r\n          if(!cop) throw new Error(`Unknown COP command ${cmd}`);\r\n\r\n          let size = 2;\r\n          const operands : any[] = [ new Byte(cop.id) ];\r\n          for(let i = 1; i < parts.length; i++) {\r\n            let part = parts[i];\r\n\r\n            if(part[0] === '#') part = part.substring(1);\r\n            if(part[0] === '$') part = part.substring(1);\r\n            \r\n            if(part.match(/^[a-fA-F0-9]+$/)) {\r\n              let value = parseInt(part, 16);\r\n              if(part.length <= 2) {\r\n                operands.push(new Byte(value));\r\n                size++;\r\n              } else if(part.length <= 4) {\r\n                operands.push(new Word(value));\r\n                size+=2;\r\n              } else {\r\n                operands.push(new Long(value));\r\n                size+=3;\r\n              }\r\n            } else {\r\n              operands.push(parts[i]);\r\n              switch(part[0]) {\r\n                case '^': size++; break;\r\n                case '*':\r\n                case '&': size += 2; break;\r\n                case '%':\r\n                case '!':\r\n                case '@': size += 3; break;\r\n                default: throw new Error(`Unknown COP operand ${part}`);\r\n              }\r\n            }\r\n          }\r\n\r\n          this.context.currentBlock!.objList.push(new Op(opCode, 0, operands, size));\r\n          this.context.currentBlock!.size += size;\r\n          continue;\r\n        }\r\n\r\n        operand = AssemblerState.doMath(operand);\r\n\r\n        opCode = null;\r\n        for (const code of codes) {\r\n          // Keep branch operands until all blocks are processed (for labels)\r\n          if (code.mode === 'PCRelative' || code.mode === 'PCRelativeLong') {\r\n            opCode = code;\r\n            break;\r\n          }\r\n\r\n          // Regex parse operand based on addressing mode\r\n          const addrMode = this.root.addrLookup[code.mode]; \r\n          const regex = addrMode.parseRegex;\r\n          if (regex) {\r\n            const match = new RegExp(regex).exec(operand);\r\n            if (match) {\r\n              // Keep the current code\r\n              opCode = code;\r\n\r\n              // Operand is the \"first\" matched group\r\n              operand = match[1];\r\n\r\n              // Support for second operand (MVN/MVP)\r\n              if (match.length > 2) {\r\n                operand2 = match[2];\r\n              }\r\n\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        if (operand!.startsWith('#')) {\r\n          operand = operand!.substring(1);\r\n        }\r\n\r\n        if (operand!.startsWith('$')) {\r\n          operand = operand!.substring(1);\r\n        }\r\n\r\n        if (opCode == null) {\r\n          const addrIx = operand!.search(RomProcessingConstants.ADDRESS_SPACE_REGEX);\r\n          if (addrIx && addrIx >= 0) {\r\n            const eix = operand!.search(/[\\s\\t,\\])]/);\r\n            if (eix && eix >= 0) {\r\n              operand = operand!.substring(addrIx, eix);\r\n            }\r\n          }\r\n\r\n          opCode = codes.find(x => x.mode === 'Immediate')\r\n            ?? codes.find(x => x.mode === 'AbsoluteLong')\r\n            ?? codes.find(x => x.mode === 'Absolute')\r\n            ?? null;\r\n\r\n          if (opCode == null) {\r\n            throw new Error(`Unable to determine mode/code line ${this.context.lineCount}: '${this.context.lineBuffer}'`);\r\n          }\r\n        }\r\n\r\n        const opnd1 = this.context.parseOperand(operand!);\r\n\r\n        const addrMode = this.root.addrLookup[opCode.mode];\r\n        let size = addrMode.size;\r\n        if (size === AsmReader.VARIABLE_SIZE_INDICATOR || opCode.mode === 'Immediate') {\r\n          size = operand?.startsWith('^') || operand?.length === 2 ? 2 : 3;\r\n        }\r\n\r\n        const operands: unknown[] = operand2 != null ? [opnd1, this.context.parseOperand(operand2)] : [opnd1];\r\n\r\n        this.context.currentBlock!.objList.push(new Op(opCode, 0, operands, size));\r\n\r\n        this.context.currentBlock!.size += size;\r\n      }\r\n    }\r\n  }\r\n\r\n  private hexStringToBytes(hex: string): Uint8Array {\r\n    const result = new Uint8Array(hex.length / 2);\r\n    for (let i = 0; i < hex.length; i += 2) {\r\n      result[i / 2] = parseInt(hex.substring(i, i + 2), 16);\r\n    }\r\n    return result;\r\n  }\r\n}\r\n","import { RomProcessingConstants, Word, Byte, Long } from '../../types';\r\nimport { DbRoot } from '../../database';\r\nimport { AsmBlock } from '../../types/assembly';\r\nimport { ChunkFile } from '../../types';\r\nimport { StringProcessor } from './string-processor';\r\nimport { SortedMap } from './sorted-map';\r\nimport { AssemblerState } from './assembler-state';\r\n\r\n// export class ConditionBlock extends AsmBlock {\r\n//   public condition: string;\r\n//   //public next: ConditionBlock | null = null;\r\n\r\n//   constructor(location: number = 0, condition: string) {\r\n//     super(location, 0, false, undefined, undefined, undefined);\r\n//     this.condition = condition;\r\n//   }\r\n// }\r\n\r\n/**\r\n * Main assembler class for parsing assembly files\r\n * Converted from GaiaLib/Rom/Rebuild/Assembler.cs\r\n */\r\nexport class Assembler {\r\n  public readonly root: DbRoot;\r\n  private readonly lines: string[];\r\n  public currentLineIndex: number = 0;\r\n  public readonly stringProcessor: StringProcessor;\r\n  public file: ChunkFile;\r\n\r\n  public lineBuffer: string = '';\r\n  public includes = new Set<string>();\r\n  public blocks: AsmBlock[] = [];\r\n  public tags : Record<string, string> = {};\r\n  public currentBlock?: AsmBlock;\r\n  public lineCount: number = 0;\r\n  //public blockIndex: number = 0;\r\n  public lastDelimiter?: number;\r\n  public reqBank?: number;\r\n  public eof: boolean = false;\r\n  public strDelimRegex: RegExp;\r\n  public conditionFiles: string[];\r\n  private inCondition: boolean = false;\r\n  private exitCondition: boolean = false;\r\n  private failCondition: boolean = false;\r\n\r\n  constructor(dbRoot: DbRoot, file: ChunkFile, conditionFiles: string[]) {\r\n    this.root = dbRoot;\r\n    this.file = file;\r\n    // Handle both Windows (\\r\\n) and Unix (\\n) line endings\r\n    this.lines = file.textData!.split(/\\r?\\n/);\r\n    this.stringProcessor = new StringProcessor(this);\r\n    this.strDelimRegex = new RegExp(`[${this.root.stringDelimiters.map(c => c.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('')}]`);\r\n    this.conditionFiles = conditionFiles;\r\n  }\r\n\r\n  public parseAssembly(): { blocks: AsmBlock[], includes: Set<string>, reqBank?: number } {\r\n    // Initialize root block (no label, location 0) and set as current\r\n    this.currentBlock = new AsmBlock(this.file);\r\n    this.blocks.push(this.currentBlock);\r\n    \r\n    // Initialize state machine and process text\r\n    const state = new AssemblerState(this);\r\n    try {\r\n      state.processText();\r\n    } catch (error: any | Error) {\r\n      //console.error(error);\r\n      error.message = `Error processing ${this.file.name} at line ${this.currentLineIndex - 1}: ${error.message}`;\r\n      throw error;\r\n    }\r\n\r\n    return { \r\n      blocks: this.blocks, \r\n      includes: this.includes, \r\n      reqBank: this.reqBank \r\n    };\r\n  }\r\n\r\n  public getLine(): boolean {\r\n    // This can happen\r\n    if (this.eof) {\r\n      return false;\r\n    }\r\n\r\n    // Keep processing what we already have\r\n    if (this.lineBuffer.length > 0) {\r\n      return true;\r\n    }\r\n\r\n    let rawLine: string | null = null;\r\n    \r\n    while (true) {\r\n      // Read next line\r\n      if (this.currentLineIndex >= this.lines.length) {\r\n        if (this.lineBuffer.length === 0) {\r\n          this.eof = true;\r\n          return false;\r\n        } else {\r\n          rawLine = '';\r\n        }\r\n      } else {\r\n        rawLine = this.lines[this.currentLineIndex++];\r\n        this.lineBuffer += rawLine;\r\n      }\r\n\r\n      this.lineCount++;\r\n\r\n      // Process hard line continuations (before comments)\r\n      if (this.lineBuffer.endsWith('\\\\')) {\r\n        this.lineBuffer = this.lineBuffer.slice(0, -1);\r\n        continue;\r\n      }\r\n\r\n      // Ignore comments\r\n      this.trimComments('--');\r\n      this.trimComments(';');\r\n      this.trimComments('//');\r\n\r\n      // Trim\r\n      this.lineBuffer = this.lineBuffer.replace(RomProcessingConstants.COMMA_SPACE_TRIM_REGEX, '');\r\n\r\n      // This can happen\r\n      if (this.lineBuffer.length === 0) {\r\n        continue;\r\n      }\r\n\r\n      // Process directives\r\n      if (this.lineBuffer[0] === '?') {\r\n        this.processDirectives();\r\n        this.lineBuffer = '';\r\n        continue;\r\n      }\r\n\r\n      if(this.failCondition) {\r\n        this.lineBuffer = '';\r\n        continue;\r\n      }\r\n\r\n      // Process tags\r\n      if (this.lineBuffer[0] === '!') {\r\n        this.processTags();\r\n        this.lineBuffer = '';\r\n        continue;\r\n      }\r\n\r\n      //this.resolveTags();\r\n\r\n      return true;\r\n    }\r\n  }\r\n\r\n  private trimComments(sequence: string): void {\r\n    // Look for the first instance of the comment sequence\r\n    const index = this.lineBuffer.indexOf(sequence);\r\n    if (index >= 0) {\r\n      // Make sure it's not inside a string\r\n      const strIndex = this.lineBuffer.search(this.strDelimRegex);\r\n      \r\n      // This works with line continuations because the string ending will not be on this line yet\r\n      // If no string, string starts after comment, or last delimiter is before comment, trim it\r\n      if (strIndex < 0 || \r\n          strIndex > index || \r\n          this.lineBuffer.lastIndexOf(this.lineBuffer[strIndex] || '') < index) {\r\n        this.lineBuffer = this.lineBuffer.substring(0, index);\r\n      }\r\n    }\r\n  }\r\n\r\n  private processDirectives(): void {\r\n          // Find end of directive\r\n      let endIx = this.lineBuffer.search(RomProcessingConstants.COMMA_SPACE_REGEX);\r\n\r\n    // Default to line length if no end characters\r\n    if (endIx < 0) {\r\n      endIx = this.lineBuffer.length;\r\n    }\r\n\r\n    let value = this.lineBuffer.substring(endIx).replace(/^[\\s,\\t]+/, '');\r\n\r\n    switch (this.lineBuffer.substring(1, endIx).toUpperCase()) {\r\n      // This is taken care of by the loader\r\n      case 'BANK':\r\n        this.reqBank = parseInt(value, 16);\r\n        break;\r\n\r\n      case 'INCLUDE':\r\n        if (value.length > 0) {\r\n          this.includes.add(value.toUpperCase().replace(/'/g, ''));\r\n        }\r\n        break;\r\n\r\n      case 'IF':\r\n        if(this.inCondition) throw new Error('IF without ENDIF');\r\n        value = value.replace(/'/g, '');\r\n        if(!value) throw new Error('IF without condition');\r\n        this.inCondition = true;\r\n        if(!this.conditionFiles.includes(value)) { this.failCondition = true; this.exitCondition = false; }\r\n        else { this.failCondition = false; this.exitCondition = true; }\r\n        break;\r\n        \r\n      case 'ELSEIF':\r\n        if(!this.inCondition) throw new Error('ELSEIF without IF');\r\n        value = value.replace(/'/g, '');\r\n        if(!value) throw new Error('ELSEIF without condition');\r\n        if(this.exitCondition || !this.conditionFiles.includes(value)) this.failCondition = true;\r\n        else { this.exitCondition = true; this.failCondition = false; }\r\n        break;\r\n        \r\n      case 'ELSE':\r\n        if(!this.inCondition) throw new Error('ELSE without IF');\r\n        if(value) throw new Error('ELSE with condition');\r\n\r\n        if(this.exitCondition) this.failCondition = true;\r\n        else { this.failCondition = false; this.exitCondition = true; }\r\n        break;\r\n\r\n      case 'ENDIF':\r\n        if(!this.inCondition) throw new Error('ENDIF without IF');\r\n        if(value) throw new Error('ENDIF with condition');\r\n        this.failCondition = false;\r\n        this.exitCondition = false;\r\n        this.inCondition = false;\r\n        break;\r\n    }\r\n  }\r\n\r\n  private processTags(): void {\r\n    // Remove the '!' prefix and trim leading spaces\r\n    this.lineBuffer = this.lineBuffer.substring(1).replace(/^[\\s,\\t]+/, '');\r\n\r\n    // Process as many pairs as we can\r\n    while (this.lineBuffer.length > 0) {\r\n      // Default name and value\r\n      let name = this.lineBuffer;\r\n      let value: string | null = null;\r\n\r\n      // Find first index of comma/space/tab\r\n      let endIx = this.lineBuffer.search(/[\\s,\\t]/);\r\n\r\n      if (endIx >= 0) {\r\n        // Split into name and value\r\n        name = this.lineBuffer.substring(0, endIx);\r\n        value = this.lineBuffer.substring(endIx + 1).replace(/^[\\s,\\t]+/, '');\r\n\r\n        // Find next index of comma/space/tab inside value\r\n        const nextIx = value.search(/[\\s,\\t]/);\r\n        if (nextIx >= 0) {\r\n          // Line buffer then take the remainder\r\n          this.lineBuffer = value.substring(nextIx + 1).replace(/^[\\s,\\t]+/, '');\r\n          // Value takes up to next index\r\n          value = value.substring(0, nextIx);\r\n        } else {\r\n          this.lineBuffer = ''; // No more pairs, clear buffer\r\n        }\r\n        \r\n        // Assign name/value pair to tags\r\n        this.tags[name] = value;\r\n\r\n      } else {\r\n        this.lineBuffer = ''; // Take all as name, clear buffer\r\n      }\r\n    }\r\n  }\r\n\r\n  // private resolveTags(): void {\r\n  //   // Tags are sorted by length descending so longer tags are replaced first (avoids minor conflicts)\r\n  //   for (const [key, value] of this.tags) {\r\n  //     let ix: number;\r\n  //     while ((ix = this.lineBuffer.toLowerCase().indexOf(key.toLowerCase())) >= 0) {\r\n  //       this.lineBuffer = this.lineBuffer.substring(0, ix) + (value || '') + \r\n  //                         this.lineBuffer.substring(ix + key.length);\r\n  //     }\r\n  //   }\r\n  // }\r\n\r\n  public parseOperand(opnd: string): unknown {\r\n    if (!opnd) return null;\r\n\r\n    if(opnd.match(/^[a-fA-F0-9]{2,6}$/)){\r\n      switch(opnd.length){\r\n        case 2:\r\n          return new Byte(parseInt(opnd, 16));\r\n        case 4:\r\n          return new Word(parseInt(opnd, 16));\r\n        case 6:\r\n          return new Long(parseInt(opnd, 16));\r\n      }\r\n    }\r\n\r\n    return opnd;\r\n  }\r\n\r\n  public processRawData(): void {\r\n    let reverse = false;\r\n\r\n    // Immediate binary marker\r\n    if (this.lineBuffer[0] === '#') {\r\n      this.lineBuffer = this.lineBuffer.substring(1);\r\n    }\r\n\r\n    // Reverse binary marker\r\n    if (this.lineBuffer[0] === '$') {\r\n      reverse = true;\r\n      this.lineBuffer = this.lineBuffer.substring(1);\r\n    }\r\n\r\n    let hex: string;\r\n    const symbolIx = this.lineBuffer.search(RomProcessingConstants.SYMBOL_SPACE_REGEX);\r\n    if (symbolIx >= 0) {\r\n      hex = this.lineBuffer.substring(0, symbolIx);\r\n      this.lineBuffer = this.lineBuffer.substring(symbolIx).replace(/^[, \\t]+/, '');\r\n    } else {\r\n      hex = this.lineBuffer;\r\n      this.lineBuffer = '';\r\n    }\r\n\r\n    if (hex.length > 0) {\r\n      // Keep string values of address markers so they can be resolved later\r\n      if (RomProcessingConstants.ADDRESS_SPACE.includes(hex[0])) {\r\n        this.currentBlock!.objList.push(hex);\r\n        this.currentBlock!.size += RomProcessingConstants.getSize(hex);\r\n      } else {\r\n        const data = this.hexStringToBytes(hex);\r\n        if (data.length === 1) {\r\n          this.currentBlock!.objList.push(new Byte(data[0]));\r\n          this.currentBlock!.size++;\r\n        } else {\r\n          if (reverse) {\r\n            data.reverse();\r\n          }\r\n\r\n          // Explicitly change two-byte data into number for easier processing later\r\n          if (data.length === 2) {\r\n            this.currentBlock!.objList.push(new Word(data[0] | (data[1] << 8)));\r\n            this.currentBlock!.size += 2;\r\n          } else {\r\n            this.currentBlock!.objList.push(data);\r\n            this.currentBlock!.size += data.length;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  private hexStringToBytes(hex: string): Uint8Array {\r\n    const result = new Uint8Array(hex.length / 2);\r\n    for (let i = 0; i < hex.length; i += 2) {\r\n      result[i / 2] = parseInt(hex.substring(i, i + 2), 16);\r\n    }\r\n    return result;\r\n  }\r\n}\r\n","/**\r\n * A map that sorts keys by length in descending order, then alphabetically\r\n * This is used for tag replacement where longer tags should be replaced first\r\n * to avoid conflicts (e.g., \"ABCD\" should be replaced before \"ABC\")\r\n */\r\nexport class SortedMap<V> {\r\n  private map = new Map<string, V>();\r\n  private _keys: string[] = [];\r\n\r\n  public get size(): number {\r\n    return this.map.size;\r\n  }\r\n\r\n  public set(key: string, value: V): this {\r\n    if (!this.map.has(key)) {\r\n      this._keys.push(key);\r\n      this.sortKeys();\r\n    }\r\n    this.map.set(key, value);\r\n    return this;\r\n  }\r\n\r\n  public get(key: string): V | undefined {\r\n    return this.map.get(key);\r\n  }\r\n\r\n  public has(key: string): boolean {\r\n    return this.map.has(key);\r\n  }\r\n\r\n  public delete(key: string): boolean {\r\n    const result = this.map.delete(key);\r\n    if (result) {\r\n      const index = this._keys.indexOf(key);\r\n      if (index >= 0) {\r\n        this._keys.splice(index, 1);\r\n      }\r\n    }\r\n    return result;\r\n  }\r\n\r\n  public clear(): void {\r\n    this.map.clear();\r\n    this._keys.length = 0;\r\n  }\r\n\r\n  public keys(): string[] {\r\n    return [...this._keys];\r\n  }\r\n\r\n  public values(): V[] {\r\n    return this._keys.map(key => this.map.get(key)!);\r\n  }\r\n\r\n  public entries(): [string, V][] {\r\n    return this._keys.map(key => [key, this.map.get(key)!]);\r\n  }\r\n\r\n  public *[Symbol.iterator](): Generator<[string, V], void, unknown> {\r\n    for (const key of this._keys) {\r\n      yield [key, this.map.get(key)!];\r\n    }\r\n  }\r\n\r\n  private sortKeys(): void {\r\n    this._keys.sort((a, b) => {\r\n      // Sort by length descending first\r\n      if (a.length !== b.length) {\r\n        return b.length - a.length;\r\n      }\r\n      // Then alphabetically\r\n      return a.localeCompare(b);\r\n    });\r\n  }\r\n}\r\n","import type { DbPart } from './parts';\r\nimport { DbTransform } from './transforms';\r\n\r\n/**\r\n * Database block definition\r\n * Converted from GaiaLib/Database/DbBlock.cs\r\n */\r\nexport class DbBlock {\r\n  public name: string;\r\n  public movable: boolean;\r\n  public group?: string;\r\n  public scene?: string;\r\n  public parts: DbPart[];\r\n  public transforms?: DbTransform[];\r\n  public postProcess?: string;\r\n  public order?: number;\r\n  public base?: number;\r\n  public location: number;\r\n  //public id?: string;\r\n\r\n  constructor(data: Partial<DbBlock>) {\r\n    this.name = data.name ?? '';\r\n    this.movable = data.movable ?? false;\r\n    this.group = data.group ?? undefined;\r\n    this.scene = data.scene ?? undefined;\r\n    this.parts = (data.parts ?? []).sort((a, b) => {\r\n      const orderA = a.order ?? a.start ?? 0;\r\n      const orderB = b.order ?? b.start ?? 0;\r\n      return orderA - orderB;\r\n    });\r\n    this.location = this.parts[0].start;\r\n    this.transforms = data.transforms ?? [];\r\n    this.postProcess = data.postProcess ?? undefined;\r\n    this.order = data.order ?? undefined;\r\n    this.base = data.base ?? undefined;\r\n    //this.id = data.id ?? undefined;\r\n\r\n\r\n    if(!this.name) throw new Error('Name is required');\r\n  }\r\n}\r\n","import { BinType } from '../types/resources';\r\n\r\nexport class DbFile {\r\n  //public id?: string;\r\n  public name: string;\r\n  public type: string;\r\n  public start: number;\r\n  public end: number;\r\n  public compressed?: boolean;\r\n  public upper?: boolean;\r\n  public group?: string;\r\n  public scene?: string;\r\n  public base?: number;\r\n  public struct?: string;\r\n\r\n  constructor(data: Partial<DbFile>) {\r\n    if(!data.name) throw new Error('Name is required');\r\n    if(!data.type) throw new Error('Type is required');\r\n    if(typeof data.start !== 'number') throw new Error('Start is required');\r\n    if(typeof data.end !== 'number') throw new Error('End is required');\r\n\r\n    this.name = data.name;\r\n    this.type = data.type;\r\n    this.start = data.start;\r\n    this.end = data.end;\r\n    this.compressed = data.compressed ?? undefined;\r\n    this.upper = data.upper ?? undefined;\r\n    this.group = data.group || undefined;\r\n    this.scene = data.scene || undefined;\r\n    this.base = data.base ?? undefined;\r\n    this.struct = data.struct ?? undefined;\r\n  }\r\n} \r\n\r\nexport class DbFileType {\r\n  public name: string;\r\n  public extension: string;\r\n  public type: string;\r\n  public isPatch: boolean;\r\n  public isBlock: boolean;\r\n  public header: number;\r\n  public compressed?: boolean;\r\n  public struct?: string;\r\n  public base?: number;\r\n  public upper?: boolean;\r\n\r\n  constructor(data: Partial<DbFileType>) {\r\n    if(!data.name) throw new Error('Name is required');\r\n    if(!data.extension) throw new Error('Extension is required');\r\n    if(!data.type) throw new Error('Type is required');\r\n\r\n    this.name = data.name;\r\n    this.extension = data.extension;\r\n    this.type = data.type;\r\n    this.isPatch = data.isPatch ?? false;\r\n    this.isBlock = data.isBlock ?? false;\r\n    this.header = data.header ?? 0;\r\n    this.compressed = data.compressed ?? undefined;\r\n    this.struct = data.struct ?? undefined;\r\n    this.base = data.base ?? undefined;\r\n    this.upper = data.upper ?? undefined;\r\n  }\r\n}","/**\r\n * Database structure definition\r\n * Converted from GaiaLib/Database/DbStruct.cs\r\n */\r\nexport class DbStruct {\r\n  public name: string;\r\n  public types?: string[];\r\n  public parent?: string;\r\n  public delimiter?: number;\r\n  public discriminator?: number;\r\n  public discriminatorLogic?: string;\r\n  public discriminatorSize?: number;\r\n  public null?: number;\r\n  public tail?: number;\r\n\r\n  constructor(data: Partial<DbStruct>) {\r\n    this.name = data.name ?? '';\r\n    this.types = data.types ?? undefined;\r\n    this.parent = data.parent ?? undefined;\r\n    this.delimiter = data.delimiter ?? undefined;\r\n    this.discriminator = data.discriminator ?? undefined;\r\n    this.discriminatorLogic = data.discriminatorLogic ?? undefined;\r\n    this.discriminatorSize = data.discriminatorSize ?? undefined;\r\n    this.null = data.null ?? undefined;\r\n    this.tail = data.tail ?? undefined;\r\n    \r\n    if(!this.name) throw new Error('Name is required');\r\n  }\r\n} ","\r\nexport class DbAddressingMode {\r\n    public name: string;\r\n    public shorthand: string;\r\n    public operands: string[];\r\n    public size: number;\r\n    public formatString?: string;\r\n    public parseRegex?: string;\r\n    public instructions: Record<string, number>;\r\n\r\n    constructor(data: Partial<DbAddressingMode>) {\r\n        if(!data.name) throw new Error('Addressing mode name is required');\r\n        if(!data.shorthand) throw new Error('Addressing mode shorthand is required');\r\n        if(!data.instructions) throw new Error('Addressing mode instructions are required');\r\n        if(!data.size) throw new Error('Addressing mode size is required');\r\n\r\n        this.name = data.name;\r\n        this.shorthand = data.shorthand;\r\n        this.operands = data.operands ?? [];\r\n        this.size = data.size ?? 1;\r\n        this.formatString = data.formatString ?? undefined;\r\n        this.parseRegex = data.parseRegex ?? undefined;\r\n        this.instructions = data.instructions;\r\n    }\r\n}\r\n","import { MemberType } from '../types/members';\r\n\r\n/**\r\n * Database string command definition\r\n * Converted from GaiaLib/Database/DbStringCommand.cs\r\n */\r\nexport class DbStringCommand {\r\n  public id: number;\r\n  public name: string;\r\n  public types: string[];\r\n  public delimiter?: number;\r\n  public halt: boolean;\r\n  public dictionary?: DbStringDictionary;\r\n  public newline: boolean;\r\n\r\n  constructor(data: Partial<DbStringCommand>) {\r\n    if(typeof data.id !== 'number') throw new Error('Id is required');\r\n    if(!data.name) throw new Error('Name is required');\r\n\r\n    this.id = data.id;\r\n    this.name = data.name;\r\n    this.types = data.types ?? [];\r\n    this.delimiter = data.delimiter ?? undefined;\r\n    this.halt = data.halt ?? false;\r\n    this.dictionary = data.dictionary ?? undefined;\r\n    this.newline = data.newline ?? false;\r\n  }\r\n}\r\n\r\n/**\r\n * Database string layer definition\r\n * Converted from GaiaLib/Database/DbStringLayer.cs\r\n */\r\nexport interface DbStringLayer {\r\n  base?: number;\r\n  range?: number;\r\n  on?: number;\r\n  shiftBit?: number;\r\n  map: string[];\r\n}\r\n\r\nexport class DbStringDictionary {\r\n  public base?: number;\r\n  //public range: number;\r\n  public command?: number;\r\n  public commandName?: string;\r\n  public name: string;\r\n  //public suffix: string;\r\n  public entries: string[];\r\n\r\n  constructor(data: Partial<DbStringDictionary>) {\r\n    if(typeof data.command !== 'number' && typeof data.base !== 'number') throw new Error('Command or base is required');\r\n    if(!data.name) throw new Error('Name is required');\r\n    if(!data.entries || data.entries.length === 0) throw new Error('Entries is required');\r\n\r\n    this.base = data.base ?? undefined;\r\n    //this.range = data.range ?? 0;\r\n    this.command = data.command ?? undefined;\r\n    this.commandName = data.commandName ?? undefined;\r\n    this.name = data.name;\r\n    this.entries = data.entries;\r\n    //this.suffix = data.suffix ?? '';\r\n\r\n    //if(this.base !== undefined) this.range = this.base + this.entries.length;\r\n  }\r\n}\r\n\r\n/**\r\n * Database string type definition\r\n * Converted from GaiaLib/Database/DbStringType.cs\r\n */\r\nexport class DbStringType {\r\n  public name: string;\r\n  public delimiter: string;\r\n  public terminator: number;\r\n  public commands: Record<string, DbStringCommand>;\r\n  public commandLookup: Record<number, DbStringCommand>;\r\n  public layers: DbStringLayer[];\r\n  public greedyTerminator: boolean;\r\n  public dictionaries: Record<string, DbStringDictionary>;\r\n  public dictionaryLookup: { text: string, id: number }[];\r\n  public modifiers?: Record<number, Record<string, string>>;\r\n\r\n  constructor(data: Partial<DbStringType>) {\r\n    if(!data.name) throw new Error('Name is required');\r\n    if(!data.delimiter) throw new Error('Delimiter is required');\r\n    if(typeof data.terminator !== 'number') throw new Error('Terminator is required');\r\n    if(!data.layers || !data.layers.length) throw new Error('Layers are required');\r\n\r\n    this.name = data.name;\r\n    this.delimiter = data.delimiter;\r\n    this.terminator = data.terminator;\r\n    this.commands = data.commands ?? {};\r\n    this.layers = data.layers;\r\n    this.greedyTerminator = data.greedyTerminator ?? false;\r\n    this.dictionaries = data.dictionaries ?? {};\r\n    this.commandLookup = Object.values(this.commands).reduce((acc, x) => {\r\n      acc[x.id] = x;\r\n      return acc;\r\n    }, {} as Record<number, DbStringCommand>);\r\n    this.dictionaryLookup = Object.values(this.dictionaries)\r\n      .flatMap((y) => y.entries.map((z, ix) => ({ text: z, id: ((y.command ?? 0) << 8) | ix })))\r\n      //.map((y, z) => ({ text: y.entries[z], id: (y.command << 8) | (y.base + z) }))\r\n      .sort((a, b) => b.text.length - a.text.length);\r\n    this.modifiers = data.modifiers;\r\n  }\r\n}\r\n","\r\n/**\r\n * COP instruction definition\r\n * Converted from GaiaLib/Database/CopDef.cs\r\n */\r\nexport class CopDef {\r\n  public id: number;\r\n  public name: string;\r\n  public parts: string[];\r\n  public halt: boolean;\r\n  public conditions?: CopCondition[];\r\n\r\n  constructor(data: Partial<CopDef>) {\r\n    if(!data.name) throw new Error('Name is required');\r\n    if(typeof data.id !== 'number') throw new Error('ID is required');\r\n\r\n    this.name = data.name;\r\n    this.id = data.id;\r\n    this.parts = data.parts ?? [];\r\n    this.halt = data.halt ?? false;\r\n    this.conditions = data.conditions ?? [];\r\n  }\r\n}\r\n\r\nexport interface CopCondition {\r\n  offset: number;\r\n  value: number;\r\n  parts: string[];\r\n  logic?: string;\r\n}","\r\n/**\r\n * Database part definition\r\n * Converted from GaiaLib/Database/DbPart.cs\r\n */\r\nexport class DbPart {\r\n  public name?: string;\r\n  public start: number;\r\n  public end: number;\r\n  public type?: string;\r\n  //public bank?: number;\r\n  public order?: number;\r\n\r\n  constructor(data: Partial<DbPart>) {\r\n    if(typeof data.start !== 'number') throw new Error('Start is required');\r\n    //if(!data.name) throw new Error('Name is required');\r\n    if(!data.end) throw new Error('End is required');\r\n    //if(!data.type) throw new Error('Struct is required');\r\n\r\n    this.name = data.name;\r\n    this.start = data.start;\r\n    this.end = data.end;\r\n    this.type = data.type;\r\n    //this.bank = data.bank ?? undefined;\r\n    this.order = data.order ?? undefined;\r\n  }\r\n}\r\n","\r\nexport class DbTransform {\r\n  key: string; \r\n  value: string;\r\n\r\n  constructor(data: Partial<DbTransform>) {\r\n    this.key = data.key ?? '';\r\n    this.value = data.value ?? '';\r\n\r\n    if(!this.key) throw new Error('Key is required');\r\n  }\r\n} ","import { DbAsset } from \"./assets\";\r\n\r\nexport class DbScene {\r\n    public name: string;\r\n    public id: number;\r\n    public description?: string;\r\n    public assets: DbAsset[];\r\n    \r\n    constructor(data: Partial<DbScene>) {\r\n        this.name = data.name ?? '';\r\n        this.id = data.id ?? 0;\r\n        this.description = data.description ?? '';\r\n        this.assets = data.assets ?? [];\r\n\r\n        if(!this.name) throw new Error('Scene name is required');\r\n        if(!this.id) throw new Error('Scene id is required');\r\n    }\r\n}","import { DbScene } from \"./scenes\";\r\n\r\nexport class DbGroup {\r\n    public name: string;\r\n    public prefix: string;\r\n    public description?: string;\r\n    public scenes: Record<string, DbScene>;\r\n\r\n    constructor(data: Partial<DbGroup>) {\r\n        this.name = data.name ?? '';\r\n        this.prefix = data.prefix ?? '';\r\n        this.description = data.description ?? '';\r\n        this.scenes = data.scenes ?? {};\r\n    }\r\n}","import { BitStream } from '../types/bitstream';\nimport { type ICompressionProvider } from '../types/compression';\n\n/**\n * QuintetLZ compression algorithm implementation\n * Dictionary-based compression used in Quintet games\n */\nexport class QuintetLZ implements ICompressionProvider {\n  public static readonly DICTIONARY_SIZE = 0x100;\n  public static readonly DICTIONARY_INIT = 0x20;\n  public static readonly DICTIONARY_OFFSET = 0xEF;\n  private static readonly DEFAULT_PAGE_SIZE = 0x8000;\n\n  /**\n   * Expand (decompress) data using QuintetLZ algorithm\n   * @param srcData Source data buffer\n   * @param srcPosition Starting position in source data\n   * @param srcLen Length of source data to process\n   * @returns Expanded data\n   */\n  public expand(srcData: Uint8Array, srcPosition: number = 0, srcLen: number = QuintetLZ.DEFAULT_PAGE_SIZE): Uint8Array {\n    const bitStream = new BitStream(srcData, srcPosition);\n    const srcStop = srcPosition + srcLen;\n\n    // Initialize dictionary with spaces (0x20)\n    const dictionary = new Uint8Array(QuintetLZ.DICTIONARY_SIZE);\n    dictionary.fill(QuintetLZ.DICTIONARY_INIT);\n\n    // Initialize positions\n    let dictPosition = QuintetLZ.DICTIONARY_OFFSET;\n    let outPosition = 0;\n\n    // First two bytes is decompressed size\n    let dstLen = bitStream.readShort();\n\n    if(dstLen === 0){\n      return srcData.slice(srcPosition + 2, srcStop);\n    } else if(dstLen & 0x8000) {\n      dstLen = 0x10000 - dstLen;\n    }\n\n    // Create output buffer with the expected size\n    const outBuffer = new Uint8Array(dstLen);\n\n    while (bitStream.currentPosition < srcStop && outPosition < dstLen) {\n      // If current bit is set, read byte and add to output buffer and dictionary\n      if (bitStream.readBit()) {\n        // Read byte from bitstream\n        const sample = bitStream.readByte();\n\n        // Add byte to output buffer and increment\n        if (outPosition < dstLen) {\n          outBuffer[outPosition++] = sample;\n        }\n\n        // Add byte to dictionary\n        dictionary[dictPosition] = sample;\n\n        // Wrap dictionary index\n        dictPosition = (dictPosition + 1) & 0xFF;\n      }\n      // If current bit is not set, read sequence from dictionary\n      else {\n        // Read wordIndex and wordLength from bitstream\n        let wordIndex = bitStream.readByte();\n        let wordLength = bitStream.readNibble() + 2;\n\n        // Continue while there are remaining bytes to copy\n        while (wordLength-- > 0) {\n          // Read byte at wordIndex\n          const sample = dictionary[wordIndex];\n\n          // Wrap dictionary index\n          wordIndex = (wordIndex + 1) & 0xFF;\n\n          // Copy byte to output buffer and increment, but only if there is space\n          if (outPosition < dstLen) {\n            outBuffer[outPosition++] = sample;\n          }\n\n          // Add byte to dictionary and increment\n          dictionary[dictPosition] = sample;\n\n          // Wrap dictionary index\n          dictPosition = (dictPosition + 1) & 0xFF;\n        }\n      }\n    }\n\n    // Return only the used portion of the buffer\n    if (outPosition < dstLen) {\n      return outBuffer.slice(0, outPosition);\n    }\n\n    return outBuffer;\n  }\n\n  /**\n   * Compact (compress) data using QuintetLZ algorithm\n   * @param srcData Source data to compress\n   * @returns Compressed data\n   */\n  public compact(srcData: Uint8Array, srcPosition?: number, srcLen?: number): Uint8Array {\n    // Initialize dictionary with spaces\n    const dictionary = new Uint8Array(QuintetLZ.DICTIONARY_SIZE);\n    dictionary.fill(QuintetLZ.DICTIONARY_INIT);\n\n    let offset = QuintetLZ.DICTIONARY_OFFSET;\n    let srcIx = srcPosition ?? 0;\n    let dstIx = 0;\n    if(!srcLen) srcLen = srcData.length - srcIx;\n    let endIx = srcIx + srcLen;\n\n\n    //const srcLen = srcData.length;\n    const outputBuffer = new Uint8Array(srcLen * 2); // Allocate extra space for safety\n\n    // Write header (16-bit length in little-endian)\n    outputBuffer[dstIx++] = srcLen & 0xFF;\n    outputBuffer[dstIx++] = (srcLen >> 8) & 0xFF;\n\n    const bitStream = new BitStream(outputBuffer, 2); // Start after header\n\n    /**\n     * Find the best match in the dictionary\n     * @returns Tuple of [startByte, length]\n     */\n    const getCommand = (): [number, number] => {\n      const maxLen = Math.min(endIx - srcIx, 17);\n      if (maxLen < 2) {\n        return [0, 0];\n      }\n\n      let startByte = 0;\n      let bestLen = 0;\n      let baseIndex = offset;\n\n      for (let i = 0; i < 0x100; i++, baseIndex = (baseIndex + 1) & 0xFF) {\n        let size = 0;\n        let currentIndex = baseIndex;\n        let sourceIndex = srcIx;\n        let isEnd = false;\n\n        while (size < maxLen) {\n          if(isEnd) { if(srcData[sourceIndex++] !== srcData[srcIx + size]) break; } \n          else if(dictionary[currentIndex] !== srcData[sourceIndex++]) break; \n          else {\n            currentIndex = (currentIndex + 1) & 0xFF;\n            if (currentIndex === offset) {\n              sourceIndex = srcIx;\n              isEnd = true;\n            }\n          }\n          \n          size++;\n        }\n\n        if (size > bestLen) {\n          startByte = baseIndex;\n          bestLen = size;\n\n          if (bestLen >= maxLen) {\n            break;\n          }\n        }\n      }\n\n      return [startByte, bestLen];\n    };\n\n    while (srcIx < endIx) {\n      const [cmdStart, cmdLen] = getCommand();\n\n      if (cmdLen >= 2) {\n        // Write dictionary reference\n        bitStream.writeBit(false);\n        bitStream.writeByte(cmdStart);\n        bitStream.writeNibble(cmdLen - 2);\n\n        // Copy bytes to dictionary\n        for (let i = 0; i < cmdLen; i++) {\n          dictionary[offset] = srcData[srcIx++];\n          offset = (offset + 1) & 0xFF;\n        }\n      } else {\n        // Write literal byte\n        bitStream.writeBit(true);\n        const val = srcData[srcIx++];\n        bitStream.writeByte(val);\n        dictionary[offset] = val;\n        offset = (offset + 1) & 0xFF;\n      }\n    }\n    bitStream.flush();\n\n    // Get the final size including the bit stream data\n    const finalSize = Math.max(dstIx, bitStream.currentPosition);\n    return outputBuffer.slice(0, finalSize);\n  }\n} ","import { ICompressionProvider } from '../types/compression';\nimport { QuintetLZ } from './QuintetLZ';\n\nexport * from './QuintetLZ';\n\nexport const CompressionAlgorithms = {\n    'QuintetLZ': () => new QuintetLZ(),\n} as Record<string, () => ICompressionProvider>;\n","\r\nexport class DbHeader {\r\n    public bank: number;\r\n    public address: number;\r\n    public condition?: string;\r\n    public parts: DbHeaderPart[];\r\n\r\n    constructor(data: Partial<DbHeader>) {\r\n        if(typeof data.address !== 'number') throw new Error('Address is required');\r\n        if(!data.parts || !data.parts.length) throw new Error('Parts are required');\r\n\r\n        this.bank = data.bank ?? 0;\r\n        this.address = data.address;\r\n        this.condition = data.condition ?? undefined;\r\n        this.parts = data.parts.map(p => new DbHeaderPart(p));\r\n    }\r\n}\r\n\r\nexport class DbHeaderPart {\r\n    public name: string;\r\n    public size: number;\r\n    public type: string;\r\n    public value?: any;\r\n\r\n    constructor(data: Partial<DbHeaderPart>) {\r\n        if(!data.name) throw new Error('Name is required');\r\n\r\n        this.name = data.name;\r\n        this.size = data.size ?? 0;\r\n        this.type = data.type ?? '';\r\n        this.value = data.value ?? undefined;\r\n    }\r\n}","import type { ICompressionProvider } from '../types/compression';\r\nimport { DbBlock } from './blocks';\r\nimport type { DbConfig } from './config';\r\nimport type { DbEntryPoint } from './entrypoints';\r\nimport { DbFile, DbFileType } from './files';\r\nimport { DbStruct } from './structs';\r\nimport { DbAddressingMode } from './addressingMode';\r\nimport { DbStringType, DbStringCommand, DbStringDictionary } from './strings';\r\nimport { CopDef } from './cop';\r\nimport { listDirectory, readFileAsBinary, saveFileAsText, saveFileAsBinary, readFileAsText } from '../utils';\r\nimport { DbPart } from './parts';\r\nimport { DbTransform } from './transforms';\r\nimport { OpCode } from './opcode';\r\nimport { MemoryMapMode } from '../types/addressing';\r\nimport { ChunkFile } from '../types/files';\r\nimport { DbScene } from './scenes';\r\nimport { DbGroup } from './groups';\r\nimport { CompressionAlgorithms } from '../compression';\r\nimport { DbGameRomModule } from './modules';\r\nimport { BlockWriter } from '../rom/extraction/writer';\r\nimport { BlockReader } from '../rom/extraction/blocks';\r\nimport { RomWriter } from '../rom/rebuild/writer';\r\nimport { DbHeader } from './header';\r\nimport { AsmBlock } from '../types/assembly';\r\nimport { decodeBase64 } from '../utils/base64';\r\n\r\n/**\r\n * Main database root class\r\n * Converted from GaiaLib/Database/DbRoot.cs\r\n */\r\nexport interface DbRoot {\r\n  copDef: Record<number, CopDef>;\r\n  copLookup: Record<string, CopDef>;\r\n  mnemonics: Record<number, string>;\r\n  mnemonicsLookup: Record<string, string>;\r\n  //paths: Record<BinType, DbPath>;\r\n  structs: Record<string, DbStruct>;\r\n  stringTypes: Record<string, DbStringType>;\r\n  stringDelimiters: string[];\r\n  stringDelimiterLookup: Record<string, DbStringType>;\r\n  //stringCharLookup: Record<string, DbStringType>;\r\n  headers: DbHeader[];\r\n  files: DbFile[];\r\n  config: DbConfig;\r\n  blocks: DbBlock[];\r\n  overrides: Record<number, Record<string, any>>;\r\n  labels: Record<number, string>;\r\n  rewrites: Record<number, number>;\r\n  entryPoints: DbEntryPoint[];\r\n  opCodes: Record<number, OpCode>;\r\n  opLookup: Record<string, OpCode[]>;\r\n  addrLookup: Record<string, DbAddressingMode>;\r\n  compression?: ICompressionProvider;\r\n  baseRomFiles?: ChunkFile[];\r\n  projectFiles?: ChunkFile[];\r\n  groups: Record<string, DbGroup>;\r\n  scenes: Record<number, DbScene>;\r\n  fileTypes: Record<string, DbFileType>;\r\n  fileExtLookup: Record<string, DbFileType>;\r\n  names: Record<number, string>;\r\n  comments: Record<number, string>;\r\n  blockNotes: Record<string, string>;\r\n  partNotes: Record<string, string>;\r\n  types: Record<number, string>;\r\n}\r\n\r\n/**\r\n * Database root utilities\r\n */\r\nexport class DbRootUtils {\r\n  /**\r\n   * JSON serialization options\r\n   */\r\n  // public static readonly JSON_OPTIONS = {\r\n  //   propertyNamingPolicy: 'camelCase',\r\n  //   readCommentHandling: 'skip',\r\n  //   writeIndented: true\r\n  // };\r\n\r\n  // /**\r\n  //  * Load database from a single file\r\n  //  */\r\n  // // public static async fromFile(dbFilePath: string): Promise<DbRoot> {\r\n  // //   return await readJsonFile<DbRoot>(dbFilePath);\r\n  // // }\r\n\r\n  // public static async fromFolder(folderPath: string, systemPath: string) : Promise<DbRoot> {\r\n  //   return this.fromGameModule(await this.gameModuleFromFolder(folderPath, systemPath));\r\n  // }\r\n\r\n  // /**\r\n  //  * Load database from folder structure\r\n  //  */\r\n  // public static async gameModuleFromFolder(folderPath: string, systemPath: string): Promise<DbGameRomModule> {\r\n  //   return {\r\n  //     mnemonics: await readJsonFile<Record<number, string>>(`${folderPath}/mnemonics.json`),\r\n  //     overrides: await readJsonFile<Record<number, Record<string, any>>>(`${folderPath}/overrides.json`),\r\n  //     rewrites: await readJsonFile<Record<string, number>>(`${folderPath}/rewrites.json`),\r\n  //     blocks: await readJsonFile<Record<string, Record<string, Partial<DbBlock>>>>(`${folderPath}/blocks.json`),\r\n  //     files: await readJsonFile<Record<string, Record<string, Record<string, Partial<DbFile>>>>>(`${folderPath}/files.json`),\r\n  //     config: await readJsonFile<DbConfig>(`${folderPath}/config.json`),\r\n  //     labels: await readJsonFile<DbLabel[]>(`${folderPath}/labels.json`),\r\n  //     structs: await readJsonFile<Record<string, DbStruct>>(`${folderPath}/structs.json`),\r\n  //     copdef: await readJsonFile<Record<string, Partial<CopDef>>>(`${folderPath}/copdef.json`),\r\n  //     addrModes: await readJsonFile<Record<string, Partial<DbAddressingMode>>>(`${systemPath}/addressingModes.json`),\r\n  //     strings: await readJsonFile<Record<string, Partial<DbStringType>>>(`${folderPath}/stringTypes.json`),\r\n  //     transforms: await readJsonFile<Record<string, Partial<DbTransform>[]>>(`${folderPath}/transforms.json`),\r\n  //     groups: await readJsonFile<Record<string, Partial<DbGroup>>>(`${folderPath}/groups.json`),\r\n  //     fileTypes: await readJsonFile<Record<string, Partial<DbFileType>>>(`${folderPath}/fileTypes.json`),\r\n  //   }\r\n  // }\r\n\r\n  public static fromGameModule(module: DbGameRomModule): DbRoot {\r\n    // Build lookup tables\r\n    const nameLookup = module.names ?? {};\r\n    const typeLookup = module.types ?? {};\r\n\r\n    const opCodes = {} as Record<number, OpCode>;\r\n    const opLookup = {} as Record<string, OpCode[]>;\r\n    const addrLookup = Object.entries(module.addrModes).reduce((acc, x) => {\r\n      const modeData = x[1];\r\n      const modeName = x[0];\r\n      for(const [mnem, code] of Object.entries(modeData.instructions ?? [])) {\r\n        const opCode = new OpCode(code, mnem, modeName);\r\n        opCodes[code] = opCode;\r\n        if (!opLookup[mnem]) opLookup[mnem] = [];\r\n        opLookup[mnem].push(opCode);\r\n      }\r\n      acc[modeName] = new DbAddressingMode({...modeData, name: modeName});\r\n      return acc;\r\n    }, {} as Record<string, DbAddressingMode>);\r\n\r\n    const blocksArray: DbBlock[] = [];\r\n    for (const [groupName, groupData] of Object.entries(module.blocks)) {\r\n      for(const [blockName, blockData] of Object.entries(groupData)) {\r\n\r\n        let parts: DbPart[] = [];\r\n        let partsData: any = blockData.parts as any;\r\n\r\n        if (partsData === undefined || partsData === null) {\r\n          parts = [new DbPart({...blockData, order: undefined})];\r\n        } else if (partsData instanceof Array) {\r\n          parts = (partsData as number[][]).map((p) => {\r\n            return new DbPart({ start: p[0], end: p[1] });\r\n          });\r\n        } else if (partsData instanceof Object) {\r\n          parts = Object.entries(partsData as Record<string, Partial<DbPart>>).map((p) => {\r\n            return new DbPart({...p[1], name: p[0]});\r\n          });\r\n        }\r\n\r\n        const transformList = (module.transforms[blockName] ?? []).map((t) => {\r\n          return new DbTransform(t);\r\n        });\r\n\r\n        const block = new DbBlock({\r\n          ...blockData, \r\n          name: blockName, \r\n          group: groupName,\r\n          parts: parts,\r\n          transforms: transformList\r\n        });\r\n\r\n        blocksArray.push(block);\r\n      }\r\n    }\r\n\r\n    const sceneLookup = {} as Record<number, DbScene>;\r\n    const groupLookup = Object.entries(module.groups).reduce((acc, x) => {\r\n      const groupData = x[1];\r\n      const groupName = x[0];\r\n\r\n      const scenes = Object.entries(groupData.scenes ?? {}).reduce((acc, y) => {\r\n        const sceneData = y[1];\r\n        const sceneName = y[0];\r\n        const scene = new DbScene({...sceneData, name: sceneName });\r\n        sceneLookup[scene.id] = scene;\r\n        acc[sceneName] = scene;\r\n        return acc;\r\n      }, {} as Record<string, DbScene>);\r\n      \r\n      acc[groupName] = new DbGroup({...groupData, name: groupName, scenes: scenes });\r\n      return acc;\r\n    }, {} as Record<string, DbGroup>);\r\n\r\n    const fileList: DbFile[] = [];\r\n    for(const [groupName, groupData] of Object.entries(module.files)) {\r\n      for(const [sceneName, sceneData] of Object.entries(groupData)) {\r\n        for(const [fileName, fileData] of Object.entries(sceneData)) {\r\n          fileList.push(new DbFile({...fileData, name: fileName, group: groupName, scene: sceneName }));\r\n        }\r\n      }\r\n    }\r\n\r\n    const stringDelimiterLookup = {} as Record<string, DbStringType>;\r\n    const stringDelimiterList: string[] = [];\r\n    const stringLookup = Object.entries(module.strings).reduce((acc, x) => {\r\n      const stringType = x[1];\r\n      const name = x[0];\r\n      const commands = Object.entries(stringType.commands ?? {}).reduce((acc, y) => {\r\n        acc[y[0]] = new DbStringCommand({...y[1], name: y[0]});\r\n        return acc;\r\n      }, {} as Record<string, DbStringCommand>);\r\n      const dictionaries = Object.entries(stringType.dictionaries ?? {}).reduce((acc, y) => {\r\n        const dictionary = new DbStringDictionary({...y[1], name: y[0]});\r\n        acc[y[0]] = dictionary;\r\n        if(dictionary.command !== undefined) {\r\n          const existingCommand = Object.values(commands).find(z => z.id === dictionary.command);\r\n          if (existingCommand) existingCommand.dictionary = dictionary;\r\n          else {\r\n            const name = dictionary.commandName ?? dictionary.command?.toString(16).padStart(2, '0').toUpperCase();\r\n            commands[name] = new DbStringCommand({id: dictionary.command, name, dictionary, types: [ \"Byte\" ]});\r\n          }\r\n        }\r\n        return acc;\r\n      }, {} as Record<string, DbStringDictionary>);\r\n      const st = new DbStringType({...stringType, name, commands, dictionaries});\r\n      acc[name] = st;\r\n      stringDelimiterLookup[st.delimiter] = st;\r\n      stringDelimiterList.push(st.delimiter);\r\n      return acc;\r\n    }, {} as Record<string, DbStringType>);\r\n\r\n    const structLookup = Object.entries(module.structs).reduce((acc, x) => {\r\n      acc[x[0].replaceAll('-', '_').replaceAll(' ', '_').toLowerCase()] = new DbStruct({...x[1], name: x[0]});\r\n      return acc;\r\n    }, {} as Record<string, DbStruct>);\r\n\r\n\r\n    const copCodes = {} as Record<number, CopDef>;\r\n    const copLookup = Object.entries(module.copdef).reduce((acc, x) => {\r\n      const copDef = x[1];\r\n      const name = x[0];\r\n      const def = new CopDef({...copDef, name});\r\n      copCodes[def.id] = def;\r\n      acc[name] = def;\r\n      return acc;\r\n    }, {} as Record<string, CopDef>);\r\n\r\n    const extLookup = {} as Record<string, DbFileType>;\r\n    const fileTypeLookup = {} as Record<string, DbFileType>;\r\n    const fileTypes = Object.entries(module.fileTypes).reduce((acc, x) => {\r\n      const fileType = x[1];\r\n      const name = x[0];\r\n      const type = new DbFileType({...fileType, name});\r\n      extLookup[type.extension] = type;\r\n      fileTypeLookup[type.name] = type;\r\n      acc[name] = type;\r\n      return acc;\r\n    }, {} as Record<string, DbFileType>);\r\n\r\n    const cfg = module.config;\r\n\r\n    const compression = cfg.compression ? CompressionAlgorithms[cfg.compression]() : undefined;\r\n\r\n    \r\n    const baseRomChunks = module.baseRomFiles?.map((file) => {\r\n      const chunkFile = new ChunkFile(fileTypeLookup[file.type], file.name);\r\n      chunkFile.textData = file.text;\r\n      chunkFile.rawData = file.data ? decodeBase64(file.data) : undefined;\r\n      chunkFile.size = chunkFile.rawData?.length ?? file.text?.length ?? 0;\r\n      return chunkFile;\r\n    });\r\n    \r\n    const projectChunks = module.projectFiles?.map((file) => {\r\n      const chunkFile = new ChunkFile(fileTypeLookup[file.type], file.name);\r\n      chunkFile.group = file.module;\r\n      chunkFile.textData = file.text;\r\n      chunkFile.rawData = file.data ? decodeBase64(file.data) : undefined;\r\n      chunkFile.size = chunkFile.rawData?.length ?? file.text?.length ?? 0;\r\n      return chunkFile;\r\n    });\r\n\r\n    // Build the database root\r\n    const root: DbRoot = {\r\n      headers: module.headers.map((h) => new DbHeader(h)),\r\n      mnemonics: module.mnemonics ?? {},\r\n      mnemonicsLookup: Object.entries(module.mnemonics).reduce((acc, x) => {\r\n        const value = parseInt(x[0])\r\n        acc[x[1]] = value.toString(16).toUpperCase().padStart(value <= 0xFF ? 2 : value <= 0xFFFF ? 4 : 6, '0');\r\n        return acc;\r\n      }, {} as Record<string, string>),\r\n      overrides: module.overrides ?? {},\r\n      rewrites: module.rewrites ?? {},\r\n      labels: module.labels ?? {},\r\n      names: nameLookup,\r\n      structs: structLookup,\r\n      blocks: blocksArray.sort((a, b) => {\r\n        const orderA = a.order ?? 0;\r\n        const orderB = b.order ?? 0;\r\n        if (orderA !== orderB) return orderA - orderB;\r\n        return a.parts[0].start - b.parts[0].start;\r\n      }),\r\n      files: fileList,\r\n      fileTypes,\r\n      fileExtLookup: extLookup,\r\n      copDef: copCodes,\r\n      copLookup,\r\n      config: cfg,\r\n      opCodes,\r\n      opLookup,\r\n      addrLookup,\r\n      entryPoints: cfg.entryPoints,\r\n      stringTypes: stringLookup,\r\n      stringDelimiters: stringDelimiterList,\r\n      stringDelimiterLookup,\r\n      compression,\r\n      groups: groupLookup,\r\n      scenes: sceneLookup,\r\n      baseRomFiles: baseRomChunks,\r\n      projectFiles: projectChunks,\r\n      comments: module.comments ?? {},\r\n      blockNotes: module.blockNotes ?? {},\r\n      partNotes: module.partNotes ?? {},\r\n      types: typeLookup\r\n    };\r\n\r\n    return root;\r\n  }\r\n\r\n  public static async applyFolder(root: DbRoot, folderPath: string, sourceFiles: ChunkFile[] = [], group?: string) : Promise<ChunkFile[]> {\r\n    const chunkFiles = sourceFiles;\r\n    const folderEntries = await listDirectory(folderPath, { recursive: true });\r\n    for(const entry of folderEntries) {\r\n      if(!entry.isFile || !entry.extension) continue; //await this.applyFolder(root, entry.path, chunkFiles);\r\n    \r\n      const type = root.fileExtLookup[entry.extension];\r\n      if(!type) continue;\r\n\r\n      const existing = chunkFiles.find(x => x.name === entry.name && x.type.type === type.type);\r\n      const chunkFile = existing ?? new ChunkFile(type, entry.name);\r\n\r\n      if(group) chunkFile.group = group;\r\n\r\n      if(chunkFile.type.isBlock || chunkFile.type.isPatch || chunkFile.struct) {\r\n        const chunkData = await readFileAsText(entry.path);\r\n        chunkFile.textData = chunkData;\r\n        chunkFile.size = chunkData.length;\r\n      } else {\r\n        const chunkData = await readFileAsBinary(entry.path);\r\n        chunkFile.rawData = chunkData;\r\n        chunkFile.size = chunkData.length;\r\n      }\r\n      if(!existing){\r\n        const sourceFile = root.files.find(x => x.name === entry.name && x.type === type.name);\r\n        if (sourceFile) {\r\n          chunkFile.location = sourceFile.start;\r\n          chunkFile.upper = sourceFile.upper ?? chunkFile.upper;\r\n          chunkFile.compressed = sourceFile.compressed ?? chunkFile.compressed;\r\n          chunkFile.base = sourceFile.base ?? chunkFile.base;\r\n          chunkFile.upper = sourceFile.upper ?? chunkFile.upper;\r\n        } else if (type.isBlock) {\r\n          const sourceBlock = root.blocks.find(x => x.name === entry.name);\r\n          if(sourceBlock) {\r\n            chunkFile.location = sourceBlock.parts[0].start;\r\n            chunkFile.upper = root.config.memoryMode === MemoryMapMode.Lo || (chunkFile.location & 0x8000) !== 0;\r\n            chunkFile.base = sourceBlock.base ?? chunkFile.base;\r\n          }\r\n        } else if (type.isPatch) { \r\n          chunkFile.upper = true;\r\n        }\r\n        \r\n        chunkFiles.push(chunkFile);\r\n      }\r\n    }\r\n    return chunkFiles;\r\n  }\r\n\r\n  \r\n  public static async extractAllContent(root: DbRoot, romPath: string, outPath: string) : Promise<void> {\r\n    const romData = await readFileAsBinary(romPath);\r\n    const reader = new BlockReader(romData, root);\r\n    const chunkFiles = reader.analyzeAndResolve();\r\n    const writer = new BlockWriter(reader);\r\n\r\n    for(const block of chunkFiles) {\r\n      const ext = block.type.extension;\r\n      const filePath = `${outPath}/${block.group ? (block.group + '/') : ''}${block.scene ? (block.scene + '/') : ''}${block.name}${ext ? '.' + ext : ''}`;\r\n      if(block.parts?.length) {\r\n        block.textData = writer.generateAsm(block);\r\n        await saveFileAsText(filePath, block.textData);\r\n      } else {\r\n        if (!block.rawData) continue;\r\n        await saveFileAsBinary(filePath, block.rawData);\r\n      }\r\n    }\r\n  }\r\n\r\n  public static async rebuildAllContent(root: DbRoot, inPath: string[], outPath: string) \r\n  : Promise<{ masterLookup: Record<string, AsmBlock>, files: ChunkFile[], header: any, romData: Uint8Array }> {\r\n    var sourceFiles: ChunkFile[] = [];\r\n\r\n    for(const path of inPath) sourceFiles = await this.applyFolder(root, path, sourceFiles);\r\n\r\n    const romWriter = new RomWriter(root);\r\n    const outData = await romWriter.repack(sourceFiles);\r\n    await saveFileAsBinary(outPath, outData.romData);\r\n\r\n    return outData;\r\n  }\r\n\r\n\r\n  // /**\r\n  //  * Get path configuration for a resource type\r\n  //  */\r\n  // public static getPath(root: DbRoot, type: BinType): DbPath {\r\n  //   return root.paths[type] || root.paths[BinType.Unknown];\r\n  // }\r\n\r\n  // /**\r\n  //  * Get resource path for a file\r\n  //  */\r\n  // public static getResource(root: DbRoot, baseDir: string, name: string, type: BinType): string {\r\n  //   const res = this.getPath(root, type);\r\n  //   return `${baseDir}/${res.folder}/${name}.${res.extension}`;\r\n  // }\r\n\r\n  /**\r\n   * Load database from Supabase using BaseRomBranch ID\r\n   * @param baseRomBranchId - The ID of the BaseRomBranch to load\r\n   * @returns Promise<DbRoot> containing the complete database root\r\n   * @throws {Error} If the branch is not found or loading fails\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const dbRoot = await DbRootUtils.fromSupabaseById('clm1234567890');\r\n   * console.log(dbRoot.files.length);\r\n   * ```\r\n   */\r\n  // public static async fromSupabaseById(baseRomBranchId: string): Promise<DbRoot> {\r\n  //   const payload = await fromSupabaseById(baseRomBranchId);\r\n  //   return this.fromSupabasePayload(payload);\r\n  // }\r\n\r\n  /**\r\n   * Load database from Supabase using name-based lookup\r\n   * @param options - Options for name-based lookup (optional)\r\n   * @returns Promise<DbRoot> containing the complete database root\r\n   * @throws {Error} If the branch is not found or loading fails\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Load default ROM (GaiaLabs BaseROM, main branch)\r\n   * const dbRoot1 = await DbRootUtils.fromSupabase({});\r\n   * \r\n   * // Load specific ROM and branch\r\n   * const dbRoot2 = await DbRootUtils.fromSupabase({\r\n   *   baseRomName: 'My Custom ROM',\r\n   *   branchName: 'development',\r\n   *   branchVersion: null\r\n   * });\r\n   * ```\r\n   */\r\n  // public static async fromSupabase(options?: FromSupabaseByNameOptions): Promise<DbRoot> {\r\n  //   const payload = await fromSupabaseByName(options);\r\n  //   return this.fromSupabasePayload(payload);\r\n  // }\r\n\r\n  // public static async fromSupabaseProject(projectName?: string, branchId?: string): Promise<DbRoot> {\r\n  //   const payload = await fromSupabaseByProject(projectName, branchId);\r\n  //   return this.fromSupabasePayload(payload);\r\n  // }\r\n\r\n  /**\r\n   * Load database from GameRomBranch data (for ROM-only processing)\r\n   * @param gameRomBranchData - Direct GameRomBranch data from Supabase API\r\n   * @returns Promise<DbRoot> containing the complete database root\r\n   */\r\n  // public static async fromSupabaseGameRom(gameRomName?: string, branchId?: string): Promise<DbRoot> {\r\n  //   const payload = await fromSupabaseByGameRom(gameRomName, branchId);\r\n  //   return this.fromSupabasePayload(payload);\r\n  // }\r\n\r\n  /**\r\n   * Convert Supabase payload to DbRoot structure\r\n   * @private\r\n   * @param payload - The ROM payload from Supabase\r\n   * @returns DbRoot containing the processed database structure\r\n   */\r\n  // private static async fromSupabasePayload(payload: ProjectPayload): Promise<DbRoot> {\r\n    \r\n  //   // Extract data from the Supabase payload\r\n  //   const gameRomBranch = payload.baseRomBranch.gameRomBranch;\r\n    \r\n  //   const config = gameRomBranch.config;\r\n  //   const copDef = gameRomBranch.coplib;\r\n  //   const romFiles = gameRomBranch.files;\r\n  //   const romBlocks = gameRomBranch.blocks;\r\n  //   const romStrings = gameRomBranch.strings;\r\n  //   const romStructs = gameRomBranch.structs;\r\n  //   const romFixups = gameRomBranch.fixups;\r\n  //   const romScenes = gameRomBranch.scenes;\r\n\r\n  //   const platformBranch = gameRomBranch.platformBranch;\r\n  //   const instructionSet = platformBranch.instructionSet;\r\n  //   const addressingModes = platformBranch.addressingModes;\r\n  //   //const vectors = platformBranch.vectors;\r\n\r\n  //   const transforms = romFixups.transforms || [];\r\n\r\n  //   // Build configuration from available data\r\n  //   const compression = config.compression ? CompressionAlgorithms[config.compression]() : null;\r\n    \r\n  //   const files: DbFile[] = Object.entries(romFiles).map((x: any) => {\r\n  //     const file = x[1];\r\n  //     file.start = file.location;\r\n  //     file.end = file.location + file.size;\r\n  //     //file.type = BinType[file.type as keyof typeof BinType] || BinType.Unknown;\r\n  //     file.name = x[0];\r\n  //     return file;\r\n  //   });\r\n    \r\n  //   const blocks: DbBlock[] = Object.entries(romBlocks).map((x: any) => {\r\n  //     const block = x[1];\r\n  //     block.name = x[0];\r\n\r\n  //     const transform = transforms[block.name];\r\n  //     block.transforms = transform ? Object.entries(transform).map((t: any) => { return { key: t[0], value: t[1] } }) : [];\r\n      \r\n  //     block.parts = Object.entries(block.parts)\r\n  //       .sort((a: any, b: any) => {\r\n  //         const orderA = a[1].order ?? 0;\r\n  //         const orderB = b[1].order ?? 0;\r\n  //         if (orderA !== orderB) {\r\n  //           return orderA - orderB;\r\n  //         }\r\n  //         return a[1].location - b[1].location;\r\n  //       })\r\n  //       .map((p: any) => {\r\n  //         const part = p[1];\r\n  //         part.name = p[0];\r\n  //         part.start = part.location;\r\n  //         part.end = part.location + part.size;\r\n  //         part.struct = part.type;\r\n  //         return part;\r\n  //       });\r\n\r\n  //     return block;\r\n  //   }).sort((a: any, b: any) => a.parts[0].location - b.parts[0].location);\r\n    \r\n  //   const baseRomFiles : ChunkFile[] = payload.baseRomFiles && payload.baseRomFiles.map((file: BaseRomFileData) => {\r\n  //     const chunkFile = new ChunkFile(file.name, 0, 0, file.type as BinType);\r\n  //     if(file.isText) {\r\n  //       chunkFile.textData = file.text ?? undefined;\r\n  //       chunkFile.size = file.text?.length ?? 0;\r\n  //     } else {\r\n  //       chunkFile.rawData = file.data;\r\n  //       chunkFile.size = file.data?.length ?? 0;\r\n  //     }\r\n  //     return chunkFile;\r\n  //   });\r\n    \r\n  //   const projectFiles : ChunkFile[] = payload.projectFiles && payload.projectFiles.map((file: ProjectFileData) => {\r\n  //     const chunkFile = new ChunkFile(file.name, 0, 0, file.type as BinType);\r\n  //     chunkFile.group = file.module ?? undefined;\r\n  //     if(file.isText) {\r\n  //       chunkFile.textData = file.text ?? undefined;\r\n  //       chunkFile.size = file.text?.length ?? 0;\r\n  //     } else {\r\n  //       chunkFile.rawData = file.data;\r\n  //       chunkFile.size = file.data?.length ?? 0;\r\n  //     }\r\n  //     return chunkFile;\r\n  //   });\r\n\r\n  //   // Extract other data from the JSON structures\r\n  //   const mnemonics = romFixups.mnemonics || {};\r\n  //   const opCodes = this.extractOpCodesFromInstructionSet(instructionSet);\r\n  //   const overrides = romFixups.overrides || {};\r\n  //   const rewrites = romFixups.rewrites || {};\r\n  //   const labels = romFixups.labels || {};\r\n  //   const structs = romStructs || {};\r\n  //   //const parts: DbPart[] = Array.isArray(typesJson.parts) ? typesJson.parts : [];\r\n  //   //const transforms: DbTransform[] = Array.isArray(typesJson.transforms) ? typesJson.transforms : [];\r\n  //   //const stringTypes = romTypes.strings || {};\r\n  //   //const stringCommands = romTypes.stringCommands || {};\r\n  //   //const stringLayers = Array.isArray(romTypes.stringLayers) ? romTypes.stringLayers : [];\r\n  //   //const copDef = Array.isArray(romTypes.copDef) ? romTypes.copDef : [];\r\n  //   const entryPoints = Array.isArray(config.entryPoints) ? config.entryPoints : [];\r\n    \r\n\r\n  //   const stringTypes = Object.entries(romStrings).reduce((acc: any, x: any) => {\r\n  //     const strType = x[1];\r\n  //     strType.name = x[0];\r\n\r\n  //     const commands = Object.entries(strType.commands).reduce((acc: any, x: any) => {\r\n  //       const cmd = x[1];\r\n  //       acc[cmd.code] = {\r\n  //         key: cmd.code,\r\n  //         value: x[0],\r\n  //         types: cmd.types,\r\n  //         delimiter: cmd.delimiter,\r\n  //         halt: cmd.halt\r\n  //       };\r\n  //       return acc;\r\n  //     }, {} as Record<number, any>);\r\n  //     strType.commands = commands;\r\n\r\n  //     acc[strType.name] = strType;\r\n  //     return acc;\r\n  //   }, {} as Record<string, DbStringType>);\r\n    \r\n  //   // Build lookup tables\r\n  //   const copLookup = Object.entries(copDef).reduce((acc: any, x: any) => {\r\n  //     const def = x[1];\r\n  //     def.mnem = x[0];\r\n  //     def.size = RomProcessingConstants.getSize(def.parts);\r\n  //     acc[x[0]] = def;\r\n  //     return acc;\r\n  //   }, {} as Record<string, CopDef>);\r\n    \r\n  //   const copDefLookup = Object.values(copDef).reduce((acc: any, x: any) => {\r\n  //     acc[x.code] = x;\r\n  //     return acc;\r\n  //   }, {} as Record<number, CopDef>);\r\n    \r\n    \r\n  //   const opLookup = Object.entries(instructionSet).reduce((acc: any, x: any) => {\r\n  //     acc[x[0]] = Object.entries(x[1]).map((y: any) => new OpCode(y[1], x[0], y[0]));\r\n  //     return acc;\r\n  //   }, {});\r\n\r\n  //   const stringDelimiters = Object.values(stringTypes).map((x: any) => x?.delimiter).filter(Boolean);\r\n  //   const stringCharLookup = Object.values(stringTypes).reduce((acc: any, x: any) => {\r\n  //     if (x?.delimiter) {\r\n  //       acc[x.delimiter] = x;\r\n  //     }\r\n  //     return acc;\r\n  //   }, {});\r\n    \r\n\r\n  //   const scenes = {} as Record<number, DbScene>;\r\n  //   const sceneGroups = Object.entries(romScenes ?? {}).reduce((acc: any, x: any) => {\r\n  //     const group = x[1];\r\n  //     const groupName = x[0];\r\n  //     const newGroup = {\r\n  //       name: groupName,\r\n  //       scenes: Object.entries(group).reduce((accy: any, y: any) => {\r\n  //         const scene = y[1];\r\n  //         const sceneName = y[0];\r\n  //         const newScene = {\r\n  //           name: sceneName,\r\n  //           id: scene.id,\r\n  //           group: groupName,\r\n  //           assets: scene.assets.map((asset: any, index: number) : DbAsset => {\r\n  //             const meta = { ...asset };\r\n  //             delete meta.type;\r\n  //             delete meta.data;\r\n  //             return { \r\n  //               index,\r\n  //               type: asset.type,\r\n  //               file: asset.data,\r\n  //               scene: sceneName,\r\n  //               meta\r\n  //             };\r\n  //           }),\r\n  //         };\r\n  //         if(scene.id) {\r\n  //           scenes[scene.id] = newScene;\r\n  //         }\r\n  //         accy[sceneName] = newScene;\r\n  //         return accy;\r\n  //       }, {} as Record<string, DbScene>)\r\n  //     }\r\n\r\n  //     acc[groupName] = newGroup;\r\n  //     return acc;\r\n  //   }, {} as Record<string, DbGroup>);\r\n    \r\n    \r\n  //   // Build the complete DbRoot structure\r\n  //   const root: DbRoot = {\r\n  //     mnemonics: Object.entries(mnemonics).reduce((acc: any, x: any) => {\r\n  //       acc[x[1]] = x[0];\r\n  //       return acc;\r\n  //     }, {} as Record<number, string>),\r\n  //     overrides: Array.isArray(overrides) ? overrides.reduce((acc: any, x: any) => {\r\n  //       acc[x.location] = x;\r\n  //       return acc;\r\n  //     }, {}) : overrides,\r\n  //     rewrites: Array.isArray(rewrites) ? rewrites.reduce((acc: any, x: any) => {\r\n  //       acc[x.location] = x.value;\r\n  //       return acc;\r\n  //     }, {}) : rewrites,\r\n  //     labels: Array.isArray(labels) ? labels.reduce((acc: any, x: any) => {\r\n  //       acc[x.location] = x.label;\r\n  //       return acc;\r\n  //     }, {}) : labels,\r\n  //     structs: Object.entries(structs).reduce((acc: any, x: any) => {\r\n  //       const struct = x[1];\r\n  //       struct.name = x[0];\r\n  //       acc[x[0]] = struct;\r\n  //       return acc;\r\n  //     }, {} as Record<string, DbStruct>),\r\n  //     blocks,\r\n  //     files,\r\n  //     copDef: copDefLookup as Record<number, CopDef>,\r\n  //     copLookup,\r\n  //     baseRomFiles,\r\n  //     projectFiles,\r\n  //     config,\r\n  //     opCodes,\r\n  //     opLookup,\r\n  //     addrLookup: addressingModes,\r\n  //     entryPoints,\r\n  //     //paths: config.paths,\r\n  //     stringTypes: stringTypes,\r\n  //     stringDelimiters,\r\n  //     //stringCharLookup: stringCharLookup as Record<string, DbStringType>,\r\n  //     compression,\r\n  //     groups: sceneGroups,\r\n  //     scenes\r\n  //   };\r\n\r\n  //   console.log('✅ Successfully transformed Supabase payload to DbRoot');\r\n  //   console.log(`📁 Files: ${files.length}, 🧱 Blocks: ${blocks.length}`);\r\n  //   console.log(`🎯 ROM: ${payload.baseRomBranch.baseRom.name} (${payload.baseRomBranch.name || 'main'})`);\r\n  //   console.log(`💾 BaseRom files: ${root?.baseRomFiles?.length} files, ${root.baseRomFiles?.reduce((sum, f) => sum + f.size, 0)} bytes total`);\r\n  //   console.log(`💾 Project files: ${root?.projectFiles?.length} files, ${root.projectFiles?.reduce((sum, f) => sum + f.size, 0)} bytes total`);\r\n    \r\n  //   return root;\r\n  // }\r\n\r\n  /**\r\n   * Extract and flatten OpCodes from the instruction set schema\r\n   * @private\r\n   * @param instructionSet - The instruction set object from the schema\r\n   * @returns Array of OpCode objects with code, mnem, mode, and size properties\r\n   */\r\n  // private static extractOpCodesFromInstructionSet(instructionSet: any): OpCode[] {\r\n  //   const opCodes: OpCode[] = [];\r\n    \r\n  //   for (const mnem in instructionSet) {\r\n  //     for (const mode in instructionSet[mnem]) {\r\n  //       const op = instructionSet[mnem][mode];\r\n  //       opCodes[op] = new OpCode(op, mnem, mode);\r\n  //     }\r\n  //   }\r\n    \r\n  //   return opCodes;\r\n  // }\r\n\r\n  // /**\r\n  //  * Convert GameRomBranch data directly to DbRoot structure\r\n  //  * @private\r\n  //  * @param gameRomBranchData - Direct GameRomBranch data from Supabase API\r\n  //  * @returns DbRoot containing the processed database structure\r\n  //  */\r\n  // private static async fromGameRomBranchData(gameRomBranchData: any): Promise<DbRoot> {\r\n    \r\n  //   // Extract data from the GameRomBranch data\r\n  //   const config = gameRomBranchData.config;\r\n  //   const copDef = gameRomBranchData.coplib;\r\n  //   const romFiles = gameRomBranchData.files;\r\n  //   const romBlocks = gameRomBranchData.blocks;\r\n  //   const romTypes = gameRomBranchData.types;\r\n  //   const romFixups = gameRomBranchData.fixups;\r\n  //   const structs = gameRomBranchData.structs;\r\n\r\n  //   // Note: For direct GameRomBranch processing, we won't have platformBranch data\r\n  //   // So we'll use defaults or extract from what's available\r\n  //   const instructionSet = {}; // Will be empty for now\r\n  //   const addressingModes = {}; // Will be empty for now\r\n    \r\n  //   const transforms = romFixups?.transforms || [];\r\n\r\n  //   // Build configuration from available data\r\n  //   const compression = CompressionRegistry.get(config?.compression || 'QuintetLZ');\r\n    \r\n  //   const files: DbFile[] = romFiles ? Object.entries(romFiles).map((x: any) => {\r\n  //     const file = x[1];\r\n  //     file.start = file.location;\r\n  //     file.end = file.location + file.size;\r\n  //     file.name = x[0];\r\n  //     return file;\r\n  //   }) : [];\r\n    \r\n  //   const blocks: DbBlock[] = romBlocks ? Object.entries(romBlocks).map((x: any) => {\r\n  //     const block = x[1];\r\n  //     block.name = x[0];\r\n\r\n  //     const transform = transforms[block.name];\r\n  //     block.transforms = transform ? Object.entries(transform).map((t: any) => { return { key: t[0], value: t[1] } }) : [];\r\n      \r\n  //     block.parts = Object.entries(block.parts || {})\r\n  //       .sort((a: any, b: any) => {\r\n  //         const orderA = a[1].order ?? 0;\r\n  //         const orderB = b[1].order ?? 0;\r\n  //         if (orderA !== orderB) {\r\n  //           return orderA - orderB;\r\n  //         }\r\n  //         return a[1].location - b[1].location;\r\n  //       })\r\n  //       .map((p: any) => {\r\n  //         const part = p[1];\r\n  //         part.name = p[0];\r\n  //         part.start = part.location;\r\n  //         part.end = part.location + part.size;\r\n  //         part.struct = part.type;\r\n  //         return part;\r\n  //       });\r\n\r\n  //     return block;\r\n  //   }).sort((a: any, b: any) => a.parts[0]?.location || 0 - b.parts[0]?.location || 0) : [];\r\n    \r\n  //   // For GameRomBranch direct processing, we don't have baseRomFiles or projectFiles\r\n  //   const baseRomFiles: ChunkFile[] = [];\r\n  //   const projectFiles: ChunkFile[] = [];\r\n    \r\n  //   const entryPoints: DbEntryPoint[] = [];\r\n    \r\n  //   // Extract overrides from configs (if available)\r\n  //   const overrides: Record<number, DbOverride> = {};\r\n    \r\n  //   // Build OpCode array from instruction set\r\n  //   const opCodes = this.extractOpCodesFromInstructionSet(instructionSet);\r\n    \r\n  //   // Build lookup tables\r\n  //   const copDefLookup = Object.values(copDef || {}).reduce((acc: any, x: any) => {\r\n  //     acc[x.code] = x;\r\n  //     return acc;\r\n  //   }, {} as Record<number, CopDef>);\r\n    \r\n  //   const opLookup = Object.entries(instructionSet).reduce((acc: any, x: any) => {\r\n  //     acc[x[0]] = Object.entries(x[1]).map((y: any) => new OpCode(y[1], x[0], y[0]));\r\n  //     return acc;\r\n  //   }, {});\r\n\r\n  //   const stringDelimiters = Object.values(romTypes || {}).map((x: any) => x?.delimiter).filter(Boolean);\r\n  //   const stringCharLookup = Object.values(romTypes || {}).reduce((acc: any, x: any) => {\r\n  //     if (x?.delimiter) {\r\n  //       acc[x.delimiter] = x;\r\n  //     }\r\n  //     return acc;\r\n  //   }, {});\r\n    \r\n  //   // Create the root object\r\n  //   const dbRoot: DbRoot = {\r\n  //     copDef: copDefLookup as Record<number, CopDef>,\r\n  //     copLookup: copDef || {},\r\n  //     stringTypes: romTypes || {},\r\n  //     stringDelimiters,\r\n  //     stringCharLookup: stringCharLookup as Record<string, DbStringType>,\r\n  //     structs: structs || {},\r\n  //     files,\r\n  //     blocks,\r\n  //     entryPoints,\r\n  //     overrides,\r\n  //     labels: {},\r\n  //     rewrites: {},\r\n  //     compression,\r\n  //     opCodes,\r\n  //     opLookup,\r\n  //     addrLookup: addressingModes,\r\n  //     mnemonics: {},\r\n  //     baseRomFiles,\r\n  //     projectFiles,\r\n  //     config: config || {}\r\n  //   };\r\n    \r\n  //   return dbRoot;\r\n  // }\r\n} ","\r\nexport class DbOverride {\r\n  location: number;\r\n  register: string;\r\n  value: number;\r\n\r\n  constructor(values: Partial<DbOverride>) {\r\n    if(typeof values.value !== 'number') throw new Error('Value is required');\r\n    if(typeof values.location !== 'number') throw new Error('Location is required');\r\n    if(!values.register) throw new Error('Register is required');\r\n\r\n    this.location = values.location;\r\n    this.register = values.register;\r\n    this.value = values.value;\r\n\r\n  }\r\n} ","/**\r\n * Database path configuration\r\n * Converted from GaiaLib/Database/DbPath.cs\r\n */\r\nexport interface DbPath {\r\n  folder: string;\r\n  extension: string;\r\n}\r\n\r\n/**\r\n * Creates a default DbPath\r\n */\r\nexport function createDbPath(folder: string = 'misc', extension: string = 'bin'): DbPath {\r\n  return {\r\n    folder,\r\n    extension\r\n  };\r\n} ","/**\r\n * Static ROM package loader\r\n * \r\n * Provides browser-friendly fetch-based alternatives to Supabase loading.\r\n * Reads pre-built JSON packages served as static files from GitHub Pages\r\n * or any other static hosting.\r\n */\r\n\r\nimport { DbGameRomModule } from '../database/modules';\r\nimport type { PackageSummary } from './types';\r\n\r\n/**\r\n * Fetch the lightweight summary from a static package URL.\r\n * Appends a timestamp query param to bypass browser/CDN caching so the\r\n * summary (and its embedded `packageHash`) is always fresh.\r\n * \r\n * @param baseUrl - Base URL where the static package is hosted (e.g. '/data' or 'https://example.com/data')\r\n * @returns PackageSummary with project name, version, modules, CRC, fileTypes, packageHash\r\n */\r\nexport async function summaryFromPackageUrl(baseUrl: string): Promise<PackageSummary> {\r\n  const url = `${baseUrl}/summary.json?t=${Date.now()}`;\r\n  const response = await fetch(url);\r\n  if (!response.ok) {\r\n    throw new Error(`Failed to fetch package summary from ${url}: ${response.status} ${response.statusText}`);\r\n  }\r\n  return response.json() as Promise<PackageSummary>;\r\n}\r\n\r\n/**\r\n * Fetch the full ROM package from a static URL and assemble a DbGameRomModule.\r\n * \r\n * When a `packageHash` is provided (from the summary), it is appended as a\r\n * query param so the browser cache invalidates whenever the content changes.\r\n * \r\n * Binary file data stored as base64 strings is decoded to Uint8Array.\r\n * \r\n * @param baseUrl - Base URL where the static package is hosted (e.g. '/data' or 'https://example.com/data')\r\n * @param packageHash - Content hash from PackageSummary.packageHash for cache-busting\r\n * @returns DbGameRomModule ready for use with DbRootUtils.fromGameModule()\r\n */\r\nexport async function fromPackageUrl(baseUrl: string, packageHash?: string): Promise<DbGameRomModule> {\r\n  const cacheBust = packageHash ? `?h=${packageHash}` : '';\r\n  const url = `${baseUrl}/rom-package.json${cacheBust}`;\r\n  const response = await fetch(url);\r\n  if (!response.ok) {\r\n    throw new Error(`Failed to fetch ROM package from ${url}: ${response.status} ${response.statusText}`);\r\n  }\r\n\r\n  const pkg = await response.json() as any;\r\n\r\n  const module: DbGameRomModule = {\r\n    projectFiles: pkg.projectFiles,\r\n    baseRomFiles: pkg.baseRomFiles,\r\n    mnemonics: pkg.mnemonics,\r\n    overrides: pkg.overrides,\r\n    rewrites: pkg.rewrites,\r\n    blocks: pkg.blocks,\r\n    files: pkg.files,\r\n    config: pkg.config,\r\n    labels: pkg.labels,\r\n    structs: pkg.structs,\r\n    copdef: pkg.copdef,\r\n    strings: pkg.strings,\r\n    transforms: pkg.transforms,\r\n    groups: pkg.groups,\r\n    fileTypes: pkg.fileTypes,\r\n    addrModes: pkg.addrModes,\r\n    headers: pkg.headers,\r\n    names: pkg.names,\r\n    types: pkg.types,\r\n  };\r\n\r\n  return module;\r\n}\r\n","import { crc32_buffer } from '../utils';\r\nimport { DbRoot, DbRootUtils } from '../database';\r\nimport { ChunkFile } from '../types/files';\r\nimport { BlockReader, BlockWriter } from './extraction';\r\nimport { RomWriter } from './rebuild';\r\nimport { fromPackageUrl } from '../static/package-loader';\r\nimport { DbGameRomModule } from '../database/modules';\r\nimport { listDirectory } from '../utils/file';\r\n\r\nexport class RomGenerator {\r\n  public readonly projectName: string;\r\n  public readonly crc: number;\r\n  public dbRoot: DbRoot = {} as DbRoot;\r\n  private sourceData: Uint8Array = new Uint8Array();\r\n\r\n  constructor(projectName: string, crc: number) {\r\n    this.projectName = projectName;\r\n    this.crc = crc;\r\n  }\r\n\r\n  public async validateAndLoad(sourceData: Uint8Array, gameModule: DbGameRomModule, baseRomPath: string, modulePath: string): Promise<boolean> {\r\n    const calc = crc32_buffer(sourceData);\r\n    if(this.crc !== calc) return false;\r\n    \r\n    this.dbRoot = DbRootUtils.fromGameModule(gameModule);\r\n\r\n    let moduleFiles: ChunkFile[] = [];\r\n    for(const entry of await listDirectory(modulePath)) {\r\n      if(!entry.isDirectory) continue;\r\n      moduleFiles.push(...await DbRootUtils.applyFolder(this.dbRoot, entry.path, [], entry.name));\r\n    }\r\n\r\n    //const moduleData = await fromSupabaseByProject(this.projectName);\r\n    this.dbRoot.baseRomFiles = await DbRootUtils.applyFolder(this.dbRoot, baseRomPath);\r\n    this.dbRoot.projectFiles = moduleFiles;\r\n    this.sourceData = sourceData;\r\n    return true;\r\n  }\r\n\r\n  public async validateAndLoadFromUrl(sourceData: Uint8Array, packageUrl: string, packageHash?: string): Promise<boolean> {\r\n    const calc = crc32_buffer(sourceData);\r\n    if(this.crc !== calc) return false;\r\n\r\n    const moduleData = await fromPackageUrl(packageUrl, packageHash);\r\n    this.dbRoot = DbRootUtils.fromGameModule(moduleData);\r\n    this.sourceData = sourceData;\r\n    return true;\r\n  }\r\n\r\n  public async generateProject(modules: string[], manualFiles?: ChunkFile[], unshiftManualFiles: boolean = false): Promise<Uint8Array> {\r\n    if(!this.dbRoot) throw new Error('Database not initialized');\r\n    if(!this.sourceData) throw new Error('Source data not initialized');\r\n\r\n    //Initialize chunks\r\n    const reader = new BlockReader(this.sourceData, this.dbRoot);\r\n    const chunkFiles = reader.analyzeAndResolve();\r\n    const asmFiles = chunkFiles.filter(b => b.parts?.length);\r\n    const patchFiles: ChunkFile[] = [];\r\n\r\n    //Convert asm blocks to text\r\n    const writer = new BlockWriter(reader);\r\n    for(const block of chunkFiles) {\r\n      if(block.parts?.length) block.textData = writer.generateAsm(block);\r\n    }\r\n\r\n    //Apply baserom files\r\n    for (const chunkFile of this.dbRoot.baseRomFiles!) this.applyPatchFile(chunkFile, chunkFiles, asmFiles, patchFiles);\r\n\r\n    //Apply base project files and collect module files\r\n    const moduleLookup = this.applyProjectInit(chunkFiles, asmFiles, patchFiles);\r\n\r\n    //Apply manual files (before modules)\r\n    if(unshiftManualFiles) {\r\n      for(const file of manualFiles ?? []) this.applyPatchFile(file, chunkFiles, asmFiles, patchFiles);\r\n    }\r\n\r\n    //Apply selected modules\r\n    for(const module of modules) {\r\n      for(const file of moduleLookup.get(module)!) this.applyPatchFile(file, chunkFiles, asmFiles, patchFiles);\r\n    }\r\n\r\n    //Apply manual files\r\n    if(!unshiftManualFiles) {\r\n      for(const file of manualFiles ?? []) this.applyPatchFile(file, chunkFiles, asmFiles, patchFiles);\r\n    }\r\n\r\n    const romWriter = new RomWriter(this.dbRoot);\r\n    const outRom = await romWriter.repack(chunkFiles, modules);\r\n\r\n    return outRom.romData;\r\n  }\r\n\r\n  private applyProjectInit(chunkFiles: ChunkFile[], asmFiles: ChunkFile[], patchFiles: ChunkFile[]){\r\n    const moduleLookup: Map<string, ChunkFile[]> = new Map();\r\n\r\n    //Run a single pass to collect all the module files, and apply base files\r\n    for (const chunkFile of this.dbRoot.projectFiles!) {\r\n      // Parse the patch file with the assembler\r\n      console.log(`Processing patch: ${chunkFile.name}`);\r\n\r\n      //ChunkFile.group is the module name\r\n      if(chunkFile.group){\r\n        let modArray = moduleLookup.get(chunkFile.group);\r\n        if(!modArray) moduleLookup.set(chunkFile.group, modArray = []);\r\n        modArray.push(chunkFile);\r\n      } else this.applyPatchFile(chunkFile, chunkFiles, asmFiles, patchFiles); //If chunk file is not part of a group, apply it now\r\n    }\r\n\r\n    return moduleLookup;\r\n  }\r\n\r\n  public applyPatchFile(chunkFile: ChunkFile, chunkFiles: ChunkFile[], asmFiles: ChunkFile[], patchFiles: ChunkFile[]): void {\r\n    console.log(`Processing patch: ${chunkFile.name}`);\r\n    const existing = chunkFiles.find(x => x.name === chunkFile.name);\r\n\r\n    if(chunkFile.textData) {\r\n      if(existing){\r\n        existing.textData = chunkFile.textData;\r\n      } else {\r\n        if(chunkFile.type.isPatch) {\r\n          patchFiles.push(chunkFile);\r\n        }\r\n        asmFiles.push(chunkFile);\r\n        chunkFiles.push(chunkFile);\r\n      }\r\n    } else {\r\n      if(existing){\r\n        existing.rawData = chunkFile.rawData;\r\n        existing.size = chunkFile.size;\r\n      } else {\r\n        chunkFiles.push(chunkFile);\r\n      }\r\n    }\r\n  }\r\n}","/**\r\n * Represents a single frame in a sprite animation sequence\r\n */\r\nexport class SpriteFrame {\r\n  public duration: number;\r\n  public groupIndex: number;\r\n  \r\n  /**\r\n   * Internal offset to the group data (not serialized)\r\n   */\r\n  public groupOffset: number;\r\n\r\n  constructor(duration: number = 0, groupIndex: number = 0, groupOffset: number = 0) {\r\n    this.duration = duration;\r\n    this.groupIndex = groupIndex;\r\n    this.groupOffset = groupOffset;\r\n  }\r\n} ","/**\r\n * Represents a single part/piece of a sprite\r\n */\r\nexport class SpritePart {\r\n  public isLarge: boolean;\r\n  public xOffset: number;\r\n  public xOffsetMirror: number;\r\n  public yOffset: number;\r\n  public yOffsetMirror: number;\r\n  public vMirror: boolean;\r\n  public hMirror: boolean;\r\n  public someOffset: number;\r\n  public paletteIndex: number;\r\n  public tileIndex: number;\r\n\r\n  constructor() {\r\n    this.isLarge = false;\r\n    this.xOffset = 0;\r\n    this.xOffsetMirror = 0;\r\n    this.yOffset = 0;\r\n    this.yOffsetMirror = 0;\r\n    this.vMirror = false;\r\n    this.hMirror = false;\r\n    this.someOffset = 0;\r\n    this.paletteIndex = 0;\r\n    this.tileIndex = 0;\r\n  }\r\n} ","import { SpritePart } from './SpritePart';\r\n\r\n/**\r\n * Represents a group of sprite parts that form a complete sprite frame\r\n */\r\nexport class SpriteGroup {\r\n  public xOffset: number;\r\n  public xOffsetMirror: number;\r\n  public yOffset: number;\r\n  public yOffsetMirror: number;\r\n  public xRecoilHitboxOffset: number;\r\n  public yRecoilHitboxOffset: number;\r\n  public xRecoilHitboxTilesize: number;\r\n  public yRecoilHitboxTilesize: number;\r\n  public xHostileHitboxOffset: number;\r\n  public xHostileHitboxSize: number;\r\n  public yHostileHitboxOffset: number;\r\n  public yHostileHitboxSize: number;\r\n  public parts: SpritePart[];\r\n\r\n  constructor() {\r\n    this.xOffset = 0;\r\n    this.xOffsetMirror = 0;\r\n    this.yOffset = 0;\r\n    this.yOffsetMirror = 0;\r\n    this.xRecoilHitboxOffset = 0;\r\n    this.yRecoilHitboxOffset = 0;\r\n    this.xRecoilHitboxTilesize = 0;\r\n    this.yRecoilHitboxTilesize = 0;\r\n    this.xHostileHitboxOffset = 0;\r\n    this.xHostileHitboxSize = 0;\r\n    this.yHostileHitboxOffset = 0;\r\n    this.yHostileHitboxSize = 0;\r\n    this.parts = [];\r\n  }\r\n} ","import { SpriteFrame } from './SpriteFrame';\r\nimport { SpriteGroup } from './SpriteGroup';\r\nimport { SpritePart } from './SpritePart';\r\n\r\n/**\r\n * Represents a complete sprite map with frame sets and groups\r\n */\r\nexport class SpriteMap {\r\n  public frameSets: SpriteFrame[][];\r\n  public groups: SpriteGroup[];\r\n\r\n  constructor() {\r\n    this.frameSets = [];\r\n    this.groups = [];\r\n  }\r\n\r\n  /**\r\n   * Create a SpriteMap from binary data\r\n   * @param data Binary data buffer\r\n   * @returns SpriteMap instance\r\n   */\r\n  public static fromBytes(data: Uint8Array): SpriteMap {\r\n    let position = 0;\r\n\r\n    const getByte = (): number => {\r\n      if (position >= data.length) return 0;\r\n      return data[position++];\r\n    };\r\n\r\n    const getUshort = (): number => {\r\n      if (position + 1 >= data.length) return 0;\r\n      const low = data[position++];\r\n      const high = data[position++];\r\n      return low | (high << 8);\r\n    };\r\n\r\n    const spriteMap = new SpriteMap();\r\n    const setOffsets = new Set<number>();\r\n    const groupOffsets = new Set<number>();\r\n\r\n    // Read frame set offsets\r\n    position = 0;\r\n    while (!setOffsets.has(position)) {\r\n      const offset = getUshort() - 0x4000;\r\n      setOffsets.add(offset);\r\n    }\r\n\r\n    // Read frame sets\r\n    for (const offStart of setOffsets) {\r\n      position = offStart;\r\n      const frameList: SpriteFrame[] = [];\r\n\r\n      while (true) {\r\n        const duration = getUshort();\r\n        if (duration === 0xFFFF) {\r\n          break;\r\n        }\r\n\r\n        const groupOffset = getUshort() - 0x4000;\r\n        frameList.push(new SpriteFrame(duration, 0, groupOffset));\r\n        groupOffsets.add(groupOffset);\r\n      }\r\n\r\n      spriteMap.frameSets.push(frameList);\r\n    }\r\n\r\n    // Read groups\r\n    let grpIx = 0;\r\n    const sortedGroupOffsets = Array.from(groupOffsets).sort((a, b) => a - b);\r\n    \r\n    for (const offStart of sortedGroupOffsets) {\r\n      position = offStart;\r\n\r\n      // Update frame group indices\r\n      for (const set of spriteMap.frameSets) {\r\n        for (const frame of set) {\r\n          if (frame.groupOffset === offStart) {\r\n            frame.groupIndex = grpIx;\r\n          }\r\n        }\r\n      }\r\n\r\n      const grp = new SpriteGroup();\r\n      grp.xOffset = getByte();\r\n      grp.xOffsetMirror = getByte();\r\n      grp.yOffset = getByte();\r\n      grp.yOffsetMirror = getByte();\r\n      grp.xRecoilHitboxOffset = getByte();\r\n      grp.yRecoilHitboxOffset = getByte();\r\n      grp.xRecoilHitboxTilesize = getByte();\r\n      grp.yRecoilHitboxTilesize = getByte();\r\n      grp.xHostileHitboxOffset = getByte();\r\n      grp.xHostileHitboxSize = getByte();\r\n      grp.yHostileHitboxOffset = getByte();\r\n      grp.yHostileHitboxSize = getByte();\r\n\r\n      let numParts = getByte();\r\n      while (numParts-- > 0) {\r\n        const part = new SpritePart();\r\n        part.isLarge = getByte() !== 0;\r\n        part.xOffset = getByte();\r\n        part.xOffsetMirror = getByte();\r\n        part.yOffset = getByte();\r\n        part.yOffsetMirror = getByte();\r\n\r\n        const props = getUshort();\r\n        part.vMirror = (props & 0x8000) !== 0;\r\n        part.hMirror = (props & 0x4000) !== 0;\r\n        part.someOffset = (props >> 12) & 0x3;\r\n        part.paletteIndex = (props >> 9) & 0x7;\r\n        part.tileIndex = props & 0x1FF;\r\n\r\n        grp.parts.push(part);\r\n      }\r\n\r\n      spriteMap.groups.push(grp);\r\n      grpIx++;\r\n    }\r\n\r\n    return spriteMap;\r\n  }\r\n\r\n  /**\r\n   * Convert this SpriteMap to binary data\r\n   * @returns Binary data buffer\r\n   */\r\n  public toBytes(): Uint8Array {\r\n    // Calculate buffer size (estimate)\r\n    let size = this.frameSets.length * 2; // Frame set offsets\r\n    \r\n    for (const set of this.frameSets) {\r\n      size += (set.length * 4) + 2; // Frames + terminator\r\n    }\r\n    \r\n    for (const grp of this.groups) {\r\n      size += (grp.parts.length * 7) + 13; // Parts + group header\r\n    }\r\n\r\n    const buffer = new Uint8Array(size);\r\n    let position = 0;\r\n\r\n    const writeShort = (val: number): void => {\r\n      buffer[position++] = val & 0xFF;\r\n      buffer[position++] = (val >> 8) & 0xFF;\r\n    };\r\n\r\n    const writeLoc = (val: number): void => writeShort(val + 0x4000);\r\n\r\n    let pos = this.frameSets.length << 1;\r\n    const groupPos = new Array<number>(this.groups.length);\r\n\r\n    // Write frame set offsets\r\n    for (const set of this.frameSets) {\r\n      writeLoc(pos);\r\n      pos += (set.length << 2) + 2;\r\n    }\r\n\r\n    // Calculate group positions\r\n    for (let i = 0; i < this.groups.length; i++) {\r\n      groupPos[i] = pos;\r\n      pos += this.groups[i].parts.length * 7 + 13;\r\n    }\r\n\r\n    // Write frame sets\r\n    for (const set of this.frameSets) {\r\n      for (const frm of set) {\r\n        writeShort(frm.duration);\r\n        writeLoc(groupPos[frm.groupIndex]);\r\n      }\r\n      writeShort(0xFFFF);\r\n    }\r\n\r\n    // Write groups\r\n    for (const grp of this.groups) {\r\n      buffer[position++] = grp.xOffset;\r\n      buffer[position++] = grp.xOffsetMirror;\r\n      buffer[position++] = grp.yOffset;\r\n      buffer[position++] = grp.yOffsetMirror;\r\n      buffer[position++] = grp.xRecoilHitboxOffset;\r\n      buffer[position++] = grp.yRecoilHitboxOffset;\r\n      buffer[position++] = grp.xRecoilHitboxTilesize;\r\n      buffer[position++] = grp.yRecoilHitboxTilesize;\r\n      buffer[position++] = grp.xHostileHitboxOffset;\r\n      buffer[position++] = grp.xHostileHitboxSize;\r\n      buffer[position++] = grp.yHostileHitboxOffset;\r\n      buffer[position++] = grp.yHostileHitboxSize;\r\n      buffer[position++] = grp.parts.length;\r\n\r\n      for (const prt of grp.parts) {\r\n        buffer[position++] = prt.isLarge ? 1 : 0;\r\n        buffer[position++] = prt.xOffset;\r\n        buffer[position++] = prt.xOffsetMirror;\r\n        buffer[position++] = prt.yOffset;\r\n        buffer[position++] = prt.yOffsetMirror;\r\n\r\n        const accum = (prt.vMirror ? 0x8000 : 0)\r\n          | (prt.hMirror ? 0x4000 : 0)\r\n          | ((prt.someOffset & 0x3) << 12)\r\n          | ((prt.paletteIndex & 0x7) << 9)\r\n          | prt.tileIndex;\r\n\r\n        writeShort(accum);\r\n      }\r\n    }\r\n\r\n    // Return trimmed buffer\r\n    return buffer.slice(0, position);\r\n  }\r\n} ","import snesAddressingModes from '../snes/addressingModes.json' with { type: 'json' };\nimport snesVectors from '../snes/vectors.json' with { type: 'json' };\nimport snesHeaders from '../snes/headers.json' with { type: 'json' };\n\nexport const snes = {\n    addressingModes: snesAddressingModes,\n    vectors: snesVectors,\n    headers: snesHeaders\n}\n\n// Core modules\nexport * from './rom';\nexport * from './assembly';\nexport * from './compression';\nexport * from './sprites';\n\n// Core types\nexport * from './types'\nexport * from './project'\nexport * from './collaboration'\n\n// Database\nexport * from './database'\n\n// Static package loading\nexport * from './static'\n\n// Utilities\nexport * from './utils' \n\n// All core modules have been converted and are exported above\n\n\n// Platform detection\n//export const isPlatformBrowser = typeof window !== 'undefined';\nexport const isPlatformNode = typeof process !== 'undefined' && process.versions?.node;\n//export const isPlatformWebWorker = typeof importScripts !== 'undefined'; \n\n"],"mappings":"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"}