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