示例#1
0
文件: cdd.c 项目: libretro/picodrive
void cdd_read_data(uint8 *dst)
{
  /* only read DATA track sectors */
  if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
  {
    /* BIN format ? */
    if (cdd.sectorSize == 2352)
    {
      /* skip 16-byte header */
      pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
    }

    /* read sector data (Mode 1 = 2048 bytes) */
    pm_read(dst, 2048, cdd.toc.tracks[0].fd);
  }
}
示例#2
0
/* checks if romFileName points to valid MegaCD image
 * if so, checks for suitable BIOS */
int emu_cdCheck(int *pregion)
{
	unsigned char buf[32];
	pm_file *cd_f;
	int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe

	cd_f = pm_open(romFileName);
	if (!cd_f) return 0; // let the upper level handle this

	if (pm_read(buf, 32, cd_f) != 32) {
		pm_close(cd_f);
		return 0;
	}

	if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1;       // Sega CD (ISO)
	if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2;       // Sega CD (BIN)
	if (type == 0) {
		pm_close(cd_f);
		return 0;
	}

	/* it seems we have a CD image here. Try to detect region now.. */
	pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET);
	pm_read(buf, 1, cd_f);
	pm_close(cd_f);

	if (buf[0] == 0x64) region = 8; // EU
	if (buf[0] == 0xa1) region = 1; // JAP

	lprintf("detected %s Sega/Mega CD image with %s region\n",
		type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA");

	if (pregion != NULL) *pregion = region;

	return type;
}
示例#3
0
static int detect_media(const char *fname)
{
  static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 };
  static const char *sms_exts[] = { "sms", "gg", "sg" };
  static const char *md_exts[] = { "gen", "bin", "smd" };
  char buff0[32], buff[32];
  unsigned short *d16;
  pm_file *pmf;
  char ext[5];
  int i;

  get_ext(fname, ext);

  // detect wrong extensions
  if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) // s.gz ~ .mds.gz
    return PM_BAD_DETECT;

  /* don't believe in extensions, except .cue */
  if (strcasecmp(ext, ".cue") == 0)
    return PM_CD;

  pmf = pm_open(fname);
  if (pmf == NULL)
    return PM_BAD_DETECT;

  if (pm_read(buff0, 32, pmf) != 32) {
    pm_close(pmf);
    return PM_BAD_DETECT;
  }

  if (strncasecmp("SEGADISCSYSTEM", buff0 + 0x00, 14) == 0 ||
      strncasecmp("SEGADISCSYSTEM", buff0 + 0x10, 14) == 0) {
    pm_close(pmf);
    return PM_CD;
  }

  /* check for SMD evil */
  if (pmf->size >= 0x4200 && (pmf->size & 0x3fff) == 0x200) {
    if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200 &&
        pm_read(buff, 16, pmf) == 16 &&
        strncmp("TMR SEGA", buff, 8) == 0)
      goto looks_like_sms;

    /* could parse further but don't bother */
    goto extension_check;
  }

  /* MD header? Act as TMSS BIOS here */
  if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100 && pm_read(buff, 16, pmf) == 16) {
    if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0)
      goto looks_like_md;
  }

  for (i = 0; i < ARRAY_SIZE(sms_offsets); i++) {
    if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i])
      continue;

    if (pm_read(buff, 16, pmf) != 16)
      continue;

    if (strncmp("TMR SEGA", buff, 8) == 0)
      goto looks_like_sms;
  }

extension_check:
  /* probably some headerless thing. Maybe check the extension after all. */
  for (i = 0; i < ARRAY_SIZE(md_exts); i++)
    if (strcasecmp(pmf->ext, md_exts[i]) == 0)
      goto looks_like_md;

  for (i = 0; i < ARRAY_SIZE(sms_exts); i++)
    if (strcasecmp(pmf->ext, sms_exts[i]) == 0)
      goto looks_like_sms;

  /* If everything else fails, make a guess on the reset vector */
  d16 = (unsigned short *)(buff0 + 4);
  if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= pmf->size) {
    lprintf("bad MD reset vector, assuming SMS\n");
    goto looks_like_sms;
  }

looks_like_md:
  pm_close(pmf);
  return PM_MD_CART;

