+/* Catacomb 3-D Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
//\r
// ID Engine\r
-// ID_SD.c - Sound Manager for Wolfenstein 3D\r
-// v1.2\r
+// ID_SD.c - Sound Manager\r
+// v1.1d1\r
// By Jason Blochowiak\r
//\r
\r
// (Use SM_SetSoundMode() to set)\r
// MusicMode - What device is used for music\r
// (Use SM_SetMusicMode() to set)\r
-// DigiMode - What device is used for digitized sound effects\r
-// (Use SM_SetDigiDevice() to set)\r
-//\r
// For Cache Mgr:\r
// NeedsDigitized - load digitized sounds?\r
// NeedsMusic - load music?\r
#pragma hdrstop\r
#pragma warn -pia\r
\r
-#ifdef nil\r
-#undef nil\r
-#endif\r
-#define nil 0\r
-\r
#define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}\r
\r
-// Macros for SoundBlaster stuff\r
-#define sbOut(n,b) outportb((n) + sbLocation,b)\r
-#define sbIn(n) inportb((n) + sbLocation)\r
-#define sbWriteDelay() while (sbIn(sbWriteStat) & 0x80);\r
-#define sbReadDelay() while (sbIn(sbDataAvail) & 0x80);\r
-\r
// Macros for AdLib stuff\r
#define selreg(n) outportb(alFMAddr,n)\r
#define writereg(n) outportb(alFMData,n)\r
#define readstat() inportb(alFMStatus)\r
\r
-// Imports from ID_SD_A.ASM\r
-extern void SDL_SetDS(void),\r
- SDL_IndicatePC(boolean on);\r
-extern void interrupt SDL_t0ExtremeAsmService(void),\r
- SDL_t0FastAsmService(void),\r
- SDL_t0SlowAsmService(void);\r
-\r
// Global variables\r
- boolean SoundSourcePresent,\r
- AdLibPresent,\r
- SoundBlasterPresent,SBProPresent,\r
- NeedsDigitized,NeedsMusic,\r
- SoundPositioned;\r
+ boolean SoundSourcePresent,SoundBlasterPresent,AdLibPresent,\r
+ NeedsDigitized,NeedsMusic;\r
SDMode SoundMode;\r
SMMode MusicMode;\r
- SDSMode DigiMode;\r
- longword TimeCount;\r
+ dword TimeCount;\r
word HackCount;\r
word *SoundTable; // Really * _seg *SoundTable, but that don't work\r
boolean ssIsTandy;\r
word ssPort = 2;\r
- int DigiMap[LASTSOUND];\r
\r
// Internal variables\r
static boolean SD_Started;\r
- boolean nextsoundpos;\r
- longword TimerDivisor,TimerCount;\r
+ boolean TimerDone;\r
+ word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;\r
+ dword TimerDivisor,TimerCount;\r
static char *ParmStrings[] =\r
{\r
"noal",\r
- "nosb",\r
- "nopro",\r
- "noss",\r
- "sst",\r
- "ss1",\r
- "ss2",\r
- "ss3",\r
nil\r
};\r
static void (*SoundUserHook)(void);\r
- soundnames SoundNumber,DigiNumber;\r
- word SoundPriority,DigiPriority;\r
- int LeftPosition,RightPosition;\r
+ word SoundNumber,SoundPriority;\r
void interrupt (*t0OldService)(void);\r
+// word t0CountTable[] = {8,8,8,8,40,40};\r
long LocalTime;\r
- word TimerRate;\r
-\r
- word NumDigi,DigiLeft,DigiPage;\r
- word _seg *DigiList;\r
- word DigiLastStart,DigiLastEnd;\r
- boolean DigiPlaying;\r
-static boolean DigiMissed,DigiLastSegment;\r
-static memptr DigiNextAddr;\r
-static word DigiNextLen;\r
-\r
-// SoundBlaster variables\r
-static boolean sbNoCheck,sbNoProCheck;\r
-static volatile boolean sbSamplePlaying;\r
-static byte sbOldIntMask = -1;\r
-static volatile byte huge *sbNextSegPtr;\r
-static byte sbDMA = 1,\r
- sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3,\r
- sba1Vals[] = {0x87,0x83,0,0x82},\r
- sba2Vals[] = {0,2,0,6},\r
- sba3Vals[] = {1,3,0,7};\r
-static int sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf,\r
- sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1};\r
-static volatile longword sbNextSegLen;\r
-static volatile SampledSound huge *sbSamples;\r
-static void interrupt (*sbOldIntHand)(void);\r
-static byte sbpOldFMMix,sbpOldVOCMix;\r
-\r
-// SoundSource variables\r
- boolean ssNoCheck;\r
- boolean ssActive;\r
- word ssControl,ssStatus,ssData;\r
- byte ssOn,ssOff;\r
- volatile byte far *ssSample;\r
- volatile longword ssLengthLeft;\r
\r
// PC Sound variables\r
- volatile byte pcLastSample,far *pcSound;\r
- longword pcLengthLeft;\r
+ volatile byte pcLastSample,far *pcSound;\r
+ dword pcLengthLeft;\r
word pcSoundLookup[255];\r
\r
// AdLib variables\r
boolean alNoCheck;\r
byte far *alSound;\r
word alBlock;\r
- longword alLengthLeft;\r
- longword alTimeCount;\r
+ dword alLengthLeft;\r
+ dword alTimeCount;\r
Instrument alZeroInst;\r
\r
// This table maps channel numbers to carrier and modulator op cells\r
long sqHackTime;\r
\r
// Internal routines\r
- void SDL_DigitizedDone(void);\r
\r
///////////////////////////////////////////////////////////////////////////\r
//\r
SDL_SetTimer0(word speed)\r
{\r
#ifndef TPROF // If using Borland's profiling, don't screw with the timer\r
-asm pushf\r
-asm cli\r
-\r
outportb(0x43,0x36); // Change timer 0\r
outportb(0x40,speed);\r
outportb(0x40,speed >> 8);\r
- // Kludge to handle special case for digitized PC sounds\r
- if (TimerDivisor == (1192030 / (TickBase * 100)))\r
- TimerDivisor = (1192030 / (TickBase * 10));\r
- else\r
- TimerDivisor = speed;\r
-\r
-asm popf\r
+ TimerDivisor = speed;\r
#else\r
TimerDivisor = 0x10000;\r
#endif\r
static void\r
SDL_SetIntsPerSec(word ints)\r
{\r
- TimerRate = ints;\r
SDL_SetTimer0(1192030 / ints);\r
}\r
\r
-static void\r
-SDL_SetTimerSpeed(void)\r
-{\r
- word rate;\r
- void interrupt (*isr)(void);\r
-\r
- if ((DigiMode == sds_PC) && DigiPlaying)\r
- {\r
- rate = TickBase * 100;\r
- isr = SDL_t0ExtremeAsmService;\r
- }\r
- else if\r
- (\r
- (MusicMode == smm_AdLib)\r
- || ((DigiMode == sds_SoundSource) && DigiPlaying)\r
- )\r
- {\r
- rate = TickBase * 10;\r
- isr = SDL_t0FastAsmService;\r
- }\r
- else\r
- {\r
- rate = TickBase * 2;\r
- isr = SDL_t0SlowAsmService;\r
- }\r
-\r
- if (rate != TimerRate)\r
- {\r
- setvect(8,isr);\r
- SDL_SetIntsPerSec(rate);\r
- TimerRate = rate;\r
- }\r
-}\r
-\r
-//\r
-// SoundBlaster code\r
-//\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SBStopSample() - Stops any active sampled sound and causes DMA\r
-// requests from the SoundBlaster to cease\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_SBStopSample(void)\r
-{\r
- byte is;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- if (sbSamplePlaying)\r
- {\r
- sbSamplePlaying = false;\r
-\r
- sbWriteDelay();\r
- sbOut(sbWriteCmd,0xd0); // Turn off DSP DMA\r
-\r
- is = inportb(0x21); // Restore interrupt mask bit\r
- if (sbOldIntMask & (1 << sbInterrupt))\r
- is |= (1 << sbInterrupt);\r
- else\r
- is &= ~(1 << sbInterrupt);\r
- outportb(0x21,is);\r
- }\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SBPlaySeg() - Plays a chunk of sampled sound on the SoundBlaster\r
-// Insures that the chunk doesn't cross a bank boundary, programs the DMA\r
-// controller, and tells the SB to start doing DMA requests for DAC\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static longword\r
-SDL_SBPlaySeg(volatile byte huge *data,longword length)\r
-{\r
- unsigned datapage;\r
- longword dataofs,uselen;\r
-\r
- uselen = length;\r
- datapage = FP_SEG(data) >> 12;\r
- dataofs = ((FP_SEG(data) & 0xfff) << 4) + FP_OFF(data);\r
- if (dataofs >= 0x10000)\r
- {\r
- datapage++;\r
- dataofs -= 0x10000;\r
- }\r
-\r
- if (dataofs + uselen > 0x10000)\r
- uselen = 0x10000 - dataofs;\r
-\r
- uselen--;\r
-\r
- // Program the DMA controller\r
-asm pushf\r
-asm cli\r
- outportb(0x0a,sbDMA | 4); // Mask off DMA on channel sbDMA\r
- outportb(0x0c,0); // Clear byte ptr flip-flop to lower byte\r
- outportb(0x0b,0x49); // Set transfer mode for D/A conv\r
- outportb(sbDMAa2,(byte)dataofs); // Give LSB of address\r
- outportb(sbDMAa2,(byte)(dataofs >> 8)); // Give MSB of address\r
- outportb(sbDMAa1,(byte)datapage); // Give page of address\r
- outportb(sbDMAa3,(byte)uselen); // Give LSB of length\r
- outportb(sbDMAa3,(byte)(uselen >> 8)); // Give MSB of length\r
- outportb(0x0a,sbDMA); // Re-enable DMA on channel sbDMA\r
-\r
- // Start playing the thing\r
- sbWriteDelay();\r
- sbOut(sbWriteCmd,0x14);\r
- sbWriteDelay();\r
- sbOut(sbWriteData,(byte)uselen);\r
- sbWriteDelay();\r
- sbOut(sbWriteData,(byte)(uselen >> 8));\r
-asm popf\r
-\r
- return(uselen + 1);\r
-}\r
-\r
///////////////////////////////////////////////////////////////////////////\r
//\r
-// SDL_SBService() - Services the SoundBlaster DMA interrupt\r
+// SDL_TimingService() - Used by SDL_InitDelay() to determine a timing\r
+// value for the current system that we're running on\r
//\r
///////////////////////////////////////////////////////////////////////////\r
static void interrupt\r
-SDL_SBService(void)\r
-{\r
- longword used;\r
-\r
- sbIn(sbDataAvail); // Ack interrupt to SB\r
-\r
- if (sbNextSegPtr)\r
- {\r
- used = SDL_SBPlaySeg(sbNextSegPtr,sbNextSegLen);\r
- if (sbNextSegLen <= used)\r
- sbNextSegPtr = nil;\r
- else\r
- {\r
- sbNextSegPtr += used;\r
- sbNextSegLen -= used;\r
- }\r
- }\r
- else\r
- {\r
- SDL_SBStopSample();\r
- SDL_DigitizedDone();\r
- }\r
-\r
- outportb(0x20,0x20); // Ack interrupt\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SBPlaySample() - Plays a sampled sound on the SoundBlaster. Sets up\r
-// DMA to play the sound\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_SBPlaySample(byte huge *data,longword len)\r
+SDL_TimingService(void)\r
{\r
- longword used;\r
-\r
- SDL_SBStopSample();\r
+ TimerVal = _CX;\r
+ TimerDone++;\r
\r
-asm pushf\r
-asm cli\r
-\r
- used = SDL_SBPlaySeg(data,len);\r
- if (len <= used)\r
- sbNextSegPtr = nil;\r
- else\r
- {\r
- sbNextSegPtr = data + used;\r
- sbNextSegLen = len - used;\r
- }\r
-\r
- // Save old interrupt status and unmask ours\r
- sbOldIntMask = inportb(0x21);\r
- outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt));\r
-\r
- sbWriteDelay();\r
- sbOut(sbWriteCmd,0xd4); // Make sure DSP DMA is enabled\r
-\r
- sbSamplePlaying = true;\r
-\r
-asm popf\r
+ outportb(0x20,0x20); // Ack interrupt\r
}\r
\r
///////////////////////////////////////////////////////////////////////////\r
//\r
-// SDL_PositionSBP() - Sets the attenuation levels for the left and right\r
-// channels by using the mixer chip on the SB Pro. This hits a hole in\r
-// the address map for normal SBs.\r
+// SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()\r
//\r
///////////////////////////////////////////////////////////////////////////\r
static void\r
-SDL_PositionSBP(int leftpos,int rightpos)\r
+SDL_InitDelay(void)\r
{\r
- byte v;\r
-\r
- if (!SBProPresent)\r
- return;\r
-\r
- leftpos = 15 - leftpos;\r
- rightpos = 15 - rightpos;\r
- v = ((leftpos & 0x0f) << 4) | (rightpos & 0x0f);\r
-\r
-asm pushf\r
-asm cli\r
-\r
- sbOut(sbpMixerAddr,sbpmVoiceVol);\r
- sbOut(sbpMixerData,v);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CheckSB() - Checks to see if a SoundBlaster resides at a\r
-// particular I/O location\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_CheckSB(int port)\r
-{\r
- int i;\r
-\r
- sbLocation = port << 4; // Initialize stuff for later use\r
-\r
- sbOut(sbReset,true); // Reset the SoundBlaster DSP\r
-asm mov dx,0x388 // Wait >4usec\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
- sbOut(sbReset,false); // Turn off sb DSP reset\r
-asm mov dx,0x388 // Wait >100usec\r
-asm mov cx,100\r
-usecloop:\r
-asm in al,dx\r
-asm loop usecloop\r
+ int i;\r
+ word timer;\r
\r
- for (i = 0;i < 100;i++)\r
- {\r
- if (sbIn(sbDataAvail) & 0x80) // If data is available...\r
- {\r
- if (sbIn(sbReadData) == 0xaa) // If it matches correct value\r
- return(true);\r
- else\r
- {\r
- sbLocation = -1; // Otherwise not a SoundBlaster\r
- return(false);\r
- }\r
- }\r
- }\r
- sbLocation = -1; // Retry count exceeded - fail\r
- return(false);\r
-}\r
+ setvect(8,SDL_TimingService); // Set to my timer 0 ISR\r
\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// Checks to see if a SoundBlaster is in the system. If the port passed is\r
-// -1, then it scans through all possible I/O locations. If the port\r
-// passed is 0, then it uses the default (2). If the port is >0, then\r
-// it just passes it directly to SDL_CheckSB()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_DetectSoundBlaster(int port)\r
-{\r
- int i;\r
+ SDL_SetIntsPerSec(1000); // Time 1ms\r
\r
- if (port == 0) // If user specifies default, use 2\r
- port = 2;\r
- if (port == -1)\r
+ for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times\r
{\r
- if (SDL_CheckSB(2)) // Check default before scanning\r
- return(true);\r
-\r
- if (SDL_CheckSB(4)) // Check other SB Pro location before scan\r
- return(true);\r
-\r
- for (i = 1;i <= 6;i++) // Scan through possible SB locations\r
- {\r
- if ((i == 2) || (i == 4))\r
- continue;\r
-\r
- if (SDL_CheckSB(i)) // If found at this address,\r
- return(true); // return success\r
- }\r
- return(false); // All addresses failed, return failure\r
+ asm xor dx,dx // Zero DX\r
+ asm mov cx,0xffff // Put starting value in CX\r
+ asm mov [TimerDone],cx // TimerDone = false - 1\r
+startloop:\r
+ asm or [TimerDone],0\r
+ asm jnz startloop // Make sure we're at the start\r
+loop:\r
+ asm test [TimerDone],1 // See if TimerDone flag got hit\r
+ asm jnz done // Yep - drop out of the loop\r
+ asm loop loop\r
+done:\r
+\r
+ if (0xffff - TimerVal > timer)\r
+ timer = 0xffff - TimerVal;\r
}\r
- else\r
- return(SDL_CheckSB(port)); // User specified address or default\r
-}\r
+ timer += timer / 2; // Use some slop\r
+ TimerDelay10 = timer / (1000 / 10);\r
+ TimerDelay25 = timer / (1000 / 25);\r
+ TimerDelay100 = timer / (1000 / 100);\r
\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SBSetDMA() - Sets the DMA channel to be used by the SoundBlaster\r
-// code. Sets up sbDMA, and sbDMAa1-sbDMAa3 (used by SDL_SBPlaySeg()).\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SDL_SBSetDMA(byte channel)\r
-{\r
- if (channel > 3)\r
- Quit("SDL_SBSetDMA() - invalid SoundBlaster DMA channel");\r
+ SDL_SetTimer0(0); // Reset timer 0\r
\r
- sbDMA = channel;\r
- sbDMAa1 = sba1Vals[channel];\r
- sbDMAa2 = sba2Vals[channel];\r
- sbDMAa3 = sba3Vals[channel];\r
+ setvect(8,t0OldService); // Set back to old ISR\r
}\r
\r
///////////////////////////////////////////////////////////////////////////\r
//\r
-// SDL_StartSB() - Turns on the SoundBlaster\r
+// SDL_Delay() - Delays the specified amount of time\r
//\r
///////////////////////////////////////////////////////////////////////////\r
static void\r
-SDL_StartSB(void)\r
+SDL_Delay(word delay)\r
{\r
- byte timevalue,test;\r
-\r
- sbIntVec = sbIntVectors[sbInterrupt];\r
- if (sbIntVec < 0)\r
- Quit("SDL_StartSB: Illegal or unsupported interrupt number for SoundBlaster");\r
-\r
- sbOldIntHand = getvect(sbIntVec); // Get old interrupt handler\r
- setvect(sbIntVec,SDL_SBService); // Set mine\r
-\r
- sbWriteDelay();\r
- sbOut(sbWriteCmd,0xd1); // Turn on DSP speaker\r
-\r
- // Set the SoundBlaster DAC time constant for 7KHz\r
- timevalue = 256 - (1000000 / 7000);\r
- sbWriteDelay();\r
- sbOut(sbWriteCmd,0x40);\r
- sbWriteDelay();\r
- sbOut(sbWriteData,timevalue);\r
-\r
- SBProPresent = false;\r
- if (sbNoProCheck)\r
+ if (!delay)\r
return;\r
\r
- // Check to see if this is a SB Pro\r
- sbOut(sbpMixerAddr,sbpmFMVol);\r
- sbpOldFMMix = sbIn(sbpMixerData);\r
- sbOut(sbpMixerData,0xbb);\r
- test = sbIn(sbpMixerData);\r
- if (test == 0xbb)\r
- {\r
- // Boost FM output levels to be equivilent with digitized output\r
- sbOut(sbpMixerData,0xff);\r
- test = sbIn(sbpMixerData);\r
- if (test == 0xff)\r
- {\r
- SBProPresent = true;\r
-\r
- // Save old Voice output levels (SB Pro)\r
- sbOut(sbpMixerAddr,sbpmVoiceVol);\r
- sbpOldVOCMix = sbIn(sbpMixerData);\r
-\r
- // Turn SB Pro stereo DAC off\r
- sbOut(sbpMixerAddr,sbpmControl);\r
- sbOut(sbpMixerData,0); // 0=off,2=on\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutSB() - Turns off the SoundBlaster\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutSB(void)\r
-{\r
- SDL_SBStopSample();\r
-\r
- if (SBProPresent)\r
- {\r
- // Restore FM output levels (SB Pro)\r
- sbOut(sbpMixerAddr,sbpmFMVol);\r
- sbOut(sbpMixerData,sbpOldFMMix);\r
-\r
- // Restore Voice output levels (SB Pro)\r
- sbOut(sbpMixerAddr,sbpmVoiceVol);\r
- sbOut(sbpMixerData,sbpOldVOCMix);\r
- }\r
-\r
- setvect(sbIntVec,sbOldIntHand); // Set vector back\r
-}\r
-\r
-// Sound Source Code\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SSStopSample() - Stops a sample playing on the Sound Source\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_SSStopSample(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)ssSample = 0;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SSService() - Handles playing the next sample on the Sound Source\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SSService(void)\r
-{\r
- boolean gotit;\r
- byte v;\r
-\r
- while (ssSample)\r
- {\r
- asm mov dx,[ssStatus] // Check to see if FIFO is currently empty\r
- asm in al,dx\r
- asm test al,0x40\r
- asm jnz done // Nope - don't push any more data out\r
-\r
- v = *ssSample++;\r
- if (!(--ssLengthLeft))\r
- {\r
- (long)ssSample = 0;\r
- SDL_DigitizedDone();\r
- }\r
-\r
- asm mov dx,[ssData] // Pump the value out\r
- asm mov al,[v]\r
- asm out dx,al\r
-\r
- asm mov dx,[ssControl] // Pulse printer select\r
- asm mov al,[ssOff]\r
- asm out dx,al\r
- asm push ax\r
- asm pop ax\r
- asm mov al,[ssOn]\r
- asm out dx,al\r
-\r
- asm push ax // Delay a short while\r
- asm pop ax\r
- asm push ax\r
- asm pop ax\r
- }\r
+asm mov cx,[delay]\r
+loop:\r
+asm test [TimerDone],0 // Useless code - just for timing equivilency\r
+asm jnz done\r
+asm loop loop\r
done:;\r
}\r
\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SSPlaySample() - Plays the specified sample on the Sound Source\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_SSPlaySample(byte huge *data,longword len)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- ssLengthLeft = len;\r
- ssSample = (volatile byte far *)data;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartSS() - Sets up for and turns on the Sound Source\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartSS(void)\r
-{\r
- if (ssPort == 3)\r
- ssControl = 0x27a; // If using LPT3\r
- else if (ssPort == 2)\r
- ssControl = 0x37a; // If using LPT2\r
- else\r
- ssControl = 0x3be; // If using LPT1\r
- ssStatus = ssControl - 1;\r
- ssData = ssStatus - 1;\r
-\r
- ssOn = 0x04;\r
- if (ssIsTandy)\r
- ssOff = 0x0e; // Tandy wierdness\r
- else\r
- ssOff = 0x0c; // For normal machines\r
-\r
- outportb(ssControl,ssOn); // Enable SS\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutSS() - Turns off the Sound Source\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutSS(void)\r
-{\r
- outportb(ssControl,ssOff);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CheckSS() - Checks to see if a Sound Source is present at the\r
-// location specified by the sound source variables\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_CheckSS(void)\r
-{\r
- boolean present = false;\r
- longword lasttime;\r
-\r
- // Turn the Sound Source on and wait awhile (4 ticks)\r
- SDL_StartSS();\r
-\r
- lasttime = TimeCount;\r
- while (TimeCount < lasttime + 4)\r
- ;\r
-\r
-asm mov dx,[ssStatus] // Check to see if FIFO is currently empty\r
-asm in al,dx\r
-asm test al,0x40\r
-asm jnz checkdone // Nope - Sound Source not here\r
-\r
-asm mov cx,32 // Force FIFO overflow (FIFO is 16 bytes)\r
-outloop:\r
-asm mov dx,[ssData] // Pump a neutral value out\r
-asm mov al,0x80\r
-asm out dx,al\r
-\r
-asm mov dx,[ssControl] // Pulse printer select\r
-asm mov al,[ssOff]\r
-asm out dx,al\r
-asm push ax\r
-asm pop ax\r
-asm mov al,[ssOn]\r
-asm out dx,al\r
-\r
-asm push ax // Delay a short while before we do this again\r
-asm pop ax\r
-asm push ax\r
-asm pop ax\r
-\r
-asm loop outloop\r
-\r
-asm mov dx,[ssStatus] // Is FIFO overflowed now?\r
-asm in al,dx\r
-asm test al,0x40\r
-asm jz checkdone // Nope, still not - Sound Source not here\r
-\r
- present = true; // Yes - it's here!\r
-\r
-checkdone:\r
- SDL_ShutSS();\r
- return(present);\r
-}\r
-\r
-static boolean\r
-SDL_DetectSoundSource(void)\r
-{\r
- for (ssPort = 1;ssPort <= 3;ssPort++)\r
- if (SDL_CheckSS())\r
- return(true);\r
- return(false);\r
-}\r
-\r
//\r
// PC Sound code\r
//\r
\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCPlaySample() - Plays the specified sample on the PC speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCPlaySample(byte huge *data,longword len)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- SDL_IndicatePC(true);\r
-\r
- pcLengthLeft = len;\r
- pcSound = (volatile byte far *)data;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCStopSample() - Stops a sample playing on the PC speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCStopSample(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)pcSound = 0;\r
-\r
- SDL_IndicatePC(false);\r
-\r
-asm in al,0x61 // Turn the speaker off\r
-asm and al,0xfd // ~2\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
///////////////////////////////////////////////////////////////////////////\r
//\r
// SDL_PCPlaySound() - Plays the specified sound on the PC speaker\r
asm popf\r
}\r
\r
-#if 0\r
///////////////////////////////////////////////////////////////////////////\r
//\r
// SDL_PCService() - Handles playing the next sample in a PC sound\r
asm or al,3\r
asm out 0x61,al\r
}\r
- else // Time for some silence\r
- {\r
- asm in al,0x61 // Turn the speaker & gate off\r
- asm and al,0xfc // ~3\r
- asm out 0x61,al\r
- }\r
-\r
- asm popf\r
- }\r
-\r
- if (!(--pcLengthLeft))\r
- {\r
- SDL_PCStopSound();\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutPC() - Turns off the pc speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutPC(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- pcSound = 0;\r
-\r
-asm in al,0x61 // Turn the speaker & gate off\r
-asm and al,0xfc // ~3\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
-//\r
-// Stuff for digitized sounds\r
-//\r
-memptr\r
-SDL_LoadDigiSegment(word page)\r
-{\r
- memptr addr;\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,10 // bright green\r
-asm out dx,al\r
-#endif\r
-\r
- addr = PM_GetSoundPage(page);\r
- PM_SetPageLock(PMSoundStart + page,pml_Locked);\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,3 // blue\r
-asm out dx,al\r
-asm mov al,0x20 // normal\r
-asm out dx,al\r
-#endif\r
-\r
- return(addr);\r
-}\r
-\r
-void\r
-SDL_PlayDigiSegment(memptr addr,word len)\r
-{\r
- switch (DigiMode)\r
- {\r
- case sds_PC:\r
- SDL_PCPlaySample(addr,len);\r
- break;\r
- case sds_SoundSource:\r
- SDL_SSPlaySample(addr,len);\r
- break;\r
- case sds_SoundBlaster:\r
- SDL_SBPlaySample(addr,len);\r
- break;\r
- }\r
-}\r
-\r
-void\r
-SD_StopDigitized(void)\r
-{\r
- int i;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- DigiLeft = 0;\r
- DigiNextAddr = nil;\r
- DigiNextLen = 0;\r
- DigiMissed = false;\r
- DigiPlaying = false;\r
- DigiNumber = DigiPriority = 0;\r
- SoundPositioned = false;\r
- if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
- SDL_SoundFinished();\r
-\r
- switch (DigiMode)\r
- {\r
- case sds_PC:\r
- SDL_PCStopSample();\r
- break;\r
- case sds_SoundSource:\r
- SDL_SSStopSample();\r
- break;\r
- case sds_SoundBlaster:\r
- SDL_SBStopSample();\r
- break;\r
- }\r
-\r
-asm popf\r
-\r
- for (i = DigiLastStart;i < DigiLastEnd;i++)\r
- PM_SetPageLock(i + PMSoundStart,pml_Unlocked);\r
- DigiLastStart = 1;\r
- DigiLastEnd = 0;\r
-}\r
-\r
-void\r
-SD_Poll(void)\r
-{\r
- if (DigiLeft && !DigiNextAddr)\r
- {\r
- DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);\r
- DigiLeft -= DigiNextLen;\r
- if (!DigiLeft)\r
- DigiLastSegment = true;\r
- DigiNextAddr = SDL_LoadDigiSegment(DigiPage++);\r
- }\r
- if (DigiMissed && DigiNextAddr)\r
- {\r
- SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);\r
- DigiNextAddr = nil;\r
- DigiMissed = false;\r
- if (DigiLastSegment)\r
- {\r
- DigiPlaying = false;\r
- DigiLastSegment = false;\r
- }\r
- }\r
- SDL_SetTimerSpeed();\r
-}\r
-\r
-void\r
-SD_SetPosition(int leftpos,int rightpos)\r
-{\r
- if\r
- (\r
- (leftpos < 0)\r
- || (leftpos > 15)\r
- || (rightpos < 0)\r
- || (rightpos > 15)\r
- || ((leftpos == 15) && (rightpos == 15))\r
- )\r
- Quit("SD_SetPosition: Illegal position");\r
-\r
- switch (DigiMode)\r
- {\r
- case sds_SoundBlaster:\r
- SDL_PositionSBP(leftpos,rightpos);\r
- break;\r
- }\r
-}\r
-\r
-void\r
-SD_PlayDigitized(word which,int leftpos,int rightpos)\r
-{\r
- word len;\r
- memptr addr;\r
-\r
- if (!DigiMode)\r
- return;\r
-\r
- SD_StopDigitized();\r
- if (which >= NumDigi)\r
- Quit("SD_PlayDigitized: bad sound number");\r
-\r
- SD_SetPosition(leftpos,rightpos);\r
-\r
- DigiPage = DigiList[(which * 2) + 0];\r
- DigiLeft = DigiList[(which * 2) + 1];\r
-\r
- DigiLastStart = DigiPage;\r
- DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize);\r
-\r
- len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);\r
- addr = SDL_LoadDigiSegment(DigiPage++);\r
-\r
- DigiPlaying = true;\r
- DigiLastSegment = false;\r
-\r
- SDL_PlayDigiSegment(addr,len);\r
- DigiLeft -= len;\r
- if (!DigiLeft)\r
- DigiLastSegment = true;\r
-\r
- SD_Poll();\r
-}\r
-\r
-void\r
-SDL_DigitizedDone(void)\r
-{\r
- if (DigiNextAddr)\r
- {\r
- SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);\r
- DigiNextAddr = nil;\r
- DigiMissed = false;\r
- }\r
- else\r
- {\r
- if (DigiLastSegment)\r
- {\r
- DigiPlaying = false;\r
- DigiLastSegment = false;\r
- if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
+ else // Time for some silence\r
{\r
- SDL_SoundFinished();\r
+ asm in al,0x61 // Turn the speaker & gate off\r
+ asm and al,0xfc // ~3\r
+ asm out 0x61,al\r
}\r
- else\r
- DigiNumber = DigiPriority = 0;\r
- SoundPositioned = false;\r
- }\r
- else\r
- DigiMissed = true;\r
- }\r
-}\r
\r
-void\r
-SD_SetDigiDevice(SDSMode mode)\r
-{\r
- boolean devicenotpresent;\r
-\r
- if (mode == DigiMode)\r
- return;\r
-\r
- SD_StopDigitized();\r
+ asm popf\r
+ }\r
\r
- devicenotpresent = false;\r
- switch (mode)\r
- {\r
- case sds_SoundBlaster:\r
- if (!SoundBlasterPresent)\r
+ if (!(--pcLengthLeft))\r
{\r
- if (SoundSourcePresent)\r
- mode = sds_SoundSource;\r
- else\r
- devicenotpresent = true;\r
+ SDL_PCStopSound();\r
+ SDL_SoundFinished();\r
}\r
- break;\r
- case sds_SoundSource:\r
- if (!SoundSourcePresent)\r
- devicenotpresent = true;\r
- break;\r
- }\r
-\r
- if (!devicenotpresent)\r
- {\r
- if (DigiMode == sds_SoundSource)\r
- SDL_ShutSS();\r
-\r
- DigiMode = mode;\r
-\r
- if (mode == sds_SoundSource)\r
- SDL_StartSS();\r
-\r
- SDL_SetTimerSpeed();\r
}\r
}\r
\r
-void\r
-SDL_SetupDigi(void)\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ShutPC() - Turns off the pc speaker\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_ShutPC(void)\r
{\r
- memptr list;\r
- word far *p,\r
- pg;\r
- int i;\r
+asm pushf\r
+asm cli\r
\r
- PM_UnlockMainMem();\r
- MM_GetPtr(&list,PMPageSize);\r
- PM_CheckMainMem();\r
- p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);\r
- _fmemcpy((void far *)list,(void far *)p,PMPageSize);\r
- pg = PMSoundStart;\r
- for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2)\r
- {\r
- if (pg >= ChunksInFile - 1)\r
- break;\r
- pg += (p[1] + (PMPageSize - 1)) / PMPageSize;\r
- }\r
- PM_UnlockMainMem();\r
- MM_GetPtr((memptr *)&DigiList,i * sizeof(word) * 2);\r
- _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);\r
- MM_FreePtr(&list);\r
- NumDigi = i;\r
-\r
- for (i = 0;i < LASTSOUND;i++)\r
- DigiMap[i] = -1;\r
+ pcSound = 0;\r
+\r
+asm in al,0x61 // Turn the speaker & gate off\r
+asm and al,0xfc // ~3\r
+asm out 0x61,al\r
+\r
+asm popf\r
}\r
\r
// AdLib Code\r
asm pushf\r
asm cli\r
\r
-asm mov dx,0x388\r
-asm mov al,[n]\r
-asm out dx,al\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm inc dx\r
-asm mov al,[b]\r
-asm out dx,al\r
+asm mov dx,0x388\r
+asm mov al,[n]\r
+asm out dx,al\r
+#if 0\r
+ SDL_Delay(TimerDelay10);\r
+#else\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+#endif\r
+\r
+asm mov dx,0x389\r
+asm mov al,[b]\r
+asm out dx,al\r
\r
asm popf\r
\r
-asm dec dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
+#if 0\r
+ SDL_Delay(TimerDelay25);\r
+#else\r
+asm mov dx,0x388\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
-asm in al,dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+#endif\r
}\r
\r
#if 0\r
alOut(c + alAttack,inst->cAttack);\r
alOut(c + alSus,inst->cSus);\r
alOut(c + alWave,inst->cWave);\r
-\r
- // Note: Switch commenting on these lines for old MUSE compatibility\r
+ // DEBUG!!! - I just put this in\r
// alOut(alFeedCon,inst->nConn);\r
- alOut(alFeedCon,0);\r
}\r
\r
///////////////////////////////////////////////////////////////////////////\r
SDL_ALPlaySound(AdLibSound far *sound)\r
{\r
Instrument far *inst;\r
- byte huge *data;\r
\r
SDL_ALStopSound();\r
\r
asm cli\r
\r
alLengthLeft = sound->common.length;\r
- data = sound->data;\r
- data++;\r
- data--;\r
- alSound = (byte far *)data;\r
+ alSound = sound->data;\r
alBlock = ((sound->block & 7) << 2) | 0x20;\r
inst = &sound->inst;\r
\r
Quit("SDL_ALPlaySound() - Bad instrument");\r
}\r
\r
- SDL_AlSetFXInst(&alZeroInst); // DEBUG\r
SDL_AlSetFXInst(inst);\r
\r
asm popf\r
}\r
\r
-#if 0\r
///////////////////////////////////////////////////////////////////////////\r
//\r
// SDL_ALSoundService() - Plays the next sample out through the AdLib card\r
//\r
///////////////////////////////////////////////////////////////////////////\r
-//static void\r
-void\r
+static void\r
SDL_ALSoundService(void)\r
{\r
byte s;\r
}\r
}\r
}\r
-#endif\r
\r
#if 0\r
-void\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SelectMeasure() - sets up sequencing variables for a given track\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_SelectMeasure(ActiveTrack *track)\r
+{\r
+ track->seq = track->moods[track->mood];\r
+ track->nextevent = 0;\r
+}\r
+#endif\r
+\r
+static void\r
SDL_ALService(void)\r
{\r
byte a,v;\r
alTimeCount = sqHackTime = 0;\r
}\r
}\r
-#endif\r
\r
///////////////////////////////////////////////////////////////////////////\r
//\r
status1 = readstat();\r
alOut(2,0xff); // Set timer 1\r
alOut(4,0x21); // Start timer 1\r
-#if 0\r
SDL_Delay(TimerDelay100);\r
-#else\r
-asm mov dx,0x388\r
-asm mov cx,100\r
-usecloop:\r
-asm in al,dx\r
-asm loop usecloop\r
-#endif\r
\r
status2 = readstat();\r
alOut(4,0x60);\r
return(false);\r
}\r
\r
-#if 0\r
///////////////////////////////////////////////////////////////////////////\r
//\r
// SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
{\r
static word count = 1;\r
\r
-#if 1 // for debugging\r
+#if 0 // for debugging\r
asm mov dx,STATUS_REGISTER_1\r
asm in al,dx\r
asm mov dx,ATR_INDEX\r
\r
HackCount++;\r
\r
- if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))\r
+ if (MusicMode == smm_AdLib)\r
{\r
SDL_ALService();\r
- SDL_SSService();\r
-// if (!(++count & 7))\r
- if (!(++count % 10))\r
+ if (!(++count & 7))\r
{\r
LocalTime++;\r
TimeCount++;\r
if (SoundUserHook)\r
SoundUserHook();\r
}\r
-// if (!(count & 3))\r
- if (!(count % 5))\r
+ if (!(count & 3))\r
{\r
switch (SoundMode)\r
{\r
outportb(0x20,0x20); // Ack the interrupt\r
olddone:;\r
\r
-#if 1 // for debugging\r
+#if 0 // for debugging\r
asm mov dx,STATUS_REGISTER_1\r
asm in al,dx\r
asm mov dx,ATR_INDEX\r
asm out dx,al\r
#endif\r
}\r
-#endif\r
\r
////////////////////////////////////////////////////////////////////////////\r
//\r
SoundNumber = SoundPriority = 0;\r
}\r
\r
+static void\r
+SDL_SetTimerSpeed(void)\r
+{\r
+ word rate;\r
+\r
+ if (MusicMode == smm_AdLib)\r
+ rate = TickBase * 8;\r
+ else\r
+ rate = TickBase * 2;\r
+ SDL_SetIntsPerSec(rate);\r
+}\r
+\r
// Public routines\r
\r
///////////////////////////////////////////////////////////////////////////\r
boolean\r
SD_SetSoundMode(SDMode mode)\r
{\r
- boolean result = false;\r
+ boolean result;\r
word tableoffset;\r
\r
SD_StopSound();\r
\r
#ifndef _MUSE_\r
- if ((mode == sdm_AdLib) && !AdLibPresent)\r
- mode = sdm_PC;\r
-\r
switch (mode)\r
{\r
case sdm_Off:\r
result = true;\r
}\r
break;\r
+ default:\r
+ result = false;\r
+ break;\r
}\r
-#else\r
- result = true;\r
#endif\r
\r
if (result && (mode != SoundMode))\r
boolean\r
SD_SetMusicMode(SMMode mode)\r
{\r
- boolean result = false;\r
+ boolean result;\r
\r
SD_FadeOutMusic();\r
while (SD_MusicPlaying())\r
result = true;\r
}\r
break;\r
+ default:\r
+ result = false;\r
+ break;\r
}\r
\r
if (result)\r
if (SD_Started)\r
return;\r
\r
- SDL_SetDS();\r
-\r
ssIsTandy = false;\r
- ssNoCheck = false;\r
alNoCheck = false;\r
- sbNoCheck = false;\r
- sbNoProCheck = false;\r
#ifndef _MUSE_\r
for (i = 1;i < _argc;i++)\r
{\r
case 0: // No AdLib detection\r
alNoCheck = true;\r
break;\r
- case 1: // No SoundBlaster detection\r
- sbNoCheck = true;\r
- break;\r
- case 2: // No SoundBlaster Pro detection\r
- sbNoProCheck = true;\r
- break;\r
- case 3:\r
- ssNoCheck = true; // No Sound Source detection\r
- break;\r
- case 4: // Tandy Sound Source handling\r
- ssIsTandy = true;\r
- break;\r
- case 5: // Sound Source present at LPT1\r
- ssPort = 1;\r
- ssNoCheck = SoundSourcePresent = true;\r
- break;\r
- case 6: // Sound Source present at LPT2\r
- ssPort = 2;\r
- ssNoCheck = SoundSourcePresent = true;\r
- break;\r
- case 7: // Sound Source present at LPT3\r
- ssPort = 3;\r
- ssNoCheck = SoundSourcePresent = true;\r
- break;\r
}\r
}\r
#endif\r
\r
t0OldService = getvect(8); // Get old timer 0 ISR\r
\r
+ SDL_InitDelay(); // SDL_InitDelay() uses t0OldService\r
+\r
+ setvect(8,SDL_t0Service); // Set to my timer 0 ISR\r
LocalTime = TimeCount = alTimeCount = 0;\r
\r
SD_SetSoundMode(sdm_Off);\r
SD_SetMusicMode(smm_Off);\r
\r
- if (!ssNoCheck)\r
- SoundSourcePresent = SDL_DetectSoundSource();\r
-\r
if (!alNoCheck)\r
- {\r
AdLibPresent = SDL_DetectAdLib();\r
- if (AdLibPresent && !sbNoCheck)\r
- {\r
- int port = -1;\r
- char *env = getenv("BLASTER");\r
- if (env)\r
- {\r
- long temp;\r
- while (*env)\r
- {\r
- while (isspace(*env))\r
- env++;\r
-\r
- switch (toupper(*env))\r
- {\r
- case 'A':\r
- temp = strtol(env + 1,&env,16);\r
- if\r
- (\r
- (temp >= 0x210)\r
- && (temp <= 0x260)\r
- && (!(temp & 0x00f))\r
- )\r
- port = (temp - 0x200) >> 4;\r
- else\r
- Quit("SD_Startup: Unsupported address value in BLASTER");\r
- break;\r
- case 'I':\r
- temp = strtol(env + 1,&env,10);\r
- if\r
- (\r
- (temp >= 0)\r
- && (temp <= 10)\r
- && (sbIntVectors[temp] != -1)\r
- )\r
- {\r
- sbInterrupt = temp;\r
- sbIntVec = sbIntVectors[sbInterrupt];\r
- }\r
- else\r
- Quit("SD_Startup: Unsupported interrupt value in BLASTER");\r
- break;\r
- case 'D':\r
- temp = strtol(env + 1,&env,10);\r
- if ((temp == 0) || (temp == 1) || (temp == 3))\r
- SDL_SBSetDMA(temp);\r
- else\r
- Quit("SD_Startup: Unsupported DMA value in BLASTER");\r
- break;\r
- default:\r
- while (isspace(*env))\r
- env++;\r
- while (*env && !isspace(*env))\r
- env++;\r
- break;\r
- }\r
- }\r
- }\r
- SoundBlasterPresent = SDL_DetectSoundBlaster(port);\r
- }\r
- }\r
\r
for (i = 0;i < 255;i++)\r
pcSoundLookup[i] = i * 60;\r
\r
- if (SoundBlasterPresent)\r
- SDL_StartSB();\r
-\r
- SDL_SetupDigi();\r
-\r
SD_Started = true;\r
}\r
\r
return;\r
\r
SD_MusicOff();\r
- SD_StopSound();\r
SDL_ShutDevice();\r
SDL_CleanDevice();\r
\r
- if (SoundBlasterPresent)\r
- SDL_ShutSB();\r
-\r
- if (SoundSourcePresent)\r
- SDL_ShutSS();\r
-\r
asm pushf\r
asm cli\r
\r
SoundUserHook = hook;\r
}\r
\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_PositionSound() - Sets up a stereo imaging location for the next\r
-// sound to be played. Each channel ranges from 0 to 15.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_PositionSound(int leftvol,int rightvol)\r
-{\r
- LeftPosition = leftvol;\r
- RightPosition = rightvol;\r
- nextsoundpos = true;\r
-}\r
-\r
///////////////////////////////////////////////////////////////////////////\r
//\r
// SD_PlaySound() - plays the specified sound on the appropriate hardware\r
//\r
///////////////////////////////////////////////////////////////////////////\r
-boolean\r
+void\r
SD_PlaySound(soundnames sound)\r
{\r
- boolean ispos;\r
SoundCommon far *s;\r
- int lp,rp;\r
-\r
- lp = LeftPosition;\r
- rp = RightPosition;\r
- LeftPosition = 0;\r
- RightPosition = 0;\r
\r
- ispos = nextsoundpos;\r
- nextsoundpos = false;\r
-\r
- if (sound == -1)\r
- return(false);\r
+ if ((SoundMode == sdm_Off) || (sound == -1))\r
+ return;\r
\r
s = MK_FP(SoundTable[sound],0);\r
- if ((SoundMode != sdm_Off) && !s)\r
+ if (!s)\r
Quit("SD_PlaySound() - Uncached sound");\r
-\r
- if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))\r
- {\r
- if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))\r
- {\r
- if (s->priority < SoundPriority)\r
- return(false);\r
-\r
- SDL_PCStopSound();\r
-\r
- SD_PlayDigitized(DigiMap[sound],lp,rp);\r
- SoundPositioned = ispos;\r
- SoundNumber = sound;\r
- SoundPriority = s->priority;\r
- }\r
- else\r
- {\r
- asm pushf\r
- asm cli\r
- if (DigiPriority && !DigiNumber)\r
- {\r
- asm popf\r
- Quit("SD_PlaySound: Priority without a sound");\r
- }\r
- asm popf\r
-\r
- if (s->priority < DigiPriority)\r
- return(false);\r
-\r
- SD_PlayDigitized(DigiMap[sound],lp,rp);\r
- SoundPositioned = ispos;\r
- DigiNumber = sound;\r
- DigiPriority = s->priority;\r
- }\r
-\r
- return(true);\r
- }\r
-\r
- if (SoundMode == sdm_Off)\r
- return(false);\r
if (!s->length)\r
Quit("SD_PlaySound() - Zero length sound");\r
if (s->priority < SoundPriority)\r
- return(false);\r
+ return;\r
\r
switch (SoundMode)\r
{\r
\r
SoundNumber = sound;\r
SoundPriority = s->priority;\r
-\r
- return(false);\r
}\r
\r
///////////////////////////////////////////////////////////////////////////\r
void\r
SD_StopSound(void)\r
{\r
- if (DigiPlaying)\r
- SD_StopDigitized();\r
-\r
switch (SoundMode)\r
{\r
case sdm_PC:\r
break;\r
}\r
\r
- SoundPositioned = false;\r
-\r
SDL_SoundFinished();\r
}\r
\r
--- /dev/null
+// Macros for SoundBlaster stuff\r
+#define sbOut(n,b) outportb((n) + sbLocation,b)\r
+#define sbIn(n) inportb((n) + sbLocation)\r
+#define sbWriteDelay() while (sbIn(sbWriteStat) & 0x80);\r
+#define sbReadDelay() while (sbIn(sbDataAvail) & 0x80);\r
+\r
+ SoundSourcePresent,\r
+ SoundBlasterPresent,SBProPresent,\r
+\r
+ word ssPort = 2;\r
+\r
+ "nosb",\r
+ "nopro",\r
+ "noss",\r
+ "sst",\r
+ "ss1",\r
+ "ss2",\r
+ "ss3",\r
+\r
+// SoundBlaster variables\r
+static boolean sbNoCheck,sbNoProCheck;\r
+static volatile boolean sbSamplePlaying;\r
+static byte sbOldIntMask = -1;\r
+static volatile byte huge *sbNextSegPtr;\r
+static byte sbDMA = 1,\r
+ sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3,\r
+ sba1Vals[] = {0x87,0x83,0,0x82},\r
+ sba2Vals[] = {0,2,0,6},\r
+ sba3Vals[] = {1,3,0,7};\r
+static int sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf,\r
+ sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1};\r
+static volatile dword sbNextSegLen;\r
+static volatile SampledSound huge *sbSamples;\r
+static void interrupt (*sbOldIntHand)(void);\r
+static byte sbpOldFMMix,sbpOldVOCMix;\r
+\r
+// SoundSource variables\r
+ boolean ssNoCheck;\r
+ boolean ssActive;\r
+ word ssControl,ssStatus,ssData;\r
+ byte ssOn,ssOff;\r
+ volatile byte far *ssSample;\r
+ volatile dword ssLengthLeft;\r
+\r
+\r
+\r
+//++#if 0\r
+//\r
+// SoundBlaster code\r
+//\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SBStopSample() - Stops any active sampled sound and causes DMA\r
+// requests from the SoundBlaster to cease\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_SBStopSample(void)\r
+{\r
+ byte is;\r
+\r
+asm pushf\r
+asm cli\r
+\r
+ if (sbSamplePlaying)\r
+ {\r
+ sbSamplePlaying = false;\r
+\r
+ sbWriteDelay();\r
+ sbOut(sbWriteCmd,0xd0); // Turn off DSP DMA\r
+\r
+ is = inportb(0x21); // Restore interrupt mask bit\r
+ if (sbOldIntMask & (1 << sbInterrupt))\r
+ is |= (1 << sbInterrupt);\r
+ else\r
+ is &= ~(1 << sbInterrupt);\r
+ outportb(0x21,is);\r
+ }\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SBPlaySeg() - Plays a chunk of sampled sound on the SoundBlaster\r
+// Insures that the chunk doesn't cross a bank boundary, programs the DMA\r
+// controller, and tells the SB to start doing DMA requests for DAC\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static dword\r
+SDL_SBPlaySeg(volatile byte huge *data,dword length)\r
+{\r
+ unsigned datapage;\r
+ dword dataofs,uselen;\r
+\r
+ uselen = length;\r
+ datapage = FP_SEG(data) >> 12;\r
+ dataofs = ((FP_SEG(data) & 0xfff) << 4) + FP_OFF(data);\r
+ if (dataofs >= 0x10000)\r
+ {\r
+ datapage++;\r
+ dataofs -= 0x10000;\r
+ }\r
+\r
+ if (dataofs + uselen > 0x10000)\r
+ uselen = 0x10000 - dataofs;\r
+\r
+ uselen--;\r
+\r
+ // Program the DMA controller\r
+asm pushf\r
+asm cli\r
+ outportb(0x0a,sbDMA | 4); // Mask off DMA on channel sbDMA\r
+ outportb(0x0c,0); // Clear byte ptr flip-flop to lower byte\r
+ outportb(0x0b,0x49); // Set transfer mode for D/A conv\r
+ outportb(sbDMAa2,(byte)dataofs); // Give LSB of address\r
+ outportb(sbDMAa2,(byte)(dataofs >> 8)); // Give MSB of address\r
+ outportb(sbDMAa1,(byte)datapage); // Give page of address\r
+ outportb(sbDMAa3,(byte)uselen); // Give LSB of length\r
+ outportb(sbDMAa3,(byte)(uselen >> 8)); // Give MSB of length\r
+ outportb(0x0a,sbDMA); // Re-enable DMA on channel sbDMA\r
+\r
+ // Start playing the thing\r
+ sbWriteDelay();\r
+ sbOut(sbWriteCmd,0x14);\r
+ sbWriteDelay();\r
+ sbOut(sbWriteData,(byte)uselen);\r
+ sbWriteDelay();\r
+ sbOut(sbWriteData,(byte)(uselen >> 8));\r
+asm popf\r
+\r
+ return(uselen + 1);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SBService() - Services the SoundBlaster DMA interrupt\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+/*static*/ void interrupt\r
+SDL_SBService(void)\r
+{\r
+ dword used;\r
+\r
+ sbIn(sbDataAvail); // Ack interrupt to SB\r
+\r
+ if (sbNextSegPtr)\r
+ {\r
+ used = SDL_SBPlaySeg(sbNextSegPtr,sbNextSegLen);\r
+ if (sbNextSegLen <= used)\r
+ sbNextSegPtr = nil;\r
+ else\r
+ {\r
+ sbNextSegPtr += used;\r
+ sbNextSegLen -= used;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ SDL_SBStopSample();\r
+ SDL_DigitizedDone();\r
+ }\r
+\r
+ outportb(0x20,0x20); // Ack interrupt\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SBPlaySample() - Plays a sampled sound on the SoundBlaster. Sets up\r
+// DMA to play the sound\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_SBPlaySample(byte huge *data,dword len)\r
+{\r
+ dword used;\r
+\r
+ SDL_SBStopSample();\r
+\r
+asm pushf\r
+asm cli\r
+\r
+ used = SDL_SBPlaySeg(data,len);\r
+ if (len <= used)\r
+ sbNextSegPtr = nil;\r
+ else\r
+ {\r
+ sbNextSegPtr = data + used;\r
+ sbNextSegLen = len - used;\r
+ }\r
+\r
+ // Save old interrupt status and unmask ours\r
+ sbOldIntMask = inportb(0x21);\r
+ outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt));\r
+\r
+ sbWriteDelay();\r
+ sbOut(sbWriteCmd,0xd4); // Make sure DSP DMA is enabled\r
+\r
+ sbSamplePlaying = true;\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_PositionSBP() - Sets the attenuation levels for the left and right\r
+// channels by using the mixer chip on the SB Pro. This hits a hole in\r
+// the address map for normal SBs.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_PositionSBP(int leftpos,int rightpos)\r
+{\r
+ byte v;\r
+\r
+ if (!SBProPresent)\r
+ return;\r
+\r
+ leftpos = 15 - leftpos;\r
+ rightpos = 15 - rightpos;\r
+ v = ((leftpos & 0x0f) << 4) | (rightpos & 0x0f);\r
+\r
+asm pushf\r
+asm cli\r
+\r
+ sbOut(sbpMixerAddr,sbpmVoiceVol);\r
+ sbOut(sbpMixerData,v);\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_CheckSB() - Checks to see if a SoundBlaster resides at a\r
+// particular I/O location\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+SDL_CheckSB(int port)\r
+{\r
+ int i;\r
+\r
+ sbLocation = port << 4; // Initialize stuff for later use\r
+\r
+ sbOut(sbReset,true); // Reset the SoundBlaster DSP\r
+asm mov dx,0x388 // Wait >4usec\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+asm in al, dx\r
+\r
+ sbOut(sbReset,false); // Turn off sb DSP reset\r
+asm mov dx,0x388 // Wait >100usec\r
+asm mov cx,100\r
+#ifdef __WATCOMC__\r
+ __asm {\r
+#endif\r
+usecloop:\r
+asm in al,dx\r
+asm loop usecloop\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\r
+\r
+ for (i = 0;i < 100;i++)\r
+ {\r
+ if (sbIn(sbDataAvail) & 0x80) // If data is available...\r
+ {\r
+ if (sbIn(sbReadData) == 0xaa) // If it matches correct value\r
+ return(true);\r
+ else\r
+ {\r
+ sbLocation = -1; // Otherwise not a SoundBlaster\r
+ return(false);\r
+ }\r
+ }\r
+ }\r
+ sbLocation = -1; // Retry count exceeded - fail\r
+ return(false);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// Checks to see if a SoundBlaster is in the system. If the port passed is\r
+// -1, then it scans through all possible I/O locations. If the port\r
+// passed is 0, then it uses the default (2). If the port is >0, then\r
+// it just passes it directly to SDL_CheckSB()\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+SDL_DetectSoundBlaster(int port)\r
+{\r
+ int i;\r
+\r
+ if (port == 0) // If user specifies default, use 2\r
+ port = 2;\r
+ if (port == -1)\r
+ {\r
+ if (SDL_CheckSB(2)) // Check default before scanning\r
+ return(true);\r
+\r
+ if (SDL_CheckSB(4)) // Check other SB Pro location before scan\r
+ return(true);\r
+\r
+ for (i = 1;i <= 6;i++) // Scan through possible SB locations\r
+ {\r
+ if ((i == 2) || (i == 4))\r
+ continue;\r
+\r
+ if (SDL_CheckSB(i)) // If found at this address,\r
+ return(true); // return success\r
+ }\r
+ return(false); // All addresses failed, return failure\r
+ }\r
+ else\r
+ return(SDL_CheckSB(port)); // User specified address or default\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SBSetDMA() - Sets the DMA channel to be used by the SoundBlaster\r
+// code. Sets up sbDMA, and sbDMAa1-sbDMAa3 (used by SDL_SBPlaySeg()).\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SDL_SBSetDMA(byte channel, global_game_variables_t *gvar)\r
+{\r
+ if (channel > 3)\r
+ Quit(gvar, "SDL_SBSetDMA() - invalid SoundBlaster DMA channel");\r
+\r
+ sbDMA = channel;\r
+ sbDMAa1 = sba1Vals[channel];\r
+ sbDMAa2 = sba2Vals[channel];\r
+ sbDMAa3 = sba3Vals[channel];\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_StartSB() - Turns on the SoundBlaster\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_StartSB(global_game_variables_t *gvar)\r
+{\r
+ byte timevalue,test;\r
+\r
+ sbIntVec = sbIntVectors[sbInterrupt];\r
+ if (sbIntVec < 0)\r
+ Quit(gvar, "SDL_StartSB: Illegal or unsupported interrupt number for SoundBlaster");\r
+\r
+ sbOldIntHand = getvect(sbIntVec); // Get old interrupt handler\r
+ setvect(sbIntVec,SDL_SBService); // Set mine\r
+\r
+ sbWriteDelay();\r
+ sbOut(sbWriteCmd,0xd1); // Turn on DSP speaker\r
+\r
+ // Set the SoundBlaster DAC time constant for 7KHz\r
+ timevalue = 256 - (1000000 / 7000);\r
+ sbWriteDelay();\r
+ sbOut(sbWriteCmd,0x40);\r
+ sbWriteDelay();\r
+ sbOut(sbWriteData,timevalue);\r
+\r
+ SBProPresent = false;\r
+ if (sbNoProCheck)\r
+ return;\r
+\r
+ // Check to see if this is a SB Pro\r
+ sbOut(sbpMixerAddr,sbpmFMVol);\r
+ sbpOldFMMix = sbIn(sbpMixerData);\r
+ sbOut(sbpMixerData,0xbb);\r
+ test = sbIn(sbpMixerData);\r
+ if (test == 0xbb)\r
+ {\r
+ // Boost FM output levels to be equivilent with digitized output\r
+ sbOut(sbpMixerData,0xff);\r
+ test = sbIn(sbpMixerData);\r
+ if (test == 0xff)\r
+ {\r
+ SBProPresent = true;\r
+\r
+ // Save old Voice output levels (SB Pro)\r
+ sbOut(sbpMixerAddr,sbpmVoiceVol);\r
+ sbpOldVOCMix = sbIn(sbpMixerData);\r
+\r
+ // Turn SB Pro stereo DAC off\r
+ sbOut(sbpMixerAddr,sbpmControl);\r
+ sbOut(sbpMixerData,0); // 0=off,2=on\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ShutSB() - Turns off the SoundBlaster\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_ShutSB(void)\r
+{\r
+ SDL_SBStopSample();\r
+\r
+ if (SBProPresent)\r
+ {\r
+ // Restore FM output levels (SB Pro)\r
+ sbOut(sbpMixerAddr,sbpmFMVol);\r
+ sbOut(sbpMixerData,sbpOldFMMix);\r
+\r
+ // Restore Voice output levels (SB Pro)\r
+ sbOut(sbpMixerAddr,sbpmVoiceVol);\r
+ sbOut(sbpMixerData,sbpOldVOCMix);\r
+ }\r
+\r
+ setvect(sbIntVec,sbOldIntHand); // Set vector back\r
+}\r
+//++#endif\r
+\r
+\r
+\r
+\r
+\r
+// Sound Source Code\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SSStopSample() - Stops a sample playing on the Sound Source\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_SSStopSample(void)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ /*(long)*/ssSample = 0;\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SSService() - Handles playing the next sample on the Sound Source\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_SSService(void)\r
+{\r
+ //boolean gotit;\r
+ boolean doneflag=false;\r
+ byte v;\r
+\r
+ while (ssSample)\r
+ {\r
+ __asm {\r
+ mov dx,[ssStatus] // Check to see if FIFO is currently empty\r
+ in al,dx\r
+ test al,0x40\r
+ jnz done // Nope - don't push any more data out\r
+ jmp end\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+ done:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ mov doneflag,1\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+ end:\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\r
+ if(!doneflag)\r
+ {\r
+ v = *ssSample++;\r
+ if (!(--ssLengthLeft))\r
+ {\r
+ /*(long)*/ssSample = 0;\r
+ SDL_DigitizedDone();\r
+ }\r
+\r
+ __asm {\r
+ mov dx,[ssData] // Pump the value out\r
+ mov al,[v]\r
+ out dx,al\r
+\r
+ mov dx,[ssControl] // Pulse printer select\r
+ mov al,[ssOff]\r
+ out dx,al\r
+ push ax\r
+ pop ax\r
+ mov al,[ssOn]\r
+ out dx,al\r
+\r
+ push ax // Delay a short while\r
+ pop ax\r
+ push ax\r
+ pop ax\r
+done:;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SSPlaySample() - Plays the specified sample on the Sound Source\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_SSPlaySample(byte huge *data,dword len)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ ssLengthLeft = len;\r
+ ssSample = (volatile byte far *)data;\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_StartSS() - Sets up for and turns on the Sound Source\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_StartSS(void)\r
+{\r
+ if (ssPort == 3)\r
+ ssControl = 0x27a; // If using LPT3\r
+ else if (ssPort == 2)\r
+ ssControl = 0x37a; // If using LPT2\r
+ else\r
+ ssControl = 0x3be; // If using LPT1\r
+ ssStatus = ssControl - 1;\r
+ ssData = ssStatus - 1;\r
+\r
+ ssOn = 0x04;\r
+ if (ssIsTandy)\r
+ ssOff = 0x0e; // Tandy wierdness\r
+ else\r
+ ssOff = 0x0c; // For normal machines\r
+\r
+ outportb(ssControl,ssOn); // Enable SS\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ShutSS() - Turns off the Sound Source\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_ShutSS(void)\r
+{\r
+ outportb(ssControl,ssOff);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_CheckSS() - Checks to see if a Sound Source is present at the\r
+// location specified by the sound source variables\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+SDL_CheckSS(void)\r
+{\r
+ boolean present = false, chkdone=0;\r
+ dword lasttime;\r
+\r
+ // Turn the Sound Source on and wait awhile (4 ticks)\r
+ SDL_StartSS();\r
+\r
+ lasttime = TimeCount;\r
+ while (TimeCount < lasttime + 4)\r
+ {}\r
+\r
+ __asm {\r
+ mov dx,[ssStatus] // Check to see if FIFO is currently empty\r
+ in al,dx\r
+ test al,0x40\r
+ jnz checkdone // Nope - Sound Source not here\r
+\r
+ mov cx,32 // Force FIFO overflow (FIFO is 16 bytes)\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+outloop:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ mov dx,[ssData] // Pump a neutral value out\r
+ mov al,0x80\r
+ out dx,al\r
+\r
+ mov dx,[ssControl] // Pulse printer select\r
+ mov al,[ssOff]\r
+ out dx,al\r
+ push ax\r
+ pop ax\r
+ mov al,[ssOn]\r
+ out dx,al\r
+\r
+ push ax // Delay a short while before we do this again\r
+ pop ax\r
+ push ax\r
+ pop ax\r
+\r
+ loop outloop\r
+\r
+ mov dx,[ssStatus] // Is FIFO overflowed now?\r
+ in al,dx\r
+ test al,0x40\r
+ jz checkdone // Nope, still not - Sound Source not here\r
+ jmp end\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+checkdone:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ mov chkdone,1\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+ end:\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\r
+\r
+ if(!chkdone) present = true; // Yes - it's here!\r
+\r
+//checkdone:\r
+ SDL_ShutSS();\r
+ return(present);\r
+}\r
+\r
+static boolean\r
+SDL_DetectSoundSource(void)\r
+{\r
+ for (ssPort = 1;ssPort <= 3;ssPort++)\r
+ if (SDL_CheckSS())\r
+ return(true);\r
+ return(false);\r
+}\r