示例#1
0
static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector)
{
	int ret = 0;
	uae_sem_wait (&cdu->sub_sem);
	if (t->subcode) {
		if (t->enctype == ENC_CHD) {
			const cdrom_track_info *cti = t->chdtrack;
			ret = do_read (cdu, t, dst, sector, cti->datasize, cti->subsize);
			if (ret)
				ret = t->subcode;
		} else if (t->subhandle) {
			int offset = 0;
			int totalsize = SUB_CHANNEL_SIZE;
			if (t->skipsize) {
				totalsize += t->size;
				offset = t->size;
			}
			zfile_fseek (t->subhandle, (uae_u64)sector * totalsize + t->suboffset + offset, SEEK_SET);
			if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0)
				ret = t->subcode;
		} else {
			memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE);
			ret = t->subcode;
		}
	}
	if (!ret) {
		memset (dst, 0, SUB_CHANNEL_SIZE);
		// regenerate Q-subchannel
		uae_u8 *s = dst + 12;
		s[0] = (t->ctrl << 4) | (t->adr << 0);
		s[1] = tobcd (t - &cdu->toc[0] + 1);
		s[2] = tobcd (1);
		int msf = lsn2msf (sector);
		tolongbcd (s + 7, msf);
		msf = lsn2msf (sector - t->address - 150);
		tolongbcd (s + 3, msf);
		ret = 2;
	}
	if (ret == 1) {
		uae_u8 tmp[SUB_CHANNEL_SIZE];
		memcpy (tmp, dst, SUB_CHANNEL_SIZE);
		sub_to_deinterleaved (tmp, dst);
		ret = 2;
	}
	uae_sem_post (&cdu->sub_sem);
	return ret;
}
示例#2
0
文件: cdtvcr.cpp 项目: rofl0r/WinUAE
static int get_toc (void)
{
	uae_u32 msf;
	uae_u8 *p, *pl;

	cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~4;
	datatrack = 0;
	if (!sys_command_cd_toc (unitnum, &toc))
		return 0;
	cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 4 | 8;
	if (toc.first_track == 1 && (toc.toc[toc.first_track_offset].control & 0x0c) == 0x04)
		datatrack = 1;
	p = &cdtvcr_4510_ram[CDTVCR_TOC];
	cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT] = 0;
	cdtvcr_4510_ram[CDTVCR_PLAYLIST_ENTRIES] = 0;
	pl = &cdtvcr_4510_ram[CDTVCR_PLAYLIST_DATA];
	p[0] = toc.first_track;
	p[1] = toc.last_track;
	msf = lsn2msf(toc.lastaddress);
	p[2] = msf >> 16;
	p[3] = msf >>  8;
	p[4] = msf >>  0;
	p += 5;
	for (int j = toc.first_track_offset; j <= toc.last_track_offset; j++) {
		struct cd_toc *s = &toc.toc[j];
		p[0] = (s->adr << 0) | (s->control << 4);
		p[1] = s->track;
		msf = lsn2msf(s->address);
		p[2] = msf >> 16;
		p[3] = msf >>  8;
		p[4] = msf >>  0;
		p += 5;
		*pl++ = s->track | 0x80;
		cdtvcr_4510_ram[CDTVCR_PLAYLIST_ENTRIES]++;
	}
	return 1;
}
示例#3
0
/**
 * Parse CDDB text
 */
Cddb::Album& Cddb::Album::operator =(const QString& rhs)
{
    discGenre.clear();
    discID = 0;
    artist.clear();
    title.clear();
    genre.clear();
    year = 0;
    submitter = "MythTV " MYTH_BINARY_VERSION;
    rev = 1;
    isCompilation = false;
    tracks.clear();
    toc.clear();
    extd.clear();
    ext.clear();

    enum { kNorm, kToc } eState = kNorm;

    QString cddb = QString::fromUtf8(rhs.toLatin1().constData());
    while (!cddb.isEmpty())
    {
        // Lines should be of the form "FIELD=value\r\n"
        QString line  = cddb.section(QRegExp("[\r\n]"), 0, 0);

        if (line.startsWith("# Track frame offsets:"))
        {
            eState = kToc;
        }
        else if (line.startsWith("# Disc length:"))
        {
            QString s = line.section(QRegExp("[ \t]"), 3, 3);
            unsigned secs = s.toULong();
            if (toc.size())
                secs -= msf2sec(toc[0]);
            toc.push_back(sec2msf(secs));
            eState = kNorm;
        }
        else if (line.startsWith("# Revision:"))
        {
            QString s = line.section(QRegExp("[ \t]"), 2, 2);
            bool bValid = false;
            int v = s.toInt(&bValid);
            if (bValid)
                rev = v;
        }
        else if (line.startsWith("# Submitted via:"))
        {
            submitter = line.section(QRegExp("[ \t]"), 3, 3);
        }
        else if (line.startsWith("#"))
        {
            if (kToc == eState)
            {
                bool bValid = false;
                QString s = line.section(QRegExp("[ \t]"), 1).trimmed();
                unsigned long lsn = s.toUInt(&bValid);
                if (bValid)
                    toc.push_back(lsn2msf(lsn));
                else
                    eState = kNorm;
            }
        }
        else
        {
            QString value = line.section('=', 1, 1);
            QString art;

            if (value.contains(" / "))
            {
                art   = value.section(" / ", 0, 0);  // Artist in *TITLE
                value = value.section(" / ", 1, 1);
            }

            if (line.startsWith("DISCID="))
            {
                bool isValid = false;
                ulong discID2 = value.toULong(&isValid,16);
                if (isValid)
                    discID = discID2;
            }
            else if (line.startsWith("DTITLE="))
            {
                // Albums (and maybe artists?) can wrap over multiple lines:
                artist += art;
                title  += value;
            }
            else if (line.startsWith("DYEAR="))
            {
                bool isValid = false;
                int val = value.toInt(&isValid);
                if (isValid)
                    year = val;
            }
            else if (line.startsWith("DGENRE="))
            {
                if (!value.isEmpty())
                    genre = value;
            }
            else if (line.startsWith("TTITLE"))
            {
                int trk = line.remove("TTITLE").section('=', 0, 0).toInt();
                if (trk >= 0 && trk < CDROM_LEADOUT_TRACK)
                {
                    if (trk >= tracks.size())
                        tracks.resize(trk + 1);

                    Cddb::Track& track = tracks[trk];

                    // Titles can wrap over multiple lines, so we load+store:
                    track.title += value;
                    track.artist += art;

                    if (art.length())
                        isCompilation = true;
                }
            }
            else if (line.startsWith("EXTD="))
            {
                if (!value.isEmpty())
                    extd = value;
            }
            else if (line.startsWith("EXTT"))
            {
                int trk = line.remove("EXTT").section('=', 0, 0).toInt();
                if (trk >= 0 && trk < CDROM_LEADOUT_TRACK)
                {
                    if (trk >= ext.size())
                        ext.resize(trk + 1);

                    ext[trk] = value;
                }
            }
        }

        // Next response line:
        cddb = cddb.section('\n', 1);
    }
    return *this;
}
示例#4
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;

}