ssize_t multi_read(void *buf, size_t count) { ssize_t size; int i; struct mfile *file; struct cdrom_msf* cdbuf = buf; file = &files[curFile]; if (curFile == numfiles) { #ifdef __DVD_DEBUG print_info("last file read.\n"); #endif return 0; } if(file->lba >= 0) { int frame = current_lba; lba_to_msf(frame, &cdbuf->cdmsf_min0, &cdbuf->cdmsf_sec0, &cdbuf->cdmsf_frame0); frame = current_lba + count; lba_to_msf(frame, &cdbuf->cdmsf_min0, &cdbuf->cdmsf_sec0, &cdbuf->cdmsf_frame1); size = ioctl(file->fd, CDROMREADMODE2, &cdbuf); current_lba += size; } else size = read(file->fd, buf, count); if (size == -1) { #ifdef __DVD_DEBUG print_info("invalid read.\n"); #endif return -1; } if (size < count) { #ifdef __DVD_DEBUG print_info("finished file %s.\n", files[curFile].name); #endif if( ++curFile >= numfiles) return size; #ifdef __DVD_DEBUG print_info("continuing with file %s.\n", files[curFile].name); #endif current_lba = files[curFile].lba; if(files[curFile].lba >= 0) { int frame = current_lba; lba_to_msf(frame, &cdbuf->cdmsf_min0, &cdbuf->cdmsf_sec0, &cdbuf->cdmsf_frame0); frame = current_lba + count-size; lba_to_msf(frame, &cdbuf->cdmsf_min0, &cdbuf->cdmsf_sec0, &cdbuf->cdmsf_frame1); size += ioctl(files[curFile].fd, CDROMREADMODE2, &cdbuf); current_lba += size; } else size += read(files[curFile].fd, buf + size, count - size); } return size; }
static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single) { uint8_t *q; int len; if (start_track > 1 && start_track != 0xaa) return -1; q = buf + 2; *q++ = 1; /* first session */ *q++ = 1; /* last session */ if (start_track <= 1) { *q++ = 0; /* reserved */ *q++ = 0x14; /* ADR, control */ *q++ = 1; /* track number */ *q++ = 0; /* reserved */ if (msf) { *q++ = 0; /* reserved */ lba_to_msf(q, 0); q += 3; } else { /* sector 0 */ *q++ = 0; *q++ = 0; *q++ = 0; *q++ = 0; } } /* lead out track */ *q++ = 0; /* reserved */ *q++ = 0x16; /* ADR, control */ *q++ = 0xaa; /* track number */ *q++ = 0; /* reserved */ last_block = image_size >> 11; if (msf) { *q++ = 0; /* reserved */ lba_to_msf(q, last_block); q += 3; } else { *q++ = last_block >> 24; *q++ = last_block >> 16; *q++ = last_block >> 8; *q++ = last_block; } len = q - buf; buf[0] = (uint8_t)(((len-2) >> 8) & 0xff); buf[1] = (uint8_t)((len-2) & 0xff); return len; }
static void iso_readsector_raw(uint8_t *b, int sector) { uint32_t temp; if (!cdrom_drive) return; fseek(iso_image, sector*2048, SEEK_SET); fread(b+16, 2048, 1, iso_image); /* sync bytes */ b[0] = 0; memset(b + 1, 0xff, 10); b[11] = 0; b += 12; lba_to_msf(b, sector); b[3] = 1; /* mode 1 data */ b += 4; b += 2048; memset(b, 0, 288); }
static int iso_readtoc_raw(unsigned char *buf, int maxlen) { uint8_t *q; int len; q = buf + 2; *q++ = 1; /* first session */ *q++ = 1; /* last session */ *q++ = 1; /* session number */ *q++ = 0x14; /* data track */ *q++ = 0; /* track number */ *q++ = 0xa0; /* lead-in */ *q++ = 0; /* min */ *q++ = 0; /* sec */ *q++ = 0; /* frame */ *q++ = 0; *q++ = 1; /* first track */ *q++ = 0x00; /* disk type */ *q++ = 0x00; *q++ = 1; /* session number */ *q++ = 0x14; /* data track */ *q++ = 0; /* track number */ *q++ = 0xa1; *q++ = 0; /* min */ *q++ = 0; /* sec */ *q++ = 0; /* frame */ *q++ = 0; *q++ = 1; /* last track */ *q++ = 0x00; *q++ = 0x00; *q++ = 1; /* session number */ *q++ = 0x14; /* data track */ *q++ = 0; /* track number */ *q++ = 0xa2; /* lead-out */ *q++ = 0; /* min */ *q++ = 0; /* sec */ *q++ = 0; /* frame */ last_block = image_size >> 11; /* this is raw, must be msf */ *q++ = 0; /* reserved */ lba_to_msf(q, last_block); q += 3; *q++ = 1; /* session number */ *q++ = 0x14; /* ADR, control */ *q++ = 0; /* track number */ *q++ = 1; /* point */ *q++ = 0; /* min */ *q++ = 0; /* sec */ *q++ = 0; /* frame */ /* same here */ *q++ = 0; *q++ = 0; *q++ = 0; *q++ = 0; len = q - buf; buf[0] = (uint8_t)(((len-2) >> 8) & 0xff); buf[1] = (uint8_t)((len-2) & 0xff); return len; }
UINT32 cdrom_read_data(cdrom_file *file, UINT32 lbasector, void *buffer, UINT32 datatype) { UINT32 tracktype, tracknum, sectoroffs; chd_error err; static const UINT8 syncbytes[12] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; if (file == NULL) return 0; /* cache in the sector */ err = read_sector_into_cache(file, lbasector, §oroffs, &tracknum); if (err != CHDERR_NONE) return 0; /* copy out the requested sector */ tracktype = file->cdtoc.tracks[tracknum].trktype; if ((datatype == tracktype) || (datatype == CD_TRACK_RAW_DONTCARE)) { memcpy(buffer, &file->cache[sectoroffs * CD_FRAME_SIZE], file->cdtoc.tracks[tracknum].datasize); } else { /* return 2048 bytes of mode 1 data from a 2352 byte mode 1 raw sector */ if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE1_RAW)) { memcpy(buffer, &file->cache[(sectoroffs * CD_FRAME_SIZE) + 16], 2048); return 1; } /* return 2352 byte mode 1 raw sector from 2048 bytes of mode 1 data */ if ((datatype == CD_TRACK_MODE1_RAW) && (tracktype == CD_TRACK_MODE1)) { UINT8 *bufptr = (UINT8 *)buffer; UINT32 msf = lba_to_msf(lbasector); memcpy(bufptr, syncbytes, 12); bufptr[12] = msf>>16; bufptr[13] = msf>>8; bufptr[14] = msf&0xff; bufptr[15] = 1; // mode 1 memcpy(bufptr+16, &file->cache[(sectoroffs * CD_FRAME_SIZE)], 2048); LOG(("CDROM: promotion of mode1/form1 sector to mode1 raw is not complete!\n")); return 1; } /* return 2048 bytes of mode 1 data from a mode2 form1 or raw sector */ if ((datatype == CD_TRACK_MODE1) && ((tracktype == CD_TRACK_MODE2_FORM1)||(tracktype == CD_TRACK_MODE2_RAW))) { memcpy(buffer, &file->cache[(sectoroffs * CD_FRAME_SIZE) + 24], 2048); return 1; } /* return mode 2 2336 byte data from a 2352 byte mode 1 or 2 raw sector (skip the header) */ if ((datatype == CD_TRACK_MODE2) && ((tracktype == CD_TRACK_MODE1_RAW) || (tracktype == CD_TRACK_MODE2_RAW))) { memcpy(buffer, &file->cache[(sectoroffs * CD_FRAME_SIZE) + 16], 2336); return 1; } LOG(("CDROM: Conversion from type %d to type %d not supported!\n", tracktype, datatype)); return 0; }
int cueify_device_read_track_indices(cueify_device *d, cueify_indices *i, uint8_t track) { cueify_device_private *dev = (cueify_device_private *)d; cueify_indices_private *indices = (cueify_indices_private *)i; cueify_full_toc_private toc; if (cueify_device_read_full_toc_unportable(dev, &toc) != CUEIFY_OK) { return CUEIFY_ERR_INTERNAL; } if ((track >= toc.first_track_number && track <= toc.last_track_number) || track == CUEIFY_LEAD_OUT_TRACK) { /* First, see if there appears to be more than one index. */ cueify_msf_t msf; cueify_position_t pos; int lba, first_lba, left_lba, right_lba, last_lba; int index; first_lba = left_lba = msf_to_lba(toc.tracks[track].offset); if (track == toc.sessions[toc.tracks[track].session].last_track_number) { last_lba = right_lba = msf_to_lba(toc.sessions[toc.tracks[track].session].leadout); } else { last_lba = right_lba = msf_to_lba(toc.tracks[track + 1].offset); } /* Get the index of the penultimate second of the track. */ lba = last_lba - 1; if (lba < left_lba) { lba = (left_lba + last_lba) / 2; } /* And the MSF of the first. */ lba_to_msf(first_lba, &msf); if (cueify_device_read_position_unportable( dev, track, lba, &pos) != CUEIFY_OK) { return CUEIFY_ERR_INTERNAL; } if (pos.track == track && pos.index != 1) { indices->num_indices = pos.index; indices->has_pregap = 0; indices->indices = calloc(indices->num_indices, sizeof(cueify_msf_t)); if (indices->indices == NULL) { return CUEIFY_ERR_INTERNAL; } indices->indices[0] = msf; } else if (pos.track == track + 1) { indices->num_indices = 2; indices->has_pregap = 1; indices->indices = calloc(indices->num_indices, sizeof(cueify_msf_t)); if (indices->indices == NULL) { return CUEIFY_ERR_INTERNAL; } indices->indices[0] = msf; /* Detect the pre-gap. */ while (left_lba != right_lba) { lba = (left_lba + right_lba) / 2; if (cueify_device_read_position_unportable( dev, track, lba, &pos) != CUEIFY_OK) { free(indices->indices); indices->indices = NULL; return CUEIFY_ERR_INTERNAL; } if (pos.track == track) { /* Choose the right half. */ left_lba = lba + 1; } else { /* Choose the left half. */ right_lba = lba; } } /* Found the start address. */ lba_to_msf(left_lba, &msf); indices->indices[1] = msf; /* Reset the right and left sides. */ last_lba = right_lba = lba; left_lba = first_lba; /* And calculate the TRUE index count. */ lba = last_lba - 1; if (lba < left_lba) { lba = (left_lba + last_lba) / 2; } if (cueify_device_read_position_unportable( dev, track, lba, &pos) != CUEIFY_OK) { free(indices->indices); indices->indices = NULL; return CUEIFY_ERR_INTERNAL; } if (pos.track == track && pos.index != 1) { indices->num_indices = pos.index + 1; indices->indices = realloc(indices->indices, indices->num_indices * sizeof(cueify_msf_t)); if (indices->indices == NULL) { return CUEIFY_ERR_INTERNAL; } /* TODO: Test me. */ /* Copy the pre-gap indices over. */ memcpy(&(indices->indices[indices->num_indices]), &(indices->indices[1]), sizeof(cueify_msf_t)); } else { /* That's it. */ return CUEIFY_OK; } } else { indices->num_indices = 1; indices->has_pregap = 0; indices->indices = calloc(1, sizeof(cueify_msf_t)); if (indices->indices == NULL) { return 0; } indices->indices[0] = msf; return CUEIFY_OK; } for (index = 1; index < indices->num_indices; index++) { /* Detect the given index by binary search. */ while (left_lba != right_lba) { lba = (left_lba + right_lba) / 2; if (cueify_device_read_position_unportable( dev, track, lba, &pos) != CUEIFY_OK) { free(indices->indices); indices->indices = NULL; return CUEIFY_ERR_INTERNAL; } if (pos.index >= index + 1) { /* Choose the left half. */ right_lba = lba; } else { /* Choose the right half. */ left_lba = lba + 1; } } /* Found the start address. */ lba_to_msf(left_lba, &msf); indices->indices[index] = msf; /* Reset the right side. */ right_lba = last_lba; } return CUEIFY_OK; } else { return CUEIFY_ERR_INTERNAL; } } /* cueify_device_read_track_indices */
int main (int argc, const char *argv[]) { VcdMpegSource *src; unsigned packets, packet_no; VcdMpegStreamCtx ctx; if (argc != 2) return 1; src = vcd_mpeg_source_new (vcd_data_source_new_stdio (argv[1])); vcd_mpeg_source_scan (src, true, true, NULL, NULL); packets = vcd_mpeg_source_get_info (src)->packets; printf ("packets: %d\n", packets); memset (&ctx, 0, sizeof (ctx)); ctx.stream.scan_data_warnings = VCD_MPEG_SCAN_DATA_WARNS + 1; printf ("cur_ofs (lba) aps prev_ofs next_ofs back_ofs forw_ofs\n"); for (packet_no = 0; packet_no < packets; packet_no++) { /* struct vcd_mpeg_packet_flags pkt_flags; */ char buf[2324]; vcd_mpeg_source_get_packet (src, packet_no, buf, /* &pkt_flags */ NULL, false); vcd_mpeg_parse_packet (&buf, 2324, true, &ctx); if (ctx.packet.scan_data_ptr) { struct vcd_mpeg_scan_data_t *sd = ctx.packet.scan_data_ptr; msf_t _msf; lba_to_msf (packet_no, &_msf); printf ("%.2x:%.2x.%.2x (%4d) %d ", _msf.m, _msf.s, _msf.f, packet_no, ctx.packet.aps); _dump_msf (&sd->prev_ofs); _dump_msf (&sd->next_ofs); _dump_msf (&sd->back_ofs); _dump_msf (&sd->forw_ofs); printf ("\n"); } } { const struct vcd_mpeg_stream_info *_info = vcd_mpeg_source_get_info (src); printf ("mpeg info\n"); printf (" %d x %d (%f:1) @%f v%d\n", _info->shdr[0].hsize, _info->shdr[0].vsize, _info->shdr[0].aratio, _info->shdr[0].frate, _info->version); } vcd_mpeg_source_destroy (src, true); return 0; }