minimal working gtk-less build
[pcsx_rearmed.git] / plugins / dfcdrom / cdr-libcdio.c
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
29 static CdIo_t *cdHandle = NULL;
30
31 static void SetSpeed(int speed) {
32         speed *= 176;
33         if (speed == 0) speed = 0xFFFF;
34
35         cdio_set_speed(cdHandle, speed);
36 }
37
38 static 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
63 static 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
74 int 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
98 void 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
109 int IsCdHandleOpen() {
110         return (cdHandle != NULL);
111 }
112
113 long 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
120 long 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
137 long 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
149 long 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
173 long 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
189 long 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
204 long 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
231 unsigned 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