aboutsummaryrefslogtreecommitdiffstats
path: root/WinQuake/cd_audio.c
diff options
context:
space:
mode:
authorwyatt8740 <wyatt8740@yahoo.com>2014-01-06 12:02:16 -0500
committerwyatt8740 <wyatt8740@yahoo.com>2014-01-06 12:02:16 -0500
commita8f828a066773a59fdf646299359d35ae0e845af (patch)
tree86123409fc6f231cf4136e81159b63cb1e9ec102 /WinQuake/cd_audio.c
parentb2951690415054ae8705c07f8df7a4ba7cde382a (diff)
downloadquake-pum-a8f828a066773a59fdf646299359d35ae0e845af.tar.gz
Removed accidental upload of copyrighted map files
Diffstat (limited to 'WinQuake/cd_audio.c')
-rw-r--r--WinQuake/cd_audio.c1772
1 files changed, 886 insertions, 886 deletions
diff --git a/WinQuake/cd_audio.c b/WinQuake/cd_audio.c
index 0393422..8b15de7 100644
--- a/WinQuake/cd_audio.c
+++ b/WinQuake/cd_audio.c
@@ -1,886 +1,886 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
-// rights reserved.
-
-#include <dpmi.h>
-#include "quakedef.h"
-#include "dosisms.h"
-
-extern cvar_t bgmvolume;
-
-#define ADDRESS_MODE_HSG 0
-#define ADDRESS_MODE_RED_BOOK 1
-
-#define STATUS_ERROR_BIT 0x8000
-#define STATUS_BUSY_BIT 0x0200
-#define STATUS_DONE_BIT 0x0100
-#define STATUS_ERROR_MASK 0x00ff
-
-#define ERROR_WRITE_PROTECT 0
-#define ERROR_UNKNOWN_UNIT 1
-#define ERROR_DRIVE_NOT_READY 2
-#define ERROR_UNKNOWN_COMMAND 3
-#define ERROR_CRC_ERROR 4
-#define ERROR_BAD_REQUEST_LEN 5
-#define ERROR_SEEK_ERROR 6
-#define ERROR_UNKNOWN_MEDIA 7
-#define ERROR_SECTOR_NOT_FOUND 8
-#define ERROR_OUT_OF_PAPER 9
-#define ERROR_WRITE_FAULT 10
-#define ERROR_READ_FAULT 11
-#define ERROR_GENERAL_FAILURE 12
-#define ERROR_RESERVED_13 13
-#define ERROR_RESERVED_14 14
-#define ERROR_BAD_DISK_CHANGE 15
-
-#define COMMAND_READ 3
-#define COMMAND_WRITE 12
-#define COMMAND_PLAY_AUDIO 132
-#define COMMAND_STOP_AUDIO 133
-#define COMMAND_RESUME_AUDIO 136
-
-#define READ_REQUEST_AUDIO_CHANNEL_INFO 4
-#define READ_REQUEST_DEVICE_STATUS 6
-#define READ_REQUEST_MEDIA_CHANGE 9
-#define READ_REQUEST_AUDIO_DISK_INFO 10
-#define READ_REQUEST_AUDIO_TRACK_INFO 11
-#define READ_REQUEST_AUDIO_STATUS 15
-
-#define WRITE_REQUEST_EJECT 0
-#define WRITE_REQUEST_RESET 2
-#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3
-
-#define STATUS_DOOR_OPEN 0x00000001
-#define STATUS_DOOR_UNLOCKED 0x00000002
-#define STATUS_RAW_SUPPORT 0x00000004
-#define STATUS_READ_WRITE 0x00000008
-#define STATUS_AUDIO_SUPPORT 0x00000010
-#define STATUS_INTERLEAVE_SUPPORT 0x00000020
-#define STATUS_BIT_6_RESERVED 0x00000040
-#define STATUS_PREFETCH_SUPPORT 0x00000080
-#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100
-#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200
-
-#define MEDIA_NOT_CHANGED 1
-#define MEDIA_STATUS_UNKNOWN 0
-#define MEDIA_CHANGED -1
-
-#define AUDIO_CONTROL_MASK 0xd0
-#define AUDIO_CONTROL_DATA_TRACK 0x40
-#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00
-#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10
-#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80
-#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90
-
-#define AUDIO_STATUS_PAUSED 0x0001
-
-#pragma pack(1)
-
-struct playAudioRequest
-{
- char addressingMode;
- int startLocation;
- int sectors;
-};
-
-struct readRequest
-{
- char mediaDescriptor;
- short bufferOffset;
- short bufferSegment;
- short length;
- short startSector;
- int volumeID;
-};
-
-struct writeRequest
-{
- char mediaDescriptor;
- short bufferOffset;
- short bufferSegment;
- short length;
- short startSector;
- int volumeID;
-};
-
-struct cd_request
-{
- char headerLength;
- char unit;
- char command;
- short status;
- char reserved[8];
- union
- {
- struct playAudioRequest playAudio;
- struct readRequest read;
- struct writeRequest write;
- } x;
-};
-
-
-struct audioChannelInfo_s
-{
- char code;
- char channel0input;
- char channel0volume;
- char channel1input;
- char channel1volume;
- char channel2input;
- char channel2volume;
- char channel3input;
- char channel3volume;
-};
-
-struct deviceStatus_s
-{
- char code;
- int status;
-};
-
-struct mediaChange_s
-{
- char code;
- char status;
-};
-
-struct audioDiskInfo_s
-{
- char code;
- char lowTrack;
- char highTrack;
- int leadOutStart;
-};
-
-struct audioTrackInfo_s
-{
- char code;
- char track;
- int start;
- char control;
-};
-
-struct audioStatus_s
-{
- char code;
- short status;
- int PRstartLocation;
- int PRendLocation;
-};
-
-struct reset_s
-{
- char code;
-};
-
-union readInfo_u
-{
- struct audioChannelInfo_s audioChannelInfo;
- struct deviceStatus_s deviceStatus;
- struct mediaChange_s mediaChange;
- struct audioDiskInfo_s audioDiskInfo;
- struct audioTrackInfo_s audioTrackInfo;
- struct audioStatus_s audioStatus;
- struct reset_s reset;
-};
-
-#pragma pack()
-
-#define MAXIMUM_TRACKS 100
-
-typedef struct
-{
- int start;
- int length;
- qboolean isData;
-} track_info;
-
-typedef struct
-{
- qboolean valid;
- int leadOutAddress;
- track_info track[MAXIMUM_TRACKS];
- byte lowTrack;
- byte highTrack;
-} cd_info;
-
-static struct cd_request *cdRequest;
-static union readInfo_u *readInfo;
-static cd_info cd;
-
-static qboolean playing = false;
-static qboolean wasPlaying = false;
-static qboolean mediaCheck = false;
-static qboolean initialized = false;
-static qboolean enabled = true;
-static qboolean playLooping = false;
-static short cdRequestSegment;
-static short cdRequestOffset;
-static short readInfoSegment;
-static short readInfoOffset;
-static byte remap[256];
-static byte cdrom;
-static byte playTrack;
-static byte cdvolume;
-
-
-static int RedBookToSector(int rb)
-{
- byte minute;
- byte second;
- byte frame;
-
- minute = (rb >> 16) & 0xff;
- second = (rb >> 8) & 0xff;
- frame = rb & 0xff;
- return minute * 60 * 75 + second * 75 + frame;
-}
-
-
-static void CDAudio_Reset(void)
-{
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_WRITE;
- cdRequest->status = 0;
-
- cdRequest->x.write.mediaDescriptor = 0;
- cdRequest->x.write.bufferOffset = readInfoOffset;
- cdRequest->x.write.bufferSegment = readInfoSegment;
- cdRequest->x.write.length = sizeof(struct reset_s);
- cdRequest->x.write.startSector = 0;
- cdRequest->x.write.volumeID = 0;
-
- readInfo->reset.code = WRITE_REQUEST_RESET;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-}
-
-
-static void CDAudio_Eject(void)
-{
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_WRITE;
- cdRequest->status = 0;
-
- cdRequest->x.write.mediaDescriptor = 0;
- cdRequest->x.write.bufferOffset = readInfoOffset;
- cdRequest->x.write.bufferSegment = readInfoSegment;
- cdRequest->x.write.length = sizeof(struct reset_s);
- cdRequest->x.write.startSector = 0;
- cdRequest->x.write.volumeID = 0;
-
- readInfo->reset.code = WRITE_REQUEST_EJECT;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-}
-
-
-static int CDAudio_GetAudioTrackInfo(byte track, int *start)
-{
- byte control;
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_READ;
- cdRequest->status = 0;
-
- cdRequest->x.read.mediaDescriptor = 0;
- cdRequest->x.read.bufferOffset = readInfoOffset;
- cdRequest->x.read.bufferSegment = readInfoSegment;
- cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
- cdRequest->x.read.startSector = 0;
- cdRequest->x.read.volumeID = 0;
-
- readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
- readInfo->audioTrackInfo.track = track;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- if (cdRequest->status & STATUS_ERROR_BIT)
- {
- Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff);
- return -1;
- }
-
- *start = readInfo->audioTrackInfo.start;
- control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
- return (control & AUDIO_CONTROL_DATA_TRACK);
-}
-
-
-static int CDAudio_GetAudioDiskInfo(void)
-{
- int n;
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_READ;
- cdRequest->status = 0;
-
- cdRequest->x.read.mediaDescriptor = 0;
- cdRequest->x.read.bufferOffset = readInfoOffset;
- cdRequest->x.read.bufferSegment = readInfoSegment;
- cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
- cdRequest->x.read.startSector = 0;
- cdRequest->x.read.volumeID = 0;
-
- readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- if (cdRequest->status & STATUS_ERROR_BIT)
- {
- Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff);
- return -1;
- }
-
- cd.valid = true;
- cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
- cd.highTrack = readInfo->audioDiskInfo.highTrack;
- cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
-
- for (n = cd.lowTrack; n <= cd.highTrack; n++)
- {
- cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
- if (n > cd.lowTrack)
- {
- cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
- if (n == cd.highTrack)
- cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
- }
- }
-
- return 0;
-}
-
-
-static int CDAudio_GetAudioStatus(void)
-{
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_READ;
- cdRequest->status = 0;
-
- cdRequest->x.read.mediaDescriptor = 0;
- cdRequest->x.read.bufferOffset = readInfoOffset;
- cdRequest->x.read.bufferSegment = readInfoSegment;
- cdRequest->x.read.length = sizeof(struct audioStatus_s);
- cdRequest->x.read.startSector = 0;
- cdRequest->x.read.volumeID = 0;
-
- readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- if (cdRequest->status & STATUS_ERROR_BIT)
- return -1;
- return 0;
-}
-
-
-static int CDAudio_MediaChange(void)
-{
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_READ;
- cdRequest->status = 0;
-
- cdRequest->x.read.mediaDescriptor = 0;
- cdRequest->x.read.bufferOffset = readInfoOffset;
- cdRequest->x.read.bufferSegment = readInfoSegment;
- cdRequest->x.read.length = sizeof(struct mediaChange_s);
- cdRequest->x.read.startSector = 0;
- cdRequest->x.read.volumeID = 0;
-
- readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- return readInfo->mediaChange.status;
-}
-
-
-// we set the volume to 0 first and then to the desired volume
-// some cd-rom drivers seem to need it done this way
-void CDAudio_SetVolume (byte volume)
-{
- if (!initialized || !enabled)
- return;
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_WRITE;
- cdRequest->status = 0;
-
- cdRequest->x.read.mediaDescriptor = 0;
- cdRequest->x.read.bufferOffset = readInfoOffset;
- cdRequest->x.read.bufferSegment = readInfoSegment;
- cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
- cdRequest->x.read.startSector = 0;
- cdRequest->x.read.volumeID = 0;
-
- readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
- readInfo->audioChannelInfo.channel0input = 0;
- readInfo->audioChannelInfo.channel0volume = 0;
- readInfo->audioChannelInfo.channel1input = 1;
- readInfo->audioChannelInfo.channel1volume = 0;
- readInfo->audioChannelInfo.channel2input = 2;
- readInfo->audioChannelInfo.channel2volume = 0;
- readInfo->audioChannelInfo.channel3input = 3;
- readInfo->audioChannelInfo.channel3volume = 0;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- readInfo->audioChannelInfo.channel0volume = volume;
- readInfo->audioChannelInfo.channel1volume = volume;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- cdvolume = volume;
-}
-
-
-void CDAudio_Play(byte track, qboolean looping)
-{
- int volume;
-
- if (!initialized || !enabled)
- return;
-
- if (!cd.valid)
- return;
-
- track = remap[track];
-
- if (playing)
- {
- if (playTrack == track)
- return;
- CDAudio_Stop();
- }
-
- playLooping = looping;
-
- if (track < cd.lowTrack || track > cd.highTrack)
- {
- Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
- return;
- }
-
- playTrack = track;
-
- if (cd.track[track].isData)
- {
- Con_DPrintf("CDAudio_Play: Can not play data.\n");
- return;
- }
-
- volume = (int)(bgmvolume.value * 255.0);
- if (volume < 0)
- {
- Cvar_SetValue ("bgmvolume", 0.0);
- volume = 0;
- }
- else if (volume > 255)
- {
- Cvar_SetValue ("bgmvolume", 1.0);
- volume = 255;
- }
- CDAudio_SetVolume (volume);
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_PLAY_AUDIO;
- cdRequest->status = 0;
-
- cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
- cdRequest->x.playAudio.startLocation = cd.track[track].start;
- cdRequest->x.playAudio.sectors = cd.track[track].length;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- if (cdRequest->status & STATUS_ERROR_BIT)
- {
- Con_DPrintf("CDAudio_Play: track %u failed\n", track);
- cd.valid = false;
- playing = false;
- return;
- }
-
- playing = true;
-}
-
-
-void CDAudio_Stop(void)
-{
- if (!initialized || !enabled)
- return;
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_STOP_AUDIO;
- cdRequest->status = 0;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- wasPlaying = playing;
- playing = false;
-}
-
-
-void CDAudio_Pause(void)
-{
- CDAudio_Stop();
-}
-
-
-void CDAudio_Resume(void)
-{
- if (!initialized || !enabled)
- return;
-
- if (!cd.valid)
- return;
-
- if (!wasPlaying)
- return;
-
- cdRequest->headerLength = 13;
- cdRequest->unit = 0;
- cdRequest->command = COMMAND_RESUME_AUDIO;
- cdRequest->status = 0;
-
- regs.x.ax = 0x1510;
- regs.x.cx = cdrom;
- regs.x.es = cdRequestSegment;
- regs.x.bx = cdRequestOffset;
- dos_int86 (0x2f);
-
- playing = true;
-}
-
-
-static void CD_f (void)
-{
- char *command;
- int ret;
- int n;
- int startAddress;
-
- if (Cmd_Argc() < 2)
- return;
-
- command = Cmd_Argv (1);
-
- if (Q_strcasecmp(command, "on") == 0)
- {
- enabled = true;
- return;
- }
-
- if (Q_strcasecmp(command, "off") == 0)
- {
- if (playing)
- CDAudio_Stop();
- enabled = false;
- return;
- }
-
- if (Q_strcasecmp(command, "reset") == 0)
- {
- enabled = true;
- if (playing)
- CDAudio_Stop();
- for (n = 0; n < 256; n++)
- remap[n] = n;
- CDAudio_Reset();
- CDAudio_GetAudioDiskInfo();
- return;
- }
-
- if (Q_strcasecmp(command, "remap") == 0)
- {
- ret = Cmd_Argc() - 2;
- if (ret <= 0)
- {
- for (n = 1; n < 256; n++)
- if (remap[n] != n)
- Con_Printf(" %u -> %u\n", n, remap[n]);
- return;
- }
- for (n = 1; n <= ret; n++)
- remap[n] = Q_atoi(Cmd_Argv (n+1));
- return;
- }
-
- if (!cd.valid)
- {
- Con_Printf("No CD in player.\n");
- return;
- }
-
- if (Q_strcasecmp(command, "play") == 0)
- {
- CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
- return;
- }
-
- if (Q_strcasecmp(command, "loop") == 0)
- {
- CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
- return;
- }
-
- if (Q_strcasecmp(command, "stop") == 0)
- {
- CDAudio_Stop();
- return;
- }
-
- if (Q_strcasecmp(command, "pause") == 0)
- {
- CDAudio_Pause();
- return;
- }
-
- if (Q_strcasecmp(command, "resume") == 0)
- {
- CDAudio_Resume();
- return;
- }
-
- if (Q_strcasecmp(command, "eject") == 0)
- {
- if (playing)
- CDAudio_Stop();
- CDAudio_Eject();
- cd.valid = false;
- return;
- }
-
- if (Q_strcasecmp(command, "info") == 0)
- {
- Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
- for (n = cd.lowTrack; n <= cd.highTrack; n++)
- {
- ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
- Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
- }
- if (playing)
- Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
- Con_Printf("Volume is %u\n", cdvolume);
- CDAudio_MediaChange();
- Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
- return;
- }
-}
-
-
-void CDAudio_Update(void)
-{
- int ret;
- int newVolume;
- static double lastUpdate;
-
- if (!initialized || !enabled)
- return;
-
- if ((realtime - lastUpdate) < 0.25)
- return;
- lastUpdate = realtime;
-
- if (mediaCheck)
- {
- static double lastCheck;
-
- if ((realtime - lastCheck) < 5.0)
- return;
- lastCheck = realtime;
-
- ret = CDAudio_MediaChange();
- if (ret == MEDIA_CHANGED)
- {
- Con_DPrintf("CDAudio: media changed\n");
- playing = false;
- wasPlaying = false;
- cd.valid = false;
- CDAudio_GetAudioDiskInfo();
- return;
- }
- }
-
- newVolume = (int)(bgmvolume.value * 255.0);
- if (newVolume != cdvolume)
- {
- if (newVolume < 0)
- {
- Cvar_SetValue ("bgmvolume", 0.0);
- newVolume = 0;
- }
- else if (newVolume > 255)
- {
- Cvar_SetValue ("bgmvolume", 1.0);
- newVolume = 255;
- }
- CDAudio_SetVolume (newVolume);
- }
-
- if (playing)
- {
- CDAudio_GetAudioStatus();
- if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
- {
- playing = false;
- if (playLooping)
- CDAudio_Play(playTrack, true);
- }
- }
-}
-
-
-int CDAudio_Init(void)
-{
- char *memory;
- int n;
-
- if (cls.state == ca_dedicated)
- return -1;
-
- if (COM_CheckParm("-nocdaudio"))
- return -1;
-
- if (COM_CheckParm("-cdmediacheck"))
- mediaCheck = true;
-
- regs.x.ax = 0x1500;
- regs.x.bx = 0;
- dos_int86 (0x2f);
- if (regs.x.bx == 0)
- {
- Con_NotifyBox (
- "MSCDEX not loaded, music is\n"
- "disabled. Use \"-nocdaudio\" if you\n"
- "wish to avoid this message in the\n"
- "future. See README.TXT for help.\n"
- );
- return -1;
- }
- if (regs.x.bx > 1)
- Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
- cdrom = regs.x.cx;
-
- regs.x.ax = 0x150c;
- regs.x.bx = 0;
- dos_int86 (0x2f);
- if (regs.x.bx == 0)
- {
- Con_NotifyBox (
- "MSCDEX version 2.00 or later\n"
- "required for music. See README.TXT\n"
- "for help.\n"
- );
- Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
- return -1;
- }
-
- memory = dos_getmemory(sizeof(struct cd_request
-) + sizeof(union readInfo_u));
- if (memory == NULL)
- {
- Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
- return -1;
- }
-
- cdRequest = (struct cd_request *)memory;
- cdRequestSegment = ptr2real(cdRequest) >> 4;
- cdRequestOffset = ptr2real(cdRequest) & 0xf;
-
- readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
- readInfoSegment = ptr2real(readInfo) >> 4;
- readInfoOffset = ptr2real(readInfo) & 0xf;
-
- for (n = 0; n < 256; n++)
- remap[n] = n;
- initialized = true;
-
- CDAudio_SetVolume (255);
- if (CDAudio_GetAudioDiskInfo())
- {
- Con_Printf("CDAudio_Init: No CD in player.\n");
- enabled = false;
- }
-
- Cmd_AddCommand ("cd", CD_f);
-
- Con_Printf("CD Audio Initialized\n");
-
- return 0;
-}
-
-
-void CDAudio_Shutdown(void)
-{
- if (!initialized)
- return;
- CDAudio_Stop();
-}
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <dpmi.h>
+#include "quakedef.h"
+#include "dosisms.h"
+
+extern cvar_t bgmvolume;
+
+#define ADDRESS_MODE_HSG 0
+#define ADDRESS_MODE_RED_BOOK 1
+
+#define STATUS_ERROR_BIT 0x8000
+#define STATUS_BUSY_BIT 0x0200
+#define STATUS_DONE_BIT 0x0100
+#define STATUS_ERROR_MASK 0x00ff
+
+#define ERROR_WRITE_PROTECT 0
+#define ERROR_UNKNOWN_UNIT 1
+#define ERROR_DRIVE_NOT_READY 2
+#define ERROR_UNKNOWN_COMMAND 3
+#define ERROR_CRC_ERROR 4
+#define ERROR_BAD_REQUEST_LEN 5
+#define ERROR_SEEK_ERROR 6
+#define ERROR_UNKNOWN_MEDIA 7
+#define ERROR_SECTOR_NOT_FOUND 8
+#define ERROR_OUT_OF_PAPER 9
+#define ERROR_WRITE_FAULT 10
+#define ERROR_READ_FAULT 11
+#define ERROR_GENERAL_FAILURE 12
+#define ERROR_RESERVED_13 13
+#define ERROR_RESERVED_14 14
+#define ERROR_BAD_DISK_CHANGE 15
+
+#define COMMAND_READ 3
+#define COMMAND_WRITE 12
+#define COMMAND_PLAY_AUDIO 132
+#define COMMAND_STOP_AUDIO 133
+#define COMMAND_RESUME_AUDIO 136
+
+#define READ_REQUEST_AUDIO_CHANNEL_INFO 4
+#define READ_REQUEST_DEVICE_STATUS 6
+#define READ_REQUEST_MEDIA_CHANGE 9
+#define READ_REQUEST_AUDIO_DISK_INFO 10
+#define READ_REQUEST_AUDIO_TRACK_INFO 11
+#define READ_REQUEST_AUDIO_STATUS 15
+
+#define WRITE_REQUEST_EJECT 0
+#define WRITE_REQUEST_RESET 2
+#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3
+
+#define STATUS_DOOR_OPEN 0x00000001
+#define STATUS_DOOR_UNLOCKED 0x00000002
+#define STATUS_RAW_SUPPORT 0x00000004
+#define STATUS_READ_WRITE 0x00000008
+#define STATUS_AUDIO_SUPPORT 0x00000010
+#define STATUS_INTERLEAVE_SUPPORT 0x00000020
+#define STATUS_BIT_6_RESERVED 0x00000040
+#define STATUS_PREFETCH_SUPPORT 0x00000080
+#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100
+#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200
+
+#define MEDIA_NOT_CHANGED 1
+#define MEDIA_STATUS_UNKNOWN 0
+#define MEDIA_CHANGED -1
+
+#define AUDIO_CONTROL_MASK 0xd0
+#define AUDIO_CONTROL_DATA_TRACK 0x40
+#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00
+#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10
+#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80
+#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90
+
+#define AUDIO_STATUS_PAUSED 0x0001
+
+#pragma pack(1)
+
+struct playAudioRequest
+{
+ char addressingMode;
+ int startLocation;
+ int sectors;
+};
+
+struct readRequest
+{
+ char mediaDescriptor;
+ short bufferOffset;
+ short bufferSegment;
+ short length;
+ short startSector;
+ int volumeID;
+};
+
+struct writeRequest
+{
+ char mediaDescriptor;
+ short bufferOffset;
+ short bufferSegment;
+ short length;
+ short startSector;
+ int volumeID;
+};
+
+struct cd_request
+{
+ char headerLength;
+ char unit;
+ char command;
+ short status;
+ char reserved[8];
+ union
+ {
+ struct playAudioRequest playAudio;
+ struct readRequest read;
+ struct writeRequest write;
+ } x;
+};
+
+
+struct audioChannelInfo_s
+{
+ char code;
+ char channel0input;
+ char channel0volume;
+ char channel1input;
+ char channel1volume;
+ char channel2input;
+ char channel2volume;
+ char channel3input;
+ char channel3volume;
+};
+
+struct deviceStatus_s
+{
+ char code;
+ int status;
+};
+
+struct mediaChange_s
+{
+ char code;
+ char status;
+};
+
+struct audioDiskInfo_s
+{
+ char code;
+ char lowTrack;
+ char highTrack;
+ int leadOutStart;
+};
+
+struct audioTrackInfo_s
+{
+ char code;
+ char track;
+ int start;
+ char control;
+};
+
+struct audioStatus_s
+{
+ char code;
+ short status;
+ int PRstartLocation;
+ int PRendLocation;
+};
+
+struct reset_s
+{
+ char code;
+};
+
+union readInfo_u
+{
+ struct audioChannelInfo_s audioChannelInfo;
+ struct deviceStatus_s deviceStatus;
+ struct mediaChange_s mediaChange;
+ struct audioDiskInfo_s audioDiskInfo;
+ struct audioTrackInfo_s audioTrackInfo;
+ struct audioStatus_s audioStatus;
+ struct reset_s reset;
+};
+
+#pragma pack()
+
+#define MAXIMUM_TRACKS 100
+
+typedef struct
+{
+ int start;
+ int length;
+ qboolean isData;
+} track_info;
+
+typedef struct
+{
+ qboolean valid;
+ int leadOutAddress;
+ track_info track[MAXIMUM_TRACKS];
+ byte lowTrack;
+ byte highTrack;
+} cd_info;
+
+static struct cd_request *cdRequest;
+static union readInfo_u *readInfo;
+static cd_info cd;
+
+static qboolean playing = false;
+static qboolean wasPlaying = false;
+static qboolean mediaCheck = false;
+static qboolean initialized = false;
+static qboolean enabled = true;
+static qboolean playLooping = false;
+static short cdRequestSegment;
+static short cdRequestOffset;
+static short readInfoSegment;
+static short readInfoOffset;
+static byte remap[256];
+static byte cdrom;
+static byte playTrack;
+static byte cdvolume;
+
+
+static int RedBookToSector(int rb)
+{
+ byte minute;
+ byte second;
+ byte frame;
+
+ minute = (rb >> 16) & 0xff;
+ second = (rb >> 8) & 0xff;
+ frame = rb & 0xff;
+ return minute * 60 * 75 + second * 75 + frame;
+}
+
+
+static void CDAudio_Reset(void)
+{
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_WRITE;
+ cdRequest->status = 0;
+
+ cdRequest->x.write.mediaDescriptor = 0;
+ cdRequest->x.write.bufferOffset = readInfoOffset;
+ cdRequest->x.write.bufferSegment = readInfoSegment;
+ cdRequest->x.write.length = sizeof(struct reset_s);
+ cdRequest->x.write.startSector = 0;
+ cdRequest->x.write.volumeID = 0;
+
+ readInfo->reset.code = WRITE_REQUEST_RESET;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+}
+
+
+static void CDAudio_Eject(void)
+{
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_WRITE;
+ cdRequest->status = 0;
+
+ cdRequest->x.write.mediaDescriptor = 0;
+ cdRequest->x.write.bufferOffset = readInfoOffset;
+ cdRequest->x.write.bufferSegment = readInfoSegment;
+ cdRequest->x.write.length = sizeof(struct reset_s);
+ cdRequest->x.write.startSector = 0;
+ cdRequest->x.write.volumeID = 0;
+
+ readInfo->reset.code = WRITE_REQUEST_EJECT;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+}
+
+
+static int CDAudio_GetAudioTrackInfo(byte track, int *start)
+{
+ byte control;
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_READ;
+ cdRequest->status = 0;
+
+ cdRequest->x.read.mediaDescriptor = 0;
+ cdRequest->x.read.bufferOffset = readInfoOffset;
+ cdRequest->x.read.bufferSegment = readInfoSegment;
+ cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
+ cdRequest->x.read.startSector = 0;
+ cdRequest->x.read.volumeID = 0;
+
+ readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
+ readInfo->audioTrackInfo.track = track;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ if (cdRequest->status & STATUS_ERROR_BIT)
+ {
+ Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff);
+ return -1;
+ }
+
+ *start = readInfo->audioTrackInfo.start;
+ control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
+ return (control & AUDIO_CONTROL_DATA_TRACK);
+}
+
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+ int n;
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_READ;
+ cdRequest->status = 0;
+
+ cdRequest->x.read.mediaDescriptor = 0;
+ cdRequest->x.read.bufferOffset = readInfoOffset;
+ cdRequest->x.read.bufferSegment = readInfoSegment;
+ cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
+ cdRequest->x.read.startSector = 0;
+ cdRequest->x.read.volumeID = 0;
+
+ readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ if (cdRequest->status & STATUS_ERROR_BIT)
+ {
+ Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff);
+ return -1;
+ }
+
+ cd.valid = true;
+ cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
+ cd.highTrack = readInfo->audioDiskInfo.highTrack;
+ cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
+
+ for (n = cd.lowTrack; n <= cd.highTrack; n++)
+ {
+ cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
+ if (n > cd.lowTrack)
+ {
+ cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
+ if (n == cd.highTrack)
+ cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
+ }
+ }
+
+ return 0;
+}
+
+
+static int CDAudio_GetAudioStatus(void)
+{
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_READ;
+ cdRequest->status = 0;
+
+ cdRequest->x.read.mediaDescriptor = 0;
+ cdRequest->x.read.bufferOffset = readInfoOffset;
+ cdRequest->x.read.bufferSegment = readInfoSegment;
+ cdRequest->x.read.length = sizeof(struct audioStatus_s);
+ cdRequest->x.read.startSector = 0;
+ cdRequest->x.read.volumeID = 0;
+
+ readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ if (cdRequest->status & STATUS_ERROR_BIT)
+ return -1;
+ return 0;
+}
+
+
+static int CDAudio_MediaChange(void)
+{
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_READ;
+ cdRequest->status = 0;
+
+ cdRequest->x.read.mediaDescriptor = 0;
+ cdRequest->x.read.bufferOffset = readInfoOffset;
+ cdRequest->x.read.bufferSegment = readInfoSegment;
+ cdRequest->x.read.length = sizeof(struct mediaChange_s);
+ cdRequest->x.read.startSector = 0;
+ cdRequest->x.read.volumeID = 0;
+
+ readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ return readInfo->mediaChange.status;
+}
+
+
+// we set the volume to 0 first and then to the desired volume
+// some cd-rom drivers seem to need it done this way
+void CDAudio_SetVolume (byte volume)
+{
+ if (!initialized || !enabled)
+ return;
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_WRITE;
+ cdRequest->status = 0;
+
+ cdRequest->x.read.mediaDescriptor = 0;
+ cdRequest->x.read.bufferOffset = readInfoOffset;
+ cdRequest->x.read.bufferSegment = readInfoSegment;
+ cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
+ cdRequest->x.read.startSector = 0;
+ cdRequest->x.read.volumeID = 0;
+
+ readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
+ readInfo->audioChannelInfo.channel0input = 0;
+ readInfo->audioChannelInfo.channel0volume = 0;
+ readInfo->audioChannelInfo.channel1input = 1;
+ readInfo->audioChannelInfo.channel1volume = 0;
+ readInfo->audioChannelInfo.channel2input = 2;
+ readInfo->audioChannelInfo.channel2volume = 0;
+ readInfo->audioChannelInfo.channel3input = 3;
+ readInfo->audioChannelInfo.channel3volume = 0;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ readInfo->audioChannelInfo.channel0volume = volume;
+ readInfo->audioChannelInfo.channel1volume = volume;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ cdvolume = volume;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+ int volume;
+
+ if (!initialized || !enabled)
+ return;
+
+ if (!cd.valid)
+ return;
+
+ track = remap[track];
+
+ if (playing)
+ {
+ if (playTrack == track)
+ return;
+ CDAudio_Stop();
+ }
+
+ playLooping = looping;
+
+ if (track < cd.lowTrack || track > cd.highTrack)
+ {
+ Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
+ return;
+ }
+
+ playTrack = track;
+
+ if (cd.track[track].isData)
+ {
+ Con_DPrintf("CDAudio_Play: Can not play data.\n");
+ return;
+ }
+
+ volume = (int)(bgmvolume.value * 255.0);
+ if (volume < 0)
+ {
+ Cvar_SetValue ("bgmvolume", 0.0);
+ volume = 0;
+ }
+ else if (volume > 255)
+ {
+ Cvar_SetValue ("bgmvolume", 1.0);
+ volume = 255;
+ }
+ CDAudio_SetVolume (volume);
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_PLAY_AUDIO;
+ cdRequest->status = 0;
+
+ cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
+ cdRequest->x.playAudio.startLocation = cd.track[track].start;
+ cdRequest->x.playAudio.sectors = cd.track[track].length;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ if (cdRequest->status & STATUS_ERROR_BIT)
+ {
+ Con_DPrintf("CDAudio_Play: track %u failed\n", track);
+ cd.valid = false;
+ playing = false;
+ return;
+ }
+
+ playing = true;
+}
+
+
+void CDAudio_Stop(void)
+{
+ if (!initialized || !enabled)
+ return;
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_STOP_AUDIO;
+ cdRequest->status = 0;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ wasPlaying = playing;
+ playing = false;
+}
+
+
+void CDAudio_Pause(void)
+{
+ CDAudio_Stop();
+}
+
+
+void CDAudio_Resume(void)
+{
+ if (!initialized || !enabled)
+ return;
+
+ if (!cd.valid)
+ return;
+
+ if (!wasPlaying)
+ return;
+
+ cdRequest->headerLength = 13;
+ cdRequest->unit = 0;
+ cdRequest->command = COMMAND_RESUME_AUDIO;
+ cdRequest->status = 0;
+
+ regs.x.ax = 0x1510;
+ regs.x.cx = cdrom;
+ regs.x.es = cdRequestSegment;
+ regs.x.bx = cdRequestOffset;
+ dos_int86 (0x2f);
+
+ playing = true;
+}
+
+
+static void CD_f (void)
+{
+ char *command;
+ int ret;
+ int n;
+ int startAddress;
+
+ if (Cmd_Argc() < 2)
+ return;
+
+ command = Cmd_Argv (1);
+
+ if (Q_strcasecmp(command, "on") == 0)
+ {
+ enabled = true;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "off") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ enabled = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "reset") == 0)
+ {
+ enabled = true;
+ if (playing)
+ CDAudio_Stop();
+ for (n = 0; n < 256; n++)
+ remap[n] = n;
+ CDAudio_Reset();
+ CDAudio_GetAudioDiskInfo();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "remap") == 0)
+ {
+ ret = Cmd_Argc() - 2;
+ if (ret <= 0)
+ {
+ for (n = 1; n < 256; n++)
+ if (remap[n] != n)
+ Con_Printf(" %u -> %u\n", n, remap[n]);
+ return;
+ }
+ for (n = 1; n <= ret; n++)
+ remap[n] = Q_atoi(Cmd_Argv (n+1));
+ return;
+ }
+
+ if (!cd.valid)
+ {
+ Con_Printf("No CD in player.\n");
+ return;
+ }
+
+ if (Q_strcasecmp(command, "play") == 0)
+ {
+ CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "loop") == 0)
+ {
+ CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "stop") == 0)
+ {
+ CDAudio_Stop();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "pause") == 0)
+ {
+ CDAudio_Pause();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "resume") == 0)
+ {
+ CDAudio_Resume();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "eject") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ CDAudio_Eject();
+ cd.valid = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "info") == 0)
+ {
+ Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
+ for (n = cd.lowTrack; n <= cd.highTrack; n++)
+ {
+ ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
+ Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
+ }
+ if (playing)
+ Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+ Con_Printf("Volume is %u\n", cdvolume);
+ CDAudio_MediaChange();
+ Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
+ return;
+ }
+}
+
+
+void CDAudio_Update(void)
+{
+ int ret;
+ int newVolume;
+ static double lastUpdate;
+
+ if (!initialized || !enabled)
+ return;
+
+ if ((realtime - lastUpdate) < 0.25)
+ return;
+ lastUpdate = realtime;
+
+ if (mediaCheck)
+ {
+ static double lastCheck;
+
+ if ((realtime - lastCheck) < 5.0)
+ return;
+ lastCheck = realtime;
+
+ ret = CDAudio_MediaChange();
+ if (ret == MEDIA_CHANGED)
+ {
+ Con_DPrintf("CDAudio: media changed\n");
+ playing = false;
+ wasPlaying = false;
+ cd.valid = false;
+ CDAudio_GetAudioDiskInfo();
+ return;
+ }
+ }
+
+ newVolume = (int)(bgmvolume.value * 255.0);
+ if (newVolume != cdvolume)
+ {
+ if (newVolume < 0)
+ {
+ Cvar_SetValue ("bgmvolume", 0.0);
+ newVolume = 0;
+ }
+ else if (newVolume > 255)
+ {
+ Cvar_SetValue ("bgmvolume", 1.0);
+ newVolume = 255;
+ }
+ CDAudio_SetVolume (newVolume);
+ }
+
+ if (playing)
+ {
+ CDAudio_GetAudioStatus();
+ if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
+ {
+ playing = false;
+ if (playLooping)
+ CDAudio_Play(playTrack, true);
+ }
+ }
+}
+
+
+int CDAudio_Init(void)
+{
+ char *memory;
+ int n;
+
+ if (cls.state == ca_dedicated)
+ return -1;
+
+ if (COM_CheckParm("-nocdaudio"))
+ return -1;
+
+ if (COM_CheckParm("-cdmediacheck"))
+ mediaCheck = true;
+
+ regs.x.ax = 0x1500;
+ regs.x.bx = 0;
+ dos_int86 (0x2f);
+ if (regs.x.bx == 0)
+ {
+ Con_NotifyBox (
+ "MSCDEX not loaded, music is\n"
+ "disabled. Use \"-nocdaudio\" if you\n"
+ "wish to avoid this message in the\n"
+ "future. See README.TXT for help.\n"
+ );
+ return -1;
+ }
+ if (regs.x.bx > 1)
+ Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
+ cdrom = regs.x.cx;
+
+ regs.x.ax = 0x150c;
+ regs.x.bx = 0;
+ dos_int86 (0x2f);
+ if (regs.x.bx == 0)
+ {
+ Con_NotifyBox (
+ "MSCDEX version 2.00 or later\n"
+ "required for music. See README.TXT\n"
+ "for help.\n"
+ );
+ Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
+ return -1;
+ }
+
+ memory = dos_getmemory(sizeof(struct cd_request
+) + sizeof(union readInfo_u));
+ if (memory == NULL)
+ {
+ Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
+ return -1;
+ }
+
+ cdRequest = (struct cd_request *)memory;
+ cdRequestSegment = ptr2real(cdRequest) >> 4;
+ cdRequestOffset = ptr2real(cdRequest) & 0xf;
+
+ readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
+ readInfoSegment = ptr2real(readInfo) >> 4;
+ readInfoOffset = ptr2real(readInfo) & 0xf;
+
+ for (n = 0; n < 256; n++)
+ remap[n] = n;
+ initialized = true;
+
+ CDAudio_SetVolume (255);
+ if (CDAudio_GetAudioDiskInfo())
+ {
+ Con_Printf("CDAudio_Init: No CD in player.\n");
+ enabled = false;
+ }
+
+ Cmd_AddCommand ("cd", CD_f);
+
+ Con_Printf("CD Audio Initialized\n");
+
+ return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+ if (!initialized)
+ return;
+ CDAudio_Stop();
+}