Mercurial > sdl-ios-xcode
annotate src/cdrom/openbsd/SDL_syscdrom.c @ 1554:0ca607a5d173
Fixed bug #84
Date: Sun, 23 Oct 2005 16:39:03 +0200
From: "A. Schmid" <sahib@phreaker.net>
Subject: [SDL] no software surfaces with svgalib driver?
Hi,
I noticed that the SDL (1.2.9) svgalib driver only makes use of linear
addressable (framebuffer) video modes. On older systems (like one of
mine), linear addressable modes are often not available.
Especially for cards with VESA VBE < 2.0 the svgalib vesa driver is
unusable, since VESA only supports framebuffering for VBE 2.0 and later.
The changes necessary to add support for software surfaces seem to be
relatively small. I only had to hack src/video/svga/SDL_svgavideo.c (see
attached patch). The code worked fine for me, but it is no more than a
proof of concept and should be reviewed (probably has a memory leak when
switching modes). It also uses the vgagl library (included in the
svgalib package) and needs to be linked against it.
-Alex
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 19 Mar 2006 12:04:40 +0000 |
parents | d910939febfa |
children | 92947e3a18db |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
25
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
24 /* Functions for system-level CD-ROM audio control */ | |
25 | |
26 #include <sys/types.h> | |
27 #include <sys/ioctl.h> | |
28 #include <sys/stat.h> | |
29 #include <fcntl.h> | |
30 #include <errno.h> | |
31 #include <unistd.h> | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
32 #include <sys/ioctl.h> |
0 | 33 #include <sys/cdio.h> |
34 | |
35 #include "SDL_cdrom.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
36 #include "../SDL_syscdrom.h" |
0 | 37 |
38 | |
39 /* The maximum number of CD-ROM drives we'll detect */ | |
40 #define MAX_DRIVES 16 | |
41 | |
42 /* A list of available CD-ROM drives */ | |
43 static char *SDL_cdlist[MAX_DRIVES]; | |
44 static dev_t SDL_cdmode[MAX_DRIVES]; | |
45 | |
46 /* The system-dependent CD control functions */ | |
47 static const char *SDL_SYS_CDName(int drive); | |
48 static int SDL_SYS_CDOpen(int drive); | |
49 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
50 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
51 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
52 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
53 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
54 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
55 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
56 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
57 | |
58 /* Some ioctl() errno values which occur when the tray is empty */ | |
59 #define ERRNO_TRAYEMPTY(errno) \ | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
60 ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL) || \ |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
61 (errno == ENODEV)) |
0 | 62 |
63 /* Check a drive to see if it is a CD-ROM */ | |
64 static int CheckDrive(char *drive, struct stat *stbuf) | |
65 { | |
66 int is_cd, cdfd; | |
67 struct ioc_read_subchannel info; | |
68 | |
69 /* If it doesn't exist, return -1 */ | |
70 if ( stat(drive, stbuf) < 0 ) { | |
71 return(-1); | |
72 } | |
73 | |
74 /* If it does exist, verify that it's an available CD-ROM */ | |
75 is_cd = 0; | |
76 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { | |
77 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); | |
78 if ( cdfd >= 0 ) { | |
79 info.address_format = CD_MSF_FORMAT; | |
80 info.data_format = CD_CURRENT_POSITION; | |
81 info.data_len = 0; | |
82 info.data = NULL; | |
83 /* Under Linux, EIO occurs when a disk is not present. | |
84 This isn't 100% reliable, so we use the USE_MNTENT | |
85 code above instead. | |
86 */ | |
87 if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) || | |
88 ERRNO_TRAYEMPTY(errno) ) { | |
89 is_cd = 1; | |
90 } | |
91 close(cdfd); | |
92 } | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
93 else if (ERRNO_TRAYEMPTY(errno)) |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
94 is_cd = 1; |
0 | 95 } |
96 return(is_cd); | |
97 } | |
98 | |
99 /* Add a CD-ROM drive to our list of valid drives */ | |
100 static void AddDrive(char *drive, struct stat *stbuf) | |
101 { | |
102 int i; | |
103 | |
104 if ( SDL_numcds < MAX_DRIVES ) { | |
105 /* Check to make sure it's not already in our list. | |
106 This can happen when we see a drive via symbolic link. | |
107 */ | |
108 for ( i=0; i<SDL_numcds; ++i ) { | |
109 if ( stbuf->st_rdev == SDL_cdmode[i] ) { | |
110 #ifdef DEBUG_CDROM | |
111 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); | |
112 #endif | |
113 return; | |
114 } | |
115 } | |
116 | |
117 /* Add this drive to our list */ | |
118 i = SDL_numcds; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
119 SDL_cdlist[i] = SDL_strdup(drive); |
0 | 120 if ( SDL_cdlist[i] == NULL ) { |
121 SDL_OutOfMemory(); | |
122 return; | |
123 } | |
124 SDL_cdmode[i] = stbuf->st_rdev; | |
125 ++SDL_numcds; | |
126 #ifdef DEBUG_CDROM | |
127 fprintf(stderr, "Added CD-ROM drive: %s\n", drive); | |
128 #endif | |
129 } | |
130 } | |
131 | |
132 int SDL_SYS_CDInit(void) | |
133 { | |
134 static char *checklist[] = { | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
135 #if defined(__OPENBSD__) |
25
3fbf86244fd2
Date: Wed, 9 May 2001 18:03:20 -0600
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
136 "?0 cd?c", "cdrom", NULL |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
137 #elif defined(__NETBSD__) |
1026
0f3aa6ab3341
Select patches included from The NetBSD Package Collection (www.pkgsrc.org)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
138 "?0 cd?d", "?0 cd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
139 #else |
0 | 140 "?0 cd?c", "?0 acd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
141 #endif |
0 | 142 }; |
143 char *SDLcdrom; | |
144 int i, j, exists; | |
145 char drive[32]; | |
146 struct stat stbuf; | |
147 | |
148 /* Fill in our driver capabilities */ | |
149 SDL_CDcaps.Name = SDL_SYS_CDName; | |
150 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
151 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
152 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
153 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
154 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
155 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
156 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
157 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
158 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
159 | |
160 /* Look in the environment for our CD-ROM drive list */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
161 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ |
0 | 162 if ( SDLcdrom != NULL ) { |
163 char *cdpath, *delim; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
164 size_t len = SDL_strlen(SDLcdrom)+1; |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
165 cdpath = SDL_stack_alloc(char, len); |
0 | 166 if ( cdpath != NULL ) { |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
167 SDL_strlcpy(cdpath, SDLcdrom, len); |
0 | 168 SDLcdrom = cdpath; |
169 do { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
170 delim = SDL_strchr(SDLcdrom, ':'); |
0 | 171 if ( delim ) { |
172 *delim++ = '\0'; | |
173 } | |
174 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { | |
175 AddDrive(SDLcdrom, &stbuf); | |
176 } | |
177 if ( delim ) { | |
178 SDLcdrom = delim; | |
179 } else { | |
180 SDLcdrom = NULL; | |
181 } | |
182 } while ( SDLcdrom ); | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
183 SDL_stack_free(cdpath); |
0 | 184 } |
185 | |
186 /* If we found our drives, there's nothing left to do */ | |
187 if ( SDL_numcds > 0 ) { | |
188 return(0); | |
189 } | |
190 } | |
191 | |
192 /* Scan the system for CD-ROM drives */ | |
193 for ( i=0; checklist[i]; ++i ) { | |
194 if ( checklist[i][0] == '?' ) { | |
195 char *insert; | |
196 exists = 1; | |
197 for ( j=checklist[i][1]; exists; ++j ) { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
198 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
199 insert = SDL_strchr(drive, '?'); |
0 | 200 if ( insert != NULL ) { |
201 *insert = j; | |
202 } | |
203 switch (CheckDrive(drive, &stbuf)) { | |
204 /* Drive exists and is a CD-ROM */ | |
205 case 1: | |
206 AddDrive(drive, &stbuf); | |
207 break; | |
208 /* Drive exists, but isn't a CD-ROM */ | |
209 case 0: | |
210 break; | |
211 /* Drive doesn't exist */ | |
212 case -1: | |
213 exists = 0; | |
214 break; | |
215 } | |
216 } | |
217 } else { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
218 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); |
0 | 219 if ( CheckDrive(drive, &stbuf) > 0 ) { |
220 AddDrive(drive, &stbuf); | |
221 } | |
222 } | |
223 } | |
224 return(0); | |
225 } | |
226 | |
227 /* General ioctl() CD-ROM command function */ | |
228 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
229 { | |
230 int retval; | |
231 | |
232 retval = ioctl(id, command, arg); | |
233 if ( retval < 0 ) { | |
234 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
235 } | |
236 return(retval); | |
237 } | |
238 | |
239 static const char *SDL_SYS_CDName(int drive) | |
240 { | |
241 return(SDL_cdlist[drive]); | |
242 } | |
243 | |
244 static int SDL_SYS_CDOpen(int drive) | |
245 { | |
246 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); | |
247 } | |
248 | |
249 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
250 { | |
251 struct ioc_toc_header toc; | |
252 int i, okay; | |
253 struct ioc_read_toc_entry entry; | |
254 struct cd_toc_entry data; | |
255 | |
256 okay = 0; | |
257 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) { | |
258 cdrom->numtracks = toc.ending_track-toc.starting_track+1; | |
259 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
260 cdrom->numtracks = SDL_MAX_TRACKS; | |
261 } | |
262 /* Read all the track TOC entries */ | |
263 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
264 if ( i == cdrom->numtracks ) { | |
265 cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */ | |
266 } else { | |
267 cdrom->track[i].id = toc.starting_track+i; | |
268 } | |
269 entry.starting_track = cdrom->track[i].id; | |
270 entry.address_format = CD_MSF_FORMAT; | |
271 entry.data_len = sizeof(data); | |
272 entry.data = &data; | |
273 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS, | |
274 &entry) < 0 ) { | |
275 break; | |
276 } else { | |
277 cdrom->track[i].type = data.control; | |
278 cdrom->track[i].offset = MSF_TO_FRAMES( | |
279 data.addr.msf.minute, | |
280 data.addr.msf.second, | |
281 data.addr.msf.frame); | |
282 cdrom->track[i].length = 0; | |
283 if ( i > 0 ) { | |
284 cdrom->track[i-1].length = | |
285 cdrom->track[i].offset- | |
286 cdrom->track[i-1].offset; | |
287 } | |
288 } | |
289 } | |
290 if ( i == (cdrom->numtracks+1) ) { | |
291 okay = 1; | |
292 } | |
293 } | |
294 return(okay ? 0 : -1); | |
295 } | |
296 | |
297 /* Get CD-ROM status */ | |
298 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
299 { | |
300 CDstatus status; | |
301 struct ioc_toc_header toc; | |
302 struct ioc_read_subchannel info; | |
303 struct cd_sub_channel_info data; | |
304 | |
305 info.address_format = CD_MSF_FORMAT; | |
306 info.data_format = CD_CURRENT_POSITION; | |
307 info.track = 0; | |
308 info.data_len = sizeof(data); | |
309 info.data = &data; | |
310 if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) { | |
311 if ( ERRNO_TRAYEMPTY(errno) ) { | |
312 status = CD_TRAYEMPTY; | |
313 } else { | |
314 status = CD_ERROR; | |
315 } | |
316 } else { | |
317 switch (data.header.audio_status) { | |
318 case CD_AS_AUDIO_INVALID: | |
319 case CD_AS_NO_STATUS: | |
320 /* Try to determine if there's a CD available */ | |
321 if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0) | |
322 status = CD_STOPPED; | |
323 else | |
324 status = CD_TRAYEMPTY; | |
325 break; | |
326 case CD_AS_PLAY_COMPLETED: | |
327 status = CD_STOPPED; | |
328 break; | |
329 case CD_AS_PLAY_IN_PROGRESS: | |
330 status = CD_PLAYING; | |
331 break; | |
332 case CD_AS_PLAY_PAUSED: | |
333 status = CD_PAUSED; | |
334 break; | |
335 default: | |
336 status = CD_ERROR; | |
337 break; | |
338 } | |
339 } | |
340 if ( position ) { | |
341 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
342 *position = MSF_TO_FRAMES( | |
343 data.what.position.absaddr.msf.minute, | |
344 data.what.position.absaddr.msf.second, | |
345 data.what.position.absaddr.msf.frame); | |
346 } else { | |
347 *position = 0; | |
348 } | |
349 } | |
350 return(status); | |
351 } | |
352 | |
353 /* Start play */ | |
354 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
355 { | |
356 struct ioc_play_msf playtime; | |
357 | |
358 FRAMES_TO_MSF(start, | |
359 &playtime.start_m, &playtime.start_s, &playtime.start_f); | |
360 FRAMES_TO_MSF(start+length, | |
361 &playtime.end_m, &playtime.end_s, &playtime.end_f); | |
362 #ifdef DEBUG_CDROM | |
363 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
364 playtime.start_m, playtime.start_s, playtime.start_f, | |
365 playtime.end_m, playtime.end_s, playtime.end_f); | |
366 #endif | |
367 ioctl(cdrom->id, CDIOCSTART, 0); | |
368 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime)); | |
369 } | |
370 | |
371 /* Pause play */ | |
372 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
373 { | |
374 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0)); | |
375 } | |
376 | |
377 /* Resume play */ | |
378 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
379 { | |
380 return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0)); | |
381 } | |
382 | |
383 /* Stop play */ | |
384 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
385 { | |
386 return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0)); | |
387 } | |
388 | |
389 /* Eject the CD-ROM */ | |
390 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
391 { | |
392 return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0)); | |
393 } | |
394 | |
395 /* Close the CD-ROM handle */ | |
396 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
397 { | |
398 close(cdrom->id); | |
399 } | |
400 | |
401 void SDL_SYS_CDQuit(void) | |
402 { | |
403 int i; | |
404 | |
405 if ( SDL_numcds > 0 ) { | |
406 for ( i=0; i<SDL_numcds; ++i ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
407 SDL_free(SDL_cdlist[i]); |
0 | 408 } |
409 SDL_numcds = 0; | |
410 } | |
411 } | |
412 |