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