@gaialabs/core 0.2.12 → 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.cjs +346 -277
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +840 -823
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +840 -823
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +346 -276
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -936,10 +936,12 @@ var ProcessorStateManager = class {
|
|
|
936
936
|
var RomDataReader = class {
|
|
937
937
|
romData;
|
|
938
938
|
position;
|
|
939
|
-
|
|
939
|
+
offset;
|
|
940
|
+
constructor(romData, offset = 0) {
|
|
940
941
|
if (!romData) throw new Error("romData cannot be null");
|
|
941
942
|
this.romData = romData;
|
|
942
943
|
this.position = 0;
|
|
944
|
+
this.offset = offset;
|
|
943
945
|
}
|
|
944
946
|
readByte() {
|
|
945
947
|
return this.romData[this.position++];
|
|
@@ -1097,7 +1099,7 @@ var RomProcessingConstants = class RomProcessingConstants {
|
|
|
1097
1099
|
* BlockReader specific constants
|
|
1098
1100
|
*/
|
|
1099
1101
|
var BlockReaderConstants = class {
|
|
1100
|
-
static REF_SEARCH_MAX_RANGE =
|
|
1102
|
+
static REF_SEARCH_MAX_RANGE = 896;
|
|
1101
1103
|
static BANK_MASK_CHECK = 64;
|
|
1102
1104
|
static BYTE_DELIMITER_THRESHOLD = 256;
|
|
1103
1105
|
static BANK_HIGH_MEMORY_1 = 126;
|
|
@@ -1671,31 +1673,63 @@ var ChunkFile = class {
|
|
|
1671
1673
|
mnemonics;
|
|
1672
1674
|
group;
|
|
1673
1675
|
scene;
|
|
1674
|
-
|
|
1676
|
+
base;
|
|
1677
|
+
referenceManager;
|
|
1678
|
+
constructor(type, name, size = 0, location = 0) {
|
|
1679
|
+
this.type = type;
|
|
1675
1680
|
this.name = name;
|
|
1676
1681
|
this.size = size;
|
|
1677
1682
|
this.location = location;
|
|
1678
1683
|
this.mnemonics = {};
|
|
1679
1684
|
this.compressed = type.compressed;
|
|
1680
|
-
|
|
1685
|
+
}
|
|
1686
|
+
enrichWithRawDataFromDbFile(file, rom, compression) {
|
|
1687
|
+
this.upper = file.upper ?? this.upper;
|
|
1688
|
+
this.size = file.end - file.start;
|
|
1689
|
+
this.location = file.start;
|
|
1690
|
+
this.base = file.base ?? this.type.base ?? this.base;
|
|
1691
|
+
this.group = file.group ?? this.group;
|
|
1692
|
+
this.scene = file.scene ?? this.scene;
|
|
1693
|
+
this.compressed = file.compressed;
|
|
1694
|
+
let start = this.location;
|
|
1695
|
+
let header = null;
|
|
1696
|
+
const fileType = this.type;
|
|
1697
|
+
if (fileType.header) {
|
|
1698
|
+
header = new Uint8Array(rom.slice(start, start + fileType.header));
|
|
1699
|
+
start += fileType.header;
|
|
1700
|
+
}
|
|
1701
|
+
let length = this.size;
|
|
1702
|
+
let fileData;
|
|
1703
|
+
if (this.compressed === true && compression) {
|
|
1704
|
+
const expanded = compression.expand(rom, start, length);
|
|
1705
|
+
fileData = combineHeader(expanded, 0, expanded.length, header, fileType.type);
|
|
1706
|
+
} else {
|
|
1707
|
+
if (this.compressed !== void 0) {
|
|
1708
|
+
start += 2;
|
|
1709
|
+
length -= 2;
|
|
1710
|
+
}
|
|
1711
|
+
fileData = combineHeader(rom, start, length, header, fileType.type);
|
|
1712
|
+
}
|
|
1713
|
+
this.rawData = fileData;
|
|
1714
|
+
this.size = fileData.length;
|
|
1715
|
+
}
|
|
1716
|
+
enrichWithAsmBlocksFromDbBlock(block, memoryMode) {
|
|
1717
|
+
this.group = block.group;
|
|
1718
|
+
this.scene = block.scene;
|
|
1719
|
+
this.parts = [];
|
|
1720
|
+
this.size = 0;
|
|
1721
|
+
if (!block.parts?.length) throw new Error(`Block ${block.name} has no parts`);
|
|
1722
|
+
this.location = block.parts[0].start;
|
|
1723
|
+
this.bank = block.movable ? void 0 : memoryMode === MemoryMapMode.Lo ? this.location >> 15 : this.location >> 16;
|
|
1724
|
+
this.transforms = block.transforms;
|
|
1725
|
+
this.postProcess = block.postProcess;
|
|
1726
|
+
for (const part of block.parts) {
|
|
1727
|
+
const asmBlock = new AsmBlock(part.start, part.end - part.start, false, part.name, part.type || void 0, part.bank);
|
|
1728
|
+
this.size += asmBlock.size;
|
|
1729
|
+
this.parts.push(asmBlock);
|
|
1730
|
+
}
|
|
1681
1731
|
}
|
|
1682
1732
|
};
|
|
1683
|
-
function createChunkFileFromDbFile(rom, compression, dbFile, fileType) {
|
|
1684
|
-
const chunkFile = new ChunkFile(dbFile.name, dbFile.end - dbFile.start, dbFile.start, fileType);
|
|
1685
|
-
chunkFile.compressed = dbFile.compressed;
|
|
1686
|
-
chunkFile.upper = dbFile.upper;
|
|
1687
|
-
chunkFile.group = dbFile.group;
|
|
1688
|
-
chunkFile.scene = dbFile.scene;
|
|
1689
|
-
enrichWithRawDataFromDbFile(rom, chunkFile, compression, dbFile, fileType);
|
|
1690
|
-
return chunkFile;
|
|
1691
|
-
}
|
|
1692
|
-
function createChunkFileFromDbBlock(block, fileType, memoryMode) {
|
|
1693
|
-
const chunkFile = new ChunkFile(block.name, 0, 0, fileType);
|
|
1694
|
-
chunkFile.group = block.group;
|
|
1695
|
-
chunkFile.scene = block.scene;
|
|
1696
|
-
enrichWithPartsFromDbBlock(chunkFile, block, memoryMode);
|
|
1697
|
-
return chunkFile;
|
|
1698
|
-
}
|
|
1699
1733
|
function combineHeader(data, position, length, header, type) {
|
|
1700
1734
|
let totalLength = length + (header ? header.length : 0);
|
|
1701
1735
|
if (type === BinType.Palette && length < 512) totalLength += 512 - length;
|
|
@@ -1711,48 +1745,6 @@ function combineHeader(data, position, length, header, type) {
|
|
|
1711
1745
|
return result;
|
|
1712
1746
|
}
|
|
1713
1747
|
/**
|
|
1714
|
-
* Enriches ChunkFile with raw binary data from DbFile
|
|
1715
|
-
*/
|
|
1716
|
-
function enrichWithRawDataFromDbFile(rom, chunkFile, compression, dbFile, fileType) {
|
|
1717
|
-
let start = dbFile.start;
|
|
1718
|
-
let header = null;
|
|
1719
|
-
if (fileType.header) {
|
|
1720
|
-
header = new Uint8Array(rom.slice(start, start + fileType.header));
|
|
1721
|
-
start += fileType.header;
|
|
1722
|
-
}
|
|
1723
|
-
let length = dbFile.end - start;
|
|
1724
|
-
let fileData;
|
|
1725
|
-
if (dbFile.compressed === true && compression) {
|
|
1726
|
-
const expanded = compression.expand(rom, start, length);
|
|
1727
|
-
fileData = combineHeader(expanded, 0, expanded.length, header, fileType.type);
|
|
1728
|
-
} else {
|
|
1729
|
-
if (dbFile.compressed !== void 0) {
|
|
1730
|
-
start += 2;
|
|
1731
|
-
length -= 2;
|
|
1732
|
-
}
|
|
1733
|
-
fileData = combineHeader(rom, start, length, header, fileType.type);
|
|
1734
|
-
}
|
|
1735
|
-
chunkFile.rawData = fileData;
|
|
1736
|
-
chunkFile.size = fileData.length;
|
|
1737
|
-
}
|
|
1738
|
-
/**
|
|
1739
|
-
* Enriches ChunkFile with AsmBlock parts from DbBlock
|
|
1740
|
-
*/
|
|
1741
|
-
function enrichWithPartsFromDbBlock(chunkFile, block, memoryMode) {
|
|
1742
|
-
chunkFile.parts = [];
|
|
1743
|
-
chunkFile.size = 0;
|
|
1744
|
-
if (!block.parts?.length) throw new Error(`Block ${block.name} has no parts`);
|
|
1745
|
-
chunkFile.location = block.parts[0].start;
|
|
1746
|
-
chunkFile.bank = block.movable ? void 0 : memoryMode === MemoryMapMode.Lo ? chunkFile.location >> 15 : chunkFile.location >> 16;
|
|
1747
|
-
chunkFile.transforms = block.transforms;
|
|
1748
|
-
chunkFile.postProcess = block.postProcess;
|
|
1749
|
-
for (const part of block.parts) {
|
|
1750
|
-
const asmBlock = new AsmBlock(part.start, part.end - part.start, false, part.name, part.type || void 0, part.bank);
|
|
1751
|
-
chunkFile.size += asmBlock.size;
|
|
1752
|
-
chunkFile.parts.push(asmBlock);
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
/**
|
|
1756
1748
|
* Chunk file utilities
|
|
1757
1749
|
*/
|
|
1758
1750
|
var ChunkFileUtils = class {
|
|
@@ -1774,16 +1766,11 @@ var ChunkFileUtils = class {
|
|
|
1774
1766
|
* Calculate the total size of all blocks
|
|
1775
1767
|
*/
|
|
1776
1768
|
static calculateSize(chunkFile) {
|
|
1777
|
-
if (!chunkFile.parts) {
|
|
1778
|
-
let size = chunkFile.rawData?.length ?? chunkFile.size;
|
|
1779
|
-
if (chunkFile.type.header === -2 || chunkFile.compressed === false) {
|
|
1780
|
-
size += 2;
|
|
1781
|
-
chunkFile.size = size;
|
|
1782
|
-
}
|
|
1783
|
-
return size;
|
|
1784
|
-
}
|
|
1785
1769
|
let size = 0;
|
|
1786
|
-
|
|
1770
|
+
if (chunkFile.rawData) {
|
|
1771
|
+
size = chunkFile.rawData.length;
|
|
1772
|
+
if (chunkFile.type.header === -2 || chunkFile.compressed === false) size += 2;
|
|
1773
|
+
} else if (chunkFile.parts) for (let x = 0; x < chunkFile.parts.length; x++) {
|
|
1787
1774
|
const block = chunkFile.parts[x];
|
|
1788
1775
|
if (x > 0 && !block.label) break;
|
|
1789
1776
|
size += block.size || 0;
|
|
@@ -1802,7 +1789,7 @@ var ChunkFileUtils = class {
|
|
|
1802
1789
|
block,
|
|
1803
1790
|
part
|
|
1804
1791
|
];
|
|
1805
|
-
for (const otherBlock of root) if (otherBlock !== block) {
|
|
1792
|
+
for (const otherBlock of root) if (otherBlock !== block && !otherBlock.type.struct) {
|
|
1806
1793
|
const [otherIsInside, otherPart] = this.isInsideWithPart(otherBlock, location);
|
|
1807
1794
|
if (otherIsInside) return [
|
|
1808
1795
|
true,
|
|
@@ -1939,6 +1926,7 @@ var ReferenceManager = class {
|
|
|
1939
1926
|
structTable = /* @__PURE__ */ new Map();
|
|
1940
1927
|
markerTable = /* @__PURE__ */ new Map();
|
|
1941
1928
|
nameTable = /* @__PURE__ */ new Map();
|
|
1929
|
+
fileTable = /* @__PURE__ */ new Map();
|
|
1942
1930
|
root;
|
|
1943
1931
|
constructor(root) {
|
|
1944
1932
|
if (!root) throw new Error("root cannot be null");
|
|
@@ -2008,7 +1996,7 @@ var ReferenceManager = class {
|
|
|
2008
1996
|
}
|
|
2009
1997
|
resolveName(location, type, isBranch) {
|
|
2010
1998
|
const prefix = Address.codeFromType(type);
|
|
2011
|
-
let name;
|
|
1999
|
+
let name = null;
|
|
2012
2000
|
let label = null;
|
|
2013
2001
|
let resolvedLocation = location;
|
|
2014
2002
|
const rewrite = this.root.rewrites[location];
|
|
@@ -2017,9 +2005,8 @@ var ReferenceManager = class {
|
|
|
2017
2005
|
resolvedLocation = result.location;
|
|
2018
2006
|
label = result.label;
|
|
2019
2007
|
}
|
|
2020
|
-
|
|
2021
|
-
if (
|
|
2022
|
-
else name = isBranch ? this.createBranchLabel(resolvedLocation) : this.findClosestReference(resolvedLocation) || this.createFallbackName(resolvedLocation);
|
|
2008
|
+
name = this.nameTable.get(resolvedLocation) || null;
|
|
2009
|
+
if (!name) name = isBranch ? this.createBranchLabel(resolvedLocation) : this.findClosestReference(resolvedLocation) || this.createFallbackName(resolvedLocation);
|
|
2023
2010
|
return `${prefix || ""}${name}${label || ""}`;
|
|
2024
2011
|
}
|
|
2025
2012
|
findClosestReference(location) {
|
|
@@ -2121,6 +2108,10 @@ var StackOperations = class {
|
|
|
2121
2108
|
case "XBA":
|
|
2122
2109
|
this.handleExchangeBytes();
|
|
2123
2110
|
break;
|
|
2111
|
+
case "RTL":
|
|
2112
|
+
case "RTS":
|
|
2113
|
+
this._blockReader._referenceManager.tryAddStruct(this._blockReader._romDataReader.position, "Code");
|
|
2114
|
+
break;
|
|
2124
2115
|
}
|
|
2125
2116
|
}
|
|
2126
2117
|
handleAccumulatorPush() {
|
|
@@ -2170,7 +2161,16 @@ var CopCommandProcessor = class {
|
|
|
2170
2161
|
* Parses a COP command based on its definition
|
|
2171
2162
|
*/
|
|
2172
2163
|
parseCopCommand(copDef, operands) {
|
|
2173
|
-
|
|
2164
|
+
let parts = copDef.parts;
|
|
2165
|
+
if (copDef.conditions) for (const condition of copDef.conditions) {
|
|
2166
|
+
let value = this._romDataReader.romData[this._romDataReader.position + condition.offset];
|
|
2167
|
+
if (condition.value >= 256) value |= this._romDataReader.romData[this._romDataReader.position + condition.offset + 1] << 8;
|
|
2168
|
+
if (value === condition.value) {
|
|
2169
|
+
parts = condition.parts;
|
|
2170
|
+
break;
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
for (let partStr of parts) {
|
|
2174
2174
|
let bank = null;
|
|
2175
2175
|
const bankHintIx = partStr.indexOf("$");
|
|
2176
2176
|
if (bankHintIx > 0) {
|
|
@@ -2353,6 +2353,7 @@ var AddressingModeHandler = class {
|
|
|
2353
2353
|
if (address.isROM) {
|
|
2354
2354
|
const wrapper = new LocationWrapper(address.toLocation(), AddressType.Address);
|
|
2355
2355
|
if (this.isJumpInstruction(mnemonic)) this._blockReader.noteType(wrapper.location, "Code", false, reg);
|
|
2356
|
+
if (mnemonic === "JML") this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, "Code");
|
|
2356
2357
|
operands.push(wrapper);
|
|
2357
2358
|
} else operands.push(address);
|
|
2358
2359
|
}
|
|
@@ -2391,12 +2392,13 @@ var AddressingModeHandler = class {
|
|
|
2391
2392
|
const isPush = this.isPushInstruction(mnemonic);
|
|
2392
2393
|
if (isPush) refLoc++;
|
|
2393
2394
|
const isJump = isPush || isIndexedIndirect || this.isJumpInstruction(mnemonic);
|
|
2394
|
-
const addr = new Address(xBank1 ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) ?? 129, refLoc, registers.mode);
|
|
2395
|
+
const addr = new Address(xBank1 ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) ?? this._blockReader._root.config.defaultBank ?? 129, refLoc, registers.mode);
|
|
2395
2396
|
if (addr.isROM) {
|
|
2396
2397
|
const wrapper = new LocationWrapper(addr.toLocation(), AddressType.Offset);
|
|
2397
2398
|
if (isJump) {
|
|
2398
2399
|
const type = isIndexedIndirect ? "&Code" : "Code";
|
|
2399
2400
|
const name = this._blockReader.noteType(wrapper.location, type, isPush, registers);
|
|
2401
|
+
if (mnemonic === "JMP") this._blockReader._referenceManager.tryAddStruct(this._dataReader.position, "Code");
|
|
2400
2402
|
if (isPush) {
|
|
2401
2403
|
operands.push(`&${name}-1`);
|
|
2402
2404
|
return;
|
|
@@ -3031,10 +3033,11 @@ var StringReader = class StringReader {
|
|
|
3031
3033
|
}
|
|
3032
3034
|
parseString(stringType, fixedSize) {
|
|
3033
3035
|
const commands = stringType.commandLookup;
|
|
3034
|
-
stringType.dictionaries;
|
|
3036
|
+
const dictionaries = stringType.dictionaries;
|
|
3035
3037
|
const builder = [];
|
|
3036
3038
|
const strLoc = this._romDataReader.position;
|
|
3037
3039
|
const terminator = stringType.terminator;
|
|
3040
|
+
const modifiers = stringType.modifiers;
|
|
3038
3041
|
let currentLayer = stringType.layers[0];
|
|
3039
3042
|
do {
|
|
3040
3043
|
const c = this._romDataReader.readByte();
|
|
@@ -3042,23 +3045,35 @@ var StringReader = class StringReader {
|
|
|
3042
3045
|
if (stringType.greedyTerminator) while (this._romDataReader.peekByte() === terminator && this._blockReader.partCanContinue()) this._romDataReader.position++;
|
|
3043
3046
|
break;
|
|
3044
3047
|
}
|
|
3045
|
-
|
|
3046
|
-
|
|
3048
|
+
let cmd = void 0;
|
|
3049
|
+
const mod = modifiers ? modifiers[c] : void 0;
|
|
3050
|
+
if (mod) {
|
|
3051
|
+
const next = mod[builder[builder.length - 1]];
|
|
3052
|
+
if (next) builder[builder.length - 1] = next;
|
|
3053
|
+
else builder.push(currentLayer.map[c - (currentLayer.base ?? 0)]);
|
|
3054
|
+
} else if (cmd = commands[c]) {
|
|
3047
3055
|
this.resolveCommand(cmd, builder);
|
|
3048
3056
|
if (cmd.halt) break;
|
|
3049
3057
|
} else {
|
|
3050
3058
|
let found = false;
|
|
3051
|
-
for (const
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3059
|
+
for (const dictionary of Object.values(dictionaries)) if (dictionary.base !== void 0 && c >= dictionary.base && c <= dictionary.base + dictionary.entries.length) {
|
|
3060
|
+
builder.push(dictionary.entries[c - dictionary.base]);
|
|
3061
|
+
found = true;
|
|
3062
|
+
break;
|
|
3063
|
+
}
|
|
3064
|
+
if (!found) {
|
|
3065
|
+
for (const layer of stringType.layers) if (layer.on !== void 0) {
|
|
3066
|
+
if (c === layer.on) {
|
|
3067
|
+
currentLayer = layer;
|
|
3068
|
+
builder.push("[--]");
|
|
3069
|
+
found = true;
|
|
3070
|
+
break;
|
|
3071
|
+
}
|
|
3072
|
+
} else if (layer.base && c >= layer.base && c < layer.base + layer.map.length) {
|
|
3073
|
+
builder.push(layer.map[c - layer.base]);
|
|
3055
3074
|
found = true;
|
|
3056
3075
|
break;
|
|
3057
3076
|
}
|
|
3058
|
-
} else if (layer.base && c >= layer.base && c < layer.base + layer.map.length) {
|
|
3059
|
-
builder.push(layer.map[c - layer.base]);
|
|
3060
|
-
found = true;
|
|
3061
|
-
break;
|
|
3062
3077
|
}
|
|
3063
3078
|
if (!found) {
|
|
3064
3079
|
let index = c - (currentLayer.base ?? 0);
|
|
@@ -3093,7 +3108,7 @@ var StringReader = class StringReader {
|
|
|
3093
3108
|
if (isNaN(sloc)) break;
|
|
3094
3109
|
if (new Address(sloc >> 16 & 255, sloc & 65535, this._blockReader._root.config.memoryMode).isROM) {
|
|
3095
3110
|
this._blockReader.resolveInclude(sloc, false);
|
|
3096
|
-
const name = this._blockReader.resolveName(sloc, AddressType.Unknown, false);
|
|
3111
|
+
const name = this._blockReader._referenceManager.resolveName(sloc, AddressType.Unknown, false);
|
|
3097
3112
|
const opix = indexOfAny(name, RomProcessingConstants.OPERATORS);
|
|
3098
3113
|
if (opix > 0) {
|
|
3099
3114
|
const offsetStr = name.substring(opix + 1);
|
|
@@ -3164,29 +3179,44 @@ var TypeParser = class {
|
|
|
3164
3179
|
if (!parentType) throw new Error(`Unknown type: ${fixedTypeName}`);
|
|
3165
3180
|
const delimiter = parentType.delimiter;
|
|
3166
3181
|
const discOffset = parentType.discriminator;
|
|
3182
|
+
const discLogic = parentType.discriminatorLogic;
|
|
3183
|
+
const nullValue = parentType.null;
|
|
3167
3184
|
const objects = [];
|
|
3185
|
+
if (delimiter === void 0 && this._blockReader.delimiterReached(nullValue)) {
|
|
3186
|
+
objects.push({
|
|
3187
|
+
name: parentType.name,
|
|
3188
|
+
parts: ["null"]
|
|
3189
|
+
});
|
|
3190
|
+
return objects;
|
|
3191
|
+
}
|
|
3168
3192
|
let delReached;
|
|
3169
3193
|
while (!(delReached = this._blockReader.delimiterReached(delimiter))) {
|
|
3170
3194
|
const startPosition = this._romDataReader.position;
|
|
3171
3195
|
let targetType = parentType;
|
|
3172
|
-
if (
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
const
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3196
|
+
if (this._blockReader.delimiterReached(nullValue)) objects.push({
|
|
3197
|
+
name: parentType.name,
|
|
3198
|
+
parts: ["null"]
|
|
3199
|
+
});
|
|
3200
|
+
else {
|
|
3201
|
+
if (discOffset !== void 0) {
|
|
3202
|
+
const discPosition = this._romDataReader.position + discOffset;
|
|
3203
|
+
const desc = this._romDataReader.romData[discPosition];
|
|
3204
|
+
targetType = Object.values(this._blockReader._root.structs).find((x) => x.parent === fixedTypeName && (discLogic === "&" ? ((x.discriminator ?? 0) & desc) !== 0 : x.discriminator === desc)) || parentType;
|
|
3205
|
+
if (discOffset === 0 && parentType != targetType && discLogic === "=") this._romDataReader.position++;
|
|
3206
|
+
}
|
|
3207
|
+
const types = targetType.types;
|
|
3208
|
+
if (types && types.length > 0) {
|
|
3209
|
+
const memberCount = types.length;
|
|
3210
|
+
const prevPosition = this._romDataReader.position;
|
|
3211
|
+
const parts = new Array(memberCount);
|
|
3212
|
+
const def = {
|
|
3213
|
+
name: targetType.name,
|
|
3214
|
+
parts
|
|
3215
|
+
};
|
|
3216
|
+
for (let i = 0; i < memberCount; i++) parts[i] = this.parseType(types[i], reg, depth + 1, bank);
|
|
3217
|
+
if (discOffset !== void 0 && discOffset === this._romDataReader.position - prevPosition) this._romDataReader.position++;
|
|
3218
|
+
objects.push(def);
|
|
3219
|
+
} else this._romDataReader.position++;
|
|
3190
3220
|
}
|
|
3191
3221
|
let checkPosition = startPosition;
|
|
3192
3222
|
while (++checkPosition < this._romDataReader.position) {
|
|
@@ -3197,6 +3227,7 @@ var TypeParser = class {
|
|
|
3197
3227
|
}
|
|
3198
3228
|
}
|
|
3199
3229
|
if (!this._blockReader.partCanContinue()) break;
|
|
3230
|
+
if (nullValue !== void 0) break;
|
|
3200
3231
|
}
|
|
3201
3232
|
if (delReached && depth === 0) this._referenceManager.tryAddStruct(this._romDataReader.position, typeName);
|
|
3202
3233
|
return objects;
|
|
@@ -3222,15 +3253,16 @@ var TypeParser = class {
|
|
|
3222
3253
|
}
|
|
3223
3254
|
parseLocation(offset, bank, typeName, addrType) {
|
|
3224
3255
|
if ((bank === void 0 || bank === null) && offset === 0) return new Word(offset);
|
|
3256
|
+
offset -= this._romDataReader.offset;
|
|
3225
3257
|
let adrs;
|
|
3226
3258
|
let loc;
|
|
3227
|
-
if (addrType === AddressType.Location) loc = offset | bank << 16;
|
|
3259
|
+
if (addrType === AddressType.Location || this._romDataReader.offset) loc = offset | bank << 16;
|
|
3228
3260
|
else {
|
|
3229
3261
|
adrs = new Address(bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode), offset, this._blockReader._root.config.memoryMode);
|
|
3230
3262
|
if (!adrs.isROM) return adrs;
|
|
3231
3263
|
loc = adrs.toLocation();
|
|
3232
3264
|
}
|
|
3233
|
-
if (typeName && !this._blockReader._root.rewrites[loc]) {
|
|
3265
|
+
if (typeName && (this._romDataReader.offset || !this._blockReader._root.rewrites[loc])) {
|
|
3234
3266
|
const oldStruct = this._referenceManager.structTable.get(loc);
|
|
3235
3267
|
if (!oldStruct || oldStruct === "Branch") this._referenceManager.structTable.set(loc, typeName);
|
|
3236
3268
|
const referenceName = `${typeName.toLowerCase()}_${loc.toString(16).toUpperCase().padStart(6, "0")}`;
|
|
@@ -3421,8 +3453,6 @@ var BlockReader = class {
|
|
|
3421
3453
|
this._stringReader = new StringReader(this);
|
|
3422
3454
|
this._asmReader = new AsmReader(this);
|
|
3423
3455
|
this._typeParser = new TypeParser(this);
|
|
3424
|
-
this.initializeOverrides();
|
|
3425
|
-
this.initializeFileReferences();
|
|
3426
3456
|
}
|
|
3427
3457
|
/**
|
|
3428
3458
|
* Processes predefined overrides for registers and bank notes
|
|
@@ -3450,9 +3480,6 @@ var BlockReader = class {
|
|
|
3450
3480
|
/**
|
|
3451
3481
|
* Processes predefined file references
|
|
3452
3482
|
*/
|
|
3453
|
-
initializeFileReferences() {
|
|
3454
|
-
for (const file of this._root.files) this._referenceManager.tryAddName(file.start, file.name);
|
|
3455
|
-
}
|
|
3456
3483
|
/**
|
|
3457
3484
|
* Resolves mnemonic for a given address
|
|
3458
3485
|
*/
|
|
@@ -3472,9 +3499,6 @@ var BlockReader = class {
|
|
|
3472
3499
|
/**
|
|
3473
3500
|
* Resolves name for a location (delegated to ReferenceManager)
|
|
3474
3501
|
*/
|
|
3475
|
-
resolveName(location, type, isBranch) {
|
|
3476
|
-
return this._referenceManager.resolveName(location, type, isBranch);
|
|
3477
|
-
}
|
|
3478
3502
|
/**
|
|
3479
3503
|
* Resolves include for a location
|
|
3480
3504
|
*/
|
|
@@ -3535,6 +3559,7 @@ var BlockReader = class {
|
|
|
3535
3559
|
}
|
|
3536
3560
|
analyzeAndResolve() {
|
|
3537
3561
|
console.log("analyzeAndResolve started");
|
|
3562
|
+
this.initializeOverrides();
|
|
3538
3563
|
this.createChunkFilesFromDatabase();
|
|
3539
3564
|
this.initializeBlocksAndParts();
|
|
3540
3565
|
this.analyzeChunkFiles();
|
|
@@ -3550,9 +3575,12 @@ var BlockReader = class {
|
|
|
3550
3575
|
*/
|
|
3551
3576
|
initializeBlocksAndParts() {
|
|
3552
3577
|
console.log("initializeBlocksAndParts");
|
|
3553
|
-
for (const block of this._enrichedChunks)
|
|
3554
|
-
|
|
3555
|
-
|
|
3578
|
+
for (const block of this._enrichedChunks) {
|
|
3579
|
+
for (const part of block.parts || []) {
|
|
3580
|
+
if (part.structName) this._referenceManager.tryAddStruct(part.location, part.structName);
|
|
3581
|
+
if (part.label) this._referenceManager.tryAddName(part.location, part.label);
|
|
3582
|
+
}
|
|
3583
|
+
this._referenceManager.tryAddName(block.location, block.name);
|
|
3556
3584
|
}
|
|
3557
3585
|
}
|
|
3558
3586
|
/**
|
|
@@ -3649,7 +3677,7 @@ var BlockReader = class {
|
|
|
3649
3677
|
const size = getSize();
|
|
3650
3678
|
const startPos = pos + offset;
|
|
3651
3679
|
const data = getBytes(size);
|
|
3652
|
-
const chunk = new ChunkFile(`sfx${i.toString(16).toUpperCase().padStart(2, "0")}`, size, startPos
|
|
3680
|
+
const chunk = new ChunkFile(fileType, `sfx${i.toString(16).toUpperCase().padStart(2, "0")}`, size, startPos);
|
|
3653
3681
|
chunk.rawData = data;
|
|
3654
3682
|
chunk.group = "sfx";
|
|
3655
3683
|
this._enrichedChunks.push(chunk);
|
|
@@ -3660,7 +3688,9 @@ var BlockReader = class {
|
|
|
3660
3688
|
*/
|
|
3661
3689
|
createChunkFilesFromDbFiles() {
|
|
3662
3690
|
for (const dbFile of this._root.files) {
|
|
3663
|
-
const
|
|
3691
|
+
const fileType = this._root.fileTypes[dbFile.type];
|
|
3692
|
+
const chunkFile = new ChunkFile(fileType, dbFile.name);
|
|
3693
|
+
chunkFile.enrichWithRawDataFromDbFile(dbFile, this._romDataReader.romData, this._root.compression);
|
|
3664
3694
|
this._enrichedChunks.push(chunkFile);
|
|
3665
3695
|
}
|
|
3666
3696
|
}
|
|
@@ -3670,7 +3700,8 @@ var BlockReader = class {
|
|
|
3670
3700
|
createChunkFilesFromDbBlocks() {
|
|
3671
3701
|
const fileType = Object.values(this._root.fileTypes).find((x) => x.isBlock);
|
|
3672
3702
|
for (const block of this._root.blocks) {
|
|
3673
|
-
const chunkFile =
|
|
3703
|
+
const chunkFile = new ChunkFile(fileType, block.name);
|
|
3704
|
+
chunkFile.enrichWithAsmBlocksFromDbBlock(block, this._root.config.memoryMode);
|
|
3674
3705
|
this._enrichedChunks.push(chunkFile);
|
|
3675
3706
|
}
|
|
3676
3707
|
}
|
|
@@ -3679,14 +3710,32 @@ var BlockReader = class {
|
|
|
3679
3710
|
*/
|
|
3680
3711
|
analyzeChunkFiles() {
|
|
3681
3712
|
console.log("analyzeChunkFiles");
|
|
3682
|
-
const
|
|
3683
|
-
|
|
3713
|
+
for (const chunkFile of this._enrichedChunks) {
|
|
3714
|
+
if (!chunkFile.type.isBlock) continue;
|
|
3715
|
+
chunkFile.referenceManager = this._referenceManager;
|
|
3684
3716
|
this._currentChunk = chunkFile;
|
|
3685
3717
|
for (const asmBlock of chunkFile.parts || []) {
|
|
3686
3718
|
this._currentAsmBlock = asmBlock;
|
|
3687
3719
|
this.processPart(asmBlock);
|
|
3688
3720
|
}
|
|
3689
3721
|
}
|
|
3722
|
+
const oldState = this._referenceManager;
|
|
3723
|
+
const oldReader = this._romDataReader;
|
|
3724
|
+
const oldTypeParser = this._typeParser;
|
|
3725
|
+
for (const chunkFile of this._enrichedChunks) {
|
|
3726
|
+
if (!chunkFile.type.struct) continue;
|
|
3727
|
+
this._currentChunk = chunkFile;
|
|
3728
|
+
const asmBlock = new AsmBlock(0, chunkFile.size, false, chunkFile.name, chunkFile.type.struct);
|
|
3729
|
+
chunkFile.parts = [asmBlock];
|
|
3730
|
+
this._currentAsmBlock = asmBlock;
|
|
3731
|
+
this._referenceManager = chunkFile.referenceManager = new ReferenceManager(this._root);
|
|
3732
|
+
this._romDataReader = new RomDataReader(chunkFile.rawData, chunkFile.base ?? 0);
|
|
3733
|
+
this._typeParser = new TypeParser(this);
|
|
3734
|
+
this.processPart(asmBlock);
|
|
3735
|
+
}
|
|
3736
|
+
this._referenceManager = oldState;
|
|
3737
|
+
this._romDataReader = oldReader;
|
|
3738
|
+
this._typeParser = oldTypeParser;
|
|
3690
3739
|
}
|
|
3691
3740
|
/**
|
|
3692
3741
|
* Resolves references in assembly ChunkFiles only
|
|
@@ -3694,8 +3743,9 @@ var BlockReader = class {
|
|
|
3694
3743
|
resolveReferences() {
|
|
3695
3744
|
console.log("resolveReferences");
|
|
3696
3745
|
for (const chunkFile of this._enrichedChunks) {
|
|
3746
|
+
if (!chunkFile.type.isBlock) continue;
|
|
3697
3747
|
this._currentChunk = chunkFile;
|
|
3698
|
-
for (const asmBlock of chunkFile.parts
|
|
3748
|
+
for (const asmBlock of chunkFile.parts) {
|
|
3699
3749
|
this._currentAsmBlock = asmBlock;
|
|
3700
3750
|
this.resolveObject(asmBlock.objList, false);
|
|
3701
3751
|
}
|
|
@@ -3885,6 +3935,7 @@ var BlockWriter = class {
|
|
|
3885
3935
|
generateAsm(block) {
|
|
3886
3936
|
if (!block.parts) throw new Error("Invalid block structure for generateAsm");
|
|
3887
3937
|
const lines = [];
|
|
3938
|
+
this._referenceManager = block.referenceManager;
|
|
3888
3939
|
if (block.bank !== void 0) lines.push(`?BANK ${block.bank.toString(16).toUpperCase().padStart(2, "0")}`);
|
|
3889
3940
|
const includes = ChunkFileUtils.getIncludes(block);
|
|
3890
3941
|
if (includes && includes.length > 0) {
|
|
@@ -3929,11 +3980,11 @@ var BlockWriter = class {
|
|
|
3929
3980
|
}
|
|
3930
3981
|
if (typeof obj === "number") {
|
|
3931
3982
|
if (op.mode === "Immediate") return obj;
|
|
3932
|
-
return this.
|
|
3983
|
+
return this._referenceManager.resolveName(obj, AddressType.Address, isBranch);
|
|
3933
3984
|
}
|
|
3934
3985
|
if (this.getObjectType(obj) === ObjectType.LocationWrapper) {
|
|
3935
3986
|
const lw = obj;
|
|
3936
|
-
return this.
|
|
3987
|
+
return this._referenceManager.resolveName(lw.location, lw.type, isBranch);
|
|
3937
3988
|
}
|
|
3938
3989
|
if (this.getObjectType(obj) === ObjectType.Address) {
|
|
3939
3990
|
const addr = obj;
|
|
@@ -3985,10 +4036,10 @@ var BlockWriter = class {
|
|
|
3985
4036
|
objLines = this.writeOpArray(obj, depth);
|
|
3986
4037
|
break;
|
|
3987
4038
|
case ObjectType.LocationWrapper:
|
|
3988
|
-
objLines = [this.
|
|
4039
|
+
objLines = [this._referenceManager.resolveName(obj.location, obj.type, isBranch)];
|
|
3989
4040
|
break;
|
|
3990
4041
|
case ObjectType.Address:
|
|
3991
|
-
objLines = isArray ? [`$#${obj.
|
|
4042
|
+
objLines = isArray ? [`$#${obj.toString()}`] : [`$${obj.toString()}`];
|
|
3992
4043
|
break;
|
|
3993
4044
|
case ObjectType.ByteArray:
|
|
3994
4045
|
objLines = [`#${Array.from(obj).map((b) => b.toString(16).toUpperCase().padStart(2, "0")).join("")}`];
|
|
@@ -4048,14 +4099,14 @@ var BlockWriter = class {
|
|
|
4048
4099
|
this._isInline = true;
|
|
4049
4100
|
let first = true;
|
|
4050
4101
|
for (const op of opList) {
|
|
4051
|
-
if (first
|
|
4052
|
-
else {
|
|
4102
|
+
if (!first || depth > 0) {
|
|
4053
4103
|
const labelResult = this._referenceManager.tryGetName(op.location);
|
|
4054
4104
|
if (labelResult.found) {
|
|
4055
4105
|
lines.push("");
|
|
4056
4106
|
lines.push(` ${labelResult.referenceName}:`);
|
|
4057
4107
|
}
|
|
4058
4108
|
}
|
|
4109
|
+
first = false;
|
|
4059
4110
|
let opLine = ` ${op.mnem} `;
|
|
4060
4111
|
if (op.copDef) {
|
|
4061
4112
|
opLine += `[${op.copDef.name}]`;
|
|
@@ -4103,7 +4154,7 @@ var BlockWriter = class {
|
|
|
4103
4154
|
const adrs = new Address(rawAddr >> 16 & 255, rawAddr & 65535, this._blockReader._root.config.memoryMode);
|
|
4104
4155
|
const addressType = char === "^" ? AddressType.Offset : AddressType.Address;
|
|
4105
4156
|
let name = "";
|
|
4106
|
-
if (adrs.isROM) name = this.
|
|
4157
|
+
if (adrs.isROM) name = this._referenceManager.resolveName(adrs.toLocation(), addressType, false);
|
|
4107
4158
|
else if (addressType === AddressType.Offset) name = adrs.offset.toString(16).toUpperCase().padStart(4, "0");
|
|
4108
4159
|
else name = adrs.toString();
|
|
4109
4160
|
str = str.replace(str.substring(ix, ix + 7), name);
|
|
@@ -4245,8 +4296,8 @@ var RomLayout = class RomLayout {
|
|
|
4245
4296
|
return parseInt(a.name.substring(a.name.length - 2, a.name.length), 16) - parseInt(b.name.substring(b.name.length - 2, b.name.length), 16);
|
|
4246
4297
|
}) : [];
|
|
4247
4298
|
this.unmatchedFiles = files.filter((x) => (x.size || 0) > 0).filter((x) => this.sfxPackType === "Individual" || x.type.type !== "Sound").sort((a, b) => {
|
|
4248
|
-
const aAsm = a.
|
|
4249
|
-
const bAsm = b.
|
|
4299
|
+
const aAsm = a.rawData ? 1 : 0;
|
|
4300
|
+
const bAsm = b.rawData ? 1 : 0;
|
|
4250
4301
|
if (aAsm !== bAsm) return aAsm - bAsm;
|
|
4251
4302
|
if (b.size !== a.size) return b.size - a.size;
|
|
4252
4303
|
if (a.location !== b.location) return a.location - b.location;
|
|
@@ -4296,7 +4347,7 @@ var RomLayout = class RomLayout {
|
|
|
4296
4347
|
start += RomProcessingConstants.PAGE_SIZE;
|
|
4297
4348
|
page++;
|
|
4298
4349
|
if (offset) {
|
|
4299
|
-
const newFile = new ChunkFile(
|
|
4350
|
+
const newFile = new ChunkFile(Object.values(this.root.fileTypes).find((x) => x.type === BinType.Binary), file.name + "_2", file.size, file.location);
|
|
4300
4351
|
const end = file.rawData.length - offset;
|
|
4301
4352
|
newFile.rawData = file.rawData.slice(end);
|
|
4302
4353
|
newFile.size = newFile.rawData.length;
|
|
@@ -4386,107 +4437,13 @@ var RomLayout = class RomLayout {
|
|
|
4386
4437
|
}
|
|
4387
4438
|
};
|
|
4388
4439
|
|
|
4389
|
-
//#endregion
|
|
4390
|
-
//#region src/rom/rebuild/processor.ts
|
|
4391
|
-
/**
|
|
4392
|
-
* ROM rebuild processor
|
|
4393
|
-
* Converted from ext/GaiaLib/Rom/Rebuild/RomProcessor.cs
|
|
4394
|
-
*/
|
|
4395
|
-
var RomProcessor = class RomProcessor {
|
|
4396
|
-
writer;
|
|
4397
|
-
constructor(writer) {
|
|
4398
|
-
this.writer = writer;
|
|
4399
|
-
}
|
|
4400
|
-
async repack(allFiles, modules) {
|
|
4401
|
-
const patches = [];
|
|
4402
|
-
const asmFiles = [];
|
|
4403
|
-
const compression = this.writer.root.compression;
|
|
4404
|
-
const canCompress = !!compression;
|
|
4405
|
-
const conditionFiles = [];
|
|
4406
|
-
if (modules) conditionFiles.push(...modules);
|
|
4407
|
-
for (const file of allFiles) {
|
|
4408
|
-
if (file.type.type === "Patch") patches.push(file);
|
|
4409
|
-
else if (file.type.type !== "Assembly") {
|
|
4410
|
-
if (file.compressed === true && canCompress) if (this.writer.root.config.uncompress) file.compressed = false;
|
|
4411
|
-
else {
|
|
4412
|
-
let newData = compression.compact(file.rawData, file.type.header);
|
|
4413
|
-
if (file.type.header) newData = new Uint8Array([...file.rawData.slice(0, file.type.header), ...newData]);
|
|
4414
|
-
file.rawData = newData;
|
|
4415
|
-
file.size = newData.length;
|
|
4416
|
-
}
|
|
4417
|
-
continue;
|
|
4418
|
-
}
|
|
4419
|
-
asmFiles.push(file);
|
|
4420
|
-
conditionFiles.push(file.name);
|
|
4421
|
-
}
|
|
4422
|
-
for (const file of asmFiles) {
|
|
4423
|
-
const { blocks, includes, reqBank } = new Assembler(this.writer.root, file.textData, conditionFiles).parseAssembly();
|
|
4424
|
-
file.parts = blocks;
|
|
4425
|
-
file.includes = includes;
|
|
4426
|
-
file.bank = reqBank ?? void 0;
|
|
4427
|
-
}
|
|
4428
|
-
RomProcessor.applyPatches(asmFiles, patches);
|
|
4429
|
-
for (const file of allFiles) ChunkFileUtils.calculateSize(file);
|
|
4430
|
-
const pages = new RomLayout(allFiles, this.writer.root).organize();
|
|
4431
|
-
for (const file of asmFiles) ChunkFileUtils.rebase(file);
|
|
4432
|
-
const masterLookup = /* @__PURE__ */ new Map();
|
|
4433
|
-
for (const f of asmFiles) {
|
|
4434
|
-
const includeBlocks = asmFiles.filter((x) => f.includes?.has(x.name.toUpperCase())).flatMap((x) => x.parts).filter((b) => !!b.label);
|
|
4435
|
-
f.includeLookup = /* @__PURE__ */ new Map();
|
|
4436
|
-
for (const b of includeBlocks) if (b.label) f.includeLookup.set(b.label.toUpperCase(), b);
|
|
4437
|
-
for (const b of f.parts) if (b.label) {
|
|
4438
|
-
const nameUpper = b.label.toUpperCase();
|
|
4439
|
-
masterLookup.set(nameUpper, b.location);
|
|
4440
|
-
f.includeLookup.set(nameUpper, b);
|
|
4441
|
-
}
|
|
4442
|
-
}
|
|
4443
|
-
const fileLookup = /* @__PURE__ */ new Map();
|
|
4444
|
-
for (const f of allFiles) fileLookup.set(f.name.toUpperCase(), f.location);
|
|
4445
|
-
this.writer.allocate(pages);
|
|
4446
|
-
for (const file of allFiles) await this.writer.writeFile(file, fileLookup);
|
|
4447
|
-
return masterLookup;
|
|
4448
|
-
}
|
|
4449
|
-
static applyPatches(asmFiles, patches) {
|
|
4450
|
-
for (const patch of patches.filter((x) => x.includes && x.includes.size > 0)) {
|
|
4451
|
-
let file = null;
|
|
4452
|
-
let dstIx = -1;
|
|
4453
|
-
const inc = asmFiles.filter((x) => patch.includes.has(x.name.toUpperCase()));
|
|
4454
|
-
for (let ix = 0; patch.parts && ix < patch.parts.length;) {
|
|
4455
|
-
const block = patch.parts[ix];
|
|
4456
|
-
let match = null;
|
|
4457
|
-
if (block.label) for (const i of inc) {
|
|
4458
|
-
if (!i.parts) continue;
|
|
4459
|
-
for (let y = 0; y < i.parts.length; y++) {
|
|
4460
|
-
const check = i.parts[y];
|
|
4461
|
-
if (check.label === block.label) {
|
|
4462
|
-
file = i;
|
|
4463
|
-
dstIx = y;
|
|
4464
|
-
match = check;
|
|
4465
|
-
break;
|
|
4466
|
-
}
|
|
4467
|
-
}
|
|
4468
|
-
}
|
|
4469
|
-
if (match) file.parts[dstIx++] = block;
|
|
4470
|
-
else if (dstIx >= 0) file.parts.splice(dstIx++, 0, block);
|
|
4471
|
-
else {
|
|
4472
|
-
ix++;
|
|
4473
|
-
continue;
|
|
4474
|
-
}
|
|
4475
|
-
file.includes = file.includes || /* @__PURE__ */ new Set();
|
|
4476
|
-
file.includes.add(patch.name.toUpperCase());
|
|
4477
|
-
patch.parts.splice(ix, 1);
|
|
4478
|
-
}
|
|
4479
|
-
}
|
|
4480
|
-
}
|
|
4481
|
-
};
|
|
4482
|
-
|
|
4483
4440
|
//#endregion
|
|
4484
4441
|
//#region src/rom/rebuild/writer.ts
|
|
4485
4442
|
/**
|
|
4486
4443
|
* ROM writer (binary)
|
|
4487
4444
|
* Converted from ext/GaiaLib/Rom/Rebuild/RomWriter.cs (subset: binary write only)
|
|
4488
4445
|
*/
|
|
4489
|
-
var RomWriter = class {
|
|
4446
|
+
var RomWriter = class RomWriter {
|
|
4490
4447
|
bpsPath;
|
|
4491
4448
|
outBuffer;
|
|
4492
4449
|
romSize;
|
|
@@ -4641,7 +4598,7 @@ var RomWriter = class {
|
|
|
4641
4598
|
}
|
|
4642
4599
|
} else if (file.parts && file.parts.length > 0) {
|
|
4643
4600
|
if (file.parts[0].location !== file.location && (file.location || 0) !== 0) throw new Error("Assembly was not based properly");
|
|
4644
|
-
|
|
4601
|
+
RomWriter.parseAssembly(this.root, file.parts, fileLookup, file.includeLookup, this.outBuffer, void 0);
|
|
4645
4602
|
}
|
|
4646
4603
|
return pos - start;
|
|
4647
4604
|
}
|
|
@@ -4653,12 +4610,10 @@ var RomWriter = class {
|
|
|
4653
4610
|
* Parse assembly blocks and write binary data to output buffer
|
|
4654
4611
|
* Converted from ext/GaiaLib/Rom/Rebuild/RomWriter.cs ParseAssembly method
|
|
4655
4612
|
*/
|
|
4656
|
-
parseAssembly(blocks, fileLookup, includeLookup) {
|
|
4613
|
+
static parseAssembly(root, blocks, fileLookup, includeLookup, outBuffer, addrOffset) {
|
|
4657
4614
|
if (!blocks) throw new Error("Assembly has not been parsed");
|
|
4658
|
-
const buf = this.outBuffer;
|
|
4659
4615
|
let bix = 0;
|
|
4660
4616
|
for (const block of blocks) {
|
|
4661
|
-
let oldPos = null;
|
|
4662
4617
|
let position = block.location;
|
|
4663
4618
|
const objList = block.objList;
|
|
4664
4619
|
let oix = 0;
|
|
@@ -4673,13 +4628,13 @@ var RomWriter = class {
|
|
|
4673
4628
|
continue;
|
|
4674
4629
|
} else if (currentObj instanceof Op) {
|
|
4675
4630
|
const op = currentObj;
|
|
4676
|
-
|
|
4631
|
+
outBuffer[position++] = op.code & 255;
|
|
4677
4632
|
opos += op.size;
|
|
4678
4633
|
for (const operand of op.operands) processObject(operand, op);
|
|
4679
4634
|
break;
|
|
4680
4635
|
} else if (currentObj instanceof Uint8Array) {
|
|
4681
4636
|
const arr = currentObj;
|
|
4682
|
-
for (let i = 0; i < arr.length; i++)
|
|
4637
|
+
for (let i = 0; i < arr.length; i++) outBuffer[position + i] = arr[i];
|
|
4683
4638
|
position += arr.length;
|
|
4684
4639
|
opos += arr.length;
|
|
4685
4640
|
break;
|
|
@@ -4691,7 +4646,7 @@ var RomWriter = class {
|
|
|
4691
4646
|
if (ix > 0) label = label.substring(ix);
|
|
4692
4647
|
let loc;
|
|
4693
4648
|
const isRelative = parentOp && (parentOp.mode === "PCRelative" || parentOp.mode === "PCRelativeLong");
|
|
4694
|
-
const operatorIdx =
|
|
4649
|
+
const operatorIdx = RomWriter.indexOfAny(label, RomProcessingConstants.OPERATORS);
|
|
4695
4650
|
let offset = null;
|
|
4696
4651
|
let useMarker = false;
|
|
4697
4652
|
if (operatorIdx > 0) {
|
|
@@ -4740,12 +4695,13 @@ var RomWriter = class {
|
|
|
4740
4695
|
if (offset !== null) loc += offset;
|
|
4741
4696
|
else if (useMarker && target instanceof AsmBlock) {
|
|
4742
4697
|
let markerOffset = 0;
|
|
4743
|
-
for (const part of target.objList) if (
|
|
4698
|
+
for (const part of target.objList) if (RomWriter.isStringMarker(part)) {
|
|
4744
4699
|
loc += markerOffset;
|
|
4745
4700
|
break;
|
|
4746
4701
|
} else markerOffset += RomProcessingConstants.getSize(part);
|
|
4747
4702
|
}
|
|
4748
|
-
if (
|
|
4703
|
+
if (addrOffset !== void 0) loc += addrOffset;
|
|
4704
|
+
else if (!isRelative && type !== AddressType.Location) loc = Address.fromLocation(loc, root.config.memoryMode, root.config.cpuMode).toInt();
|
|
4749
4705
|
switch (type) {
|
|
4750
4706
|
case AddressType.Offset:
|
|
4751
4707
|
case AddressType.WRelative:
|
|
@@ -4770,7 +4726,7 @@ var RomWriter = class {
|
|
|
4770
4726
|
} else if (currentObj instanceof TypedNumber) {
|
|
4771
4727
|
let value = currentObj.value;
|
|
4772
4728
|
for (let i = 0; i < currentObj.size; i++) {
|
|
4773
|
-
|
|
4729
|
+
outBuffer[position++] = value & 255;
|
|
4774
4730
|
value >>= 8;
|
|
4775
4731
|
}
|
|
4776
4732
|
break;
|
|
@@ -4778,26 +4734,26 @@ var RomWriter = class {
|
|
|
4778
4734
|
const num = currentObj;
|
|
4779
4735
|
const size = parentOp?.size ?? 0;
|
|
4780
4736
|
if (num <= 255 && size <= 2) {
|
|
4781
|
-
|
|
4737
|
+
outBuffer[position] = num & 255;
|
|
4782
4738
|
position++;
|
|
4783
4739
|
} else if (num <= 65535 && size <= 3) {
|
|
4784
|
-
|
|
4785
|
-
|
|
4740
|
+
outBuffer[position] = num & 255;
|
|
4741
|
+
outBuffer[position + 1] = num >> 8 & 255;
|
|
4786
4742
|
position += 2;
|
|
4787
4743
|
} else if (num <= 16777215 && size <= 4) {
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4744
|
+
outBuffer[position] = num & 255;
|
|
4745
|
+
outBuffer[position + 1] = num >> 8 & 255;
|
|
4746
|
+
outBuffer[position + 2] = num >> 16 & 255;
|
|
4791
4747
|
position += 3;
|
|
4792
4748
|
} else {
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4749
|
+
outBuffer[position] = num & 255;
|
|
4750
|
+
outBuffer[position + 1] = num >> 8 & 255;
|
|
4751
|
+
outBuffer[position + 2] = num >> 16 & 255;
|
|
4752
|
+
outBuffer[position + 3] = num >> 24 & 255;
|
|
4797
4753
|
position += 4;
|
|
4798
4754
|
}
|
|
4799
4755
|
break;
|
|
4800
|
-
} else if (
|
|
4756
|
+
} else if (RomWriter.isStringMarker(currentObj)) break;
|
|
4801
4757
|
else throw new Error(`Unable to process '${currentObj}'`);
|
|
4802
4758
|
};
|
|
4803
4759
|
for (const obj of objList) {
|
|
@@ -4810,21 +4766,121 @@ var RomWriter = class {
|
|
|
4810
4766
|
/**
|
|
4811
4767
|
* Helper method to find index of any character from an array in a string
|
|
4812
4768
|
*/
|
|
4813
|
-
indexOfAny(str, chars) {
|
|
4769
|
+
static indexOfAny(str, chars) {
|
|
4814
4770
|
for (let i = 0; i < str.length; i++) if (chars.includes(str[i])) return i;
|
|
4815
4771
|
return -1;
|
|
4816
4772
|
}
|
|
4817
4773
|
/**
|
|
4818
4774
|
* Helper method to check if an object is a StringMarker
|
|
4819
4775
|
*/
|
|
4820
|
-
isStringMarker(obj) {
|
|
4776
|
+
static isStringMarker(obj) {
|
|
4821
4777
|
return typeof obj === "object" && obj !== null && "offset" in obj;
|
|
4822
4778
|
}
|
|
4823
|
-
isTableEntry(obj) {
|
|
4779
|
+
static isTableEntry(obj) {
|
|
4824
4780
|
return typeof obj === "object" && obj !== null && "location" in obj && "object" in obj;
|
|
4825
4781
|
}
|
|
4826
4782
|
};
|
|
4827
4783
|
|
|
4784
|
+
//#endregion
|
|
4785
|
+
//#region src/rom/rebuild/processor.ts
|
|
4786
|
+
/**
|
|
4787
|
+
* ROM rebuild processor
|
|
4788
|
+
* Converted from ext/GaiaLib/Rom/Rebuild/RomProcessor.cs
|
|
4789
|
+
*/
|
|
4790
|
+
var RomProcessor = class RomProcessor {
|
|
4791
|
+
writer;
|
|
4792
|
+
constructor(writer) {
|
|
4793
|
+
this.writer = writer;
|
|
4794
|
+
}
|
|
4795
|
+
async repack(allFiles, modules) {
|
|
4796
|
+
const patches = [];
|
|
4797
|
+
const asmFiles = [];
|
|
4798
|
+
const compression = this.writer.root.compression;
|
|
4799
|
+
const canCompress = !!compression;
|
|
4800
|
+
const conditionFiles = [];
|
|
4801
|
+
if (modules) conditionFiles.push(...modules);
|
|
4802
|
+
const dummyMap = /* @__PURE__ */ new Map();
|
|
4803
|
+
for (const file of allFiles) {
|
|
4804
|
+
conditionFiles.push(file.name);
|
|
4805
|
+
if (file.type.isPatch) {
|
|
4806
|
+
patches.push(file);
|
|
4807
|
+
asmFiles.push(file);
|
|
4808
|
+
} else if (file.type.isBlock) asmFiles.push(file);
|
|
4809
|
+
else if (!file.type.struct) continue;
|
|
4810
|
+
const { blocks, includes, reqBank } = new Assembler(this.writer.root, file.textData, conditionFiles).parseAssembly();
|
|
4811
|
+
file.parts = blocks;
|
|
4812
|
+
file.includes = includes;
|
|
4813
|
+
file.bank = reqBank ?? void 0;
|
|
4814
|
+
if (file.type.struct) {
|
|
4815
|
+
file.includeLookup = /* @__PURE__ */ new Map();
|
|
4816
|
+
for (const b of file.parts) if (b.label) file.includeLookup.set(b.label.toUpperCase(), b);
|
|
4817
|
+
file.rawData = void 0;
|
|
4818
|
+
file.rawData = new Uint8Array(ChunkFileUtils.calculateSize(file));
|
|
4819
|
+
RomWriter.parseAssembly(this.writer.root, file.parts, dummyMap, file.includeLookup, file.rawData, file.type.base ?? 0);
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
for (const file of allFiles) if (file.compressed === true && canCompress) if (this.writer.root.config.uncompress) file.compressed = false;
|
|
4823
|
+
else {
|
|
4824
|
+
let newData = compression.compact(file.rawData, file.type.header);
|
|
4825
|
+
if (file.type.header) newData = new Uint8Array([...file.rawData.slice(0, file.type.header), ...newData]);
|
|
4826
|
+
file.rawData = newData;
|
|
4827
|
+
file.size = newData.length;
|
|
4828
|
+
}
|
|
4829
|
+
RomProcessor.applyPatches(asmFiles, patches);
|
|
4830
|
+
for (const file of allFiles) ChunkFileUtils.calculateSize(file);
|
|
4831
|
+
const pages = new RomLayout(allFiles, this.writer.root).organize();
|
|
4832
|
+
for (const file of asmFiles) ChunkFileUtils.rebase(file);
|
|
4833
|
+
const masterLookup = /* @__PURE__ */ new Map();
|
|
4834
|
+
for (const f of asmFiles) {
|
|
4835
|
+
const includeBlocks = asmFiles.filter((x) => f.includes?.has(x.name.toUpperCase())).flatMap((x) => x.parts).filter((b) => !!b.label);
|
|
4836
|
+
f.includeLookup = /* @__PURE__ */ new Map();
|
|
4837
|
+
for (const b of includeBlocks) if (b.label) f.includeLookup.set(b.label.toUpperCase(), b);
|
|
4838
|
+
for (const b of f.parts) if (b.label) {
|
|
4839
|
+
const nameUpper = b.label.toUpperCase();
|
|
4840
|
+
masterLookup.set(nameUpper, b.location);
|
|
4841
|
+
f.includeLookup.set(nameUpper, b);
|
|
4842
|
+
}
|
|
4843
|
+
}
|
|
4844
|
+
const fileLookup = /* @__PURE__ */ new Map();
|
|
4845
|
+
for (const f of allFiles) fileLookup.set(f.name.toUpperCase(), f.location);
|
|
4846
|
+
this.writer.allocate(pages);
|
|
4847
|
+
for (const file of allFiles) await this.writer.writeFile(file, fileLookup);
|
|
4848
|
+
return masterLookup;
|
|
4849
|
+
}
|
|
4850
|
+
static applyPatches(asmFiles, patches) {
|
|
4851
|
+
for (const patch of patches.filter((x) => x.includes && x.includes.size > 0)) {
|
|
4852
|
+
let file = null;
|
|
4853
|
+
let dstIx = -1;
|
|
4854
|
+
const inc = asmFiles.filter((x) => patch.includes.has(x.name.toUpperCase()));
|
|
4855
|
+
for (let ix = 0; patch.parts && ix < patch.parts.length;) {
|
|
4856
|
+
const block = patch.parts[ix];
|
|
4857
|
+
let match = null;
|
|
4858
|
+
if (block.label) for (const i of inc) {
|
|
4859
|
+
if (!i.parts) continue;
|
|
4860
|
+
for (let y = 0; y < i.parts.length; y++) {
|
|
4861
|
+
const check = i.parts[y];
|
|
4862
|
+
if (check.label === block.label) {
|
|
4863
|
+
file = i;
|
|
4864
|
+
dstIx = y;
|
|
4865
|
+
match = check;
|
|
4866
|
+
break;
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
if (match) file.parts[dstIx++] = block;
|
|
4871
|
+
else if (dstIx >= 0) file.parts.splice(dstIx++, 0, block);
|
|
4872
|
+
else {
|
|
4873
|
+
ix++;
|
|
4874
|
+
continue;
|
|
4875
|
+
}
|
|
4876
|
+
if (!file.includes) file.includes = /* @__PURE__ */ new Set();
|
|
4877
|
+
file.includes.add(patch.name.toUpperCase());
|
|
4878
|
+
patch.parts.splice(ix, 1);
|
|
4879
|
+
}
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
};
|
|
4883
|
+
|
|
4828
4884
|
//#endregion
|
|
4829
4885
|
//#region src/rom/rebuild/string-processor.ts
|
|
4830
4886
|
/**
|
|
@@ -5517,10 +5573,7 @@ var DbBlock = class {
|
|
|
5517
5573
|
this.group = data.group ?? void 0;
|
|
5518
5574
|
this.scene = data.scene ?? void 0;
|
|
5519
5575
|
this.parts = (data.parts ?? []).sort((a, b) => {
|
|
5520
|
-
|
|
5521
|
-
const orderB = b.order ?? 0;
|
|
5522
|
-
if (orderA !== orderB) return orderA - orderB;
|
|
5523
|
-
return a.start - b.start;
|
|
5576
|
+
return (a.order ?? a.start ?? 0) - (b.order ?? b.start ?? 0);
|
|
5524
5577
|
});
|
|
5525
5578
|
this.transforms = data.transforms ?? [];
|
|
5526
5579
|
this.postProcess = data.postProcess ?? void 0;
|
|
@@ -5540,6 +5593,7 @@ var DbFile = class {
|
|
|
5540
5593
|
upper;
|
|
5541
5594
|
group;
|
|
5542
5595
|
scene;
|
|
5596
|
+
base;
|
|
5543
5597
|
constructor(data) {
|
|
5544
5598
|
if (!data.name) throw new Error("Name is required");
|
|
5545
5599
|
if (!data.type) throw new Error("Type is required");
|
|
@@ -5553,6 +5607,7 @@ var DbFile = class {
|
|
|
5553
5607
|
this.upper = data.upper ?? void 0;
|
|
5554
5608
|
this.group = data.group || void 0;
|
|
5555
5609
|
this.scene = data.scene || void 0;
|
|
5610
|
+
this.base = data.base ?? void 0;
|
|
5556
5611
|
}
|
|
5557
5612
|
};
|
|
5558
5613
|
var DbFileType = class {
|
|
@@ -5563,17 +5618,21 @@ var DbFileType = class {
|
|
|
5563
5618
|
isBlock;
|
|
5564
5619
|
header;
|
|
5565
5620
|
compressed;
|
|
5621
|
+
struct;
|
|
5622
|
+
base;
|
|
5566
5623
|
constructor(data) {
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5624
|
+
if (!data.name) throw new Error("Name is required");
|
|
5625
|
+
if (!data.extension) throw new Error("Extension is required");
|
|
5626
|
+
if (!data.type) throw new Error("Type is required");
|
|
5627
|
+
this.name = data.name;
|
|
5628
|
+
this.extension = data.extension;
|
|
5629
|
+
this.type = data.type;
|
|
5570
5630
|
this.isPatch = data.isPatch ?? false;
|
|
5571
5631
|
this.isBlock = data.isBlock ?? false;
|
|
5572
5632
|
this.header = data.header ?? 0;
|
|
5573
5633
|
this.compressed = data.compressed ?? void 0;
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
if (!this.type) throw new Error("Type is required");
|
|
5634
|
+
this.struct = data.struct ?? void 0;
|
|
5635
|
+
this.base = data.base ?? void 0;
|
|
5577
5636
|
}
|
|
5578
5637
|
};
|
|
5579
5638
|
|
|
@@ -5589,12 +5648,16 @@ var DbStruct = class {
|
|
|
5589
5648
|
parent;
|
|
5590
5649
|
delimiter;
|
|
5591
5650
|
discriminator;
|
|
5651
|
+
discriminatorLogic;
|
|
5652
|
+
null;
|
|
5592
5653
|
constructor(data) {
|
|
5593
5654
|
this.name = data.name ?? "";
|
|
5594
5655
|
this.types = data.types ?? void 0;
|
|
5595
5656
|
this.parent = data.parent ?? void 0;
|
|
5596
5657
|
this.delimiter = data.delimiter ?? void 0;
|
|
5597
5658
|
this.discriminator = data.discriminator ?? void 0;
|
|
5659
|
+
this.discriminatorLogic = data.discriminatorLogic ?? (this.discriminator !== void 0 ? "=" : void 0);
|
|
5660
|
+
this.null = data.null ?? void 0;
|
|
5598
5661
|
if (!this.name) throw new Error("Name is required");
|
|
5599
5662
|
}
|
|
5600
5663
|
};
|
|
@@ -5649,14 +5712,16 @@ var DbStringCommand = class {
|
|
|
5649
5712
|
}
|
|
5650
5713
|
};
|
|
5651
5714
|
var DbStringDictionary = class {
|
|
5715
|
+
base;
|
|
5652
5716
|
command;
|
|
5653
5717
|
commandName;
|
|
5654
5718
|
name;
|
|
5655
5719
|
entries;
|
|
5656
5720
|
constructor(data) {
|
|
5657
|
-
if (typeof data.command !== "number") throw new Error("Command is required");
|
|
5721
|
+
if (typeof data.command !== "number" && typeof data.base !== "number") throw new Error("Command or base is required");
|
|
5658
5722
|
if (!data.name) throw new Error("Name is required");
|
|
5659
5723
|
if (!data.entries || data.entries.length === 0) throw new Error("Entries is required");
|
|
5724
|
+
this.base = data.base ?? void 0;
|
|
5660
5725
|
this.command = data.command ?? void 0;
|
|
5661
5726
|
this.commandName = data.commandName ?? void 0;
|
|
5662
5727
|
this.name = data.name;
|
|
@@ -5677,6 +5742,7 @@ var DbStringType = class {
|
|
|
5677
5742
|
greedyTerminator;
|
|
5678
5743
|
dictionaries;
|
|
5679
5744
|
dictionaryLookup;
|
|
5745
|
+
modifiers;
|
|
5680
5746
|
constructor(data) {
|
|
5681
5747
|
if (!data.name) throw new Error("Name is required");
|
|
5682
5748
|
if (!data.delimiter) throw new Error("Delimiter is required");
|
|
@@ -5697,6 +5763,7 @@ var DbStringType = class {
|
|
|
5697
5763
|
text: z,
|
|
5698
5764
|
id: (y.command ?? 0) << 8 | ix
|
|
5699
5765
|
}))).sort((a, b) => b.text.length - a.text.length);
|
|
5766
|
+
this.modifiers = data.modifiers;
|
|
5700
5767
|
}
|
|
5701
5768
|
};
|
|
5702
5769
|
|
|
@@ -5712,6 +5779,7 @@ var CopDef = class {
|
|
|
5712
5779
|
size;
|
|
5713
5780
|
parts;
|
|
5714
5781
|
halt;
|
|
5782
|
+
conditions;
|
|
5715
5783
|
constructor(data) {
|
|
5716
5784
|
if (!data.name) throw new Error("Name is required");
|
|
5717
5785
|
if (typeof data.id !== "number") throw new Error("ID is required");
|
|
@@ -5720,6 +5788,7 @@ var CopDef = class {
|
|
|
5720
5788
|
this.parts = data.parts ?? [];
|
|
5721
5789
|
this.halt = data.halt ?? false;
|
|
5722
5790
|
this.size = data.size ?? 0;
|
|
5791
|
+
this.conditions = data.conditions ?? [];
|
|
5723
5792
|
}
|
|
5724
5793
|
};
|
|
5725
5794
|
|
|
@@ -6102,7 +6171,7 @@ var DbRootUtils = class {
|
|
|
6102
6171
|
const cfg = module.config;
|
|
6103
6172
|
const compression = cfg.compression ? CompressionAlgorithms[cfg.compression]() : void 0;
|
|
6104
6173
|
const baseRomChunks = module.baseRomFiles ?? module.supaBaseRomFiles?.map((file) => {
|
|
6105
|
-
const chunkFile = new ChunkFile(file.
|
|
6174
|
+
const chunkFile = new ChunkFile(fileTypeLookup[file.type], file.name);
|
|
6106
6175
|
if (file.isText) {
|
|
6107
6176
|
chunkFile.textData = file.text ?? void 0;
|
|
6108
6177
|
chunkFile.size = file.text?.length ?? 0;
|
|
@@ -6113,7 +6182,7 @@ var DbRootUtils = class {
|
|
|
6113
6182
|
return chunkFile;
|
|
6114
6183
|
});
|
|
6115
6184
|
const projectChunks = module.projectFiles ?? module.supaProjectFiles?.map((file) => {
|
|
6116
|
-
const chunkFile = new ChunkFile(file.
|
|
6185
|
+
const chunkFile = new ChunkFile(fileTypeLookup[file.type], file.name);
|
|
6117
6186
|
chunkFile.group = file.module ?? void 0;
|
|
6118
6187
|
if (file.isText) {
|
|
6119
6188
|
chunkFile.textData = file.text ?? void 0;
|
|
@@ -6165,9 +6234,9 @@ var DbRootUtils = class {
|
|
|
6165
6234
|
const type = root.fileExtLookup[entry.extension];
|
|
6166
6235
|
if (!type) continue;
|
|
6167
6236
|
const existing = chunkFiles.find((x) => x.name === entry.name && x.type.type === type.type);
|
|
6168
|
-
const chunkFile = existing ?? new ChunkFile(entry.name
|
|
6237
|
+
const chunkFile = existing ?? new ChunkFile(type, entry.name);
|
|
6169
6238
|
if (group) chunkFile.group = group;
|
|
6170
|
-
if (chunkFile.type.
|
|
6239
|
+
if (chunkFile.type.isBlock || chunkFile.type.isPatch || chunkFile.type.struct) {
|
|
6171
6240
|
const chunkData = await readFileAsText(entry.path);
|
|
6172
6241
|
chunkFile.textData = chunkData;
|
|
6173
6242
|
chunkFile.size = chunkData.length;
|
|
@@ -6196,7 +6265,7 @@ var DbRootUtils = class {
|
|
|
6196
6265
|
const ext = block.type.extension;
|
|
6197
6266
|
const filePath = `${outPath}/${block.group ? block.group + "/" : ""}${block.scene ? block.scene + "/" : ""}${block.name}${ext ? "." + ext : ""}`;
|
|
6198
6267
|
if (block.parts?.length) {
|
|
6199
|
-
|
|
6268
|
+
block.textData = writer.generateAsm(block);
|
|
6200
6269
|
await saveFileAsText(filePath, block.textData);
|
|
6201
6270
|
} else {
|
|
6202
6271
|
if (!block.rawData) continue;
|
|
@@ -7114,6 +7183,7 @@ async function summaryFromSupabaseByProject(projectName) {
|
|
|
7114
7183
|
notes,
|
|
7115
7184
|
gameRomId,
|
|
7116
7185
|
platformBranchId,
|
|
7186
|
+
fileTypes,
|
|
7117
7187
|
createdAt,
|
|
7118
7188
|
updatedAt,
|
|
7119
7189
|
gameRom:GameRom!inner(
|
|
@@ -7224,10 +7294,10 @@ var RomGenerator = class {
|
|
|
7224
7294
|
if (!this.sourceData) throw new Error("Source data not initialized");
|
|
7225
7295
|
const reader = new BlockReader(this.sourceData, this.dbRoot);
|
|
7226
7296
|
const chunkFiles = reader.analyzeAndResolve();
|
|
7227
|
-
const asmFiles = chunkFiles.filter((b) => b.type.
|
|
7297
|
+
const asmFiles = chunkFiles.filter((b) => b.type.isBlock);
|
|
7228
7298
|
const patchFiles = [];
|
|
7229
7299
|
const writer = new BlockWriter(reader);
|
|
7230
|
-
for (const block of
|
|
7300
|
+
for (const block of chunkFiles) if (block.parts?.length) block.textData = writer.generateAsm(block);
|
|
7231
7301
|
for (const chunkFile of this.dbRoot.baseRomFiles) this.applyPatchFile(chunkFile, chunkFiles, asmFiles, patchFiles);
|
|
7232
7302
|
const moduleLookup = this.applyProjectInit(chunkFiles, asmFiles, patchFiles);
|
|
7233
7303
|
if (unshiftManualFiles) for (const file of manualFiles ?? []) this.applyPatchFile(file, chunkFiles, asmFiles, patchFiles);
|
|
@@ -7252,7 +7322,7 @@ var RomGenerator = class {
|
|
|
7252
7322
|
const existing = chunkFiles.find((x) => x.name === chunkFile.name);
|
|
7253
7323
|
if (chunkFile.textData) if (existing) existing.textData = chunkFile.textData;
|
|
7254
7324
|
else {
|
|
7255
|
-
if (chunkFile.type.
|
|
7325
|
+
if (chunkFile.type.isPatch) patchFiles.push(chunkFile);
|
|
7256
7326
|
asmFiles.push(chunkFile);
|
|
7257
7327
|
chunkFiles.push(chunkFile);
|
|
7258
7328
|
}
|
|
@@ -7587,11 +7657,10 @@ exports.base64ToUint8Array = base64ToUint8Array;
|
|
|
7587
7657
|
exports.binaryToUtf8String = binaryToUtf8String;
|
|
7588
7658
|
exports.bytesToHex = bytesToHex;
|
|
7589
7659
|
exports.clamp = clamp;
|
|
7660
|
+
exports.combineHeader = combineHeader;
|
|
7590
7661
|
exports.crc32_buffer = crc32_buffer;
|
|
7591
7662
|
exports.crc32_text_utf16 = crc32_text_utf16;
|
|
7592
7663
|
exports.crc32_text_utf8 = crc32_text_utf8;
|
|
7593
|
-
exports.createChunkFileFromDbBlock = createChunkFileFromDbBlock;
|
|
7594
|
-
exports.createChunkFileFromDbFile = createChunkFileFromDbFile;
|
|
7595
7664
|
exports.createDbPath = createDbPath;
|
|
7596
7665
|
exports.createSupabaseClient = createSupabaseClient;
|
|
7597
7666
|
exports.createTempDirectory = createTempDirectory;
|