1// #include <dpmi.h> 2#include "quakedef.h" 3// #include "dosisms.h" 4 5extern cvar_t bgmvolume; 6 7#define ADDRESS_MODE_HSG 0 8#define ADDRESS_MODE_RED_BOOK 1 9 10#define STATUS_ERROR_BIT 0x8000 11#define STATUS_BUSY_BIT 0x0200 12#define STATUS_DONE_BIT 0x0100 13#define STATUS_ERROR_MASK 0x00ff 14 15#define ERROR_WRITE_PROTECT 0 16#define ERROR_UNKNOWN_UNIT 1 17#define ERROR_DRIVE_NOT_READY 2 18#define ERROR_UNKNOWN_COMMAND 3 19#define ERROR_CRC_ERROR 4 20#define ERROR_BAD_REQUEST_LEN 5 21#define ERROR_SEEK_ERROR 6 22#define ERROR_UNKNOWN_MEDIA 7 23#define ERROR_SECTOR_NOT_FOUND 8 24#define ERROR_OUT_OF_PAPER 9 25#define ERROR_WRITE_FAULT 10 26#define ERROR_READ_FAULT 11 27#define ERROR_GENERAL_FAILURE 12 28#define ERROR_RESERVED_13 13 29#define ERROR_RESERVED_14 14 30#define ERROR_BAD_DISK_CHANGE 15 31 32#define COMMAND_READ 3 33#define COMMAND_WRITE 12 34#define COMMAND_PLAY_AUDIO 132 35#define COMMAND_STOP_AUDIO 133 36#define COMMAND_RESUME_AUDIO 136 37 38#define READ_REQUEST_AUDIO_CHANNEL_INFO 4 39#define READ_REQUEST_DEVICE_STATUS 6 40#define READ_REQUEST_MEDIA_CHANGE 9 41#define READ_REQUEST_AUDIO_DISK_INFO 10 42#define READ_REQUEST_AUDIO_TRACK_INFO 11 43#define READ_REQUEST_AUDIO_STATUS 15 44 45#define WRITE_REQUEST_EJECT 0 46#define WRITE_REQUEST_RESET 2 47#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3 48 49#define STATUS_DOOR_OPEN 0x00000001 50#define STATUS_DOOR_UNLOCKED 0x00000002 51#define STATUS_RAW_SUPPORT 0x00000004 52#define STATUS_READ_WRITE 0x00000008 53#define STATUS_AUDIO_SUPPORT 0x00000010 54#define STATUS_INTERLEAVE_SUPPORT 0x00000020 55#define STATUS_BIT_6_RESERVED 0x00000040 56#define STATUS_PREFETCH_SUPPORT 0x00000080 57#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100 58#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200 59 60#define MEDIA_NOT_CHANGED 1 61#define MEDIA_STATUS_UNKNOWN 0 62#define MEDIA_CHANGED -1 63 64#define AUDIO_CONTROL_MASK 0xd0 65#define AUDIO_CONTROL_DATA_TRACK 0x40 66#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00 67#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10 68#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80 69#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90 70 71#define AUDIO_STATUS_PAUSED 0x0001 72 73#pragma pack(1) 74 75struct playAudioRequest 76{ 77 char addressingMode; 78 int startLocation; 79 int sectors; 80}; 81 82struct readRequest 83{ 84 char mediaDescriptor; 85 short bufferOffset; 86 short bufferSegment; 87 short length; 88 short startSector; 89 int volumeID; 90}; 91 92struct writeRequest 93{ 94 char mediaDescriptor; 95 short bufferOffset; 96 short bufferSegment; 97 short length; 98 short startSector; 99 int volumeID; 100}; 101 102struct cd_request 103{ 104 char headerLength; 105 char unit; 106 char command; 107 short status; 108 char reserved[8]; 109 union 110 { 111 struct playAudioRequest playAudio; 112 struct readRequest read; 113 struct writeRequest write; 114 } x; 115}; 116 117 118struct audioChannelInfo_s 119{ 120 char code; 121 char channel0input; 122 char channel0volume; 123 char channel1input; 124 char channel1volume; 125 char channel2input; 126 char channel2volume; 127 char channel3input; 128 char channel3volume; 129}; 130 131struct deviceStatus_s 132{ 133 char code; 134 int status; 135}; 136 137struct mediaChange_s 138{ 139 char code; 140 char status; 141}; 142 143struct audioDiskInfo_s 144{ 145 char code; 146 char lowTrack; 147 char highTrack; 148 int leadOutStart; 149}; 150 151struct audioTrackInfo_s 152{ 153 char code; 154 char track; 155 int start; 156 char control; 157}; 158 159struct audioStatus_s 160{ 161 char code; 162 short status; 163 int PRstartLocation; 164 int PRendLocation; 165}; 166 167struct reset_s 168{ 169 char code; 170}; 171 172union readInfo_u 173{ 174 struct audioChannelInfo_s audioChannelInfo; 175 struct deviceStatus_s deviceStatus; 176 struct mediaChange_s mediaChange; 177 struct audioDiskInfo_s audioDiskInfo; 178 struct audioTrackInfo_s audioTrackInfo; 179 struct audioStatus_s audioStatus; 180 struct reset_s reset; 181}; 182 183#pragma pack() 184 185#define MAXIMUM_TRACKS 32 186 187typedef struct 188{ 189 int start; 190 int length; 191 qboolean isData; 192} track_info; 193 194typedef struct 195{ 196 qboolean valid; 197 int leadOutAddress; 198 track_info track[MAXIMUM_TRACKS]; 199 byte lowTrack; 200 byte highTrack; 201} cd_info; 202 203static struct cd_request *cdRequest; 204static union readInfo_u *readInfo; 205static cd_info cd; 206 207static qboolean playing = false; 208static qboolean wasPlaying = false; 209static qboolean mediaCheck = false; 210static qboolean initialized = false; 211static qboolean enabled = true; 212static qboolean playLooping = false; 213static short cdRequestSegment; 214static short cdRequestOffset; 215static short readInfoSegment; 216static short readInfoOffset; 217static byte remap[256]; 218static byte cdrom; 219static byte playTrack; 220static byte cdvolume; 221 222 223static int RedBookToSector(int rb) 224{ 225 byte minute; 226 byte second; 227 byte frame; 228 229 minute = (rb >> 16) & 0xff; 230 second = (rb >> 8) & 0xff; 231 frame = rb & 0xff; 232 return minute * 60 * 75 + second * 75 + frame; 233} 234 235 236static void CDAudio_Reset(void) 237{ 238#if 0 239 cdRequest->headerLength = 13; 240 cdRequest->unit = 0; 241 cdRequest->command = COMMAND_WRITE; 242 cdRequest->status = 0; 243 244 cdRequest->x.write.mediaDescriptor = 0; 245 cdRequest->x.write.bufferOffset = readInfoOffset; 246 cdRequest->x.write.bufferSegment = readInfoSegment; 247 cdRequest->x.write.length = sizeof(struct reset_s); 248 cdRequest->x.write.startSector = 0; 249 cdRequest->x.write.volumeID = 0; 250 251 readInfo->reset.code = WRITE_REQUEST_RESET; 252 253 regs.x.ax = 0x1510; 254 regs.x.cx = cdrom; 255 regs.x.es = cdRequestSegment; 256 regs.x.bx = cdRequestOffset; 257 dos_int86 (0x2f); 258 259#endif 260} 261 262 263static void CDAudio_Eject(void) 264{ 265#if 0 266 cdRequest->headerLength = 13; 267 cdRequest->unit = 0; 268 cdRequest->command = COMMAND_WRITE; 269 cdRequest->status = 0; 270 271 cdRequest->x.write.mediaDescriptor = 0; 272 cdRequest->x.write.bufferOffset = readInfoOffset; 273 cdRequest->x.write.bufferSegment = readInfoSegment; 274 cdRequest->x.write.length = sizeof(struct reset_s); 275 cdRequest->x.write.startSector = 0; 276 cdRequest->x.write.volumeID = 0; 277 278 readInfo->reset.code = WRITE_REQUEST_EJECT; 279 280 regs.x.ax = 0x1510; 281 regs.x.cx = cdrom; 282 regs.x.es = cdRequestSegment; 283 regs.x.bx = cdRequestOffset; 284 dos_int86 (0x2f); 285 286#endif 287 288} 289 290 291static int CDAudio_GetAudioTrackInfo(byte track, int *start) 292{ 293#if 0 294 byte control; 295 296 cdRequest->headerLength = 13; 297 cdRequest->unit = 0; 298 cdRequest->command = COMMAND_READ; 299 cdRequest->status = 0; 300 301 cdRequest->x.read.mediaDescriptor = 0; 302 cdRequest->x.read.bufferOffset = readInfoOffset; 303 cdRequest->x.read.bufferSegment = readInfoSegment; 304 cdRequest->x.read.length = sizeof(struct audioTrackInfo_s); 305 cdRequest->x.read.startSector = 0; 306 cdRequest->x.read.volumeID = 0; 307 308 readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO; 309 readInfo->audioTrackInfo.track = track; 310 311 regs.x.ax = 0x1510; 312 regs.x.cx = cdrom; 313 regs.x.es = cdRequestSegment; 314 regs.x.bx = cdRequestOffset; 315 dos_int86 (0x2f); 316 317 if (cdRequest->status & STATUS_ERROR_BIT) 318 { 319 Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff); 320 return -1; 321 } 322 323 *start = readInfo->audioTrackInfo.start; 324 control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK; 325 return (control & AUDIO_CONTROL_DATA_TRACK); 326 327#endif 328 329 return 0; 330 331} 332 333 334static int CDAudio_GetAudioDiskInfo(void) 335{ 336#if 0 337 int n; 338 339 cdRequest->headerLength = 13; 340 cdRequest->unit = 0; 341 cdRequest->command = COMMAND_READ; 342 cdRequest->status = 0; 343 344 cdRequest->x.read.mediaDescriptor = 0; 345 cdRequest->x.read.bufferOffset = readInfoOffset; 346 cdRequest->x.read.bufferSegment = readInfoSegment; 347 cdRequest->x.read.length = sizeof(struct audioDiskInfo_s); 348 cdRequest->x.read.startSector = 0; 349 cdRequest->x.read.volumeID = 0; 350 351 readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO; 352 353 regs.x.ax = 0x1510; 354 regs.x.cx = cdrom; 355 regs.x.es = cdRequestSegment; 356 regs.x.bx = cdRequestOffset; 357 dos_int86 (0x2f); 358 359 if (cdRequest->status & STATUS_ERROR_BIT) 360 { 361 Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff); 362 return -1; 363 } 364 365 cd.valid = true; 366 cd.lowTrack = readInfo->audioDiskInfo.lowTrack; 367 cd.highTrack = readInfo->audioDiskInfo.highTrack; 368 cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart; 369 370 for (n = cd.lowTrack; n <= cd.highTrack; n++) 371 { 372 cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start); 373 if (n > cd.lowTrack) 374 { 375 cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start); 376 if (n == cd.highTrack) 377 cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start); 378 } 379 } 380 381#endif 382 383 return 0; 384} 385 386 387static int CDAudio_GetAudioStatus(void) 388{ 389#if 0 390 cdRequest->headerLength = 13; 391 cdRequest->unit = 0; 392 cdRequest->command = COMMAND_READ; 393 cdRequest->status = 0; 394 395 cdRequest->x.read.mediaDescriptor = 0; 396 cdRequest->x.read.bufferOffset = readInfoOffset; 397 cdRequest->x.read.bufferSegment = readInfoSegment; 398 cdRequest->x.read.length = sizeof(struct audioStatus_s); 399 cdRequest->x.read.startSector = 0; 400 cdRequest->x.read.volumeID = 0; 401 402 readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS; 403 404 regs.x.ax = 0x1510; 405 regs.x.cx = cdrom; 406 regs.x.es = cdRequestSegment; 407 regs.x.bx = cdRequestOffset; 408 dos_int86 (0x2f); 409 410 if (cdRequest->status & STATUS_ERROR_BIT) 411 return -1; 412 return 0; 413#endif 414 return 0; 415} 416 417 418static int CDAudio_MediaChange(void) 419{ 420#if 0 421 cdRequest->headerLength = 13; 422 cdRequest->unit = 0; 423 cdRequest->command = COMMAND_READ; 424 cdRequest->status = 0; 425 426 cdRequest->x.read.mediaDescriptor = 0; 427 cdRequest->x.read.bufferOffset = readInfoOffset; 428 cdRequest->x.read.bufferSegment = readInfoSegment; 429 cdRequest->x.read.length = sizeof(struct mediaChange_s); 430 cdRequest->x.read.startSector = 0; 431 cdRequest->x.read.volumeID = 0; 432 433 readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE; 434 435 regs.x.ax = 0x1510; 436 regs.x.cx = cdrom; 437 regs.x.es = cdRequestSegment; 438 regs.x.bx = cdRequestOffset; 439 dos_int86 (0x2f); 440 441 return readInfo->mediaChange.status; 442#endif 443 return 0; 444} 445 446 447byte CDAudio_GetVolume (void) 448{ 449 return cdvolume; 450} 451 452 453// we set the volume to 0 first and then to the desired volume 454// some cd-rom drivers seem to need it done this way 455void CDAudio_SetVolume (byte volume) 456{ 457 if (!initialized || !enabled) 458 return; 459 460#if 0 461 462 cdRequest->headerLength = 13; 463 cdRequest->unit = 0; 464 cdRequest->command = COMMAND_WRITE; 465 cdRequest->status = 0; 466 467 cdRequest->x.read.mediaDescriptor = 0; 468 cdRequest->x.read.bufferOffset = readInfoOffset; 469 cdRequest->x.read.bufferSegment = readInfoSegment; 470 cdRequest->x.read.length = sizeof(struct audioChannelInfo_s); 471 cdRequest->x.read.startSector = 0; 472 cdRequest->x.read.volumeID = 0; 473 474 readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO; 475 readInfo->audioChannelInfo.channel0input = 0; 476 readInfo->audioChannelInfo.channel0volume = 0; 477 readInfo->audioChannelInfo.channel1input = 1; 478 readInfo->audioChannelInfo.channel1volume = 0; 479 readInfo->audioChannelInfo.channel2input = 2; 480 readInfo->audioChannelInfo.channel2volume = 0; 481 readInfo->audioChannelInfo.channel3input = 3; 482 readInfo->audioChannelInfo.channel3volume = 0; 483 484 regs.x.ax = 0x1510; 485 regs.x.cx = cdrom; 486 regs.x.es = cdRequestSegment; 487 regs.x.bx = cdRequestOffset; 488 dos_int86 (0x2f); 489 490 readInfo->audioChannelInfo.channel0volume = volume; 491 readInfo->audioChannelInfo.channel1volume = volume; 492 493 regs.x.ax = 0x1510; 494 regs.x.cx = cdrom; 495 regs.x.es = cdRequestSegment; 496 regs.x.bx = cdRequestOffset; 497 dos_int86 (0x2f); 498 499#endif 500 501 cdvolume = volume; 502} 503 504 505void CDAudio_Play(byte track, qboolean looping) 506{ 507 508#if 0 509 if (!initialized || !enabled) 510 return; 511 512 if (!cd.valid) 513 return; 514 515 track = remap[track]; 516 517 if (playing) 518 { 519 if (playTrack == track) 520 return; 521 CDAudio_Stop(); 522 } 523 524 playLooping = looping; 525 526 if (track < cd.lowTrack || track > cd.highTrack) 527 { 528 Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track); 529 return; 530 } 531 532 playTrack = track; 533 534 if (cd.track[track].isData) 535 { 536 Con_DPrintf("CDAudio_Play: Can not play data.\n"); 537 return; 538 } 539 540 cdRequest->headerLength = 13; 541 cdRequest->unit = 0; 542 cdRequest->command = COMMAND_PLAY_AUDIO; 543 cdRequest->status = 0; 544 545 cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK; 546 cdRequest->x.playAudio.startLocation = cd.track[track].start; 547 cdRequest->x.playAudio.sectors = cd.track[track].length; 548 549 regs.x.ax = 0x1510; 550 regs.x.cx = cdrom; 551 regs.x.es = cdRequestSegment; 552 regs.x.bx = cdRequestOffset; 553 dos_int86 (0x2f); 554 555 if (cdRequest->status & STATUS_ERROR_BIT) 556 { 557 Con_DPrintf("CDAudio_Play: track %u failed\n", track); 558 cd.valid = false; 559 playing = false; 560 return; 561 } 562 563#endif 564 565 playing = true; 566} 567 568 569void CDAudio_Stop(void) 570{ 571 if (!initialized || !enabled) 572 return; 573 574#if 0 575 cdRequest->headerLength = 13; 576 cdRequest->unit = 0; 577 cdRequest->command = COMMAND_STOP_AUDIO; 578 cdRequest->status = 0; 579 580 regs.x.ax = 0x1510; 581 regs.x.cx = cdrom; 582 regs.x.es = cdRequestSegment; 583 regs.x.bx = cdRequestOffset; 584 dos_int86 (0x2f); 585#endif 586 587 wasPlaying = playing; 588 playing = false; 589} 590 591 592void CDAudio_Resume(void) 593{ 594 if (!initialized || !enabled) 595 return; 596 597 if (!cd.valid) 598 return; 599 600 if (!wasPlaying) 601 return; 602 603#if 0 604 cdRequest->headerLength = 13; 605 cdRequest->unit = 0; 606 cdRequest->command = COMMAND_RESUME_AUDIO; 607 cdRequest->status = 0; 608 609 regs.x.ax = 0x1510; 610 regs.x.cx = cdrom; 611 regs.x.es = cdRequestSegment; 612 regs.x.bx = cdRequestOffset; 613 dos_int86 (0x2f); 614#endif 615 616 playing = true; 617} 618 619static void CD_f (void) 620{ 621 char *command; 622 int ret; 623 int n; 624 int startAddress; 625 startAddress = 0; 626 627 if (Cmd_Argc() < 2) 628 return; 629 630 command = Cmd_Argv (1); 631 632 if (Q_strcasecmp(command, "on") == 0) 633 { 634 enabled = true; 635 return; 636 } 637 638 if (Q_strcasecmp(command, "off") == 0) 639 { 640 if (playing) 641 CDAudio_Stop(); 642 enabled = false; 643 return; 644 } 645 646 if (Q_strcasecmp(command, "reset") == 0) 647 { 648 enabled = true; 649 if (playing) 650 CDAudio_Stop(); 651 for (n = 0; n < 256; n++) 652 remap[n] = n; 653 CDAudio_Reset(); 654 CDAudio_GetAudioDiskInfo(); 655 return; 656 } 657 658 if (Q_strcasecmp(command, "remap") == 0) 659 { 660 ret = Cmd_Argc() - 2; 661 if (ret <= 0) 662 { 663 for (n = 1; n < 256; n++) 664 if (remap[n] != n) 665 Con_Printf(" %u -> %u\n", n, remap[n]); 666 return; 667 } 668 for (n = 1; n <= ret; n++) 669 remap[n] = Q_atoi(Cmd_Argv (n+1)); 670 return; 671 } 672 673 if (!cd.valid) 674 { 675 Con_Printf("No CD in player.\n"); 676 return; 677 } 678 679 if (Q_strcasecmp(command, "play") == 0) 680 { 681 CDAudio_Play(Q_atoi(Cmd_Argv (2)), false); 682 return; 683 } 684 685 if (Q_strcasecmp(command, "loop") == 0) 686 { 687 CDAudio_Play(Q_atoi(Cmd_Argv (2)), true); 688 return; 689 } 690 691 if (Q_strcasecmp(command, "stop") == 0) 692 { 693 CDAudio_Stop(); 694 return; 695 } 696 697 if (Q_strcasecmp(command, "resume") == 0) 698 { 699 CDAudio_Resume(); 700 return; 701 } 702 703 if (Q_strcasecmp(command, "eject") == 0) 704 { 705 if (playing) 706 CDAudio_Stop(); 707 CDAudio_Eject(); 708 cd.valid = false; 709 return; 710 } 711 712 if (Q_strcasecmp(command, "info") == 0) 713 { 714 Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1); 715 for (n = cd.lowTrack; n <= cd.highTrack; n++) 716 { 717 ret = CDAudio_GetAudioTrackInfo (n, &startAddress); 718 Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff); 719 } 720 if (playing) 721 Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); 722 Con_Printf("Volume is %u\n", cdvolume); 723 CDAudio_MediaChange(); 724 Con_Printf("Status %04x\n", cdRequest->status & 0xffff); 725 return; 726 } 727} 728 729void CDAudio_Update(void) 730{ 731 int ret; 732 int newVolume; 733 static double lastUpdate; 734 735 if (!initialized || !enabled) 736 return; 737 738 if ((realtime - lastUpdate) < 0.25) 739 return; 740 lastUpdate = realtime; 741 742 if (mediaCheck) 743 { 744 static double lastCheck; 745 746 if ((realtime - lastCheck) < 5.0) 747 return; 748 lastCheck = realtime; 749 750 ret = CDAudio_MediaChange(); 751 if (ret == MEDIA_CHANGED) 752 { 753 Con_DPrintf("CDAudio: media changed\n"); 754 playing = false; 755 wasPlaying = false; 756 cd.valid = false; 757 CDAudio_GetAudioDiskInfo(); 758 return; 759 } 760 } 761 762 newVolume = (int)(bgmvolume.value * 255.0); 763 if (newVolume < 0) 764 { 765 Cvar_SetValue ("bgmvolume", 0.0); 766 newVolume = 0; 767 } 768 else if (newVolume > 255) 769 { 770 Cvar_SetValue ("bgmvolume", 1.0); 771 newVolume = 255; 772 } 773 if (cdvolume != newVolume) 774 CDAudio_SetVolume (newVolume); 775 776 if (playing) 777 { 778 CDAudio_GetAudioStatus(); 779 if ((cdRequest->status & STATUS_BUSY_BIT) == 0) 780 { 781 playing = false; 782 if (playLooping) 783 CDAudio_Play(playTrack, true); 784 } 785 } 786} 787 788 789qboolean CDAudio_Playing(void) 790{ 791 return playing; 792} 793 794 795int CDAudio_Init(void) 796{ 797 char *memory; 798 int n; 799 800#if 0 801 802 if (cls.state == ca_dedicated) 803 return -1; 804 805 if (COM_CheckParm("-nocdaudio")) 806 return -1; 807 808 if (COM_CheckParm("-cdmediacheck")) 809 mediaCheck = true; 810 811 regs.x.ax = 0x1500; 812 regs.x.bx = 0; 813 dos_int86 (0x2f); 814 if (regs.x.bx == 0) 815 { 816 Con_NotifyBox ( 817 "MSCDEX not loaded, music is\n" 818 "disabled. Use \"-nocdaudio\" if you\n" 819 "wish to avoid this message in the\n" 820 "future. See README.TXT for help.\n" 821 ); 822 return -1; 823 } 824 if (regs.x.bx > 1) 825 Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n"); 826 cdrom = regs.x.cx; 827 828 regs.x.ax = 0x150c; 829 regs.x.bx = 0; 830 dos_int86 (0x2f); 831 if (regs.x.bx == 0) 832 { 833 Con_NotifyBox ( 834 "MSCDEX version 2.00 or later\n" 835 "required for music. See README.TXT\n" 836 "for help.\n" 837 ); 838 Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n"); 839 return -1; 840 } 841 842 memory = dos_getmemory(sizeof(struct cd_request 843) + sizeof(union readInfo_u)); 844 if (memory == NULL) 845 { 846 Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n"); 847 return -1; 848 } 849 850 cdRequest = (struct cd_request *)memory; 851 cdRequestSegment = ptr2real(cdRequest) >> 4; 852 cdRequestOffset = ptr2real(cdRequest) & 0xf; 853 854 readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request)); 855 readInfoSegment = ptr2real(readInfo) >> 4; 856 readInfoOffset = ptr2real(readInfo) & 0xf; 857 858#endif 859 860 for (n = 0; n < 256; n++) 861 remap[n] = n; 862 initialized = true; 863 864 CDAudio_SetVolume (255); 865 if (CDAudio_GetAudioDiskInfo()) 866 { 867 Con_Printf("CDAudio_Init: No CD in player.\n"); 868 enabled = false; 869 } 870 871 Cmd_AddCommand ("cd", CD_f); 872 873 Con_Printf("CD Audio Initialized\n"); 874 875 return 0; 876} 877 878 879void CDAudio_Shutdown(void) 880{ 881 if (!initialized) 882 return; 883 CDAudio_Stop(); 884} 885