Esempio n. 1
0
enum media_type_e PicoLoadMedia(const char *filename,
  const char *carthw_cfg_fname,
  const char *(*get_bios_filename)(int *region, const char *cd_fname),
  void (*do_region_override)(const char *media_filename))
{
  const char *rom_fname = filename;
  enum media_type_e media_type;
  enum cd_img_type cd_img_type = CIT_NOT_CD;
  unsigned char *rom_data = NULL;
  unsigned int rom_size = 0;
  pm_file *rom = NULL;
  int cd_region = 0;
  int ret;

  media_type = detect_media(filename);
  if (media_type == PM_BAD_DETECT)
    goto out;

  if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL)
    cdd_unload();
  PicoCartUnload();
  PicoAHW = 0;
  PicoQuirks = 0;

  if (media_type == PM_CD)
  {
    // check for MegaCD image
    cd_img_type = PicoCdCheck(filename, &cd_region);
    if ((int)cd_img_type >= 0 && cd_img_type != CIT_NOT_CD)
    {
      // valid CD image, ask frontend for BIOS..
      rom_fname = NULL;
      if (get_bios_filename != NULL)
        rom_fname = get_bios_filename(&cd_region, filename);
      if (rom_fname == NULL) {
        media_type = PM_BAD_CD_NO_BIOS;
        goto out;
      }

      PicoAHW |= PAHW_MCD;
    }
    else {
      media_type = PM_BAD_CD;
      goto out;
    }
  }
  else if (media_type == PM_MARK3) {
    lprintf("detected SMS ROM\n");
    PicoAHW = PAHW_SMS;
  }

  rom = pm_open(rom_fname);
  if (rom == NULL) {
    lprintf("Failed to open ROM\n");
    media_type = PM_ERROR;
    goto out;
  }

  ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoAHW & PAHW_SMS) ? 1 : 0);
  pm_close(rom);
  if (ret != 0) {
    if      (ret == 2) lprintf("Out of memory\n");
    else if (ret == 3) lprintf("Read failed\n");
    else               lprintf("PicoCartLoad() failed.\n");
    media_type = PM_ERROR;
    goto out;
  }

  // detect wrong files
  if (strncmp((char *)rom_data, "Pico", 4) == 0) {
    lprintf("savestate selected?\n");
    media_type = PM_BAD_DETECT;
    goto out;
  }

  if (!(PicoAHW & PAHW_SMS)) {
    unsigned short *d = (unsigned short *)(rom_data + 4);
    if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) {
      lprintf("bad reset vector\n");
      media_type = PM_BAD_DETECT;
      goto out;
    }
  }

  // load config for this ROM (do this before insert to get correct region)
  if (!(PicoAHW & PAHW_MCD)) {
    memcpy(media_id_header, rom_data + 0x100, sizeof(media_id_header));
    if (do_region_override != NULL)
      do_region_override(filename);
  }

  if (PicoCartInsert(rom_data, rom_size, carthw_cfg_fname)) {
    media_type = PM_ERROR;
    goto out;
  }
  rom_data = NULL; // now belongs to PicoCart
  Pico.m.ncart_in = 0;

  // insert CD if it was detected
  if (cd_img_type != CIT_NOT_CD) {
    ret = cdd_load(filename, cd_img_type);
    if (ret != 0) {
      PicoCartUnload();
      media_type = PM_BAD_CD;
      goto out;
    }
    Pico.m.ncart_in = 1;
  }

  if (PicoQuirks & PQUIRK_FORCE_6BTN)
    PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN);

out:
  if (rom_data)
    free(rom_data);
  return media_type;
}
Esempio n. 2
0
int cdd_load(const char *filename, int type)
{
  char header[0x210];
  int ret;

  /* first unmount any loaded disc */
  cdd_unload();

  /* genplus parses cue here, in PD we use our own parser */
  ret = load_cd_image(filename, &type);
  if (ret != 0)
    return ret;

  /* read first 16 bytes */
  pm_read(header, 0x10, cdd.toc.tracks[0].fd);

  /* look for valid CD image ID string */
  if (memcmp("SEGADISCSYSTEM", header, 14))
  {    
    /* if not found, read next 16 bytes */
    pm_read(header, 0x10, cdd.toc.tracks[0].fd);

    /* look again for valid CD image ID string */
    if (memcmp("SEGADISCSYSTEM", header, 14))
    {
      elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
      /* assume bin without security code */
    }

    /* BIN format (2352 bytes data blocks) */
    cdd.sectorSize = 2352;
  }
  else
  {
    /* ISO format (2048 bytes data blocks) */
    cdd.sectorSize = 2048;
  }

  ret = (type == CT_BIN) ? 2352 : 2048;
  if (ret != cdd.sectorSize)
    elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");

  /* read CD image header + security code */
  pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);

  /* Simulate audio tracks if none found */
  if (cdd.toc.last == 1)
  {
    /* Some games require exact TOC infos */
    if (strstr(header + 0x180,"T-95035") != NULL)
    {
      /* Snatcher */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 21);
    }
    else if (strstr(header + 0x180,"T-127015") != NULL)
    {
      /* Lunar - The Silver Star */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 52);
    }
    else if (strstr(header + 0x180,"T-113045") != NULL)
    {
      /* Shadow of the Beast II */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 15);
    }
    else if (strstr(header + 0x180,"T-143025") != NULL)
    {
      /* Dungeon Explorer */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 13);
    }
    else if (strstr(header + 0x180,"MK-4410") != NULL)
    {
      /* Final Fight CD (USA, Europe) */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 26);
    }
    else if (strstr(header + 0x180,"G-6013") != NULL)
    {
      /* Final Fight CD (Japan) */
      cdd.toc.last = cdd.toc.end = 0;
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while (cdd.toc.last < 29);
    }
#if 0
    else
    {
      /* default TOC (99 tracks & 2s per audio tracks) */
      do
      {
        cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
        cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
        cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
        cdd.toc.last++;
      }
      while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
    }
#endif
  }

  /* Lead-out */
  cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;

  /* CD loaded */
  cdd.loaded = 1;

  /* disc not scanned yet */
  cdd.status = NO_DISC;

  return 0;
}