ID_SD.C 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  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. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. //
  19. // ID Engine
  20. // ID_SD.c - Sound Manager
  21. // v1.1d1
  22. // By Jason Blochowiak
  23. //
  24. //
  25. // This module handles dealing with generating sound on the appropriate
  26. // hardware
  27. //
  28. // Depends on: User Mgr (for parm checking)
  29. //
  30. // Globals:
  31. // For User Mgr:
  32. // SoundSourcePresent - Sound Source thingie present?
  33. // SoundBlasterPresent - SoundBlaster card present?
  34. // AdLibPresent - AdLib card present?
  35. // SoundMode - What device is used for sound effects
  36. // (Use SM_SetSoundMode() to set)
  37. // MusicMode - What device is used for music
  38. // (Use SM_SetMusicMode() to set)
  39. // For Cache Mgr:
  40. // NeedsDigitized - load digitized sounds?
  41. // NeedsMusic - load music?
  42. //
  43. #define USE_MUSIC 0
  44. #pragma hdrstop // Wierdo thing with MUSE
  45. #include <dos.h>
  46. #ifdef _MUSE_ // Will be defined in ID_Types.h
  47. #include "ID_SD.h"
  48. #else
  49. #include "ID_HEADS.H"
  50. #endif
  51. #pragma hdrstop
  52. #pragma warn -pia
  53. #define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}
  54. // Macros for AdLib stuff
  55. #define selreg(n) outportb(0x388,n)
  56. #define writereg(n) outportb(0x389,n)
  57. #define readstat() inportb(0x388)
  58. // Global variables
  59. boolean SoundSourcePresent,SoundBlasterPresent,AdLibPresent,
  60. NeedsDigitized,NeedsMusic;
  61. SDMode SoundMode;
  62. SMMode MusicMode;
  63. longword TimeCount;
  64. word HackCount;
  65. word *SoundTable; // Really * _seg *SoundTable, but that don't work
  66. boolean ssIsTandy;
  67. word ssPort = 2;
  68. // Internal variables
  69. static boolean SD_Started;
  70. static boolean TimerDone;
  71. static word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;
  72. static longword TimerDivisor,TimerCount;
  73. static char *ParmStrings[] =
  74. {
  75. "noal",
  76. nil
  77. };
  78. static void (*SoundUserHook)(void);
  79. static word SoundNumber,SoundPriority;
  80. static void interrupt (*t0OldService)(void);
  81. //static word t0CountTable[] = {8,8,8,8,40,40};
  82. static long LocalTime;
  83. // PC Sound variables
  84. static byte pcLastSample,far *pcSound;
  85. static longword pcLengthLeft;
  86. static word pcSoundLookup[255];
  87. // AdLib variables
  88. static boolean alNoCheck;
  89. static byte far *alSound;
  90. static word alBlock;
  91. static longword alLengthLeft;
  92. static longword alTimeCount;
  93. static Instrument alZeroInst;
  94. // This table maps channel numbers to carrier and modulator op cells
  95. static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},
  96. modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},
  97. // This table maps percussive voice numbers to op cells
  98. pcarriers[5] = {19,0xff,0xff,0xff,0xff},
  99. pmodifiers[5] = {16,17,18,20,21};
  100. // Sequencer variables
  101. static boolean sqActive;
  102. static word alFXReg;
  103. static ActiveTrack *tracks[sqMaxTracks],
  104. mytracks[sqMaxTracks];
  105. static word sqMode,sqFadeStep;
  106. static word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;
  107. static long sqHackTime;
  108. // Internal routines
  109. ///////////////////////////////////////////////////////////////////////////
  110. //
  111. // SDL_SetTimer0() - Sets system timer 0 to the specified speed
  112. //
  113. ///////////////////////////////////////////////////////////////////////////
  114. #pragma argsused
  115. static void
  116. SDL_SetTimer0(word speed)
  117. {
  118. #ifndef TPROF // If using Borland's profiling, don't screw with the timer
  119. outportb(0x43,0x36); // Change timer 0
  120. outportb(0x40,speed);
  121. outportb(0x40,speed >> 8);
  122. TimerDivisor = speed;
  123. #else
  124. TimerDivisor = 0x10000;
  125. #endif
  126. }
  127. ///////////////////////////////////////////////////////////////////////////
  128. //
  129. // SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of
  130. // interrupts generated by system timer 0 per second
  131. //
  132. ///////////////////////////////////////////////////////////////////////////
  133. static void
  134. SDL_SetIntsPerSec(word ints)
  135. {
  136. SDL_SetTimer0(1192030 / ints);
  137. }
  138. ///////////////////////////////////////////////////////////////////////////
  139. //
  140. // SDL_TimingService() - Used by SDL_InitDelay() to determine a timing
  141. // value for the current system that we're running on
  142. //
  143. ///////////////////////////////////////////////////////////////////////////
  144. static void interrupt
  145. SDL_TimingService(void)
  146. {
  147. TimerVal = _CX;
  148. TimerDone++;
  149. outportb(0x20,0x20); // Ack interrupt
  150. }
  151. ///////////////////////////////////////////////////////////////////////////
  152. //
  153. // SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()
  154. //
  155. ///////////////////////////////////////////////////////////////////////////
  156. static void
  157. SDL_InitDelay(void)
  158. {
  159. int i;
  160. word timer;
  161. setvect(8,SDL_TimingService); // Set to my timer 0 ISR
  162. SDL_SetIntsPerSec(1000); // Time 1ms
  163. for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times
  164. {
  165. asm xor dx,dx // Zero DX
  166. asm mov cx,0xffff // Put starting value in CX
  167. asm mov [TimerDone],cx // TimerDone = false - 1
  168. startloop:
  169. asm or [TimerDone],0
  170. asm jnz startloop // Make sure we're at the start
  171. loop:
  172. asm test [TimerDone],1 // See if TimerDone flag got hit
  173. asm jnz done // Yep - drop out of the loop
  174. asm loop loop
  175. done:
  176. if (0xffff - TimerVal > timer)
  177. timer = 0xffff - TimerVal;
  178. }
  179. timer += timer / 2; // Use some slop
  180. TimerDelay10 = timer / (1000 / 10);
  181. TimerDelay25 = timer / (1000 / 25);
  182. TimerDelay100 = timer / (1000 / 100);
  183. SDL_SetTimer0(0); // Reset timer 0
  184. setvect(8,t0OldService); // Set back to old ISR
  185. }
  186. ///////////////////////////////////////////////////////////////////////////
  187. //
  188. // SDL_Delay() - Delays the specified amount of time
  189. //
  190. ///////////////////////////////////////////////////////////////////////////
  191. static void
  192. SDL_Delay(word delay)
  193. {
  194. if (!delay)
  195. return;
  196. asm mov cx,[delay]
  197. loop:
  198. asm test [TimerDone],0 // Useless code - just for timing equivilency
  199. asm jnz done
  200. asm loop loop
  201. done:;
  202. }
  203. //
  204. // PC Sound code
  205. //
  206. ///////////////////////////////////////////////////////////////////////////
  207. //
  208. // SDL_PCPlaySound() - Plays the specified sound on the PC speaker
  209. //
  210. ///////////////////////////////////////////////////////////////////////////
  211. #ifdef _MUSE_
  212. void
  213. #else
  214. static void
  215. #endif
  216. SDL_PCPlaySound(PCSound far *sound)
  217. {
  218. asm pushf
  219. asm cli
  220. pcLastSample = -1;
  221. pcLengthLeft = sound->common.length;
  222. pcSound = sound->data;
  223. asm popf
  224. }
  225. ///////////////////////////////////////////////////////////////////////////
  226. //
  227. // SDL_PCStopSound() - Stops the current sound playing on the PC Speaker
  228. //
  229. ///////////////////////////////////////////////////////////////////////////
  230. #ifdef _MUSE_
  231. void
  232. #else
  233. static void
  234. #endif
  235. SDL_PCStopSound(void)
  236. {
  237. asm pushf
  238. asm cli
  239. (long)pcSound = 0;
  240. asm in al,0x61 // Turn the speaker off
  241. asm and al,0xfd // ~2
  242. asm out 0x61,al
  243. asm popf
  244. }
  245. ///////////////////////////////////////////////////////////////////////////
  246. //
  247. // SDL_PCService() - Handles playing the next sample in a PC sound
  248. //
  249. ///////////////////////////////////////////////////////////////////////////
  250. static void
  251. SDL_PCService(void)
  252. {
  253. byte s;
  254. word t;
  255. if (pcSound)
  256. {
  257. s = *pcSound++;
  258. if (s != pcLastSample)
  259. {
  260. asm pushf
  261. asm cli
  262. pcLastSample = s;
  263. if (s) // We have a frequency!
  264. {
  265. t = pcSoundLookup[s];
  266. asm mov bx,[t]
  267. asm mov al,0xb6 // Write to channel 2 (speaker) timer
  268. asm out 43h,al
  269. asm mov al,bl
  270. asm out 42h,al // Low byte
  271. asm mov al,bh
  272. asm out 42h,al // High byte
  273. asm in al,0x61 // Turn the speaker & gate on
  274. asm or al,3
  275. asm out 0x61,al
  276. }
  277. else // Time for some silence
  278. {
  279. asm in al,0x61 // Turn the speaker & gate off
  280. asm and al,0xfc // ~3
  281. asm out 0x61,al
  282. }
  283. asm popf
  284. }
  285. if (!(--pcLengthLeft))
  286. {
  287. SDL_PCStopSound();
  288. SDL_SoundFinished();
  289. }
  290. }
  291. }
  292. ///////////////////////////////////////////////////////////////////////////
  293. //
  294. // SDL_ShutPC() - Turns off the pc speaker
  295. //
  296. ///////////////////////////////////////////////////////////////////////////
  297. static void
  298. SDL_ShutPC(void)
  299. {
  300. asm pushf
  301. asm cli
  302. pcSound = 0;
  303. asm in al,0x61 // Turn the speaker & gate off
  304. asm and al,0xfc // ~3
  305. asm out 0x61,al
  306. asm popf
  307. }
  308. // AdLib Code
  309. ///////////////////////////////////////////////////////////////////////////
  310. //
  311. // alOut(n,b) - Puts b in AdLib card register n
  312. //
  313. ///////////////////////////////////////////////////////////////////////////
  314. void
  315. alOut(byte n,byte b)
  316. {
  317. asm pushf
  318. asm cli
  319. asm mov dx,0x388
  320. asm mov al,[n]
  321. asm out dx,al
  322. #if 0
  323. SDL_Delay(TimerDelay10);
  324. #else
  325. asm in al, dx
  326. asm in al, dx
  327. asm in al, dx
  328. asm in al, dx
  329. asm in al, dx
  330. asm in al, dx
  331. #endif
  332. asm mov dx,0x389
  333. asm mov al,[b]
  334. asm out dx,al
  335. asm popf
  336. #if 0
  337. SDL_Delay(TimerDelay25);
  338. #else
  339. asm mov dx,0x388
  340. asm in al, dx
  341. asm in al, dx
  342. asm in al, dx
  343. asm in al, dx
  344. asm in al, dx
  345. asm in al, dx
  346. asm in al, dx
  347. asm in al, dx
  348. asm in al, dx
  349. asm in al, dx
  350. asm in al, dx
  351. asm in al, dx
  352. asm in al, dx
  353. asm in al, dx
  354. asm in al, dx
  355. asm in al, dx
  356. asm in al, dx
  357. asm in al, dx
  358. asm in al, dx
  359. asm in al, dx
  360. asm in al, dx
  361. asm in al, dx
  362. asm in al, dx
  363. asm in al, dx
  364. asm in al, dx
  365. asm in al, dx
  366. asm in al, dx
  367. asm in al, dx
  368. asm in al, dx
  369. asm in al, dx
  370. asm in al, dx
  371. asm in al, dx
  372. asm in al, dx
  373. asm in al, dx
  374. asm in al, dx
  375. #endif
  376. }
  377. #if 0
  378. ///////////////////////////////////////////////////////////////////////////
  379. //
  380. // SDL_SetInstrument() - Puts an instrument into a generator
  381. //
  382. ///////////////////////////////////////////////////////////////////////////
  383. static void
  384. SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)
  385. {
  386. byte c,m;
  387. if (percussive)
  388. {
  389. c = pcarriers[which];
  390. m = pmodifiers[which];
  391. }
  392. else
  393. {
  394. c = carriers[which];
  395. m = modifiers[which];
  396. }
  397. tracks[track - 1]->inst = *inst;
  398. tracks[track - 1]->percussive = percussive;
  399. alOut(m + alChar,inst->mChar);
  400. alOut(m + alScale,inst->mScale);
  401. alOut(m + alAttack,inst->mAttack);
  402. alOut(m + alSus,inst->mSus);
  403. alOut(m + alWave,inst->mWave);
  404. // Most percussive instruments only use one cell
  405. if (c != 0xff)
  406. {
  407. alOut(c + alChar,inst->cChar);
  408. alOut(c + alScale,inst->cScale);
  409. alOut(c + alAttack,inst->cAttack);
  410. alOut(c + alSus,inst->cSus);
  411. alOut(c + alWave,inst->cWave);
  412. }
  413. alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right
  414. }
  415. #endif
  416. ///////////////////////////////////////////////////////////////////////////
  417. //
  418. // SDL_ALStopSound() - Turns off any sound effects playing through the
  419. // AdLib card
  420. //
  421. ///////////////////////////////////////////////////////////////////////////
  422. #ifdef _MUSE_
  423. void
  424. #else
  425. static void
  426. #endif
  427. SDL_ALStopSound(void)
  428. {
  429. asm pushf
  430. asm cli
  431. (long)alSound = 0;
  432. alOut(alFreqH + 0,0);
  433. asm popf
  434. }
  435. static void
  436. SDL_AlSetFXInst(Instrument far *inst)
  437. {
  438. byte c,m;
  439. m = modifiers[0];
  440. c = carriers[0];
  441. alOut(m + alChar,inst->mChar);
  442. alOut(m + alScale,inst->mScale);
  443. alOut(m + alAttack,inst->mAttack);
  444. alOut(m + alSus,inst->mSus);
  445. alOut(m + alWave,inst->mWave);
  446. alOut(c + alChar,inst->cChar);
  447. alOut(c + alScale,inst->cScale);
  448. alOut(c + alAttack,inst->cAttack);
  449. alOut(c + alSus,inst->cSus);
  450. alOut(c + alWave,inst->cWave);
  451. // DEBUG!!! - I just put this in
  452. // alOut(alFeedCon,inst->nConn);
  453. }
  454. ///////////////////////////////////////////////////////////////////////////
  455. //
  456. // SDL_ALPlaySound() - Plays the specified sound on the AdLib card
  457. //
  458. ///////////////////////////////////////////////////////////////////////////
  459. #ifdef _MUSE_
  460. void
  461. #else
  462. static void
  463. #endif
  464. SDL_ALPlaySound(AdLibSound far *sound)
  465. {
  466. Instrument far *inst;
  467. SDL_ALStopSound();
  468. asm pushf
  469. asm cli
  470. alLengthLeft = sound->common.length;
  471. alSound = sound->data;
  472. alBlock = ((sound->block & 7) << 2) | 0x20;
  473. inst = &sound->inst;
  474. if (!(inst->mSus | inst->cSus))
  475. {
  476. asm popf
  477. Quit("SDL_ALPlaySound() - Bad instrument");
  478. }
  479. SDL_AlSetFXInst(inst);
  480. asm popf
  481. }
  482. ///////////////////////////////////////////////////////////////////////////
  483. //
  484. // SDL_ALSoundService() - Plays the next sample out through the AdLib card
  485. //
  486. ///////////////////////////////////////////////////////////////////////////
  487. static void
  488. SDL_ALSoundService(void)
  489. {
  490. byte s;
  491. if (alSound)
  492. {
  493. s = *alSound++;
  494. if (!s)
  495. alOut(alFreqH + 0,0);
  496. else
  497. {
  498. alOut(alFreqL + 0,s);
  499. alOut(alFreqH + 0,alBlock);
  500. }
  501. if (!(--alLengthLeft))
  502. {
  503. (long)alSound = 0;
  504. alOut(alFreqH + 0,0);
  505. SDL_SoundFinished();
  506. }
  507. }
  508. }
  509. #if 0
  510. ///////////////////////////////////////////////////////////////////////////
  511. //
  512. // SDL_SelectMeasure() - sets up sequencing variables for a given track
  513. //
  514. ///////////////////////////////////////////////////////////////////////////
  515. static void
  516. SDL_SelectMeasure(ActiveTrack *track)
  517. {
  518. track->seq = track->moods[track->mood];
  519. track->nextevent = 0;
  520. }
  521. #endif
  522. static void
  523. SDL_ALService(void)
  524. {
  525. byte a,v;
  526. word w;
  527. if (!sqActive)
  528. return;
  529. while (sqHackLen && (sqHackTime <= alTimeCount))
  530. {
  531. w = *sqHackPtr++;
  532. sqHackTime = alTimeCount + *sqHackPtr++;
  533. asm mov dx,[w]
  534. asm mov [a],dl
  535. asm mov [v],dh
  536. alOut(a,v);
  537. sqHackLen -= 4;
  538. }
  539. alTimeCount++;
  540. if (!sqHackLen)
  541. {
  542. sqHackPtr = (word far *)sqHack;
  543. sqHackLen = sqHackSeqLen;
  544. alTimeCount = sqHackTime = 0;
  545. }
  546. }
  547. ///////////////////////////////////////////////////////////////////////////
  548. //
  549. // SDL_ShutAL() - Shuts down the AdLib card for sound effects
  550. //
  551. ///////////////////////////////////////////////////////////////////////////
  552. static void
  553. SDL_ShutAL(void)
  554. {
  555. asm pushf
  556. asm cli
  557. alOut(alEffects,0);
  558. alOut(alFreqH + 0,0);
  559. SDL_AlSetFXInst(&alZeroInst);
  560. alSound = 0;
  561. asm popf
  562. }
  563. ///////////////////////////////////////////////////////////////////////////
  564. //
  565. // SDL_CleanAL() - Totally shuts down the AdLib card
  566. //
  567. ///////////////////////////////////////////////////////////////////////////
  568. static void
  569. SDL_CleanAL(void)
  570. {
  571. int i;
  572. asm pushf
  573. asm cli
  574. alOut(alEffects,0);
  575. for (i = 1;i < 0xf5;i++)
  576. alOut(i,0);
  577. asm popf
  578. }
  579. ///////////////////////////////////////////////////////////////////////////
  580. //
  581. // SDL_StartAL() - Starts up the AdLib card for sound effects
  582. //
  583. ///////////////////////////////////////////////////////////////////////////
  584. static void
  585. SDL_StartAL(void)
  586. {
  587. alFXReg = 0;
  588. alOut(alEffects,alFXReg);
  589. SDL_AlSetFXInst(&alZeroInst);
  590. }
  591. ///////////////////////////////////////////////////////////////////////////
  592. //
  593. // SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster
  594. // emulating an AdLib) present
  595. //
  596. ///////////////////////////////////////////////////////////////////////////
  597. static boolean
  598. SDL_DetectAdLib(void)
  599. {
  600. byte status1,status2;
  601. int i;
  602. alOut(4,0x60); // Reset T1 & T2
  603. alOut(4,0x80); // Reset IRQ
  604. status1 = readstat();
  605. alOut(2,0xff); // Set timer 1
  606. alOut(4,0x21); // Start timer 1
  607. SDL_Delay(TimerDelay100);
  608. status2 = readstat();
  609. alOut(4,0x60);
  610. alOut(4,0x80);
  611. if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))
  612. {
  613. for (i = 1;i <= 0xf5;i++) // Zero all the registers
  614. alOut(i,0);
  615. alOut(1,0x20); // Set WSE=1
  616. alOut(8,0); // Set CSM=0 & SEL=0
  617. return(true);
  618. }
  619. else
  620. return(false);
  621. }
  622. ///////////////////////////////////////////////////////////////////////////
  623. //
  624. // SDL_t0Service() - My timer 0 ISR which handles the different timings and
  625. // dispatches to whatever other routines are appropriate
  626. //
  627. ///////////////////////////////////////////////////////////////////////////
  628. static void interrupt
  629. SDL_t0Service(void)
  630. {
  631. static word count = 1;
  632. #if 0 // for debugging
  633. asm mov dx,STATUS_REGISTER_1
  634. asm in al,dx
  635. asm mov dx,ATR_INDEX
  636. asm mov al,ATR_OVERSCAN
  637. asm out dx,al
  638. asm mov al,4 // red
  639. asm out dx,al
  640. #endif
  641. HackCount++;
  642. #if USE_MUSIC
  643. if (MusicMode == smm_AdLib)
  644. {
  645. SDL_ALService();
  646. if (!(++count & 7))
  647. {
  648. LocalTime++;
  649. TimeCount++;
  650. if (SoundUserHook)
  651. SoundUserHook();
  652. }
  653. if (!(count & 3))
  654. {
  655. switch (SoundMode)
  656. {
  657. case sdm_PC:
  658. SDL_PCService();
  659. break;
  660. case sdm_AdLib:
  661. SDL_ALSoundService();
  662. break;
  663. }
  664. }
  665. }
  666. else
  667. #endif
  668. {
  669. if (!(++count & 1))
  670. {
  671. LocalTime++;
  672. TimeCount++;
  673. if (SoundUserHook)
  674. SoundUserHook();
  675. }
  676. switch (SoundMode)
  677. {
  678. case sdm_PC:
  679. SDL_PCService();
  680. break;
  681. case sdm_AdLib:
  682. SDL_ALSoundService();
  683. break;
  684. }
  685. }
  686. asm mov ax,[WORD PTR TimerCount]
  687. asm add ax,[WORD PTR TimerDivisor]
  688. asm mov [WORD PTR TimerCount],ax
  689. asm jnc myack
  690. t0OldService(); // If we overflow a word, time to call old int handler
  691. asm jmp olddone
  692. myack:;
  693. outportb(0x20,0x20); // Ack the interrupt
  694. olddone:;
  695. #if 0 // for debugging
  696. asm mov dx,STATUS_REGISTER_1
  697. asm in al,dx
  698. asm mov dx,ATR_INDEX
  699. asm mov al,ATR_OVERSCAN
  700. asm out dx,al
  701. asm mov al,3 // blue
  702. asm out dx,al
  703. asm mov al,0x20 // normal
  704. asm out dx,al
  705. #endif
  706. }
  707. ////////////////////////////////////////////////////////////////////////////
  708. //
  709. // SDL_ShutDevice() - turns off whatever device was being used for sound fx
  710. //
  711. ////////////////////////////////////////////////////////////////////////////
  712. static void
  713. SDL_ShutDevice(void)
  714. {
  715. switch (SoundMode)
  716. {
  717. case sdm_PC:
  718. SDL_ShutPC();
  719. break;
  720. case sdm_AdLib:
  721. SDL_ShutAL();
  722. break;
  723. }
  724. SoundMode = sdm_Off;
  725. }
  726. ///////////////////////////////////////////////////////////////////////////
  727. //
  728. // SDL_CleanDevice() - totally shuts down all sound devices
  729. //
  730. ///////////////////////////////////////////////////////////////////////////
  731. static void
  732. SDL_CleanDevice(void)
  733. {
  734. if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))
  735. SDL_CleanAL();
  736. }
  737. ///////////////////////////////////////////////////////////////////////////
  738. //
  739. // SDL_StartDevice() - turns on whatever device is to be used for sound fx
  740. //
  741. ///////////////////////////////////////////////////////////////////////////
  742. static void
  743. SDL_StartDevice(void)
  744. {
  745. switch (SoundMode)
  746. {
  747. case sdm_AdLib:
  748. SDL_StartAL();
  749. break;
  750. }
  751. SoundNumber = SoundPriority = 0;
  752. }
  753. static void
  754. SDL_SetTimerSpeed(void)
  755. {
  756. word rate;
  757. #if USE_MUSIC
  758. if (MusicMode == smm_AdLib)
  759. rate = TickBase * 8;
  760. else
  761. #endif
  762. rate = TickBase * 2;
  763. SDL_SetIntsPerSec(rate);
  764. }
  765. // Public routines
  766. ///////////////////////////////////////////////////////////////////////////
  767. //
  768. // SD_SetSoundMode() - Sets which sound hardware to use for sound effects
  769. //
  770. ///////////////////////////////////////////////////////////////////////////
  771. boolean
  772. SD_SetSoundMode(SDMode mode)
  773. {
  774. boolean result;
  775. word tableoffset;
  776. SD_StopSound();
  777. #ifndef _MUSE_
  778. switch (mode)
  779. {
  780. case sdm_Off:
  781. NeedsDigitized = false;
  782. result = true;
  783. break;
  784. case sdm_PC:
  785. tableoffset = STARTPCSOUNDS;
  786. NeedsDigitized = false;
  787. result = true;
  788. break;
  789. case sdm_AdLib:
  790. if (AdLibPresent)
  791. {
  792. tableoffset = STARTADLIBSOUNDS;
  793. NeedsDigitized = false;
  794. result = true;
  795. }
  796. break;
  797. default:
  798. result = false;
  799. break;
  800. }
  801. #endif
  802. if (result && (mode != SoundMode))
  803. {
  804. SDL_ShutDevice();
  805. SoundMode = mode;
  806. #ifndef _MUSE_
  807. SoundTable = (word *)(&audiosegs[tableoffset]);
  808. #endif
  809. SDL_StartDevice();
  810. }
  811. SDL_SetTimerSpeed();
  812. return(result);
  813. }
  814. ///////////////////////////////////////////////////////////////////////////
  815. //
  816. // SD_SetMusicMode() - sets the device to use for background music
  817. //
  818. ///////////////////////////////////////////////////////////////////////////
  819. boolean
  820. SD_SetMusicMode(SMMode mode)
  821. {
  822. #if USE_MUSIC
  823. boolean result;
  824. SD_FadeOutMusic();
  825. while (SD_MusicPlaying())
  826. ;
  827. switch (mode)
  828. {
  829. case smm_Off:
  830. NeedsMusic = false;
  831. result = true;
  832. break;
  833. case smm_AdLib:
  834. if (AdLibPresent)
  835. {
  836. NeedsMusic = true;
  837. result = true;
  838. }
  839. break;
  840. default:
  841. result = false;
  842. break;
  843. }
  844. if (result)
  845. MusicMode = mode;
  846. SDL_SetTimerSpeed();
  847. return(result);
  848. #endif
  849. }
  850. ///////////////////////////////////////////////////////////////////////////
  851. //
  852. // SD_Startup() - starts up the Sound Mgr
  853. // Detects all additional sound hardware and installs my ISR
  854. //
  855. ///////////////////////////////////////////////////////////////////////////
  856. void
  857. SD_Startup(void)
  858. {
  859. int i;
  860. if (SD_Started)
  861. return;
  862. ssIsTandy = false;
  863. alNoCheck = false;
  864. #ifndef _MUSE_
  865. for (i = 1;i < _argc;i++)
  866. {
  867. switch (US_CheckParm(_argv[i],ParmStrings))
  868. {
  869. case 0: // No AdLib detection
  870. alNoCheck = true;
  871. break;
  872. }
  873. }
  874. #endif
  875. SoundUserHook = 0;
  876. t0OldService = getvect(8); // Get old timer 0 ISR
  877. SDL_InitDelay(); // SDL_InitDelay() uses t0OldService
  878. setvect(8,SDL_t0Service); // Set to my timer 0 ISR
  879. LocalTime = TimeCount = alTimeCount = 0;
  880. SD_SetSoundMode(sdm_Off);
  881. #if USE_MUSIC
  882. SD_SetMusicMode(smm_Off);
  883. #endif
  884. if (!alNoCheck)
  885. AdLibPresent = SDL_DetectAdLib();
  886. for (i = 0;i < 255;i++)
  887. pcSoundLookup[i] = i * 60;
  888. SD_Started = true;
  889. }
  890. ///////////////////////////////////////////////////////////////////////////
  891. //
  892. // SD_Default() - Sets up the default behaviour for the Sound Mgr whether
  893. // the config file was present or not.
  894. //
  895. ///////////////////////////////////////////////////////////////////////////
  896. void
  897. SD_Default(boolean gotit,SDMode sd,SMMode sm)
  898. {
  899. boolean gotsd,gotsm;
  900. gotsd = gotsm = gotit;
  901. if (gotsd) // Make sure requested sound hardware is available
  902. {
  903. switch (sd)
  904. {
  905. case sdm_AdLib:
  906. gotsd = AdLibPresent;
  907. break;
  908. }
  909. }
  910. if (!gotsd)
  911. {
  912. if (AdLibPresent)
  913. sd = sdm_AdLib;
  914. else
  915. sd = sdm_PC;
  916. }
  917. if (sd != SoundMode)
  918. SD_SetSoundMode(sd);
  919. if (gotsm) // Make sure requested music hardware is available
  920. {
  921. switch (sm)
  922. {
  923. case sdm_AdLib:
  924. gotsm = AdLibPresent;
  925. break;
  926. }
  927. }
  928. if (!gotsm)
  929. {
  930. if (AdLibPresent)
  931. sm = smm_AdLib;
  932. }
  933. #if USE_MUSIC
  934. if (sm != MusicMode)
  935. SD_SetMusicMode(sm);
  936. #endif
  937. }
  938. ///////////////////////////////////////////////////////////////////////////
  939. //
  940. // SD_Shutdown() - shuts down the Sound Mgr
  941. // Removes sound ISR and turns off whatever sound hardware was active
  942. //
  943. ///////////////////////////////////////////////////////////////////////////
  944. void
  945. SD_Shutdown(void)
  946. {
  947. if (!SD_Started)
  948. return;
  949. #if USE_MUSIC
  950. SD_MusicOff();
  951. #endif
  952. SDL_ShutDevice();
  953. SDL_CleanDevice();
  954. asm pushf
  955. asm cli
  956. SDL_SetTimer0(0);
  957. setvect(8,t0OldService);
  958. asm popf
  959. SD_Started = false;
  960. }
  961. ///////////////////////////////////////////////////////////////////////////
  962. //
  963. // SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th
  964. // of a second from its timer 0 ISR
  965. //
  966. ///////////////////////////////////////////////////////////////////////////
  967. void
  968. SD_SetUserHook(void (* hook)(void))
  969. {
  970. SoundUserHook = hook;
  971. }
  972. ///////////////////////////////////////////////////////////////////////////
  973. //
  974. // SD_PlaySound() - plays the specified sound on the appropriate hardware
  975. //
  976. ///////////////////////////////////////////////////////////////////////////
  977. void
  978. SD_PlaySound(soundnames sound)
  979. {
  980. SoundCommon far *s;
  981. if ((SoundMode == sdm_Off) || (sound == -1))
  982. return;
  983. s = MK_FP(SoundTable[sound],0);
  984. if (!s)
  985. Quit("SD_PlaySound() - Uncached sound");
  986. if (!s->length)
  987. Quit("SD_PlaySound() - Zero length sound");
  988. if (s->priority < SoundPriority)
  989. return;
  990. switch (SoundMode)
  991. {
  992. case sdm_PC:
  993. SDL_PCPlaySound((void far *)s);
  994. break;
  995. case sdm_AdLib:
  996. SDL_ALPlaySound((void far *)s);
  997. break;
  998. }
  999. SoundNumber = sound;
  1000. SoundPriority = s->priority;
  1001. }
  1002. ///////////////////////////////////////////////////////////////////////////
  1003. //
  1004. // SD_SoundPlaying() - returns the sound number that's playing, or 0 if
  1005. // no sound is playing
  1006. //
  1007. ///////////////////////////////////////////////////////////////////////////
  1008. word
  1009. SD_SoundPlaying(void)
  1010. {
  1011. boolean result = false;
  1012. switch (SoundMode)
  1013. {
  1014. case sdm_PC:
  1015. result = pcSound? true : false;
  1016. break;
  1017. case sdm_AdLib:
  1018. result = alSound? true : false;
  1019. break;
  1020. }
  1021. if (result)
  1022. return(SoundNumber);
  1023. else
  1024. return(false);
  1025. }
  1026. ///////////////////////////////////////////////////////////////////////////
  1027. //
  1028. // SD_StopSound() - if a sound is playing, stops it
  1029. //
  1030. ///////////////////////////////////////////////////////////////////////////
  1031. void
  1032. SD_StopSound(void)
  1033. {
  1034. switch (SoundMode)
  1035. {
  1036. case sdm_PC:
  1037. SDL_PCStopSound();
  1038. break;
  1039. case sdm_AdLib:
  1040. SDL_ALStopSound();
  1041. break;
  1042. }
  1043. SDL_SoundFinished();
  1044. }
  1045. ///////////////////////////////////////////////////////////////////////////
  1046. //
  1047. // SD_WaitSoundDone() - waits until the current sound is done playing
  1048. //
  1049. ///////////////////////////////////////////////////////////////////////////
  1050. void
  1051. SD_WaitSoundDone(void)
  1052. {
  1053. while (SD_SoundPlaying())
  1054. ;
  1055. }
  1056. ///////////////////////////////////////////////////////////////////////////
  1057. //
  1058. // SD_MusicOn() - turns on the sequencer
  1059. //
  1060. ///////////////////////////////////////////////////////////////////////////
  1061. void
  1062. SD_MusicOn(void)
  1063. {
  1064. #if USE_MUSIC
  1065. sqActive = true;
  1066. #endif
  1067. }
  1068. ///////////////////////////////////////////////////////////////////////////
  1069. //
  1070. // SD_MusicOff() - turns off the sequencer and any playing notes
  1071. //
  1072. ///////////////////////////////////////////////////////////////////////////
  1073. void
  1074. SD_MusicOff(void)
  1075. {
  1076. #if USE_MUSIC
  1077. word i;
  1078. switch (MusicMode)
  1079. {
  1080. case smm_AdLib:
  1081. alFXReg = 0;
  1082. alOut(alEffects,0);
  1083. for (i = 0;i < sqMaxTracks;i++)
  1084. alOut(alFreqH + i + 1,0);
  1085. break;
  1086. }
  1087. sqActive = false;
  1088. #endif
  1089. }
  1090. ///////////////////////////////////////////////////////////////////////////
  1091. //
  1092. // SD_StartMusic() - starts playing the music pointed to
  1093. //
  1094. ///////////////////////////////////////////////////////////////////////////
  1095. void
  1096. SD_StartMusic(MusicGroup far *music)
  1097. {
  1098. #if USE_MUSIC
  1099. SD_MusicOff();
  1100. asm pushf
  1101. asm cli
  1102. if (MusicMode == smm_AdLib)
  1103. {
  1104. sqHackPtr = sqHack = music->values;
  1105. sqHackSeqLen = sqHackLen = music->length;
  1106. sqHackTime = 0;
  1107. alTimeCount = 0;
  1108. SD_MusicOn();
  1109. }
  1110. asm popf
  1111. #endif
  1112. }
  1113. ///////////////////////////////////////////////////////////////////////////
  1114. //
  1115. // SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()
  1116. // to see if the fadeout is complete
  1117. //
  1118. ///////////////////////////////////////////////////////////////////////////
  1119. void
  1120. SD_FadeOutMusic(void)
  1121. {
  1122. #if USE_MUSIC
  1123. switch (MusicMode)
  1124. {
  1125. case smm_AdLib:
  1126. // DEBUG - quick hack to turn the music off
  1127. SD_MusicOff();
  1128. break;
  1129. }
  1130. #endif
  1131. }
  1132. ///////////////////////////////////////////////////////////////////////////
  1133. //
  1134. // SD_MusicPlaying() - returns true if music is currently playing, false if
  1135. // not
  1136. //
  1137. ///////////////////////////////////////////////////////////////////////////
  1138. boolean
  1139. SD_MusicPlaying(void)
  1140. {
  1141. #if USE_MUSIC
  1142. boolean result;
  1143. switch (MusicMode)
  1144. {
  1145. case smm_AdLib:
  1146. result = false;
  1147. // DEBUG - not written
  1148. break;
  1149. default:
  1150. result = false;
  1151. }
  1152. return(result);
  1153. #endif
  1154. }