diff options
author | PCSX* teams | 2010-11-16 14:15:22 +0200 |
---|---|---|
committer | Grazvydas Ignotas | 2010-11-16 14:15:22 +0200 |
commit | ef79bbde537d6b9c745a7d86cb9df1d04c35590d (patch) | |
tree | ef8d2520dbb9e1e345b41b12c9959f300ca8fd10 /plugins/dfcdrom/cdr-libcdio.c | |
download | pcsx_rearmed-ef79bbde537d6b9c745a7d86cb9df1d04c35590d.tar.gz pcsx_rearmed-ef79bbde537d6b9c745a7d86cb9df1d04c35590d.tar.bz2 pcsx_rearmed-ef79bbde537d6b9c745a7d86cb9df1d04c35590d.zip |
pcsxr-1.9.92
Diffstat (limited to 'plugins/dfcdrom/cdr-libcdio.c')
-rw-r--r-- | plugins/dfcdrom/cdr-libcdio.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/plugins/dfcdrom/cdr-libcdio.c b/plugins/dfcdrom/cdr-libcdio.c new file mode 100644 index 0000000..738d203 --- /dev/null +++ b/plugins/dfcdrom/cdr-libcdio.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * By: linuzappz <linuzappz@hotmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#ifdef USE_LIBCDIO + +#include <cdio/cdio.h> +#include <cdio/mmc.h> + +#include "cdr.h" + +static CdIo_t *cdHandle = NULL; + +static void SetSpeed(int speed) { + speed *= 176; + if (speed == 0) speed = 0xFFFF; + + cdio_set_speed(cdHandle, speed); +} + +static void SetSpinDown(unsigned char spindown) { + mmc_cdb_t cdb; + char buf[16]; + + memset(&cdb, 0, sizeof(cdb)); + + cdb.field[0] = 0x5A; + cdb.field[2] = 0x0D; + cdb.field[8] = sizeof(buf); + + if (mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS) + return; + + buf[11] = (buf[11] & 0xF0) | (spindown & 0x0F); + + memset(&cdb, 0, sizeof(cdb)); + memset(buf, 0, 2); + + cdb.field[0] = 0x55; + cdb.field[1] = 0x10; + cdb.field[8] = sizeof(buf); + + mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, sizeof(buf), buf); +} + +static void UnlockDoor() { + mmc_cdb_t cdb; + + memset(&cdb, 0, sizeof(cdb)); + + cdb.field[0] = 0x1E; + cdb.field[4] = 0; + + mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, 0, NULL); +} + +int OpenCdHandle(const char *dev) { + if (dev == NULL || dev[0] == '\0') { + if ((dev = cdio_get_default_device(NULL)) == NULL) { + return -1; + } + } + +#ifdef __FreeBSD__ + cdHandle = cdio_open_am_cd(dev, "CAM"); +#else + cdHandle = cdio_open_cd(dev); +#endif + + if (cdHandle != NULL) { + SetSpeed(CdrSpeed); + SetSpinDown(SpinDown); + UnlockDoor(); + + return 0; + } + + return -1; +} + +void CloseCdHandle() { + if (cdHandle != NULL) { + cdio_set_speed(cdHandle, 0xFFFF); + SetSpinDown(SPINDOWN_VENDOR_SPECIFIC); + + cdio_destroy(cdHandle); + } + + cdHandle = NULL; +} + +int IsCdHandleOpen() { + return (cdHandle != NULL); +} + +long GetTN(unsigned char *buffer) { + buffer[0] = cdio_get_first_track_num(cdHandle); + buffer[1] = cdio_get_last_track_num(cdHandle); + + return 0; +} + +long GetTD(unsigned char track, unsigned char *buffer) { + msf_t msf; + + if (track == 0) track = CDIO_CDROM_LEADOUT_TRACK; + + if (!cdio_get_track_msf(cdHandle, track, &msf)) { + memset(buffer + 1, 0, 3); + return 0; + } + + buffer[0] = btoi(msf.f); + buffer[1] = btoi(msf.s); + buffer[2] = btoi(msf.m); + + return 0; +} + +long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) { + unsigned char msf[3]; + + lba_to_msf(cdio_get_track_lba(cdHandle, track + 1) - CD_MSF_OFFSET, msf); + + *m = msf[0]; + *s = msf[1]; + *f = msf[2]; + + return 0; +} + +long ReadSector(crdata *cr) { + int lba; + MMC_READ_CD cdb; + + lba = msf_to_lba(cr->msf.cdmsf_min0, cr->msf.cdmsf_sec0, cr->msf.cdmsf_frame0); + memset(&cdb, 0, sizeof(cdb)); + + cdb.Code = 0xBE; + cdb.IncludeEDC = 1; + cdb.IncludeUserData = 1; + cdb.HeaderCode = 3; + cdb.IncludeSyncData = 1; + cdb.SubChannelSelection = 0; + cdb.StartingLBA[1] = lba >> 16; + cdb.StartingLBA[2] = lba >> 8; + cdb.StartingLBA[3] = lba; + cdb.TransferBlocks[2] = 1; + + if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(*cr), cr) != DRIVER_OP_SUCCESS) + return -1; + + return 0; +} + +long PlayCDDA(unsigned char *sector) { + msf_t start, end; + + if (!cdio_get_track_msf(cdHandle, CDIO_CDROM_LEADOUT_TRACK, &end)) + return -1; + + start.m = itob(sector[0]); + start.s = itob(sector[1]); + start.f = itob(sector[2]); + + if (cdio_audio_play_msf(cdHandle, &start, &end) != DRIVER_OP_SUCCESS) + return -1; + + return 0; +} + +long StopCDDA() { + cdio_subchannel_t subchnl; + + if (cdio_audio_read_subchannel(cdHandle, &subchnl) != DRIVER_OP_SUCCESS) + return -1; + + switch (subchnl.audio_status) { + case CDIO_MMC_READ_SUB_ST_PLAY: + case CDIO_MMC_READ_SUB_ST_PAUSED: + cdio_audio_stop(cdHandle); + } + + return 0; +} + +long GetStatus(int playing, struct CdrStat *stat) { + cdio_subchannel_t subchnl; + + memset(stat, 0, sizeof(struct CdrStat)); + + if (playing) { + if (cdio_audio_read_subchannel(cdHandle, &subchnl) == DRIVER_OP_SUCCESS) { + stat->Time[0] = btoi(subchnl.abs_addr.m); + stat->Time[1] = btoi(subchnl.abs_addr.s); + stat->Time[2] = btoi(subchnl.abs_addr.f); + } + } + + stat->Type = 0x01; + + if (mmc_get_tray_status(cdHandle)) { + stat->Type = 0xff; + stat->Status |= 0x10; + } else { + SetSpeed(CdrSpeed); + SetSpinDown(SpinDown); + UnlockDoor(); + } + + return 0; +} + +unsigned char *ReadSub(const unsigned char *time) { + int lba = msf_to_lba(btoi(time[0]), btoi(time[1]), btoi(time[2])); + static unsigned char buf[CD_FRAMESIZE_RAW + 96]; + + MMC_READ_CD cdb; + + memset(&cdb, 0, sizeof(cdb)); + + cdb.Code = 0xBE; + cdb.IncludeEDC = 1; + cdb.IncludeUserData = 1; + cdb.HeaderCode = 3; + cdb.IncludeSyncData = 1; + cdb.StartingLBA[1] = lba >> 16; + cdb.StartingLBA[2] = lba >> 8; + cdb.StartingLBA[3] = lba; + cdb.TransferBlocks[2] = 1; + cdb.SubChannelSelection = 1; + + if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS) + return NULL; + + DecodeRawSubData(buf + CD_FRAMESIZE_RAW); + return buf + CD_FRAMESIZE_RAW; +} + +#endif |