@gaialabs/core 0.2.1 → 0.2.2
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 +385 -257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -12
- package/dist/index.d.mts +29 -12
- package/dist/index.mjs +385 -258
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -131,6 +131,148 @@ var RomDataReader = class {
|
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/types/constants.ts
|
|
136
|
+
/**
|
|
137
|
+
* ROM processing constants
|
|
138
|
+
* Converted from GaiaLib/Types/RomProcessingConstants.cs
|
|
139
|
+
*/
|
|
140
|
+
var RomProcessingConstants = class RomProcessingConstants {
|
|
141
|
+
static PAGE_SIZE = 32768;
|
|
142
|
+
static SNES_HEADER_SIZE = 80;
|
|
143
|
+
static DICTIONARIES = ["dictionary_01EBA8", "dictionary_01F54D"];
|
|
144
|
+
static DICT_COMMANDS = [214, 215];
|
|
145
|
+
static END_CHARS = [
|
|
146
|
+
192,
|
|
147
|
+
202,
|
|
148
|
+
209
|
|
149
|
+
];
|
|
150
|
+
static WHITESPACE = [" ", " "];
|
|
151
|
+
static OPERATORS = ["-", "+"];
|
|
152
|
+
static COMMA_SPACE = [
|
|
153
|
+
",",
|
|
154
|
+
" ",
|
|
155
|
+
" "
|
|
156
|
+
];
|
|
157
|
+
static ADDRESS_SPACE = [
|
|
158
|
+
"@",
|
|
159
|
+
"&",
|
|
160
|
+
"^",
|
|
161
|
+
"#",
|
|
162
|
+
"$",
|
|
163
|
+
"%",
|
|
164
|
+
"*"
|
|
165
|
+
];
|
|
166
|
+
static SYMBOL_SPACE = [
|
|
167
|
+
",",
|
|
168
|
+
" ",
|
|
169
|
+
" ",
|
|
170
|
+
"<",
|
|
171
|
+
">",
|
|
172
|
+
"(",
|
|
173
|
+
")",
|
|
174
|
+
":",
|
|
175
|
+
"[",
|
|
176
|
+
"]",
|
|
177
|
+
"{",
|
|
178
|
+
"}",
|
|
179
|
+
"`",
|
|
180
|
+
"~",
|
|
181
|
+
"|"
|
|
182
|
+
];
|
|
183
|
+
static LABEL_SPACE = [
|
|
184
|
+
"[",
|
|
185
|
+
"{",
|
|
186
|
+
"#",
|
|
187
|
+
"`",
|
|
188
|
+
"~",
|
|
189
|
+
"|",
|
|
190
|
+
":"
|
|
191
|
+
];
|
|
192
|
+
static OBJECT_SPACE = ["<", "["];
|
|
193
|
+
static COP_SPLIT_CHARS = [
|
|
194
|
+
" ",
|
|
195
|
+
" ",
|
|
196
|
+
",",
|
|
197
|
+
"(",
|
|
198
|
+
")",
|
|
199
|
+
"[",
|
|
200
|
+
"]",
|
|
201
|
+
"$",
|
|
202
|
+
"#"
|
|
203
|
+
];
|
|
204
|
+
static WHITESPACE_REGEX = /[ \t]/;
|
|
205
|
+
static COMMA_SPACE_REGEX = /[, \t]/;
|
|
206
|
+
static SYMBOL_SPACE_REGEX = /[, \t<>()\:\[\]{}`~|]/;
|
|
207
|
+
static LABEL_SPACE_REGEX = /[\[{#`~|:]/;
|
|
208
|
+
static OBJECT_SPACE_REGEX = /[<\[]/;
|
|
209
|
+
static ADDRESS_SPACE_REGEX = /[@&^#$%*]/;
|
|
210
|
+
static COP_SPLIT_REGEX = /[ \t,()[\]$#]/;
|
|
211
|
+
static COMMA_SPACE_TRIM_REGEX = /^[, \t]+|[, \t]+$/g;
|
|
212
|
+
/**
|
|
213
|
+
* Gets the size of an object for processing purposes
|
|
214
|
+
* @param obj The object to get the size for
|
|
215
|
+
* @returns Size in bytes
|
|
216
|
+
* @throws Error when unable to determine size
|
|
217
|
+
*/
|
|
218
|
+
static getSize(obj) {
|
|
219
|
+
if (obj === void 0 || obj === null) return 0;
|
|
220
|
+
switch (typeof obj) {
|
|
221
|
+
case "object":
|
|
222
|
+
if (Array.isArray(obj)) return obj.reduce((acc, x) => acc + RomProcessingConstants.getSize(x), 0);
|
|
223
|
+
if ("size" in obj) return obj.size;
|
|
224
|
+
if ("length" in obj) return obj.length;
|
|
225
|
+
if ("_tag" in obj) switch (obj._tag) {
|
|
226
|
+
case "Byte": return 1;
|
|
227
|
+
case "Word": return 2;
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
230
|
+
case "number":
|
|
231
|
+
if (obj <= 255) return 1;
|
|
232
|
+
if (obj <= 65535) return 2;
|
|
233
|
+
if (obj <= 16777215) return 3;
|
|
234
|
+
return 4;
|
|
235
|
+
case "string":
|
|
236
|
+
if (!obj.length) return 0;
|
|
237
|
+
switch (obj[0]) {
|
|
238
|
+
case "@":
|
|
239
|
+
case "%": return 3;
|
|
240
|
+
case "*":
|
|
241
|
+
case "&": return 2;
|
|
242
|
+
case "^": return 1;
|
|
243
|
+
}
|
|
244
|
+
switch (obj) {
|
|
245
|
+
case "Byte": return 1;
|
|
246
|
+
case "Word": return 2;
|
|
247
|
+
case "Offset": return 2;
|
|
248
|
+
case "Address": return 3;
|
|
249
|
+
}
|
|
250
|
+
return obj.length;
|
|
251
|
+
}
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* BlockReader specific constants
|
|
257
|
+
*/
|
|
258
|
+
var BlockReaderConstants = class {
|
|
259
|
+
static REF_SEARCH_MAX_RANGE = 416;
|
|
260
|
+
static BANK_MASK_CHECK = 64;
|
|
261
|
+
static BYTE_DELIMITER_THRESHOLD = 256;
|
|
262
|
+
static BANK_HIGH_MEMORY_1 = 126;
|
|
263
|
+
static BANK_HIGH_MEMORY_2 = 127;
|
|
264
|
+
static POINTER_CHARACTERS = ["&", "@"];
|
|
265
|
+
static WIDE_STRING_TYPE = "WideString";
|
|
266
|
+
static BINARY_TYPE = "Binary";
|
|
267
|
+
static CODE_TYPE = "Code";
|
|
268
|
+
static LOCATION_FORMAT = "loc_{0:X6}";
|
|
269
|
+
static TYPE_NAME_FORMAT = "{0}_{1:X6}";
|
|
270
|
+
static OFFSET_FORMAT = "+{0:X}";
|
|
271
|
+
static MARKER_FORMAT = "+M";
|
|
272
|
+
static NEGATIVE_OFFSET_FORMAT = "-{0:X}";
|
|
273
|
+
static NEGATIVE_MARKER_FORMAT = "-M";
|
|
274
|
+
};
|
|
275
|
+
|
|
134
276
|
//#endregion
|
|
135
277
|
//#region src/types/addressing.ts
|
|
136
278
|
/**
|
|
@@ -144,6 +286,7 @@ let AddressType = /* @__PURE__ */ function(AddressType) {
|
|
|
144
286
|
AddressType["Address"] = "Address";
|
|
145
287
|
AddressType["WBank"] = "WBank";
|
|
146
288
|
AddressType["Relative"] = "Relative";
|
|
289
|
+
AddressType["WRelative"] = "WRelative";
|
|
147
290
|
AddressType["Location"] = "Location";
|
|
148
291
|
return AddressType;
|
|
149
292
|
}({});
|
|
@@ -165,6 +308,11 @@ let MemoryMapMode = /* @__PURE__ */ function(MemoryMapMode) {
|
|
|
165
308
|
MemoryMapMode["ExHi"] = "ExHi";
|
|
166
309
|
return MemoryMapMode;
|
|
167
310
|
}({});
|
|
311
|
+
let CpuMode = /* @__PURE__ */ function(CpuMode) {
|
|
312
|
+
CpuMode["Slow"] = "Slow";
|
|
313
|
+
CpuMode["Fast"] = "Fast";
|
|
314
|
+
return CpuMode;
|
|
315
|
+
}({});
|
|
168
316
|
/**
|
|
169
317
|
* SNES address structure
|
|
170
318
|
* Converted from GaiaLib/Types/Address.cs
|
|
@@ -193,14 +341,19 @@ var Address = class Address {
|
|
|
193
341
|
get isCodeBank() {
|
|
194
342
|
return (this.bank & Address.DATA_BANK_FLAG) === 0;
|
|
195
343
|
}
|
|
196
|
-
|
|
344
|
+
toLocation() {
|
|
197
345
|
if (this.mode === MemoryMapMode.Lo) return (this.bank & 63) << 15 | this.offset & 32767;
|
|
198
346
|
if (this.mode === MemoryMapMode.Hi || this.bank & Address.FAST_BANK_FLAG) return (this.bank & 63) << 16 | this.offset & 65535;
|
|
199
347
|
return this.bank === 62 ? this.offset + 20774912 : this.bank === 63 ? this.offset + 20840448 : ((this.bank & 63) << 16 | this.offset & 65535) + 16777216;
|
|
200
348
|
}
|
|
201
|
-
static
|
|
202
|
-
|
|
203
|
-
if (mode === MemoryMapMode.
|
|
349
|
+
static fromLocation(value, mode, cpuMode) {
|
|
350
|
+
let bankFlag = cpuMode === CpuMode.Fast ? Address.FAST_BANK_FLAG : 0;
|
|
351
|
+
if (mode === MemoryMapMode.Lo) return new Address(value >> 15 & 127 | bankFlag, value & 32767 | 32768, mode);
|
|
352
|
+
if (mode === MemoryMapMode.Hi) {
|
|
353
|
+
if ((value & RomProcessingConstants.PAGE_SIZE) === 0) bankFlag = 192;
|
|
354
|
+
return new Address(value >> 16 & 127 | bankFlag, value & 65535, mode);
|
|
355
|
+
}
|
|
356
|
+
if (value & Address.FAST_BANK_FLAG) return new Address(value >> 16 & 255, value & 65535, mode);
|
|
204
357
|
if (value >= 20774912 && value < 20840448) return new Address(62, value - 20774912, mode);
|
|
205
358
|
if (value >= 20840448 && value < 20905984) return new Address(63, value - 20840448, mode);
|
|
206
359
|
return new Address(value >> 16 & 127, value & 65535, mode);
|
|
@@ -212,8 +365,11 @@ var Address = class Address {
|
|
|
212
365
|
if (value >= 20840448 && value < 20905984) return 63;
|
|
213
366
|
return value >> 16 & 127;
|
|
214
367
|
}
|
|
368
|
+
toInt() {
|
|
369
|
+
return this.bank << 16 | this.offset;
|
|
370
|
+
}
|
|
215
371
|
toString() {
|
|
216
|
-
return
|
|
372
|
+
return this.toInt().toString(16).toUpperCase().padStart(6, "0");
|
|
217
373
|
}
|
|
218
374
|
static typeFromCode(code) {
|
|
219
375
|
switch (code) {
|
|
@@ -346,12 +502,12 @@ let BinType = /* @__PURE__ */ function(BinType) {
|
|
|
346
502
|
BinType["Palette"] = "Palette";
|
|
347
503
|
BinType["Sound"] = "Sound";
|
|
348
504
|
BinType["Music"] = "Music";
|
|
349
|
-
BinType["Unknown"] = "Unknown";
|
|
350
505
|
BinType["Meta17"] = "Meta17";
|
|
351
506
|
BinType["Spritemap"] = "Spritemap";
|
|
352
507
|
BinType["Assembly"] = "Assembly";
|
|
353
508
|
BinType["Patch"] = "Patch";
|
|
354
509
|
BinType["Transform"] = "Transform";
|
|
510
|
+
BinType["Binary"] = "Binary";
|
|
355
511
|
return BinType;
|
|
356
512
|
}({});
|
|
357
513
|
|
|
@@ -649,148 +805,6 @@ var CompressionRegistry = class {
|
|
|
649
805
|
}
|
|
650
806
|
};
|
|
651
807
|
|
|
652
|
-
//#endregion
|
|
653
|
-
//#region src/types/constants.ts
|
|
654
|
-
/**
|
|
655
|
-
* ROM processing constants
|
|
656
|
-
* Converted from GaiaLib/Types/RomProcessingConstants.cs
|
|
657
|
-
*/
|
|
658
|
-
var RomProcessingConstants = class RomProcessingConstants {
|
|
659
|
-
static PAGE_SIZE = 32768;
|
|
660
|
-
static SNES_HEADER_SIZE = 80;
|
|
661
|
-
static DICTIONARIES = ["dictionary_01EBA8", "dictionary_01F54D"];
|
|
662
|
-
static DICT_COMMANDS = [214, 215];
|
|
663
|
-
static END_CHARS = [
|
|
664
|
-
192,
|
|
665
|
-
202,
|
|
666
|
-
209
|
|
667
|
-
];
|
|
668
|
-
static WHITESPACE = [" ", " "];
|
|
669
|
-
static OPERATORS = ["-", "+"];
|
|
670
|
-
static COMMA_SPACE = [
|
|
671
|
-
",",
|
|
672
|
-
" ",
|
|
673
|
-
" "
|
|
674
|
-
];
|
|
675
|
-
static ADDRESS_SPACE = [
|
|
676
|
-
"@",
|
|
677
|
-
"&",
|
|
678
|
-
"^",
|
|
679
|
-
"#",
|
|
680
|
-
"$",
|
|
681
|
-
"%",
|
|
682
|
-
"*"
|
|
683
|
-
];
|
|
684
|
-
static SYMBOL_SPACE = [
|
|
685
|
-
",",
|
|
686
|
-
" ",
|
|
687
|
-
" ",
|
|
688
|
-
"<",
|
|
689
|
-
">",
|
|
690
|
-
"(",
|
|
691
|
-
")",
|
|
692
|
-
":",
|
|
693
|
-
"[",
|
|
694
|
-
"]",
|
|
695
|
-
"{",
|
|
696
|
-
"}",
|
|
697
|
-
"`",
|
|
698
|
-
"~",
|
|
699
|
-
"|"
|
|
700
|
-
];
|
|
701
|
-
static LABEL_SPACE = [
|
|
702
|
-
"[",
|
|
703
|
-
"{",
|
|
704
|
-
"#",
|
|
705
|
-
"`",
|
|
706
|
-
"~",
|
|
707
|
-
"|",
|
|
708
|
-
":"
|
|
709
|
-
];
|
|
710
|
-
static OBJECT_SPACE = ["<", "["];
|
|
711
|
-
static COP_SPLIT_CHARS = [
|
|
712
|
-
" ",
|
|
713
|
-
" ",
|
|
714
|
-
",",
|
|
715
|
-
"(",
|
|
716
|
-
")",
|
|
717
|
-
"[",
|
|
718
|
-
"]",
|
|
719
|
-
"$",
|
|
720
|
-
"#"
|
|
721
|
-
];
|
|
722
|
-
static WHITESPACE_REGEX = /[ \t]/;
|
|
723
|
-
static COMMA_SPACE_REGEX = /[, \t]/;
|
|
724
|
-
static SYMBOL_SPACE_REGEX = /[, \t<>()\:\[\]{}`~|]/;
|
|
725
|
-
static LABEL_SPACE_REGEX = /[\[{#`~|:]/;
|
|
726
|
-
static OBJECT_SPACE_REGEX = /[<\[]/;
|
|
727
|
-
static ADDRESS_SPACE_REGEX = /[@&^#$%*]/;
|
|
728
|
-
static COP_SPLIT_REGEX = /[ \t,()[\]$#]/;
|
|
729
|
-
static COMMA_SPACE_TRIM_REGEX = /^[, \t]+|[, \t]+$/g;
|
|
730
|
-
/**
|
|
731
|
-
* Gets the size of an object for processing purposes
|
|
732
|
-
* @param obj The object to get the size for
|
|
733
|
-
* @returns Size in bytes
|
|
734
|
-
* @throws Error when unable to determine size
|
|
735
|
-
*/
|
|
736
|
-
static getSize(obj) {
|
|
737
|
-
if (obj === void 0 || obj === null) return 0;
|
|
738
|
-
switch (typeof obj) {
|
|
739
|
-
case "object":
|
|
740
|
-
if (Array.isArray(obj)) return obj.reduce((acc, x) => acc + RomProcessingConstants.getSize(x), 0);
|
|
741
|
-
if ("size" in obj) return obj.size;
|
|
742
|
-
if ("length" in obj) return obj.length;
|
|
743
|
-
if ("_tag" in obj) switch (obj._tag) {
|
|
744
|
-
case "Byte": return 1;
|
|
745
|
-
case "Word": return 2;
|
|
746
|
-
}
|
|
747
|
-
break;
|
|
748
|
-
case "number":
|
|
749
|
-
if (obj <= 255) return 1;
|
|
750
|
-
if (obj <= 65535) return 2;
|
|
751
|
-
if (obj <= 16777215) return 3;
|
|
752
|
-
return 4;
|
|
753
|
-
case "string":
|
|
754
|
-
if (!obj.length) return 0;
|
|
755
|
-
switch (obj[0]) {
|
|
756
|
-
case "@":
|
|
757
|
-
case "%": return 3;
|
|
758
|
-
case "*":
|
|
759
|
-
case "&": return 2;
|
|
760
|
-
case "^": return 1;
|
|
761
|
-
}
|
|
762
|
-
switch (obj) {
|
|
763
|
-
case "Byte": return 1;
|
|
764
|
-
case "Word": return 2;
|
|
765
|
-
case "Offset": return 2;
|
|
766
|
-
case "Address": return 3;
|
|
767
|
-
}
|
|
768
|
-
return obj.length;
|
|
769
|
-
}
|
|
770
|
-
return 0;
|
|
771
|
-
}
|
|
772
|
-
};
|
|
773
|
-
/**
|
|
774
|
-
* BlockReader specific constants
|
|
775
|
-
*/
|
|
776
|
-
var BlockReaderConstants = class {
|
|
777
|
-
static REF_SEARCH_MAX_RANGE = 416;
|
|
778
|
-
static BANK_MASK_CHECK = 64;
|
|
779
|
-
static BYTE_DELIMITER_THRESHOLD = 256;
|
|
780
|
-
static BANK_HIGH_MEMORY_1 = 126;
|
|
781
|
-
static BANK_HIGH_MEMORY_2 = 127;
|
|
782
|
-
static POINTER_CHARACTERS = ["&", "@"];
|
|
783
|
-
static WIDE_STRING_TYPE = "WideString";
|
|
784
|
-
static BINARY_TYPE = "Binary";
|
|
785
|
-
static CODE_TYPE = "Code";
|
|
786
|
-
static LOCATION_FORMAT = "loc_{0:X6}";
|
|
787
|
-
static TYPE_NAME_FORMAT = "{0}_{1:X6}";
|
|
788
|
-
static OFFSET_FORMAT = "+{0:X}";
|
|
789
|
-
static MARKER_FORMAT = "+M";
|
|
790
|
-
static NEGATIVE_OFFSET_FORMAT = "-{0:X}";
|
|
791
|
-
static NEGATIVE_MARKER_FORMAT = "-M";
|
|
792
|
-
};
|
|
793
|
-
|
|
794
808
|
//#endregion
|
|
795
809
|
//#region src/types/files.ts
|
|
796
810
|
/**
|
|
@@ -850,11 +864,11 @@ function createChunkFileFromDbFile(rom, compression, dbFile, fileType) {
|
|
|
850
864
|
enrichWithRawDataFromDbFile(rom, chunkFile, compression, dbFile, fileType);
|
|
851
865
|
return chunkFile;
|
|
852
866
|
}
|
|
853
|
-
function createChunkFileFromDbBlock(block, fileType) {
|
|
867
|
+
function createChunkFileFromDbBlock(block, fileType, memoryMode) {
|
|
854
868
|
const chunkFile = new ChunkFile(block.name, 0, 0, fileType);
|
|
855
869
|
chunkFile.group = block.group;
|
|
856
870
|
chunkFile.scene = block.scene;
|
|
857
|
-
enrichWithPartsFromDbBlock(chunkFile, block);
|
|
871
|
+
enrichWithPartsFromDbBlock(chunkFile, block, memoryMode);
|
|
858
872
|
return chunkFile;
|
|
859
873
|
}
|
|
860
874
|
function combineHeader(data, position, length, header, type) {
|
|
@@ -899,12 +913,12 @@ function enrichWithRawDataFromDbFile(rom, chunkFile, compression, dbFile, fileTy
|
|
|
899
913
|
/**
|
|
900
914
|
* Enriches ChunkFile with AsmBlock parts from DbBlock
|
|
901
915
|
*/
|
|
902
|
-
function enrichWithPartsFromDbBlock(chunkFile, block) {
|
|
916
|
+
function enrichWithPartsFromDbBlock(chunkFile, block, memoryMode) {
|
|
903
917
|
chunkFile.parts = [];
|
|
904
918
|
chunkFile.size = 0;
|
|
905
919
|
if (!block.parts?.length) throw new Error(`Block ${block.name} has no parts`);
|
|
906
920
|
chunkFile.location = block.parts[0].start;
|
|
907
|
-
chunkFile.bank = block.movable ? void 0 : chunkFile.location >> 16;
|
|
921
|
+
chunkFile.bank = block.movable ? void 0 : memoryMode === MemoryMapMode.Lo ? chunkFile.location >> 15 : chunkFile.location >> 16;
|
|
908
922
|
chunkFile.transforms = block.transforms;
|
|
909
923
|
chunkFile.postProcess = block.postProcess;
|
|
910
924
|
for (const part of block.parts) {
|
|
@@ -936,8 +950,12 @@ var ChunkFileUtils = class {
|
|
|
936
950
|
*/
|
|
937
951
|
static calculateSize(chunkFile) {
|
|
938
952
|
if (!chunkFile.parts) {
|
|
939
|
-
|
|
940
|
-
|
|
953
|
+
let size$1 = chunkFile.rawData?.length ?? chunkFile.size;
|
|
954
|
+
if (chunkFile.type.header === -2 || chunkFile.compressed === false) {
|
|
955
|
+
size$1 += 2;
|
|
956
|
+
chunkFile.size = size$1;
|
|
957
|
+
}
|
|
958
|
+
return size$1;
|
|
941
959
|
}
|
|
942
960
|
let size = 0;
|
|
943
961
|
for (let x = 0; x < chunkFile.parts.length; x++) {
|
|
@@ -1367,7 +1385,7 @@ var CopCommandProcessor = class {
|
|
|
1367
1385
|
if (bank === null && offset === 0) return new Word(offset);
|
|
1368
1386
|
const addr = new Address(bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode), offset, this._blockReader._root.config.memoryMode);
|
|
1369
1387
|
if (addr.isROM) {
|
|
1370
|
-
const location = addr.
|
|
1388
|
+
const location = addr.toLocation();
|
|
1371
1389
|
if (partStr !== "Address" && isPtr && !this._blockReader._root.rewrites[location]) this._blockReader.noteType(location, otherStr, true);
|
|
1372
1390
|
if (type === AddressType.Unknown) type = this.tryParseAddressType(partStr) ?? AddressType.Unknown;
|
|
1373
1391
|
return new LocationWrapper(location, type);
|
|
@@ -1501,7 +1519,7 @@ var AddressingModeHandler = class {
|
|
|
1501
1519
|
const refLoc = this._dataReader.readUShort();
|
|
1502
1520
|
const address = new Address(this._dataReader.readByte(), refLoc, reg.mode);
|
|
1503
1521
|
if (address.isROM) {
|
|
1504
|
-
const wrapper = new LocationWrapper(address.
|
|
1522
|
+
const wrapper = new LocationWrapper(address.toLocation(), AddressType.Address);
|
|
1505
1523
|
if (this.isJumpInstruction(mnemonic)) this._blockReader.noteType(wrapper.location, "Code", false, reg);
|
|
1506
1524
|
operands.push(wrapper);
|
|
1507
1525
|
} else operands.push(address);
|
|
@@ -1517,7 +1535,7 @@ var AddressingModeHandler = class {
|
|
|
1517
1535
|
handlePCRelativeMode(operands, nextAddress, reg, isLong) {
|
|
1518
1536
|
const relative = isLong ? nextAddress + this._dataReader.readShort() : nextAddress + this._dataReader.readSByte();
|
|
1519
1537
|
this._blockReader.updateRegisterState(relative, reg);
|
|
1520
|
-
operands.push(new LocationWrapper(relative, AddressType.Relative));
|
|
1538
|
+
operands.push(new LocationWrapper(relative, isLong ? AddressType.WRelative : AddressType.Relative));
|
|
1521
1539
|
}
|
|
1522
1540
|
handleStackRelativeMode(operands) {
|
|
1523
1541
|
operands.push(new Byte(this._dataReader.readByte()));
|
|
@@ -1542,7 +1560,7 @@ var AddressingModeHandler = class {
|
|
|
1542
1560
|
const isJump = isPush || isIndexedIndirect || this.isJumpInstruction(mnemonic);
|
|
1543
1561
|
const addr = new Address(xBank1 ?? (isJump ? Address.resolveBank(this._dataReader.position, registers.mode) : dataBank) ?? 129, refLoc, registers.mode);
|
|
1544
1562
|
if (addr.isROM) {
|
|
1545
|
-
const wrapper = new LocationWrapper(addr.
|
|
1563
|
+
const wrapper = new LocationWrapper(addr.toLocation(), AddressType.Offset);
|
|
1546
1564
|
if (isJump) {
|
|
1547
1565
|
const type = isIndexedIndirect ? "&Code" : "Code";
|
|
1548
1566
|
const name = this._blockReader.noteType(wrapper.location, type, isPush, registers);
|
|
@@ -1607,16 +1625,7 @@ var TransformProcessor = class TransformProcessor {
|
|
|
1607
1625
|
}
|
|
1608
1626
|
applyDefaultTransform(operandIndex, operands, bank) {
|
|
1609
1627
|
const opnd = operands[operandIndex];
|
|
1610
|
-
|
|
1611
|
-
const loc = adrs.toInt();
|
|
1612
|
-
const nameResult = this._referenceManager.tryGetName(loc);
|
|
1613
|
-
let referenceName;
|
|
1614
|
-
if (!nameResult.found) {
|
|
1615
|
-
referenceName = `loc_${adrs.toString()}`;
|
|
1616
|
-
this._referenceManager.tryAddName(loc, referenceName);
|
|
1617
|
-
} else referenceName = nameResult.referenceName;
|
|
1618
|
-
this._blockReader.resolveInclude(loc, false);
|
|
1619
|
-
operands[operandIndex] = `&${referenceName}`;
|
|
1628
|
+
operands[operandIndex] = new LocationWrapper(new Address(bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode), opnd && "value" in opnd ? opnd["value"] : opnd, this._blockReader._root.config.memoryMode).toLocation(), AddressType.Offset);
|
|
1620
1629
|
}
|
|
1621
1630
|
cleanTransformName(transform) {
|
|
1622
1631
|
let name = transform;
|
|
@@ -1790,7 +1799,6 @@ var DbStringDictionary = class {
|
|
|
1790
1799
|
range;
|
|
1791
1800
|
command;
|
|
1792
1801
|
name;
|
|
1793
|
-
suffix;
|
|
1794
1802
|
entries;
|
|
1795
1803
|
constructor(data) {
|
|
1796
1804
|
this.base = data.base ?? void 0;
|
|
@@ -1798,7 +1806,6 @@ var DbStringDictionary = class {
|
|
|
1798
1806
|
this.command = data.command ?? void 0;
|
|
1799
1807
|
this.name = data.name ?? "";
|
|
1800
1808
|
this.entries = data.entries ?? void 0;
|
|
1801
|
-
this.suffix = data.suffix ?? "";
|
|
1802
1809
|
if (this.base === void 0 && this.command === void 0) throw new Error("Base or command is required");
|
|
1803
1810
|
if (!this.name) throw new Error("Name is required");
|
|
1804
1811
|
if (!this.entries) throw new Error("Entries is required");
|
|
@@ -2624,13 +2631,13 @@ var QuintetLZ = class QuintetLZ {
|
|
|
2624
2631
|
* @param srcData Source data to compress
|
|
2625
2632
|
* @returns Compressed data
|
|
2626
2633
|
*/
|
|
2627
|
-
compact(srcData) {
|
|
2634
|
+
compact(srcData, srcPosition, srcLen) {
|
|
2628
2635
|
const dictionary = new Uint8Array(QuintetLZ.DICTIONARY_SIZE);
|
|
2629
2636
|
dictionary.fill(QuintetLZ.DICTIONARY_INIT);
|
|
2630
2637
|
let offset = QuintetLZ.DICTIONARY_OFFSET;
|
|
2631
|
-
let srcIx = 0;
|
|
2638
|
+
let srcIx = srcPosition ?? 0;
|
|
2632
2639
|
let dstIx = 0;
|
|
2633
|
-
|
|
2640
|
+
if (!srcLen) srcLen = srcData.length - srcIx;
|
|
2634
2641
|
const outputBuffer = new Uint8Array(srcLen * 2);
|
|
2635
2642
|
outputBuffer[dstIx++] = srcLen & 255;
|
|
2636
2643
|
outputBuffer[dstIx++] = srcLen >> 8 & 255;
|
|
@@ -2897,7 +2904,7 @@ var BlockWriter = class {
|
|
|
2897
2904
|
if (typeof obj === "number") return ObjectType.Number;
|
|
2898
2905
|
return ObjectType.String;
|
|
2899
2906
|
}
|
|
2900
|
-
writeObject(obj, depth, isBranch = false) {
|
|
2907
|
+
writeObject(obj, depth, isBranch = false, isArray = false) {
|
|
2901
2908
|
const lines = [];
|
|
2902
2909
|
const objType = this.getObjectType(obj);
|
|
2903
2910
|
let objLines;
|
|
@@ -2915,7 +2922,7 @@ var BlockWriter = class {
|
|
|
2915
2922
|
objLines = [this._blockReader.resolveName(obj.location, obj.type, isBranch)];
|
|
2916
2923
|
break;
|
|
2917
2924
|
case ObjectType.Address:
|
|
2918
|
-
objLines = [`$${obj.toString()}`];
|
|
2925
|
+
objLines = isArray ? [`$#${obj.offset.toString(16).toUpperCase().padStart(4, "0")}`] : [`$${obj.toString()}`];
|
|
2919
2926
|
break;
|
|
2920
2927
|
case ObjectType.ByteArray:
|
|
2921
2928
|
objLines = [`#${Array.from(obj).map((b) => b.toString(16).toUpperCase().padStart(2, "0")).join("")}`];
|
|
@@ -3028,13 +3035,13 @@ var BlockWriter = class {
|
|
|
3028
3035
|
const hexStr = str.substring(ix + 1, ix + 7);
|
|
3029
3036
|
const rawAddr = parseInt(hexStr, 16);
|
|
3030
3037
|
const adrs = new Address(rawAddr >> 16 & 255, rawAddr & 65535, this._blockReader._root.config.memoryMode);
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
ix = str.indexOf(char
|
|
3038
|
+
const addressType = char === "^" ? AddressType.Offset : AddressType.Address;
|
|
3039
|
+
let name = "";
|
|
3040
|
+
if (adrs.isROM) name = this._blockReader.resolveName(adrs.toLocation(), addressType, false);
|
|
3041
|
+
else if (addressType === AddressType.Offset) name = adrs.offset.toString(16).toUpperCase().padStart(4, "0");
|
|
3042
|
+
else name = adrs.toString();
|
|
3043
|
+
str = str.replace(str.substring(ix, ix + 7), name);
|
|
3044
|
+
ix = str.indexOf(char);
|
|
3038
3045
|
}
|
|
3039
3046
|
}
|
|
3040
3047
|
const refChar = stringObj.type.delimiter;
|
|
@@ -3085,7 +3092,7 @@ var BlockWriter = class {
|
|
|
3085
3092
|
lines.push("[");
|
|
3086
3093
|
this._isInline = false;
|
|
3087
3094
|
for (let i = 0; i < arr.length; i++) {
|
|
3088
|
-
const objLines = this.writeObject(arr[i], depth + 1);
|
|
3095
|
+
const objLines = this.writeObject(arr[i], depth + 1, false, true);
|
|
3089
3096
|
for (const line of objLines) lines.push(indent + " " + line);
|
|
3090
3097
|
lines[lines.length - 1] += ` ;${i.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
3091
3098
|
}
|
|
@@ -3297,19 +3304,19 @@ var TypeParser = class {
|
|
|
3297
3304
|
}
|
|
3298
3305
|
const stringType = this._stringTypes[fixedTypeName];
|
|
3299
3306
|
if (stringType) return this._stringReader.parseString(stringType, fixedSize);
|
|
3300
|
-
const mType = this.tryParseMemberType(
|
|
3307
|
+
const mType = this.tryParseMemberType(fixedTypeName);
|
|
3301
3308
|
if (mType !== null) switch (mType) {
|
|
3302
3309
|
case MemberType.Byte: return new Byte(this._romDataReader.readByte());
|
|
3303
3310
|
case MemberType.Word: return new Word(this.parseWordSafe());
|
|
3304
3311
|
case MemberType.Offset: return this.parseLocation(this._romDataReader.readUShort(), bank, null, AddressType.Offset);
|
|
3305
3312
|
case MemberType.Address: return this.parseLocation(this._romDataReader.readUShort(), this._romDataReader.readByte(), null, AddressType.Address);
|
|
3306
3313
|
case MemberType.Location: return this.parseLocation(this._romDataReader.readUShort(), this._romDataReader.readByte(), null, AddressType.Location);
|
|
3307
|
-
case MemberType.Binary: return this.parseBinary();
|
|
3314
|
+
case MemberType.Binary: return this.parseBinary(fixedSize);
|
|
3308
3315
|
case MemberType.Code: return this.parseCode(reg);
|
|
3309
3316
|
default: throw new Error("Invalid member type");
|
|
3310
3317
|
}
|
|
3311
|
-
const parentType = this._blockReader._root.structs[
|
|
3312
|
-
if (!parentType) throw new Error(`Unknown type: ${
|
|
3318
|
+
const parentType = this._blockReader._root.structs[fixedTypeName];
|
|
3319
|
+
if (!parentType) throw new Error(`Unknown type: ${fixedTypeName}`);
|
|
3313
3320
|
const delimiter = parentType.delimiter;
|
|
3314
3321
|
const discOffset = parentType.discriminator;
|
|
3315
3322
|
const objects = [];
|
|
@@ -3321,7 +3328,7 @@ var TypeParser = class {
|
|
|
3321
3328
|
const discPosition = this._romDataReader.position + discOffset;
|
|
3322
3329
|
const desc = this._romDataReader.romData[discPosition];
|
|
3323
3330
|
if (discOffset === 0) this._romDataReader.position++;
|
|
3324
|
-
targetType = Object.values(this._blockReader._root.structs).find((x) => x.parent ===
|
|
3331
|
+
targetType = Object.values(this._blockReader._root.structs).find((x) => x.parent === fixedTypeName && x.discriminator === desc) || parentType;
|
|
3325
3332
|
}
|
|
3326
3333
|
const types = targetType.types;
|
|
3327
3334
|
if (types && types.length > 0) {
|
|
@@ -3354,12 +3361,13 @@ var TypeParser = class {
|
|
|
3354
3361
|
parseWordSafe() {
|
|
3355
3362
|
return this._referenceManager.containsStruct(this._romDataReader.position + 1) ? this._romDataReader.readByte() : this._romDataReader.readUShort();
|
|
3356
3363
|
}
|
|
3357
|
-
parseBinary() {
|
|
3364
|
+
parseBinary(size) {
|
|
3358
3365
|
const startPosition = this._romDataReader.position;
|
|
3359
|
-
|
|
3366
|
+
let len = 0;
|
|
3367
|
+
do {
|
|
3360
3368
|
this._romDataReader.position++;
|
|
3361
|
-
|
|
3362
|
-
|
|
3369
|
+
len++;
|
|
3370
|
+
} while (len !== size && this._blockReader.partCanContinue());
|
|
3363
3371
|
const outBuffer = new Uint8Array(len);
|
|
3364
3372
|
for (let i = 0; i < len; i++) outBuffer[i] = this._romDataReader.romData[startPosition + i];
|
|
3365
3373
|
return outBuffer;
|
|
@@ -3372,7 +3380,7 @@ var TypeParser = class {
|
|
|
3372
3380
|
else {
|
|
3373
3381
|
adrs = new Address(bank ?? Address.resolveBank(this._romDataReader.position, this._blockReader._root.config.memoryMode), offset, this._blockReader._root.config.memoryMode);
|
|
3374
3382
|
if (!adrs.isROM) return adrs;
|
|
3375
|
-
loc = adrs.
|
|
3383
|
+
loc = adrs.toLocation();
|
|
3376
3384
|
}
|
|
3377
3385
|
if (typeName && !this._blockReader._root.rewrites[loc]) {
|
|
3378
3386
|
this._referenceManager.tryAddStruct(loc, typeName);
|
|
@@ -3617,26 +3625,40 @@ var BlockReader = class {
|
|
|
3617
3625
|
*/
|
|
3618
3626
|
createChunkFilesFromSfx() {
|
|
3619
3627
|
let pos = this._root.config.sfxLocation;
|
|
3628
|
+
let offset = 0;
|
|
3620
3629
|
const count = this._root.config.sfxCount;
|
|
3621
3630
|
const romData = this._romDataReader.romData;
|
|
3622
3631
|
const fileType = Object.values(this._root.fileTypes).find((x) => x.type === BinType.Sound);
|
|
3623
|
-
const
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3632
|
+
const getByte = this._root.config.sfxType === "Striped" ? () => {
|
|
3633
|
+
const byte = romData[pos + offset++];
|
|
3634
|
+
if (offset & RomProcessingConstants.PAGE_SIZE) offset += RomProcessingConstants.PAGE_SIZE;
|
|
3635
|
+
return byte;
|
|
3636
|
+
} : () => romData[pos + offset++];
|
|
3637
|
+
const getSize = () => getByte() | getByte() << 8;
|
|
3638
|
+
const getBytes = this._root.config.sfxType === "Striped" ? (size) => {
|
|
3639
|
+
let end = offset + size;
|
|
3629
3640
|
let data;
|
|
3630
3641
|
if (end & RomProcessingConstants.PAGE_SIZE) {
|
|
3631
3642
|
const endLen = end & 32767;
|
|
3632
|
-
|
|
3633
|
-
data = romData.slice(pos, pos +
|
|
3634
|
-
|
|
3635
|
-
end =
|
|
3636
|
-
const data2 = romData.slice(pos, end);
|
|
3643
|
+
size -= endLen;
|
|
3644
|
+
data = romData.slice(pos + offset, pos + offset + size);
|
|
3645
|
+
offset += size + RomProcessingConstants.PAGE_SIZE;
|
|
3646
|
+
end = offset + endLen;
|
|
3647
|
+
const data2 = romData.slice(pos + offset, pos + end);
|
|
3637
3648
|
data = new Uint8Array([...data, ...data2]);
|
|
3638
|
-
} else data = romData.slice(pos, end);
|
|
3639
|
-
|
|
3649
|
+
} else data = romData.slice(pos + offset, pos + end);
|
|
3650
|
+
offset = end;
|
|
3651
|
+
return data;
|
|
3652
|
+
} : (size) => {
|
|
3653
|
+
const end = offset + size;
|
|
3654
|
+
const data = romData.slice(pos + offset, pos + end);
|
|
3655
|
+
offset = end;
|
|
3656
|
+
return data;
|
|
3657
|
+
};
|
|
3658
|
+
for (let i = 0; i < count; i++) {
|
|
3659
|
+
const size = getSize();
|
|
3660
|
+
const startPos = pos + offset;
|
|
3661
|
+
const data = getBytes(size);
|
|
3640
3662
|
const chunk = new ChunkFile(`sfx${i.toString(16).toUpperCase().padStart(2, "0")}`, size, startPos, fileType);
|
|
3641
3663
|
chunk.rawData = data;
|
|
3642
3664
|
chunk.group = "sfx";
|
|
@@ -3657,7 +3679,7 @@ var BlockReader = class {
|
|
|
3657
3679
|
*/
|
|
3658
3680
|
createChunkFilesFromDbBlocks() {
|
|
3659
3681
|
for (const block of this._root.blocks) {
|
|
3660
|
-
const chunkFile = createChunkFileFromDbBlock(block, Object.values(this._root.fileTypes).find((x) => x.isBlock));
|
|
3682
|
+
const chunkFile = createChunkFileFromDbBlock(block, Object.values(this._root.fileTypes).find((x) => x.isBlock), this._root.config.memoryMode);
|
|
3661
3683
|
this._enrichedChunks.push(chunkFile);
|
|
3662
3684
|
}
|
|
3663
3685
|
}
|
|
@@ -3763,8 +3785,18 @@ var RomLayout = class RomLayout {
|
|
|
3763
3785
|
bestDepth = 0;
|
|
3764
3786
|
bestOffset = 0;
|
|
3765
3787
|
bestRemain = 0;
|
|
3766
|
-
|
|
3767
|
-
|
|
3788
|
+
root;
|
|
3789
|
+
config;
|
|
3790
|
+
sfxPackType;
|
|
3791
|
+
sfxFiles = [];
|
|
3792
|
+
constructor(files, root) {
|
|
3793
|
+
this.root = root;
|
|
3794
|
+
this.config = root.config;
|
|
3795
|
+
this.sfxPackType = root.config.sfxPack ?? root.config.sfxType;
|
|
3796
|
+
this.sfxFiles = this.sfxPackType !== "Individual" ? files.filter((x) => x.type.type === "Sound").sort((a, b) => {
|
|
3797
|
+
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);
|
|
3798
|
+
}) : [];
|
|
3799
|
+
this.unmatchedFiles = files.filter((x) => (x.size || 0) > 0).filter((x) => this.sfxPackType === "Individual" || x.type.type !== "Sound").sort((a, b) => {
|
|
3768
3800
|
const aAsm = a.parts ? 0 : 1;
|
|
3769
3801
|
const bAsm = b.parts ? 0 : 1;
|
|
3770
3802
|
if (aAsm !== bAsm) return aAsm - bAsm;
|
|
@@ -3774,16 +3806,67 @@ var RomLayout = class RomLayout {
|
|
|
3774
3806
|
});
|
|
3775
3807
|
}
|
|
3776
3808
|
organize() {
|
|
3777
|
-
|
|
3809
|
+
let stripeSfx = false;
|
|
3810
|
+
let page;
|
|
3811
|
+
const maxPages = this.config.memoryMode === MemoryMapMode.Hi ? 128 : this.config.memoryMode === MemoryMapMode.ExHi ? 256 : 64;
|
|
3812
|
+
for (page = 0; page < maxPages; page++) {
|
|
3778
3813
|
if (this.unmatchedFiles.length === 0) break;
|
|
3814
|
+
let start = page << 15;
|
|
3779
3815
|
let remain = RomProcessingConstants.PAGE_SIZE;
|
|
3780
|
-
if (
|
|
3781
|
-
|
|
3782
|
-
|
|
3816
|
+
if (start <= this.config.sfxLocation && start + remain > this.config.sfxLocation) {
|
|
3817
|
+
this.config.sfxLocation - start;
|
|
3818
|
+
if (this.sfxPackType === "Sequential") {
|
|
3819
|
+
let offset = 0;
|
|
3820
|
+
for (const file of this.sfxFiles) {
|
|
3821
|
+
file.location = start + offset;
|
|
3822
|
+
console.log(` ${file.location.toString(16).toUpperCase().padStart(6, "0")}: ${file.name}`);
|
|
3823
|
+
offset += file.size;
|
|
3824
|
+
if (offset & RomProcessingConstants.PAGE_SIZE) {
|
|
3825
|
+
offset &= 32767;
|
|
3826
|
+
console.log(`Page ${start.toString(16).toUpperCase().padStart(6, "0")} matched with SFX files 0 remaining`);
|
|
3827
|
+
start += RomProcessingConstants.PAGE_SIZE;
|
|
3828
|
+
page++;
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
console.log(`Page ${start.toString(16).toUpperCase().padStart(6, "0")} matched with SFX files ${remain} remaining`);
|
|
3832
|
+
start += offset;
|
|
3833
|
+
remain = RomProcessingConstants.PAGE_SIZE - offset;
|
|
3834
|
+
} else if (this.sfxPackType === "Striped") stripeSfx = true;
|
|
3835
|
+
}
|
|
3836
|
+
if (page === 0 && this.config.memoryMode === MemoryMapMode.Lo || page === 1 && this.config.memoryMode === MemoryMapMode.Hi) remain -= RomProcessingConstants.SNES_HEADER_SIZE;
|
|
3837
|
+
if (stripeSfx) {
|
|
3838
|
+
let offset = 0;
|
|
3839
|
+
while (remain > 0 && this.sfxFiles.length) {
|
|
3840
|
+
const file = this.sfxFiles.shift();
|
|
3841
|
+
file.location = start + offset;
|
|
3842
|
+
console.log(` ${file.location.toString(16).toUpperCase().padStart(6, "0")}: ${file.name}`);
|
|
3843
|
+
offset += file.size;
|
|
3844
|
+
if (offset & RomProcessingConstants.PAGE_SIZE) {
|
|
3845
|
+
offset &= 32767;
|
|
3846
|
+
console.log(`Page ${start.toString(16).toUpperCase().padStart(6, "0")} matched with SFX files 0 remaining`);
|
|
3847
|
+
start += RomProcessingConstants.PAGE_SIZE;
|
|
3848
|
+
page++;
|
|
3849
|
+
if (offset) {
|
|
3850
|
+
const newFile = new ChunkFile(file.name + "_2", file.size, file.location, Object.values(this.root.fileTypes).find((x) => x.type === BinType.Binary));
|
|
3851
|
+
const end = file.rawData.length - offset;
|
|
3852
|
+
newFile.rawData = file.rawData.slice(end);
|
|
3853
|
+
newFile.size = newFile.rawData.length;
|
|
3854
|
+
this.sfxFiles.unshift(newFile);
|
|
3855
|
+
file.rawData = file.rawData.slice(0, end);
|
|
3856
|
+
file.size -= offset;
|
|
3857
|
+
}
|
|
3858
|
+
remain = 0;
|
|
3859
|
+
break;
|
|
3860
|
+
} else remain -= file.size;
|
|
3861
|
+
}
|
|
3862
|
+
start += offset;
|
|
3863
|
+
if (!this.sfxFiles.length) stripeSfx = false;
|
|
3864
|
+
}
|
|
3865
|
+
this.currentUpper = this.config.memoryMode === MemoryMapMode.Lo || (page & 1) !== 0;
|
|
3866
|
+
this.currentBank = this.config.memoryMode === MemoryMapMode.Lo ? page : page >> 1;
|
|
3783
3867
|
this.bestDepth = 0;
|
|
3784
3868
|
this.bestRemain = remain;
|
|
3785
3869
|
this.bestOffset = 0;
|
|
3786
|
-
const start = page << 15;
|
|
3787
3870
|
this.testDepth(0, 0, remain, this.currentUpper);
|
|
3788
3871
|
if (this.currentUpper) {
|
|
3789
3872
|
this.bestOffset = this.bestDepth;
|
|
@@ -3794,7 +3877,7 @@ var RomLayout = class RomLayout {
|
|
|
3794
3877
|
const file = this.unmatchedFiles[this.bestResult[i++]];
|
|
3795
3878
|
file.location = position;
|
|
3796
3879
|
console.log(` ${position.toString(16).toUpperCase().padStart(6, "0")}: ${file.name}`);
|
|
3797
|
-
position += file.size
|
|
3880
|
+
position += file.size;
|
|
3798
3881
|
}
|
|
3799
3882
|
console.log(`Page ${start.toString(16).toUpperCase().padStart(6, "0")} matched with ${this.bestDepth} files ${this.bestRemain} remaining`);
|
|
3800
3883
|
this.commitPage();
|
|
@@ -3803,6 +3886,7 @@ var RomLayout = class RomLayout {
|
|
|
3803
3886
|
const names = this.unmatchedFiles.map((x) => x.name).join("\r\n");
|
|
3804
3887
|
throw new Error(`Unable to match ${this.unmatchedFiles.length} files\r\n${names}`);
|
|
3805
3888
|
}
|
|
3889
|
+
return page;
|
|
3806
3890
|
}
|
|
3807
3891
|
testDepth(startIndex, depth, remain, asmMode) {
|
|
3808
3892
|
for (let fileIndex = startIndex; fileIndex < this.unmatchedFiles.length; fileIndex++) {
|
|
@@ -3868,7 +3952,16 @@ var RomProcessor = class RomProcessor {
|
|
|
3868
3952
|
const asmFiles = [];
|
|
3869
3953
|
for (const file of allFiles) {
|
|
3870
3954
|
if (file.type.type === "Patch") patches.push(file);
|
|
3871
|
-
else if (file.type.type !== "Assembly")
|
|
3955
|
+
else if (file.type.type !== "Assembly") {
|
|
3956
|
+
if (file.compressed === true) if (this.writer.root.config.uncompress) file.compressed = false;
|
|
3957
|
+
else {
|
|
3958
|
+
let newData = this.writer.root.compression.compact(file.rawData, file.type.header);
|
|
3959
|
+
if (file.type.header) newData = new Uint8Array([...file.rawData.slice(0, file.type.header), ...newData]);
|
|
3960
|
+
file.rawData = newData;
|
|
3961
|
+
file.size = newData.length;
|
|
3962
|
+
}
|
|
3963
|
+
continue;
|
|
3964
|
+
}
|
|
3872
3965
|
asmFiles.push(file);
|
|
3873
3966
|
if (!file.parts) {
|
|
3874
3967
|
const { blocks, includes, reqBank } = new Assembler(this.writer.root, file.textData).parseAssembly();
|
|
@@ -3879,7 +3972,7 @@ var RomProcessor = class RomProcessor {
|
|
|
3879
3972
|
}
|
|
3880
3973
|
RomProcessor.applyPatches(asmFiles, patches);
|
|
3881
3974
|
for (const file of allFiles) ChunkFileUtils.calculateSize(file);
|
|
3882
|
-
new RomLayout(allFiles).organize();
|
|
3975
|
+
const pages = new RomLayout(allFiles, this.writer.root).organize();
|
|
3883
3976
|
for (const file of asmFiles) ChunkFileUtils.rebase(file);
|
|
3884
3977
|
for (const f of asmFiles) {
|
|
3885
3978
|
const includeBlocks = asmFiles.filter((x) => f.includes?.has(x.name.toUpperCase())).flatMap((x) => x.parts).filter((b) => !!b.label);
|
|
@@ -3889,6 +3982,7 @@ var RomProcessor = class RomProcessor {
|
|
|
3889
3982
|
}
|
|
3890
3983
|
const blockLookup = /* @__PURE__ */ new Map();
|
|
3891
3984
|
for (const f of allFiles) blockLookup.set(f.name.toUpperCase(), f.location);
|
|
3985
|
+
this.writer.allocate(pages);
|
|
3892
3986
|
for (const file of allFiles) await this.writer.writeFile(file, blockLookup);
|
|
3893
3987
|
}
|
|
3894
3988
|
static applyPatches(asmFiles, patches) {
|
|
@@ -3934,6 +4028,7 @@ var RomProcessor = class RomProcessor {
|
|
|
3934
4028
|
var RomWriter = class {
|
|
3935
4029
|
bpsPath;
|
|
3936
4030
|
outBuffer;
|
|
4031
|
+
romSize;
|
|
3937
4032
|
cartName;
|
|
3938
4033
|
makerCode;
|
|
3939
4034
|
root;
|
|
@@ -3941,7 +4036,6 @@ var RomWriter = class {
|
|
|
3941
4036
|
this.cartName = cartName;
|
|
3942
4037
|
this.makerCode = makerCode;
|
|
3943
4038
|
this.root = root;
|
|
3944
|
-
this.outBuffer = new Uint8Array(4194304);
|
|
3945
4039
|
}
|
|
3946
4040
|
async repack(files) {
|
|
3947
4041
|
await new RomProcessor(this).repack(files);
|
|
@@ -3950,35 +4044,47 @@ var RomWriter = class {
|
|
|
3950
4044
|
this.writeChecksum();
|
|
3951
4045
|
return this.outBuffer;
|
|
3952
4046
|
}
|
|
4047
|
+
allocate(pages) {
|
|
4048
|
+
const size = pages * RomProcessingConstants.PAGE_SIZE;
|
|
4049
|
+
let bits = 0;
|
|
4050
|
+
let target = 1024;
|
|
4051
|
+
while (target < size) {
|
|
4052
|
+
target <<= 1;
|
|
4053
|
+
bits++;
|
|
4054
|
+
}
|
|
4055
|
+
this.romSize = bits;
|
|
4056
|
+
this.outBuffer = new Uint8Array(target);
|
|
4057
|
+
}
|
|
3953
4058
|
writeHeader() {
|
|
3954
4059
|
const buf = this.outBuffer;
|
|
3955
|
-
let pos = 65456;
|
|
4060
|
+
let pos = this.root.config.memoryMode === MemoryMapMode.Lo ? 32688 : 65456;
|
|
3956
4061
|
this.writeAscii(this.makerCode.padEnd(6, " "), pos);
|
|
3957
4062
|
pos += 6;
|
|
3958
4063
|
for (let i = 0; i < 10; i++) buf[pos++] = 0;
|
|
3959
4064
|
this.writeAscii(this.cartName.toUpperCase().padEnd(21, " "), pos);
|
|
3960
4065
|
pos += 21;
|
|
3961
|
-
buf[pos++] =
|
|
3962
|
-
buf[pos++] =
|
|
3963
|
-
buf[pos++] =
|
|
3964
|
-
buf[pos++] =
|
|
4066
|
+
buf[pos++] = 32 | (this.root.config.cpuMode === CpuMode.Fast ? 16 : 0) | (this.root.config.memoryMode === MemoryMapMode.Hi ? 1 : this.root.config.memoryMode === MemoryMapMode.ExHi ? 5 : 0);
|
|
4067
|
+
buf[pos++] = this.root.config.chipset;
|
|
4068
|
+
buf[pos++] = this.romSize;
|
|
4069
|
+
buf[pos++] = this.root.config.ramSize;
|
|
3965
4070
|
buf[pos++] = 1;
|
|
3966
4071
|
buf[pos++] = 51;
|
|
3967
4072
|
buf[pos++] = 0;
|
|
3968
4073
|
}
|
|
3969
4074
|
writeChecksum() {
|
|
3970
4075
|
const buf = this.outBuffer;
|
|
3971
|
-
|
|
3972
|
-
buf[
|
|
3973
|
-
buf[
|
|
3974
|
-
buf[
|
|
4076
|
+
let pos = this.root.config.memoryMode === MemoryMapMode.Lo ? 32732 : 65500;
|
|
4077
|
+
buf[pos] = 255;
|
|
4078
|
+
buf[pos + 1] = 255;
|
|
4079
|
+
buf[pos + 2] = 0;
|
|
4080
|
+
buf[pos + 3] = 0;
|
|
3975
4081
|
let sum = 0;
|
|
3976
4082
|
for (let i = 0; i < buf.length; i++) sum += buf[i];
|
|
3977
|
-
buf[
|
|
3978
|
-
buf[
|
|
4083
|
+
buf[pos + 2] = sum & 255;
|
|
4084
|
+
buf[pos + 3] = sum >> 8 & 255;
|
|
3979
4085
|
const comp = ~sum;
|
|
3980
|
-
buf[
|
|
3981
|
-
buf[
|
|
4086
|
+
buf[pos] = comp & 255;
|
|
4087
|
+
buf[pos + 1] = comp >> 8 & 255;
|
|
3982
4088
|
}
|
|
3983
4089
|
writeEntryPoints(asmFiles) {
|
|
3984
4090
|
const buf = this.outBuffer;
|
|
@@ -3986,8 +4092,10 @@ var RomWriter = class {
|
|
|
3986
4092
|
for (const ep of this.root.config.entryPoints) {
|
|
3987
4093
|
const match = entryBlocks.find((b) => b.label === ep.name);
|
|
3988
4094
|
if (match) {
|
|
3989
|
-
|
|
3990
|
-
|
|
4095
|
+
let location = match.location;
|
|
4096
|
+
if (this.root.config.memoryMode === MemoryMapMode.Lo) location += RomProcessingConstants.PAGE_SIZE;
|
|
4097
|
+
buf[ep.location] = location & 255;
|
|
4098
|
+
buf[ep.location + 1] = location >> 8 & 255;
|
|
3991
4099
|
}
|
|
3992
4100
|
}
|
|
3993
4101
|
}
|
|
@@ -3999,19 +4107,21 @@ var RomWriter = class {
|
|
|
3999
4107
|
const data = file.rawData;
|
|
4000
4108
|
let remain = file.size;
|
|
4001
4109
|
let srcPos = 0;
|
|
4002
|
-
if (file.
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4110
|
+
if (file.compressed !== true) {
|
|
4111
|
+
if (file.type.header === -2) {
|
|
4112
|
+
remain -= 2;
|
|
4113
|
+
buf[pos++] = remain & 255;
|
|
4114
|
+
buf[pos++] = remain >> 8 & 255;
|
|
4115
|
+
} else if (file.type.header > 0) {
|
|
4116
|
+
remain -= file.type.header;
|
|
4117
|
+
for (let i = 0; i < file.type.header; i++) buf[pos++] = data[srcPos++];
|
|
4118
|
+
}
|
|
4009
4119
|
}
|
|
4010
|
-
if (file.compressed
|
|
4120
|
+
if (file.compressed === false) {
|
|
4011
4121
|
remain -= 2;
|
|
4012
|
-
const
|
|
4013
|
-
buf[pos++] =
|
|
4014
|
-
buf[pos++] =
|
|
4122
|
+
const size = 0 - remain & 65535;
|
|
4123
|
+
buf[pos++] = size & 255;
|
|
4124
|
+
buf[pos++] = size >> 8 & 255;
|
|
4015
4125
|
}
|
|
4016
4126
|
while (remain > 0) {
|
|
4017
4127
|
buf[pos++] = data[srcPos++];
|
|
@@ -4105,7 +4215,7 @@ var RomWriter = class {
|
|
|
4105
4215
|
default: throw new Error(`Invalid operand '${label}'`);
|
|
4106
4216
|
}
|
|
4107
4217
|
}
|
|
4108
|
-
let type = Address.typeFromCode(str[0]);
|
|
4218
|
+
let type = isRelative ? parentOp?.size === 3 ? AddressType.WRelative : AddressType.Relative : Address.typeFromCode(str[0]);
|
|
4109
4219
|
if (type === AddressType.Unknown) type = parentOp?.size === 4 ? AddressType.Address : parentOp?.size === 2 ? AddressType.Unknown : AddressType.Offset;
|
|
4110
4220
|
if (isRelative) {
|
|
4111
4221
|
loc -= block.location + opos;
|
|
@@ -4119,22 +4229,24 @@ var RomWriter = class {
|
|
|
4119
4229
|
break;
|
|
4120
4230
|
} else markerOffset += RomProcessingConstants.getSize(part);
|
|
4121
4231
|
}
|
|
4232
|
+
if (!isRelative && type !== AddressType.Location) loc = Address.fromLocation(loc, this.root.config.memoryMode, this.root.config.cpuMode).toInt();
|
|
4122
4233
|
switch (type) {
|
|
4123
4234
|
case AddressType.Offset:
|
|
4235
|
+
case AddressType.WRelative:
|
|
4124
4236
|
currentObj = new Word(loc);
|
|
4125
4237
|
continue;
|
|
4126
4238
|
case AddressType.Bank:
|
|
4127
|
-
currentObj = new Byte(loc >> 16
|
|
4239
|
+
currentObj = new Byte(loc >> 16);
|
|
4128
4240
|
continue;
|
|
4129
4241
|
case AddressType.WBank:
|
|
4130
|
-
currentObj = new Word(loc >> 16
|
|
4242
|
+
currentObj = new Word(loc >> 16);
|
|
4131
4243
|
continue;
|
|
4132
4244
|
case AddressType.Address:
|
|
4133
|
-
currentObj = new Long(loc | ((loc & 65535) >= 32768 ? 8388608 : 12582912));
|
|
4134
|
-
continue;
|
|
4135
4245
|
case AddressType.Location:
|
|
4136
4246
|
currentObj = new Long(loc);
|
|
4137
4247
|
continue;
|
|
4248
|
+
case AddressType.Unknown:
|
|
4249
|
+
case AddressType.Relative:
|
|
4138
4250
|
default:
|
|
4139
4251
|
currentObj = new Byte(loc);
|
|
4140
4252
|
continue;
|
|
@@ -4549,7 +4661,7 @@ var StringReader = class StringReader {
|
|
|
4549
4661
|
} else {
|
|
4550
4662
|
let found = false;
|
|
4551
4663
|
for (const dictionary of Object.values(dictionaries)) if (c >= dictionary.base && c <= dictionary.range) {
|
|
4552
|
-
builder.push(dictionary.entries[c - dictionary.base]
|
|
4664
|
+
builder.push(dictionary.entries[c - dictionary.base]);
|
|
4553
4665
|
found = true;
|
|
4554
4666
|
break;
|
|
4555
4667
|
}
|
|
@@ -4668,24 +4780,38 @@ var StringProcessor = class {
|
|
|
4668
4780
|
}
|
|
4669
4781
|
}
|
|
4670
4782
|
processString(str, stringType) {
|
|
4671
|
-
const
|
|
4783
|
+
const cmdLookup = stringType.commands;
|
|
4784
|
+
const dictLookup = stringType.dictionaries;
|
|
4672
4785
|
let lastCmd = null;
|
|
4786
|
+
for (const dictionary of Object.values(dictLookup)) for (let ix = 0; ix < dictionary.entries.length; ix++) {
|
|
4787
|
+
const entry = dictionary.entries[ix];
|
|
4788
|
+
if (str.indexOf(entry) >= 0) if (dictionary.command !== void 0) str = str.replace(entry, `[${dictionary.command}:${(ix + dictionary.base).toString(16).toUpperCase()}]`);
|
|
4789
|
+
else str = str.replace(entry, `[${(ix + dictionary.base).toString(16).toUpperCase()}]`);
|
|
4790
|
+
}
|
|
4673
4791
|
for (let x = 0; x < str.length; x++) {
|
|
4674
4792
|
const c = str[x];
|
|
4675
4793
|
if (c === "[") {
|
|
4676
4794
|
const endIx = str.indexOf("]", x + 1);
|
|
4677
|
-
const
|
|
4795
|
+
const splitChars = [
|
|
4678
4796
|
":",
|
|
4679
4797
|
",",
|
|
4680
4798
|
" "
|
|
4681
|
-
]
|
|
4799
|
+
];
|
|
4800
|
+
const subStr = str.substring(x + 1, endIx);
|
|
4801
|
+
let ix = subStr.length === 2 ? parseInt(subStr, 16) : NaN;
|
|
4802
|
+
if (!isNaN(ix)) {
|
|
4803
|
+
this.memBuffer.push(ix);
|
|
4804
|
+
x = endIx;
|
|
4805
|
+
continue;
|
|
4806
|
+
}
|
|
4807
|
+
const parts = str.substring(x + 1, endIx).split(/* @__PURE__ */ new RegExp(`[${splitChars.join("")}]`)).filter((p) => p.length > 0);
|
|
4682
4808
|
x = endIx;
|
|
4683
4809
|
if (parts.length === 0) {
|
|
4684
4810
|
this.flushBuffer(stringType, true);
|
|
4685
4811
|
this.context.currentBlock.objList.push({ offset: this.context.currentBlock.size });
|
|
4686
4812
|
continue;
|
|
4687
4813
|
}
|
|
4688
|
-
const cmd =
|
|
4814
|
+
const cmd = cmdLookup[parts[0]];
|
|
4689
4815
|
if (cmd) {
|
|
4690
4816
|
lastCmd = cmd;
|
|
4691
4817
|
this.memBuffer.push(cmd.id);
|
|
@@ -6157,12 +6283,12 @@ var RomGenerator = class {
|
|
|
6157
6283
|
this.assembleCodeFromText(asmFiles);
|
|
6158
6284
|
RomProcessor.applyPatches(asmFiles, patchFiles);
|
|
6159
6285
|
for (const asm of chunkFiles) ChunkFileUtils.calculateSize(asm);
|
|
6160
|
-
new RomLayout(chunkFiles).organize();
|
|
6286
|
+
const pages = new RomLayout(chunkFiles, this.dbRoot).organize();
|
|
6161
6287
|
for (const file of asmFiles) ChunkFileUtils.rebase(file);
|
|
6162
6288
|
this.generateAsmIncludeLookups(asmFiles);
|
|
6163
6289
|
const blockLookup = /* @__PURE__ */ new Map();
|
|
6164
6290
|
for (const f of chunkFiles) blockLookup.set(f.name.toUpperCase(), f.location);
|
|
6165
|
-
return await this.writeRom(blockLookup, chunkFiles, asmFiles);
|
|
6291
|
+
return await this.writeRom(blockLookup, chunkFiles, asmFiles, pages);
|
|
6166
6292
|
}
|
|
6167
6293
|
applyProjectInit(chunkFiles, asmFiles, patchFiles) {
|
|
6168
6294
|
const moduleLookup = /* @__PURE__ */ new Map();
|
|
@@ -6207,8 +6333,9 @@ var RomGenerator = class {
|
|
|
6207
6333
|
existing.size = chunkFile.size;
|
|
6208
6334
|
} else chunkFiles.push(chunkFile);
|
|
6209
6335
|
}
|
|
6210
|
-
async writeRom(blockLookup, chunkFiles, asmFiles) {
|
|
6336
|
+
async writeRom(blockLookup, chunkFiles, asmFiles, pages) {
|
|
6211
6337
|
const romWriter = new RomWriter(this.dbRoot, "GAIALABS", "01JG ");
|
|
6338
|
+
romWriter.allocate(pages);
|
|
6212
6339
|
for (const file of chunkFiles) await romWriter.writeFile(file, blockLookup);
|
|
6213
6340
|
romWriter.writeHeader();
|
|
6214
6341
|
romWriter.writeEntryPoints(asmFiles);
|
|
@@ -6492,6 +6619,7 @@ exports.CompressionAlgorithms = CompressionAlgorithms;
|
|
|
6492
6619
|
exports.CompressionRegistry = CompressionRegistry;
|
|
6493
6620
|
exports.CopCommandProcessor = CopCommandProcessor;
|
|
6494
6621
|
exports.CopDef = CopDef;
|
|
6622
|
+
exports.CpuMode = CpuMode;
|
|
6495
6623
|
exports.DbAddressingMode = DbAddressingMode;
|
|
6496
6624
|
exports.DbBlock = DbBlock;
|
|
6497
6625
|
exports.DbFile = DbFile;
|