]> 4ch.mooo.com Git - 16.git/blob - src/lib/id_sd.c
943dede1093f35034ae12af43622597ae39e953a
[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 \r
1477 //??    SDL_SetDS();\r
1478 \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 \r
1524         SDL_InitDelay();                        // SDL_InitDelay() uses t0OldService\r
1525 \r
1526         setvect(8,SDL_t0Service);       // Set to my timer 0 ISR\r
1527         LocalTime = TimeCount = alTimeCount = 0;\r
1528 \r
1529         SD_SetSoundMode(sdm_Off, gvar);\r
1530         SD_SetMusicMode(smm_Off);\r
1531 \r
1532 //SS    if (!ssNoCheck)\r
1533 //SS            SoundSourcePresent = SDL_DetectSoundSource();\r
1534 \r
1535         if (!alNoCheck)\r
1536         {\r
1537                 AdLibPresent = SDL_DetectAdLib();\r
1538 //SB            if (AdLibPresent) && !sbNoCheck)\r
1539 //SB            {\r
1540 //SB                    int port = -1;\r
1541 //SB                    char *env = getenv("BLASTER");\r
1542 //SB                    if (env)\r
1543 //SB                    {\r
1544 //SB                            long temp;\r
1545 //SB                            while (*env)\r
1546 //SB                            {\r
1547 //SB                                    while (isspace(*env))\r
1548 //SB                                            env++;\r
1549 //SB\r
1550 //SB                                    switch (toupper(*env))\r
1551 //SB                                    {\r
1552 //SB                                    case 'A':\r
1553 //SB                                            temp = strtol(env + 1,&env,16);\r
1554 //SB                                            if\r
1555 //SB                                            (\r
1556 //SB                                                    (temp >= 0x210)\r
1557 //SB                                            &&      (temp <= 0x260)\r
1558 //SB                                            &&      (!(temp & 0x00f))\r
1559 //SB                                            )\r
1560 //SB                                                    port = (temp - 0x200) >> 4;\r
1561 //SB                                            else\r
1562 //SB                                                    Quit(gvar, "SD_Startup: Unsupported address value in BLASTER");\r
1563 //SB                                            break;\r
1564 //SB                                    case 'I':\r
1565 //SB                                            temp = strtol(env + 1,&env,10);\r
1566 //SB                                            if\r
1567 //SB                                            (\r
1568 //SB                                                    (temp >= 0)\r
1569 //SB                                            &&      (temp <= 10)\r
1570 //SB                                            &&      (sbIntVectors[temp] != -1)\r
1571 //SB                                            )\r
1572 //SB                                            {\r
1573 //SB                                                    sbInterrupt = temp;\r
1574 //SB                                                    sbIntVec = sbIntVectors[sbInterrupt];\r
1575 //SB                                            }\r
1576 //SB                                            else\r
1577 //SB                                                    Quit(gvar, "SD_Startup: Unsupported interrupt value in BLASTER");\r
1578 //SB                                            break;\r
1579 //SB                                    case 'D':\r
1580 //SB                                            temp = strtol(env + 1,&env,10);\r
1581 //SB                                            if ((temp == 0) || (temp == 1) || (temp == 3))\r
1582 //SB                                                    SDL_SBSetDMA(temp);\r
1583 //SB                                            else\r
1584 //SB                                                    Quit(gvar, "SD_Startup: Unsupported DMA value in BLASTER");\r
1585 //SB                                            break;\r
1586 //SB                                    default:\r
1587 //SB                                            while (isspace(*env))\r
1588 //SB                                                    env++;\r
1589 //SB                                            while (*env && !isspace(*env))\r
1590 //SB                                                    env++;\r
1591 //SB                                            break;\r
1592 //SB                                    }\r
1593 //SB                            }\r
1594 //SB                    }\r
1595 //SB                    SoundBlasterPresent = SDL_DetectSoundBlaster(port);\r
1596 //SB            }\r
1597         }\r
1598 \r
1599         for (i = 0;i < 255;i++)\r
1600                 pcSoundLookup[i] = i * 60;\r
1601 \r
1602 //SB    if (SoundBlasterPresent)\r
1603 //SB            SDL_StartSB();\r
1604 \r
1605         SDL_SetupDigi(gvar);\r
1606 \r
1607         SD_Started = true;\r
1608 }\r
1609 \r
1610 ///////////////////////////////////////////////////////////////////////////\r
1611 //\r
1612 //      SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
1613 //              the config file was present or not.\r
1614 //\r
1615 ///////////////////////////////////////////////////////////////////////////\r
1616 void\r
1617 SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar)\r
1618 {\r
1619         boolean gotsd,gotsm;\r
1620 \r
1621         gotsd = gotsm = gotit;\r
1622 \r
1623         if (gotsd)      // Make sure requested sound hardware is available\r
1624         {\r
1625                 switch (sd)\r
1626                 {\r
1627                 case sdm_AdLib:\r
1628                         gotsd = AdLibPresent;\r
1629                         break;\r
1630                 }\r
1631         }\r
1632         if (!gotsd)\r
1633         {\r
1634                 if (AdLibPresent)\r
1635                         sd = sdm_AdLib;\r
1636                 else\r
1637                         sd = sdm_PC;\r
1638         }\r
1639         if (sd != SoundMode)\r
1640                 SD_SetSoundMode(sd, gvar);\r
1641 \r
1642 \r
1643         if (gotsm)      // Make sure requested music hardware is available\r
1644         {\r
1645                 switch (sm)\r
1646                 {\r
1647                 case sdm_AdLib:\r
1648                         gotsm = AdLibPresent;\r
1649                         break;\r
1650                 }\r
1651         }\r
1652         if (!gotsm)\r
1653         {\r
1654                 if (AdLibPresent)\r
1655                         sm = smm_AdLib;\r
1656         }\r
1657         if (sm != MusicMode)\r
1658                 SD_SetMusicMode(sm);\r
1659 }\r
1660 \r
1661 ///////////////////////////////////////////////////////////////////////////\r
1662 //\r
1663 //      SD_Shutdown() - shuts down the Sound Mgr\r
1664 //              Removes sound ISR and turns off whatever sound hardware was active\r
1665 //\r
1666 ///////////////////////////////////////////////////////////////////////////\r
1667 void\r
1668 SD_Shutdown(global_game_variables_t *gvar)\r
1669 {\r
1670         if (!SD_Started)\r
1671                 return;\r
1672 \r
1673         SD_MusicOff();\r
1674         SD_StopSound(gvar);\r
1675         SDL_ShutDevice();\r
1676         SDL_CleanDevice();\r
1677 \r
1678 //SB    if (SoundBlasterPresent)\r
1679 //SB            SDL_ShutSB();\r
1680 \r
1681 //SS    if (SoundSourcePresent)\r
1682 //SS            SDL_ShutSS();\r
1683 \r
1684         asm     pushf\r
1685         asm     cli\r
1686 \r
1687         SDL_SetTimer0(0);\r
1688 \r
1689         setvect(8,t0OldService);\r
1690 \r
1691         asm     popf\r
1692 \r
1693         SD_Started = false;\r
1694 }\r
1695 \r
1696 ///////////////////////////////////////////////////////////////////////////\r
1697 //\r
1698 //      SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
1699 //              of a second from its timer 0 ISR\r
1700 //\r
1701 ///////////////////////////////////////////////////////////////////////////\r
1702 void\r
1703 SD_SetUserHook(void (* hook)(void))\r
1704 {\r
1705         SoundUserHook = hook;\r
1706 }\r
1707 \r
1708 ///////////////////////////////////////////////////////////////////////////\r
1709 //\r
1710 //      SD_PositionSound() - Sets up a stereo imaging location for the next\r
1711 //              sound to be played. Each channel ranges from 0 to 15.\r
1712 //\r
1713 ///////////////////////////////////////////////////////////////////////////\r
1714 void\r
1715 SD_PositionSound(int leftvol,int rightvol)\r
1716 {\r
1717         LeftPosition = leftvol;\r
1718         RightPosition = rightvol;\r
1719         nextsoundpos = true;\r
1720 }\r
1721 \r
1722 ///////////////////////////////////////////////////////////////////////////\r
1723 //\r
1724 //      SD_PlaySound() - plays the specified sound on the appropriate hardware\r
1725 //\r
1726 ///////////////////////////////////////////////////////////////////////////\r
1727 boolean\r
1728 SD_PlaySound(soundnames sound, global_game_variables_t *gvar)\r
1729 {\r
1730         boolean         ispos;\r
1731         SoundCommon     far *s;\r
1732         int     lp,rp;\r
1733 \r
1734         lp = LeftPosition;\r
1735         rp = RightPosition;\r
1736         LeftPosition = 0;\r
1737         RightPosition = 0;\r
1738 \r
1739         ispos = nextsoundpos;\r
1740         nextsoundpos = false;\r
1741 \r
1742         if (sound == -1)\r
1743                 return(false);\r
1744 \r
1745         s = MK_FP(SoundTable[sound],0);\r
1746         if ((SoundMode != sdm_Off) && !s)\r
1747                 Quit(gvar, "SD_PlaySound() - Uncached sound");\r
1748 \r
1749         if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))\r
1750         {\r
1751                 if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
1752                 {\r
1753                         if (s->priority < SoundPriority)\r
1754                                 return(false);\r
1755 \r
1756                         SDL_PCStopSound();\r
1757 \r
1758                         SD_PlayDigitized(DigiMap[sound],lp,rp, gvar);\r
1759                         SoundPositioned = ispos;\r
1760                         SoundNumber = sound;\r
1761                         SoundPriority = s->priority;\r
1762                 }\r
1763                 else\r
1764                 {\r
1765                 asm     pushf\r
1766                 asm     cli\r
1767                         if (DigiPriority && !DigiNumber)\r
1768                         {\r
1769                         asm     popf\r
1770                                 Quit(gvar, "SD_PlaySound: Priority without a sound");\r
1771                         }\r
1772                 asm     popf\r
1773 \r
1774                         if (s->priority < DigiPriority)\r
1775                                 return(false);\r
1776 \r
1777                         SD_PlayDigitized(DigiMap[sound],lp,rp, gvar);\r
1778                         SoundPositioned = ispos;\r
1779                         DigiNumber = sound;\r
1780                         DigiPriority = s->priority;\r
1781                 }\r
1782 \r
1783                 return(true);\r
1784         }\r
1785 \r
1786         if (SoundMode == sdm_Off)\r
1787                 return(false);\r
1788         if (!s->length)\r
1789                 Quit(gvar, "SD_PlaySound() - Zero length sound");\r
1790         if (s->priority < SoundPriority)\r
1791                 return(false);\r
1792 \r
1793         switch (SoundMode)\r
1794         {\r
1795         case sdm_PC:\r
1796                 SDL_PCPlaySound((void far *)s);\r
1797                 break;\r
1798         case sdm_AdLib:\r
1799                 SDL_ALPlaySound((void far *)s, gvar);\r
1800                 break;\r
1801         }\r
1802 \r
1803         SoundNumber = sound;\r
1804         SoundPriority = s->priority;\r
1805 \r
1806         return(false);\r
1807 }\r
1808 \r
1809 ///////////////////////////////////////////////////////////////////////////\r
1810 //\r
1811 //      SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
1812 //              no sound is playing\r
1813 //\r
1814 ///////////////////////////////////////////////////////////////////////////\r
1815 word\r
1816 SD_SoundPlaying(void)\r
1817 {\r
1818         boolean result = false;\r
1819 \r
1820         switch (SoundMode)\r
1821         {\r
1822         case sdm_PC:\r
1823                 result = pcSound? true : false;\r
1824                 break;\r
1825         case sdm_AdLib:\r
1826                 result = alSound? true : false;\r
1827                 break;\r
1828         }\r
1829 \r
1830         if (result)\r
1831                 return(SoundNumber);\r
1832         else\r
1833                 return(false);\r
1834 }\r
1835 \r
1836 ///////////////////////////////////////////////////////////////////////////\r
1837 //\r
1838 //      SD_StopSound() - if a sound is playing, stops it\r
1839 //\r
1840 ///////////////////////////////////////////////////////////////////////////\r
1841 void\r
1842 SD_StopSound(global_game_variables_t *gvar)\r
1843 {\r
1844         if (DigiPlaying)\r
1845                 SD_StopDigitized(gvar);\r
1846 \r
1847         switch (SoundMode)\r
1848         {\r
1849         case sdm_PC:\r
1850                 SDL_PCStopSound();\r
1851                 break;\r
1852         case sdm_AdLib:\r
1853                 SDL_ALStopSound();\r
1854                 break;\r
1855         }\r
1856 \r
1857         SoundPositioned = false;\r
1858 \r
1859         SDL_SoundFinished();\r
1860 }\r
1861 \r
1862 ///////////////////////////////////////////////////////////////////////////\r
1863 //\r
1864 //      SD_WaitSoundDone() - waits until the current sound is done playing\r
1865 //\r
1866 ///////////////////////////////////////////////////////////////////////////\r
1867 void\r
1868 SD_WaitSoundDone(void)\r
1869 {\r
1870         while (SD_SoundPlaying())\r
1871                 ;\r
1872 }\r
1873 \r
1874 ///////////////////////////////////////////////////////////////////////////\r
1875 //\r
1876 //      SD_MusicOn() - turns on the sequencer\r
1877 //\r
1878 ///////////////////////////////////////////////////////////////////////////\r
1879 void\r
1880 SD_MusicOn(void)\r
1881 {\r
1882         sqActive = true;\r
1883 }\r
1884 \r
1885 ///////////////////////////////////////////////////////////////////////////\r
1886 //\r
1887 //      SD_MusicOff() - turns off the sequencer and any playing notes\r
1888 //\r
1889 ///////////////////////////////////////////////////////////////////////////\r
1890 void\r
1891 SD_MusicOff(void)\r
1892 {\r
1893         word    i;\r
1894 \r
1895 \r
1896         switch (MusicMode)\r
1897         {\r
1898         case smm_AdLib:\r
1899                 alFXReg = 0;\r
1900                 alOut(alEffects,0);\r
1901                 for (i = 0;i < sqMaxTracks;i++)\r
1902                         alOut(alFreqH + i + 1,0);\r
1903                 break;\r
1904         }\r
1905         sqActive = false;\r
1906 }\r
1907 \r
1908 ///////////////////////////////////////////////////////////////////////////\r
1909 //\r
1910 //      SD_StartMusic() - starts playing the music pointed to\r
1911 //\r
1912 ///////////////////////////////////////////////////////////////////////////\r
1913 void\r
1914 SD_StartMusic(MusicGroup far *music)\r
1915 {\r
1916         SD_MusicOff();\r
1917 asm     pushf\r
1918 asm     cli\r
1919 \r
1920         if (MusicMode == smm_AdLib)\r
1921         {\r
1922                 sqHackPtr = sqHack = music->values;\r
1923                 sqHackSeqLen = sqHackLen = music->length;\r
1924                 sqHackTime = 0;\r
1925                 alTimeCount = 0;\r
1926                 SD_MusicOn();\r
1927         }\r
1928 \r
1929 asm     popf\r
1930 }\r
1931 \r
1932 ///////////////////////////////////////////////////////////////////////////\r
1933 //\r
1934 //      SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
1935 //              to see if the fadeout is complete\r
1936 //\r
1937 ///////////////////////////////////////////////////////////////////////////\r
1938 void\r
1939 SD_FadeOutMusic(void)\r
1940 {\r
1941         switch (MusicMode)\r
1942         {\r
1943         case smm_AdLib:\r
1944                 // DEBUG - quick hack to turn the music off\r
1945                 SD_MusicOff();\r
1946                 break;\r
1947         }\r
1948 }\r
1949 \r
1950 ///////////////////////////////////////////////////////////////////////////\r
1951 //\r
1952 //      SD_MusicPlaying() - returns true if music is currently playing, false if\r
1953 //              not\r
1954 //\r
1955 ///////////////////////////////////////////////////////////////////////////\r
1956 boolean\r
1957 SD_MusicPlaying(void)\r
1958 {\r
1959         boolean result;\r
1960 \r
1961         switch (MusicMode)\r
1962         {\r
1963         case smm_AdLib:\r
1964                 result = false;\r
1965                 // DEBUG - not written\r
1966                 break;\r
1967         default:\r
1968                 result = false;\r
1969         }\r
1970 \r
1971         return(result);\r
1972 }\r
1973 \r
1974 #if 0\r
1975 // SD ASS!\r
1976 void SDL_SetDS()\r
1977 {\r
1978         __asm {\r
1979                 mov     ax,ds\r
1980                 mov     [cs:MyDS],ds\r
1981                 ret\r
1982         }\r
1983 }\r
1984 \r
1985 void SDL_turnOnPCSpeaker(word timerval)\r
1986 {\r
1987         __asm {\r
1988                 mov     bx,timerval\r
1989                 mov     al,0b6h\r
1990                 out     43h,al\r
1991                 mov     al,bl\r
1992                 out     42h,al\r
1993                 mov     al,bh\r
1994                 out     42h,al\r
1995                 in      al,61h\r
1996                 or      al,3\r
1997                 out     61h,al\r
1998         }\r
1999 }\r
2000 \r
2001 void SDL_turnOffPCSpeaker()\r
2002 {\r
2003         __asm {\r
2004                 in      al,61h\r
2005                 and     al,0fch\r
2006                 out     61h,al\r
2007         }\r
2008 }\r
2009 \r
2010 void SDL_setPCSpeaker(byte val)\r
2011 {\r
2012         __asm {\r
2013                 mov     al,val\r
2014                 in      al,61h\r
2015                 and     al,0fch\r
2016                 or      al,ah\r
2017                 out     61h,al\r
2018         }\r
2019 }\r
2020 \r
2021 void SDL_DoFX()\r
2022 {\r
2023         if(pcSound)\r
2024         {\r
2025                 if(*pcSound!=pcLastSample)\r
2026                 {\r
2027                         pcLastSample=*pcSound;\r
2028 \r
2029                         if(pcLastSample)\r
2030                                 SDL_turnOnPCSpeaker(pcLastSample*60);\r
2031                         else\r
2032                                 SDL_turnOffPCSpeaker();\r
2033                 }\r
2034                 pcSound++;\r
2035                 pcLengthLeft--;\r
2036                 if(!pcLengthLeft)\r
2037                 {\r
2038                         pcSound=0;\r
2039                         SoundNumber=(soundnames)0;\r
2040                         SoundPriority=0;\r
2041                         SDL_turnOffPCSpeaker();\r
2042                 }\r
2043         }\r
2044 \r
2045         if(alSound && !alNoIRQ)\r
2046         {\r
2047                 if(*alSound)\r
2048                 {\r
2049                         alOutInIRQ(alFreqL,*alSound);\r
2050                         alOutInIRQ(alFreqH,alBlock);\r
2051                 }\r
2052                 else alOutInIRQ(alFreqH,0);\r
2053                 alSound++;\r
2054                 alLengthLeft--;\r
2055                 if(!alLengthLeft)\r
2056                 {\r
2057                         alSound=0;\r
2058                         SoundNumber=(soundnames)0;\r
2059                         SoundPriority=0;\r
2060                         alOutInIRQ(alFreqH,0);\r
2061                 }\r
2062         }\r
2063 \r
2064 }\r
2065 \r
2066 void SDL_DoFast()\r
2067 {\r
2068         count_fx++;\r
2069         if(count_fx>=5)\r
2070         {\r
2071                 count_fx=0;\r
2072 \r
2073                 SDL_DoFX();\r
2074 \r
2075                 count_time++;\r
2076                 if(count_time>=2)\r
2077                 {\r
2078                         TimeCount++;\r
2079                         count_time=0;\r
2080                 }\r
2081         }\r
2082 \r
2083         if(sqActive && !alNoIRQ)\r
2084         {\r
2085                 if(sqHackLen)\r
2086                 {\r
2087                         do\r
2088                         {\r
2089                                 if(sqHackTime>alTimeCount) break;\r
2090                                 sqHackTime=alTimeCount+*(sqHackPtr+1);\r
2091                                 alOutInIRQ(*(byte *)sqHackPtr,*(((byte *)sqHackPtr)+1));\r
2092                                 sqHackPtr+=2;\r
2093                                 sqHackLen-=4;\r
2094                         }\r
2095                         while(sqHackLen);\r
2096                 }\r
2097                 alTimeCount++;\r
2098                 if(!sqHackLen)\r
2099                 {\r
2100                         sqHackPtr=sqHack;\r
2101                         sqHackLen=sqHackSeqLen;\r
2102                         alTimeCount=0;\r
2103                         sqHackTime=0;\r
2104                 }\r
2105         }\r
2106 \r
2107         if(ssSample)\r
2108         {\r
2109                 if(!(inp(ssStatus)&0x40))\r
2110                 {\r
2111                         outp(ssData,*ssSample++);\r
2112                         outp(ssControl,ssOff);\r
2113                         __asm push ax\r
2114                         __asm pop ax\r
2115                         outp(ssControl,ssOn);\r
2116                         __asm push ax\r
2117                         __asm pop ax\r
2118                         ssLengthLeft--;\r
2119                         if(!ssLengthLeft)\r
2120                         {\r
2121                                 ssSample=0;\r
2122                                 SDL_DigitizedDoneInIRQ();\r
2123                         }\r
2124                 }\r
2125         }\r
2126 \r
2127         TimerCount+=TimerDivisor;\r
2128         if(*((word *)&TimerCount+1))\r
2129         {\r
2130                 *((word *)&TimerCount+1)=0;\r
2131                 t0OldService();\r
2132         }\r
2133         else\r
2134         {\r
2135                 outp(0x20,0x20);\r
2136         }\r
2137 }\r
2138 \r
2139 // Timer 0 ISR for 7000Hz interrupts\r
2140 void interrupt SDL_t0ExtremeAsmService(void)\r
2141 {\r
2142         if(pcindicate)\r
2143         {\r
2144                 if(pcSound)\r
2145                 {\r
2146                         SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
2147                         pcLengthLeft--;\r
2148                         if(!pcLengthLeft)\r
2149                         {\r
2150                                 pcSound=0;\r
2151                                 SDL_turnOffPCSpeaker();\r
2152                                 SDL_DigitizedDoneInIRQ();\r
2153                         }\r
2154                 }\r
2155         }\r
2156         extreme++;\r
2157         if(extreme>=10)\r
2158         {\r
2159                 extreme=0;\r
2160                 SDL_DoFast();\r
2161         }\r
2162         else\r
2163                 outp(0x20,0x20);\r
2164 }\r
2165 \r
2166 // Timer 0 ISR for 7000Hz interrupts\r
2167 void interrupt __SDL_t0ExtremeAsmService()\r
2168 {\r
2169         if(pcindicate)\r
2170         {\r
2171                 if(pcSound)\r
2172                 {\r
2173                         SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
2174                         pcLengthLeft--;\r
2175                         if(!pcLengthLeft)\r
2176                         {\r
2177                                 pcSound=0;\r
2178                                 SDL_turnOffPCSpeaker();\r
2179                                 SDL_DigitizedDoneInIRQ();\r
2180                         }\r
2181                 }\r
2182         }\r
2183         extreme++;\r
2184         if(extreme>=10)\r
2185         {\r
2186                 extreme=0;\r
2187                 SDL_DoFast();\r
2188         }\r
2189         else\r
2190                 outp(0x20,0x20);\r
2191 }\r
2192 \r
2193 // Timer 0 ISR for 700Hz interrupts\r
2194 void interrupt SDL_t0FastAsmService(void)\r
2195 {\r
2196         SDL_DoFast();\r
2197 }\r
2198 \r
2199 // Timer 0 ISR for 140Hz interrupts\r
2200 void interrupt SDL_t0SlowAsmService(void)\r
2201 {\r
2202         count_time++;\r
2203         if(count_time>=2)\r
2204         {\r
2205                 TimeCount++;\r
2206                 count_time=0;\r
2207         }\r
2208 \r
2209         SDL_DoFX();\r
2210 \r
2211         TimerCount+=TimerDivisor;\r
2212         if(*((word *)&TimerCount+1))\r
2213         {\r
2214                 *((word *)&TimerCount+1)=0;\r
2215                 t0OldService();\r
2216         }\r
2217         else\r
2218                 outp(0x20,0x20);\r
2219 }\r
2220 #endif\r
2221 void SDL_IndicatePC(boolean ind)\r
2222 {\r
2223         pcindicate=ind;\r
2224 }\r
2225 #if 0\r
2226 void\r
2227 SDL_DigitizedDoneInIRQ(void)\r
2228 {\r
2229         if (DigiNextAddr)\r
2230         {\r
2231                 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen/*,true*/);\r
2232                 DigiNextAddr = nil;\r
2233                 DigiMissed = false;\r
2234         }\r
2235         else\r
2236         {\r
2237                 if (DigiLastSegment)\r
2238                 {\r
2239                         DigiPlaying = false;\r
2240                         DigiLastSegment = false;\r
2241                         if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
2242                         {\r
2243                                 SDL_SoundFinished();\r
2244                         }\r
2245                         else\r
2246                         {\r
2247                                 DigiNumber = (soundnames) 0;\r
2248                                 DigiPriority = 0;\r
2249                         }\r
2250                         SoundPositioned = false;\r
2251                 }\r
2252                 else\r
2253                         DigiMissed = true;\r
2254         }\r
2255 }\r
2256 \r
2257 // Inside an interrupt handler interrupts should already be disabled\r
2258 // so don't disable them again and cause V86 exceptions which cost\r
2259 // aprox. 300 processor tics!\r
2260 \r
2261 //static\r
2262 void alOutInIRQ(byte n,byte b)\r
2263 {\r
2264         __asm {\r
2265                 mov     dx,0x388\r
2266                 mov     al,[n]\r
2267                 out     dx,al\r
2268                 in      al,dx\r
2269                 in      al,dx\r
2270                 in      al,dx\r
2271                 in      al,dx\r
2272                 in      al,dx\r
2273                 in      al,dx\r
2274                 inc     dx\r
2275                 mov     al,[b]\r
2276                 out     dx,al\r
2277 \r
2278                 dec     dx\r
2279                 in      al,dx\r
2280                 in      al,dx\r
2281                 in      al,dx\r
2282                 in      al,dx\r
2283                 in      al,dx\r
2284                 in      al,dx\r
2285                 in      al,dx\r
2286                 in      al,dx\r
2287                 in      al,dx\r
2288                 in      al,dx\r
2289 \r
2290                 in      al,dx\r
2291                 in      al,dx\r
2292                 in      al,dx\r
2293                 in      al,dx\r
2294                 in      al,dx\r
2295                 in      al,dx\r
2296                 in      al,dx\r
2297                 in      al,dx\r
2298                 in      al,dx\r
2299                 in      al,dx\r
2300 \r
2301                 in      al,dx\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 \r
2312                 in      al,dx\r
2313                 in      al,dx\r
2314                 in      al,dx\r
2315                 in      al,dx\r
2316                 in      al,dx\r
2317         }\r
2318 }\r
2319 #endif\r