pcsxr-1.9.92
[pcsx_rearmed.git] / plugins / dfcdrom / cdr-libcdio.c
CommitLineData
ef79bbde
P
1/*
2 * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
3 * All Rights Reserved.
4 *
5 * Based on: Cdrom for Psemu Pro like Emulators
6 * By: linuzappz <linuzappz@hotmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses>.
20 */
21
22#ifdef USE_LIBCDIO
23
24#include <cdio/cdio.h>
25#include <cdio/mmc.h>
26
27#include "cdr.h"
28
29static CdIo_t *cdHandle = NULL;
30
31static void SetSpeed(int speed) {
32 speed *= 176;
33 if (speed == 0) speed = 0xFFFF;
34
35 cdio_set_speed(cdHandle, speed);
36}
37
38static void SetSpinDown(unsigned char spindown) {
39 mmc_cdb_t cdb;
40 char buf[16];
41
42 memset(&cdb, 0, sizeof(cdb));
43
44 cdb.field[0] = 0x5A;
45 cdb.field[2] = 0x0D;
46 cdb.field[8] = sizeof(buf);
47
48 if (mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS)
49 return;
50
51 buf[11] = (buf[11] & 0xF0) | (spindown & 0x0F);
52
53 memset(&cdb, 0, sizeof(cdb));
54 memset(buf, 0, 2);
55
56 cdb.field[0] = 0x55;
57 cdb.field[1] = 0x10;
58 cdb.field[8] = sizeof(buf);
59
60 mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, sizeof(buf), buf);
61}
62
63static void UnlockDoor() {
64 mmc_cdb_t cdb;
65
66 memset(&cdb, 0, sizeof(cdb));
67
68 cdb.field[0] = 0x1E;
69 cdb.field[4] = 0;
70
71 mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, 0, NULL);
72}
73
74int OpenCdHandle(const char *dev) {
75 if (dev == NULL || dev[0] == '\0') {
76 if ((dev = cdio_get_default_device(NULL)) == NULL) {
77 return -1;
78 }
79 }
80
81#ifdef __FreeBSD__
82 cdHandle = cdio_open_am_cd(dev, "CAM");
83#else
84 cdHandle = cdio_open_cd(dev);
85#endif
86
87 if (cdHandle != NULL) {
88 SetSpeed(CdrSpeed);
89 SetSpinDown(SpinDown);
90 UnlockDoor();
91
92 return 0;
93 }
94
95 return -1;
96}
97
98void CloseCdHandle() {
99 if (cdHandle != NULL) {
100 cdio_set_speed(cdHandle, 0xFFFF);
101 SetSpinDown(SPINDOWN_VENDOR_SPECIFIC);
102
103 cdio_destroy(cdHandle);
104 }
105
106 cdHandle = NULL;
107}
108
109int IsCdHandleOpen() {
110 return (cdHandle != NULL);
111}
112
113long GetTN(unsigned char *buffer) {
114 buffer[0] = cdio_get_first_track_num(cdHandle);
115 buffer[1] = cdio_get_last_track_num(cdHandle);
116
117 return 0;
118}
119
120long GetTD(unsigned char track, unsigned char *buffer) {
121 msf_t msf;
122
123 if (track == 0) track = CDIO_CDROM_LEADOUT_TRACK;
124
125 if (!cdio_get_track_msf(cdHandle, track, &msf)) {
126 memset(buffer + 1, 0, 3);
127 return 0;
128 }
129
130 buffer[0] = btoi(msf.f);
131 buffer[1] = btoi(msf.s);
132 buffer[2] = btoi(msf.m);
133
134 return 0;
135}
136
137long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) {
138 unsigned char msf[3];
139
140 lba_to_msf(cdio_get_track_lba(cdHandle, track + 1) - CD_MSF_OFFSET, msf);
141
142 *m = msf[0];
143 *s = msf[1];
144 *f = msf[2];
145
146 return 0;
147}
148
149long ReadSector(crdata *cr) {
150 int lba;
151 MMC_READ_CD cdb;
152
153 lba = msf_to_lba(cr->msf.cdmsf_min0, cr->msf.cdmsf_sec0, cr->msf.cdmsf_frame0);
154 memset(&cdb, 0, sizeof(cdb));
155
156 cdb.Code = 0xBE;
157 cdb.IncludeEDC = 1;
158 cdb.IncludeUserData = 1;
159 cdb.HeaderCode = 3;
160 cdb.IncludeSyncData = 1;
161 cdb.SubChannelSelection = 0;
162 cdb.StartingLBA[1] = lba >> 16;
163 cdb.StartingLBA[2] = lba >> 8;
164 cdb.StartingLBA[3] = lba;
165 cdb.TransferBlocks[2] = 1;
166
167 if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(*cr), cr) != DRIVER_OP_SUCCESS)
168 return -1;
169
170 return 0;
171}
172
173long PlayCDDA(unsigned char *sector) {
174 msf_t start, end;
175
176 if (!cdio_get_track_msf(cdHandle, CDIO_CDROM_LEADOUT_TRACK, &end))
177 return -1;
178
179 start.m = itob(sector[0]);
180 start.s = itob(sector[1]);
181 start.f = itob(sector[2]);
182
183 if (cdio_audio_play_msf(cdHandle, &start, &end) != DRIVER_OP_SUCCESS)
184 return -1;
185
186 return 0;
187}
188
189long StopCDDA() {
190 cdio_subchannel_t subchnl;
191
192 if (cdio_audio_read_subchannel(cdHandle, &subchnl) != DRIVER_OP_SUCCESS)
193 return -1;
194
195 switch (subchnl.audio_status) {
196 case CDIO_MMC_READ_SUB_ST_PLAY:
197 case CDIO_MMC_READ_SUB_ST_PAUSED:
198 cdio_audio_stop(cdHandle);
199 }
200
201 return 0;
202}
203
204long GetStatus(int playing, struct CdrStat *stat) {
205 cdio_subchannel_t subchnl;
206
207 memset(stat, 0, sizeof(struct CdrStat));
208
209 if (playing) {
210 if (cdio_audio_read_subchannel(cdHandle, &subchnl) == DRIVER_OP_SUCCESS) {
211 stat->Time[0] = btoi(subchnl.abs_addr.m);
212 stat->Time[1] = btoi(subchnl.abs_addr.s);
213 stat->Time[2] = btoi(subchnl.abs_addr.f);
214 }
215 }
216
217 stat->Type = 0x01;
218
219 if (mmc_get_tray_status(cdHandle)) {
220 stat->Type = 0xff;
221 stat->Status |= 0x10;
222 } else {
223 SetSpeed(CdrSpeed);
224 SetSpinDown(SpinDown);
225 UnlockDoor();
226 }
227
228 return 0;
229}
230
231unsigned char *ReadSub(const unsigned char *time) {
232 int lba = msf_to_lba(btoi(time[0]), btoi(time[1]), btoi(time[2]));
233 static unsigned char buf[CD_FRAMESIZE_RAW + 96];
234
235 MMC_READ_CD cdb;
236
237 memset(&cdb, 0, sizeof(cdb));
238
239 cdb.Code = 0xBE;
240 cdb.IncludeEDC = 1;
241 cdb.IncludeUserData = 1;
242 cdb.HeaderCode = 3;
243 cdb.IncludeSyncData = 1;
244 cdb.StartingLBA[1] = lba >> 16;
245 cdb.StartingLBA[2] = lba >> 8;
246 cdb.StartingLBA[3] = lba;
247 cdb.TransferBlocks[2] = 1;
248 cdb.SubChannelSelection = 1;
249
250 if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS)
251 return NULL;
252
253 DecodeRawSubData(buf + CD_FRAMESIZE_RAW);
254 return buf + CD_FRAMESIZE_RAW;
255}
256
257#endif