///////////////////////////////////////////////////////////////////////////
//
// SDL_StartAL() - Starts up the AdLib card for sound effects
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_StartAL(void)
{
alFXReg = 0;
alOut(alEffects,alFXReg);
SDL_AlSetFXInst(&alZeroInst);
}
///////////////////////////////////////////////////////////////////////////
//
// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster
// emulating an AdLib) present
//
///////////////////////////////////////////////////////////////////////////
static boolean
SDL_DetectAdLib(void)
{
byte status1,status2;
int i;
alOut(4,0x60); // Reset T1 & T2
alOut(4,0x80); // Reset IRQ
status1 = readstat();
alOut(2,0xff); // Set timer 1
alOut(4,0x21); // Start timer 1
#if 0
SDL_Delay(TimerDelay100);
#else
asm mov dx,0x388
asm mov cx,100
usecloop:
asm in al,dx
asm loop usecloop
#endif
status2 = readstat();
alOut(4,0x60);
alOut(4,0x80);
if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))
{
for (i = 1;i = 0xf5;i++) // Zero all the registers
alOut(i,0);
alOut(1,0x20); // Set WSE=1
alOut(8,0); // Set CSM=0 & SEL=0
return(true);
}
else
return(false);
}
#if 0
///////////////////////////////////////////////////////////////////////////
//
// SDL_t0Service() - My timer 0 ISR which handles the different timings and
// dispatches to whatever other routines are appropriate
//
///////////////////////////////////////////////////////////////////////////
static void interrupt
SDL_t0Service(void)
{
static word count = 1;
#if 1 // for debugging
asm mov dx,STATUS_REGISTER_1
asm in al,dx
asm mov dx,ATR_INDEX
asm mov al,ATR_OVERSCAN
asm out dx,al
asm mov al,4 // red
asm out dx,al
#endif
HackCount++;
if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))
{
SDL_ALService();
SDL_SSService();
// if (!(++count & 7))
if (!(++count % 10))
{
LocalTime++;
TimeCount++;
if (SoundUserHook)
SoundUserHook();
}
// if (!(count & 3))
if (!(count % 5))
{
switch (SoundMode)
{
case sdm_PC:
SDL_PCService();
break;
case sdm_AdLib:
SDL_ALSoundService();
break;
}
}
}
else
{
if (!(++count & 1))
{
LocalTime++;
TimeCount++;
if (SoundUserHook)
SoundUserHook();
}
switch (SoundMode)
{
case sdm_PC:
SDL_PCService();
break;
case sdm_AdLib:
SDL_ALSoundService();
break;
}
}
asm mov ax,[WORD PTR TimerCount]
asm add ax,[WORD PTR TimerDivisor]
asm mov [WORD PTR TimerCount],ax
asm jnc myack
t0OldService(); // If we overflow a word, time to call old int handler
asm jmp olddone
myack:;
outportb(0x20,0x20); // Ack the interrupt
olddone:;
#if 1 // for debugging
asm mov dx,STATUS_REGISTER_1
asm in al,dx
asm mov dx,ATR_INDEX
asm mov al,ATR_OVERSCAN
asm out dx,al
asm mov al,3 // blue
asm out dx,al
asm mov al,0x20 // normal
asm out dx,al
#endif
}
#endif
////////////////////////////////////////////////////////////////////////////
//
// SDL_ShutDevice() - turns off whatever device was being used for sound fx
//
////////////////////////////////////////////////////////////////////////////
static void
SDL_ShutDevice(void)
{
switch (SoundMode)
{
case sdm_PC:
SDL_ShutPC();
break;
case sdm_AdLib:
SDL_ShutAL();
break;
}
SoundMode = sdm_Off;
}
///////////////////////////////////////////////////////////////////////////
//
// SDL_CleanDevice() - totally shuts down all sound devices
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_CleanDevice(void)
{
if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))
SDL_CleanAL();
}
///////////////////////////////////////////////////////////////////////////
//
// SDL_StartDevice() - turns on whatever device is to be used for sound fx
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_StartDevice(void)
{
switch (SoundMode)
{
case sdm_AdLib:
SDL_StartAL();
break;
}
SoundNumber = SoundPriority = 0;
}
// Public routines
///////////////////////////////////////////////////////////////////////////
//
// SD_SetSoundMode() - Sets which sound hardware to use for sound effects
//
///////////////////////////////////////////////////////////////////////////
boolean
SD_SetSoundMode(SDMode mode)
{
boolean result = false;
word tableoffset;
SD_StopSound();
#ifndef _MUSE_
if ((mode == sdm_AdLib) && !AdLibPresent)
mode = sdm_PC;
switch (mode)
{
case sdm_Off:
NeedsDigitized = false;
result = true;
break;
case sdm_PC:
tableoffset = STARTPCSOUNDS;
NeedsDigitized = false;
result = true;
break;
case sdm_AdLib:
if (AdLibPresent)
{
tableoffset = STARTADLIBSOUNDS;
NeedsDigitized = false;
result = true;
}
break;
}
#else
result = true;
#endif
if (result && (mode != SoundMode))
{
SDL_ShutDevice();
SoundMode = mode;
#ifndef _MUSE_
SoundTable = (word *)(&audiosegs[tableoffset]);
#endif
SDL_StartDevice();
}
SDL_SetTimerSpeed();
return(result);
}
///////////////////////////////////////////////////////////////////////////
//
// SD_SetMusicMode() - sets the device to use for background music
//
///////////////////////////////////////////////////////////////////////////
boolean
SD_SetMusicMode(SMMode mode)
{
boolean result = false;
SD_FadeOutMusic();
while (SD_MusicPlaying())
;
switch (mode)
{
case smm_Off:
NeedsMusic = false;
result = true;
break;
case smm_AdLib:
if (AdLibPresent)
{
NeedsMusic = true;
result = true;
}
break;
}
if (result)
MusicMode = mode;
SDL_SetTimerSpeed();
return(result);
}
///////////////////////////////////////////////////////////////////////////
//
// SD_Startup() - starts up the Sound Mgr
// Detects all additional sound hardware and installs my ISR
//
///////////////////////////////////////////////////////////////////////////
void
SD_Startup(void)
{
int i;
if (SD_Started)
return;
SDL_SetDS();
ssIsTandy = false;
ssNoCheck = false;
alNoCheck = false;
sbNoCheck = false;
sbNoProCheck = false;
#ifndef _MUSE_
for (i = 1;i _argc;i++)
{
switch (US_CheckParm(_argv[i],ParmStrings))
{
case 0: // No AdLib detection
alNoCheck = true;
break;
case 1: // No SoundBlaster detection
sbNoCheck = true;
break;
case 2: // No SoundBlaster Pro detection
sbNoProCheck = true;
break;
case 3:
ssNoCheck = true; // No Sound Source detection
break;
case 4: // Tandy Sound Source handling
ssIsTandy = true;
break;
case 5: // Sound Source present at LPT1
ssPort = 1;
ssNoCheck = SoundSourcePresent = true;
break;
case 6: // Sound Source present at LPT2
ssPort = 2;
ssNoCheck = SoundSourcePresent = true;
break;
case 7: // Sound Source present at LPT3
ssPort = 3;
ssNoCheck = SoundSourcePresent = true;
break;
}
}
#endif
SoundUserHook = 0;
t0OldService = getvect(8); // Get old timer 0 ISR
LocalTime = TimeCount = alTimeCount = 0;
SD_SetSoundMode(sdm_Off);
SD_SetMusicMode(smm_Off);
if (!ssNoCheck)
SoundSourcePresent = SDL_DetectSoundSource();
if (!alNoCheck)
{
AdLibPresent = SDL_DetectAdLib();
if (AdLibPresent && !sbNoCheck)
{
int port = -1;
char *env = getenv("BLASTER");
if (env)
{
long temp;
while (*env)
{
while (isspace(*env))
env++;
switch (toupper(*env))
{
case 'A':
temp = strtol(env + 1,&env,16);
if
(
(temp >= 0x210)
&& (temp = 0x260)
&& (!(temp & 0x00f))
)
port = (temp - 0x200) >> 4;
else
Quit("SD_Startup: Unsupported address value in BLASTER");
break;
case 'I':
temp = strtol(env + 1,&env,10);
if
(
(temp >= 0)
&& (temp = 10)
&& (sbIntVectors[temp] != -1)
)
{
sbInterrupt = temp;
sbIntVec = sbIntVectors[sbInterrupt];
}
else
Quit("SD_Startup: Unsupported interrupt value in BLASTER");
break;
case 'D':
temp = strtol(env + 1,&env,10);
if ((temp == 0) || (temp == 1) || (temp == 3))
SDL_SBSetDMA(temp);
else
Quit("SD_Startup: Unsupported DMA value in BLASTER");
break;
default:
while (isspace(*env))
env++;
while (*env && !isspace(*env))
env++;
break;
}
}
}
SoundBlasterPresent = SDL_DetectSoundBlaster(port);
}
}
for (i = 0;i 255;i++)
pcSoundLookup[i] = i * 60;
if (SoundBlasterPresent)
SDL_StartSB();
SDL_SetupDigi();
SD_Started = true;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_Default() - Sets up the default behaviour for the Sound Mgr whether
// the config file was present or not.
//
///////////////////////////////////////////////////////////////////////////
void
SD_Default(boolean gotit,SDMode sd,SMMode sm)
{
boolean gotsd,gotsm;
gotsd = gotsm = gotit;
if (gotsd) // Make sure requested sound hardware is available
{
switch (sd)
{
case sdm_AdLib:
gotsd = AdLibPresent;
break;
}
}
if (!gotsd)
{
if (AdLibPresent)
sd = sdm_AdLib;
else
sd = sdm_PC;
}
if (sd != SoundMode)
SD_SetSoundMode(sd);
if (gotsm) // Make sure requested music hardware is available
{
switch (sm)
{
case sdm_AdLib:
gotsm = AdLibPresent;
break;
}
}
if (!gotsm)
{
if (AdLibPresent)
sm = smm_AdLib;
}
if (sm != MusicMode)
SD_SetMusicMode(sm);
}
///////////////////////////////////////////////////////////////////////////
//
// SD_Shutdown() - shuts down the Sound Mgr
// Removes sound ISR and turns off whatever sound hardware was active
//
///////////////////////////////////////////////////////////////////////////
void
SD_Shutdown(void)
{
if (!SD_Started)
return;
SD_MusicOff();
SD_StopSound();
SDL_ShutDevice();
SDL_CleanDevice();
if (SoundBlasterPresent)
SDL_ShutSB();
if (SoundSourcePresent)
SDL_ShutSS();
asm pushf
asm cli
SDL_SetTimer0(0);
setvect(8,t0OldService);
asm popf
SD_Started = false;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th
// of a second from its timer 0 ISR
//
///////////////////////////////////////////////////////////////////////////
void
SD_SetUserHook(void (* hook)(void))
{
SoundUserHook = hook;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_PositionSound() - Sets up a stereo imaging location for the next
// sound to be played. Each channel ranges from 0 to 15.
//
///////////////////////////////////////////////////////////////////////////
void
SD_PositionSound(int leftvol,int rightvol)
{
LeftPosition = leftvol;
RightPosition = rightvol;
nextsoundpos = true;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_PlaySound() - plays the specified sound on the appropriate hardware
//
///////////////////////////////////////////////////////////////////////////
boolean
SD_PlaySound(soundnames sound)
{
boolean ispos;
SoundCommon far *s;
int lp,rp;
lp = LeftPosition;
rp = RightPosition;
LeftPosition = 0;
RightPosition = 0;
ispos = nextsoundpos;
nextsoundpos = false;
if (sound == -1)
return(false);
s = MK_FP(SoundTable[sound],0);
if ((SoundMode != sdm_Off) && !s)
Quit("SD_PlaySound() - Uncached sound");
if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))
{
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
{
if (s->priority SoundPriority)
return(false);
SDL_PCStopSound();
SD_PlayDigitized(DigiMap[sound],lp,rp);
SoundPositioned = ispos;
SoundNumber = sound;
SoundPriority = s->priority;
}
else
{
asm pushf
asm cli
if (DigiPriority && !DigiNumber)
{
asm popf
Quit("SD_PlaySound: Priority without a sound");
}
asm popf
if (s->priority DigiPriority)
return(false);
SD_PlayDigitized(DigiMap[sound],lp,rp);
SoundPositioned = ispos;
DigiNumber = sound;
DigiPriority = s->priority;
}
return(true);
}
if (SoundMode == sdm_Off)
return(false);
if (!s->length)
Quit("SD_PlaySound() - Zero length sound");
if (s->priority SoundPriority)
return(false);
switch (SoundMode)
{
case sdm_PC:
SDL_PCPlaySound((void far *)s);
break;
case sdm_AdLib:
SDL_ALPlaySound((void far *)s);
break;
}
SoundNumber = sound;
SoundPriority = s->priority;
return(false);
}
///////////////////////////////////////////////////////////////////////////
//
// SD_SoundPlaying() - returns the sound number that's playing, or 0 if
// no sound is playing
//
///////////////////////////////////////////////////////////////////////////
word
SD_SoundPlaying(void)
{
boolean result = false;
switch (SoundMode)
{
case sdm_PC:
result = pcSound? true : false;
break;
case sdm_AdLib:
result = alSound? true : false;
break;
}
if (result)
return(SoundNumber);
else
return(false);
}
///////////////////////////////////////////////////////////////////////////
//
// SD_StopSound() - if a sound is playing, stops it
//
///////////////////////////////////////////////////////////////////////////
void
SD_StopSound(void)
{
if (DigiPlaying)
SD_StopDigitized();
switch (SoundMode)
{
case sdm_PC:
SDL_PCStopSound();
break;
case sdm_AdLib:
SDL_ALStopSound();
break;
}
SoundPositioned = false;
SDL_SoundFinished();
}
///////////////////////////////////////////////////////////////////////////
//
// SD_WaitSoundDone() - waits until the current sound is done playing
//
///////////////////////////////////////////////////////////////////////////
void
SD_WaitSoundDone(void)
{
while (SD_SoundPlaying())
;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_MusicOn() - turns on the sequencer
//
///////////////////////////////////////////////////////////////////////////
void
SD_MusicOn(void)
{
sqActive = true;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_MusicOff() - turns off the sequencer and any playing notes
//
///////////////////////////////////////////////////////////////////////////
void
SD_MusicOff(void)
{
word i;
switch (MusicMode)
{
case smm_AdLib:
alFXReg = 0;
alOut(alEffects,0);
for (i = 0;i sqMaxTracks;i++)
alOut(alFreqH + i + 1,0);
break;
}
sqActive = false;
}
///////////////////////////////////////////////////////////////////////////
//
// SD_StartMusic() - starts playing the music pointed to
//
///////////////////////////////////////////////////////////////////////////
void
SD_StartMusic(MusicGroup far *music)
{
SD_MusicOff();
asm pushf
asm cli
if (MusicMode == smm_AdLib)
{
sqHackPtr = sqHack = music->values;
sqHackSeqLen = sqHackLen = music->length;
sqHackTime = 0;
alTimeCount = 0;
SD_MusicOn();
}
asm popf
}
///////////////////////////////////////////////////////////////////////////
//
// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()
// to see if the fadeout is complete
//
///////////////////////////////////////////////////////////////////////////
void
SD_FadeOutMusic(void)
{
switch (MusicMode)
{
case smm_AdLib:
// DEBUG - quick hack to turn the music off
SD_MusicOff();
break;
}
}
///////////////////////////////////////////////////////////////////////////
//
// SD_MusicPlaying() - returns true if music is currently playing, false if
// not
//
///////////////////////////////////////////////////////////////////////////
boolean
SD_MusicPlaying(void)
{
boolean result;
switch (MusicMode)
{
case smm_AdLib:
result = false;
// DEBUG - not written
break;
default:
result = false;
}
return(result);
}