cd_audio.c 17 KB

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