int main(int argc, char *argv[]) { int i, x, y, q, inz; struct section *s; float f; if (sizeof(double) != 8) { fprintf(stderr, "MAIN: sizeof(double) == %d != 8. WLALINK will not work properly.\n", (int)(sizeof(double))); return -1; } atexit(procedures_at_exit); i = SUCCEEDED; x = SUCCEEDED; if (argc > 1) x = parse_flags(argv[1]); else i = FAILED; if (x == FAILED && argc < 3) i = FAILED; if (x == SUCCEEDED && argc < 4) i = FAILED; if (i == FAILED) { printf("\nWLALINK GB-Z80/Z80/6502/65C02/6510/65816/HUC6280/SPC-700 WLA Macro Assembler Linker v5.7\n"); printf("Written by Ville Helin in 2000-2007\n"); printf("Modified for snes-sdk by Ulrich Hecht\n"); printf("USAGE: %s [-bdrvsSno] (<LINK FILE>|<OBJECT FILES...>) <OUTPUT FILE>\n", argv[0]); printf("Options:\n"); printf("b Program file output\n"); printf("d Discard unreferenced sections\n"); printf("i Write list files\n"); printf("r ROM file output (default)\n"); printf("v Verbose messages\n"); printf("s Write also a NO$GMB symbol file\n"); printf("S Write also a WLA symbol file\n"); printf("n Do not link standard libraries\n"); printf("o Take object files instead of link file\n\n"); return 0; } /* load files */ if (load_files(argv, argc, x == SUCCEEDED) == FAILED) return 1; /* check file types */ if (check_file_types() == FAILED) return 1; /* check object headers */ if (check_headers() == FAILED) return 1; /* obtain the amount of rom banks */ if (obtain_rombanks() == FAILED) return 1; banks = malloc(sizeof(int) * rombanks); if (banks == NULL) { fprintf(stderr, "MAIN: Out of memory error.\n"); return 1; } bankaddress = malloc(sizeof(int) * rombanks); if (bankaddress == NULL) { fprintf(stderr, "MAIN: Out of memory error.\n"); return 1; } /* obtain rom bank map and check the project integrity */ if (obtain_rombankmap() == FAILED) return 1; /* obtain memory map and check the project integrity */ if (obtain_memorymap() == FAILED) return 1; /* calculate romsize */ for (romsize = 0, x = 0; x < rombanks; x++) romsize += banks[x]; /* obtain source file names used in compiling */ if (obtain_source_file_names() == FAILED) return 1; /* collect all defines, labels and outside references */ if (collect_dlr() == FAILED) return 1; /* take rom size and allocate memory */ if (allocate_rom() == FAILED) return 1; /* parse data blocks */ if (parse_data_blocks() == FAILED) return 1; /* clean up the structures */ if (clean_up_dlr() == FAILED) return 1; /* drop all unreferenced sections */ if (discard_unreferenced_sections == ON) { if (discard_unused_sections() == FAILED) return 1; /* remove dropped labels */ discard_drop_labels(); } /* correct 65816 library section addresses */ if (cpu_65816 != 0) { if (correct_65816_library_sections() == FAILED) return 1; } #ifdef _MAIN_DEBUG { printf("\n*********************************************\n"); printf("JUST LOADED IN\n"); printf("*********************************************\n\n"); } { struct label *l; printf("LABELS:\n"); l = labels_first; while (l != NULL) { printf("--------------------------------------\n"); printf("name: \"%s\"\n", l->name); printf("sect: \"%d\"\n", l->section); printf("slot: \"%d\"\n", l->slot); printf("base: \"%d\"\n", l->base); printf("bank: \"%d\"\n", l->bank); printf("address: \"%d\"\n", (int)l->address); printf("status: \"%d\"\n", l->status); printf("file_id: \"%d\"\n", l->file_id); l = l->next; } printf("--------------------------------------\n"); } { struct stack *s; printf("STACKS:\n"); s = stacks_first; while (s != NULL) { printf("--------------------------------------\n"); printf("result: \"%d\"\n", s->result); printf("id: \"%d\"\n", s->id); printf("file_id: \"%d\"\n", s->file_id); printf("bank: \"%d\"\n", s->bank); printf("linenumber: \"%d\"\n", s->linenumber); printf("type: \"%d\"\n", s->type); printf("position: \"%d\"\n", s->position); s = s->next; } printf("--------------------------------------\n"); } #endif /* insert sections */ if (insert_sections() == FAILED) return 1; #ifdef _MAIN_DEBUG { struct section *s; printf("SECTIONS:\n"); s = sec_first; while (s != NULL) { printf("--------------------------------------\n"); printf("file: \"%s\"\n", get_file_name(s->file_id)); printf("name: \"%s\"\n", s->name); printf("id: %d\n", s->id); printf("addr: %d\n", s->address); printf("stat: %d\n", s->status); printf("bank: %d\n", s->bank); printf("slot: %d\n", s->slot); printf("size: %d\n", s->size); s = s->next; } printf("--------------------------------------\n"); } #endif /* compute the labels' addresses */ if (fix_labels() == FAILED) return 1; /* compute pending calculations */ if (compute_pending_calculations() == FAILED) return 1; #ifdef _MAIN_DEBUG { struct stack *s; printf("RESOLVED STACKS:\n"); s = stacks_first; while (s != NULL) { printf("--------------------------------------\n"); printf("result: \"%d\"\n", s->result); printf("id: \"%d\"\n", s->id); printf("file_id: \"%d\"\n", s->file_id); s = s->next; } printf("--------------------------------------\n"); } #endif #ifdef _MAIN_DEBUG { struct reference *r; printf("REFERENCES:\n"); r = reference_first; while (r != NULL) { printf("--------------------------------------\n"); printf("name: \"%s\"\n", r->name); printf("file_id: \"%d\"\n", r->file_id); r = r->next; } printf("--------------------------------------\n"); } #endif /* transform computation stack definitions to ordinary definitions */ if (transform_stack_definitions() == FAILED) return 1; /* fix references */ if (fix_references() == FAILED) return 1; /* write checksums and other last minute data */ if (compute_checksums() == FAILED) return 1; /* write rom file */ if (write_rom_file(argv[argc - 1]) == FAILED) return 1; #ifdef _MAIN_DEBUG { printf("\n*********************************************\n"); printf("AFTER EVERYTHING\n"); printf("*********************************************\n\n"); } { struct label *l; printf("LABELS:\n"); l = labels_first; while (l != NULL) { printf("--------------------------------------\n"); printf("name: \"%s\"\n", l->name); printf("sect: \"%d\"\n", l->section); printf("slot: \"%d\"\n", l->slot); printf("base: \"%d\"\n", l->base); printf("address: \"%d\"\n", (int)l->address); printf("rom_address: \"%d\"\n", l->rom_address); printf("bank: \"%d\"\n", l->bank); printf("status: \"%d\"\n", l->status); printf("file_id: \"%d\"\n", l->file_id); l = l->next; } printf("--------------------------------------\n"); } #endif /* export symbolic information file */ if (symbol_mode != SYMBOL_MODE_NONE) { if (write_symbol_file(argv[argc - 1], symbol_mode) == FAILED) return FAILED; } /* write list files */ if (listfile_data == YES) { if (listfile_write_listfiles(sec_first) == FAILED) return FAILED; } /* show rom information */ y = 0; if (verbose_mode == ON) { x = 0; for (i = 0; i < romsize; i++) { if (rom_usage[i] == 0 && x == 0) { x = 1; y = i; } else if (rom_usage[i] != 0 && x == 1) { if (y == (i - 1)) fprintf(stderr, "Free space at $%.4x.\n", y); else fprintf(stderr, "Free space at $%.4x-$%.4x.\n", y, i - 1); x = 0; } } if (x == 1) { if (y == (i - 1)) fprintf(stderr, "Free space at $%.4x.\n", y); else fprintf(stderr, "Free space at $%.4x-$%.4x.\n", y, i - 1); } for (y = 0, q = 0; y < romsize; q++) { for (x = 0, inz = 0; inz < banks[q]; inz++) { if (rom_usage[y++] == 0) x++; } f = (((float)x)/banks[q]) * 100.0f; if (f == 100.0f) printf("Bank %.2d has %.5d bytes (%.1f%%) free.\n", q, x, f); else printf("Bank %.2d has %.5d bytes (%.2f%%) free.\n", q, x, f); } /* ROM data */ if (output_mode == OUTPUT_ROM) { for (i = 0, y = 0; i < romsize; i++) { if (rom_usage[i] == 0) y++; } fprintf(stderr, "%d unused bytes of total %d.\n", y, romsize); q = romsize; } /* program file data */ else { for (i = program_start, y = 0; i < program_end; i++) { if (rom_usage[i] == 0) y++; } q = program_end - program_start + 1; fprintf(stderr, "%d unused bytes (%.2f%%) of total %d.\n", y, (((double)y) / q) * 100, q); } if (file_header_size != 0) fprintf(stderr, "File header size %d.\n", file_header_size); if (file_footer_size != 0) fprintf(stderr, "File footer size %d.\n", file_footer_size); if (smc_status != 0) { fprintf(stderr, "512 additional bytes from the SMC ROM header.\n"); i = file_header_size + file_footer_size + 512; } else i = file_header_size + file_footer_size; s = sec_hd_first; while (s != NULL) { fprintf(stderr, "Bank %d header section size %d.\n", s->bank, s->size); i += s->size; s = s->next; } if (i != 0) { fprintf(stderr, "Total %d additional bytes (from headers and footers).\n", i); fprintf(stderr, "Total size %d bytes.\n", i + q); } } return 0; }
int main(int argc, char *argv[]) { int i, x, y, q, inz; struct section *s; float f; if (sizeof(double) != 8) { fprintf(stderr, "MAIN: sizeof(double) == %d != 8. WLALINK will not work properly.\n", (int)(sizeof(double))); return -1; } atexit(procedures_at_exit); i = SUCCEEDED; if (argc > 2) x = parse_flags(argv, argc); else x = FAILED; if (load_file_failed == YES) return 0; if (x == FAILED) { printf("\nWLALINK GB-Z80/Z80/6502/65C02/6510/65816/HUC6280/SPC-700 WLA Macro Assembler Linker v5.8b\n"); printf("Written by Ville Helin in 2000-2008 - In GitHub since 2014: https://github.com/vhelin/wla-dx\n"); printf("USAGE: %s [OPTIONS] <OBJECT FILES> <OUTPUT FILE>\n\n", argv[0]); printf("Options:\n"); printf("-b Program file output\n"); printf("-d Discard unreferenced sections\n"); printf("-i Write list files\n"); printf("-r ROM file output (default)\n"); printf("-s Write also a NO$GMB symbol file\n"); printf("-S Write also a WLA symbol file\n"); printf("-v Verbose messages\n"); printf("-l LIBNAME\n"); printf(" Search for library LIBNAME\n"); printf("-L DIRECTORY\n"); printf(" Add DIRECTORY to library search path\n\n"); return 0; } global_unique_label_map = hashmap_new(); namespace_map = hashmap_new(); /* load objects */ if (load_objects(argv, argc) == FAILED) return 1; /* check file types */ if (check_file_types() == FAILED) return 1; /* check object headers */ if (check_headers() == FAILED) return 1; /* obtain the amount of rom banks */ if (obtain_rombanks() == FAILED) return 1; banksizes = malloc(sizeof(int) * rombanks); if (banksizes == NULL) { fprintf(stderr, "MAIN: Out of memory error.\n"); return 1; } bankaddress = malloc(sizeof(int) * rombanks); if (bankaddress == NULL) { fprintf(stderr, "MAIN: Out of memory error.\n"); return 1; } /* obtain rom bank map and check the project integrity */ if (obtain_rombankmap() == FAILED) return 1; /* obtain memory map and check the project integrity */ if (obtain_memorymap() == FAILED) return 1; /* calculate romsize */ for (romsize = 0, x = 0; x < rombanks; x++) romsize += banksizes[x]; /* obtain source file names used in compiling */ if (obtain_source_file_names() == FAILED) return 1; /* collect all defines, labels, outside references and pending (stack) calculations */ if (collect_dlr() == FAILED) return 1; /* take rom size and allocate memory */ if (allocate_rom() == FAILED) return 1; /* parse data blocks */ if (parse_data_blocks() == FAILED) return 1; /* clean up the structures */ if (clean_up_dlr() == FAILED) return 1; /* associate labels with their sections */ if (fix_label_sections() == FAILED) return 1; /* drop all unreferenced sections */ if (discard_unreferenced_sections == ON) { if (discard_unused_sections() == FAILED) return 1; /* remove dropped labels */ discard_drop_labels(); } /* correct 65816 library section addresses */ if (cpu_65816 != 0) { if (correct_65816_library_sections() == FAILED) return 1; } /* if ROM size < 32KBs, correct SDSC tag sections' addresses */ if (smstag_defined != 0 && romsize < 0x8000) { struct section *s = sec_first; int sub = 0x4000; /* assume 16KB ROM size */ if (romsize < 0x4000) sub = 0x6000; /* assume 8KB ROM size */ while (s != NULL) { if (strcmp(s->name, "!__WLA_SDSCTAG_STRINGS") == 0 || strcmp(s->name, "!__WLA_SDSCTAG_TIMEDATE") == 0) { /* these sections would originally go to 0x7Fnm, but as we now assume that the ROM is smaller, we'll bring them down */ s->address -= sub; } s = s->next; } } #ifdef WLALINK_DEBUG printf("\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("*** LOADED LOADED LOADED LOADED LOADED LOADED LOADED LOADED LOADED ***\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); if (labels_first != NULL) { struct label *l = labels_first; printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- LABELS ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); while (l != NULL) { debug_print_label(l); l = l->next; } } if (stacks_first != NULL) { struct stack *s = stacks_first; printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- (STACK) CALCULATIONS ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); while (s != NULL) { printf("----------------------------------------------------------------------\n"); { int z; for (z = 0; z < s->stacksize; z++) { struct stackitem *si = &s->stack[z]; printf(get_stack_item_description(si)); } } printf("id: %d file: %s line: %d type: %d bank: %d position: %d\n", s->id, get_file_name(s->file_id), s->linenumber, s->type, s->bank, s->position); s = s->next; } printf("----------------------------------------------------------------------\n"); } #endif /* reserve the bytes the checksummers will use, so no (free type) sections will be placed there */ reserve_checksum_bytes(); #ifdef WLALINK_DEBUG printf("\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("*** RESOLVED RESOLVED RESOLVED RESOLVED RESOLVED RESOLVED RESOLVED ***\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); printf("**********************************************************************\n"); if (sec_first != NULL) { printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- SECTIONS ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); } #endif /* insert sections */ if (insert_sections() == FAILED) return 1; #ifdef WLALINK_DEBUG if (sec_first != NULL) { struct section *s = sec_first; while (s != NULL) { printf("----------------------------------------------------------------------\n"); printf("name: \"%s\" file: %s\n", s->name, get_file_name(s->file_id)); printf("id : %d\n", s->id); printf("addr : %d\n", s->address); printf("stat : %d\n", s->status); printf("bank : %d\n", s->bank); printf("slot : %d\n", s->slot); printf("size : %d\n", s->size); printf("align: %d\n", s->alignment); s = s->next; } printf("----------------------------------------------------------------------\n"); } if (labels_first != NULL) { printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- LABELS ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); } #endif /* compute the labels' addresses */ if (fix_label_addresses() == FAILED) return 1; #ifdef WLALINK_DEBUG if (labels_first != NULL) { struct label *l = labels_first; while (l != NULL) { debug_print_label(l); l = l->next; } } if (stacks_first != NULL) { printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- (STACK) CALCULATIONS ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); } #endif /* compute pending calculations */ if (compute_pending_calculations() == FAILED) return 1; #ifdef WLALINK_DEBUG if (stacks_first != NULL) { struct stack *s = stacks_first; while (s != NULL) { printf("----------------------------------------------------------------------\n"); { int z; for (z = 0; z < s->stacksize; z++) { struct stackitem *si = &s->stack[z]; printf(get_stack_item_description(si)); } } printf("id: %d file: %s line: %d type: %d bank: %d position: %d result: %d/$%x\n", s->id, get_file_name(s->file_id), s->linenumber, s->type, s->bank, s->position, s->result, s->result); s = s->next; } printf("----------------------------------------------------------------------\n"); } if (reference_first != NULL) { printf("\n"); printf("----------------------------------------------------------------------\n"); printf("--- REFERENCES ---\n"); printf("----------------------------------------------------------------------\n"); printf("\n"); } #endif /* transform computation stack definitions to ordinary definitions */ if (transform_stack_definitions() == FAILED) return 1; /* fix references */ if (fix_references() == FAILED) return 1; #ifdef WLALINK_DEBUG if (reference_first != NULL) { struct reference *r = reference_first; while (r != NULL) { printf("name: \"%s\" file: %s\n", r->name, get_file_name(r->file_id)); r = r->next; } } #endif /* write checksums and other last minute data */ if (compute_checksums() == FAILED) return 1; /* write rom file */ if (write_rom_file(argv[argc - 1]) == FAILED) return 1; /* export symbolic information file */ if (symbol_mode != SYMBOL_MODE_NONE) { if (write_symbol_file(argv[argc - 1], symbol_mode) == FAILED) return FAILED; } /* write list files */ if (listfile_data == YES) { if (listfile_write_listfiles(sec_first) == FAILED) return FAILED; } /* show rom information */ y = 0; if (verbose_mode == ON) { x = 0; for (i = 0; i < romsize; i++) { if (rom_usage[i] == 0 && x == 0) { x = 1; y = i; } else if (rom_usage[i] != 0 && x == 1) { if (y == (i - 1)) fprintf(stderr, "Free space at $%.4x.\n", y); else fprintf(stderr, "Free space at $%.4x-$%.4x.\n", y, i - 1); x = 0; } } if (x == 1) { if (y == (i - 1)) fprintf(stderr, "Free space at $%.4x.\n", y); else fprintf(stderr, "Free space at $%.4x-$%.4x.\n", y, i - 1); } for (y = 0, q = 0; y < romsize; q++) { for (x = 0, inz = 0; inz < banksizes[q]; inz++) { if (rom_usage[y++] == 0) x++; } f = (((float)x)/banksizes[q]) * 100.0f; if (f == 100.0f) fprintf(stderr, "Bank %.2d has %.5d bytes (%.1f%%) free.\n", q, x, f); else fprintf(stderr, "Bank %.2d has %.5d bytes (%.2f%%) free.\n", q, x, f); } /* ROM data */ if (output_mode == OUTPUT_ROM) { for (i = 0, y = 0; i < romsize; i++) { if (rom_usage[i] == 0) y++; } fprintf(stderr, "%d unused bytes of total %d.\n", y, romsize); q = romsize; } /* program file data */ else { for (i = program_start, y = 0; i < program_end; i++) { if (rom_usage[i] == 0) y++; } q = program_end - program_start + 1; fprintf(stderr, "%d unused bytes (%.2f%%) of total %d.\n", y, (((double)y) / q) * 100, q); } if (file_header_size != 0) fprintf(stderr, "File header size %d.\n", file_header_size); if (file_footer_size != 0) fprintf(stderr, "File footer size %d.\n", file_footer_size); if (smc_status != 0) { fprintf(stderr, "512 additional bytes from the SMC ROM header.\n"); i = file_header_size + file_footer_size + 512; } else i = file_header_size + file_footer_size; s = sec_hd_first; while (s != NULL) { fprintf(stderr, "Bank %d header section size %d.\n", s->bank, s->size); i += s->size; s = s->next; } if (i != 0) { fprintf(stderr, "Total %d additional bytes (from headers and footers).\n", i); fprintf(stderr, "Total size %d bytes.\n", i + q); } } return 0; }