gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-support/bankpack/obj_data.c
1
2 // This is free and unencumbered software released into the public domain.
3 // For more information, please refer to <https://unlicense.org>
4 // bbbbbr 2020
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12
13 #include "common.h"
14 #include "list.h"
15 #include "files.h"
16 #include "options.h"
17 #include "obj_data.h"
18
19
20 static bool bank_check_mbc1_ok(uint32_t bank_num);
21 static void bank_update_assigned_minmax(uint16_t bank_num);
22 static void bank_update_all_max(uint16_t bank_num);
23 static void bank_add_area(bank_item * p_bank, uint16_t bank_num, area_item * p_area);
24 static void bank_check_area_size(area_item * p_area);
25 static void banks_assign_area(area_item * p_area);
26 static int area_item_compare(const void* a, const void* b);
27 static void areas_sort(void);
28 static bool symbol_banked_check_rewrite_ok(char *, uint32_t);
29
30
31
32 list_type banklist;
33 list_type arealist;
34 list_type symbollist;
35 list_type symbol_matchlist;
36
37 uint16_t bank_limit_rom_min = BANK_NUM_ROM_DEFAULT;
38 uint16_t bank_limit_rom_max = BANK_NUM_ROM_MAX;
39
40
41 uint16_t bank_assigned_rom_min = BANK_NUM_ROM_MAX;
42 uint16_t bank_assigned_rom_max = 0;
43 uint16_t bank_assigned_rom_max_alltypes = 0;
44
45
46 void obj_data_init(void) {
47 int c;
48 bank_item newbank;
49
50 list_init(&banklist, sizeof(bank_item));
51 list_init(&arealist, sizeof(area_item));
52 list_init(&symbollist, sizeof(symbol_item));
53 list_init(&symbol_matchlist, sizeof(symbol_match_item));
54
55 // Pre-populate bank list with max number of banks
56 // to allow handling fixed-bank (non-autobank) areas
57 newbank.size = newbank.free = BANK_SIZE_ROM;
58 newbank.reserved = 0;
59 newbank.type = BANK_TYPE_UNSET;
60 newbank.item_count = 0;
61 for (c=0; c < BANK_ROM_TOTAL; c++)
62 list_additem(&banklist, &newbank);
63
64 // Add default symbol match and replace
65 symbol_match_add("___bank_");
66 }
67
68
69 void obj_data_cleanup(void) {
70 list_cleanup(&banklist);
71 list_cleanup(&arealist);
72 list_cleanup(&symbollist);
73 list_cleanup(&symbol_matchlist);
74 }
75
76
77 // Add a symbol to the match and replace list
78 void symbol_match_add(char * symbol_str) {
79
80 symbol_match_item newmatch;
81
82 if (snprintf(newmatch.name, sizeof(newmatch.name), "%s", symbol_str) > sizeof(newmatch.name))
83 printf("BankPack: Warning: truncated symbol match string to:%s\n",newmatch.name);
84
85 list_additem(&symbol_matchlist, &newmatch);
86 }
87
88
89
90 // Add an area into the pool of areas to assign (if it's banked CODE)
91 int areas_add(char * area_str, uint32_t file_id) {
92
93 area_item newarea;
94
95 // Only match areas which are banked ("_CODE_" vs "_CODE") and ("_LIT_")
96 if (AREA_LINE_RECORDS == sscanf(area_str,"A _CODE _%3d size %4x flags %*4x addr %*4x",
97 &newarea.bank_num_in, &newarea.size)) {
98 newarea.type = BANK_TYPE_CODE;
99 }
100 else if (AREA_LINE_RECORDS == sscanf(area_str,"A _LIT_%3d size %4x flags %*4x addr %*4x",
101 &newarea.bank_num_in, &newarea.size)) {
102 newarea.type = BANK_TYPE_LIT_EXCLUSIVE;
103 }
104 else
105 return false;
106
107 // Only process areas with (size > 0)
108 if (newarea.size > 0) {
109 if (newarea.type == BANK_TYPE_LIT_EXCLUSIVE)
110 sprintf(newarea.name, "_LIT_"); // Hardwired to _LIT_ for now
111 else
112 sprintf(newarea.name, "_CODE_"); // Hardwired to _CODE_ for now
113 newarea.file_id = file_id;
114 newarea.bank_num_out = BANK_NUM_UNASSIGNED;
115 list_additem(&arealist, &newarea);
116 return true;
117 } else
118 return false;
119 }
120
121
122 // Check and add a symbol record (if it's banked CODE)
123 int symbols_add(char * symbol_str, uint32_t file_id, unsigned int obj_file_format) {
124
125 symbol_item newsymbol;
126
127 const char * s_def_matches[] = {[OBJ_FILE_XL3_24BIT_ADDR] = "S %" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def00%4x",
128 [OBJ_FILE_XL4_32BIT_ADDR] = "S %" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def0000%4x"};
129 if (obj_file_format >= OBJ_FILE_UNKNOWN) return false;
130
131 if (SYMBOL_LINE_RECORDS == sscanf(symbol_str, s_def_matches[obj_file_format], newsymbol.name, &newsymbol.bank_num_in)) {
132
133 // Symbols that start with b_ store the bank num for the matching symbol without 'b'
134 newsymbol.is_banked_def = (newsymbol.name[0] == 'b');
135 newsymbol.file_id = file_id;
136 newsymbol.found_matching_symbol = false;
137
138 // Don't add banked symbols if they're not set to the autobank bank #
139 if ((newsymbol.is_banked_def) && (newsymbol.bank_num_in != BANK_NUM_AUTO))
140 return false;
141
142 list_additem(&symbollist, &newsymbol);
143 return true;
144 }
145 return false;
146 }
147
148
149 // Track Min/Max assigned banks used
150 static void bank_update_assigned_minmax(uint16_t bank_num) {
151
152 if (bank_num > bank_assigned_rom_max)
153 bank_assigned_rom_max = bank_num;
154
155 if (bank_num < bank_assigned_rom_min)
156 bank_assigned_rom_min = bank_num;
157
158 bank_update_all_max(bank_num);
159 }
160
161
162 // Tracks Max bank for *all* banks used, including fixed banks outside max limits
163 static void bank_update_all_max(uint16_t bank_num) {
164
165 if (bank_num > bank_assigned_rom_max_alltypes)
166 bank_assigned_rom_max_alltypes = bank_num;
167 }
168
169
170 // Add an area to a bank.
171 // It should only error out when there isn't enough
172 // room with a fixed-bank area (non-autobank)
173 static void bank_add_area(bank_item * p_bank, uint16_t bank_num, area_item * p_area) {
174
175 // Make sure there is room and then update free space
176 if (p_area->size > p_bank->free) {
177
178 // Trying to add an auto-bank area to a full bank should be prevented by previous tests, but just in case
179 if (p_area->bank_num_in == BANK_NUM_AUTO) {
180 printf("BankPack: ERROR! Auto-banked Area %s, bank %d, size %d won't fit in assigned bank %d (%d bytes free, %d bytes reserved)\n",
181 p_area->name, p_area->bank_num_in, p_area->size, bank_num, p_bank->free, p_bank->reserved);
182 exit(EXIT_FAILURE);
183 } else {
184 // Only warn for fixed bank areas. Don't exit and add the area anyway
185 printf("BankPack: Warning: Fixed-bank Area %s, bank %d, size %d won't fit in assigned bank %d (%d bytes free, %d bytes reserved)\n",
186 p_area->name, p_area->bank_num_in, p_area->size, bank_num, p_bank->free, p_bank->reserved);
187 }
188
189 // Force bank space to zero, subtracting at this point would overflow
190 p_bank->free = 0;
191 } else
192 p_bank->free -= p_area->size;
193
194 // Copy bank type from area: some platforms (sms) don't allow mixing of area types in the same bank
195 // Assign outbound bank number for the area
196 p_bank->type = p_area->type;
197 p_bank->item_count++;
198 p_area->bank_num_out = bank_num;
199 bank_update_assigned_minmax(bank_num);
200 }
201
202
203 // Check to see if the specified bank is allowed with MBC1
204 static bool bank_check_mbc1_ok(uint32_t bank_num) {
205
206 if ((bank_num == 0x20U) || (bank_num == 0x40U) || (bank_num == 0x60U))
207 return false;
208 else
209 return true;
210 }
211
212
213 // Checks to make sure area size is not larger than an entire bank
214 static void bank_check_area_size(area_item * p_area) {
215 if (p_area->size > BANK_SIZE_ROM) {
216 printf("BankPack: ERROR! Area %s, bank %d, size %d is too large for bank size %d (file %s)\n",
217 p_area->name, p_area->bank_num_in, p_area->size, BANK_SIZE_ROM, file_get_name_in_by_id(p_area->file_id));
218 exit(EXIT_FAILURE);
219 }
220 }
221
222
223 // Display a error message about bank mixing
224 static void bank_report_mixed_area_error(bank_item * p_bank, uint16_t bank_num, area_item * p_area) {
225
226 printf("BankPack: ERROR! Bank %d already assigned different area type.\n"
227 " Can't mix _CODE_ and _LIT_ areas in the same bank for this platform.\n"
228 " Rejecting: Area %s, bank %d, file:%s\n",
229 p_area->bank_num_in, p_area->name, bank_num, file_get_name_in_by_id(p_area->file_id));
230
231 if (option_get_verbose())
232 banks_show();
233 }
234
235
236 // Checks whether mixing area types in the same bank should be rejected
237 static bool bank_check_mixed_area_types_ok(bank_item * p_bank, uint16_t bank_num, area_item * p_area) {
238
239 // Don't allow mixing of _CODE_ and _LIT_ for sms/gg ports
240 // If one type has already been assigned to the bank, lock others out
241 if ((option_get_platform() == PLATFORM_SMS) &&
242 (p_bank->type != BANK_TYPE_UNSET) &&
243 (p_area->type != p_bank->type))
244 return false;
245 else
246 return true;
247 }
248
249
250 // Verify that a bank is available for an area
251 // Checks: Size, MBC Availability, Mixed area restrictions
252 static bool bank_check_ok_for_area(uint16_t bank_num, area_item * p_area, bank_item * banks) {
253
254 // Check for MBC bank restrictions
255 if ((option_get_mbc_type() != MBC_TYPE_MBC1) || (bank_check_mbc1_ok(bank_num))) {
256 // Check for allowed area mixing if needed
257 if (bank_check_mixed_area_types_ok(&banks[bank_num], bank_num, p_area)) {
258 // Make sure there is enough space for the area
259 if (p_area->size <= banks[bank_num].free) {
260 return true;
261 }
262 }
263 }
264
265 return false;
266 }
267
268
269 // Assign areas randomly and distributed as sparsely as possible
270 static bool banks_assign_area_random(area_item * p_area, bank_item * banks) {
271
272 uint16_t bank_num;
273 uint16_t item_count_min = BANK_ITEM_COUNT_MAX;
274 uint16_t list_of_banks[BANK_ROM_TOTAL];
275 uint16_t list_count = 0;
276
277 // Find lowest number of areas per bank among banks which have sufficient space for the area
278 for (bank_num = bank_limit_rom_min; bank_num <= bank_limit_rom_max; bank_num++)
279 if ((banks[bank_num].item_count < item_count_min) && bank_check_ok_for_area(bank_num, p_area, banks))
280 item_count_min = banks[bank_num].item_count;
281
282 // Now make a list of suitable banks below that threshold
283 for (bank_num = bank_limit_rom_min; bank_num <= bank_limit_rom_max; bank_num++)
284 if ((banks[bank_num].item_count <= item_count_min) && bank_check_ok_for_area(bank_num, p_area, banks))
285 list_of_banks[list_count++] = bank_num;
286
287 if (list_count > 0) {
288 // Choose a random bank from the selected banks and add the area to it
289 bank_num = list_of_banks[ rand() % list_count ];
290 bank_add_area(&banks[bank_num], bank_num, p_area);
291
292 return true;
293 } else
294 return false; // Fail if no banks were available
295 }
296
297
298 // Assign areas linearly, trying to fill up lowest banks first
299 static bool banks_assign_area_linear(area_item * p_area, bank_item * banks) {
300
301 uint16_t bank_num;
302
303 // Try to assign area to first allowed bank with enough free space
304 // Bank array index maps directly to bank numbers, so [2] will be _CODE_2
305 for (bank_num = bank_limit_rom_min; bank_num <= bank_limit_rom_max; bank_num++) {
306 if (bank_check_ok_for_area(bank_num, p_area, banks)) {
307 bank_add_area(&banks[bank_num], bank_num, p_area);
308 return true;
309 }
310 }
311 return false; // Fail if no banks were available
312 }
313
314
315 // Find a bank for a given area using First Fit Decreasing (FFD)
316 // All possible banks (0-255) were pre-created and initialized [in obj_data_init()],
317 // so there is no need to add when using a fresh bank
318 static void banks_assign_area(area_item * p_area) {
319
320 uint16_t bank_num;
321 bank_item * banks = (bank_item *)banklist.p_array;
322 bool result;
323
324 bank_check_area_size(p_area);
325
326 // Try to assign fixed bank areas to their expected bank.
327 // (ignore the area if it's outside the processing range)
328 if (p_area->bank_num_in != BANK_NUM_AUTO) {
329
330 bank_num = p_area->bank_num_in;
331
332 // Update max bank var that tracks regardless of limits
333 // For auto banks this will get updated via bank_add_area()
334 bank_update_all_max(bank_num);
335
336 if ((bank_num >= bank_limit_rom_min) &&
337 (bank_num <= bank_limit_rom_max)) {
338
339 if ((option_get_mbc_type() == MBC_TYPE_MBC1) && (!bank_check_mbc1_ok(bank_num)))
340 printf("BankPack: Warning: Area in fixed bank assigned to MBC1 excluded bank: %d, file: %s\n", bank_num, file_get_name_in_by_id(p_area->file_id));
341
342 if (!bank_check_mixed_area_types_ok(&banks[bank_num], bank_num, p_area)) {
343 bank_report_mixed_area_error(&banks[bank_num], bank_num, p_area);
344 exit(EXIT_FAILURE);
345 }
346
347 bank_add_area(&banks[bank_num], bank_num, p_area);
348 }
349 //else
350 // printf("BankPack: Notice: Ignoring Area in fixed bank %d outside specified range %d - %d, file: %s\n", bank_num, bank_limit_rom_min, bank_limit_rom_max, file_get_name_in_by_id(p_area->file_id));
351
352 return;
353 }
354 else if (p_area->bank_num_in == BANK_NUM_AUTO) {
355
356 if (option_get_random_assign())
357 result = banks_assign_area_random(p_area, banks);
358 else
359 result = banks_assign_area_linear(p_area, banks);
360
361 if (result) // Success
362 return;
363 }
364
365 if (option_get_verbose())
366 banks_show();
367 printf("BankPack: ERROR! Failed to assign bank for Area %s, bank %d, size %d. Out of banks!\n",
368 p_area->name, p_area->bank_num_in, p_area->size);
369 exit(EXIT_FAILURE);
370 }
371
372
373 // qsort compare rule function for sorting areas
374 static int area_item_compare(const void* a, const void* b) {
375
376 // Sort:
377 // - First by bank num [asc] (implied fixed first, since fixed [0..254] < auto [255])
378 // - Then by size [desc]
379 //
380 // This assumes the autobank indicator (255) is larger than all fixed bank numbers (< 255)
381 if (((area_item *)a)->bank_num_in != ((area_item *)b)->bank_num_in)
382 return (((area_item *)a)->bank_num_in < ((area_item *)b)->bank_num_in) ? QSORT_A_FIRST : QSORT_A_AFTER;
383 else if (((area_item *)a)->size != ((area_item *)b)->size)
384 return (((area_item *)a)->size > ((area_item *)b)->size) ? QSORT_A_FIRST : QSORT_A_AFTER;
385 else
386 return QSORT_A_SAME;
387 }
388
389 static void areas_sort(void) {
390 // Sort banks by name
391 qsort (arealist.p_array, arealist.count, sizeof(area_item), area_item_compare);
392 }
393
394
395 // Assigns all areas -> banks, and bank numbers -> files
396 // Fixed bank areas are placed first, then auto-banks fill the rest in
397 // Only call after all areas have been collected from object files
398 void obj_data_process(list_type * p_filelist) {
399 uint32_t c, s;
400 area_item * areas = (area_item *)arealist.p_array;
401 symbol_item * symbols = (symbol_item *)symbollist.p_array;
402 file_item * files = (file_item *)(p_filelist->p_array);
403
404 // Sort all areas (see function for sort order)
405 areas_sort();
406
407 // Assign areas to banks
408 for (c = 0; c < arealist.count; c++) {
409 banks_assign_area(&(areas[c]));
410 // Set linkerfile order based on sort order above
411 //
412 // All files get processed here, including Fixed bank files.
413 // The Fixed vs Auto sorting guarantees Fixed are always before Auto,
414 // they are then sub-sorted by size
415 //
416 // The + 1 differentiates it from the default LINKERFILE_ORDER_FIRST
417 files[ areas[c].file_id ].linkerfile_order = c + 1;
418
419 // If area was auto-banked then set bank number in associated file
420 if ((areas[c].bank_num_in == BANK_NUM_AUTO) &&
421 (areas[c].bank_num_out != BANK_NUM_UNASSIGNED)) {
422
423 if (files[ areas[c].file_id ].bank_num != BANK_NUM_UNASSIGNED) {
424 printf("BankPack: ERROR! Can't assign bank number to a file more than once! Already %d, new is %d\n",
425 files[ areas[c].file_id ].bank_num, areas[c].bank_num_out);
426 exit(EXIT_FAILURE);
427 }
428
429 files[ areas[c].file_id ].bank_num = areas[c].bank_num_out;
430 files[ areas[c].file_id ].rewrite_needed = true;
431 }
432 }
433
434 // Check all symbols for matching banked entries ("b<symbol>"), flag if match found
435 // TODO: inefficient to loop over symbols for all files
436 for (c = 0; c < symbollist.count; c++) {
437 if (symbols[c].is_banked_def) {
438 for (s = 0; s < symbollist.count; s++) {
439 if (symbols[c].file_id == symbols[s].file_id) {
440 // offset +1 past the "b" char at start of banked symbol entry name
441 if (strcmp(symbols[c].name + 1, symbols[s].name) == 0) {
442 symbols[c].found_matching_symbol = true;
443 break;
444 } else if (s == symbollist.count -1)
445 printf(" -> NO MATCH FOUND%s\n", symbols[c].name);
446 }
447 }
448 }
449 }
450
451 }
452
453
454 // Display file/area/bank assignment
455 // Should be called after obj_data_process()
456 void banks_show(void) {
457
458 uint32_t c;
459 uint32_t a;
460
461 printf("\n== Banks assigned: %d -> %d (allowed %d -> %d). Max including fixed: %d) ==\n",
462 bank_assigned_rom_min, bank_assigned_rom_max,
463 bank_limit_rom_min, bank_limit_rom_max,
464 bank_assigned_rom_max_alltypes);
465
466 bank_item * banks = (bank_item *)banklist.p_array;
467 area_item * areas = (area_item *)arealist.p_array;
468 for (c = 0; c < banklist.count; c++) {
469 if (banks[c].free != BANK_SIZE_ROM) {
470 printf("Bank %d: Size=%5d, Free=%5d, Reserved=%5d\n", c, banks[c].size, banks[c].free, banks[c].reserved);
471 printf(" Area Size Bank in->out File in->out\n");
472 for (a = 0; a < arealist.count; a++) {
473 if (areas[a].bank_num_out == c) {
474 printf(" %8s %5d %3d -> %3d ",
475 areas[a].name,
476 areas[a].size,
477 areas[a].bank_num_in,
478 areas[a].bank_num_out);
479
480 // Split in/out files to separate lines if output would extend
481 // beyond 80 chars (28 leading chars from print above, 4 for " -> ")
482 bool no_line_break = ((strlen(file_get_name_in_by_id(areas[a].file_id)) +
483 strlen(file_get_name_out_by_id(areas[a].file_id)) + 4 + 28) <= 80);
484 printf("%s%s-> %s\n",
485 file_get_name_in_by_id(areas[a].file_id),
486 (no_line_break) ? " " : "\n ",
487 file_get_name_out_by_id(areas[a].file_id));
488 }
489 }
490 // End of bank line break
491 printf("\n");
492 }
493 }
494 }
495
496
497 // Accepts an input string line and writes it
498 // out with an **updated bank num** to a file
499 // * Adds trailing \n if missing
500 bool area_modify_and_write_to_file(char * strline_in, FILE * out_file, uint16_t bank_num) {
501
502 // Only rewrite area bank number for unset banked CODE
503 if (strline_in[0] == 'A') {
504 // For lines: A _CODE_255 ...
505 if (strstr(strline_in, "A _CODE_255")) {
506 fprintf(out_file, "A _CODE_%d %s", bank_num, strstr(strline_in, "size"));
507 // Add trailing \n if missing (may be, due to using strtok() to split the string)
508 if (strline_in[(strlen(strline_in)-1)] != '\n')
509 fprintf(out_file, "\n");
510 return true;
511 }
512 else if (strstr(strline_in, "A _LIT_255")) {
513 fprintf(out_file, "A _LIT_%d %s", bank_num, strstr(strline_in, "size"));
514 // Add trailing \n if missing (may be, due to using strtok() to split the string)
515 if (strline_in[(strlen(strline_in)-1)] != '\n')
516 fprintf(out_file, "\n");
517 return true;
518 }
519 }
520 return false;
521 }
522
523
524 // Check to make sure a banked symbol has a matching symbol in the same file
525 // This prevents mistakenly rewriting symbol b_<something> entries from asm files
526 bool symbol_banked_check_rewrite_ok(char * symbol_name, uint32_t file_id) {
527
528 uint32_t c;
529 symbol_item * symbols = (symbol_item *)symbollist.p_array;
530
531 for (c = 0; c < symbollist.count; c++) {
532 if ((symbols[c].file_id == file_id) &&
533 (symbols[c].is_banked_def) &&
534 (symbols[c].found_matching_symbol)) {
535 // Make sure b_<name> matches
536 if (strcmp(symbols[c].name + 2, symbol_name) == 0)
537 return true;
538 }
539 }
540 return false;
541 }
542
543
544 // Accepts an input string line
545 // and writes it out with an updated bank to a file
546 // * Adds trailing \n if missing
547 bool symbol_modify_and_write_to_file(char * strline_in, FILE * out_file, uint16_t bank_num, uint32_t file_id, unsigned int obj_file_format) {
548
549 uint32_t c;
550 uint32_t bank_in = 0;
551 char strmatch[OBJ_NAME_MAX_STR_LEN];
552 char symbol_name[OBJ_NAME_MAX_STR_LEN];
553 symbol_match_item * sym_match = (symbol_match_item *)symbol_matchlist.p_array;
554
555 const char * s_def_b_matches[] = {[OBJ_FILE_XL3_24BIT_ADDR] = "S b_%" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def%06x",
556 [OBJ_FILE_XL4_32BIT_ADDR] = "S b_%" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def%08x"};
557 const char * s_def_b_rewrite[] = {[OBJ_FILE_XL3_24BIT_ADDR] = "S b_%s Def0000%02x",
558 [OBJ_FILE_XL4_32BIT_ADDR] = "S b_%s Def0000%04x"};
559
560 const char * s_def_matches[] = {[OBJ_FILE_XL3_24BIT_ADDR] = "S %s%%" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def%%06x",
561 [OBJ_FILE_XL4_32BIT_ADDR] = "S %s%%" TOSTR(OBJ_NAME_MAX_STR_LEN) "s Def%%08x"};
562 const char * s_def_rewrite[] = {[OBJ_FILE_XL3_24BIT_ADDR] = "S %s%s Def0000%02x",
563 [OBJ_FILE_XL4_32BIT_ADDR] = "S %s%s Def0000%04x"};
564
565 if (obj_file_format >= OBJ_FILE_UNKNOWN) return false;
566
567 // Only rewrite banked symbol entries
568 if (strline_in[0] == 'S') {
569 // For lines: S b_<symbol name>... Def0000FF (XL3 version)
570 // For lines: S b_<symbol name>... Def000000FF (XL4 version)
571 if (SYMBOL_REWRITE_RECORDS == sscanf(strline_in, s_def_b_matches[obj_file_format], symbol_name, &bank_in)) {
572 if (bank_in == BANK_NUM_AUTO) {
573 if (symbol_banked_check_rewrite_ok(symbol_name, file_id)) {
574 fprintf(out_file, s_def_b_rewrite[obj_file_format], symbol_name, bank_num);
575 if (strline_in[(strlen(strline_in)-1)] != '\n')
576 fprintf(out_file, "\n");
577 return true;
578 }
579 }
580 } // For lines: S ___bank_<trailing symbol name>... Def0000FF
581 else {
582 for (c = 0; c < symbol_matchlist.count; c++) {
583 // Prepare a sscanf match test string for the current symbol name
584 if (snprintf(strmatch, sizeof(strmatch), s_def_matches[obj_file_format], sym_match[c].name) > sizeof(strmatch))
585 printf("BankPack: Warning: truncated symbol match string to:%s\n",strmatch);
586
587 if (SYMBOL_REWRITE_RECORDS == sscanf(strline_in, strmatch, symbol_name, &bank_in)) {
588 if (bank_in == BANK_NUM_AUTO) {
589 fprintf(out_file, s_def_rewrite[obj_file_format], sym_match[c].name, symbol_name, bank_num);
590 if (strline_in[(strlen(strline_in)-1)] != '\n')
591 fprintf(out_file, "\n");
592 return true;
593 }
594 }
595 }
596 }
597 }
598 return false;
599 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.