Пример #1
0
int fix_labels(void) {

  struct section *s = NULL;
  struct label *l, *m;

  
  /* fix labels' addresses */
  l = labels_first;
  while (l != NULL) {
    if (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_SYMBOL || l->status == LABEL_STATUS_BREAKPOINT) {
      if (l->section_status == ON) {
	s = sec_first;
	while (s != NULL) {
	  if (s->id == l->section) {
	    l->bank = s->bank;
	    l->address += s->address;
	    l->rom_address = l->address + bankaddress[l->bank];
	    if (s->status != SECTION_STATUS_ABSOLUTE)
	      l->address += slots[l->slot].address;
	    break;
	  }
	  s = s->next;
	}
      }
      else {
	l->rom_address = l->address + bankaddress[l->bank];
	l->address += slots[l->slot].address;
      }
    }
    l = l->next;
  }

  /* check out if a label exists more than once in a different place */
  l = labels_first;
  while (l != NULL) {
    if (is_label_anonymous(l->name) == FAILED && (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_DEFINE)) {
      m = l->next;
      while (m != NULL) {
	if (strcmp(m->name, l->name) == 0) {
	  if (l->address != m->address && !(m->name[0] == '*' || m->name[0] == '_')) {
	    if (l->status == LABEL_STATUS_DEFINE)
	      fprintf(stderr, "%s: FIX_LABELS: Definition \"%s\" was defined more than once.\n", get_file_name(l->file_id), l->name);
	    else
	      fprintf(stderr, "%s:%s:%d: FIX_LABELS: Label \"%s\" was defined more than once.\n", get_file_name(l->file_id),
		      get_source_file_name(l->file_id, l->file_id_source), l->linenumber, l->name);
	    return FAILED;
	  }
	}
	m = m->next;
      }
    }
    l = l->next;
  }

  return SUCCEEDED;
}
Пример #2
0
int mem_insert_ref(int address, unsigned char data) {

  if (address > romsize || address < 0) {
    fprintf(stderr, "%s:%s:%d: MEM_INSERT: Address $%x is out of the output range $0-$%x.\n",
	    get_file_name(memory_file_id), get_source_file_name(memory_file_id, memory_file_id_source), memory_line_number, address, romsize);
    return FAILED;
  }
  if (rom_usage[address] > 1 && rom[address] != data) {
    if (memory_line_number != 0)
      fprintf(stderr, "%s:%s:%d: MEM_INSERT: Overwrite at $%x (old $%.2x new $%.2x).\n",
	      get_file_name(memory_file_id), get_source_file_name(memory_file_id, memory_file_id_source), memory_line_number, address, rom[address], data);
    else
      fprintf(stderr, "%s:%s:[WLA]: MEM_INSERT: Overwrite at $%x (old $%.2x new $%.2x).\n",
	      get_file_name(memory_file_id), get_source_file_name(memory_file_id, memory_file_id_source), address, rom[address], data);
  }

  rom_usage[address]++;
  rom[address] = data;

  return SUCCEEDED;
}
Пример #3
0
int discard_unused_sections(void) {

  struct section *s;
  int a = 0, b = -1;

  
  /* iterate section discarding until there's no change in the amount of dropped sections */
  while (a != b) {
    s = sec_first;
    while (s != NULL) {
      s->referenced = 0;
      s = s->next;
    }

    a = b;
    discard_iteration();

    b = 0;
    s = sec_first;
    while (s != NULL) {
      if (s->referenced == 0)
        s->alive = NO;
      else
        s->alive = YES;
      if (s->alive == NO)
        b++;
      s = s->next;
    }
  }

  if (verbose_mode == ON) {
    /* announce all the unreferenced sections that will get dropped */
    s = sec_first;
    while (s != NULL) {
      if (s->alive == NO)
	fprintf(stderr, "DISCARD: %s: %s: Section \"%s\" was discarded.\n",
		get_file_name(s->file_id), get_source_file_name(s->file_id, s->file_id_source), s->name);
      s = s->next;
    }
  }
  
  return SUCCEEDED;
}
Пример #4
0
int insert_sections(void) {

  struct section *s, **sa;
  int d, f, i, x, t, q, sn, p;
  char *ram_slots[256], *c;

  
  /* initialize ram slots */
  for (i = 0; i < 256; i++)
    ram_slots[i] = NULL;

  /* find all touched slots */
  s = sec_first;
  while (s != NULL) {
    if (s->status == SECTION_STATUS_RAM && ram_slots[s->slot] == NULL) {
      ram_slots[s->slot] = malloc(slots[s->slot].size);
      if (ram_slots[s->slot] == NULL) {
	fprintf(stderr, "INSERT_SECTIONS: Out of memory error.\n");
	return FAILED;
      }
      memset(ram_slots[s->slot], 0, slots[s->slot].size);
    }
    s = s->next;
  }

  /* count the sections */
  i = 0;
  s = sec_first;
  while (s != NULL) {
    /* no references - skip it */
    if (s->alive == YES)
      i++;
    s = s->next;
  }
  sn = i;

  if (sn == 0)
    return SUCCEEDED;

  sa = malloc(sizeof(struct section *) * sn);
  if (sa == NULL) {
    fprintf(stderr, "INSERT_SECTIONS: Out of memory error.\n");
    return FAILED;
  }

  /* insert the sections into an array for sorting */
  i = 0;
  s = sec_first;
  while (s != NULL) {
    /* no references - skip it */
    if (s->alive == YES)
      sa[i++] = s;
    s = s->next;
  }

  /* sort the sections by size, biggest first */
  qsort(sa, sn, sizeof(struct section *), _sections_sort);

  /* print the sizes (DEBUG) */
  /*
    for (d = 0; d < i; d++)
    fprintf(stderr, "SIZE: %d\n", sa[d]->size);
  */

  /* ram sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];

    /* search for free space */
    if (s->status == SECTION_STATUS_RAM) {
      c = ram_slots[s->slot];
      i = slots[s->slot].size;
      t = 0;
      for (x = 0; x < i; x++, c++) {
	if (*c == 0) {
	  for (q = 0; x < i && q < s->size; x++, q++, c++) {
	    if (*c != 0)
	      break;
	  }
	  if (q == s->size) {
	    t = 1;
	    break;
	  }
	}
      }

      if (t == 0) {
	fprintf(stderr, "INSERT_SECTIONS: No room for RAM section \"%s\" (%d bytes) in slot %d.\n", s->name, s->size, s->slot);
	return FAILED;
      }

      /* mark as used */
      c = c - s->size;
      for (i = 0; i < s->size; i++, c++)
	*c = 1;

      s->address = c - s->size - ram_slots[s->slot];
    }
  }

  /* free tmp memory */
  for (i = 0; i < 256; i++) {
    if (ram_slots[i] != NULL)
      free(ram_slots[i]);
  }

  /* force sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_FORCE) {
      memory_file_id = s->file_id;
      banksize = banksizes[s->bank];
      pc_bank = s->address;
      pc_slot = slots[s->slot].address + pc_bank;
      pc_full = pc_bank + bankaddress[s->bank];
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
      d = pc_full;
      i = d + s->size;
      s->output_address = d;
      section_overwrite = OFF;
      if (i > romsize) {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) goes beyond the ROM size.\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
	return FAILED;
      }
      if (s->address + s->size > banksize) {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) overflows from ROM bank %d.\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
	return FAILED;
      }
      for (; d < i; d++) {
	if (rom_usage[d] != 0 && rom[d] != s->data[d - pc_full])
	  break;
      }
      if (d == i) {
	for (i = 0; i < s->size; i++) {
	  if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
	    return FAILED;
	}
      }
      else {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes).\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
	return FAILED;
      }
    }
  }

  /* absolute sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_ABSOLUTE) {
      d = s->address;
      s->output_address = d;
      section_overwrite = ON;
      for (i = 0; i < s->size; i++) {
	if (mem_insert(d + i, s->data[i]) == FAILED)
	  return FAILED;
      }
    }
  }

  /* semisubfree sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_SEMISUBFREE) {
      pc_bank = 0;
      d = bankaddress[s->bank];

      /* align the starting address */
      f = (pc_bank + d) % s->alignment;
      if (f > 0)
	pc_bank += s->alignment - f;

      i = FAILED;
      while (i == FAILED) {
	f = pc_bank;
	for (x = 0; pc_bank < s->address && rom_usage[pc_bank + d] == 0 && x < s->size; pc_bank++, x++)
	  ;
	if (x == s->size) {
	  i = SUCCEEDED;
	  break;
	}
	if (pc_bank == s->address) {
	  fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes) in ROM bank %d.\n", get_file_name(s->file_id),
		  get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
	  return FAILED;
	}

	/* find the next starting address */
	f = (pc_bank + d) % s->alignment;
	if (f > 0)
	  pc_bank += s->alignment - f;
        for (; pc_bank < s->address && rom_usage[pc_bank + d] != 0; pc_bank += s->alignment)
	  ;
      }

      memory_file_id = s->file_id;
      banksize = banksizes[s->bank];
      pc_bank = f;
      pc_slot = slots[s->slot].address + pc_bank;
      pc_full = pc_bank + bankaddress[s->bank];
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
      s->address = pc_bank;
      s->output_address = pc_full;
      section_overwrite = OFF;
      for (i = 0; i < s->size; i++) {
	if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
	  return FAILED;
      }
    }
  }

  /* free & semifree sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_FREE || s->status == SECTION_STATUS_SEMIFREE) {
      pc_bank = s->address;
      d = bankaddress[s->bank];

      /* align the starting address */
      f = (pc_bank + d) % s->alignment;
      if (f > 0)
	pc_bank += s->alignment - f;

      i = FAILED;
      while (i == FAILED) {
	f = pc_bank;
	for (x = 0; pc_bank < banksizes[s->bank] && rom_usage[pc_bank + d] == 0 && x < s->size; pc_bank++, x++)
	  ;
	if (x == s->size) {
	  i = SUCCEEDED;
	  break;
	}
	if (pc_bank == banksizes[s->bank]) {
	  fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes) in ROM bank %d.\n", get_file_name(s->file_id),
		  get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
	  return FAILED;
	}

	/* find the next starting address */
	f = (pc_bank + d) % s->alignment;
	if (f > 0)
	  pc_bank += s->alignment - f;
        for (; pc_bank < banksizes[s->bank] && rom_usage[pc_bank + d] != 0; pc_bank += s->alignment)
	  ;
      }

      memory_file_id = s->file_id;
      banksize = banksizes[s->bank];
      pc_bank = f;
      pc_slot = slots[s->slot].address + pc_bank;
      pc_full = pc_bank + bankaddress[s->bank];
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
      s->address = pc_bank;
      s->output_address = pc_full;
      section_overwrite = OFF;
      for (i = 0; i < s->size; i++) {
	if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
	  return FAILED;
      }
    }
  }

  /* superfree sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_SUPERFREE) {
      /* go through all the banks */
      i = FAILED;
      f = 0;

      for (q = 0; i == FAILED && q < rombanks; q++) {
	pc_bank = 0;
	d = bankaddress[q];

	/* align the starting address */
	f = (pc_bank + d) % s->alignment;
	if (f > 0)
	  pc_bank += s->alignment - f;

	/* if the slotsize and banksize differ -> try the next bank */
	if (banksizes[q] != slots[s->slot].size)
	  continue;

	while (i == FAILED) {
	  f = pc_bank;
	  for (x = 0; pc_bank < banksizes[q] && rom_usage[pc_bank + d] == 0 && x < s->size; pc_bank++, x++)
	    ;
	  if (x == s->size) {
	    i = SUCCEEDED;
	    break;
	  }
	  if (pc_bank == banksizes[q])
	    break;

	  /* find the next starting address */
	  f = (pc_bank + d) % s->alignment;
	  if (f > 0)
	    pc_bank += s->alignment - f;
	  for (; pc_bank < banksizes[s->bank] && rom_usage[pc_bank + d] != 0; pc_bank += s->alignment)
	    ;
	}
      }

      if (i == SUCCEEDED) {
	s->bank = q-1;
	memory_file_id = s->file_id;
	banksize = banksizes[s->bank];
	pc_bank = f;
	pc_slot = pc_bank;
	pc_full = pc_bank + bankaddress[s->bank];
	pc_slot_max = slots[s->slot].size;
	s->address = pc_bank;
	s->output_address = pc_full;
	section_overwrite = OFF;

	for (i = 0; i < s->size; i++)
	  if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
	    return FAILED;
      }
      else {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes).\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
	return FAILED;
      }
    }
  }

  /* overwrite sections */
  p = 0;
  while (p < sn) {
    s = sa[p++];
    if (s->status == SECTION_STATUS_OVERWRITE) {
      memory_file_id = s->file_id;
      banksize = banksizes[s->bank];
      pc_bank = s->address;
      pc_slot = slots[s->slot].address + pc_bank;
      pc_full = pc_bank + bankaddress[s->bank];
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
      s->output_address = pc_full;
      section_overwrite = ON;
      if (pc_full + s->size > romsize) {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) goes beyond the ROM size.\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
	return FAILED;
      }
      if (s->address + s->size > banksize) {
	fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) overflows from ROM bank %d.\n", get_file_name(s->file_id),
		get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
	return FAILED;
      }
      for (i = 0; i < s->size; i++) {
	if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
	  return FAILED;
      }
    }
  }

  free(sa);

  return SUCCEEDED;
}
Пример #5
0
int fix_references(void) {

  struct reference *r;
  struct section *s = NULL;
  struct label *l, lt;
  int i, x;

  
  section_overwrite = OFF;

  /* insert references */
  r = reference_first;
  while (r != NULL) {
    x = r->address;
    /* search for the section of the reference and fix the address */
    if (r->section_status == ON) {
      s = sec_first;
      while (s != NULL) {
	if (s->id == r->section) {
	  r->bank = s->bank;
	  x += s->address;
	  r->address += s->address;
	  break;
	}
	s = s->next;
      }
      /* reference is inside a discarded section? */
      if (s != NULL && s->alive == NO) {
	r = r->next;
	continue;
      }
      if (s == NULL) {
	if (write_bank_header_references(r) == FAILED)
	  return FAILED;
	r = r->next;
	continue;
      }
    }

    if (!(r->section_status == ON && s->status == SECTION_STATUS_ABSOLUTE)) {
      x += bankaddress[r->bank];
      r->address += slots[r->slot].address;
    }

    /* find the destination */
    l = labels_first;

    /* request for bank number? */
    if (r->name[0] == ':') {
      if (is_label_anonymous(&r->name[1]) == SUCCEEDED) {
	l = get_closest_anonymous_label(&r->name[1], x, r->file_id, l, r->section_status, r->section);
      }
      else if (strcmp(&r->name[1], "CADDR") == 0 || strcmp(&r->name[1], "caddr") == 0) {
	lt.status = LABEL_STATUS_LABEL;
	strcpy(lt.name, &r->name[1]);
	lt.address = r->address;
	lt.bank = r->bank;
	lt.section_status = OFF;
	l = &lt;
      }
      else {
	while (l != NULL) {
	  if (strcmp(l->name, &r->name[1]) == 0 && l->status != LABEL_STATUS_SYMBOL && l->status != LABEL_STATUS_BREAKPOINT)
	    break;
	  l = l->next;
	}
      }

      if (l == NULL) {
	fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Bank number request for an unknown label \"%s\".\n",
		get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, &r->name[1]);
	return FAILED;
      }

      if (cpu_65816 != 0)
	i = get_snes_pc_bank(l) >> 16;
      else
	i = l->bank;

      memory_file_id = r->file_id;
      memory_file_id_source = r->file_id_source;
      memory_line_number = r->linenumber;

      /* direct 16bit */
      if (r->type == REFERENCE_TYPE_DIRECT_16BIT || r->type == REFERENCE_TYPE_RELATIVE_16BIT) {
	mem_insert_ref(x, i & 0xFF);
	mem_insert_ref(x + 1, (i >> 8) & 0xFF);
      }
      /* direct / relative 8bit with a definition */
      else if (l->status == LABEL_STATUS_DEFINE) {
Пример #6
0
      else
	i = l->bank;

      memory_file_id = r->file_id;
      memory_file_id_source = r->file_id_source;
      memory_line_number = r->linenumber;

      /* direct 16bit */
      if (r->type == REFERENCE_TYPE_DIRECT_16BIT || r->type == REFERENCE_TYPE_RELATIVE_16BIT) {
	mem_insert_ref(x, i & 0xFF);
	mem_insert_ref(x + 1, (i >> 8) & 0xFF);
      }
      /* direct / relative 8bit with a definition */
      else if (l->status == LABEL_STATUS_DEFINE) {
	fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Bank number request for a definition \"%s\"?\n",
		get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, l->name);
	return FAILED;
      }
      /* direct 24bit */
      else if (r->type == REFERENCE_TYPE_DIRECT_24BIT) {
	mem_insert_ref(x, i & 0xFF);
	mem_insert_ref(x + 1, (i >> 8) & 0xFF);
	mem_insert_ref(x + 2, (i >> 16) & 0xFF);
      }
      /* relative/direct 8bit with a label */
      else {
	mem_insert_ref(x, i & 0xFF);
      }
    }
    /* normal reference */
    else {