Esempio n. 1
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;
  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;
}
Esempio n. 2
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;
}