// this only supports 2048 byte sectors static int command_read (int unitnum, uae_u8 *data, int sector, int numsectors) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; struct cdtoc *t = findtoc (cdu, §or); if (!t) return 0; cdda_stop (cdu); if (t->size == 2048) { while (numsectors-- > 0) { do_read (cdu, t, data, sector, 0, 2048); data += 2048; sector++; } } else { while (numsectors-- > 0) { if (t->size == 2352) { uae_u8 b = 0; do_read (cdu, t, &b, sector, 15, 1); // 2 = MODE2 do_read (cdu, t, data, sector, b == 2 ? 24 : 16, 2048); } else { do_read (cdu, t, data, sector, 16, 2048); } data += 2048; sector++; } } cdu->cd_last_pos = sector; return 1; }
/* play CD audio */ static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; ciw->cdda_play_finished = 0; ciw->cdda_subfunc = subfunc; ciw->cdda_statusfunc = statusfunc; ciw->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); ciw->cdda_delay = setstate (ciw, -1); ciw->cdda_delay_frames = setstate (ciw, -2); setstate (ciw, AUDIO_STATUS_NOT_SUPPORTED); if (!open_createfile (ciw, 0)) { setstate (ciw, AUDIO_STATUS_PLAY_ERROR); return 0; } if (!isaudiotrack (&ciw->di.toc, startlsn)) { setstate (ciw, AUDIO_STATUS_PLAY_ERROR); return 0; } if (!ciw->cdda_play) { uae_start_thread (_T("ioctl_cdda_play"), cdda_play, ciw, NULL); } ciw->cdda_start = startlsn; ciw->cdda_end = endlsn; ciw->cd_last_pos = ciw->cdda_start; ciw->cdda_play++; return 1; }
static int command_stop (int unitnum) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; cdda_stop (cdu); return 1; }
static void close_scsi_device (int unitnum) { struct dev_info_spti *di = unitisopen (unitnum); if (!di) return; close_scsi_device2 (di); blkdev_cd_change (unitnum, di->drvletter ? di->drvlettername : di->name); unittable[unitnum] = 0; }
static int command_pause (int unitnum, int paused) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return -1; int old = cdu->cdda_paused; if ((paused && cdu->cdda_play) || !paused) cdu->cdda_paused = paused; return old; }
static uae_u8 *execscsicmd_out (int unitnum, uae_u8 *data, int len) { struct dev_info_spti *di = unitisopen (unitnum); if (!di) return 0; int v = execscsicmd (di, unitnum, data, len, 0, 0); if (v < 0) return 0; return data; }
static uae_u32 ioctl_command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return -1; uae_u32 old = (ciw->cdda_volume[1] << 16) | (ciw->cdda_volume[0] << 0); ciw->cdda_volume[0] = volume_left; ciw->cdda_volume[1] = volume_right; return old; }
/* stop CD audio */ static int ioctl_command_stop (int unitnum) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; cdda_stop (ciw); return 1; }
/* pause/unpause CD audio */ static int ioctl_command_pause (int unitnum, int paused) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return -1; int old = ciw->cdda_paused; if ((paused && ciw->cdda_play) || !paused) ciw->cdda_paused = paused; return old; }
static uae_u32 command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return -1; uae_u32 old = (cdu->cdda_volume[1] << 16) | (cdu->cdda_volume[0] << 0); cdu->cdda_volume[0] = volume_left; cdu->cdda_volume[1] = volume_right; return old; }
static int ioctl_ismedia (int unitnum, int quick) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return -1; if (quick) { return ciw->di.media_inserted; } update_device_info (unitnum); return ismedia (ciw, unitnum); }
static int eject (int unitnum, bool eject) { DWORD len; struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; if (!unitisopen (unitnum)) return 0; cdda_stop (ciw); if (!open_createfile (ciw, 0)) return 0; int ret = 0; seterrormode (ciw); if (!DeviceIoControl (ciw->h, eject ? IOCTL_STORAGE_EJECT_MEDIA : IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &len, NULL)) { ret = 1; } reseterrormode (ciw); return ret; }
static int command_toc (int unitnum, struct cd_toc_head *th) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; int i; memset (&cdu->di.toc, 0, sizeof (struct cd_toc_head)); if (!cdu->tracks) return 0; memset (th, 0, sizeof (struct cd_toc_head)); struct cd_toc *toc = &th->toc[0]; th->first_track = 1; th->last_track = cdu->tracks; th->points = cdu->tracks + 3; th->tracks = cdu->tracks; th->firstaddress = 0; th->lastaddress = cdu->toc[cdu->tracks].address; toc->adr = 1; toc->point = 0xa0; toc->track = th->first_track; toc++; th->first_track_offset = 1; for (i = 0; i < cdu->tracks; i++) { toc->adr = cdu->toc[i].adr; toc->control = cdu->toc[i].ctrl; toc->track = i + 1; toc->point = i + 1; toc->paddress = cdu->toc[i].address; toc++; } th->last_track_offset = cdu->tracks; toc->adr = 1; toc->point = 0xa1; toc->track = th->last_track; toc++; toc->adr = 1; toc->point = 0xa2; toc->paddress = th->lastaddress; toc++; memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head)); return 1; }
static uae_u8 *execscsicmd_in (int unitnum, uae_u8 *data, int len, int *outlen) { struct dev_info_spti *di = unitisopen (unitnum); if (!di) return 0; int v = execscsicmd (di, unitnum, data, len, di->scsibuf, DEVICE_SCSI_BUFSIZE); if (v < 0) return 0; if (v == 0) return 0; if (outlen) *outlen = v < *outlen ? v : *outlen; return di->scsibuf; }
static int command_qcode (int unitnum, uae_u8 *buf, int sector) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; uae_u8 subbuf[SUB_CHANNEL_SIZE]; uae_u8 *p; int trk; int pos; int status; memset (buf, 0, SUBQ_SIZE); p = buf; status = cdu->cdda_play_state; if (cdu->cdda_play > 0 && cdu->cdda_paused) status = AUDIO_STATUS_PAUSED; if (sector < 0) pos = cdu->cd_last_pos; else pos = sector; p[1] = status; p[3] = 12; p = buf + 4; struct cdtoc *td = NULL; for (trk = 0; trk <= cdu->tracks; trk++) { td = &cdu->toc[trk]; if (pos < td->address) { if (trk > 0) td--; break; } if (pos >= td->address && pos < td[1].address) break; } if (!td) return 0; getsub_deinterleaved (subbuf, cdu, td, pos); memcpy (p, subbuf + 12, 12); // write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"), // pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); return 1; }
static void update_device_info (int unitnum) { struct dev_info_spti *dispti = unitisopen (unitnum); if (!dispti) return; struct device_info *di = &dispti->di; _tcscpy (di->label, dispti->drvletter ? dispti->drvlettername : dispti->name); _tcscpy (di->mediapath, dispti->drvpath); di->bus = 0; di->target = unitnum; di->lun = 0; di->media_inserted = mediacheck (dispti, unitnum); di->removable = dispti->removable; mediacheck_full (dispti, unitnum, di); di->type = dispti->type; di->unitnum = unitnum + 1; di->backend = L"SPTI"; if (log_scsi) { write_log (L"MI=%d TP=%d WP=%d CY=%d BK=%d RMB=%d '%s'\n", di->media_inserted, di->type, di->write_protected, di->cylinders, di->bytespersector, di->removable, di->label); } }
static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc) { struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; cdu->cd_last_pos = startlsn; cdu->cdda_start = startlsn; cdu->cdda_end = endlsn; cdu->cdda_subfunc = subfunc; cdu->cdda_statusfunc = statusfunc; cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); cdu->cdda_delay = setstate (cdu, -1); cdu->cdda_delay_frames = setstate (cdu, -2); setstate (cdu, AUDIO_STATUS_NOT_SUPPORTED); if (!isaudiotrack (&cdu->di.toc, startlsn)) { setstate (cdu, AUDIO_STATUS_PLAY_ERROR); return 0; } if (!cdu->cdda_play) uae_start_thread (_T("cdimage_cdda_play"), cdda_play_func, cdu, NULL); cdu->cdda_play++; return 1; }
/* read qcode */ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; uae_u8 *p; int trk; CDROM_TOC *toc = &ciw->cdromtoc; int pos; int msf; int start, end; int status; bool valid = false; bool regenerate = true; memset (buf, 0, SUBQ_SIZE); p = buf; status = AUDIO_STATUS_NO_STATUS; if (ciw->cdda_play) { status = AUDIO_STATUS_IN_PROGRESS; if (ciw->cdda_paused) status = AUDIO_STATUS_PAUSED; } else if (ciw->cdda_play_finished) { status = AUDIO_STATUS_PLAY_COMPLETE; } p[1] = status; p[3] = 12; p = buf + 4; if (sector < 0) pos = ciw->cd_last_pos; else pos = sector; if (!regenerate) { if (sector < 0 && ciw->subcodevalid && ciw->cdda_play) { uae_sem_wait (&ciw->sub_sem2); uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (ciw->subcodebuf, subbuf); memcpy (p, subbuf + 12, 12); uae_sem_post (&ciw->sub_sem2); valid = true; } if (!valid && sector >= 0) { DWORD len; uae_sem_wait (&ciw->sub_sem); seterrormode (ciw); RAW_READ_INFO rri; rri.DiskOffset.QuadPart = 2048 * (pos + 0); rri.SectorCount = 1; rri.TrackMode = RawWithSubCode; memset (ciw->tempbuffer, 0, CD_RAW_SECTOR_WITH_SUBCODE_SIZE); if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, ciw->tempbuffer, CD_RAW_SECTOR_WITH_SUBCODE_SIZE, &len, NULL)) { DWORD err = GetLastError (); write_log (_T("IOCTL_CDROM_RAW_READ SUBQ CDDA sector %d returned %d\n"), pos, err); } reseterrormode (ciw); uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (ciw->tempbuffer + 2352, subbuf); uae_sem_post (&ciw->sub_sem); memcpy (p, subbuf + 12, 12); valid = true; } } if (!valid) { start = end = 0; for (trk = 0; trk <= toc->LastTrack; trk++) { TRACK_DATA *td = &toc->TrackData[trk]; start = msf2lsn ((td->Address[1] << 16) | (td->Address[2] << 8) | td->Address[3]); end = msf2lsn ((td[1].Address[1] << 16) | (td[1].Address[2] << 8) | td[1].Address[3]); if (pos < start) break; if (pos >= start && pos < end) break; } p[0] = (toc->TrackData[trk].Control << 4) | (toc->TrackData[trk].Adr << 0); p[1] = tobcd (trk + 1); p[2] = tobcd (1); msf = lsn2msf (pos); tolongbcd (p + 7, msf); msf = lsn2msf (pos - start - 150); tolongbcd (p + 3, msf); } // write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"), // pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); return 1; }
static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u32 extra) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; uae_u8 *p = ciw->tempbuffer; int ret = 0; if (log_scsi) write_log (_T("IOCTL rawread unit=%d sector=%d blocksize=%d\n"), unitnum, sector, sectorsize); cdda_stop (ciw); gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE); if (sectorsize > 0) { if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048 && sectorsize != 2336 + 96 && sectorsize != 2352 + 96 && sectorsize != 2048 + 96) return 0; while (size-- > 0) { if (!read_block (ciw, unitnum, data, sector, 1, sectorsize)) break; ciw->cd_last_pos = sector; data += sectorsize; ret += sectorsize; sector++; } } else { uae_u8 sectortype = extra >> 16; uae_u8 cmd9 = extra >> 8; int sync = (cmd9 >> 7) & 1; int headercodes = (cmd9 >> 5) & 3; int userdata = (cmd9 >> 4) & 1; int edcecc = (cmd9 >> 3) & 1; int errorfield = (cmd9 >> 1) & 3; uae_u8 subs = extra & 7; if (subs != 0 && subs != 1 && subs != 2 && subs != 4) return -1; if (errorfield >= 3) return -1; uae_u8 *d = data; if (isaudiotrack (&ciw->di.toc, sector)) { if (sectortype != 0 && sectortype != 1) return -2; for (int i = 0; i < size; i++) { uae_u8 *odata = data; int blocksize = errorfield == 0 ? 2352 : (errorfield == 1 ? 2352 + 294 : 2352 + 296); int readblocksize = errorfield == 0 ? 2352 : 2352 + 296; if (!read_block (ciw, unitnum, NULL, sector, 1, readblocksize)) { reseterrormode (ciw); return ret; } ciw->cd_last_pos = sector; if (subs == 0) { memcpy (data, p, blocksize); data += blocksize; } else if (subs == 4) { // all, de-interleaved memcpy (data, p, blocksize); data += blocksize; sub_to_deinterleaved (p + readblocksize, data); data += SUB_CHANNEL_SIZE; } else if (subs == 2) { // q-only memcpy (data, p, blocksize); data += blocksize; uae_u8 subdata[SUB_CHANNEL_SIZE]; sub_to_deinterleaved (p + readblocksize, subdata); memcpy (data, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); p += SUB_ENTRY_SIZE; } else if (subs == 1) { // all, interleaved memcpy (data, p, blocksize); memcpy (data + blocksize, p + readblocksize, SUB_CHANNEL_SIZE); data += blocksize + SUB_CHANNEL_SIZE; } ret += data - odata; sector++; } } } return ret; }
static int execscsicmd_direct (int unitnum, struct amigascsi *as) { struct dev_info_spti *di = unitisopen (unitnum); if (!di) return -1; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD status; int sactual = 0, i; int io_error = 0, err, parm; uae_u8 *scsi_datap, *scsi_datap_org; uae_u32 scsi_cmd_len_orig = as->cmd_len; memset (&swb, 0, sizeof (swb)); swb.spt.Length = sizeof (SCSI_PASS_THROUGH); swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf); if (as->len > DEVICE_SCSI_BUFSIZE) as->len = DEVICE_SCSI_BUFSIZE; uae_sem_wait (&scgp_sem); /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */ swb.spt.TimeOutValue = 80 * 60; scsi_datap = scsi_datap_org = as->len ? as->data : 0; swb.spt.DataIn = (as->flags & 1) ? SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT; for (i = 0; i < as->cmd_len; i++) swb.spt.Cdb[i] = as->cmd[i]; if (as->sense_len > 32) as->sense_len = 32; swb.spt.SenseInfoLength = (as->flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */ (as->flags & 2) ? as->sense_len : /* SCSIF_AUTOSENSE */ 32; if (dev_info[unitnum].isatapi) scsi_atapi_fixup_pre (swb.spt.Cdb, &as->cmd_len, &scsi_datap, &as->len, &parm); memcpy (di->scsibuf, scsi_datap, as->len); swb.spt.CdbLength = (UCHAR)as->cmd_len; swb.spt.DataTransferLength = as->len; swb.spt.DataBuffer = di->scsibuf; status = doscsi (di, unitnum, &swb, &err); memcpy (scsi_datap, di->scsibuf, as->len); as->cmdactual = status == 0 ? 0 : scsi_cmd_len_orig; /* fake scsi_CmdActual */ as->status = swb.spt.ScsiStatus; /* scsi_Status */ if (swb.spt.ScsiStatus) { io_error = 45; /* HFERR_BadStatus */ /* copy sense? */ for (sactual = 0; sactual < as->sense_len && sactual < swb.spt.SenseInfoLength; sactual++) as->sensedata[sactual] = swb.SenseBuf[sactual]; as->actual = 0; /* scsi_Actual */ } else { int i; for (i = 0; i < as->sense_len; i++) as->sensedata[i] = 0; sactual = 0; if (status == 0) { io_error = 20; /* io_Error, but not specified */ as->actual = 0; /* scsi_Actual */ } else { as->len = swb.spt.DataTransferLength; if (dev_info[unitnum].isatapi) scsi_atapi_fixup_post (swb.spt.Cdb, as->cmd_len, scsi_datap_org, scsi_datap, &as->len, parm); io_error = 0; as->actual = as->len; /* scsi_Actual */ } } as->sactual = sactual; uae_sem_post (&scgp_sem); if (scsi_datap != scsi_datap_org) free (scsi_datap); return io_error; }
static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, uae_u8 *data) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; if (ciw->usesptiread) return ioctl_command_rawread (unitnum, data, sector, size, 2048, 0); cdda_stop (ciw); DWORD dtotal; int cnt = 3; uae_u8 *p = ciw->tempbuffer; int blocksize = ciw->di.bytespersector; if (!open_createfile (ciw, 0)) return 0; ciw->cd_last_pos = sector; while (cnt-- > 0) { LARGE_INTEGER offset; gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE); seterrormode (ciw); offset.QuadPart = (uae_u64)sector * ciw->di.bytespersector; if (SetFilePointer (ciw->h, offset.LowPart, &offset.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) { reseterrormode (ciw); if (win32_error (ciw, unitnum, _T("SetFilePointer")) < 0) continue; return 0; } reseterrormode (ciw); break; } while (size-- > 0) { gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE); seterrormode (ciw); if (write) { if (data) { memcpy (p, data, blocksize); data += blocksize; } if (!WriteFile (ciw->h, p, blocksize, &dtotal, 0)) { int err; reseterrormode (ciw); err = win32_error (ciw, unitnum, _T("WriteFile")); if (err < 0) continue; if (err == ERROR_WRITE_PROTECT) return -1; return 0; } } else { dtotal = 0; if (!ReadFile (ciw->h, p, blocksize, &dtotal, 0)) { reseterrormode (ciw); if (win32_error (ciw, unitnum, _T("ReadFile")) < 0) continue; return 0; } if (dtotal == 0) { static int reported; /* ESS Mega (CDTV) "fake" data area returns zero bytes and no error.. */ spti_read (ciw, unitnum, data, sector, 2048); if (reported++ < 100) write_log (_T("IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n"), unitnum, sector, GetLastError ()); return 1; } if (data) { memcpy (data, p, blocksize); data += blocksize; } } reseterrormode (ciw); gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE); } return 1; }
static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u32 extra) { int ret = 0; struct cdunit *cdu = unitisopen (unitnum); if (!cdu) return 0; int asector = sector; struct cdtoc *t = findtoc (cdu, §or); int ssize = t->size + t->skipsize; if (!t) goto end; cdda_stop (cdu); if (sectorsize > 0) { if (sectorsize == 2352 && t->size == 2048) { // 2048 -> 2352 while (size-- > 0) { memset (data, 0, 16); do_read (cdu, t, data + 16, sector, 0, 2048); encode_l2 (data, sector + 150); sector++; asector++; data += sectorsize; ret += sectorsize; } } else if (sectorsize == 2048 && t->size == 2352) { // 2352 -> 2048 while (size-- > 0) { uae_u8 b = 0; do_read (cdu, t, &b, sector, 15, 1); do_read (cdu, t, data, sector, b == 2 ? 24 : 16, sectorsize); sector++; asector++; data += sectorsize; ret += sectorsize; } } else if (sectorsize == 2336 && t->size == 2352) { // 2352 -> 2336 while (size-- > 0) { uae_u8 b = 0; do_read (cdu, t, &b, sector, 15, 1); if (b != 2 && b != 0) // MODE0 or MODE2 only allowed return 0; do_read (cdu, t, data, sector, 16, sectorsize); sector++; asector++; data += sectorsize; ret += sectorsize; } } else if (sectorsize == t->size) { // no change while (size -- > 0) { do_read (cdu, t, data, sector, 0, sectorsize); sector++; asector++; data += sectorsize; ret++; } } cdu->cd_last_pos = asector; } else { uae_u8 sectortype = extra >> 16; uae_u8 cmd9 = extra >> 8; int sync = (cmd9 >> 7) & 1; int headercodes = (cmd9 >> 5) & 3; int userdata = (cmd9 >> 4) & 1; int edcecc = (cmd9 >> 3) & 1; int errorfield = (cmd9 >> 1) & 3; uae_u8 subs = extra & 7; if (subs != 0 && subs != 1 && subs != 2 && subs != 4) { ret = -1; goto end; } if (isaudiotrack (&cdu->di.toc, sector)) { if (sectortype != 0 && sectortype != 1) { ret = -2; goto end; } if (t->size != 2352) { ret = -1; goto end; } for (int i = 0; i < size; i++) { do_read (cdu, t, data, sector, 0, t->size); uae_u8 *p = data + t->size; if (subs) { uae_u8 subdata[SUB_CHANNEL_SIZE]; getsub_deinterleaved (subdata, cdu, t, sector); if (subs == 4) { // all, de-interleaved memcpy (p, subdata, SUB_CHANNEL_SIZE); p += SUB_CHANNEL_SIZE; } else if (subs == 2) { // q-only memcpy (p, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); p += SUB_ENTRY_SIZE; } else if (subs == 1) { // all, interleaved sub_to_interleaved (subdata, p); p += SUB_CHANNEL_SIZE; } } ret += p - data; data = p; sector++; } } } end: return ret; }
/* read toc */ static int ioctl_command_toc2 (int unitnum, struct cd_toc_head *tocout, bool hide_errors) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; DWORD len; int i; struct cd_toc_head *th = &ciw->di.toc; struct cd_toc *t = th->toc; int cnt = 3; CDROM_TOC *toc = &ciw->cdromtoc; if (!unitisopen (unitnum)) return 0; if (!open_createfile (ciw, 0)) return 0; while (cnt-- > 0) { seterrormode (ciw); if (!DeviceIoControl (ciw->h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) { DWORD err = GetLastError (); reseterrormode (ciw); if (!hide_errors || (hide_errors && err == ERROR_WRONG_DISK)) { if (win32_error (ciw, unitnum, _T("IOCTL_CDROM_READ_TOC")) < 0) continue; } return 0; } reseterrormode (ciw); break; } memset (th, 0, sizeof (struct cd_toc_head)); th->first_track = toc->FirstTrack; th->last_track = toc->LastTrack; th->tracks = th->last_track - th->first_track + 1; th->points = th->tracks + 3; th->firstaddress = 0; th->lastaddress = msf2lsn ((toc->TrackData[toc->LastTrack].Address[1] << 16) | (toc->TrackData[toc->LastTrack].Address[2] << 8) | (toc->TrackData[toc->LastTrack].Address[3] << 0)); t->adr = 1; t->point = 0xa0; t->track = th->first_track; t++; th->first_track_offset = 1; for (i = 0; i < toc->LastTrack; i++) { t->adr = toc->TrackData[i].Adr; t->control = toc->TrackData[i].Control; t->paddress = msf2lsn ((toc->TrackData[i].Address[1] << 16) | (toc->TrackData[i].Address[2] << 8) | (toc->TrackData[i].Address[3] << 0)); t->point = t->track = i + 1; t++; } th->last_track_offset = toc->LastTrack; t->adr = 1; t->point = 0xa1; t->track = th->last_track; t++; t->adr = 1; t->point = 0xa2; t->paddress = th->lastaddress; t++; memcpy (tocout, th, sizeof (struct cd_toc_head)); return 1; }