summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/cd_linux.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
committerFranklin Wei <git@fwei.tk>2019-07-19 22:37:40 -0400
commit5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4 (patch)
tree84406e21639529a185556a33e5de7f43cffc277b /apps/plugins/sdl/progs/quake/cd_linux.c
parentb70fecf21ddc21877ec1ae7888d9c18a979e37ad (diff)
downloadrockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.tar.gz
rockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.zip
Quake!
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
Diffstat (limited to 'apps/plugins/sdl/progs/quake/cd_linux.c')
-rw-r--r--apps/plugins/sdl/progs/quake/cd_linux.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/cd_linux.c b/apps/plugins/sdl/progs/quake/cd_linux.c
new file mode 100644
index 0000000000..0e23d96035
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/cd_linux.c
@@ -0,0 +1,416 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
21// rights reserved.
22
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <sys/ioctl.h>
27#include <sys/file.h>
28#include <sys/types.h>
29#include <fcntl.h>
30#include <string.h>
31#include <time.h>
32#include <errno.h>
33
34#include <linux/cdrom.h>
35
36#include "quakedef.h"
37
38static qboolean cdValid = false;
39static qboolean playing = false;
40static qboolean wasPlaying = false;
41static qboolean initialized = false;
42static qboolean enabled = true;
43static qboolean playLooping = false;
44static float cdvolume;
45static byte remap[100];
46static byte playTrack;
47static byte maxTrack;
48
49static int cdfile = -1;
50static char cd_dev[64] = "/dev/cdrom";
51
52static void CDAudio_Eject(void)
53{
54 if (cdfile == -1 || !enabled)
55 return; // no cd init'd
56
57 if ( ioctl(cdfile, CDROMEJECT) == -1 )
58 Con_DPrintf("ioctl cdromeject failed\n");
59}
60
61
62static void CDAudio_CloseDoor(void)
63{
64 if (cdfile == -1 || !enabled)
65 return; // no cd init'd
66
67 if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 )
68 Con_DPrintf("ioctl cdromclosetray failed\n");
69}
70
71static int CDAudio_GetAudioDiskInfo(void)
72{
73 struct cdrom_tochdr tochdr;
74
75 cdValid = false;
76
77 if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
78 {
79 Con_DPrintf("ioctl cdromreadtochdr failed\n");
80 return -1;
81 }
82
83 if (tochdr.cdth_trk0 < 1)
84 {
85 Con_DPrintf("CDAudio: no music tracks\n");
86 return -1;
87 }
88
89 cdValid = true;
90 maxTrack = tochdr.cdth_trk1;
91
92 return 0;
93}
94
95
96void CDAudio_Play(byte track, qboolean looping)
97{
98 struct cdrom_tocentry entry;
99 struct cdrom_ti ti;
100
101 if (cdfile == -1 || !enabled)
102 return;
103
104 if (!cdValid)
105 {
106 CDAudio_GetAudioDiskInfo();
107 if (!cdValid)
108 return;
109 }
110
111 track = remap[track];
112
113 if (track < 1 || track > maxTrack)
114 {
115 Con_DPrintf("CDAudio: Bad track number %u.\n", track);
116 return;
117 }
118
119 // don't try to play a non-audio track
120 entry.cdte_track = track;
121 entry.cdte_format = CDROM_MSF;
122 if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
123 {
124 Con_DPrintf("ioctl cdromreadtocentry failed\n");
125 return;
126 }
127 if (entry.cdte_ctrl == CDROM_DATA_TRACK)
128 {
129 Con_Printf("CDAudio: track %i is not audio\n", track);
130 return;
131 }
132
133 if (playing)
134 {
135 if (playTrack == track)
136 return;
137 CDAudio_Stop();
138 }
139
140 ti.cdti_trk0 = track;
141 ti.cdti_trk1 = track;
142 ti.cdti_ind0 = 1;
143 ti.cdti_ind1 = 99;
144
145 if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 )
146 {
147 Con_DPrintf("ioctl cdromplaytrkind failed\n");
148 return;
149 }
150
151 if ( ioctl(cdfile, CDROMRESUME) == -1 )
152 Con_DPrintf("ioctl cdromresume failed\n");
153
154 playLooping = looping;
155 playTrack = track;
156 playing = true;
157
158 if (cdvolume == 0.0)
159 CDAudio_Pause ();
160}
161
162
163void CDAudio_Stop(void)
164{
165 if (cdfile == -1 || !enabled)
166 return;
167
168 if (!playing)
169 return;
170
171 if ( ioctl(cdfile, CDROMSTOP) == -1 )
172 Con_DPrintf("ioctl cdromstop failed (%d)\n", errno);
173
174 wasPlaying = false;
175 playing = false;
176}
177
178void CDAudio_Pause(void)
179{
180 if (cdfile == -1 || !enabled)
181 return;
182
183 if (!playing)
184 return;
185
186 if ( ioctl(cdfile, CDROMPAUSE) == -1 )
187 Con_DPrintf("ioctl cdrompause failed\n");
188
189 wasPlaying = playing;
190 playing = false;
191}
192
193
194void CDAudio_Resume(void)
195{
196 if (cdfile == -1 || !enabled)
197 return;
198
199 if (!cdValid)
200 return;
201
202 if (!wasPlaying)
203 return;
204
205 if ( ioctl(cdfile, CDROMRESUME) == -1 )
206 Con_DPrintf("ioctl cdromresume failed\n");
207 playing = true;
208}
209
210static void CD_f (void)
211{
212 char *command;
213 int ret;
214 int n;
215
216 if (Cmd_Argc() < 2)
217 return;
218
219 command = Cmd_Argv (1);
220
221 if (Q_strcasecmp(command, "on") == 0)
222 {
223 enabled = true;
224 return;
225 }
226
227 if (Q_strcasecmp(command, "off") == 0)
228 {
229 if (playing)
230 CDAudio_Stop();
231 enabled = false;
232 return;
233 }
234
235 if (Q_strcasecmp(command, "reset") == 0)
236 {
237 enabled = true;
238 if (playing)
239 CDAudio_Stop();
240 for (n = 0; n < 100; n++)
241 remap[n] = n;
242 CDAudio_GetAudioDiskInfo();
243 return;
244 }
245
246 if (Q_strcasecmp(command, "remap") == 0)
247 {
248 ret = Cmd_Argc() - 2;
249 if (ret <= 0)
250 {
251 for (n = 1; n < 100; n++)
252 if (remap[n] != n)
253 Con_Printf(" %u -> %u\n", n, remap[n]);
254 return;
255 }
256 for (n = 1; n <= ret; n++)
257 remap[n] = Q_atoi(Cmd_Argv (n+1));
258 return;
259 }
260
261 if (Q_strcasecmp(command, "close") == 0)
262 {
263 CDAudio_CloseDoor();
264 return;
265 }
266
267 if (!cdValid)
268 {
269 CDAudio_GetAudioDiskInfo();
270 if (!cdValid)
271 {
272 Con_Printf("No CD in player.\n");
273 return;
274 }
275 }
276
277 if (Q_strcasecmp(command, "play") == 0)
278 {
279 CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
280 return;
281 }
282
283 if (Q_strcasecmp(command, "loop") == 0)
284 {
285 CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
286 return;
287 }
288
289 if (Q_strcasecmp(command, "stop") == 0)
290 {
291 CDAudio_Stop();
292 return;
293 }
294
295 if (Q_strcasecmp(command, "pause") == 0)
296 {
297 CDAudio_Pause();
298 return;
299 }
300
301 if (Q_strcasecmp(command, "resume") == 0)
302 {
303 CDAudio_Resume();
304 return;
305 }
306
307 if (Q_strcasecmp(command, "eject") == 0)
308 {
309 if (playing)
310 CDAudio_Stop();
311 CDAudio_Eject();
312 cdValid = false;
313 return;
314 }
315
316 if (Q_strcasecmp(command, "info") == 0)
317 {
318 Con_Printf("%u tracks\n", maxTrack);
319 if (playing)
320 Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
321 else if (wasPlaying)
322 Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
323 Con_Printf("Volume is %f\n", cdvolume);
324 return;
325 }
326}
327
328void CDAudio_Update(void)
329{
330 struct cdrom_subchnl subchnl;
331 static time_t lastchk;
332
333 if (!enabled)
334 return;
335
336 if (bgmvolume.value != cdvolume)
337 {
338 if (cdvolume)
339 {
340 Cvar_SetValue ("bgmvolume", 0.0);
341 cdvolume = bgmvolume.value;
342 CDAudio_Pause ();
343 }
344 else
345 {
346 Cvar_SetValue ("bgmvolume", 1.0);
347 cdvolume = bgmvolume.value;
348 CDAudio_Resume ();
349 }
350 }
351
352 if (playing && lastchk < time(NULL)) {
353 lastchk = time(NULL) + 2; //two seconds between chks
354 subchnl.cdsc_format = CDROM_MSF;
355 if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
356 Con_DPrintf("ioctl cdromsubchnl failed\n");
357 playing = false;
358 return;
359 }
360 if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
361 subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
362 playing = false;
363 if (playLooping)
364 CDAudio_Play(playTrack, true);
365 }
366 }
367}
368
369int CDAudio_Init(void)
370{
371 int i;
372
373 if (cls.state == ca_dedicated)
374 return -1;
375
376 if (COM_CheckParm("-nocdaudio"))
377 return -1;
378
379 if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) {
380 strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
381 cd_dev[sizeof(cd_dev) - 1] = 0;
382 }
383
384 if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
385 Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
386 cdfile = -1;
387 return -1;
388 }
389
390 for (i = 0; i < 100; i++)
391 remap[i] = i;
392 initialized = true;
393 enabled = true;
394
395 if (CDAudio_GetAudioDiskInfo())
396 {
397 Con_Printf("CDAudio_Init: No CD in player.\n");
398 cdValid = false;
399 }
400
401 Cmd_AddCommand ("cd", CD_f);
402
403 Con_Printf("CD Audio Initialized\n");
404
405 return 0;
406}
407
408
409void CDAudio_Shutdown(void)
410{
411 if (!initialized)
412 return;
413 CDAudio_Stop();
414 close(cdfile);
415 cdfile = -1;
416}