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

  int i, x, n, m, l, o;

  if (snes_rom_mode == SNES_ROM_MODE_LOROM) {
    if (romsize < 0x8000) {
      fprintf(stderr, "COMPUTE_SNES_CHECKSUM: SNES checksum computing for a LoROM image requires a ROM of at least 32KB.\n");
      return FAILED;
    }
  }
  else {
    if (romsize < 0x10000) {
      fprintf(stderr, "COMPUTE_SNES_CHECKSUM: SNES checksum computing for a HiROM image requires a ROM of at least 64KB.\n");
      return FAILED;
    }
  }

  /* n = data inside 4mbit blocks, m = data outside that */
  if (romsize < 512*1024) {
    n = romsize;
    m = 0;
  }
  else {
    n = (romsize/(512*1024))*512*1024;
    m = romsize - n;
  }

  /* sum all the bytes inside the 4mbit blocks */
  x = 0;
  for (i = 0; i < n; i++) {
    if (snes_rom_mode == SNES_ROM_MODE_LOROM) {
      /* skip the checksum bytes */
      if (!(i == 0x7FDC || i == 0x7FDD || i == 0x7FDE || i == 0x7FDF))
	x += rom[i];
    }
    else {
      /* skip the checksum bytes */
      if (!(i == 0xFFDC || i == 0xFFDD || i == 0xFFDE || i == 0xFFDF))
	x += rom[i];
    }
  }

  /* add to that the data outside the 4mbit blocks, ringbuffer style repeating 
     the remaining block until the the final part reaches 4mbits */
  for (o = 0, l = i; i < romsize; i++, o++)
    x += rom[(o % m) + l];

  /* 2*255 is for the checksum and its complement bytes that we skipped earlier */
  x += 2*255;

  /* compute the inverse checksum */
  l = (x & 0xFFFF) ^ 0xFFFF;

  /* insert the checksum bytes */
  if (snes_rom_mode == SNES_ROM_MODE_LOROM) {
    mem_insert(0x7FDC, l & 0xFF);
    mem_insert(0x7FDD, (l >> 8) & 0xFF);
    mem_insert(0x7FDE, x & 0xFF);
    mem_insert(0x7FDF, (x >> 8) & 0xFF);
  }
Пример #2
0
int mem_insert_allow_overwrite(int address, unsigned char data, unsigned int allowed_overwrites) {

  if (rom_usage[address] > allowed_overwrites)
    return mem_insert(address, data);

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

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

  int i, x;

  if (romsize < 0x8000) {
    fprintf(stderr, "COMPUTE_GB_COMPLEMENT_CHECK: GB complement check computing requires a ROM of at least 32KB.\n");
    return FAILED;
  }

  i = 0;
  for (x = 0x134; x <= 0x14C; x++)
    i += rom[x];
  i += 25;
  mem_insert(0x14D, 0 - (i & 0xFF));

  return SUCCEEDED;
}
Пример #4
0
/*!
 * \brief Insert string into string
 *
 * Insert \p s into \p *str. It the function succeeds. \p *str will be passed to
 * `free()` and \p *str will be updated to point to the newly allocated string.
 * If the function fails, \p *str will be left unchanged.
 *
 * \param[in,out] str Pointer to string to modify
 * \param[in] pos Position in which to insert new string
 *                (0 \<= \p pos \<= \p *mem_size)
 * \param[in] s New string to insert
 *
 * \return Nothing if successful. Otherwise, the error code.
 */
oc::result<void> str_insert(char **str, size_t pos, const char *s)
{
    size_t str_size;

    str_size = strlen(*str);

    if (pos > str_size) {
        return std::make_error_code(std::errc::invalid_argument);
    } else if (str_size == SIZE_MAX) {
        return std::make_error_code(std::errc::value_too_large);
    }

    ++str_size;

    return mem_insert(reinterpret_cast<void **>(str), &str_size, pos,
                      s, strlen(s));
}
Пример #5
0
int compute_gb_checksum(void) {

  int i, x;

  if (romsize < 0x8000) {
    fprintf(stderr, "COMPUTE_GB_CHECKSUM: GB checksum computing requires a ROM of at least 32KB.\n");
    return FAILED;
  }

  i = 0;
  for (x = 0; x < 0x14E; x++)
    i += rom[x];
  for (x = 0x150; x < romsize; x++)
    i += rom[x];

  mem_insert(0x14E, (i >> 8) & 0xFF);
  mem_insert(0x14F, i & 0xFF);

  return SUCCEEDED;
}
Пример #6
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;
}