This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_syscdrom.c
339 lines (290 loc) · 8.86 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2004 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
22
#include "SDL_config.h"
23
24
25
#ifdef SDL_CDROM_MINT
26
27
28
29
30
31
32
33
34
35
36
37
/*
Atari MetaDOS CD-ROM functions
Patrice Mandin
*/
#include <errno.h>
#include <cdromio.h>
#include <metados.h>
#include "SDL_cdrom.h"
38
#include "../SDL_syscdrom.h"
39
40
41
42
43
44
45
46
/* Some ioctl() errno values which occur when the tray is empty */
#ifndef ENOMEDIUM
#define ENOMEDIUM ENOENT
#endif
#define ERRNO_TRAYEMPTY(errno) \
((errno == EIO) || (errno == ENOENT) || \
(errno == EINVAL) || (errno == ENOMEDIUM))
47
48
/* The maximum number of CD-ROM drives we'll detect */
49
#define MAX_DRIVES 32
50
51
52
53
54
typedef struct
{
unsigned char device[3]; /* Physical device letter + ':' + '\0' */
metaopen_t metaopen; /* Infos on opened drive */
55
56
57
58
59
} metados_drive_t;
static metados_drive_t metados_drives[MAX_DRIVES];
/* The system-dependent CD control functions */
60
61
62
63
64
65
66
67
68
69
70
static const char *SDL_SYS_CDName(int drive);
static int SDL_SYS_CDOpen(int drive);
static void SDL_SYS_CDClose(SDL_CD * cdrom);
static int SDL_SYS_CDioctl(int id, int command, void *arg);
static int SDL_SYS_CDGetTOC(SDL_CD * cdrom);
static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position);
static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length);
static int SDL_SYS_CDPause(SDL_CD * cdrom);
static int SDL_SYS_CDResume(SDL_CD * cdrom);
static int SDL_SYS_CDStop(SDL_CD * cdrom);
static int SDL_SYS_CDEject(SDL_CD * cdrom);
71
72
int
73
SDL_SYS_CDInit(void)
74
{
75
76
77
78
metainit_t metainit = { 0, 0, 0, 0 };
metaopen_t metaopen;
int i, handle;
struct cdrom_subchnl info;
79
80
Metainit(&metainit);
81
if (metainit.version == NULL) {
82
#ifdef DEBUG_CDROM
83
fprintf(stderr, "MetaDOS not installed\n");
84
#endif
85
86
return -1;
}
87
88
if (metainit.drives_map == 0) {
89
#ifdef DEBUG_CDROM
90
fprintf(stderr, "No MetaDOS devices present\n");
91
#endif
92
93
94
95
96
97
98
99
100
101
102
return -1;
}
SDL_numcds = 0;
for (i = 'A'; i <= 'Z'; i++) {
metados_drives[SDL_numcds].device[0] = 0;
metados_drives[SDL_numcds].device[1] = ':';
metados_drives[SDL_numcds].device[2] = 0;
if (metainit.drives_map & (1 << (i - 'A'))) {
103
handle = Metaopen(i, &metaopen);
104
105
106
107
108
if (handle == 0) {
info.cdsc_format = CDROM_MSF;
if ((Metaioctl
(i, METADOS_IOCTL_MAGIC, CDROMSUBCHNL, &info) == 0)
109
|| ERRNO_TRAYEMPTY(errno)) {
110
111
112
113
metados_drives[SDL_numcds].device[0] = i;
++SDL_numcds;
}
114
Metaclose(i);
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
}
}
}
/* Fill in our driver capabilities */
SDL_CDcaps.Name = SDL_SYS_CDName;
SDL_CDcaps.Open = SDL_SYS_CDOpen;
SDL_CDcaps.Close = SDL_SYS_CDClose;
SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
SDL_CDcaps.Status = SDL_SYS_CDStatus;
SDL_CDcaps.Play = SDL_SYS_CDPlay;
SDL_CDcaps.Pause = SDL_SYS_CDPause;
SDL_CDcaps.Resume = SDL_SYS_CDResume;
SDL_CDcaps.Stop = SDL_SYS_CDStop;
SDL_CDcaps.Eject = SDL_SYS_CDEject;
return 0;
133
134
}
135
void
136
SDL_SYS_CDQuit(void)
137
{
138
SDL_numcds = 0;
139
140
}
141
static const char *
142
SDL_SYS_CDName(int drive)
143
{
144
return (metados_drives[drive].device);
145
146
}
147
static int
148
SDL_SYS_CDOpen(int drive)
149
{
150
int handle;
151
152
handle =
153
154
Metaopen(metados_drives[drive].device[0],
&(metados_drives[drive].metaopen));
155
156
157
if (handle == 0) {
return drive;
}
158
159
return -1;
160
161
}
162
static void
163
SDL_SYS_CDClose(SDL_CD * cdrom)
164
{
165
Metaclose(metados_drives[cdrom->id].device[0]);
166
167
}
168
static int
169
SDL_SYS_CDioctl(int id, int command, void *arg)
170
{
171
172
173
int retval;
retval =
174
175
Metaioctl(metados_drives[id].device[0], METADOS_IOCTL_MAGIC, command,
arg);
176
if (retval < 0) {
177
SDL_SetError("ioctl() error: %s", strerror(errno));
178
179
}
return (retval);
180
181
}
182
static int
183
SDL_SYS_CDGetTOC(SDL_CD * cdrom)
184
{
185
186
187
188
189
int i, okay;
struct cdrom_tochdr toc;
struct cdrom_tocentry entry;
/* Use standard ioctl() */
190
if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) < 0) {
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
return -1;
}
cdrom->numtracks = toc.cdth_trk1 - toc.cdth_trk0 + 1;
if (cdrom->numtracks > SDL_MAX_TRACKS) {
cdrom->numtracks = SDL_MAX_TRACKS;
}
/* Read all the track TOC entries */
okay = 1;
for (i = 0; i <= cdrom->numtracks; ++i) {
if (i == cdrom->numtracks) {
cdrom->track[i].id = CDROM_LEADOUT;
} else {
cdrom->track[i].id = toc.cdth_trk0 + i;
}
entry.cdte_track = cdrom->track[i].id;
entry.cdte_format = CDROM_MSF;
209
if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, &entry) < 0) {
210
211
212
213
214
215
216
217
218
okay = 0;
break;
} else {
if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
cdrom->track[i].type = SDL_DATA_TRACK;
} else {
cdrom->track[i].type = SDL_AUDIO_TRACK;
}
cdrom->track[i].offset =
219
220
221
MSF_TO_FRAMES(entry.cdte_addr.msf.minute,
entry.cdte_addr.msf.second,
entry.cdte_addr.msf.frame);
222
223
224
225
226
227
228
229
230
cdrom->track[i].length = 0;
if (i > 0) {
cdrom->track[i - 1].length =
cdrom->track[i].offset - cdrom->track[i - 1].offset;
}
}
}
return (okay ? 0 : -1);
231
232
233
}
/* Get CD-ROM status */
234
static CDstatus
235
SDL_SYS_CDStatus(SDL_CD * cdrom, int *position)
236
{
237
238
239
240
241
CDstatus status;
struct cdrom_tochdr toc;
struct cdrom_subchnl info;
info.cdsc_format = CDROM_MSF;
242
243
if (SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0) {
if (ERRNO_TRAYEMPTY(errno)) {
244
245
246
247
248
249
250
251
252
status = CD_TRAYEMPTY;
} else {
status = CD_ERROR;
}
} else {
switch (info.cdsc_audiostatus) {
case CDROM_AUDIO_INVALID:
case CDROM_AUDIO_NO_STATUS:
/* Try to determine if there's a CD available */
253
if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0) {
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
status = CD_STOPPED;
} else {
status = CD_TRAYEMPTY;
}
break;
case CDROM_AUDIO_COMPLETED:
status = CD_STOPPED;
break;
case CDROM_AUDIO_PLAY:
status = CD_PLAYING;
break;
case CDROM_AUDIO_PAUSED:
/* Workaround buggy CD-ROM drive */
if (info.cdsc_trk == CDROM_LEADOUT) {
status = CD_STOPPED;
} else {
status = CD_PAUSED;
}
break;
default:
status = CD_ERROR;
break;
}
}
if (position) {
if (status == CD_PLAYING || (status == CD_PAUSED)) {
280
281
282
*position = MSF_TO_FRAMES(info.cdsc_absaddr.msf.minute,
info.cdsc_absaddr.msf.second,
info.cdsc_absaddr.msf.frame);
283
284
285
286
287
} else {
*position = 0;
}
}
return (status);
288
289
290
}
/* Start play */
291
static int
292
SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length)
293
{
294
struct cdrom_msf playtime;
295
296
297
298
299
300
FRAMES_TO_MSF(start,
&playtime.cdmsf_min0, &playtime.cdmsf_sec0,
&playtime.cdmsf_frame0);
FRAMES_TO_MSF(start + length, &playtime.cdmsf_min1, &playtime.cdmsf_sec1,
&playtime.cdmsf_frame1);
301
#ifdef DEBUG_CDROM
302
303
304
fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
305
#endif
306
307
return SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime);
308
309
310
}
/* Pause play */
311
static int
312
SDL_SYS_CDPause(SDL_CD * cdrom)
313
{
314
return SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0);
315
316
317
}
/* Resume play */
318
static int
319
SDL_SYS_CDResume(SDL_CD * cdrom)
320
{
321
return SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0);
322
323
324
}
/* Stop play */
325
static int
326
SDL_SYS_CDStop(SDL_CD * cdrom)
327
{
328
return SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0);
329
330
331
}
/* Eject the CD-ROM */
332
static int
333
SDL_SYS_CDEject(SDL_CD * cdrom)
334
{
335
return SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0);
336
}
337
338
#endif /* SDL_CDROM_MINT */
339
/* vi: set ts=4 sw=4 expandtab: */