looks_like_sms:
  pm_close(pmf);
  return PM_MARK3;
}
示例#4
0
/* checks if fname points to valid MegaCD image */
int PicoCdCheck(const char *fname_in, int *pregion)
{
  const char *fname = fname_in;
  unsigned char buf[32];
  pm_file *cd_f;
  int region = 4; // 1: Japan, 4: US, 8: Europe
  char ext[5];
  cue_track_type type = CT_UNKNOWN;
  cue_data_t *cue_data = NULL;

  // opens a cue, or searches for one
  cue_data = cue_parse(fname_in);
  if (cue_data != NULL) {
    fname = cue_data->tracks[1].fname;
    type  = cue_data->tracks[1].type;
  }
  else {
    get_ext(fname_in, ext);
    if (strcasecmp(ext, ".cue") == 0)
      return -1;
  }

  cd_f = pm_open(fname);
  if (cue_data != NULL)
    cue_destroy(cue_data);

  if (cd_f == NULL) return 0; // let the upper level handle this

  if (pm_read(buf, 32, cd_f) != 32) {
    pm_close(cd_f);
    return -1;
  }

  if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) {
    if (type && type != CT_ISO)
      elprintf(EL_STATUS, ".cue has wrong type: %i", type);
    type = CT_ISO;       // Sega CD (ISO)
  }
  if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) {
    if (type && type != CT_BIN)
      elprintf(EL_STATUS, ".cue has wrong type: %i", type);
    type = CT_BIN;       // Sega CD (BIN)
  }

  if (type == CT_UNKNOWN) {
    pm_close(cd_f);
    return 0;
  }

  pm_seek(cd_f, (type == CT_ISO) ? 0x100 : 0x110, SEEK_SET);
  pm_read(media_id_header, sizeof(media_id_header), cd_f);

  /* it seems we have a CD image here. Try to detect region now.. */
  pm_seek(cd_f, (type == CT_ISO) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET);
  pm_read(buf, 1, cd_f);
  pm_close(cd_f);

  if (buf[0] == 0x64) region = 8; // EU
  if (buf[0] == 0xa1) region = 1; // JAP

  lprintf("detected %s Sega/Mega CD image with %s region\n",
    type == CT_BIN ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA");

  if (pregion != NULL)
    *pregion = region;

  return type;
}
示例#5
0
文件: cdd.c 项目: libretro/picodrive
int cdd_context_load(uint8 *state)
{
  int lba;
  int bufferptr = 0;

#ifdef USE_LIBTREMOR
#ifdef DISABLE_MANY_OGG_OPEN_FILES
  /* close previous track VORBIS file structure to save memory */
  if (cdd.toc.tracks[cdd.index].vf.datasource)
  {
    ogg_free(cdd.index);
  }
#endif
#endif

  load_param(&cdd.cycles, sizeof(cdd.cycles));
  load_param(&cdd.latency, sizeof(cdd.latency));
  load_param(&cdd.index, sizeof(cdd.index));
  load_param(&cdd.lba, sizeof(cdd.lba));
  load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
  load_param(&cdd.volume, sizeof(cdd.volume));
  load_param(&cdd.status, sizeof(cdd.status));

  /* adjust current LBA within track limit */
  lba = cdd.lba;
  if (lba < cdd.toc.tracks[cdd.index].start)
  {
    lba = cdd.toc.tracks[cdd.index].start;
  }

  /* seek to current track position */
  if (!cdd.index)
  {
    /* DATA track */
    if (cdd.toc.tracks[0].fd)
    {
      pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
    }
  }
#ifdef USE_LIBTREMOR
  else if (cdd.toc.tracks[cdd.index].vf.seekable)
  {
#ifdef DISABLE_MANY_OGG_OPEN_FILES
    /* VORBIS file need to be opened first */
    ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
#endif
    /* VORBIS AUDIO track */
    ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
  }
#endif
#if 0
  else if (cdd.toc.tracks[cdd.index].fd)
  {
    /* PCM AUDIO track */
    fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  }
#else
  else
  {
    cdd_change_track(cdd.index, lba);
  }
#endif

  return bufferptr;
}
示例#6
0
/* this is was a try to fight slow SD access of GP2X */
PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
{
	int is_bin, offs, read_len, moved = 0;
	reads++;

	is_bin = Pico_mcd->TOC.Tracks[0].ftype == CT_BIN;

	if (PicoCDBuffers <= 0)
	{
		/* no buffering */
		int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
		pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
		pm_read(dest, 2048, Pico_mcd->TOC.Tracks[0].F);
		return;
	}

	/* hit? */
	offs = lba - prev_lba;
	if (offs >= 0 && offs < PicoCDBuffers)
	{
		hits++;
		if (offs == 0) dprintf("CD buffer seek to old %i -> %i\n", prev_lba, lba);
		memcpy32(dest, (int *)(cd_buffer + offs*2048), 2048/4);
		return;
	}

	if (prev_lba + PicoCDBuffers != lba)
	{
		int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
		dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
		pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
	}

	dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);

	if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
	{
		read_len = prev_lba - lba;
		dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
		memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
		moved = 1;
	}
	else
	{
		read_len = PicoCDBuffers;
	}

	if (PicoMessage != NULL && read_len >= 512)
	{
		PicoMessage("Buffering data...");
	}

	if (is_bin)
	{
		int i = 0;
#ifdef _PSP_FW_VERSION
		int bufs = (read_len*2048) / (2048+304);
		pm_read(cd_buffer, bufs*(2048+304), Pico_mcd->TOC.Tracks[0].F);
		for (i = 1; i < bufs; i++)
			// should really use memmove here, but my memcpy32 implementation is also suitable here
			memcpy32((int *)(cd_buffer + i*2048), (int *)(cd_buffer + i*(2048+304)), 2048/4);
#endif
		for (; i < read_len - 1; i++)
		{
			pm_read(cd_buffer + i*2048, 2048 + 304, Pico_mcd->TOC.Tracks[0].F);
			// pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR); // seeking is slower, in PSP case even more
		}
		// further data might be moved, do not overwrite
		pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
		pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
	}
	else
	{
		pm_read(cd_buffer, read_len*2048, Pico_mcd->TOC.Tracks[0].F);
	}
	memcpy32(dest, (int *) cd_buffer, 2048/4);
	prev_lba = lba;

	if (moved)
	{
		/* file pointer must point to the same data in file, as would-be data after our buffer */
		int where_seek;
		lba += PicoCDBuffers;
		where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
		pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
	}
}