Пример #1
0
// 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, &sector);
	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;
}
Пример #2
0
/* 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;
}
Пример #3
0
static int command_stop (int unitnum)
{
	struct cdunit *cdu = unitisopen (unitnum);
	if (!cdu)
		return 0;
	cdda_stop (cdu);
	return 1;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
/* 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;
}
Пример #9
0
/* 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;
}
Пример #10
0
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;
}
Пример #11
0
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);
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
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);
	}
}
Пример #17
0
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;
}
Пример #18
0
/* 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;

}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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, &sector);
	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;
}
Пример #23
0
/* 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;
}