@gaialabs/core 0.2.13 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1098,7 +1098,7 @@ var RomProcessingConstants = class RomProcessingConstants {
1098
1098
  * BlockReader specific constants
1099
1099
  */
1100
1100
  var BlockReaderConstants = class {
1101
- static REF_SEARCH_MAX_RANGE = 416;
1101
+ static REF_SEARCH_MAX_RANGE = 896;
1102
1102
  static BANK_MASK_CHECK = 64;
1103
1103
  static BYTE_DELIMITER_THRESHOLD = 256;
1104
1104
  static BANK_HIGH_MEMORY_1 = 126;
@@ -1925,6 +1925,7 @@ var ReferenceManager = class {
1925
1925
  structTable = /* @__PURE__ */ new Map();
1926
1926
  markerTable = /* @__PURE__ */ new Map();
1927
1927
  nameTable = /* @__PURE__ */ new Map();
1928
+ fileTable = /* @__PURE__ */ new Map();
1928
1929
  root;
1929
1930
  constructor(root) {
1930
1931
  if (!root) throw new Error("root cannot be null");
@@ -1994,7 +1995,7 @@ var ReferenceManager = class {
1994
1995
  }
1995
1996
  resolveName(location, type, isBranch) {
1996
1997
  const prefix = Address.codeFromType(type);
1997
- let name;
1998
+ let name = null;
1998
1999
  let label = null;
1999
2000
  let resolvedLocation = location;
2000
2001
  const rewrite = this.root.rewrites[location];
@@ -2003,9 +2004,8 @@ var ReferenceManager = class {
2003
2004
  resolvedLocation = result.location;
2004
2005
  label = result.label;
2005
2006
  }
2006
- const existingName = this.nameTable.get(resolvedLocation);
2007
- if (existingName) name = existingName;
2008
- else name = isBranch ? this.createBranchLabel(resolvedLocation) : this.findClosestReference(resolvedLocation) || this.createFallbackName(resolvedLocation);
2007
+ name = this.nameTable.get(resolvedLocation) || null;
2008
+ if (!name) name = isBranch ? this.createBranchLabel(resolvedLocation) : this.findClosestReference(resolvedLocation) || this.createFallbackName(resolvedLocation);
2009
2009
  return `${prefix || ""}${name}${label || ""}`;
2010
2010
  }
2011
2011
  findClosestReference(location) {
@@ -2107,6 +2107,10 @@ var StackOperations = class {
2107
2107
  case "XBA":
2108
2108
  this.handleExchangeBytes();
2109
2109
  break;
2110
+ case "RTL":
2111
+ case "RTS":
2112
+ this._blockReader._referenceManager.tryAddStruct(this._blockReader._romDataReader.position, "Code");
2113
+ break;
2110
2114
  }
2111
2115
  }
2112
2116
  handleAccumulatorPush() {
@@ -2156,7 +2160,16 @@ var CopCommandProcessor = class {
2156
2160
  * Parses a COP command based on its definition
2157
2161
  */
2158
2162
  parseCopCommand(copDef, operands) {
2159
- for (let partStr of copDef.parts) {
2163
+ let parts = copDef.parts;
2164
+ if (copDef.conditions) for (const condition of copDef.conditions) {
2165
+ let value = this._romDataReader.romData[this._romDataReader.position + condition.offset];
2166
+ if (condition.value >= 256) value |= this._romDataReader.romData[this._romDataReader.position + condition.offset + 1] << 8;
2167
+ if (value === condition.value) {
2168
+ parts = condition.parts;
2169
+ break;
2170
+ }
2171
+ }
2172
+ for (let partStr of parts) {
2160
2173
  let bank = null;
2161
2174
  const bankHintIx = partStr.indexOf("$");
2162
2175
  if (bankHintIx > 0) {
@@ -2339,6 +2352,7 @@ var AddressingModeHandler = class {
2339
2352
  if (address.isROM) {
2340
2353
  const wrapper = new LocationWrapper(address.toLocation(), AddressType.Address);
2341
2354
  if (this.isJumpInstruction(mnemonic)) this._blockReader.noteType(wrapper.location, "Code", false, reg);
2355
+ if (mnemonic === "JML") this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, "Code");
2342
2356
  operands.push(wrapper);
2343
2357
  } else operands.push(address);
2344
2358
  }
@@ -2377,12 +2391,13 @@ var AddressingModeHandler = class {
2377
2391
  const isPush = this.isPushInstruction(mnemonic);
2378
2392
  if (isPush) refLoc++;
2379
2393
  const isJump = isPush || isIndexedIndirect || this.isJumpInstruction(mnemonic);
2380
- const addr = new Address(xBank1 ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) ?? 129, refLoc, registers.mode);
2394
+ const addr = new Address(xBank1 ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) ?? this._blockReader._root.config.defaultBank ?? 129, refLoc, registers.mode);
2381
2395
  if (addr.isROM) {
2382
2396
  const wrapper = new LocationWrapper(addr.toLocation(), AddressType.Offset);
2383
2397
  if (isJump) {
2384
2398
  const type = isIndexedIndirect ? "&Code" : "Code";
2385
2399
  const name = this._blockReader.noteType(wrapper.location, type, isPush, registers);
2400
+ if (mnemonic === "JMP") this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, "Code");
2386
2401
  if (isPush) {
2387
2402
  operands.push(`&${name}-1`);
2388
2403
  return;
@@ -3017,10 +3032,11 @@ var StringReader = class StringReader {
3017
3032
  }
3018
3033
  parseString(stringType, fixedSize) {
3019
3034
  const commands = stringType.commandLookup;
3020
- stringType.dictionaries;
3035
+ const dictionaries = stringType.dictionaries;
3021
3036
  const builder = [];
3022
3037
  const strLoc = this._romDataReader.position;
3023
3038
  const terminator = stringType.terminator;
3039
+ const modifiers = stringType.modifiers;
3024
3040
  let currentLayer = stringType.layers[0];
3025
3041
  do {
3026
3042
  const c = this._romDataReader.readByte();
@@ -3028,23 +3044,35 @@ var StringReader = class StringReader {
3028
3044
  if (stringType.greedyTerminator) while (this._romDataReader.peekByte() === terminator && this._blockReader.partCanContinue()) this._romDataReader.position++;
3029
3045
  break;
3030
3046
  }
3031
- const cmd = commands[c];
3032
- if (cmd) {
3047
+ let cmd = void 0;
3048
+ const mod = modifiers ? modifiers[c] : void 0;
3049
+ if (mod) {
3050
+ const next = mod[builder[builder.length - 1]];
3051
+ if (next) builder[builder.length - 1] = next;
3052
+ else builder.push(currentLayer.map[c - (currentLayer.base ?? 0)]);
3053
+ } else if (cmd = commands[c]) {
3033
3054
  this.resolveCommand(cmd, builder);
3034
3055
  if (cmd.halt) break;
3035
3056
  } else {
3036
3057
  let found = false;
3037
- for (const layer of stringType.layers) if (layer.on !== void 0) {
3038
- if (c === layer.on) {
3039
- currentLayer = layer;
3040
- builder.push("[--]");
3058
+ for (const dictionary of Object.values(dictionaries)) if (dictionary.base !== void 0 && c >= dictionary.base && c <= dictionary.base + dictionary.entries.length) {
3059
+ builder.push(dictionary.entries[c - dictionary.base]);
3060
+ found = true;
3061
+ break;
3062
+ }
3063
+ if (!found) {
3064
+ for (const layer of stringType.layers) if (layer.on !== void 0) {
3065
+ if (c === layer.on) {
3066
+ currentLayer = layer;
3067
+ builder.push("[--]");
3068
+ found = true;
3069
+ break;
3070
+ }
3071
+ } else if (layer.base && c >= layer.base && c < layer.base + layer.map.length) {
3072
+ builder.push(layer.map[c - layer.base]);
3041
3073
  found = true;
3042
3074
  break;
3043
3075
  }
3044
- } else if (layer.base && c >= layer.base && c < layer.base + layer.map.length) {
3045
- builder.push(layer.map[c - layer.base]);
3046
- found = true;
3047
- break;
3048
3076
  }
3049
3077
  if (!found) {
3050
3078
  let index = c - (currentLayer.base ?? 0);
@@ -3150,29 +3178,44 @@ var TypeParser = class {
3150
3178
  if (!parentType) throw new Error(`Unknown type: ${fixedTypeName}`);
3151
3179
  const delimiter = parentType.delimiter;
3152
3180
  const discOffset = parentType.discriminator;
3181
+ const discLogic = parentType.discriminatorLogic;
3182
+ const nullValue = parentType.null;
3153
3183
  const objects = [];
3184
+ if (delimiter === void 0 && this._blockReader.delimiterReached(nullValue)) {
3185
+ objects.push({
3186
+ name: parentType.name,
3187
+ parts: ["null"]
3188
+ });
3189
+ return objects;
3190
+ }
3154
3191
  let delReached;
3155
3192
  while (!(delReached = this._blockReader.delimiterReached(delimiter))) {
3156
3193
  const startPosition = this._romDataReader.position;
3157
3194
  let targetType = parentType;
3158
- if (discOffset !== void 0) {
3159
- const discPosition = this._romDataReader.position + discOffset;
3160
- const desc = this._romDataReader.romData[discPosition];
3161
- if (discOffset === 0) this._romDataReader.position++;
3162
- targetType = Object.values(this._blockReader._root.structs).find((x) => x.parent === fixedTypeName && x.discriminator === desc) || parentType;
3163
- }
3164
- const types = targetType.types;
3165
- if (types && types.length > 0) {
3166
- const memberCount = types.length;
3167
- const prevPosition = this._romDataReader.position;
3168
- const parts = new Array(memberCount);
3169
- const def = {
3170
- name: targetType.name,
3171
- parts
3172
- };
3173
- for (let i = 0; i < memberCount; i++) parts[i] = this.parseType(types[i], reg, depth + 1, bank);
3174
- if (discOffset !== void 0 && discOffset === this._romDataReader.position - prevPosition) this._romDataReader.position++;
3175
- objects.push(def);
3195
+ if (this._blockReader.delimiterReached(nullValue)) objects.push({
3196
+ name: parentType.name,
3197
+ parts: ["null"]
3198
+ });
3199
+ else {
3200
+ if (discOffset !== void 0) {
3201
+ const discPosition = this._romDataReader.position + discOffset;
3202
+ const desc = this._romDataReader.romData[discPosition];
3203
+ targetType = Object.values(this._blockReader._root.structs).find((x) => x.parent === fixedTypeName && (discLogic === "&" ? ((x.discriminator ?? 0) & desc) !== 0 : x.discriminator === desc)) || parentType;
3204
+ if (discOffset === 0 && parentType != targetType && discLogic === "=") this._romDataReader.position++;
3205
+ }
3206
+ const types = targetType.types;
3207
+ if (types && types.length > 0) {
3208
+ const memberCount = types.length;
3209
+ const prevPosition = this._romDataReader.position;
3210
+ const parts = new Array(memberCount);
3211
+ const def = {
3212
+ name: targetType.name,
3213
+ parts
3214
+ };
3215
+ for (let i = 0; i < memberCount; i++) parts[i] = this.parseType(types[i], reg, depth + 1, bank);
3216
+ if (discOffset !== void 0 && discOffset === this._romDataReader.position - prevPosition) this._romDataReader.position++;
3217
+ objects.push(def);
3218
+ } else this._romDataReader.position++;
3176
3219
  }
3177
3220
  let checkPosition = startPosition;
3178
3221
  while (++checkPosition < this._romDataReader.position) {
@@ -3183,6 +3226,7 @@ var TypeParser = class {
3183
3226
  }
3184
3227
  }
3185
3228
  if (!this._blockReader.partCanContinue()) break;
3229
+ if (nullValue !== void 0) break;
3186
3230
  }
3187
3231
  if (delReached && depth === 0) this._referenceManager.tryAddStruct(this._romDataReader.position, typeName);
3188
3232
  return objects;
@@ -3435,9 +3479,6 @@ var BlockReader = class {
3435
3479
  /**
3436
3480
  * Processes predefined file references
3437
3481
  */
3438
- initializeFileReferences() {
3439
- for (const file of this._root.files) this._referenceManager.tryAddName(file.start, file.name);
3440
- }
3441
3482
  /**
3442
3483
  * Resolves mnemonic for a given address
3443
3484
  */
@@ -3518,7 +3559,6 @@ var BlockReader = class {
3518
3559
  analyzeAndResolve() {
3519
3560
  console.log("analyzeAndResolve started");
3520
3561
  this.initializeOverrides();
3521
- this.initializeFileReferences();
3522
3562
  this.createChunkFilesFromDatabase();
3523
3563
  this.initializeBlocksAndParts();
3524
3564
  this.analyzeChunkFiles();
@@ -3534,9 +3574,12 @@ var BlockReader = class {
3534
3574
  */
3535
3575
  initializeBlocksAndParts() {
3536
3576
  console.log("initializeBlocksAndParts");
3537
- for (const block of this._enrichedChunks) for (const part of block.parts || []) {
3538
- if (part.structName) this._referenceManager.tryAddStruct(part.location, part.structName);
3539
- if (part.label) this._referenceManager.tryAddName(part.location, part.label);
3577
+ for (const block of this._enrichedChunks) {
3578
+ for (const part of block.parts || []) {
3579
+ if (part.structName) this._referenceManager.tryAddStruct(part.location, part.structName);
3580
+ if (part.label) this._referenceManager.tryAddName(part.location, part.label);
3581
+ }
3582
+ this._referenceManager.tryAddName(block.location, block.name);
3540
3583
  }
3541
3584
  }
3542
3585
  /**
@@ -3995,7 +4038,7 @@ var BlockWriter = class {
3995
4038
  objLines = [this._referenceManager.resolveName(obj.location, obj.type, isBranch)];
3996
4039
  break;
3997
4040
  case ObjectType.Address:
3998
- objLines = isArray ? [`$#${obj.offset.toString(16).toUpperCase().padStart(4, "0")}`] : [`$${obj.toString()}`];
4041
+ objLines = isArray ? [`$#${obj.toString()}`] : [`$${obj.toString()}`];
3999
4042
  break;
4000
4043
  case ObjectType.ByteArray:
4001
4044
  objLines = [`#${Array.from(obj).map((b) => b.toString(16).toUpperCase().padStart(2, "0")).join("")}`];
@@ -4055,14 +4098,14 @@ var BlockWriter = class {
4055
4098
  this._isInline = true;
4056
4099
  let first = true;
4057
4100
  for (const op of opList) {
4058
- if (first) first = false;
4059
- else {
4101
+ if (!first || depth > 0) {
4060
4102
  const labelResult = this._referenceManager.tryGetName(op.location);
4061
4103
  if (labelResult.found) {
4062
4104
  lines.push("");
4063
4105
  lines.push(` ${labelResult.referenceName}:`);
4064
4106
  }
4065
4107
  }
4108
+ first = false;
4066
4109
  let opLine = ` ${op.mnem} `;
4067
4110
  if (op.copDef) {
4068
4111
  opLine += `[${op.copDef.name}]`;
@@ -4829,7 +4872,7 @@ var RomProcessor = class RomProcessor {
4829
4872
  ix++;
4830
4873
  continue;
4831
4874
  }
4832
- file.includes = file.includes || /* @__PURE__ */ new Set();
4875
+ if (!file.includes) file.includes = /* @__PURE__ */ new Set();
4833
4876
  file.includes.add(patch.name.toUpperCase());
4834
4877
  patch.parts.splice(ix, 1);
4835
4878
  }
@@ -5529,10 +5572,7 @@ var DbBlock = class {
5529
5572
  this.group = data.group ?? void 0;
5530
5573
  this.scene = data.scene ?? void 0;
5531
5574
  this.parts = (data.parts ?? []).sort((a, b) => {
5532
- const orderA = a.order ?? 0;
5533
- const orderB = b.order ?? 0;
5534
- if (orderA !== orderB) return orderA - orderB;
5535
- return a.start - b.start;
5575
+ return (a.order ?? a.start ?? 0) - (b.order ?? b.start ?? 0);
5536
5576
  });
5537
5577
  this.transforms = data.transforms ?? [];
5538
5578
  this.postProcess = data.postProcess ?? void 0;
@@ -5607,12 +5647,16 @@ var DbStruct = class {
5607
5647
  parent;
5608
5648
  delimiter;
5609
5649
  discriminator;
5650
+ discriminatorLogic;
5651
+ null;
5610
5652
  constructor(data) {
5611
5653
  this.name = data.name ?? "";
5612
5654
  this.types = data.types ?? void 0;
5613
5655
  this.parent = data.parent ?? void 0;
5614
5656
  this.delimiter = data.delimiter ?? void 0;
5615
5657
  this.discriminator = data.discriminator ?? void 0;
5658
+ this.discriminatorLogic = data.discriminatorLogic ?? (this.discriminator !== void 0 ? "=" : void 0);
5659
+ this.null = data.null ?? void 0;
5616
5660
  if (!this.name) throw new Error("Name is required");
5617
5661
  }
5618
5662
  };
@@ -5667,14 +5711,16 @@ var DbStringCommand = class {
5667
5711
  }
5668
5712
  };
5669
5713
  var DbStringDictionary = class {
5714
+ base;
5670
5715
  command;
5671
5716
  commandName;
5672
5717
  name;
5673
5718
  entries;
5674
5719
  constructor(data) {
5675
- if (typeof data.command !== "number") throw new Error("Command is required");
5720
+ if (typeof data.command !== "number" && typeof data.base !== "number") throw new Error("Command or base is required");
5676
5721
  if (!data.name) throw new Error("Name is required");
5677
5722
  if (!data.entries || data.entries.length === 0) throw new Error("Entries is required");
5723
+ this.base = data.base ?? void 0;
5678
5724
  this.command = data.command ?? void 0;
5679
5725
  this.commandName = data.commandName ?? void 0;
5680
5726
  this.name = data.name;
@@ -5695,6 +5741,7 @@ var DbStringType = class {
5695
5741
  greedyTerminator;
5696
5742
  dictionaries;
5697
5743
  dictionaryLookup;
5744
+ modifiers;
5698
5745
  constructor(data) {
5699
5746
  if (!data.name) throw new Error("Name is required");
5700
5747
  if (!data.delimiter) throw new Error("Delimiter is required");
@@ -5715,6 +5762,7 @@ var DbStringType = class {
5715
5762
  text: z,
5716
5763
  id: (y.command ?? 0) << 8 | ix
5717
5764
  }))).sort((a, b) => b.text.length - a.text.length);
5765
+ this.modifiers = data.modifiers;
5718
5766
  }
5719
5767
  };
5720
5768
 
@@ -5730,6 +5778,7 @@ var CopDef = class {
5730
5778
  size;
5731
5779
  parts;
5732
5780
  halt;
5781
+ conditions;
5733
5782
  constructor(data) {
5734
5783
  if (!data.name) throw new Error("Name is required");
5735
5784
  if (typeof data.id !== "number") throw new Error("ID is required");
@@ -5738,6 +5787,7 @@ var CopDef = class {
5738
5787
  this.parts = data.parts ?? [];
5739
5788
  this.halt = data.halt ?? false;
5740
5789
  this.size = data.size ?? 0;
5790
+ this.conditions = data.conditions ?? [];
5741
5791
  }
5742
5792
  };
5743
5793