64-bit fixes.
[AROS-Contrib.git] / Games / Quake / cd_audio.c
blob03934220c734f5b6a88c756597469e94f8adc14c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
21 // rights reserved.
23 #include <dpmi.h>
24 #include "quakedef.h"
25 #include "dosisms.h"
27 extern cvar_t bgmvolume;
29 #define ADDRESS_MODE_HSG 0
30 #define ADDRESS_MODE_RED_BOOK 1
32 #define STATUS_ERROR_BIT 0x8000
33 #define STATUS_BUSY_BIT 0x0200
34 #define STATUS_DONE_BIT 0x0100
35 #define STATUS_ERROR_MASK 0x00ff
37 #define ERROR_WRITE_PROTECT 0
38 #define ERROR_UNKNOWN_UNIT 1
39 #define ERROR_DRIVE_NOT_READY 2
40 #define ERROR_UNKNOWN_COMMAND 3
41 #define ERROR_CRC_ERROR 4
42 #define ERROR_BAD_REQUEST_LEN 5
43 #define ERROR_SEEK_ERROR 6
44 #define ERROR_UNKNOWN_MEDIA 7
45 #define ERROR_SECTOR_NOT_FOUND 8
46 #define ERROR_OUT_OF_PAPER 9
47 #define ERROR_WRITE_FAULT 10
48 #define ERROR_READ_FAULT 11
49 #define ERROR_GENERAL_FAILURE 12
50 #define ERROR_RESERVED_13 13
51 #define ERROR_RESERVED_14 14
52 #define ERROR_BAD_DISK_CHANGE 15
54 #define COMMAND_READ 3
55 #define COMMAND_WRITE 12
56 #define COMMAND_PLAY_AUDIO 132
57 #define COMMAND_STOP_AUDIO 133
58 #define COMMAND_RESUME_AUDIO 136
60 #define READ_REQUEST_AUDIO_CHANNEL_INFO 4
61 #define READ_REQUEST_DEVICE_STATUS 6
62 #define READ_REQUEST_MEDIA_CHANGE 9
63 #define READ_REQUEST_AUDIO_DISK_INFO 10
64 #define READ_REQUEST_AUDIO_TRACK_INFO 11
65 #define READ_REQUEST_AUDIO_STATUS 15
67 #define WRITE_REQUEST_EJECT 0
68 #define WRITE_REQUEST_RESET 2
69 #define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3
71 #define STATUS_DOOR_OPEN 0x00000001
72 #define STATUS_DOOR_UNLOCKED 0x00000002
73 #define STATUS_RAW_SUPPORT 0x00000004
74 #define STATUS_READ_WRITE 0x00000008
75 #define STATUS_AUDIO_SUPPORT 0x00000010
76 #define STATUS_INTERLEAVE_SUPPORT 0x00000020
77 #define STATUS_BIT_6_RESERVED 0x00000040
78 #define STATUS_PREFETCH_SUPPORT 0x00000080
79 #define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100
80 #define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200
82 #define MEDIA_NOT_CHANGED 1
83 #define MEDIA_STATUS_UNKNOWN 0
84 #define MEDIA_CHANGED -1
86 #define AUDIO_CONTROL_MASK 0xd0
87 #define AUDIO_CONTROL_DATA_TRACK 0x40
88 #define AUDIO_CONTROL_AUDIO_2_TRACK 0x00
89 #define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10
90 #define AUDIO_CONTROL_AUDIO_4_TRACK 0x80
91 #define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90
93 #define AUDIO_STATUS_PAUSED 0x0001
95 #pragma pack(1)
97 struct playAudioRequest
99 char addressingMode;
100 int startLocation;
101 int sectors;
104 struct readRequest
106 char mediaDescriptor;
107 short bufferOffset;
108 short bufferSegment;
109 short length;
110 short startSector;
111 int volumeID;
114 struct writeRequest
116 char mediaDescriptor;
117 short bufferOffset;
118 short bufferSegment;
119 short length;
120 short startSector;
121 int volumeID;
124 struct cd_request
126 char headerLength;
127 char unit;
128 char command;
129 short status;
130 char reserved[8];
131 union
133 struct playAudioRequest playAudio;
134 struct readRequest read;
135 struct writeRequest write;
136 } x;
140 struct audioChannelInfo_s
142 char code;
143 char channel0input;
144 char channel0volume;
145 char channel1input;
146 char channel1volume;
147 char channel2input;
148 char channel2volume;
149 char channel3input;
150 char channel3volume;
153 struct deviceStatus_s
155 char code;
156 int status;
159 struct mediaChange_s
161 char code;
162 char status;
165 struct audioDiskInfo_s
167 char code;
168 char lowTrack;
169 char highTrack;
170 int leadOutStart;
173 struct audioTrackInfo_s
175 char code;
176 char track;
177 int start;
178 char control;
181 struct audioStatus_s
183 char code;
184 short status;
185 int PRstartLocation;
186 int PRendLocation;
189 struct reset_s
191 char code;
194 union readInfo_u
196 struct audioChannelInfo_s audioChannelInfo;
197 struct deviceStatus_s deviceStatus;
198 struct mediaChange_s mediaChange;
199 struct audioDiskInfo_s audioDiskInfo;
200 struct audioTrackInfo_s audioTrackInfo;
201 struct audioStatus_s audioStatus;
202 struct reset_s reset;
205 #pragma pack()
207 #define MAXIMUM_TRACKS 100
209 typedef struct
211 int start;
212 int length;
213 qboolean isData;
214 } track_info;
216 typedef struct
218 qboolean valid;
219 int leadOutAddress;
220 track_info track[MAXIMUM_TRACKS];
221 byte lowTrack;
222 byte highTrack;
223 } cd_info;
225 static struct cd_request *cdRequest;
226 static union readInfo_u *readInfo;
227 static cd_info cd;
229 static qboolean playing = false;
230 static qboolean wasPlaying = false;
231 static qboolean mediaCheck = false;
232 static qboolean initialized = false;
233 static qboolean enabled = true;
234 static qboolean playLooping = false;
235 static short cdRequestSegment;
236 static short cdRequestOffset;
237 static short readInfoSegment;
238 static short readInfoOffset;
239 static byte remap[256];
240 static byte cdrom;
241 static byte playTrack;
242 static byte cdvolume;
245 static int RedBookToSector(int rb)
247 byte minute;
248 byte second;
249 byte frame;
251 minute = (rb >> 16) & 0xff;
252 second = (rb >> 8) & 0xff;
253 frame = rb & 0xff;
254 return minute * 60 * 75 + second * 75 + frame;
258 static void CDAudio_Reset(void)
260 cdRequest->headerLength = 13;
261 cdRequest->unit = 0;
262 cdRequest->command = COMMAND_WRITE;
263 cdRequest->status = 0;
265 cdRequest->x.write.mediaDescriptor = 0;
266 cdRequest->x.write.bufferOffset = readInfoOffset;
267 cdRequest->x.write.bufferSegment = readInfoSegment;
268 cdRequest->x.write.length = sizeof(struct reset_s);
269 cdRequest->x.write.startSector = 0;
270 cdRequest->x.write.volumeID = 0;
272 readInfo->reset.code = WRITE_REQUEST_RESET;
274 regs.x.ax = 0x1510;
275 regs.x.cx = cdrom;
276 regs.x.es = cdRequestSegment;
277 regs.x.bx = cdRequestOffset;
278 dos_int86 (0x2f);
282 static void CDAudio_Eject(void)
284 cdRequest->headerLength = 13;
285 cdRequest->unit = 0;
286 cdRequest->command = COMMAND_WRITE;
287 cdRequest->status = 0;
289 cdRequest->x.write.mediaDescriptor = 0;
290 cdRequest->x.write.bufferOffset = readInfoOffset;
291 cdRequest->x.write.bufferSegment = readInfoSegment;
292 cdRequest->x.write.length = sizeof(struct reset_s);
293 cdRequest->x.write.startSector = 0;
294 cdRequest->x.write.volumeID = 0;
296 readInfo->reset.code = WRITE_REQUEST_EJECT;
298 regs.x.ax = 0x1510;
299 regs.x.cx = cdrom;
300 regs.x.es = cdRequestSegment;
301 regs.x.bx = cdRequestOffset;
302 dos_int86 (0x2f);
306 static int CDAudio_GetAudioTrackInfo(byte track, int *start)
308 byte control;
310 cdRequest->headerLength = 13;
311 cdRequest->unit = 0;
312 cdRequest->command = COMMAND_READ;
313 cdRequest->status = 0;
315 cdRequest->x.read.mediaDescriptor = 0;
316 cdRequest->x.read.bufferOffset = readInfoOffset;
317 cdRequest->x.read.bufferSegment = readInfoSegment;
318 cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
319 cdRequest->x.read.startSector = 0;
320 cdRequest->x.read.volumeID = 0;
322 readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
323 readInfo->audioTrackInfo.track = track;
325 regs.x.ax = 0x1510;
326 regs.x.cx = cdrom;
327 regs.x.es = cdRequestSegment;
328 regs.x.bx = cdRequestOffset;
329 dos_int86 (0x2f);
331 if (cdRequest->status & STATUS_ERROR_BIT)
333 Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff);
334 return -1;
337 *start = readInfo->audioTrackInfo.start;
338 control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
339 return (control & AUDIO_CONTROL_DATA_TRACK);
343 static int CDAudio_GetAudioDiskInfo(void)
345 int n;
347 cdRequest->headerLength = 13;
348 cdRequest->unit = 0;
349 cdRequest->command = COMMAND_READ;
350 cdRequest->status = 0;
352 cdRequest->x.read.mediaDescriptor = 0;
353 cdRequest->x.read.bufferOffset = readInfoOffset;
354 cdRequest->x.read.bufferSegment = readInfoSegment;
355 cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
356 cdRequest->x.read.startSector = 0;
357 cdRequest->x.read.volumeID = 0;
359 readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
361 regs.x.ax = 0x1510;
362 regs.x.cx = cdrom;
363 regs.x.es = cdRequestSegment;
364 regs.x.bx = cdRequestOffset;
365 dos_int86 (0x2f);
367 if (cdRequest->status & STATUS_ERROR_BIT)
369 Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff);
370 return -1;
373 cd.valid = true;
374 cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
375 cd.highTrack = readInfo->audioDiskInfo.highTrack;
376 cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
378 for (n = cd.lowTrack; n <= cd.highTrack; n++)
380 cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
381 if (n > cd.lowTrack)
383 cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
384 if (n == cd.highTrack)
385 cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
389 return 0;
393 static int CDAudio_GetAudioStatus(void)
395 cdRequest->headerLength = 13;
396 cdRequest->unit = 0;
397 cdRequest->command = COMMAND_READ;
398 cdRequest->status = 0;
400 cdRequest->x.read.mediaDescriptor = 0;
401 cdRequest->x.read.bufferOffset = readInfoOffset;
402 cdRequest->x.read.bufferSegment = readInfoSegment;
403 cdRequest->x.read.length = sizeof(struct audioStatus_s);
404 cdRequest->x.read.startSector = 0;
405 cdRequest->x.read.volumeID = 0;
407 readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
409 regs.x.ax = 0x1510;
410 regs.x.cx = cdrom;
411 regs.x.es = cdRequestSegment;
412 regs.x.bx = cdRequestOffset;
413 dos_int86 (0x2f);
415 if (cdRequest->status & STATUS_ERROR_BIT)
416 return -1;
417 return 0;
421 static int CDAudio_MediaChange(void)
423 cdRequest->headerLength = 13;
424 cdRequest->unit = 0;
425 cdRequest->command = COMMAND_READ;
426 cdRequest->status = 0;
428 cdRequest->x.read.mediaDescriptor = 0;
429 cdRequest->x.read.bufferOffset = readInfoOffset;
430 cdRequest->x.read.bufferSegment = readInfoSegment;
431 cdRequest->x.read.length = sizeof(struct mediaChange_s);
432 cdRequest->x.read.startSector = 0;
433 cdRequest->x.read.volumeID = 0;
435 readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
437 regs.x.ax = 0x1510;
438 regs.x.cx = cdrom;
439 regs.x.es = cdRequestSegment;
440 regs.x.bx = cdRequestOffset;
441 dos_int86 (0x2f);
443 return readInfo->mediaChange.status;
447 // we set the volume to 0 first and then to the desired volume
448 // some cd-rom drivers seem to need it done this way
449 void CDAudio_SetVolume (byte volume)
451 if (!initialized || !enabled)
452 return;
454 cdRequest->headerLength = 13;
455 cdRequest->unit = 0;
456 cdRequest->command = COMMAND_WRITE;
457 cdRequest->status = 0;
459 cdRequest->x.read.mediaDescriptor = 0;
460 cdRequest->x.read.bufferOffset = readInfoOffset;
461 cdRequest->x.read.bufferSegment = readInfoSegment;
462 cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
463 cdRequest->x.read.startSector = 0;
464 cdRequest->x.read.volumeID = 0;
466 readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
467 readInfo->audioChannelInfo.channel0input = 0;
468 readInfo->audioChannelInfo.channel0volume = 0;
469 readInfo->audioChannelInfo.channel1input = 1;
470 readInfo->audioChannelInfo.channel1volume = 0;
471 readInfo->audioChannelInfo.channel2input = 2;
472 readInfo->audioChannelInfo.channel2volume = 0;
473 readInfo->audioChannelInfo.channel3input = 3;
474 readInfo->audioChannelInfo.channel3volume = 0;
476 regs.x.ax = 0x1510;
477 regs.x.cx = cdrom;
478 regs.x.es = cdRequestSegment;
479 regs.x.bx = cdRequestOffset;
480 dos_int86 (0x2f);
482 readInfo->audioChannelInfo.channel0volume = volume;
483 readInfo->audioChannelInfo.channel1volume = volume;
485 regs.x.ax = 0x1510;
486 regs.x.cx = cdrom;
487 regs.x.es = cdRequestSegment;
488 regs.x.bx = cdRequestOffset;
489 dos_int86 (0x2f);
491 cdvolume = volume;
495 void CDAudio_Play(byte track, qboolean looping)
497 int volume;
499 if (!initialized || !enabled)
500 return;
502 if (!cd.valid)
503 return;
505 track = remap[track];
507 if (playing)
509 if (playTrack == track)
510 return;
511 CDAudio_Stop();
514 playLooping = looping;
516 if (track < cd.lowTrack || track > cd.highTrack)
518 Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
519 return;
522 playTrack = track;
524 if (cd.track[track].isData)
526 Con_DPrintf("CDAudio_Play: Can not play data.\n");
527 return;
530 volume = (int)(bgmvolume.value * 255.0);
531 if (volume < 0)
533 Cvar_SetValue ("bgmvolume", 0.0);
534 volume = 0;
536 else if (volume > 255)
538 Cvar_SetValue ("bgmvolume", 1.0);
539 volume = 255;
541 CDAudio_SetVolume (volume);
543 cdRequest->headerLength = 13;
544 cdRequest->unit = 0;
545 cdRequest->command = COMMAND_PLAY_AUDIO;
546 cdRequest->status = 0;
548 cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
549 cdRequest->x.playAudio.startLocation = cd.track[track].start;
550 cdRequest->x.playAudio.sectors = cd.track[track].length;
552 regs.x.ax = 0x1510;
553 regs.x.cx = cdrom;
554 regs.x.es = cdRequestSegment;
555 regs.x.bx = cdRequestOffset;
556 dos_int86 (0x2f);
558 if (cdRequest->status & STATUS_ERROR_BIT)
560 Con_DPrintf("CDAudio_Play: track %u failed\n", track);
561 cd.valid = false;
562 playing = false;
563 return;
566 playing = true;
570 void CDAudio_Stop(void)
572 if (!initialized || !enabled)
573 return;
575 cdRequest->headerLength = 13;
576 cdRequest->unit = 0;
577 cdRequest->command = COMMAND_STOP_AUDIO;
578 cdRequest->status = 0;
580 regs.x.ax = 0x1510;
581 regs.x.cx = cdrom;
582 regs.x.es = cdRequestSegment;
583 regs.x.bx = cdRequestOffset;
584 dos_int86 (0x2f);
586 wasPlaying = playing;
587 playing = false;
591 void CDAudio_Pause(void)
593 CDAudio_Stop();
597 void CDAudio_Resume(void)
599 if (!initialized || !enabled)
600 return;
602 if (!cd.valid)
603 return;
605 if (!wasPlaying)
606 return;
608 cdRequest->headerLength = 13;
609 cdRequest->unit = 0;
610 cdRequest->command = COMMAND_RESUME_AUDIO;
611 cdRequest->status = 0;
613 regs.x.ax = 0x1510;
614 regs.x.cx = cdrom;
615 regs.x.es = cdRequestSegment;
616 regs.x.bx = cdRequestOffset;
617 dos_int86 (0x2f);
619 playing = true;
623 static void CD_f (void)
625 char *command;
626 int ret;
627 int n;
628 int startAddress;
630 if (Cmd_Argc() < 2)
631 return;
633 command = Cmd_Argv (1);
635 if (Q_strcasecmp(command, "on") == 0)
637 enabled = true;
638 return;
641 if (Q_strcasecmp(command, "off") == 0)
643 if (playing)
644 CDAudio_Stop();
645 enabled = false;
646 return;
649 if (Q_strcasecmp(command, "reset") == 0)
651 enabled = true;
652 if (playing)
653 CDAudio_Stop();
654 for (n = 0; n < 256; n++)
655 remap[n] = n;
656 CDAudio_Reset();
657 CDAudio_GetAudioDiskInfo();
658 return;
661 if (Q_strcasecmp(command, "remap") == 0)
663 ret = Cmd_Argc() - 2;
664 if (ret <= 0)
666 for (n = 1; n < 256; n++)
667 if (remap[n] != n)
668 Con_Printf(" %u -> %u\n", n, remap[n]);
669 return;
671 for (n = 1; n <= ret; n++)
672 remap[n] = Q_atoi(Cmd_Argv (n+1));
673 return;
676 if (!cd.valid)
678 Con_Printf("No CD in player.\n");
679 return;
682 if (Q_strcasecmp(command, "play") == 0)
684 CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
685 return;
688 if (Q_strcasecmp(command, "loop") == 0)
690 CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
691 return;
694 if (Q_strcasecmp(command, "stop") == 0)
696 CDAudio_Stop();
697 return;
700 if (Q_strcasecmp(command, "pause") == 0)
702 CDAudio_Pause();
703 return;
706 if (Q_strcasecmp(command, "resume") == 0)
708 CDAudio_Resume();
709 return;
712 if (Q_strcasecmp(command, "eject") == 0)
714 if (playing)
715 CDAudio_Stop();
716 CDAudio_Eject();
717 cd.valid = false;
718 return;
721 if (Q_strcasecmp(command, "info") == 0)
723 Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
724 for (n = cd.lowTrack; n <= cd.highTrack; n++)
726 ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
727 Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
729 if (playing)
730 Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
731 Con_Printf("Volume is %u\n", cdvolume);
732 CDAudio_MediaChange();
733 Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
734 return;
739 void CDAudio_Update(void)
741 int ret;
742 int newVolume;
743 static double lastUpdate;
745 if (!initialized || !enabled)
746 return;
748 if ((realtime - lastUpdate) < 0.25)
749 return;
750 lastUpdate = realtime;
752 if (mediaCheck)
754 static double lastCheck;
756 if ((realtime - lastCheck) < 5.0)
757 return;
758 lastCheck = realtime;
760 ret = CDAudio_MediaChange();
761 if (ret == MEDIA_CHANGED)
763 Con_DPrintf("CDAudio: media changed\n");
764 playing = false;
765 wasPlaying = false;
766 cd.valid = false;
767 CDAudio_GetAudioDiskInfo();
768 return;
772 newVolume = (int)(bgmvolume.value * 255.0);
773 if (newVolume != cdvolume)
775 if (newVolume < 0)
777 Cvar_SetValue ("bgmvolume", 0.0);
778 newVolume = 0;
780 else if (newVolume > 255)
782 Cvar_SetValue ("bgmvolume", 1.0);
783 newVolume = 255;
785 CDAudio_SetVolume (newVolume);
788 if (playing)
790 CDAudio_GetAudioStatus();
791 if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
793 playing = false;
794 if (playLooping)
795 CDAudio_Play(playTrack, true);
801 int CDAudio_Init(void)
803 char *memory;
804 int n;
806 if (cls.state == ca_dedicated)
807 return -1;
809 if (COM_CheckParm("-nocdaudio"))
810 return -1;
812 if (COM_CheckParm("-cdmediacheck"))
813 mediaCheck = true;
815 regs.x.ax = 0x1500;
816 regs.x.bx = 0;
817 dos_int86 (0x2f);
818 if (regs.x.bx == 0)
820 Con_NotifyBox (
821 "MSCDEX not loaded, music is\n"
822 "disabled. Use \"-nocdaudio\" if you\n"
823 "wish to avoid this message in the\n"
824 "future. See README.TXT for help.\n"
826 return -1;
828 if (regs.x.bx > 1)
829 Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
830 cdrom = regs.x.cx;
832 regs.x.ax = 0x150c;
833 regs.x.bx = 0;
834 dos_int86 (0x2f);
835 if (regs.x.bx == 0)
837 Con_NotifyBox (
838 "MSCDEX version 2.00 or later\n"
839 "required for music. See README.TXT\n"
840 "for help.\n"
842 Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
843 return -1;
846 memory = dos_getmemory(sizeof(struct cd_request
847 ) + sizeof(union readInfo_u));
848 if (memory == NULL)
850 Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
851 return -1;
854 cdRequest = (struct cd_request *)memory;
855 cdRequestSegment = ptr2real(cdRequest) >> 4;
856 cdRequestOffset = ptr2real(cdRequest) & 0xf;
858 readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
859 readInfoSegment = ptr2real(readInfo) >> 4;
860 readInfoOffset = ptr2real(readInfo) & 0xf;
862 for (n = 0; n < 256; n++)
863 remap[n] = n;
864 initialized = true;
866 CDAudio_SetVolume (255);
867 if (CDAudio_GetAudioDiskInfo())
869 Con_Printf("CDAudio_Init: No CD in player.\n");
870 enabled = false;
873 Cmd_AddCommand ("cd", CD_f);
875 Con_Printf("CD Audio Initialized\n");
877 return 0;
881 void CDAudio_Shutdown(void)
883 if (!initialized)
884 return;
885 CDAudio_Stop();