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