]> 4ch.mooo.com Git - 16.git/blob - src/lib/id_sd.c
8883f62a71d5a20df1b58648edeb8df9d9365c65
[16.git] / src / lib / id_sd.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 //\r
24 //      ID Engine\r
25 //      ID_SD.c - Sound Manager for Wolfenstein 3D\r
26 //      v1.2w\r
27 //      By Jason Blochowiak\r
28 //      Open Watcom port by sparky4\r
29 //\r
30 \r
31 //\r
32 //      This module handles dealing with generating sound on the appropriate\r
33 //              hardware\r
34 //\r
35 //      Depends on: User Mgr (for parm checking)\r
36 //\r
37 //      Globals:\r
38 //              For User Mgr:\r
39 //                      SoundSourcePresent - Sound Source thingie present?\r
40 //                      SoundBlasterPresent - SoundBlaster card present?\r
41 //                      AdLibPresent - AdLib card present?\r
42 //                      SoundMode - What device is used for sound effects\r
43 //                              (Use SM_SetSoundMode() to set)\r
44 //                      MusicMode - What device is used for music\r
45 //                              (Use SM_SetMusicMode() to set)\r
46 //                      DigiMode - What device is used for digitized sound effects\r
47 //                              (Use SM_SetDigiDevice() to set)\r
48 //\r
49 //              For Cache Mgr:\r
50 //                      NeedsDigitized - load digitized sounds?\r
51 //                      NeedsMusic - load music?\r
52 //\r
53 \r
54 #pragma hdrstop         // Wierdo thing with MUSE\r
55 \r
56 #include <dos.h>\r
57 \r
58 #ifndef _MUSE_      // Will be defined in ID_Types.h\r
59 #include "src/lib/id_sd.h"\r
60 #else\r
61 #include "src/lib/16_head.h"\r
62 #endif\r
63 #pragma hdrstop\r
64 #pragma warn    -pia\r
65 \r
66 #define SDL_SoundFinished()     {SoundNumber = SoundPriority = 0;}\r
67 \r
68 // Macros for AdLib stuff\r
69 #define selreg(n)       outportb(alFMAddr,n)\r
70 #define writereg(n)     outportb(alFMData,n)\r
71 #define readstat()      inportb(alFMStatus)\r
72 \r
73 //      Imports from ID_SD_A.ASM\r
74 /*extern*/      void                    SDL_SetDS(void),\r
75                                                 SDL_IndicatePC(boolean on);\r
76 /*extern*/      void interrupt  SDL_t0ExtremeAsmService(void),\r
77                                                 SDL_t0FastAsmService(void),\r
78                                                 SDL_t0SlowAsmService(void);\r
79 \r
80 //      Global variables\r
81         boolean         SoundSourcePresent,\r
82                                 AdLibPresent,\r
83                                 SoundBlasterPresent,SBProPresent,\r
84                                 NeedsDigitized,NeedsMusic,\r
85                                 SoundPositioned;\r
86         SDMode          SoundMode;\r
87         SMMode          MusicMode;\r
88         SDSMode         DigiMode;\r
89         dword   TimeCount;\r
90         word            HackCount;\r
91         word            *SoundTable;    // Really * _seg *SoundTable, but that don't work\r
92         boolean         ssIsTandy;\r
93         word            ssPort = 2;\r
94         int                     DigiMap[LASTSOUND];\r
95 \r
96 //      Internal variables\r
97 static  boolean                 SD_Started;\r
98                 boolean                 nextsoundpos;\r
99                 word/*boolean_+*/                       TimerDone;\r
100                 word                    TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;\r
101                 dword           TimerDivisor,TimerCount;\r
102 static  char                    *ParmStrings[] =\r
103                                                 {\r
104                                                         "noal",\r
105                                                         "nosb",\r
106                                                         "nopro",\r
107                                                         "noss",\r
108                                                         "sst",\r
109                                                         "ss1",\r
110                                                         "ss2",\r
111                                                         "ss3",\r
112                                                         nil\r
113                                                 };\r
114 static  void                    (*SoundUserHook)(void);\r
115                 soundnames              SoundNumber,DigiNumber;\r
116                 word                    SoundPriority,DigiPriority;\r
117                 int                             LeftPosition,RightPosition;\r
118                 void interrupt  (*t0OldService)(void);\r
119                 long                    LocalTime;\r
120                 word                    TimerRate;\r
121 \r
122                 word                    NumDigi,DigiLeft,DigiPage;\r
123                 word                    _seg *DigiList;\r
124                 word                    DigiLastStart,DigiLastEnd;\r
125                 boolean                 DigiPlaying;\r
126 static  boolean                 DigiMissed,DigiLastSegment;\r
127 static  memptr                  DigiNextAddr;\r
128 static  word                    DigiNextLen;\r
129 \r
130 #if 0\r
131 //      SoundBlaster variables\r
132 static  boolean                                 sbNoCheck,sbNoProCheck;\r
133 static  volatile boolean                sbSamplePlaying;\r
134 static  byte                                    sbOldIntMask = -1;\r
135 static  volatile byte                   huge *sbNextSegPtr;\r
136 static  byte                                    sbDMA = 1,\r
137                                                                 sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3,\r
138                                                                 sba1Vals[] = {0x87,0x83,0,0x82},\r
139                                                                 sba2Vals[] = {0,2,0,6},\r
140                                                                 sba3Vals[] = {1,3,0,7};\r
141 static  int                                             sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf,\r
142                                                                 sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1};\r
143 static  volatile dword          sbNextSegLen;\r
144 static  volatile SampledSound   huge *sbSamples;\r
145 static  void interrupt                  (*sbOldIntHand)(void);\r
146 static  byte                                    sbpOldFMMix,sbpOldVOCMix;\r
147 \r
148 //      SoundSource variables\r
149                 boolean                         ssNoCheck;\r
150                 boolean                         ssActive;\r
151                 word                            ssControl,ssStatus,ssData;\r
152                 byte                            ssOn,ssOff;\r
153                 volatile byte           far *ssSample;\r
154                 volatile dword  ssLengthLeft;\r
155 #endif\r
156 \r
157 //      PC Sound variables\r
158                 volatile byte   pcLastSample,far *pcSound;\r
159                 dword           pcLengthLeft;\r
160                 word                    pcSoundLookup[255];\r
161 \r
162 //      AdLib variables\r
163                 boolean                 alNoCheck;\r
164                 byte                    far *alSound;\r
165                 word                    alBlock;\r
166                 dword           alLengthLeft;\r
167                 dword           alTimeCount;\r
168                 Instrument              alZeroInst;\r
169 \r
170 // This table maps channel numbers to carrier and modulator op cells\r
171 static  byte                    carriers[9] =  { 3, 4, 5,11,12,13,19,20,21},\r
172                                                 modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},\r
173 // This table maps percussive voice numbers to op cells\r
174                                                 pcarriers[5] = {19,0xff,0xff,0xff,0xff},\r
175                                                 pmodifiers[5] = {16,17,18,20,21};\r
176 \r
177 //      Sequencer variables\r
178                 boolean                 sqActive;\r
179 static  word                    alFXReg;\r
180 static  ActiveTrack             *tracks[sqMaxTracks];//,\r
181 //--                                            mytracks[sqMaxTracks];\r
182 static  word                    sqMode,sqFadeStep;\r
183                 word                    far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;\r
184                 long                    sqHackTime;\r
185 \r
186 //      Internal routines\r
187                 void                    SDL_DigitizedDone(void);\r
188 \r
189 ///////////////////////////////////////////////////////////////////////////\r
190 //\r
191 //      SDL_SetTimer0() - Sets system timer 0 to the specified speed\r
192 //\r
193 ///////////////////////////////////////////////////////////////////////////\r
194 #pragma argsused\r
195 static void\r
196 SDL_SetTimer0(word speed)\r
197 {\r
198 #ifndef TPROF   // If using Borland's profiling, don't screw with the timer\r
199 asm     pushf\r
200 asm     cli\r
201 \r
202         outportb(0x43,0x36);                            // Change timer 0\r
203         outportb(0x40,speed);\r
204         outportb(0x40,speed >> 8);\r
205         // Kludge to handle special case for digitized PC sounds\r
206         if (TimerDivisor == (1192030 / (TickBase * 100)))\r
207                 TimerDivisor = (1192030 / (TickBase * 10));\r
208         else\r
209                 TimerDivisor = speed;\r
210 \r
211 asm     popf\r
212 #else\r
213         TimerDivisor = 0x10000;\r
214 #endif\r
215 }\r
216 \r
217 ///////////////////////////////////////////////////////////////////////////\r
218 //\r
219 //      SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of\r
220 //              interrupts generated by system timer 0 per second\r
221 //\r
222 ///////////////////////////////////////////////////////////////////////////\r
223 static void\r
224 SDL_SetIntsPerSec(word ints)\r
225 {\r
226         TimerRate = ints;\r
227         SDL_SetTimer0(1192030 / ints);\r
228 }\r
229 \r
230 static void\r
231 SDL_SetTimerSpeed(void)\r
232 {\r
233         word    rate;\r
234         void interrupt  (*isr)(void);\r
235 \r
236         if ((DigiMode == sds_PC) && DigiPlaying)\r
237         {\r
238                 rate = TickBase * 100;\r
239                 isr = SDL_t0ExtremeAsmService;\r
240         }\r
241         else if\r
242         (\r
243                 (MusicMode == smm_AdLib)\r
244         ||      ((DigiMode == sds_SoundSource) && DigiPlaying)\r
245         )\r
246         {\r
247                 rate = TickBase * 10;\r
248                 isr = SDL_t0FastAsmService;\r
249         }\r
250         else\r
251         {\r
252                 rate = TickBase * 2;\r
253                 isr = SDL_t0SlowAsmService;\r
254         }\r
255 \r
256         if (rate != TimerRate)\r
257         {\r
258                 setvect(8,isr);\r
259                 SDL_SetIntsPerSec(rate);\r
260                 TimerRate = rate;\r
261         }\r
262 }\r
263 \r
264 ///////////////////////////////////////////////////////////////////////////\r
265 //\r
266 //      SDL_TimingService() - Used by SDL_InitDelay() to determine a timing\r
267 //              value for the current system that we're running on\r
268 //\r
269 ///////////////////////////////////////////////////////////////////////////\r
270 //static void interrupt\r
271 void interrupt\r
272 SDL_TimingService(void)\r
273 {\r
274         //TimerVal = _CX;\r
275         __asm {\r
276                 mov TimerVal,cx\r
277         }\r
278         TimerDone = 1;\r
279 \r
280         outportb(0x20,0x20);                            // Ack interrupt\r
281 }\r
282 \r
283 ///////////////////////////////////////////////////////////////////////////\r
284 //\r
285 //      SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()\r
286 //\r
287 ///////////////////////////////////////////////////////////////////////////\r
288 static void\r
289 SDL_InitDelay(void)\r
290 {\r
291         int             i;\r
292         word    timer;\r
293 \r
294         setvect(8,SDL_TimingService);           // Set to my timer 0 ISR\r
295 \r
296         SDL_SetIntsPerSec(1000);                        // Time 1ms\r
297 \r
298         for (i = 0,timer = 0;i < 10;i++)        // Do timing test 10 times\r
299         {\r
300                 __asm {\r
301                         xor             dx,dx                                   // Zero DX\r
302                         mov             cx,0xffff                               // Put starting value in CX\r
303                         mov             [TimerDone],cx                  // TimerDone = false - 1\r
304 #ifdef __BORLANDC__\r
305                 }\r
306 #endif\r
307 startloop:\r
308 #ifdef __BORLANDC__\r
309                 __asm {\r
310 #endif\r
311                         or              [TimerDone],0\r
312                         jnz             startloop                               // Make sure we're at the start\r
313 #ifdef __BORLANDC__\r
314                 }\r
315 #endif\r
316 loop_:\r
317 #ifdef __BORLANDC__\r
318                 __asm {\r
319 #endif\r
320                         test    [TimerDone],1                   // See if TimerDone flag got hit\r
321                         jnz             done                                    // Yep - drop out of the loop\r
322                         loop    loop_\r
323 #ifdef __BORLANDC__\r
324                 }\r
325 #endif\r
326 done:\r
327 #ifdef __WATCOMC__\r
328         }\r
329 #endif\r
330 \r
331                 if (0xffff - TimerVal > timer)\r
332                         timer = 0xffff - TimerVal;\r
333         }\r
334         timer += timer / 2;                                     // Use some slop\r
335         TimerDelay10 =  timer / (1000 / 10);\r
336         TimerDelay25 =  timer / (1000 / 25);\r
337         TimerDelay100 = timer / (1000 / 100);\r
338 \r
339         SDL_SetTimer0(0);                                       // Reset timer 0\r
340 \r
341         setvect(8,t0OldService);                        // Set back to old ISR\r
342 }\r
343 \r
344 ///////////////////////////////////////////////////////////////////////////\r
345 //\r
346 //      SDL_Delay() - Delays the specified amount of time\r
347 //\r
348 ///////////////////////////////////////////////////////////////////////////\r
349 static void\r
350 SDL_Delay(word delay)\r
351 {\r
352         if (!delay)\r
353                 return;\r
354 \r
355         __asm {\r
356                 mov             cx,[delay]\r
357 #ifdef __BORLANDC__\r
358         }\r
359 #endif\r
360 loop_:\r
361 #ifdef __BORLANDC__\r
362         __asm {\r
363 #endif\r
364                 test    [TimerDone],0   // Useless code - just for timing equivilency\r
365                 jnz             done\r
366                 loop    loop_\r
367 #ifdef __BORLANDC__\r
368         }\r
369 #endif\r
370 done:\r
371 #ifdef __WATCOMC__\r
372         }\r
373 #endif\r
374 }\r
375 \r
376 //\r
377 //      PC Sound code\r
378 //\r
379 \r
380 ///////////////////////////////////////////////////////////////////////////\r
381 //\r
382 //      SDL_PCPlaySample() - Plays the specified sample on the PC speaker\r
383 //\r
384 ///////////////////////////////////////////////////////////////////////////\r
385 #ifdef  _MUSE_\r
386 void\r
387 #else\r
388 static void\r
389 #endif\r
390 SDL_PCPlaySample(byte huge *data,dword len)\r
391 {\r
392 asm     pushf\r
393 asm     cli\r
394 \r
395         SDL_IndicatePC(true);\r
396 \r
397         pcLengthLeft = len;\r
398         pcSound = (volatile byte far *)data;\r
399 \r
400 asm     popf\r
401 }\r
402 \r
403 ///////////////////////////////////////////////////////////////////////////\r
404 //\r
405 //      SDL_PCStopSample() - Stops a sample playing on the PC speaker\r
406 //\r
407 ///////////////////////////////////////////////////////////////////////////\r
408 #ifdef  _MUSE_\r
409 void\r
410 #else\r
411 static void\r
412 #endif\r
413 SDL_PCStopSample(void)\r
414 {\r
415 asm     pushf\r
416 asm     cli\r
417 \r
418         /*(long)*/pcSound = 0;\r
419 \r
420         SDL_IndicatePC(false);\r
421 \r
422 asm     in      al,0x61                 // Turn the speaker off\r
423 asm     and     al,0xfd                 // ~2\r
424 asm     out     0x61,al\r
425 \r
426 asm     popf\r
427 }\r
428 \r
429 ///////////////////////////////////////////////////////////////////////////\r
430 //\r
431 //      SDL_PCPlaySound() - Plays the specified sound on the PC speaker\r
432 //\r
433 ///////////////////////////////////////////////////////////////////////////\r
434 #ifdef  _MUSE_\r
435 void\r
436 #else\r
437 static void\r
438 #endif\r
439 SDL_PCPlaySound(PCSound far *sound)\r
440 {\r
441 asm     pushf\r
442 asm     cli\r
443 \r
444         pcLastSample = -1;\r
445         pcLengthLeft = sound->common.length;\r
446         pcSound = sound->data;\r
447 \r
448 asm     popf\r
449 }\r
450 \r
451 ///////////////////////////////////////////////////////////////////////////\r
452 //\r
453 //      SDL_PCStopSound() - Stops the current sound playing on the PC Speaker\r
454 //\r
455 ///////////////////////////////////////////////////////////////////////////\r
456 #ifdef  _MUSE_\r
457 void\r
458 #else\r
459 static void\r
460 #endif\r
461 SDL_PCStopSound(void)\r
462 {\r
463 asm     pushf\r
464 asm     cli\r
465 \r
466         /*(long)*/pcSound = 0;\r
467 \r
468 asm     in      al,0x61                 // Turn the speaker off\r
469 asm     and     al,0xfd                 // ~2\r
470 asm     out     0x61,al\r
471 \r
472 asm     popf\r
473 }\r
474 \r
475 ///////////////////////////////////////////////////////////////////////////\r
476 //\r
477 //      SDL_PCService() - Handles playing the next sample in a PC sound\r
478 //\r
479 ///////////////////////////////////////////////////////////////////////////\r
480 static void\r
481 SDL_PCService(void)\r
482 {\r
483         byte    s;\r
484         word    t;\r
485 \r
486         if (pcSound)\r
487         {\r
488                 s = *pcSound++;\r
489                 if (s != pcLastSample)\r
490                 {\r
491                 asm     pushf\r
492                 asm     cli\r
493 \r
494                         pcLastSample = s;\r
495                         if (s)                                  // We have a frequency!\r
496                         {\r
497                                 t = pcSoundLookup[s];\r
498                         asm     mov     bx,[t]\r
499 \r
500                         asm     mov     al,0xb6                 // Write to channel 2 (speaker) timer\r
501                         asm     out     43h,al\r
502                         asm     mov     al,bl\r
503                         asm     out     42h,al                  // Low byte\r
504                         asm     mov     al,bh\r
505                         asm     out     42h,al                  // High byte\r
506 \r
507                         asm     in      al,0x61                 // Turn the speaker & gate on\r
508                         asm     or      al,3\r
509                         asm     out     0x61,al\r
510                         }\r
511                         else                                    // Time for some silence\r
512                         {\r
513                         asm     in      al,0x61                 // Turn the speaker & gate off\r
514                         asm     and     al,0xfc                 // ~3\r
515                         asm     out     0x61,al\r
516                         }\r
517 \r
518                 asm     popf\r
519                 }\r
520 \r
521                 if (!(--pcLengthLeft))\r
522                 {\r
523                         SDL_PCStopSound();\r
524                         SDL_SoundFinished();\r
525                 }\r
526         }\r
527 }\r
528 \r
529 ///////////////////////////////////////////////////////////////////////////\r
530 //\r
531 //      SDL_ShutPC() - Turns off the pc speaker\r
532 //\r
533 ///////////////////////////////////////////////////////////////////////////\r
534 static void\r
535 SDL_ShutPC(void)\r
536 {\r
537 asm     pushf\r
538 asm     cli\r
539 \r
540         pcSound = 0;\r
541 \r
542 asm     in      al,0x61                 // Turn the speaker & gate off\r
543 asm     and     al,0xfc                 // ~3\r
544 asm     out     0x61,al\r
545 \r
546 asm     popf\r
547 }\r
548 \r
549 //\r
550 //      Stuff for digitized sounds\r
551 //\r
552 memptr\r
553 SDL_LoadDigiSegment(word page, global_game_variables_t *gvar)\r
554 {\r
555         memptr  addr;\r
556 \r
557 #if 0   // for debugging\r
558 asm     mov     dx,STATUS_REGISTER_1\r
559 asm     in      al,dx\r
560 asm     mov     dx,ATR_INDEX\r
561 asm     mov     al,ATR_OVERSCAN\r
562 asm     out     dx,al\r
563 asm     mov     al,10   // bright green\r
564 asm     out     dx,al\r
565 #endif\r
566 \r
567         addr = PM_GetSoundPage(page);\r
568         PM_SetPageLock(gvar->pm.fi.PMSoundStart + page,pml_Locked, gvar);\r
569 \r
570 #if 0   // for debugging\r
571 asm     mov     dx,STATUS_REGISTER_1\r
572 asm     in      al,dx\r
573 asm     mov     dx,ATR_INDEX\r
574 asm     mov     al,ATR_OVERSCAN\r
575 asm     out     dx,al\r
576 asm     mov     al,3    // blue\r
577 asm     out     dx,al\r
578 asm     mov     al,0x20 // normal\r
579 asm     out     dx,al\r
580 #endif\r
581 \r
582         return(addr);\r
583 }\r
584 \r
585 void\r
586 SDL_PlayDigiSegment(memptr addr,word len)\r
587 {\r
588         switch (DigiMode)\r
589         {\r
590         case sds_PC:\r
591         SDL_PCPlaySample(addr,len);\r
592                 break;\r
593 //SS    case sds_SoundSource:\r
594 //SS            SDL_SSPlaySample(addr,len);\r
595 //SS            break;\r
596 //SB    case sds_SoundBlaster:\r
597 //SB            SDL_SBPlaySample(addr,len);\r
598 //SB            break;\r
599         }\r
600 }\r
601 \r
602 void\r
603 SD_StopDigitized(global_game_variables_t *gvar)\r
604 {\r
605         int     i;\r
606 \r
607 asm     pushf\r
608 asm     cli\r
609 \r
610         DigiLeft = 0;\r
611         DigiNextAddr = nil;\r
612         DigiNextLen = 0;\r
613         DigiMissed = false;\r
614         DigiPlaying = false;\r
615         DigiNumber = DigiPriority = 0;\r
616         SoundPositioned = false;\r
617         if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
618                 SDL_SoundFinished();\r
619 \r
620         switch (DigiMode)\r
621         {\r
622         case sds_PC:\r
623                 SDL_PCStopSample();\r
624                 break;\r
625 //SS    case sds_SoundSource:\r
626 //SS            SDL_SSStopSample();\r
627 //SS            break;\r
628 //SB    case sds_SoundBlaster:\r
629 //SB            SDL_SBStopSample();\r
630 //SB            break;\r
631         }\r
632 \r
633 asm     popf\r
634 \r
635         for (i = DigiLastStart;i < DigiLastEnd;i++)\r
636                 PM_SetPageLock(i + gvar->pm.fi.PMSoundStart,pml_Unlocked, gvar);\r
637         DigiLastStart = 1;\r
638         DigiLastEnd = 0;\r
639 }\r
640 \r
641 void\r
642 SD_Poll(global_game_variables_t *gvar)\r
643 {\r
644         if (DigiLeft && !DigiNextAddr)\r
645         {\r
646                 DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);\r
647                 DigiLeft -= DigiNextLen;\r
648                 if (!DigiLeft)\r
649                         DigiLastSegment = true;\r
650                 DigiNextAddr = SDL_LoadDigiSegment(DigiPage++, gvar);\r
651         }\r
652         if (DigiMissed && DigiNextAddr)\r
653         {\r
654                 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);\r
655                 DigiNextAddr = nil;\r
656                 DigiMissed = false;\r
657                 if (DigiLastSegment)\r
658                 {\r
659                         DigiPlaying = false;\r
660                         DigiLastSegment = false;\r
661                 }\r
662         }\r
663         SDL_SetTimerSpeed();\r
664 }\r
665 \r
666 void\r
667 SD_SetPosition(int leftpos,int rightpos, global_game_variables_t *gvar)\r
668 {\r
669         if\r
670         (\r
671                 (leftpos < 0)\r
672         ||      (leftpos > 15)\r
673         ||      (rightpos < 0)\r
674         ||      (rightpos > 15)\r
675         ||      ((leftpos == 15) && (rightpos == 15))\r
676         )\r
677                 Quit(gvar, "SD_SetPosition: Illegal position");\r
678 \r
679         switch (DigiMode)\r
680         {\r
681 //SB    case sds_SoundBlaster:\r
682 //SB            SDL_PositionSBP(leftpos,rightpos);\r
683 //SB            break;\r
684         }\r
685 }\r
686 \r
687 void\r
688 SD_PlayDigitized(word which,int leftpos,int rightpos, global_game_variables_t *gvar)\r
689 {\r
690         word    len;\r
691         memptr  addr;\r
692 \r
693         if (!DigiMode)\r
694                 return;\r
695 \r
696         SD_StopDigitized(gvar);\r
697         if (which >= NumDigi)\r
698                 Quit(gvar, "SD_PlayDigitized: bad sound number");\r
699 \r
700         SD_SetPosition(leftpos,rightpos, gvar);\r
701 \r
702         DigiPage = DigiList[(which * 2) + 0];\r
703         DigiLeft = DigiList[(which * 2) + 1];\r
704 \r
705         DigiLastStart = DigiPage;\r
706         DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize);\r
707 \r
708         len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);\r
709         addr = SDL_LoadDigiSegment(DigiPage++, gvar);\r
710 \r
711         DigiPlaying = true;\r
712         DigiLastSegment = false;\r
713 \r
714         SDL_PlayDigiSegment(addr,len);\r
715         DigiLeft -= len;\r
716         if (!DigiLeft)\r
717                 DigiLastSegment = true;\r
718 \r
719         SD_Poll(gvar);\r
720 }\r
721 \r
722 void\r
723 SDL_DigitizedDone(void)\r
724 {\r
725         if (DigiNextAddr)\r
726         {\r
727                 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);\r
728                 DigiNextAddr = nil;\r
729                 DigiMissed = false;\r
730         }\r
731         else\r
732         {\r
733                 if (DigiLastSegment)\r
734                 {\r
735                         DigiPlaying = false;\r
736                         DigiLastSegment = false;\r
737                         if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
738                         {\r
739                                 SDL_SoundFinished();\r
740                         }\r
741                         else\r
742                                 DigiNumber = DigiPriority = 0;\r
743                         SoundPositioned = false;\r
744                 }\r
745                 else\r
746                         DigiMissed = true;\r
747         }\r
748 }\r
749 \r
750 void\r
751 SD_SetDigiDevice(SDSMode mode, global_game_variables_t *gvar)\r
752 {\r
753         boolean devicenotpresent;\r
754 \r
755         if (mode == DigiMode)\r
756                 return;\r
757 \r
758         SD_StopDigitized(gvar);\r
759 \r
760         devicenotpresent = false;\r
761         switch (mode)\r
762         {\r
763         case sds_SoundBlaster:\r
764                 if (!SoundBlasterPresent)\r
765                 {\r
766                         if (SoundSourcePresent)\r
767                                 mode = sds_SoundSource;\r
768                         else\r
769                                 devicenotpresent = true;\r
770                 }\r
771                 break;\r
772         case sds_SoundSource:\r
773                 if (!SoundSourcePresent)\r
774                         devicenotpresent = true;\r
775                 break;\r
776         }\r
777 \r
778         if (!devicenotpresent)\r
779         {\r
780 //SS            if (DigiMode == sds_SoundSource)\r
781 //SS                    SDL_ShutSS();\r
782 \r
783                 DigiMode = mode;\r
784 \r
785 //SS            if (mode == sds_SoundSource)\r
786 //SS                    SDL_StartSS();\r
787 \r
788                 SDL_SetTimerSpeed();\r
789         }\r
790 }\r
791 \r
792 void\r
793 SDL_SetupDigi(global_game_variables_t *gvar)\r
794 {\r
795         memptr  list;\r
796         word    far *p,\r
797                         pg;\r
798         int             i;\r
799 \r
800         PM_UnlockMainMem(gvar);\r
801         MM_GetPtr(&list,PMPageSize, gvar);\r
802         PM_CheckMainMem(gvar);\r
803         p = (word far *)MK_FP(PM_GetPage(gvar->pm.fi.ChunksInFile - 1, gvar),0);\r
804         _fmemcpy((void far *)list,(void far *)p,PMPageSize);\r
805         pg = gvar->pm.fi.PMSoundStart;\r
806         for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2)\r
807         {\r
808                 if (pg >= gvar->pm.fi.ChunksInFile - 1)\r
809                         break;\r
810                 pg += (p[1] + (PMPageSize - 1)) / PMPageSize;\r
811         }\r
812         PM_UnlockMainMem(gvar);\r
813         MM_GetPtr(MEMPTRCONV DigiList,i * sizeof(word) * 2, gvar);\r
814         _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);\r
815         MM_FreePtr(&list, gvar);\r
816         NumDigi = i;\r
817 \r
818         for (i = 0;i < LASTSOUND;i++)\r
819                 DigiMap[i] = -1;\r
820 }\r
821 \r
822 //      AdLib Code\r
823 \r
824 ///////////////////////////////////////////////////////////////////////////\r
825 //\r
826 //      alOut(n,b) - Puts b in AdLib card register n\r
827 //\r
828 ///////////////////////////////////////////////////////////////////////////\r
829 void\r
830 alOut(byte n,byte b)\r
831 {\r
832 asm     pushf\r
833 asm     cli\r
834 \r
835 asm     mov             dx,0x388\r
836 asm     mov             al,[n]\r
837 asm     out             dx,al\r
838 #if 0\r
839         SDL_Delay(TimerDelay10);\r
840 #else\r
841 asm     in      al, dx\r
842 asm     in      al, dx\r
843 asm     in      al, dx\r
844 asm     in      al, dx\r
845 asm     in      al, dx\r
846 asm     in      al, dx\r
847 #endif\r
848 \r
849 asm     mov             dx,0x389\r
850 asm     mov             al,[b]\r
851 asm     out             dx,al\r
852 \r
853 asm     popf\r
854 \r
855 #if 0\r
856         SDL_Delay(TimerDelay25);\r
857 #else\r
858 asm     mov     dx,0x388\r
859 asm     in      al, dx\r
860 asm     in      al, dx\r
861 asm     in      al, dx\r
862 asm     in      al, dx\r
863 asm     in      al, dx\r
864 asm     in      al, dx\r
865 asm     in      al, dx\r
866 asm     in      al, dx\r
867 asm     in      al, dx\r
868 asm     in      al, dx\r
869 \r
870 asm     in      al, dx\r
871 asm     in      al, dx\r
872 asm     in      al, dx\r
873 asm     in      al, dx\r
874 asm     in      al, dx\r
875 asm     in      al, dx\r
876 asm     in      al, dx\r
877 asm     in      al, dx\r
878 asm     in      al, dx\r
879 asm     in      al, dx\r
880 \r
881 asm     in      al, dx\r
882 asm     in      al, dx\r
883 asm     in      al, dx\r
884 asm     in      al, dx\r
885 asm     in      al, dx\r
886 asm     in      al, dx\r
887 asm     in      al, dx\r
888 asm     in      al, dx\r
889 asm     in      al, dx\r
890 asm     in      al, dx\r
891 \r
892 asm     in      al, dx\r
893 asm     in      al, dx\r
894 asm     in      al, dx\r
895 asm     in      al, dx\r
896 asm     in      al, dx\r
897 #endif\r
898 }\r
899 \r
900 //#if 0\r
901 ///////////////////////////////////////////////////////////////////////////\r
902 //\r
903 //      SDL_SetInstrument() - Puts an instrument into a generator\r
904 //\r
905 ///////////////////////////////////////////////////////////////////////////\r
906 static void\r
907 SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)\r
908 {\r
909         byte            c,m;\r
910 \r
911         if (percussive)\r
912         {\r
913                 c = pcarriers[which];\r
914                 m = pmodifiers[which];\r
915         }\r
916         else\r
917         {\r
918                 c = carriers[which];\r
919                 m = modifiers[which];\r
920         }\r
921 \r
922         tracks[track - 1]->inst = *inst;\r
923         tracks[track - 1]->percussive = percussive;\r
924 \r
925         alOut(m + alChar,inst->mChar);\r
926         alOut(m + alScale,inst->mScale);\r
927         alOut(m + alAttack,inst->mAttack);\r
928         alOut(m + alSus,inst->mSus);\r
929         alOut(m + alWave,inst->mWave);\r
930 \r
931         // Most percussive instruments only use one cell\r
932         if (c != 0xff)\r
933         {\r
934                 alOut(c + alChar,inst->cChar);\r
935                 alOut(c + alScale,inst->cScale);\r
936                 alOut(c + alAttack,inst->cAttack);\r
937                 alOut(c + alSus,inst->cSus);\r
938                 alOut(c + alWave,inst->cWave);\r
939         }\r
940 \r
941         alOut(which + alFeedCon,inst->nConn);   // DEBUG - I think this is right\r
942 }\r
943 //#endif\r
944 \r
945 ///////////////////////////////////////////////////////////////////////////\r
946 //\r
947 //      SDL_ALStopSound() - Turns off any sound effects playing through the\r
948 //              AdLib card\r
949 //\r
950 ///////////////////////////////////////////////////////////////////////////\r
951 #ifdef  _MUSE_\r
952 void\r
953 #else\r
954 static void\r
955 #endif\r
956 SDL_ALStopSound(void)\r
957 {\r
958 asm     pushf\r
959 asm     cli\r
960 \r
961         /*(long)*/alSound = 0;\r
962         alOut(alFreqH + 0,0);\r
963 \r
964 asm     popf\r
965 }\r
966 \r
967 static void\r
968 SDL_AlSetFXInst(Instrument far *inst)\r
969 {\r
970         byte            c,m;\r
971 \r
972         m = modifiers[0];\r
973         c = carriers[0];\r
974         alOut(m + alChar,inst->mChar);\r
975         alOut(m + alScale,inst->mScale);\r
976         alOut(m + alAttack,inst->mAttack);\r
977         alOut(m + alSus,inst->mSus);\r
978         alOut(m + alWave,inst->mWave);\r
979         alOut(c + alChar,inst->cChar);\r
980         alOut(c + alScale,inst->cScale);\r
981         alOut(c + alAttack,inst->cAttack);\r
982         alOut(c + alSus,inst->cSus);\r
983         alOut(c + alWave,inst->cWave);\r
984 \r
985         // Note: Switch commenting on these lines for old MUSE compatibility\r
986 //      alOut(alFeedCon,inst->nConn);\r
987         alOut(alFeedCon,0);\r
988 }\r
989 \r
990 ///////////////////////////////////////////////////////////////////////////\r
991 //\r
992 //      SDL_ALPlaySound() - Plays the specified sound on the AdLib card\r
993 //\r
994 ///////////////////////////////////////////////////////////////////////////\r
995 #ifdef  _MUSE_\r
996 void\r
997 #else\r
998 static void\r
999 #endif\r
1000 SDL_ALPlaySound(AdLibSound far *sound, global_game_variables_t *gvar)\r
1001 {\r
1002         Instrument      __far *inst;\r
1003         byte            huge *data;\r
1004 \r
1005         SDL_ALStopSound();\r
1006 \r
1007 asm     pushf\r
1008 asm     cli\r
1009 \r
1010         alLengthLeft = sound->common.length;\r
1011         data = sound->data;\r
1012         data++;\r
1013         data--;\r
1014         alSound = (byte far *)data;\r
1015         alBlock = ((sound->block & 7) << 2) | 0x20;\r
1016         inst = &sound->inst;\r
1017 \r
1018         if (!(inst->mSus | inst->cSus))\r
1019         {\r
1020         asm     popf\r
1021                 Quit(gvar, "SDL_ALPlaySound() - Bad instrument");\r
1022         }\r
1023 \r
1024         SDL_AlSetFXInst(&alZeroInst);   // DEBUG\r
1025         SDL_AlSetFXInst(inst);\r
1026 \r
1027 asm     popf\r
1028 }\r
1029 \r
1030 //#if 0\r
1031 ///////////////////////////////////////////////////////////////////////////\r
1032 //\r
1033 //      SDL_ALSoundService() - Plays the next sample out through the AdLib card\r
1034 //\r
1035 ///////////////////////////////////////////////////////////////////////////\r
1036 //static void\r
1037 void\r
1038 SDL_ALSoundService(void)\r
1039 {\r
1040         byte    s;\r
1041 \r
1042         if (alSound)\r
1043         {\r
1044                 s = *alSound++;\r
1045                 if (!s)\r
1046                         alOut(alFreqH + 0,0);\r
1047                 else\r
1048                 {\r
1049                         alOut(alFreqL + 0,s);\r
1050                         alOut(alFreqH + 0,alBlock);\r
1051                 }\r
1052 \r
1053                 if (!(--alLengthLeft))\r
1054                 {\r
1055                         /*(long)*/alSound = 0;\r
1056                         alOut(alFreqH + 0,0);\r
1057                         SDL_SoundFinished();\r
1058                 }\r
1059         }\r
1060 }\r
1061 //#endif\r
1062 \r
1063 #if 0\r
1064 ///////////////////////////////////////////////////////////////////////////\r
1065 //\r
1066 //      SDL_SelectMeasure() - sets up sequencing variables for a given track\r
1067 //\r
1068 ///////////////////////////////////////////////////////////////////////////\r
1069 void\r
1070 SDL_SelectMeasure(ActiveTrack *track)\r
1071 {\r
1072         track->seq = track->moods[track->mood];\r
1073         track->nextevent = 0;\r
1074 }\r
1075 #endif\r
1076 \r
1077 //#if 0\r
1078 void\r
1079 SDL_ALService(void)\r
1080 {\r
1081         byte    a,v;\r
1082         word    w;\r
1083 \r
1084         a=v=0;\r
1085 \r
1086         if (!sqActive)\r
1087                 return;\r
1088 \r
1089         while (sqHackLen && (sqHackTime <= alTimeCount))\r
1090         {\r
1091                 w = *sqHackPtr++;\r
1092                 sqHackTime = alTimeCount + *sqHackPtr++;\r
1093         asm     mov     dx,[w]\r
1094         asm     mov     [a],dl\r
1095         asm     mov     [v],dh\r
1096                 alOut(a,v);\r
1097                 sqHackLen -= 4;\r
1098         }\r
1099         alTimeCount++;\r
1100         if (!sqHackLen)\r
1101         {\r
1102                 sqHackPtr = (word far *)sqHack;\r
1103                 sqHackLen = sqHackSeqLen;\r
1104                 alTimeCount = sqHackTime = 0;\r
1105         }\r
1106 }\r
1107 //#endif\r
1108 \r
1109 ///////////////////////////////////////////////////////////////////////////\r
1110 //\r
1111 //      SDL_ShutAL() - Shuts down the AdLib card for sound effects\r
1112 //\r
1113 ///////////////////////////////////////////////////////////////////////////\r
1114 static void\r
1115 SDL_ShutAL(void)\r
1116 {\r
1117 asm     pushf\r
1118 asm     cli\r
1119 \r
1120         alOut(alEffects,0);\r
1121         alOut(alFreqH + 0,0);\r
1122         SDL_AlSetFXInst(&alZeroInst);\r
1123         alSound = 0;\r
1124 \r
1125 asm     popf\r
1126 }\r
1127 \r
1128 ///////////////////////////////////////////////////////////////////////////\r
1129 //\r
1130 //      SDL_CleanAL() - Totally shuts down the AdLib card\r
1131 //\r
1132 ///////////////////////////////////////////////////////////////////////////\r
1133 static void\r
1134 SDL_CleanAL(void)\r
1135 {\r
1136         int     i;\r
1137 \r
1138 asm     pushf\r
1139 asm     cli\r
1140 \r
1141         alOut(alEffects,0);\r
1142         for (i = 1;i < 0xf5;i++)\r
1143                 alOut(i,0);\r
1144 \r
1145 asm     popf\r
1146 }\r
1147 \r
1148 ///////////////////////////////////////////////////////////////////////////\r
1149 //\r
1150 //      SDL_StartAL() - Starts up the AdLib card for sound effects\r
1151 //\r
1152 ///////////////////////////////////////////////////////////////////////////\r
1153 static void\r
1154 SDL_StartAL(void)\r
1155 {\r
1156         alFXReg = 0;\r
1157         alOut(alEffects,alFXReg);\r
1158         SDL_AlSetFXInst(&alZeroInst);\r
1159 }\r
1160 \r
1161 ///////////////////////////////////////////////////////////////////////////\r
1162 //\r
1163 //      SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster\r
1164 //              emulating an AdLib) present\r
1165 //\r
1166 ///////////////////////////////////////////////////////////////////////////\r
1167 static boolean\r
1168 SDL_DetectAdLib(void)\r
1169 {\r
1170         byte    status1,status2;\r
1171         int             i;\r
1172 \r
1173         alOut(4,0x60);  // Reset T1 & T2\r
1174         alOut(4,0x80);  // Reset IRQ\r
1175         status1 = readstat();\r
1176         alOut(2,0xff);  // Set timer 1\r
1177         alOut(4,0x21);  // Start timer 1\r
1178 #if 0\r
1179         SDL_Delay(TimerDelay100);\r
1180 #else\r
1181         __asm {\r
1182                 mov     dx,0x388\r
1183                 mov     cx,100\r
1184 #ifdef __BORLANDC__\r
1185         }\r
1186 #endif\r
1187 usecloop:\r
1188 #ifdef __BORLANDC__\r
1189         __asm {\r
1190 #endif\r
1191         in      al,dx\r
1192         loop usecloop\r
1193         }\r
1194 #endif\r
1195 \r
1196         status2 = readstat();\r
1197         alOut(4,0x60);\r
1198         alOut(4,0x80);\r
1199 \r
1200         if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))\r
1201         {\r
1202                 for (i = 1;i <= 0xf5;i++)       // Zero all the registers\r
1203                         alOut(i,0);\r
1204 \r
1205                 alOut(1,0x20);  // Set WSE=1\r
1206                 alOut(8,0);             // Set CSM=0 & SEL=0\r
1207 \r
1208                 return(true);\r
1209         }\r
1210         else\r
1211                 return(false);\r
1212 }\r
1213 \r
1214 #if 0\r
1215 ///////////////////////////////////////////////////////////////////////////\r
1216 //\r
1217 //      SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
1218 //              dispatches to whatever other routines are appropriate\r
1219 //\r
1220 ///////////////////////////////////////////////////////////////////////////\r
1221 static void interrupt\r
1222 SDL_t0Service(void)\r
1223 {\r
1224 static  word    count = 1;\r
1225 \r
1226 #if 1   // for debugging\r
1227 asm     mov     dx,STATUS_REGISTER_1\r
1228 asm     in      al,dx\r
1229 asm     mov     dx,ATR_INDEX\r
1230 asm     mov     al,ATR_OVERSCAN\r
1231 asm     out     dx,al\r
1232 asm     mov     al,4    // red\r
1233 asm     out     dx,al\r
1234 #endif\r
1235 \r
1236         HackCount++;\r
1237 \r
1238         if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))\r
1239         {\r
1240                 SDL_ALService();\r
1241                 SDL_SSService();\r
1242 //              if (!(++count & 7))\r
1243                 if (!(++count % 10))\r
1244                 {\r
1245                         LocalTime++;\r
1246                         TimeCount++;\r
1247                         if (SoundUserHook)\r
1248                                 SoundUserHook();\r
1249                 }\r
1250 //              if (!(count & 3))\r
1251                 if (!(count % 5))\r
1252                 {\r
1253                         switch (SoundMode)\r
1254                         {\r
1255                         case sdm_PC:\r
1256                                 SDL_PCService();\r
1257                                 break;\r
1258                         case sdm_AdLib:\r
1259                                 SDL_ALSoundService();\r
1260                                 break;\r
1261                         }\r
1262                 }\r
1263         }\r
1264         else\r
1265         {\r
1266                 if (!(++count & 1))\r
1267                 {\r
1268                         LocalTime++;\r
1269                         TimeCount++;\r
1270                         if (SoundUserHook)\r
1271                                 SoundUserHook();\r
1272                 }\r
1273                 switch (SoundMode)\r
1274                 {\r
1275                 case sdm_PC:\r
1276                         SDL_PCService();\r
1277                         break;\r
1278                 case sdm_AdLib:\r
1279                         SDL_ALSoundService();\r
1280                         break;\r
1281                 }\r
1282         }\r
1283 \r
1284 asm     mov     ax,[WORD PTR TimerCount]\r
1285 asm     add     ax,[WORD PTR TimerDivisor]\r
1286 asm     mov     [WORD PTR TimerCount],ax\r
1287 asm     jnc     myack\r
1288         t0OldService();                 // If we overflow a word, time to call old int handler\r
1289 asm     jmp     olddone\r
1290 myack:;\r
1291         outportb(0x20,0x20);    // Ack the interrupt\r
1292 olddone:;\r
1293 \r
1294 #if 1   // for debugging\r
1295 asm     mov     dx,STATUS_REGISTER_1\r
1296 asm     in      al,dx\r
1297 asm     mov     dx,ATR_INDEX\r
1298 asm     mov     al,ATR_OVERSCAN\r
1299 asm     out     dx,al\r
1300 asm     mov     al,3    // blue\r
1301 asm     out     dx,al\r
1302 asm     mov     al,0x20 // normal\r
1303 asm     out     dx,al\r
1304 #endif\r
1305 }\r
1306 #endif\r
1307 \r
1308 ////////////////////////////////////////////////////////////////////////////\r
1309 //\r
1310 //      SDL_ShutDevice() - turns off whatever device was being used for sound fx\r
1311 //\r
1312 ////////////////////////////////////////////////////////////////////////////\r
1313 static void\r
1314 SDL_ShutDevice(void)\r
1315 {\r
1316         switch (SoundMode)\r
1317         {\r
1318         case sdm_PC:\r
1319                 SDL_ShutPC();\r
1320                 break;\r
1321         case sdm_AdLib:\r
1322                 SDL_ShutAL();\r
1323                 break;\r
1324         }\r
1325         SoundMode = sdm_Off;\r
1326 }\r
1327 \r
1328 ///////////////////////////////////////////////////////////////////////////\r
1329 //\r
1330 //      SDL_CleanDevice() - totally shuts down all sound devices\r
1331 //\r
1332 ///////////////////////////////////////////////////////////////////////////\r
1333 static void\r
1334 SDL_CleanDevice(void)\r
1335 {\r
1336         if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))\r
1337                 SDL_CleanAL();\r
1338 }\r
1339 \r
1340 ///////////////////////////////////////////////////////////////////////////\r
1341 //\r
1342 //      SDL_StartDevice() - turns on whatever device is to be used for sound fx\r
1343 //\r
1344 ///////////////////////////////////////////////////////////////////////////\r
1345 static void\r
1346 SDL_StartDevice(void)\r
1347 {\r
1348         switch (SoundMode)\r
1349         {\r
1350         case sdm_AdLib:\r
1351                 SDL_StartAL();\r
1352                 break;\r
1353         }\r
1354         SoundNumber = SoundPriority = 0;\r
1355 }\r
1356 \r
1357 //      Public routines\r
1358 \r
1359 ///////////////////////////////////////////////////////////////////////////\r
1360 //\r
1361 //      SD_SetSoundMode() - Sets which sound hardware to use for sound effects\r
1362 //\r
1363 ///////////////////////////////////////////////////////////////////////////\r
1364 boolean\r
1365 SD_SetSoundMode(SDMode mode, global_game_variables_t *gvar)\r
1366 {\r
1367         boolean result = false;\r
1368         word    tableoffset;\r
1369 \r
1370         SD_StopSound(gvar);\r
1371 \r
1372 #ifndef _MUSE_\r
1373         if ((mode == sdm_AdLib) && !AdLibPresent)\r
1374                 mode = sdm_PC;\r
1375 \r
1376         switch (mode)\r
1377         {\r
1378         case sdm_Off:\r
1379                 NeedsDigitized = false;\r
1380                 result = true;\r
1381                 break;\r
1382         case sdm_PC:\r
1383                 tableoffset = STARTPCSOUNDS;\r
1384                 NeedsDigitized = false;\r
1385                 result = true;\r
1386                 break;\r
1387         case sdm_AdLib:\r
1388                 if (AdLibPresent)\r
1389                 {\r
1390                         tableoffset = STARTADLIBSOUNDS;\r
1391                         NeedsDigitized = false;\r
1392                         result = true;\r
1393                 }\r
1394                 break;\r
1395         }\r
1396 #else\r
1397         result = true;\r
1398 #endif\r
1399 \r
1400         if (result && (mode != SoundMode))\r
1401         {\r
1402                 SDL_ShutDevice();\r
1403                 SoundMode = mode;\r
1404 #ifndef _MUSE_\r
1405                 SoundTable = (word *)(&gvar->ca.audiosegs[tableoffset]);\r
1406 #endif\r
1407                 SDL_StartDevice();\r
1408         }\r
1409 \r
1410         SDL_SetTimerSpeed();\r
1411 \r
1412         return(result);\r
1413 }\r
1414 \r
1415 ///////////////////////////////////////////////////////////////////////////\r
1416 //\r
1417 //      SD_SetMusicMode() - sets the device to use for background music\r
1418 //\r
1419 ///////////////////////////////////////////////////////////////////////////\r
1420 boolean\r
1421 SD_SetMusicMode(SMMode mode)\r
1422 {\r
1423         boolean result = false;\r
1424 \r
1425         SD_FadeOutMusic();\r
1426         while (SD_MusicPlaying())\r
1427                 ;\r
1428 \r
1429         switch (mode)\r
1430         {\r
1431         case smm_Off:\r
1432                 NeedsMusic = false;\r
1433                 result = true;\r
1434                 break;\r
1435         case smm_AdLib:\r
1436                 if (AdLibPresent)\r
1437                 {\r
1438                         NeedsMusic = true;\r
1439                         result = true;\r
1440                 }\r
1441                 break;\r
1442         }\r
1443 \r
1444         if (result)\r
1445                 MusicMode = mode;\r
1446 \r
1447         SDL_SetTimerSpeed();\r
1448 \r
1449         return(result);\r
1450 }\r
1451 \r
1452 ///////////////////////////////////////////////////////////////////////////\r
1453 //\r
1454 //      SD_Startup() - starts up the Sound Mgr\r
1455 //              Detects all additional sound hardware and installs my ISR\r
1456 //\r
1457 ///////////////////////////////////////////////////////////////////////////\r
1458 void\r
1459 SD_Startup(global_game_variables_t *gvar)\r
1460 {\r
1461         int     i;\r
1462 \r
1463         if (SD_Started)\r
1464                 return;\r
1465 \r
1466         SDL_SetDS();\r
1467 \r
1468         ssIsTandy = false;\r
1469 //SS    ssNoCheck = false;\r
1470         alNoCheck = false;\r
1471 //SB    sbNoCheck = false;\r
1472 //SB    sbNoProCheck = false;\r
1473 #ifndef _MUSE_\r
1474         for (i = 1;i < _argc;i++)\r
1475         {\r
1476                 switch (US_CheckParm(_argv[i],ParmStrings))\r
1477                 {\r
1478                 case 0:                                         // No AdLib detection\r
1479                         alNoCheck = true;\r
1480                         break;\r
1481 //SB            case 1:                                         // No SoundBlaster detection\r
1482 //SB                    sbNoCheck = true;\r
1483 //SB                    break;\r
1484 //SB            case 2:                                         // No SoundBlaster Pro detection\r
1485 //SB                    sbNoProCheck = true;\r
1486 //SB                    break;\r
1487 //SS            case 3:\r
1488 //SS                    ssNoCheck = true;               // No Sound Source detection\r
1489 //SS                    break;\r
1490                 case 4:                                         // Tandy Sound Source handling\r
1491                         ssIsTandy = true;\r
1492                         break;\r
1493 //SS            case 5:                                         // Sound Source present at LPT1\r
1494 //SS                    ssPort = 1;\r
1495 //SS                    ssNoCheck = SoundSourcePresent = true;\r
1496 //SS                    break;\r
1497 //SS            case 6:                     // Sound Source present at LPT2\r
1498 //SS                    ssPort = 2;\r
1499 //SS                    ssNoCheck = SoundSourcePresent = true;\r
1500 //SS                    break;\r
1501 //SS            case 7:                     // Sound Source present at LPT3\r
1502 //SS                    ssPort = 3;\r
1503 //SS                    ssNoCheck = SoundSourcePresent = true;\r
1504 //SS                    break;\r
1505                 }\r
1506         }\r
1507 #endif\r
1508 \r
1509         SoundUserHook = 0;\r
1510 \r
1511         t0OldService = getvect(8);      // Get old timer 0 ISR\r
1512 \r
1513         LocalTime = TimeCount = alTimeCount = 0;\r
1514 \r
1515         SD_SetSoundMode(sdm_Off, gvar);\r
1516         SD_SetMusicMode(smm_Off);\r
1517 \r
1518 //SS    if (!ssNoCheck)\r
1519 //SS            SoundSourcePresent = SDL_DetectSoundSource();\r
1520 \r
1521         if (!alNoCheck)\r
1522         {\r
1523                 AdLibPresent = SDL_DetectAdLib();\r
1524 //SB            if (AdLibPresent) && !sbNoCheck)\r
1525 //SB            {\r
1526 //SB                    int port = -1;\r
1527 //SB                    char *env = getenv("BLASTER");\r
1528 //SB                    if (env)\r
1529 //SB                    {\r
1530 //SB                            long temp;\r
1531 //SB                            while (*env)\r
1532 //SB                            {\r
1533 //SB                                    while (isspace(*env))\r
1534 //SB                                            env++;\r
1535 //SB\r
1536 //SB                                    switch (toupper(*env))\r
1537 //SB                                    {\r
1538 //SB                                    case 'A':\r
1539 //SB                                            temp = strtol(env + 1,&env,16);\r
1540 //SB                                            if\r
1541 //SB                                            (\r
1542 //SB                                                    (temp >= 0x210)\r
1543 //SB                                            &&      (temp <= 0x260)\r
1544 //SB                                            &&      (!(temp & 0x00f))\r
1545 //SB                                            )\r
1546 //SB                                                    port = (temp - 0x200) >> 4;\r
1547 //SB                                            else\r
1548 //SB                                                    Quit(gvar, "SD_Startup: Unsupported address value in BLASTER");\r
1549 //SB                                            break;\r
1550 //SB                                    case 'I':\r
1551 //SB                                            temp = strtol(env + 1,&env,10);\r
1552 //SB                                            if\r
1553 //SB                                            (\r
1554 //SB                                                    (temp >= 0)\r
1555 //SB                                            &&      (temp <= 10)\r
1556 //SB                                            &&      (sbIntVectors[temp] != -1)\r
1557 //SB                                            )\r
1558 //SB                                            {\r
1559 //SB                                                    sbInterrupt = temp;\r
1560 //SB                                                    sbIntVec = sbIntVectors[sbInterrupt];\r
1561 //SB                                            }\r
1562 //SB                                            else\r
1563 //SB                                                    Quit(gvar, "SD_Startup: Unsupported interrupt value in BLASTER");\r
1564 //SB                                            break;\r
1565 //SB                                    case 'D':\r
1566 //SB                                            temp = strtol(env + 1,&env,10);\r
1567 //SB                                            if ((temp == 0) || (temp == 1) || (temp == 3))\r
1568 //SB                                                    SDL_SBSetDMA(temp);\r
1569 //SB                                            else\r
1570 //SB                                                    Quit(gvar, "SD_Startup: Unsupported DMA value in BLASTER");\r
1571 //SB                                            break;\r
1572 //SB                                    default:\r
1573 //SB                                            while (isspace(*env))\r
1574 //SB                                                    env++;\r
1575 //SB                                            while (*env && !isspace(*env))\r
1576 //SB                                                    env++;\r
1577 //SB                                            break;\r
1578 //SB                                    }\r
1579 //SB                            }\r
1580 //SB                    }\r
1581 //SB                    SoundBlasterPresent = SDL_DetectSoundBlaster(port);\r
1582 //SB            }\r
1583         }\r
1584 \r
1585         for (i = 0;i < 255;i++)\r
1586                 pcSoundLookup[i] = i * 60;\r
1587 \r
1588 //SB    if (SoundBlasterPresent)\r
1589 //SB            SDL_StartSB();\r
1590 \r
1591         SDL_SetupDigi(gvar);\r
1592 \r
1593         SD_Started = true;\r
1594 }\r
1595 \r
1596 ///////////////////////////////////////////////////////////////////////////\r
1597 //\r
1598 //      SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
1599 //              the config file was present or not.\r
1600 //\r
1601 ///////////////////////////////////////////////////////////////////////////\r
1602 void\r
1603 SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar)\r
1604 {\r
1605         boolean gotsd,gotsm;\r
1606 \r
1607         gotsd = gotsm = gotit;\r
1608 \r
1609         if (gotsd)      // Make sure requested sound hardware is available\r
1610         {\r
1611                 switch (sd)\r
1612                 {\r
1613                 case sdm_AdLib:\r
1614                         gotsd = AdLibPresent;\r
1615                         break;\r
1616                 }\r
1617         }\r
1618         if (!gotsd)\r
1619         {\r
1620                 if (AdLibPresent)\r
1621                         sd = sdm_AdLib;\r
1622                 else\r
1623                         sd = sdm_PC;\r
1624         }\r
1625         if (sd != SoundMode)\r
1626                 SD_SetSoundMode(sd, gvar);\r
1627 \r
1628 \r
1629         if (gotsm)      // Make sure requested music hardware is available\r
1630         {\r
1631                 switch (sm)\r
1632                 {\r
1633                 case sdm_AdLib:\r
1634                         gotsm = AdLibPresent;\r
1635                         break;\r
1636                 }\r
1637         }\r
1638         if (!gotsm)\r
1639         {\r
1640                 if (AdLibPresent)\r
1641                         sm = smm_AdLib;\r
1642         }\r
1643         if (sm != MusicMode)\r
1644                 SD_SetMusicMode(sm);\r
1645 }\r
1646 \r
1647 ///////////////////////////////////////////////////////////////////////////\r
1648 //\r
1649 //      SD_Shutdown() - shuts down the Sound Mgr\r
1650 //              Removes sound ISR and turns off whatever sound hardware was active\r
1651 //\r
1652 ///////////////////////////////////////////////////////////////////////////\r
1653 void\r
1654 SD_Shutdown(global_game_variables_t *gvar)\r
1655 {\r
1656         if (!SD_Started)\r
1657                 return;\r
1658 \r
1659         SD_MusicOff();\r
1660         SD_StopSound(gvar);\r
1661         SDL_ShutDevice();\r
1662         SDL_CleanDevice();\r
1663 \r
1664 //SB    if (SoundBlasterPresent)\r
1665 //SB            SDL_ShutSB();\r
1666 \r
1667 //SS    if (SoundSourcePresent)\r
1668 //SS            SDL_ShutSS();\r
1669 \r
1670         asm     pushf\r
1671         asm     cli\r
1672 \r
1673         SDL_SetTimer0(0);\r
1674 \r
1675         setvect(8,t0OldService);\r
1676 \r
1677         asm     popf\r
1678 \r
1679         SD_Started = false;\r
1680 }\r
1681 \r
1682 ///////////////////////////////////////////////////////////////////////////\r
1683 //\r
1684 //      SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
1685 //              of a second from its timer 0 ISR\r
1686 //\r
1687 ///////////////////////////////////////////////////////////////////////////\r
1688 void\r
1689 SD_SetUserHook(void (* hook)(void))\r
1690 {\r
1691         SoundUserHook = hook;\r
1692 }\r
1693 \r
1694 ///////////////////////////////////////////////////////////////////////////\r
1695 //\r
1696 //      SD_PositionSound() - Sets up a stereo imaging location for the next\r
1697 //              sound to be played. Each channel ranges from 0 to 15.\r
1698 //\r
1699 ///////////////////////////////////////////////////////////////////////////\r
1700 void\r
1701 SD_PositionSound(int leftvol,int rightvol)\r
1702 {\r
1703         LeftPosition = leftvol;\r
1704         RightPosition = rightvol;\r
1705         nextsoundpos = true;\r
1706 }\r
1707 \r
1708 ///////////////////////////////////////////////////////////////////////////\r
1709 //\r
1710 //      SD_PlaySound() - plays the specified sound on the appropriate hardware\r
1711 //\r
1712 ///////////////////////////////////////////////////////////////////////////\r
1713 boolean\r
1714 SD_PlaySound(soundnames sound, global_game_variables_t *gvar)\r
1715 {\r
1716         boolean         ispos;\r
1717         SoundCommon     far *s;\r
1718         int     lp,rp;\r
1719 \r
1720         lp = LeftPosition;\r
1721         rp = RightPosition;\r
1722         LeftPosition = 0;\r
1723         RightPosition = 0;\r
1724 \r
1725         ispos = nextsoundpos;\r
1726         nextsoundpos = false;\r
1727 \r
1728         if (sound == -1)\r
1729                 return(false);\r
1730 \r
1731         s = MK_FP(SoundTable[sound],0);\r
1732         if ((SoundMode != sdm_Off) && !s)\r
1733                 Quit(gvar, "SD_PlaySound() - Uncached sound");\r
1734 \r
1735         if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))\r
1736         {\r
1737                 if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
1738                 {\r
1739                         if (s->priority < SoundPriority)\r
1740                                 return(false);\r
1741 \r
1742                         SDL_PCStopSound();\r
1743 \r
1744                         SD_PlayDigitized(DigiMap[sound],lp,rp, gvar);\r
1745                         SoundPositioned = ispos;\r
1746                         SoundNumber = sound;\r
1747                         SoundPriority = s->priority;\r
1748                 }\r
1749                 else\r
1750                 {\r
1751                 asm     pushf\r
1752                 asm     cli\r
1753                         if (DigiPriority && !DigiNumber)\r
1754                         {\r
1755                         asm     popf\r
1756                                 Quit(gvar, "SD_PlaySound: Priority without a sound");\r
1757                         }\r
1758                 asm     popf\r
1759 \r
1760                         if (s->priority < DigiPriority)\r
1761                                 return(false);\r
1762 \r
1763                         SD_PlayDigitized(DigiMap[sound],lp,rp, gvar);\r
1764                         SoundPositioned = ispos;\r
1765                         DigiNumber = sound;\r
1766                         DigiPriority = s->priority;\r
1767                 }\r
1768 \r
1769                 return(true);\r
1770         }\r
1771 \r
1772         if (SoundMode == sdm_Off)\r
1773                 return(false);\r
1774         if (!s->length)\r
1775                 Quit(gvar, "SD_PlaySound() - Zero length sound");\r
1776         if (s->priority < SoundPriority)\r
1777                 return(false);\r
1778 \r
1779         switch (SoundMode)\r
1780         {\r
1781         case sdm_PC:\r
1782                 SDL_PCPlaySound((void far *)s);\r
1783                 break;\r
1784         case sdm_AdLib:\r
1785                 SDL_ALPlaySound((void far *)s, gvar);\r
1786                 break;\r
1787         }\r
1788 \r
1789         SoundNumber = sound;\r
1790         SoundPriority = s->priority;\r
1791 \r
1792         return(false);\r
1793 }\r
1794 \r
1795 ///////////////////////////////////////////////////////////////////////////\r
1796 //\r
1797 //      SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
1798 //              no sound is playing\r
1799 //\r
1800 ///////////////////////////////////////////////////////////////////////////\r
1801 word\r
1802 SD_SoundPlaying(void)\r
1803 {\r
1804         boolean result = false;\r
1805 \r
1806         switch (SoundMode)\r
1807         {\r
1808         case sdm_PC:\r
1809                 result = pcSound? true : false;\r
1810                 break;\r
1811         case sdm_AdLib:\r
1812                 result = alSound? true : false;\r
1813                 break;\r
1814         }\r
1815 \r
1816         if (result)\r
1817                 return(SoundNumber);\r
1818         else\r
1819                 return(false);\r
1820 }\r
1821 \r
1822 ///////////////////////////////////////////////////////////////////////////\r
1823 //\r
1824 //      SD_StopSound() - if a sound is playing, stops it\r
1825 //\r
1826 ///////////////////////////////////////////////////////////////////////////\r
1827 void\r
1828 SD_StopSound(global_game_variables_t *gvar)\r
1829 {\r
1830         if (DigiPlaying)\r
1831                 SD_StopDigitized(gvar);\r
1832 \r
1833         switch (SoundMode)\r
1834         {\r
1835         case sdm_PC:\r
1836                 SDL_PCStopSound();\r
1837                 break;\r
1838         case sdm_AdLib:\r
1839                 SDL_ALStopSound();\r
1840                 break;\r
1841         }\r
1842 \r
1843         SoundPositioned = false;\r
1844 \r
1845         SDL_SoundFinished();\r
1846 }\r
1847 \r
1848 ///////////////////////////////////////////////////////////////////////////\r
1849 //\r
1850 //      SD_WaitSoundDone() - waits until the current sound is done playing\r
1851 //\r
1852 ///////////////////////////////////////////////////////////////////////////\r
1853 void\r
1854 SD_WaitSoundDone(void)\r
1855 {\r
1856         while (SD_SoundPlaying())\r
1857                 ;\r
1858 }\r
1859 \r
1860 ///////////////////////////////////////////////////////////////////////////\r
1861 //\r
1862 //      SD_MusicOn() - turns on the sequencer\r
1863 //\r
1864 ///////////////////////////////////////////////////////////////////////////\r
1865 void\r
1866 SD_MusicOn(void)\r
1867 {\r
1868         sqActive = true;\r
1869 }\r
1870 \r
1871 ///////////////////////////////////////////////////////////////////////////\r
1872 //\r
1873 //      SD_MusicOff() - turns off the sequencer and any playing notes\r
1874 //\r
1875 ///////////////////////////////////////////////////////////////////////////\r
1876 void\r
1877 SD_MusicOff(void)\r
1878 {\r
1879         word    i;\r
1880 \r
1881 \r
1882         switch (MusicMode)\r
1883         {\r
1884         case smm_AdLib:\r
1885                 alFXReg = 0;\r
1886                 alOut(alEffects,0);\r
1887                 for (i = 0;i < sqMaxTracks;i++)\r
1888                         alOut(alFreqH + i + 1,0);\r
1889                 break;\r
1890         }\r
1891         sqActive = false;\r
1892 }\r
1893 \r
1894 ///////////////////////////////////////////////////////////////////////////\r
1895 //\r
1896 //      SD_StartMusic() - starts playing the music pointed to\r
1897 //\r
1898 ///////////////////////////////////////////////////////////////////////////\r
1899 void\r
1900 SD_StartMusic(MusicGroup far *music)\r
1901 {\r
1902         SD_MusicOff();\r
1903 asm     pushf\r
1904 asm     cli\r
1905 \r
1906         if (MusicMode == smm_AdLib)\r
1907         {\r
1908                 sqHackPtr = sqHack = music->values;\r
1909                 sqHackSeqLen = sqHackLen = music->length;\r
1910                 sqHackTime = 0;\r
1911                 alTimeCount = 0;\r
1912                 SD_MusicOn();\r
1913         }\r
1914 \r
1915 asm     popf\r
1916 }\r
1917 \r
1918 ///////////////////////////////////////////////////////////////////////////\r
1919 //\r
1920 //      SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
1921 //              to see if the fadeout is complete\r
1922 //\r
1923 ///////////////////////////////////////////////////////////////////////////\r
1924 void\r
1925 SD_FadeOutMusic(void)\r
1926 {\r
1927         switch (MusicMode)\r
1928         {\r
1929         case smm_AdLib:\r
1930                 // DEBUG - quick hack to turn the music off\r
1931                 SD_MusicOff();\r
1932                 break;\r
1933         }\r
1934 }\r
1935 \r
1936 ///////////////////////////////////////////////////////////////////////////\r
1937 //\r
1938 //      SD_MusicPlaying() - returns true if music is currently playing, false if\r
1939 //              not\r
1940 //\r
1941 ///////////////////////////////////////////////////////////////////////////\r
1942 boolean\r
1943 SD_MusicPlaying(void)\r
1944 {\r
1945         boolean result;\r
1946 \r
1947         switch (MusicMode)\r
1948         {\r
1949         case smm_AdLib:\r
1950                 result = false;\r
1951                 // DEBUG - not written\r
1952                 break;\r
1953         default:\r
1954                 result = false;\r
1955         }\r
1956 \r
1957         return(result);\r
1958 }\r
1959 \r
1960 #if 0\r
1961 // SD ASS!\r
1962 void SDL_SetDS()\r
1963 {\r
1964         __asm {\r
1965                 mov     ax,ds\r
1966                 mov     [cs:MyDS],ds\r
1967                 ret\r
1968         }\r
1969 }\r
1970 \r
1971 void SDL_turnOnPCSpeaker(word timerval)\r
1972 {\r
1973         __asm {\r
1974                 mov     bx,timerval\r
1975                 mov     al,0b6h\r
1976                 out     43h,al\r
1977                 mov     al,bl\r
1978                 out     42h,al\r
1979                 mov     al,bh\r
1980                 out     42h,al\r
1981                 in      al,61h\r
1982                 or      al,3\r
1983                 out     61h,al\r
1984         }\r
1985 }\r
1986 \r
1987 void SDL_turnOffPCSpeaker()\r
1988 {\r
1989         __asm {\r
1990                 in      al,61h\r
1991                 and     al,0fch\r
1992                 out     61h,al\r
1993         }\r
1994 }\r
1995 \r
1996 void SDL_setPCSpeaker(byte val)\r
1997 {\r
1998         __asm {\r
1999                 mov     al,val\r
2000                 in      al,61h\r
2001                 and     al,0fch\r
2002                 or      al,ah\r
2003                 out     61h,al\r
2004         }\r
2005 }\r
2006 \r
2007 void SDL_DoFX()\r
2008 {\r
2009         if(pcSound)\r
2010         {\r
2011                 if(*pcSound!=pcLastSample)\r
2012                 {\r
2013                         pcLastSample=*pcSound;\r
2014 \r
2015                         if(pcLastSample)\r
2016                                 SDL_turnOnPCSpeaker(pcLastSample*60);\r
2017                         else\r
2018                                 SDL_turnOffPCSpeaker();\r
2019                 }\r
2020                 pcSound++;\r
2021                 pcLengthLeft--;\r
2022                 if(!pcLengthLeft)\r
2023                 {\r
2024                         pcSound=0;\r
2025                         SoundNumber=(soundnames)0;\r
2026                         SoundPriority=0;\r
2027                         SDL_turnOffPCSpeaker();\r
2028                 }\r
2029         }\r
2030 \r
2031         if(alSound && !alNoIRQ)\r
2032         {\r
2033                 if(*alSound)\r
2034                 {\r
2035                         alOutInIRQ(alFreqL,*alSound);\r
2036                         alOutInIRQ(alFreqH,alBlock);\r
2037                 }\r
2038                 else alOutInIRQ(alFreqH,0);\r
2039                 alSound++;\r
2040                 alLengthLeft--;\r
2041                 if(!alLengthLeft)\r
2042                 {\r
2043                         alSound=0;\r
2044                         SoundNumber=(soundnames)0;\r
2045                         SoundPriority=0;\r
2046                         alOutInIRQ(alFreqH,0);\r
2047                 }\r
2048         }\r
2049 \r
2050 }\r
2051 \r
2052 void SDL_DoFast()\r
2053 {\r
2054         count_fx++;\r
2055         if(count_fx>=5)\r
2056         {\r
2057                 count_fx=0;\r
2058 \r
2059                 SDL_DoFX();\r
2060 \r
2061                 count_time++;\r
2062                 if(count_time>=2)\r
2063                 {\r
2064                         TimeCount++;\r
2065                         count_time=0;\r
2066                 }\r
2067         }\r
2068 \r
2069         if(sqActive && !alNoIRQ)\r
2070         {\r
2071                 if(sqHackLen)\r
2072                 {\r
2073                         do\r
2074                         {\r
2075                                 if(sqHackTime>alTimeCount) break;\r
2076                                 sqHackTime=alTimeCount+*(sqHackPtr+1);\r
2077                                 alOutInIRQ(*(byte *)sqHackPtr,*(((byte *)sqHackPtr)+1));\r
2078                                 sqHackPtr+=2;\r
2079                                 sqHackLen-=4;\r
2080                         }\r
2081                         while(sqHackLen);\r
2082                 }\r
2083                 alTimeCount++;\r
2084                 if(!sqHackLen)\r
2085                 {\r
2086                         sqHackPtr=sqHack;\r
2087                         sqHackLen=sqHackSeqLen;\r
2088                         alTimeCount=0;\r
2089                         sqHackTime=0;\r
2090                 }\r
2091         }\r
2092 \r
2093         if(ssSample)\r
2094         {\r
2095                 if(!(inp(ssStatus)&0x40))\r
2096                 {\r
2097                         outp(ssData,*ssSample++);\r
2098                         outp(ssControl,ssOff);\r
2099                         __asm push ax\r
2100                         __asm pop ax\r
2101                         outp(ssControl,ssOn);\r
2102                         __asm push ax\r
2103                         __asm pop ax\r
2104                         ssLengthLeft--;\r
2105                         if(!ssLengthLeft)\r
2106                         {\r
2107                                 ssSample=0;\r
2108                                 SDL_DigitizedDoneInIRQ();\r
2109                         }\r
2110                 }\r
2111         }\r
2112 \r
2113         TimerCount+=TimerDivisor;\r
2114         if(*((word *)&TimerCount+1))\r
2115         {\r
2116                 *((word *)&TimerCount+1)=0;\r
2117                 t0OldService();\r
2118         }\r
2119         else\r
2120         {\r
2121                 outp(0x20,0x20);\r
2122         }\r
2123 }\r
2124 \r
2125 // Timer 0 ISR for 7000Hz interrupts\r
2126 void interrupt SDL_t0ExtremeAsmService(void)\r
2127 {\r
2128         if(pcindicate)\r
2129         {\r
2130                 if(pcSound)\r
2131                 {\r
2132                         SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
2133                         pcLengthLeft--;\r
2134                         if(!pcLengthLeft)\r
2135                         {\r
2136                                 pcSound=0;\r
2137                                 SDL_turnOffPCSpeaker();\r
2138                                 SDL_DigitizedDoneInIRQ();\r
2139                         }\r
2140                 }\r
2141         }\r
2142         extreme++;\r
2143         if(extreme>=10)\r
2144         {\r
2145                 extreme=0;\r
2146                 SDL_DoFast();\r
2147         }\r
2148         else\r
2149                 outp(0x20,0x20);\r
2150 }\r
2151 \r
2152 // Timer 0 ISR for 7000Hz interrupts\r
2153 void interrupt __SDL_t0ExtremeAsmService()\r
2154 {\r
2155         if(pcindicate)\r
2156         {\r
2157                 if(pcSound)\r
2158                 {\r
2159                         SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
2160                         pcLengthLeft--;\r
2161                         if(!pcLengthLeft)\r
2162                         {\r
2163                                 pcSound=0;\r
2164                                 SDL_turnOffPCSpeaker();\r
2165                                 SDL_DigitizedDoneInIRQ();\r
2166                         }\r
2167                 }\r
2168         }\r
2169         extreme++;\r
2170         if(extreme>=10)\r
2171         {\r
2172                 extreme=0;\r
2173                 SDL_DoFast();\r
2174         }\r
2175         else\r
2176                 outp(0x20,0x20);\r
2177 }\r
2178 \r
2179 // Timer 0 ISR for 700Hz interrupts\r
2180 void interrupt SDL_t0FastAsmService(void)\r
2181 {\r
2182         SDL_DoFast();\r
2183 }\r
2184 \r
2185 // Timer 0 ISR for 140Hz interrupts\r
2186 void interrupt SDL_t0SlowAsmService(void)\r
2187 {\r
2188         count_time++;\r
2189         if(count_time>=2)\r
2190         {\r
2191                 TimeCount++;\r
2192                 count_time=0;\r
2193         }\r
2194 \r
2195         SDL_DoFX();\r
2196 \r
2197         TimerCount+=TimerDivisor;\r
2198         if(*((word *)&TimerCount+1))\r
2199         {\r
2200                 *((word *)&TimerCount+1)=0;\r
2201                 t0OldService();\r
2202         }\r
2203         else\r
2204                 outp(0x20,0x20);\r
2205 }\r
2206 \r
2207 void SDL_IndicatePC(boolean ind)\r
2208 {\r
2209         pcindicate=ind;\r
2210 }\r
2211 \r
2212 void\r
2213 SDL_DigitizedDoneInIRQ(void)\r
2214 {\r
2215         if (DigiNextAddr)\r
2216         {\r
2217                 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen/*,true*/);\r
2218                 DigiNextAddr = nil;\r
2219                 DigiMissed = false;\r
2220         }\r
2221         else\r
2222         {\r
2223                 if (DigiLastSegment)\r
2224                 {\r
2225                         DigiPlaying = false;\r
2226                         DigiLastSegment = false;\r
2227                         if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
2228                         {\r
2229                                 SDL_SoundFinished();\r
2230                         }\r
2231                         else\r
2232                         {\r
2233                                 DigiNumber = (soundnames) 0;\r
2234                                 DigiPriority = 0;\r
2235                         }\r
2236                         SoundPositioned = false;\r
2237                 }\r
2238                 else\r
2239                         DigiMissed = true;\r
2240         }\r
2241 }\r
2242 \r
2243 // Inside an interrupt handler interrupts should already be disabled\r
2244 // so don't disable them again and cause V86 exceptions which cost\r
2245 // aprox. 300 processor tics!\r
2246 \r
2247 //static\r
2248 void alOutInIRQ(byte n,byte b)\r
2249 {\r
2250         __asm {\r
2251                 mov     dx,0x388\r
2252                 mov     al,[n]\r
2253                 out     dx,al\r
2254                 in      al,dx\r
2255                 in      al,dx\r
2256                 in      al,dx\r
2257                 in      al,dx\r
2258                 in      al,dx\r
2259                 in      al,dx\r
2260                 inc     dx\r
2261                 mov     al,[b]\r
2262                 out     dx,al\r
2263 \r
2264                 dec     dx\r
2265                 in      al,dx\r
2266                 in      al,dx\r
2267                 in      al,dx\r
2268                 in      al,dx\r
2269                 in      al,dx\r
2270                 in      al,dx\r
2271                 in      al,dx\r
2272                 in      al,dx\r
2273                 in      al,dx\r
2274                 in      al,dx\r
2275 \r
2276                 in      al,dx\r
2277                 in      al,dx\r
2278                 in      al,dx\r
2279                 in      al,dx\r
2280                 in      al,dx\r
2281                 in      al,dx\r
2282                 in      al,dx\r
2283                 in      al,dx\r
2284                 in      al,dx\r
2285                 in      al,dx\r
2286 \r
2287                 in      al,dx\r
2288                 in      al,dx\r
2289                 in      al,dx\r
2290                 in      al,dx\r
2291                 in      al,dx\r
2292                 in      al,dx\r
2293                 in      al,dx\r
2294                 in      al,dx\r
2295                 in      al,dx\r
2296                 in      al,dx\r
2297 \r
2298                 in      al,dx\r
2299                 in      al,dx\r
2300                 in      al,dx\r
2301                 in      al,dx\r
2302                 in      al,dx\r
2303         }\r
2304 }\r
2305 #endif\r